Documentation ¶
Overview ¶
Package measurex contains an heavily modified internal/measurex.
Index ¶
- Constants
- Variables
- func ALPNForHTTPSEndpoint(network archival.NetworkType) []string
- func CanonicalURLString(URL *SimpleURL) string
- func GetWebPageTitle(webpage []byte) string
- func NewCookieJar() http.CookieJar
- func NewHTTPGetRequest(ctx context.Context, URL string) (*http.Request, error)
- func NewHTTPRequestHeaderForMeasuring() http.Header
- func NewHTTPRequestWithContext(ctx context.Context, method, URL string, body io.Reader) (*http.Request, error)
- func ParseCookies(cookie ...string) []*http.Cookie
- func PortFromURL(URL *SimpleURL) (string, error)
- func SerializeCookies(in []*http.Cookie) (out []string)
- func SerializeCookiesNames(in []*http.Cookie) (out []string)
- func SortedSerializedCookiesNames(in []*http.Cookie) (out []string)
- func StringListSortUniq(in []string) (out []string)
- func URLAddressListToString(ual []*URLAddress) string
- type AbstractMeasurer
- type ArchivalDNSLookupMeasurement
- type ArchivalEndpointMeasurement
- type ArchivalURLMeasurement
- type Cache
- func (c *Cache) FindDNSLookupMeasurement(plan *DNSLookupPlan, policy CachingPolicy) (*DNSLookupMeasurement, bool)
- func (c *Cache) FindEndpointMeasurement(plan *EndpointPlan, policy CachingPolicy) (*EndpointMeasurement, bool)
- func (c *Cache) StartTrimmer(ctx context.Context)
- func (c *Cache) StoreDNSLookupMeasurement(dlm *DNSLookupMeasurement) error
- func (c *Cache) StoreEndpointMeasurement(em *EndpointMeasurement) error
- func (c *Cache) Trim()
- type CachedDNSLookupMeasurement
- type CachedEndpointMeasurement
- type CachingMeasurer
- func (mx *CachingMeasurer) DNSLookups(ctx context.Context, dnsLookups ...*DNSLookupPlan) <-chan *DNSLookupMeasurement
- func (mx *CachingMeasurer) FlattenOptions() *Options
- func (mx *CachingMeasurer) MeasureEndpoints(ctx context.Context, epnts ...*EndpointPlan) <-chan *EndpointMeasurement
- func (mx *CachingMeasurer) NewURLMeasurement(input string) (*URLMeasurement, error)
- func (mx *CachingMeasurer) NewURLRedirectDeque() *URLRedirectDeque
- func (mx *CachingMeasurer) NextID() int64
- func (mx *CachingMeasurer) Redirects(epnts []*EndpointMeasurement, opts *Options) ([]*URLMeasurement, bool)
- type CachingPolicy
- type Crawler
- type DNSLookupMeasurement
- func (dlm *DNSLookupMeasurement) ALPNs() []string
- func (dlm *DNSLookupMeasurement) Addresses() []string
- func (dlm *DNSLookupMeasurement) CNAME() string
- func (dlm *DNSLookupMeasurement) CouldDeriveFrom(p *DNSLookupPlan) bool
- func (dlm *DNSLookupMeasurement) Describe() string
- func (dlm *DNSLookupMeasurement) Domain() string
- func (dlm *DNSLookupMeasurement) Failure() archival.FlatFailure
- func (dlm *DNSLookupMeasurement) FinishedUnixNano() int64
- func (dlm *DNSLookupMeasurement) IsAnotherInstanceOf(o *DNSLookupMeasurement) bool
- func (dlm *DNSLookupMeasurement) IsCompatibleWith(other *DNSLookupMeasurement) bool
- func (dlm *DNSLookupMeasurement) IsWeaklyCompatibleWith(other *DNSLookupMeasurement) bool
- func (dlm *DNSLookupMeasurement) LookupType() archival.DNSLookupType
- func (dlm *DNSLookupMeasurement) NS() []string
- func (dlm *DNSLookupMeasurement) PTRs() []string
- func (dlm *DNSLookupMeasurement) ResolverAddress() string
- func (dlm *DNSLookupMeasurement) ResolverNetwork() archival.NetworkType
- func (dlm *DNSLookupMeasurement) ResolverURL() string
- func (dlm *DNSLookupMeasurement) Runtime() (out time.Duration)
- func (dlm *DNSLookupMeasurement) Summary() string
- func (dlm *DNSLookupMeasurement) SupportsHTTP3() bool
- func (m *DNSLookupMeasurement) ToArchival(begin time.Time) ArchivalDNSLookupMeasurement
- func (dlm *DNSLookupMeasurement) UsingResolverIPv6() (usingIPv6 bool)
- type DNSLookupPlan
- func (dlp *DNSLookupPlan) Clone() (out *DNSLookupPlan)
- func (dlp *DNSLookupPlan) CloneWithLookupType(lt archival.DNSLookupType) (out *DNSLookupPlan)
- func (dlp *DNSLookupPlan) Equals(other *DNSLookupPlan) bool
- func (dlp *DNSLookupPlan) ResolverAddress() string
- func (dlp *DNSLookupPlan) ResolverNetwork() archival.NetworkType
- func (dlp *DNSLookupPlan) Summary() string
- type DNSResolverInfo
- type EndpointMeasurement
- func (em *EndpointMeasurement) BodyIsTruncated() bool
- func (em *EndpointMeasurement) BodyLength() int64
- func (em *EndpointMeasurement) CouldDeriveFrom(plan *EndpointPlan) bool
- func (em *EndpointMeasurement) Describe() string
- func (em *EndpointMeasurement) EndpointAddress() string
- func (em *EndpointMeasurement) FinishedUnixNano() int64
- func (em *EndpointMeasurement) IPAddress() string
- func (em *EndpointMeasurement) IsAnotherInstanceOf(other *EndpointMeasurement) bool
- func (em *EndpointMeasurement) IsHTTP3Measurement() bool
- func (em *EndpointMeasurement) IsHTTPMeasurement() bool
- func (em *EndpointMeasurement) IsHTTPRedirect() bool
- func (em *EndpointMeasurement) IsHTTPSMeasurement() bool
- func (em *EndpointMeasurement) LocationAsString() string
- func (em *EndpointMeasurement) RedirectLocationDomain() string
- func (em *EndpointMeasurement) RedirectSummary() (string, bool)
- func (em *EndpointMeasurement) RequestHeaders() http.Header
- func (em *EndpointMeasurement) ResponseBody() []byte
- func (em *EndpointMeasurement) ResponseBodyTLSH() string
- func (em *EndpointMeasurement) ResponseHeaders() http.Header
- func (em *EndpointMeasurement) Scheme() string
- func (em *EndpointMeasurement) SeemsLegitimateRedirect() bool
- func (em *EndpointMeasurement) StatusCode() int64
- func (em *EndpointMeasurement) Summary() string
- func (em *EndpointMeasurement) SupportsAltSvcHTTP3() bool
- func (em *EndpointMeasurement) TCPQUICConnectRuntime() (out time.Duration)
- func (m *EndpointMeasurement) ToArchival(begin time.Time, bodyFlags int64) ArchivalEndpointMeasurement
- func (em *EndpointMeasurement) URLAddressList() ([]*URLAddress, bool)
- func (em *EndpointMeasurement) URLAsString() string
- func (em *EndpointMeasurement) URLDomain() string
- func (em *EndpointMeasurement) UsingAddressIPv6() (usingIPv6 bool)
- type EndpointPlan
- type FlatFailedOperation
- type IDGenerator
- type Library
- func (lib *Library) NewDialerWithoutResolver(saver *archival.Saver) model.Dialer
- func (lib *Library) NewHTTPTransportWithConn(saver *archival.Saver, conn net.Conn, maxBodySnapshotSize int64) model.HTTPTransport
- func (lib *Library) NewHTTPTransportWithQUICSess(saver *archival.Saver, sess quic.EarlySession, maxBodySnapshotSize int64) model.HTTPTransport
- func (lib *Library) NewHTTPTransportWithTLSConn(saver *archival.Saver, conn model.TLSConn, maxBodySnapshotSize int64) model.HTTPTransport
- func (lib *Library) NewQUICDialerWithoutResolver(saver *archival.Saver) model.QUICDialer
- func (lib *Library) NewResolverDoH(saver *archival.Saver, clnt model.HTTPClient, network, address string) model.Resolver
- func (lib *Library) NewResolverSystem(saver *archival.Saver) model.Resolver
- func (lib *Library) NewResolverUDP(saver *archival.Saver, address string) model.Resolver
- func (lib *Library) NewTLSHandshakerStdlib() model.TLSHandshaker
- func (lib *Library) WrapHTTPClient(clnt model.HTTPClient) model.HTTPClient
- type Measurer
- func (mx *Measurer) DNSLookups(ctx context.Context, dnsLookups ...*DNSLookupPlan) <-chan *DNSLookupMeasurement
- func (mx *Measurer) FlattenOptions() *Options
- func (mx *Measurer) MeasureEndpoints(ctx context.Context, epnts ...*EndpointPlan) <-chan *EndpointMeasurement
- func (mx *Measurer) NewURLMeasurement(input string) (*URLMeasurement, error)
- func (mx *Measurer) NewURLRedirectDeque() *URLRedirectDeque
- func (mx *Measurer) NextID() int64
- func (mx *Measurer) Redirects(epnts []*EndpointMeasurement, opts *Options) ([]*URLMeasurement, bool)
- type NetxliteLibrary
- type OperationLogger
- type Options
- type SimpleURL
- type URLAddress
- type URLAddressListDiff
- type URLMeasurement
- func (um *URLMeasurement) AddFromExternalDNSLookup(mx AbstractMeasurer, resolverNetwork, resolverAddress string, alpns []string, ...)
- func (um *URLMeasurement) Domain() string
- func (um *URLMeasurement) IsHTTP() bool
- func (um *URLMeasurement) IsHTTPS() bool
- func (um *URLMeasurement) NewDNSLookupPlans(flags int64, ri ...*DNSResolverInfo) []*DNSLookupPlan
- func (um *URLMeasurement) NewDNSReverseLookupPlans(addrs []string, ri ...*DNSResolverInfo) []*DNSLookupPlan
- func (um *URLMeasurement) NewEndpointPlan(flags int64) ([]*EndpointPlan, bool)
- func (um *URLMeasurement) NewEndpointPlanWithAddressList(addrs []*URLAddress, flags int64) ([]*EndpointPlan, bool)
- func (m *URLMeasurement) ToArchival(begin time.Time, bodyFlags int64) ArchivalURLMeasurement
- func (um *URLMeasurement) URLAddressList() ([]*URLAddress, bool)
- type URLRedirectDeque
- func (r *URLRedirectDeque) Append(um ...*URLMeasurement)
- func (r *URLRedirectDeque) Depth() int64
- func (r *URLRedirectDeque) MaxDepth() int64
- func (r *URLRedirectDeque) PopLeft() (*URLMeasurement, error)
- func (r *URLRedirectDeque) RememberVisitedURLs(epnts []*EndpointMeasurement)
- func (r *URLRedirectDeque) String() string
Constants ¶
const ( // DNSLookupFlagNS modifies the DNSLookupPlan to request resolving // the target domain's nameservers using NS. DNSLookupFlagNS = 1 << iota // DNSLookupFlagHTTPS modifies the DNSLookupPlan to request resolving // the target domain using HTTPSSvc. DNSLookupFlagHTTPS )
const ( // DefaultDNSLookupTimeout is the default Options.DNSLookupTimeout value. DefaultDNSLookupTimeout = 4 * time.Second // DefaultDNSParallelism is the default Options.DNSParallelism value. DefaultDNSParallelism = 4 // DefaultEndpointParallelism is the default Options.EndpointParallelism value. DefaultEndpointParallelism = 8 // DefaultHTTPGETTimeout is the default Options.HTTPGETTimeout value. DefaultHTTPGETTimeout = 15 * time.Second // DefaultMaxAddressPerFamily is the default value of Options.MaxAddressesPerFamily. For // experiments like websteps, where we have a TH, we're actually going to test twice this // number when there are many IP addresses per domain, because we're also going to take // into account some TH-tested addresses. Going below the recommended value of 2 here // is not recommended for websteps. Because websteps uses more than one resolver and // because measurex tries to arrange addresses so that we intermix system-resolver and // non-system-resolver resolutions, if you use less than two here you are going to // only test the first IP address returned by the system resolver, which means you're // probably going to miss part of the censorship that's there. DefaultMaxAddressPerFamily = 2 // DefaultMaxCrawlerDepth is the default value of Options.MaxCrawlerDepth. DefaultMaxCrawlerDepth = 3 // DefaultMaxHTTPResponseBodySnapshotSize is the default value // of Options.MaxHTTPResponseBodySnapshotSize. DefaultMaxHTTPResponseBodySnapshotSize = 1 << 19 // DefaultMaxHTTPSResponseBodySnapshotSizeConnectivity is the default value // of Options.MaxHTTPSResponseBodySnapshotSize when the URL path is "/", // where we assume we just want to check connectivity. DefaultMaxHTTPSResponseBodySnapshotSizeConnectivity = 1 << 12 // DefaultMaxHTTPSResponseBodySnapshotSizeThrottling is the default value // of Options.MaxHTTPSResponseBodySnapshotSize when the URL path is no "/", // where we assume we want to detect signs of throttling. DefaultMaxHTTPSResponseBodySnapshotSizeThrottling = 1 << 19 // DefaultQUICHandshakeTimeout is the default Options.QUICHandshakeTimeout value. DefaultQUICHandshakeTimeout = 10 * time.Second // DefaultTCPConnectTimeout is the default Options.TCPConnectTimeout value. DefaultTCPConnectTimeout = 15 * time.Second // DefaultTLSHandshakeTimeout is the default Options.TLSHandshakeTimeout value. DefaultTLSHandshakeTimeout = 10 * time.Second )
const ( // URLAddressSupportsHTTP3 indicates that a given URL address supports HTTP3. URLAddressSupportsHTTP3 = 1 << iota // URLAddressAlreadyTestedHTTP indicates that this address has already // been tested using the cleartext HTTP protocol. URLAddressAlreadyTestedHTTP // URLAddressAlreadyTestedHTTPS indicates that this address has already // been tested using the encrypted HTTPS protocol. URLAddressAlreadyTestedHTTPS // URLAddressAlreadyTestedHTTP3 indicates that this address has already // been tested using the encrypted HTTP3 protocol. URLAddressAlreadyTestedHTTP3 // URLAddressSystemResolver indicates that this entry has been // discovered through the system resolver. URLAddressSystemResolver )
const ( // EndpointPlanningExcludeBogons excludes bogons from NewEndpointPlan's planning. EndpointPlanningExcludeBogons = 1 << iota // EndpointPlanningOnlyHTTP3 ensures we only test HTTP3. EndpointPlanningOnlyHTTP3 // EndpointPlanningIncludeAll ensures that we include all the IP addresses // regardless on any options based restriction on the maximum number of // addresses per domain. This flag is used to ensure the TH receives the // whole list of IP addresses discovered by the client. EndpointPlanningIncludeAll // EndpointPlanningMeasureAgain ensures that we include endpoints that // we have already measured into the plan. EndpointPlanningMeasureAgain )
Variables ¶
var ( // ErrUnknownURLScheme means that the given // endpoint's URL scheme is neither HTTP nor HTTPS. ErrUnknownURLScheme = errors.New("unknown URL.Scheme") // ErrUnknownEndpointNetwork means that the given endpoint's // network is of a type that we don't know how to handle. ErrUnknownEndpointNetwork = errors.New("unknown Endpoint.Network") )
var ( // ErrCrawlerDepth indicates we have reached the maximum crawler depth ErrCrawlerDepth = errors.New("reached maximum crawler depth") // ErrCrawlerEOF indicates we have measured all URLs. ErrCrawlerEOF = errors.New("measured all the provided URLs") )
var DefaultHTTP3Transport = &http3.RoundTripper{}
DefaultHTTP3Transport is the default HTTP3 transport used by this library.
var ErrCannotDeterminePortFromURL = errors.New("cannot determine port from URL")
ErrCannotDeterminePortFromURL indicates that we could not determine the correct port from the URL authority and scheme.
var ErrHTTPTooManyRedirects = errors.New("stopped after 10 redirects")
ErrHTTPTooManyRedirects is the unexported error that the standard library would return when hitting too many redirects.
Functions ¶
func ALPNForHTTPSEndpoint ¶
func ALPNForHTTPSEndpoint(network archival.NetworkType) []string
ALPNForHTTPSEndpoint selects the correct ALPN for an HTTP endpoint given the network. On failure, we return an empty list.
func CanonicalURLString ¶
CanonicalURLString returns a representation of the given URL that should be more canonical than the random URLs returned by web services.
We need as canonical as possible URLs in URLRedirectDeque because their string representation is used to decide whether we need to follow redirects or not.
SPDX-License-Identifier: MIT
Adapted from: https://github.com/sekimura/go-normalize-url.
func GetWebPageTitle ¶
GetWebPageTitle returns the title or an empty string.
func NewCookieJar ¶
NewCookieJar is a convenience factory for creating an http.CookieJar that is aware of the effective TLS / public suffix list. This means that the jar won't allow a domain to set cookies for another unrelated domain (in the public-suffix-list sense).
func NewHTTPGetRequest ¶
NewHTTPGetRequest is a convenience factory for creating a new http.Request using the GET method and the given URL.
func NewHTTPRequestHeaderForMeasuring ¶
NewHTTPRequestHeaderForMeasuring returns an http.Header where the headers are the ones we use for measuring.
func NewHTTPRequestWithContext ¶
func NewHTTPRequestWithContext(ctx context.Context, method, URL string, body io.Reader) (*http.Request, error)
NewHTTPRequestWithContext is a convenience factory for creating a new HTTP request with the typical headers we use when performing measurements already set inside of req.Header.
func ParseCookies ¶
ParseCookies parses one or more serialized cookies into a list of *http.Cookie.
func PortFromURL ¶
PortFromURL returns the port determined from the URL or an error.
func SerializeCookies ¶
SerializeCookies takes in input []*http.Cookie and returns a []string where each string is a serialized cookie.
func SerializeCookiesNames ¶
SerializeCookiesNames takes in input []*http.Cookie and returns a []string where each string is a cookie name.
func SortedSerializedCookiesNames ¶
SortedSerializedCookiesNames returns a sorted copy of the cookies names.
func StringListSortUniq ¶
StringListSortUniq ensures a []string returns a sorted copy of the original list that does not contain any duplicate strings.
func URLAddressListToString ¶
func URLAddressListToString(ual []*URLAddress) string
URLAddressListToString transforms an URLAddressList to a flat list of IP addresses, which is useful for logging.
Types ¶
type AbstractMeasurer ¶
type AbstractMeasurer interface { // DNSLookups behaves like Measurer.DNSLookups. DNSLookups(ctx context.Context, dnsLookups ...*DNSLookupPlan) <-chan *DNSLookupMeasurement // FlattenOptions returns flattened options. FlattenOptions() *Options // MeasureEndpoints behaves like Measurer.MeasureEndpoints. MeasureEndpoints(ctx context.Context, epnts ...*EndpointPlan) <-chan *EndpointMeasurement // NewURLMeasurement behaves like Measurer.NewURLMeasurement. NewURLMeasurement(input string) (*URLMeasurement, error) // NewURLRedirectDeque behaves like Measurer.NewURLRedirectDeque. NewURLRedirectDeque() *URLRedirectDeque // NextID behaves like Measurer.NextID. NextID() int64 // Redirects behaves like Measurer.Redirects. Redirects(epnts []*EndpointMeasurement, opts *Options) ([]*URLMeasurement, bool) }
AbstractMeasurer is an abstract view of a Measurer.
type ArchivalDNSLookupMeasurement ¶
type ArchivalDNSLookupMeasurement struct { // ID is the unique ID of this measurement. ID int64 `json:"id,omitempty"` // Domain is the domain this lookup refers to. Domain string `json:"domain"` // ReverseAddress is a convenience field to help analysis that is only // set when we're performing a reverse DNS lookup. ReverseAddress string `json:"reverse_address,omitempty"` // ResolverNetwork is the network used by this resolver. ResolverNetwork string `json:"resolver_network"` // ResolverAddress is the address used by this resolver. ResolverAddress string `json:"resolver_address"` // Failure is the failure that occurred. Failure *string `json:"failure"` // Addresses contains the discovered addresses. Addresses []string `json:"addresses"` // Queries contains the DNS lookup events. Queries []model.ArchivalDNSLookupResult `json:"queries"` }
ArchivalDNSLookupMeasurement is an archival DNS lookup measurement.
func NewArchivalDNSLookupMeasurementList ¶
func NewArchivalDNSLookupMeasurementList( begin time.Time, in []*DNSLookupMeasurement) (out []ArchivalDNSLookupMeasurement)
NewArchivalDNSLookupMeasurementList converts a []*DNSLookupMeasurement into a []ArchivalDNSLookupMeasurement.
type ArchivalEndpointMeasurement ¶
type ArchivalEndpointMeasurement struct { // ID is the unique ID of this measurement. ID int64 `json:"id,omitempty"` // URL is the URL we're fetching. URL string `json:"url"` // Endpoint is the endpoint network. Network string `json:"network"` // Address is the endpoint address. Address string `json:"address"` // CookieNames contains the cookie names we sent. CookiesNames []string `json:"cookies_names"` // Failure is the error that occurred. Failure *string `json:"failure"` // FailedOperation is the operation that failed. FailedOperation *string `json:"failed_operation"` // StatusCode is the status code if any. StatusCode int64 `json:"status_code"` // Location is the redirect location if any. Location string `json:"location"` // BodyLength is the body length if any. BodyLength int64 `json:"body_length"` // Title is the webpage title if any. Title string `json:"title"` // NetworkEvent contains network events (if any). NetworkEvents []model.ArchivalNetworkEvent `json:"network_events"` // TCPConnect contains the TCP connect event (if any). TCPConnect *model.ArchivalTCPConnectResult `json:"tcp_connect"` // QUICTLSHandshake contains the QUIC/TLS handshake event (if any). QUICTLSHandshake *model.ArchivalTLSOrQUICHandshakeResult `json:"quic_tls_handshake"` // HTTPRoundTrip contains the HTTP round trip event (if any). HTTPRoundTrip *model.ArchivalHTTPRequestResult `json:"request"` }
ArchivalEndpointMeasurement is the archival format of an endpoint measurement.
func NewArchivalEndpointMeasurementList ¶
func NewArchivalEndpointMeasurementList(begin time.Time, in []*EndpointMeasurement, bodyFlags int64) (out []ArchivalEndpointMeasurement)
NewArchivalEndpointMeasurementList converts a []*EndpointMeasurement into a []ArchivalEndpointMeasurement.
type ArchivalURLMeasurement ¶
type ArchivalURLMeasurement struct { // ID is the unique ID of this URLMeasurement. ID int64 `json:"id"` // EndpointIDs contains the ID of the EndpointMeasurement(s) that // generated this URLMeasurement through redirects. EndpointIDs []int64 `json:"endpoint_ids"` // URL is the underlying URL to measure. URL string `json:"url"` // Cookies contains the cookies. Cookies []string `json:"cookies"` // DNS contains a list of DNS measurements. DNS []ArchivalDNSLookupMeasurement `json:"dns"` // Endpoint contains a list of endpoint measurements. Endpoint []ArchivalEndpointMeasurement `json:"endpoint"` }
ArchivalURLMeasurement is the archival format of an URL measurement.
type Cache ¶
type Cache struct { // DisableNetwork allows to disable network operations. DisableNetwork bool // DNS is a reference to the underlying DNS cache. DNS *caching.FSCache // Endpoint is a reference to the underlying endpoint cache. Endpoint *caching.FSCache }
Cache is a cache for measurex DNS and endpoint measurements.
func (*Cache) FindDNSLookupMeasurement ¶
func (c *Cache) FindDNSLookupMeasurement( plan *DNSLookupPlan, policy CachingPolicy) (*DNSLookupMeasurement, bool)
FindDNSLookupMeasurement searches for a DNSLookupMeasurement compatible with the plan.
func (*Cache) FindEndpointMeasurement ¶
func (c *Cache) FindEndpointMeasurement( plan *EndpointPlan, policy CachingPolicy) (*EndpointMeasurement, bool)
FindEndpointMeasurement finds the endpoint measurement deriving from the given plan.
func (*Cache) StartTrimmer ¶
StartTrimmer starts a background goroutine that runs until the given context is active and periodically trims the cache.
func (*Cache) StoreDNSLookupMeasurement ¶
func (c *Cache) StoreDNSLookupMeasurement(dlm *DNSLookupMeasurement) error
StoreDNSLookupMeasurement stores the given measurement into the cache.
func (*Cache) StoreEndpointMeasurement ¶
func (c *Cache) StoreEndpointMeasurement(em *EndpointMeasurement) error
StoreEndpointMeasurement stores the given measurement in cache.
type CachedDNSLookupMeasurement ¶
type CachedDNSLookupMeasurement struct { T time.Time M *DNSLookupMeasurement }
CachedDNSLookupMeasurement is the cached form of a DNSLookupMeasurement.
type CachedEndpointMeasurement ¶
type CachedEndpointMeasurement struct { T time.Time M *EndpointMeasurement }
CachedEndpointMeasurement is the cached form of an EndpointMeasurement.
type CachingMeasurer ¶
type CachingMeasurer struct {
// contains filtered or unexported fields
}
CachingMeasurer is a measurer using a local cache.
The cache works as follows:
1. it stores all the DNS lookup measurements using the same target domain into the same bucket and checks for equality using a strict definition of equality that includes not only the domain but also the lookup type to distinguish between similar DNS lookups for the same domain.
2. it stores all the endpoint measurements using as key their summary, which should avoid creating too large buckets.
On disk, the cache stores a list of records having the same ~unique sha256. Even when there should only be a single record with a given identifier (unlikely for domains but much more likely for endpoints) we use a list on disk just in case there's going to be any hash collision.
func NewCachingMeasurer ¶
func NewCachingMeasurer(mx AbstractMeasurer, cache *Cache, policy CachingPolicy) *CachingMeasurer
NewCachingMeasurer takes in input an existing measurer and the cache and returns a new instance of CachingMeasurer.
func (*CachingMeasurer) DNSLookups ¶
func (mx *CachingMeasurer) DNSLookups(ctx context.Context, dnsLookups ...*DNSLookupPlan) <-chan *DNSLookupMeasurement
DNSLookups implements AbstractMeasurer.DNSLookups.
func (*CachingMeasurer) FlattenOptions ¶
func (mx *CachingMeasurer) FlattenOptions() *Options
FlattenOptions implements AbstractMeasurer.FlattenOptions.
func (*CachingMeasurer) MeasureEndpoints ¶
func (mx *CachingMeasurer) MeasureEndpoints(ctx context.Context, epnts ...*EndpointPlan) <-chan *EndpointMeasurement
MeasureEndpoints implements AbstractMeasurer.MeasureEndpoints.
func (*CachingMeasurer) NewURLMeasurement ¶
func (mx *CachingMeasurer) NewURLMeasurement(input string) (*URLMeasurement, error)
NewURLMeasurement implements AbstractMeasurer.NewURLMeasurement.
func (*CachingMeasurer) NewURLRedirectDeque ¶
func (mx *CachingMeasurer) NewURLRedirectDeque() *URLRedirectDeque
NewURLRedirectDeque implements AbstractMeasurer.NewURLRedirectDeque.
func (*CachingMeasurer) NextID ¶
func (mx *CachingMeasurer) NextID() int64
NextID implements AbstractMeasurer.NextID.
func (*CachingMeasurer) Redirects ¶
func (mx *CachingMeasurer) Redirects(epnts []*EndpointMeasurement, opts *Options) ([]*URLMeasurement, bool)
Redirects implements AbstractMeasurer.Redirects.
type CachingPolicy ¶
type CachingPolicy interface { // StaleDNSLookupMeasurement returns whether a DNSLookupMeasurement is stale. StaleDNSLookupMeasurement(m *CachedDNSLookupMeasurement) bool // StaleEndpointMeasurement returns whether an EndpointMeasurement is stale. StaleEndpointMeasurement(m *CachedEndpointMeasurement) bool }
CachingPolicy allows to customize che CachingMeasurer policy.
func CachingForeverPolicy ¶
func CachingForeverPolicy() CachingPolicy
CachingForeverPolicy returns a policy that caches entries forever.
func ReasonableCachingPolicy ¶
func ReasonableCachingPolicy() CachingPolicy
ReasonableCachingPolicy returns a reasonable caching policy.
type Crawler ¶
type Crawler struct { // Measurer is the measurer to use. Measurer AbstractMeasurer // Options contains options. If this field is nil, we will // end up using the default option values. Options *Options // Resolvers contains the resolvers to use. Resolvers []*DNSResolverInfo }
Crawler starts from an input URL and visits the forest of all the URLs deriving from such an URL.
Please, either use NewCrawler to create a new instance or ensure you initialize all this struct's fields.
func NewCrawler ¶
func NewCrawler(mx AbstractMeasurer) *Crawler
NewCrawler creates a new instance of Crawler.
type DNSLookupMeasurement ¶
type DNSLookupMeasurement struct { // ID is the unique ID of this measurement. ID int64 `json:",omitempty"` // URLMeasurementID is the ID of the parent URLMeasurement. We do not // emit this information to JSON because it is redundant, but it's still // handy to know it when we're processing measurements. URLMeasurementID int64 `json:"-"` // ReverseAddress is a convenience field holding the addr for // which we issued a reverse lookup, which only makes sense when // we're actually performing a reverse lookup. ReverseAddress string `json:",omitempty"` // Lookup contains the DNS lookup event. This field contains a summary // of the information discovered during this lookup. We recommend using // this structure for processing the results. Lookup *archival.FlatDNSLookupEvent // RoundTrip contains DNS round trips. This field contains one or // more round trips performed during the lookup. The system resolver // fakes out a round trip with query type ANY and all the info // that we could gather from calling getaddrinfo (or equivalent). RoundTrip []*archival.FlatDNSRoundTripEvent `json:",omitempty"` }
DNSLookupMeasurement is a DNS lookup measurement.
func NewFakeHTTPSSvcDNSLookupMeasurement ¶
func NewFakeHTTPSSvcDNSLookupMeasurement(mx AbstractMeasurer, resolverNetwork archival.NetworkType, resolverAddress string, domain string, alpns []string, addresses []string) *DNSLookupMeasurement
NewFakeHTTPSSvcDNSLookupMeasurement creates a fake DNSLookupMeasurement from IP addresses obtained from an external source.
This factory is the best solution to fake a DNS lookup that can be compared with other DNS lookups. Because the returned lookup may also include ALPN information, we're faking an HTTPSSvc lookup result.
func (*DNSLookupMeasurement) ALPNs ¶
func (dlm *DNSLookupMeasurement) ALPNs() []string
ALPNs returns the list of ALPNs we discovered during the lookup.
func (*DNSLookupMeasurement) Addresses ¶
func (dlm *DNSLookupMeasurement) Addresses() []string
Addresses returns the list of addresses we discovered during the lookup.
func (*DNSLookupMeasurement) CNAME ¶
func (dlm *DNSLookupMeasurement) CNAME() string
CNAME returns the CNAME we discovered during the lookup.
func (*DNSLookupMeasurement) CouldDeriveFrom ¶
func (dlm *DNSLookupMeasurement) CouldDeriveFrom(p *DNSLookupPlan) bool
CouldDeriveFrom returns true if this measurement could have been the result of the plan provided as argument. This is true when the summary of the measurement is equal to the plan's summary.
func (*DNSLookupMeasurement) Describe ¶
func (dlm *DNSLookupMeasurement) Describe() string
Describe returns a compact human-readable description of this measurement.
func (*DNSLookupMeasurement) Domain ¶
func (dlm *DNSLookupMeasurement) Domain() string
Domain returns the domain for which we issued a DNS lookup.
func (*DNSLookupMeasurement) Failure ¶
func (dlm *DNSLookupMeasurement) Failure() archival.FlatFailure
Failure returns the failure that occurred.
func (*DNSLookupMeasurement) FinishedUnixNano ¶
func (dlm *DNSLookupMeasurement) FinishedUnixNano() int64
FinishedUnixNano returns the time when this measurement finished expressed in nanoseconds since the UNIX epoch.
func (*DNSLookupMeasurement) IsAnotherInstanceOf ¶
func (dlm *DNSLookupMeasurement) IsAnotherInstanceOf(o *DNSLookupMeasurement) bool
IsAnotherInstanceOf returns whether the current measurement is another instance of the other measurement, `o`. This is true when they have equal summary.
func (*DNSLookupMeasurement) IsCompatibleWith ¶
func (dlm *DNSLookupMeasurement) IsCompatibleWith(other *DNSLookupMeasurement) bool
IsCompatibleWith returns whether the current DNSLookupMeasurement can safely be compared with another DNSLookupMeasurement regardless of which specific DNS resolver has been used to perform the two measurements.
1. they are resolving the same domain;
2. they use the same lookup type.
A weaker definition of compatibility is provided by IsWeaklyCompatibleWith.
func (*DNSLookupMeasurement) IsWeaklyCompatibleWith ¶
func (dlm *DNSLookupMeasurement) IsWeaklyCompatibleWith(other *DNSLookupMeasurement) bool
IsWeaklyCompatibleWith returns whether the current DNSLookupMeasurement can safely be compared with another DNSLookupMeasurement regardless of which specific DNS resolver has been used to perform the two measurements.
We say that two DNSLookupMeasurements are weakly compatible if:
1. they are relative to the same domain;
2. the lookup type is compatible.
The following table shows when two lookup types are weakly compatible:
+-------------+-------------+-------+--------+---------+ | | getaddrinfo | https | ns | reverse | +-------------+-------------+-------+--------+---------+ | getaddrinfo | yes | yes | no | no | +-------------+-------------+-------+--------+---------+ | https | yes | yes | no | no | +-------------+-------------+-------+--------+---------+ | ns | no | no | yes | no | +-------------+-------------+-------+--------+---------+ | reverse | no | no | no | yes | +-------------+-------------+-------+--------+---------+
In addition, two lookup types are _always_ weakly compatible when they're the same, even if they are not listed in the above table.
A stronger definition of compatibility is provided by IsCompatibleWith.
func (*DNSLookupMeasurement) LookupType ¶
func (dlm *DNSLookupMeasurement) LookupType() archival.DNSLookupType
LookupType returns the lookup type (e.g., getaddrinfo, NS).
func (*DNSLookupMeasurement) NS ¶
func (dlm *DNSLookupMeasurement) NS() []string
NS returns the list of NS we discovered during the lookup.
func (*DNSLookupMeasurement) PTRs ¶
func (dlm *DNSLookupMeasurement) PTRs() []string
PTRs returns the PTRs we discovered during the lookup.
func (*DNSLookupMeasurement) ResolverAddress ¶
func (dlm *DNSLookupMeasurement) ResolverAddress() string
ResolverAddress returns the resolver address (e.g., 8.8.8.8:53).
func (*DNSLookupMeasurement) ResolverNetwork ¶
func (dlm *DNSLookupMeasurement) ResolverNetwork() archival.NetworkType
ResolverNetwork returns the resolver network (e.g., udp, system).
func (*DNSLookupMeasurement) ResolverURL ¶
func (dlm *DNSLookupMeasurement) ResolverURL() string
ResolverURL returns a URL containing the resolver's network and address. For DoH resolvers, we just return the URL. For all the other resolvers, we use the network as the scheme and the address as the URL host.
func (*DNSLookupMeasurement) Runtime ¶
func (dlm *DNSLookupMeasurement) Runtime() (out time.Duration)
Runtime returns the time elapsed waiting for the lookup to complete.
func (*DNSLookupMeasurement) Summary ¶
func (dlm *DNSLookupMeasurement) Summary() string
Summary returns a string representing the DNS measurement's plan. Two measurements are ~same if they have the same summary.
The summary of a DNS lookup consists of these fields:
- domain - lookupType - resolver network - resolver address
If the measurement is nil, we return the empty string.
func (*DNSLookupMeasurement) SupportsHTTP3 ¶
func (dlm *DNSLookupMeasurement) SupportsHTTP3() bool
SupportsHTTP3 returns whether this DNSLookupMeasurement includes the "h3" ALPN in the list of ALPNs for this domain.
func (*DNSLookupMeasurement) ToArchival ¶
func (m *DNSLookupMeasurement) ToArchival(begin time.Time) ArchivalDNSLookupMeasurement
ToArchival converts a DNSLookupMeasurement to ArchivalDNSLookupMeasurement.
func (*DNSLookupMeasurement) UsingResolverIPv6 ¶
func (dlm *DNSLookupMeasurement) UsingResolverIPv6() (usingIPv6 bool)
UsingResolverIPv6 returns whether this DNS lookups used an IPv6 resolver.
type DNSLookupPlan ¶
type DNSLookupPlan struct { // URLMeasurementID is the ID of the original URLMeasurement. URLMeasurementID int64 `json:",omitempty"` // Domain is the domain to measure. Domain string // ReverseAddress is a convenience field holding the addr for // which we issued a reverse lookup, which only makes sense when // we're actually performing a reverse lookup. ReverseAddress string `json:",omitempty"` // LookupType is the type of lookup to perform. LookupType archival.DNSLookupType // Options contains the options. If nil we'll use default values. Options *Options // Resolver is the resolver to use. Resolver *DNSResolverInfo }
DNSLookupPlan is a plan for performing a DNS lookup.
func NewDNSLookupPlans ¶
func NewDNSLookupPlans(domain string, options *Options, flags int64, ri ...*DNSResolverInfo) []*DNSLookupPlan
NewDNSLookupPlans creates a plan for measuring the given domain with the given options using the given list of resolvers. By default, we perform a getaddrinfo like lookup (i.e., A and AAAA). Use flags to add additional lookup types. For example, you can add a NS lookup using DNSLookupTypeNS.
func (*DNSLookupPlan) Clone ¶
func (dlp *DNSLookupPlan) Clone() (out *DNSLookupPlan)
Clone creates a DNSLookupPlan deep copy.
func (*DNSLookupPlan) CloneWithLookupType ¶
func (dlp *DNSLookupPlan) CloneWithLookupType(lt archival.DNSLookupType) (out *DNSLookupPlan)
CloneWithLookupType clones the original plan, configures the required lookup type, and returns the modified clone.
func (*DNSLookupPlan) Equals ¶
func (dlp *DNSLookupPlan) Equals(other *DNSLookupPlan) bool
Equals returns wheter a plan equals another plan. Two plans are equal if they have the same summary.
func (*DNSLookupPlan) ResolverAddress ¶
func (dlp *DNSLookupPlan) ResolverAddress() string
ResolverAddress returns the resolver address.
func (*DNSLookupPlan) ResolverNetwork ¶
func (dlp *DNSLookupPlan) ResolverNetwork() archival.NetworkType
ResolverNetwork returns the resolver network.
func (*DNSLookupPlan) Summary ¶
func (dlp *DNSLookupPlan) Summary() string
Summary returns a string representing the DNS lookup's plan. Two plans are ~same if they have the same summary.
The summary of a DNS lookup consists of these fields:
- domain - lookupType - resolver network - resolver address
If the plan is nil, we return the empty string.
type DNSResolverInfo ¶
type DNSResolverInfo struct { // Network is the resolver's network (e.g., "doh", "udp") Network archival.NetworkType // Address is the address (e.g., "1.1.1.1:53", "https://1.1.1.1/dns-query") Address string }
DNSResolverInfo contains info about a DNS resolver.
func NewResolversHTTPS ¶
func NewResolversHTTPS(urls ...string) []*DNSResolverInfo
NewResolversHTTPS creates a list of HTTPS resolvers from a list of URLs.
func NewResolversUDP ¶
func NewResolversUDP(endpoints ...string) []*DNSResolverInfo
NewResolversUDP creates a list of UDP resolvers from a list of endpoints.
func (*DNSResolverInfo) Clone ¶
func (dri *DNSResolverInfo) Clone() (out *DNSResolverInfo)
Clone returns a clone of this resolver info.
func (*DNSResolverInfo) Equals ¶
func (dri *DNSResolverInfo) Equals(other *DNSResolverInfo) bool
Equals returns whether a DNSResolverInfo equals another one.
type EndpointMeasurement ¶
type EndpointMeasurement struct { // ID is the unique ID of this measurement. ID int64 `json:",omitempty"` // URLMeasurementID is the ID of the URLMeasurement that created us. URLMeasurementID int64 `json:"-"` // URL is the URL this measurement refers to. URL *SimpleURL // Network is the network of this endpoint. Network archival.NetworkType // Address is the address of this endpoint. Address string // Options contains the options used for the measurement. Options *Options // OrigCookies contains the cookies we originally used. OrigCookies []*http.Cookie `json:",omitempty"` // Finished is when this measurement is finished. Finished time.Time // Failure is the error that occurred. Failure archival.FlatFailure `json:",omitempty"` // FailedOperation is the operation that failed. FailedOperation FlatFailedOperation `json:",omitempty"` // NewCookies contains cookies the next redirection (if any) should use. NewCookies []*http.Cookie `json:",omitempty"` // Location is the URL we're redirected to (if any). Location *SimpleURL `json:",omitempty"` // HTTPTitle is the webpage title (if any). HTTPTitle string `json:",omitempty"` // NetworkEvent contains network events (if any). NetworkEvent []*archival.FlatNetworkEvent `json:",omitempty"` // TCPConnect contains the TCP connect event (if any). TCPConnect *archival.FlatNetworkEvent `json:",omitempty"` // QUICTLSHandshake contains the QUIC/TLS handshake event (if any). QUICTLSHandshake *archival.FlatQUICTLSHandshakeEvent `json:",omitempty"` // HTTPRoundTrip contains the HTTP round trip event (if any). HTTPRoundTrip *archival.FlatHTTPRoundTripEvent `json:",omitempty"` }
EndpointMeasurement is an endpoint measurement.
func (*EndpointMeasurement) BodyIsTruncated ¶
func (em *EndpointMeasurement) BodyIsTruncated() bool
BodyIsTruncated returns whether the body is truncated. If there's no body, this function returns false.
func (*EndpointMeasurement) BodyLength ¶
func (em *EndpointMeasurement) BodyLength() int64
BodyLength returns the body length. If there's no body, it returns zero.
func (*EndpointMeasurement) CouldDeriveFrom ¶
func (em *EndpointMeasurement) CouldDeriveFrom(plan *EndpointPlan) bool
CouldDeriveFrom returns whether this endpoint could derive from the given plan. This happens when they have the same summary.
func (*EndpointMeasurement) Describe ¶
func (em *EndpointMeasurement) Describe() string
Describe describes this measurement.
func (*EndpointMeasurement) EndpointAddress ¶
func (em *EndpointMeasurement) EndpointAddress() string
EndpointAddress returns a string like "{address}/{network}".
func (*EndpointMeasurement) FinishedUnixNano ¶
func (em *EndpointMeasurement) FinishedUnixNano() int64
FinishedUnixNano returns the UnixNano time when this measurement was finished.
func (*EndpointMeasurement) IPAddress ¶
func (em *EndpointMeasurement) IPAddress() string
IPAddress returns the IP address used in this EndpointMeasurement.
func (*EndpointMeasurement) IsAnotherInstanceOf ¶
func (em *EndpointMeasurement) IsAnotherInstanceOf(other *EndpointMeasurement) bool
IsAnotherInstanceOf returns whether this EndpointMeasurement is another instance of the other EndpointMeasurement.
This happens when the two measurements have the same summary.
func (*EndpointMeasurement) IsHTTP3Measurement ¶
func (em *EndpointMeasurement) IsHTTP3Measurement() bool
IsHTTP3Measurement returns whether this EndpointMeasurement measures the encrypted HTTPS protocol using the QUIC network.
func (*EndpointMeasurement) IsHTTPMeasurement ¶
func (em *EndpointMeasurement) IsHTTPMeasurement() bool
IsHTTPMeasurement returns whether this EndpointMeasurement measures the cleartex HTTP protocol using the TCP network.
func (*EndpointMeasurement) IsHTTPRedirect ¶
func (em *EndpointMeasurement) IsHTTPRedirect() bool
IsHTTPRedirect returns whether this endpoint contains an HTTP redirect.
func (*EndpointMeasurement) IsHTTPSMeasurement ¶
func (em *EndpointMeasurement) IsHTTPSMeasurement() bool
IsHTTPSMeasurement returns whether this EndpointMeasurement measures the encrypted HTTPS protocol using the TCP network.
func (*EndpointMeasurement) LocationAsString ¶
func (em *EndpointMeasurement) LocationAsString() string
LocationAsString converts the location URL to string. If the location URL is nil, we return an empty string.
func (*EndpointMeasurement) RedirectLocationDomain ¶
func (em *EndpointMeasurement) RedirectLocationDomain() string
RedirectLocationDomain returns the domain of the redirect location.
func (*EndpointMeasurement) RedirectSummary ¶
func (em *EndpointMeasurement) RedirectSummary() (string, bool)
RedirectSummary is a summary of the endpoint's redirect. If there's no redirect, we return an empty string and false. Otherwise, we return a string that uniquely identifies this redirect and true.
Two redirects are ~same if they have the same redirect summary.
There is a redirect if the code is 301, 302, 303, 307, or 308 and there is a non-nil redirect location.
We use these fields for computing the summary:
- redirect location
- new cookies names (sorted)
func (*EndpointMeasurement) RequestHeaders ¶
func (em *EndpointMeasurement) RequestHeaders() http.Header
RequestHeaders returns the request headers. If there's no request we just return a set of empty headers.
func (*EndpointMeasurement) ResponseBody ¶
func (em *EndpointMeasurement) ResponseBody() []byte
ResponseBody returns the response body or empty byte array.
func (*EndpointMeasurement) ResponseBodyTLSH ¶
func (em *EndpointMeasurement) ResponseBodyTLSH() string
ResponseBodyTLSH returns the TLSH of the response body or empty string.
func (*EndpointMeasurement) ResponseHeaders ¶
func (em *EndpointMeasurement) ResponseHeaders() http.Header
ResponseHeaders returns the response headers. If there's no response we just return a set of empty headers.
func (*EndpointMeasurement) Scheme ¶
func (em *EndpointMeasurement) Scheme() string
Scheme returns the URL scheme or an empty string.
func (*EndpointMeasurement) SeemsLegitimateRedirect ¶
func (em *EndpointMeasurement) SeemsLegitimateRedirect() bool
SeemsLegitimateRedirect works as follows:
1. if this endpoint does not contain a redirect, return false;
2. if this endpoint's location is nil, return false;
3. otherwise returns whether the redirect domain is either equal to the original domain or has the same "public suffix".
func (*EndpointMeasurement) StatusCode ¶
func (em *EndpointMeasurement) StatusCode() int64
StatusCode returns the response status code. If there's no response we just return zero to the caller.
func (*EndpointMeasurement) Summary ¶
func (em *EndpointMeasurement) Summary() string
Summary returns a string representing the endpoint's summary. Two endpoints are ~same if they have the same summary.
The summary of an endpoint consists of these fields:
- URL
- Network
- Address
- relevant endpoint options
- original cookies names (sorted)
If the endpoint URL is nil, we return the empty string.
func (*EndpointMeasurement) SupportsAltSvcHTTP3 ¶
func (em *EndpointMeasurement) SupportsAltSvcHTTP3() bool
SupportsAltSvcHTTP3 indicates whether the response in this EndpointMeasurement contains headers claiming the service also supports HTTP3.
func (*EndpointMeasurement) TCPQUICConnectRuntime ¶
func (em *EndpointMeasurement) TCPQUICConnectRuntime() (out time.Duration)
TCPQUICConnectRuntime returns the TCP/QUIC connect runtime depending on which network is used by this endpoint.
func (*EndpointMeasurement) ToArchival ¶
func (m *EndpointMeasurement) ToArchival( begin time.Time, bodyFlags int64) ArchivalEndpointMeasurement
ToArchival converts a EndpointMeasurement to ArchivalEndpointMeasurement.
func (*EndpointMeasurement) URLAddressList ¶
func (em *EndpointMeasurement) URLAddressList() ([]*URLAddress, bool)
URLAddressList converts this EndpointMeasurement to an URLAddress list.
func (*EndpointMeasurement) URLAsString ¶
func (em *EndpointMeasurement) URLAsString() string
URLAsString converts the endpoint URL to string. If such an URL is nil, we return an empty string.
func (*EndpointMeasurement) URLDomain ¶
func (em *EndpointMeasurement) URLDomain() string
URLDomain returns the domain used by the URL.
func (*EndpointMeasurement) UsingAddressIPv6 ¶
func (em *EndpointMeasurement) UsingAddressIPv6() (usingIPv6 bool)
UsingAddressIPv6 returns true whether this specific endpoint has used an IPv6 destination address, false otherwise.
type EndpointPlan ¶
type EndpointPlan struct { // URLMeasurementID is the ID of the URLMeasurement that created us. URLMeasurementID int64 // Domain is the endpoint domain (e.g., "dns.google"). Domain string // Network is the network (e.g., "tcp" or "quic"). Network archival.NetworkType // Address is the endpoint address (e.g., "8.8.8.8:443"). Address string // URL is the endpoint URL. URL *SimpleURL // Options contains the options. A nil value implies that we're // going to use the default value of each option. Options *Options // Cookies contains the cookie to use when measuring. Cookies []*http.Cookie }
EndpointPlan is the plan to measure an endpoint.
func (*EndpointPlan) IPAddress ¶
func (em *EndpointPlan) IPAddress() string
IPAddress returns the IP address used in this EndpointMeasurement.
func (*EndpointPlan) Summary ¶
func (e *EndpointPlan) Summary() string
Summary returns a string representing the endpoint's plan. Two plans are ~same if they have the same summary.
The summary of an endpoint consists of these fields:
- URL
- Network
- Address
- relevant endpoint options
- cookies names (sorted)
If the endpoint URL is nil, we return the empty string.
type FlatFailedOperation ¶
type FlatFailedOperation = archival.FlatFailure
FlatFailedOperation is a flat representation of a failed operation.
type IDGenerator ¶
type IDGenerator struct {
// contains filtered or unexported fields
}
IDGenerator generates unique IDs for measurements.
func (*IDGenerator) NextID ¶
func (g *IDGenerator) NextID() int64
NextID returns the next unique ID.
type Library ¶
type Library struct {
// contains filtered or unexported fields
}
Library is a basic library for performing network measurements.
func NewDefaultLibrary ¶
func NewDefaultLibrary() *Library
NewDefaultLibrary creates a Library that uses netxlite.
func NewLibrary ¶
func NewLibrary(netx NetxliteLibrary) *Library
NewLibrary creates a new basic measurement library instance using a custom implementation of the nextlite library.
func (*Library) NewDialerWithoutResolver ¶
NewDialerWithoutResolver is a convenience factory for creating a dialer that saves measurements into the saver and that is not attached to any resolver (hence only works when passed IP addresses).
func (*Library) NewHTTPTransportWithConn ¶
func (lib *Library) NewHTTPTransportWithConn(saver *archival.Saver, conn net.Conn, maxBodySnapshotSize int64) model.HTTPTransport
NewHTTPTransportWithConn creates and wraps an HTTPTransport that does not dial and only uses the given conn.
func (*Library) NewHTTPTransportWithQUICSess ¶
func (lib *Library) NewHTTPTransportWithQUICSess(saver *archival.Saver, sess quic.EarlySession, maxBodySnapshotSize int64) model.HTTPTransport
NewHTTPTransportWithQUICSess creates and wraps an HTTPTransport that does not dial and only uses the given QUIC session.
func (*Library) NewHTTPTransportWithTLSConn ¶
func (lib *Library) NewHTTPTransportWithTLSConn(saver *archival.Saver, conn model.TLSConn, maxBodySnapshotSize int64) model.HTTPTransport
NewHTTPTransportWithTLSConn creates and wraps an HTTPTransport that does not dial and only uses the given conn.
func (*Library) NewQUICDialerWithoutResolver ¶
func (lib *Library) NewQUICDialerWithoutResolver(saver *archival.Saver) model.QUICDialer
NewQUICDialerWithoutResolver creates a new QUICDialer that is not attached to any resolver. This means that every attempt to dial any address containing a domain name will fail. This QUICDialer will save any event into the Saver. Any QUICConn created by it will likewise save any event into the Saver.
func (*Library) NewResolverDoH ¶
func (lib *Library) NewResolverDoH(saver *archival.Saver, clnt model.HTTPClient, network, address string) model.Resolver
NewResolverDoH is a convenience factory for creating a Resolver using DNS-over-HTTPS that saves measurements into the Saver.
Note that we'll not save HTTP related events (such as connecting, or handshaking) when issuing queries because the lifecycle of the HTTP client is much larger than the one of the saver.
The network argument should one of "doh" and "doh3". The former uses DNS-over-HTTPS and the latter DNS-over-HTTP3.
func (*Library) NewResolverSystem ¶
NewResolverSystem creates a system resolver and then wraps it using the WrapResolver function.
func (*Library) NewResolverUDP ¶
NewResolverUDP is a convenience factory for creating a Resolver using UDP that saves measurements into the Saver.
func (*Library) NewTLSHandshakerStdlib ¶
func (lib *Library) NewTLSHandshakerStdlib() model.TLSHandshaker
NewTLSHandshakerStdlib creates a new TLS handshaker that uses the Go standard library by invoking the underlying netxlite library.
func (*Library) WrapHTTPClient ¶
func (lib *Library) WrapHTTPClient(clnt model.HTTPClient) model.HTTPClient
WrapHTTPClient wraps an HTTP client using the underlying netxlite library.
type Measurer ¶
type Measurer struct { // HTTP3ClientForDoH is MANDATORY and is like HTTPClientForDoH except // that this client only uses the HTTP3 protocol. HTTP3ClientForDoH model.HTTPClient // HTTPClientForDoH is the MANDATORY HTTPClient to use for any // DNS resolution using the DNS-over-HTTPS transport. This client // SHOULD use a transport that allows multiple connections per // host, so we can issue queries in parallel. HTTPClientForDoH model.HTTPClient // IDGenerator is the MANDATORY atomic variable used to generate // unique identifiers for measurements. IDGenerator *IDGenerator // Library is the MANDATORY network-measurement library. Library *Library // Options contains the options. If nil, we'll use default values. Options *Options // TLSHandshaker is the MANDATORY TLS handshaker. TLSHandshaker model.TLSHandshaker }
Measurer performs measurements. If you don't use a factory for creating this type, make sure you set all the MANDATORY fields.
func NewMeasurer ¶
NewMeasurer creates a new Measurer instance using the default settings.
func NewMeasurerWithDefaultSettings ¶
func NewMeasurerWithDefaultSettings() *Measurer
NewMeasurerWithDefaultSettings creates a new measurer using apex/log's singleton as the logger and netxlite as the underlying library.
func NewMeasurerWithOptions ¶
NewMeasurerWithOptions creates a new Measurer instance with the given options.
func (*Measurer) DNSLookups ¶
func (mx *Measurer) DNSLookups(ctx context.Context, dnsLookups ...*DNSLookupPlan) <-chan *DNSLookupMeasurement
DNSLookups performs DNS lookups in parallel.
This function returns a channel where to read/ measurements from. The channel is closed when done.
func (*Measurer) FlattenOptions ¶
FlattenOptions implements AbstractMeasurer.FlattenOptions.
func (*Measurer) MeasureEndpoints ¶
func (mx *Measurer) MeasureEndpoints( ctx context.Context, epnts ...*EndpointPlan) <-chan *EndpointMeasurement
MeasureEndpoints measures some endpoints in parallel.
You can choose the parallelism with the parallelism argument. If this argument is zero, or negative, we use a small default value.
This function returns to the caller a channel where to read measurements from. The channel is closed when done.
func (*Measurer) NewURLMeasurement ¶
func (mx *Measurer) NewURLMeasurement(input string) (*URLMeasurement, error)
NewURLMeasurement creates a new URLMeasurement from a string URL.
func (*Measurer) NewURLRedirectDeque ¶
func (mx *Measurer) NewURLRedirectDeque() *URLRedirectDeque
NewURLRedirectDeque creates an URLRedirectDeque.
func (*Measurer) Redirects ¶
func (mx *Measurer) Redirects( epnts []*EndpointMeasurement, opts *Options) ([]*URLMeasurement, bool)
Redirects returns all the redirects seen in this URLMeasurement as a list of follow-up URLMeasurement instances. This function will return false if the returned list of follow-up measurements is empty.
type NetxliteLibrary ¶
type NetxliteLibrary interface { // NewDNSOverUDPTransport creates a new DNS-over-UDP DNS transport. NewDNSOverUDPTransport(dialer model.Dialer, address string) model.DNSTransport // NewDNSOverHTTPSTransport creates a new DNS-over-HTTPS DNS transport. The // network argument should be one of "doh" and "doh3". NewDNSOverHTTPSTransport(clnt model.HTTPClient, network, address string) model.DNSTransport // NewDNSSystemResolver creates a DNS resolver using the system resolver. NewDNSSystemResolver(txp model.DNSTransport) model.Resolver // NewDNSSystemTransport creates a DNS transport using the system resolver. NewDNSSystemTransport() model.DNSTransport // NewDialerWithResolver creates a new dialer using the given resolver NewDialerWithResolver(reso model.Resolver) model.Dialer // NewDialerWithoutResolver creates a new dialer not using any resolver. NewDialerWithoutResolver() model.Dialer // NewHTTP3Transport creates a new HTTPTransport using HTTP3. NewHTTP3Transport(dialer model.QUICDialer, tlsConfig *tls.Config) model.HTTPTransport // NewHTTPTransport creates a new HTTPTransport. NewHTTPTransport(dialer model.Dialer, tlsDialer model.TLSDialer) model.HTTPTransport // NewNullDialer creates a new "null" Dialer. NewNullDialer() model.Dialer // NewNullTLSDialer creates a new "null" TLSDialer. NewNullTLSDialer() model.TLSDialer // NewQUICDialerWithoutResolver creates a new QUIC dialer // that is not attached to any resolver. NewQUICDialerWithoutResolver(ql model.UDPListener) model.QUICDialer // NewUDPListener creates a new UDP listener. NewUDPListener() model.UDPListener // NewUnwrappedParallelResolver creates a new "parallel" resolver. (Note that // this resolver needs to be wrapped.) NewUnwrappedParallelResolver(txp model.DNSTransport) model.Resolver // NewSingleUseDialer creates a new "single use" dialer. NewSingleUseDialer(conn net.Conn) model.Dialer // NewSingleUseQUICDialer creates a new "single use" QUIC dialer. NewSingleUseQUICDialer(sess quic.EarlySession) model.QUICDialer // NewSingleUseTLSDialer creates a new "single use" TLS dialer. NewSingleUseTLSDialer(conn model.TLSConn) model.TLSDialer // NewTLSHandshakerStdlib creates a new TLS handshaker using the stdlib. NewTLSHandshakerStdlib() model.TLSHandshaker // WrapHTTPClient wraps an HTTP client. WrapHTTPClient(clnt model.HTTPClient) model.HTTPClient // WrapResolver wraps a resolver. WrapResolver(reso model.Resolver) model.Resolver }
NetxliteLibrary abstracts the netxlite dependency.
type OperationLogger ¶
type OperationLogger struct {
// contains filtered or unexported fields
}
OperationLogger logs about an in-progress operation
func NewOperationLogger ¶
func NewOperationLogger(format string, v ...interface{}) *OperationLogger
NewOperationLogger creates a new logger that logs about an in-progress operation.
func (*OperationLogger) Stop ¶
func (ol *OperationLogger) Stop(err error)
type Options ¶
type Options struct { // ALPN allows to override the QUIC/TLS ALPN we'll use. ALPN []string `json:",omitempty"` // DNSLookupTimeout is the maximum time we're willing to wait // for any DNS lookup to complete. DNSLookupTimeout time.Duration `json:",omitempty"` // DNSParallelism is the number of parallel goroutines we will // use for measuring HTTP/HTTPS/HTTP3 endpoints. DNSParallelism int64 `json:",omitempty"` // EndpointParallellism is the number of parallel goroutines we will // use for measuring HTTP/HTTPS/HTTP3 endpoints. EndpointParallelism int64 `json:",omitempty"` // HTTPGetTimeout is the maximum time we're willing to wait // for any HTTP GET operation to complete. HTTPGetTimeout time.Duration `json:",omitempty"` // HTTPHostHeader allows to override the Host header we'll use. HTTPHostHeader string `json:",omitempty"` // HTTPRequestHeaders controls the HTTP request headers we'll use in // the first HTTP request. Subsequent requests following redirects // will use the same headers of the first request. HTTPRequestHeaders http.Header `json:",omitempty"` // DoNotInitiallyForceHTTPAndHTTPS controls whether we're going to // initially force using both HTTP and HTTPS for the first URL. // // TODO(bassosimone): per the latest spec, we should rename this // variable to become DoNotFollowHTTPAndHTTPS (or maybe we can even // find a better name that is even more explanatory). DoNotInitiallyForceHTTPAndHTTPS bool `json:",omitempty"` // MaxAddressesPerFamily controls the maximum number of IP addresses // per family (i.e., A and AAAA) we'll test. MaxAddressesPerFamily int64 `json:",omitempty"` // MaxCrawlerDepth is the maximum exploration depth. Every different // redirection is another depth level. We will stop exploring when we'll // have reached the maximum depth. MaxCrawlerDepth int64 `json:",omitempty"` // MaxHTTPResponseBodySnapshotSize is the maximum response body // snapshot size for cleartext requests (HTTP). MaxHTTPResponseBodySnapshotSize int64 `json:",omitempty"` // MaxHTTPSResponseBodySnapshotSizeConnectivity is the maximum response body // snapshot size for encrypted requests (HTTPS/HTTP3), used when we're just // ensuring that we can speak with a given HTTPS endpoint. MaxHTTPSResponseBodySnapshotSizeConnectivity int64 `json:",omitempty"` // MaxHTTPSResponseBodySnapshotSizeThrottling is the maximum response body // snapshot size for encrypted requests (HTTPS/HTTP3), used when we want // to measure the download speed by downloading a sizable body chunk. MaxHTTPSResponseBodySnapshotSizeThrottling int64 `json:",omitempty"` // Parent is the parent Options data structure. By setting this field // you can layer new Options on top of existing Options. Parent *Options `json:",omitempty"` // QUICHandshakeTimeout is the maximum time we're willing to wait // for any QUIC handshake to complete. QUICHandshakeTimeout time.Duration `json:",omitempty"` // TCPConnectTimeout is the maximum time we're willing to wait // for any TCP connect attempt to complete. TCPconnectTimeout time.Duration `json:",omitempty"` // TLSHandshakeTimeout is the maximum time we're willing to wait // for any TLS handshake to complete. TLSHandshakeTimeout time.Duration `json:",omitempty"` // SNI allows to override the QUIC/TLS SNI we'll use. SNI string `json:",omitempty"` }
Options contains options. Every field in this structure is optional and all the methods works as intended when *Options is nil.
type SimpleURL ¶
type SimpleURL struct { // Scheme is the URL scheme. Scheme string `json:",omitempty"` // Host is the host (possily containing a port) Host string // Path is the URL path. Path string `json:",omitempty"` // RawQuery contains the unparsed query. RawQuery string `json:",omitempty"` }
SimpleURL is a simpler URL representation.
func NewSimpleURL ¶
NewSimpleURL creates a simple URL from an URL.
func ParseSimpleURL ¶
ParseSimpleURL parses a simple URL and returns it.
type URLAddress ¶
type URLAddress struct { // URLMeasurementID is the ID of the parent URLMeasurement. URLMeasurementID int64 // Address is the target IPv4/IPv6 address. Address string // Domain is the domain of the URL. Domain string // Flags contains URL flags. Flags int64 }
URLAddress is an address associated with a given URL.
func EndpointMeasurementListToURLAddressList ¶
func EndpointMeasurementListToURLAddressList( domain string, eml ...*EndpointMeasurement) ([]*URLAddress, bool)
EndpointMeasurementListToURLAddressList takes in input a list of EndpointMeasurement and produces an URLAddressList.
The domain filter selects only the measurements that are actually valid for the given domain.
Note: do not use this function if you have better ways of creating an URLAddress list, such as, URLMeasurement.URLAddressList.
func MergeURLAddressListStable ¶
func MergeURLAddressListStable(in ...[]*URLAddress) []*URLAddress
MergeURLAddressListStable takes in input a list of []*URLAddress and it returns a new list where each IP address appears just once and the flags of all its duplicates in input have been merged. The first step of the algorithm is creating a unique list concatenating all the lists provided in input. Then, it will proceed to remove duplicates. In doing so, it will preserve the original order in which unique IP addresses appear in the concatenated list. For example, if IP A appears before IP B in the concatenated list, the same will hold for the return list. Note that the elements of the returned list are clones of the original. So this is a non-destructive and data-race-safe operation.
func NewURLAddressList ¶
func NewURLAddressList(ID int64, domain string, dns []*DNSLookupMeasurement, endpoint []*EndpointMeasurement) ([]*URLAddress, bool)
NewURLAddressList generates a list of URLAddresses based on DNS lookups and Endpoint measurements, all relative to the given ID. We'll _only_ include into the result the IP addresses relative to the given domain. The boolean return value indicates whether we have at least one IP address in the result.
func (*URLAddress) AlreadyTestedHTTP ¶
func (ua *URLAddress) AlreadyTestedHTTP() bool
AlreadyTestedHTTP returns whether we've already tested this IP address using HTTP.
func (*URLAddress) AlreadyTestedHTTP3 ¶
func (ua *URLAddress) AlreadyTestedHTTP3() bool
AlreadyTestedHTTP3 returns whether we've already tested this IP address using HTTP3.
func (*URLAddress) AlreadyTestedHTTPS ¶
func (ua *URLAddress) AlreadyTestedHTTPS() bool
AlreadyTestedHTTPS returns whether we've already tested this IP address using HTTPS.
func (*URLAddress) Clone ¶
func (ua *URLAddress) Clone() *URLAddress
Clone creates a clone of this URLAddressList.
func (*URLAddress) SupportsHTTP3 ¶
func (ua *URLAddress) SupportsHTTP3() bool
SupportsHTTP3 returns whether we think this address supports HTTP3.
type URLAddressListDiff ¶
type URLAddressListDiff struct { // ModifiedFlags contains all the entries in A that have different // flags compared to the respective entries in B. ModifiedFlags []*URLAddress // NewEntries contains all the entries in A that do not appear in B. NewEntries []*URLAddress }
URLAddressListDiff is the diff of two []*URLAddress.
func NewURLAddressListDiff ¶
func NewURLAddressListDiff(A, B []*URLAddress) *URLAddressListDiff
NewURLAddressListDiff takes in input two []*URLAddress A and B and returns in output all the elements of A that do not appear in B or appear in B with different flags than they appear in A. If the two lists are equal, we just return to the caller an empty diff. The output will always be a valid struct containing lists with pointers to the original matching elements in the A list. The relative order of elements in the lists of the returned diff struct is consistent with the order they appear in the A list.
type URLMeasurement ¶
type URLMeasurement struct { // ID is the unique ID of this URLMeasurement. ID int64 // EndpointIDs contains the ID of the EndpointMeasurement(s) that // generated this URLMeasurement through redirects. EndpointIDs []int64 `json:",omitempty"` // Options contains options. If nil, we'll use default values. Options *Options `json:",omitempty"` // URL is the underlying URL to measure. URL *SimpleURL // Cookies contains the list of cookies to use. Cookies []*http.Cookie `json:",omitempty"` // DNS contains a list of DNS measurements. DNS []*DNSLookupMeasurement // Endpoint contains a list of endpoint measurements. Endpoint []*EndpointMeasurement }
URLMeasurement is the (possibly interim) result of measuring an URL.
func (*URLMeasurement) AddFromExternalDNSLookup ¶
func (um *URLMeasurement) AddFromExternalDNSLookup(mx AbstractMeasurer, resolverNetwork, resolverAddress string, alpns []string, addrs ...string)
AddFromExternalDNSLookup adds the result of an "external" DNS lookup (i.e., a lookup not performed using measurex) to the URLMeasurement.DNS list. You can use this functionality, for example, for pre-filling the DNS list with selected IP addresses.
Each IP address will be added to a single entry. We will skip strings that are not valid IP addresses representations. The fake entry will use the given resolver network and address (you may want to, e.g., set them to "probe" or "th").
The entry will fake an HTTPSvc lookup because that also allows you to include ALPN, which you may know, into the generated fake lookup entry. If you don't know the ALPN, pass nil as the alpns argument; we will convert it to an empty list for you.
If there are duplicate entries, they will be collapsed by this function.
func (*URLMeasurement) Domain ¶
func (um *URLMeasurement) Domain() string
Domain is the domain inside the input URL.
func (*URLMeasurement) IsHTTP ¶
func (um *URLMeasurement) IsHTTP() bool
IsHTTP returns whether this URL is HTTP.
func (*URLMeasurement) IsHTTPS ¶
func (um *URLMeasurement) IsHTTPS() bool
IsHTTPS returns whether this URL is HTTPS.
func (*URLMeasurement) NewDNSLookupPlans ¶
func (um *URLMeasurement) NewDNSLookupPlans( flags int64, ri ...*DNSResolverInfo) []*DNSLookupPlan
NewDNSLookupPlans is a convenience function for calling the NewDNSLookupPlans free function in the context of this URLMeasurement.
func (*URLMeasurement) NewDNSReverseLookupPlans ¶
func (um *URLMeasurement) NewDNSReverseLookupPlans( addrs []string, ri ...*DNSResolverInfo) []*DNSLookupPlan
NewDNSReverseLookupPlans generates a []*DNSLookupPlan for performing a reverse lookup for the given list of addresses and the given resolvers.
func (*URLMeasurement) NewEndpointPlan ¶
func (um *URLMeasurement) NewEndpointPlan(flags int64) ([]*EndpointPlan, bool)
NewEndpointPlan is a convenience function that calls um.URLAddressList and passes the resulting list to um.NewEndpointPlanWithAddressList.
func (*URLMeasurement) NewEndpointPlanWithAddressList ¶
func (um *URLMeasurement) NewEndpointPlanWithAddressList( addrs []*URLAddress, flags int64) ([]*EndpointPlan, bool)
NewEndpointPlanWithAddressList creates a new plan for measuring all the endpoints derived from the given address list compatibly with options constraints.
Note that the returned list will include HTTP, HTTPS, and HTTP3 plans related to the original URL regardless of its scheme.
The flags argument allows to specify flags that modify the planning algorithm. The EndpointPlanningExcludeBogons flag is such that we will not include any bogon IP address into the returned plan.
func (*URLMeasurement) ToArchival ¶
func (m *URLMeasurement) ToArchival(begin time.Time, bodyFlags int64) ArchivalURLMeasurement
ToArchival converts URLMeasurement to ArchivalURLMeasurement.
func (*URLMeasurement) URLAddressList ¶
func (um *URLMeasurement) URLAddressList() ([]*URLAddress, bool)
URLAddressList calls NewURLAddressList using um.ID, um.DNS, and um.Endpoint.
type URLRedirectDeque ¶
type URLRedirectDeque struct {
// contains filtered or unexported fields
}
URLRedirectDeque is the type we use to manage the redirection queue and to follow a reasonable number of redirects.
func (*URLRedirectDeque) Append ¶
func (r *URLRedirectDeque) Append(um ...*URLMeasurement)
Append appends one or more URLMeasurement to the right of the deque.
func (*URLRedirectDeque) Depth ¶
func (r *URLRedirectDeque) Depth() int64
Depth returns the number or redirects we followed so far.
func (*URLRedirectDeque) MaxDepth ¶
func (r *URLRedirectDeque) MaxDepth() int64
MaxDepth returns the maximum depth.
func (*URLRedirectDeque) PopLeft ¶
func (r *URLRedirectDeque) PopLeft() (*URLMeasurement, error)
PopLeft removes the first element in the redirect deque. Returns true if we returned an element and false when the deque is empty.
func (*URLRedirectDeque) RememberVisitedURLs ¶
func (r *URLRedirectDeque) RememberVisitedURLs(epnts []*EndpointMeasurement)
RememberVisitedURLs register the URLs we've already visited so that we're not going to visit them again.
func (*URLRedirectDeque) String ¶
func (r *URLRedirectDeque) String() string
String returns a string representation of the deque.