measurexlite

package
v0.0.0-...-7d1b61d Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 19, 2023 License: GPL-3.0 Imports: 22 Imported by: 0

Documentation

Overview

Package measurexlite contains measurement extensions.

See docs/design/dd-003-step-by-step.md in the ooni/probe-cli repository for the design document.

This implementation features a Trace that saves events in buffered channels as proposed by df-003-step-by-step.md. We have reasonable default buffers for channels. But, if you are not draining them, eventually we stop collecting events.

Index

Constants

View Source
const (
	// NetworkEventBufferSize is the buffer size for constructing
	// the Trace's networkEvent buffered channel.
	NetworkEventBufferSize = 64

	// DNSLookupBufferSize is the buffer size for constructing
	// the Trace's dnsLookup buffered channel.
	DNSLookupBufferSize = 8

	// DNSResponseBufferSize is the buffer size for constructing
	// the Trace's dnsDelayedResponse buffered channel.
	DelayedDNSResponseBufferSize = 8

	// TCPConnectBufferSize is the buffer size for constructing
	// the Trace's tcpConnect buffered channel.
	TCPConnectBufferSize = 8

	// TLSHandshakeBufferSize is the buffer for construcing
	// the Trace's tlsHandshake buffered channel.
	TLSHandshakeBufferSize = 8

	// QUICHandshakeBufferSize is the buffer for constructing
	// the Trace's quicHandshake buffered channel.
	QUICHandshakeBufferSize = 8
)

Variables

View Source
var ErrDelayedDNSResponseBufferFull = errors.New("buffer full")

ErrDelayedDNSResponseBufferFull indicates that the delayedDNSResponse buffer is full.

Functions

func MaybeClose

func MaybeClose(conn net.Conn) (err error)

MaybeClose is a convenience function for closing a conn only when such a conn isn't nil.

func MaybeCloseQUICConn

func MaybeCloseQUICConn(conn quic.EarlyConnection) (err error)

MaybeCloseQUICConn is a convenience function for closing a quic.EarlyConnection only when such a conn isn't nil.

func MaybeCloseUDPLikeConn

func MaybeCloseUDPLikeConn(conn model.UDPLikeConn) (err error)

MaybeUDPLikeClose is a convenience function for closing a conn only when such a conn isn't nil.

func NewAnnotationArchivalNetworkEvent

func NewAnnotationArchivalNetworkEvent(
	index int64, time time.Duration, operation string) *model.ArchivalNetworkEvent

NewAnnotationArchivalNetworkEvent is a simplified NewArchivalNetworkEvent where we create a simple annotation without attached I/O info.

func NewArchivalDNSLookupResultFromRoundTrip

func NewArchivalDNSLookupResultFromRoundTrip(index int64, started time.Duration, reso DNSNetworkAddresser, query model.DNSQuery,
	response model.DNSResponse, addrs []string, err error, finished time.Duration) *model.ArchivalDNSLookupResult

NewArchivalDNSLookupResultFromRoundTrip generates a model.ArchivalDNSLookupResultFromRoundTrip from the available information right after the DNS RoundTrip

func NewArchivalHTTPRequestResult

func NewArchivalHTTPRequestResult(index int64, started time.Duration, network, address, alpn string,
	transport string, req *http.Request, resp *http.Response, maxRespBodySize int64, body []byte, err error,
	finished time.Duration) *model.ArchivalHTTPRequestResult

NewArchivalHTTPRequestResult creates a new model.ArchivalHTTPRequestResult.

Arguments:

- index is the index of the trace;

- started is when we started sending the request;

- network is the underlying network in use ("tcp" or "udp");

- address is the remote endpoint's address;

- alpn is the negotiated ALPN or an empty string when not applicable;

- transport is the HTTP transport's protocol we're using ("udp" or "tcp"): this field was introduced a long time ago to support QUIC measurements and we keep it for backwards compatibility but network, address, and alpn are much more informative;

- req is the certainly-non-nil HTTP request;

- resp is the possibly-nil HTTP response;

- maxRespBodySize is the maximum body snapshot size;

- body is the possibly-nil HTTP response body;

- err is the possibly-nil error that occurred during the transaction;

- finished is when we finished reading the response's body.

func NewArchivalNetworkEvent

func NewArchivalNetworkEvent(index int64, started time.Duration, operation string, network string,
	address string, count int, err error, finished time.Duration) *model.ArchivalNetworkEvent

NewArchivalNetworkEvent creates a new model.ArchivalNetworkEvent.

func NewArchivalTCPConnectResult

func NewArchivalTCPConnectResult(index int64, started time.Duration, address string,
	err error, finished time.Duration) *model.ArchivalTCPConnectResult

NewArchivalTCPConnectResult generates a model.ArchivalTCPConnectResult from the available information right after connect returns.

func NewArchivalTLSOrQUICHandshakeResult

func NewArchivalTLSOrQUICHandshakeResult(
	index int64, started time.Duration, network string, address string, config *tls.Config,
	state tls.ConnectionState, err error, finished time.Duration) *model.ArchivalTLSOrQUICHandshakeResult

NewArchivalTLSOrQUICHandshakeResult generates a model.ArchivalTLSOrQUICHandshakeResult from the available information right after the TLS handshake returns.

func NewFailure

func NewFailure(err error) *string

NewFailure creates an OONI failure from an error. If the error is nil, we return nil. If the error is not already an ErrWrapper, it's converted to an ErrWrapper. If the ErrWrapper's Failure is not empty, we return its string representation. Otherwise we return a string indicating that an ErrWrapper has an empty failure (should not happen).

See https://github.com/ooni/spec/blob/master/data-formats/df-007-errors.md for more information about OONI failures.

func TLSPeerCerts

func TLSPeerCerts(
	state tls.ConnectionState, err error) (out []model.ArchivalMaybeBinaryData)

TLSPeerCerts extracts the certificates either from the list of certificates in the connection state or from the error that occurred.

func WebGetTitle

func WebGetTitle(measurementBody string) string

WebGetTitle returns the title or an empty string.

Types

type DNSNetworkAddresser

type DNSNetworkAddresser interface {
	// Address is like model.DNSTransport.Address
	Address() string

	// Network is like model.DNSTransport.Network
	Network() string
}

DNSNetworkAddresser is the type of something we just used to perform a DNS round trip (e.g., model.DNSTransport, model.Resolver) that allows us to get the network and the address of the underlying resolver/transport.

type OperationLogger

type OperationLogger struct {
	// contains filtered or unexported fields
}

OperationLogger keeps state required to log about an in-progress operation as documented by NewOperationLogger.

func NewOperationLogger

func NewOperationLogger(logger model.Logger, format string, v ...any) *OperationLogger

NewOperationLogger creates a new logger that logs about an in-progress operation. If it takes too much time to emit the result of the operation, the code will emit an interim log message mentioning that the operation is currently in progress.

func (*OperationLogger) Stop

func (ol *OperationLogger) Stop(value any)

Stop must be called when the operation is done. The [value] argument is the result of the operation, which may be nil. This method ensures that we log the final result of the now-completed operation.

type Trace

type Trace struct {
	// Index is the MANDATORY unique index of this trace within the
	// current measurement. If you don't care about uniquely identifying
	// traces, you can use zero to indicate the "default" trace.
	Index int64

	// NewStdlibResolverFn is OPTIONAL and can be used to overide
	// calls to the netxlite.NewStdlibResolver factory.
	NewStdlibResolverFn func(logger model.Logger) model.Resolver

	// NewParallelUDPResolverFn is OPTIONAL and can be used to overide
	// calls to the netxlite.NewParallelUDPResolver factory.
	NewParallelUDPResolverFn func(logger model.Logger, dialer model.Dialer, address string) model.Resolver

	// NewParallelDNSOverHTTPSResolverFn is OPTIONAL and can be used to overide
	// calls to the netxlite.NewParallelDNSOverHTTPSUDPResolver factory.
	NewParallelDNSOverHTTPSResolverFn func(logger model.Logger, URL string) model.Resolver

	// NewDialerWithoutResolverFn is OPTIONAL and can be used to override
	// calls to the netxlite.NewDialerWithoutResolver factory.
	NewDialerWithoutResolverFn func(dl model.DebugLogger) model.Dialer

	// NewTLSHandshakerStdlibFn is OPTIONAL and can be used to overide
	// calls to the netxlite.NewTLSHandshakerStdlib factory.
	NewTLSHandshakerStdlibFn func(dl model.DebugLogger) model.TLSHandshaker

	// NewTLSHandshakerUTLSFn is OPTIONAL and can be used to overide
	// calls to the netxlite.NewTLSHandshakerUTLS factory.
	NewTLSHandshakerUTLSFn func(dl model.DebugLogger, id *utls.ClientHelloID) model.TLSHandshaker

	// NewDialerWithoutResolverFn is OPTIONAL and can be used to override
	// calls to the netxlite.NewQUICDialerWithoutResolver factory.
	NewQUICDialerWithoutResolverFn func(listener model.QUICListener, dl model.DebugLogger) model.QUICDialer

	// TimeNowFn is OPTIONAL and can be used to override calls to time.Now
	// to produce deterministic timing when testing.
	TimeNowFn func() time.Time

	// ZeroTime is the MANDATORY time when we started the current measurement.
	ZeroTime time.Time
	// contains filtered or unexported fields
}

Trace implements model.Trace.

The zero-value of this struct is invalid. To construct you should either fill all the fields marked as MANDATORY or use NewTrace.

Buffered channels

NewTrace uses reasonable buffer sizes for the channels used for collecting events. You should drain the channels used by this implementation after each operation you perform (i.e., we expect you to peform step-by-step measurements). If you want larger (or smaller) buffers, then you should construct this data type manually with the desired buffer sizes.

We have convenience methods for extracting events from the buffered channels. Otherwise, you could read the channels directly. (In which case, remember to issue nonblocking channel reads because channels are never closed and they're just written when new events occur.)

func NewTrace

func NewTrace(index int64, zeroTime time.Time) *Trace

NewTrace creates a new instance of Trace using default settings.

We create buffered channels using as buffer sizes the constants that are also defined by this package.

Arguments:

- index is the unique index of this trace within the current measurement (use zero if you don't care about giving this trace a unique ID);

- zeroTime is the time when we started the current measurement.

func (*Trace) DNSLookupsFromRoundTrip

func (tx *Trace) DNSLookupsFromRoundTrip() (out []*model.ArchivalDNSLookupResult)

DNSLookupsFromRoundTrip drains the network events buffered inside the DNSLookup channel

func (*Trace) DelayedDNSResponseWithTimeout

func (tx *Trace) DelayedDNSResponseWithTimeout(ctx context.Context,
	timeout time.Duration) (out []*model.ArchivalDNSLookupResult)

DelayedDNSResponseWithTimeout drains the network events buffered inside the delayedDNSResponse channel. We construct a child context based on [ctx] and the given [timeout] and we stop reading when original [ctx] has been cancelled or the given [timeout] expires, whatever happens first. Once the timeout expired, we drain the chan as much as possible before returning.

func (*Trace) FirstDNSLookup

func (tx *Trace) FirstDNSLookup() *model.ArchivalDNSLookupResult

FirstDNSLookupOrNil drains the network events buffered inside the DNSLookup channel and returns the first DNSLookup, if any. Otherwise, it returns nil.

func (*Trace) FirstNetworkEventOrNil

func (tx *Trace) FirstNetworkEventOrNil() *model.ArchivalNetworkEvent

FirstNetworkEventOrNil drains the network events buffered inside the NetworkEvents channel and returns the first NetworkEvent, if any. Otherwise, it returns nil.

func (*Trace) FirstQUICHandshakeOrNil

func (tx *Trace) FirstQUICHandshakeOrNil() *model.ArchivalTLSOrQUICHandshakeResult

FirstQUICHandshakeOrNil drains the network events buffered inside the QUICHandshake channel and returns the first QUICHandshake, if any. Otherwise, it returns nil.

func (*Trace) FirstTCPConnectOrNil

func (tx *Trace) FirstTCPConnectOrNil() *model.ArchivalTCPConnectResult

FirstTCPConnectOrNil drains the network events buffered inside the TCPConnect channel and returns the first TCPConnect, if any. Otherwise, it returns nil.

func (*Trace) FirstTLSHandshakeOrNil

func (tx *Trace) FirstTLSHandshakeOrNil() *model.ArchivalTLSOrQUICHandshakeResult

FirstTLSHandshakeOrNil drains the network events buffered inside the TLSHandshake channel and returns the first TLSHandshake, if any. Otherwise, it returns nil.

func (*Trace) MaybeWrapNetConn

func (tx *Trace) MaybeWrapNetConn(conn net.Conn) net.Conn

MaybeWrapNetConn implements model.Trace.MaybeWrapNetConn.

func (*Trace) MaybeWrapUDPLikeConn

func (tx *Trace) MaybeWrapUDPLikeConn(conn model.UDPLikeConn) model.UDPLikeConn

MaybeWrapUDPLikeConn implements model.Trace.MaybeWrapUDPLikeConn.

func (*Trace) NetworkEvents

func (tx *Trace) NetworkEvents() (out []*model.ArchivalNetworkEvent)

NetworkEvents drains the network events buffered inside the NetworkEvent channel.

func (*Trace) NewDialerWithoutResolver

func (tx *Trace) NewDialerWithoutResolver(dl model.DebugLogger) model.Dialer

NewDialerWithoutResolver is equivalent to netxlite.NewDialerWithoutResolver except that it returns a model.Dialer that uses this trace.

Note: unlike code in netx or measurex, this factory DOES NOT return you a dialer that also performs wrapping of a net.Conn in case of success. If you want to wrap the conn, you need to wrap it explicitly using WrapNetConn.

func (*Trace) NewParallelDNSOverHTTPSResolver

func (tx *Trace) NewParallelDNSOverHTTPSResolver(logger model.Logger, URL string) model.Resolver

NewParallelDNSOverHTTPSResolver returns a trace-aware parallel DoH resolver

func (*Trace) NewParallelUDPResolver

func (tx *Trace) NewParallelUDPResolver(logger model.Logger, dialer model.Dialer, address string) model.Resolver

NewParallelUDPResolver returns a trace-ware parallel UDP resolver

func (*Trace) NewQUICDialerWithoutResolver

func (tx *Trace) NewQUICDialerWithoutResolver(listener model.QUICListener, dl model.DebugLogger) model.QUICDialer

NewQUICDialerWithoutResolver is equivalent to netxlite.NewQUICDialerWithoutResolver except that it returns a model.QUICDialer that uses this trace.

func (*Trace) NewStdlibResolver

func (tx *Trace) NewStdlibResolver(logger model.Logger) model.Resolver

NewStdlibResolver returns a trace-ware system resolver

func (*Trace) NewTLSHandshakerStdlib

func (tx *Trace) NewTLSHandshakerStdlib(dl model.DebugLogger) model.TLSHandshaker

NewTLSHandshakerStdlib is equivalent to netxlite.NewTLSHandshakerStdlib except that it returns a model.TLSHandshaker that uses this trace.

func (*Trace) NewTLSHandshakerUTLS

func (tx *Trace) NewTLSHandshakerUTLS(dl model.DebugLogger, id *utls.ClientHelloID) model.TLSHandshaker

NewTLSHandshakerUTLS is equivalent to netxlite.NewTLSHandshakerUTLS except that it returns a model.TLSHandshaker that uses this trace.

func (*Trace) OnConnectDone

func (tx *Trace) OnConnectDone(
	started time.Time, network, domain, remoteAddr string, err error, finished time.Time)

OnTCPConnectDone implements model.Trace.OnTCPConnectDone.

func (*Trace) OnDNSRoundTripForLookupHost

func (tx *Trace) OnDNSRoundTripForLookupHost(started time.Time, reso model.Resolver, query model.DNSQuery,
	response model.DNSResponse, addrs []string, err error, finished time.Time)

OnDNSRoundTripForLookupHost implements model.Trace.OnDNSRoundTripForLookupHost

func (*Trace) OnDelayedDNSResponse

func (tx *Trace) OnDelayedDNSResponse(started time.Time, txp model.DNSTransport, query model.DNSQuery,
	response model.DNSResponse, addrs []string, err error, finished time.Time) error

OnDelayedDNSResponse implements model.Trace.OnDelayedDNSResponse

func (*Trace) OnQUICHandshakeDone

func (tx *Trace) OnQUICHandshakeDone(started time.Time, remoteAddr string, qconn quic.EarlyConnection,
	config *tls.Config, err error, finished time.Time)

OnQUICHandshakeDone implements model.Trace.OnQUICHandshakeDone

func (*Trace) OnQUICHandshakeStart

func (tx *Trace) OnQUICHandshakeStart(now time.Time, remoteAddr string, config *quic.Config)

OnQUICHandshakeStart implements model.Trace.OnQUICHandshakeStart

func (*Trace) OnTLSHandshakeDone

func (tx *Trace) OnTLSHandshakeDone(started time.Time, remoteAddr string, config *tls.Config,
	state tls.ConnectionState, err error, finished time.Time)

OnTLSHandshakeDone implements model.Trace.OnTLSHandshakeDone.

func (*Trace) OnTLSHandshakeStart

func (tx *Trace) OnTLSHandshakeStart(now time.Time, remoteAddr string, config *tls.Config)

OnTLSHandshakeStart implements model.Trace.OnTLSHandshakeStart.

func (*Trace) QUICHandshakes

func (tx *Trace) QUICHandshakes() (out []*model.ArchivalTLSOrQUICHandshakeResult)

QUICHandshakes drains the network events buffered inside the QUICHandshake channel.

func (*Trace) TCPConnects

func (tx *Trace) TCPConnects() (out []*model.ArchivalTCPConnectResult)

TCPConnects drains the network events buffered inside the TCPConnect channel.

func (*Trace) TLSHandshakes

func (tx *Trace) TLSHandshakes() (out []*model.ArchivalTLSOrQUICHandshakeResult)

TLSHandshakes drains the network events buffered inside the TLSHandshake channel.

func (*Trace) TimeNow

func (tx *Trace) TimeNow() time.Time

TimeNow implements model.Trace.TimeNow.

func (*Trace) TimeSince

func (tx *Trace) TimeSince(t0 time.Time) time.Duration

TimeSince is equivalent to Trace.TimeNow().Sub(t0).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL