Documentation ¶
Overview ¶
Package dslvm contains low-level code for implementing the measurements DSL.
Index ¶
- func Start(ctx context.Context, rtx Runtime, stages ...Stage)
- func Wait(channels ...<-chan Done)
- type Closer
- type DNSLookupUDPStage
- type DedupAddrsStage
- type Done
- type DropStage
- type GetaddrinfoStage
- type HTTPConnection
- type HTTPRoundTripStage
- type MakeEndpointsStage
- type Observations
- type QUICConnection
- func (c *QUICConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
- func (c *QUICConnection) Close(logger model.Logger) error
- func (c *QUICConnection) Network() string
- func (c *QUICConnection) RemoteAddress() (addr string)
- func (c *QUICConnection) Scheme() string
- func (c *QUICConnection) TLSNegotiatedProtocol() string
- func (c *QUICConnection) Trace() Trace
- type QUICHandshakeStage
- type Runtime
- type Semaphore
- type Stage
- type TCPConnectStage
- type TCPConnection
- func (c *TCPConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
- func (c *TCPConnection) Close(logger model.Logger) error
- func (c *TCPConnection) Network() string
- func (c *TCPConnection) RemoteAddress() (addr string)
- func (c *TCPConnection) Scheme() string
- func (c *TCPConnection) TLSNegotiatedProtocol() string
- func (c *TCPConnection) Trace() Trace
- type TLSConnection
- func (c *TLSConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
- func (c *TLSConnection) Close(logger model.Logger) error
- func (c *TLSConnection) Network() string
- func (c *TLSConnection) RemoteAddress() (addr string)
- func (c *TLSConnection) Scheme() string
- func (c *TLSConnection) TLSNegotiatedProtocol() string
- func (c *TLSConnection) Trace() Trace
- type TLSHandshakeStage
- type TakeNStage
- type TeeAddrsStage
- type Trace
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type DNSLookupUDPStage ¶
type DNSLookupUDPStage struct { // Domain is the MANDATORY domain to resolve using this DNS resolver. Domain string // Output is the MANDATORY channel emitting IP addresses. We will close this // channel when we have finished streaming the resolved addresses. Output chan<- string // Resolver is the MANDATORY resolver endpoint (e.g., [::1]:53). Resolver string // Tags contains OPTIONAL tags for the DNS observations. Tags []string }
DNSLookupUDPStage is a Stage that resolves domain names using an UDP resolver.
func (*DNSLookupUDPStage) Run ¶
func (sx *DNSLookupUDPStage) Run(ctx context.Context, rtx Runtime)
Run resolves a Domain using the given Do53 Endpoint and streams the results on Output, which is closed when we're done.
This function honours the semaphore returned by the Runtime ActiveDNSLookups method and waits until it's given the permission to start a lookup.
type DedupAddrsStage ¶
type DedupAddrsStage struct { // Inputs contains the MANDATORY channels from which to read IP addresses. We // assume that these channels will be closed when done. Inputs []<-chan string // Output is the MANDATORY channel where we emit the deduplicated IP addresss. We // close this channel when all the Inputs have been closed. Output chan<- string }
DedupAddrsStage is a Stage that deduplicates IP addresses.
type DropStage ¶
type DropStage[T any] struct { // Input contains the MANDATORY channel from which to read instances to drop. We // assume that this channel will be closed when done. Input <-chan T // Output contains the MANDATORY channel closed when Input has been closed. Output chan Done }
DropStage is a Stage that drops reference to whatever it is passed in input. If the input is a Closer, this stage will also make sure it is closed.
type GetaddrinfoStage ¶
type GetaddrinfoStage struct { // Domain is the MANDATORY domain to resolve using this DNS resolver. Domain string // Output is the MANDATORY channel emitting IP addresses. We will close this // channel when we have finished streaming the resolved addresses. Output chan<- string // Tags contains OPTIONAL tags for the DNS observations. Tags []string }
GetaddrinfoStage is a Stage that resolves domain names using getaddrinfo.
type HTTPConnection ¶
type HTTPConnection interface { // AsSingleUseTransport converts the connection to a single-use HTTP transport AsSingleUseTransport(logger model.Logger) model.HTTPTransport // Closer embeds the Closer interface Closer // Network returns the network Network() string // RemoteAddress returns the remote address RemoteAddress() string // Scheme returns the HTTP scheme for this connection Scheme() string // TLSNegotiatedProtocol is the protocol negotiated by TLS TLSNegotiatedProtocol() string // Trace returns the Trace to use Trace() Trace }
HTTPConnection is the connection type expected by *HTTPRoundTripStage.
type HTTPRoundTripStage ¶
type HTTPRoundTripStage[T HTTPConnection] struct { // Accept contains the OPTIONAL accept header. Accept string // AcceptLanguage contains the OPTIONAL accept-language header. AcceptLanguage string // Host contains the MANDATORY host header. Host string // Input contains the MANDATORY channel from which to connections. We // assume that this channel will be closed when done. Input <-chan T // MaxBodySnapshotSize is the OPTIONAL maximum body snapshot size. MaxBodySnapshotSize int64 // Method contains the MANDATORY method. Method string // Output is the MANDATORY channel emitting [Void]. We will close this // channel when the Input channel has been closed. Output chan<- Done // Referer contains the OPTIONAL referer header. Referer string // URLPath contains the MANDATORY URL path. URLPath string // UserAgent contains the OPTIONAL user-agent header. UserAgent string }
HTTPRoundTripStage performs HTTP round trips with connections of type T.
func (*HTTPRoundTripStage[T]) Run ¶
func (sx *HTTPRoundTripStage[T]) Run(ctx context.Context, rtx Runtime)
Run is like [*TCPConnect.Run] except that it reads connections in Input and emits [Void] in Output. Each HTTP round trip runs in its own background goroutine. The parallelism is controlled by the Runtime ActiveConnections Semaphore. Note that this code TAKES OWNERSHIP of the connection it reads and closes it at the end of the round trip. While closing the conn, we signal Runtime ActiveConnections to unblock another measurement.
type MakeEndpointsStage ¶
type MakeEndpointsStage struct { // Input contains the MANDATORY channel from which to read IP addresses. We // assume that this channel will be closed when done. Input <-chan string // Output is the MANDATORY channel emitting endpoints. We will close this // channel when the Input channel has been closed. Output chan<- string // Port is the MANDATORY port. Port string }
MakeEndpointsStage is a Stage that transforms IP addresses to TCP/UDP endpoints.
type Observations ¶
type Observations struct { // NetworkEvents contains I/O events. NetworkEvents []*model.ArchivalNetworkEvent `json:"network_events"` // Queries contains the DNS queries results. Queries []*model.ArchivalDNSLookupResult `json:"queries"` // Requests contains HTTP request results. Requests []*model.ArchivalHTTPRequestResult `json:"requests"` // TCPConnect contains the TCP connect results. TCPConnect []*model.ArchivalTCPConnectResult `json:"tcp_connect"` // TLSHandshakes contains the TLS handshakes results. TLSHandshakes []*model.ArchivalTLSOrQUICHandshakeResult `json:"tls_handshakes"` // QUICHandshakes contains the QUIC handshakes results. QUICHandshakes []*model.ArchivalTLSOrQUICHandshakeResult `json:"quic_handshakes"` }
Observations is the skeleton shared by most OONI measurements where we group observations by type using standard test keys.
func NewObservations ¶
func NewObservations() *Observations
NewObservations initializes all measurements to empty arrays and returns the Observations skeleton.
type QUICConnection ¶
type QUICConnection struct { Conn quic.EarlyConnection // contains filtered or unexported fields }
QUICConnection is a QUIC connection.
func (*QUICConnection) AsSingleUseTransport ¶
func (c *QUICConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
AsSingleUseTransport implements HTTPConnection.
func (*QUICConnection) Close ¶
func (c *QUICConnection) Close(logger model.Logger) error
Close implements HTTPConnection.
func (*QUICConnection) Network ¶
func (c *QUICConnection) Network() string
Network implements HTTPConnection.
func (*QUICConnection) RemoteAddress ¶
func (c *QUICConnection) RemoteAddress() (addr string)
RemoteAddress implements HTTPConnection.
func (*QUICConnection) Scheme ¶
func (c *QUICConnection) Scheme() string
Scheme implements HTTPConnection.
func (*QUICConnection) TLSNegotiatedProtocol ¶
func (c *QUICConnection) TLSNegotiatedProtocol() string
TLSNegotiatedProtocol implements HTTPConnection.
func (*QUICConnection) Trace ¶
func (c *QUICConnection) Trace() Trace
Trace implements HTTPConnection.
type QUICHandshakeStage ¶
type QUICHandshakeStage struct { // Input contains the MANDATORY channel from which to read endpoints. We // assume that this channel will be closed when done. Input <-chan string // InsecureSkipVerify OPTIONALLY skips QUIC verification. InsecureSkipVerify bool // NextProtos OPTIONALLY configures the ALPN. NextProtos []string // Output is the MANDATORY channel emitting [*QUICConnection]. We will close this // channel when the Input channel has been closed. Output chan<- *QUICConnection // RootCAs OPTIONALLY configures alternative root CAs. RootCAs *x509.CertPool // ServerName is the MANDATORY server name. ServerName string // Tags contains OPTIONAL tags to add to the endpoint observations. Tags []string }
QUICHandshakeStage is a Stage that creates *QUICConnection.
func (*QUICHandshakeStage) Run ¶
func (sx *QUICHandshakeStage) Run(ctx context.Context, rtx Runtime)
Run is like [*TCPConnect.Run] except that it reads [endpoints] in Input and emits *QUICConnection in Output. Each QUIC handshake runs in its own background goroutine. The parallelism is controlled by the Runtime ActiveConnections Semaphore and you MUST arrange for the *QUICConnection to eventually enter into a [*CloseStage] such that the code can release the above mentioned Semaphore and close the conn. Note that this code TAKES OWNERSHIP of the *TCPConnection it reads. We will close these conns automatically on failure. On success, they will be closed when the *QUICConnection wrapping them eventually enters into a [*CloseStage].
type Runtime ¶
type Runtime interface { // ActiveConnections returns the [Semaphore] controlling the // maximum number of active connections that we can have. ActiveConnections() *Semaphore // ActiveDNSLookups returns the [Semaphore] controlling the // maximum number of active DNS lookups that we can have. ActiveDNSLookups() *Semaphore // IDGenerator returns an atomic counter used to generate // separate unique IDs for each trace. IDGenerator() *atomic.Int64 // Logger returns the base logger to use. Logger() model.Logger // NewTrace creates a [Trace] instance. Note that each [Runtime] // creates its own [Trace] type. A [Trace] is not guaranteed to collect // [*Observations]. For example, [NewMinimalRuntime] creates a [Runtime] // that does not collect any [*Observations]. NewTrace(index int64, zeroTime time.Time, tags ...string) Trace // Observations returns the [*Observations] saved so far and clears our // internal copy such that the next call to this method only returns // the [*Observations] saved since the previous call. // // You can safely call this method from multiple goroutine contexts. Observations() *Observations // SaveObservations saves [*Observations] inside the [Runtime]. You can // get the saved [*Observations] by calling Observations. // // You can safely call this method from multiple goroutine contexts. SaveObservations(obs ...*Observations) // ZeroTime returns the runtime's "zero" time, which is used as the // starting point to generate observation's delta times. ZeroTime() time.Time }
Runtime is the runtime in which we execute the DSL.
type Semaphore ¶
type Semaphore struct {
// contains filtered or unexported fields
}
Semaphore implements a semaphore.
See https://en.wikipedia.org/wiki/Semaphore_(programming).
func NewSemaphore ¶
NewSemaphore creates a new *Semaphore with the given count of available resources. This function PANICS if the given count of available resources is zero or negative.
type TCPConnectStage ¶
type TCPConnectStage struct { // Input contains the MANDATORY channel from which to read endpoints. We // assume that this channel will be closed when done. Input <-chan string // Output is the MANDATORY channel emitting [*TCPConnection]. We will close this // channel when the Input channel has been closed. Output chan<- *TCPConnection // Tags contains OPTIONAL tags to add to the endpoint observations. Tags []string }
TCPConnectStage is a Stage that creates *TCPConnection.
func (*TCPConnectStage) Run ¶
func (sx *TCPConnectStage) Run(ctx context.Context, rtx Runtime)
Run reads endpoints from Input and streams on the Output channel the *TCPConnection that it could successfully establish. Note that this function honors the Semaphore returned by the Runtime ActiveConnections that controls how many connections we can measure in parallel. When given the permission to run, this function spawns a background goroutine that attempts to establish a connection. The *TCPConnection returned by this stage MUST eventually feed into a [*CloseStage], so that the code can notify the above mentioned Semaphore and so that we close the open connection. This function will close the Output channel when Inputs have been closed and there are no pending connection attempts. In case of failure, the code will automatically notify the Semaphore.
type TCPConnection ¶
TCPConnection is a TCP connection.
func (*TCPConnection) AsSingleUseTransport ¶
func (c *TCPConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
AsSingleUseTransport implements HTTPConnection.
func (*TCPConnection) Close ¶
func (c *TCPConnection) Close(logger model.Logger) error
Close implements HTTPConnection.
func (*TCPConnection) Network ¶
func (c *TCPConnection) Network() string
Network implements HTTPConnection.
func (*TCPConnection) RemoteAddress ¶
func (c *TCPConnection) RemoteAddress() (addr string)
RemoteAddress implements HTTPConnection.
func (*TCPConnection) Scheme ¶
func (c *TCPConnection) Scheme() string
Scheme implements HTTPConnection.
func (*TCPConnection) TLSNegotiatedProtocol ¶
func (c *TCPConnection) TLSNegotiatedProtocol() string
TLSNegotiatedProtocol implements HTTPConnection.
func (*TCPConnection) Trace ¶
func (c *TCPConnection) Trace() Trace
Trace implements HTTPConnection.
type TLSConnection ¶
TLSConnection is a TLS connection.
func (*TLSConnection) AsSingleUseTransport ¶
func (c *TLSConnection) AsSingleUseTransport(logger model.Logger) model.HTTPTransport
AsSingleUseTransport implements HTTPConnection.
func (*TLSConnection) Close ¶
func (c *TLSConnection) Close(logger model.Logger) error
Close implements HTTPConnection.
func (*TLSConnection) Network ¶
func (c *TLSConnection) Network() string
Network implements HTTPConnection.
func (*TLSConnection) RemoteAddress ¶
func (c *TLSConnection) RemoteAddress() (addr string)
RemoteAddress implements HTTPConnection.
func (*TLSConnection) Scheme ¶
func (c *TLSConnection) Scheme() string
Scheme implements HTTPConnection.
func (*TLSConnection) TLSNegotiatedProtocol ¶
func (c *TLSConnection) TLSNegotiatedProtocol() string
TLSNegotiatedProtocol implements HTTPConnection.
func (*TLSConnection) Trace ¶
func (c *TLSConnection) Trace() Trace
Trace implements HTTPConnection.
type TLSHandshakeStage ¶
type TLSHandshakeStage struct { // Input contains the MANDATORY channel from which to read [*TCPConnection]. We // assume that this channel will be closed when done. Input <-chan *TCPConnection // InsecureSkipVerify OPTIONALLY skips TLS verification. InsecureSkipVerify bool // NextProtos OPTIONALLY configures the ALPN. NextProtos []string // Output is the MANDATORY channel emitting [*TLSConnection]. We will close this // channel when the Input channel has been closed. Output chan<- *TLSConnection // RootCAs OPTIONALLY configures alternative root CAs. RootCAs *x509.CertPool // ServerName is the MANDATORY server name. ServerName string }
TLSHandshakeStage is a Stage that creates *TLSConnection.
func (*TLSHandshakeStage) Run ¶
func (sx *TLSHandshakeStage) Run(ctx context.Context, rtx Runtime)
Run is like [*TCPConnect.Run] except that it reads *TCPConnection in Input and emits *TLSConnection in Output. Each TLS handshake runs in its own background goroutine. The parallelism is controlled by the Runtime ActiveConnections Semaphore and you MUST arrange for the *TLSConnection to eventually enter into a [*CloseStage] such that the code can release the above mentioned Semaphore and close the conn. Note that this code TAKES OWNERSHIP of the *TCPConnection it reads. We will close these conns automatically on failure. On success, they will be closed when the *TLSConnection wrapping them eventually enters into a [*CloseStage].
type TakeNStage ¶
type TakeNStage[T any] struct { // Input contains the MANDATORY channel from which to read T. We // assume that this channel will be closed when done. Input <-chan T // N is the maximum number of entries to allow to pass. Any value // lower than zero is equivalent to setting this field to zero. N int64 // Output is the MANDATORY channel emitting [T]. We will close this // channel when the Input channel has been closed. Output chan<- T }
TakeNStage is a Stage that allows N elements with type T to pass and drops subsequent elements.
type TeeAddrsStage ¶
type TeeAddrsStage struct { // Input is the MANDATORY channel from which we read addresses. We assume // this channel is closed when done. Input <-chan string // Outputs is the MANDATORY list of channels where to duplicate the addresses read // from the Input channel. We close all Outputs when done. Outputs []chan<- string }
TeeAddrsStage is a Stage that duplicates the addresses read in Input into each of the channels belonging to [Outputs].
type Trace ¶
type Trace interface { // CloneBytesReceivedMap returns a clone of the internal bytes received map. The key of the // map is a string following the "EPNT_ADDRESS PROTO" pattern where the "EPNT_ADDRESS" contains // the endpoint address and "PROTO" is "tcp" or "udp". CloneBytesReceivedMap() (out map[string]int64) // DNSLookupsFromRoundTrip returns all the DNS lookup results collected so far. DNSLookupsFromRoundTrip() (out []*model.ArchivalDNSLookupResult) // Index returns the unique index used by this trace. Index() int64 // NewDialerWithoutResolver is equivalent to netxlite.Netx.NewDialerWithoutResolver // except that it returns a model.Dialer that uses this trace. // // Caveat: the dialer wrappers are there to implement the // model.MeasuringNetwork interface, but they're not used by this function. NewDialerWithoutResolver(dl model.DebugLogger, wrappers ...model.DialerWrapper) model.Dialer // NewParallelUDPResolver returns a possibly-trace-ware parallel UDP resolver NewParallelUDPResolver(logger model.DebugLogger, dialer model.Dialer, address string) model.Resolver // NewQUICDialerWithoutResolver is equivalent to // netxlite.Netx.NewQUICDialerWithoutResolver except that it returns a // model.QUICDialer that uses this trace. // // Caveat: the dialer wrappers are there to implement the // model.MeasuringNetwork interface, but they're not used by this function. NewQUICDialerWithoutResolver(listener model.UDPListener, dl model.DebugLogger, wrappers ...model.QUICDialerWrapper) model.QUICDialer // NewTLSHandshakerStdlib is equivalent to netxlite.Netx.NewTLSHandshakerStdlib // except that it returns a model.TLSHandshaker that uses this trace. NewTLSHandshakerStdlib(dl model.DebugLogger) model.TLSHandshaker // NetworkEvents returns all the network events collected so far. NetworkEvents() (out []*model.ArchivalNetworkEvent) // NewStdlibResolver returns a possibly-trace-ware system resolver. NewStdlibResolver(logger model.DebugLogger) model.Resolver // NewUDPListener implements model.MeasuringNetwork. NewUDPListener() model.UDPListener // QUICHandshakes collects all the QUIC handshake results collected so far. QUICHandshakes() (out []*model.ArchivalTLSOrQUICHandshakeResult) // TCPConnects collects all the TCP connect results collected so far. TCPConnects() (out []*model.ArchivalTCPConnectResult) // TLSHandshakes collects all the TLS handshake results collected so far. TLSHandshakes() (out []*model.ArchivalTLSOrQUICHandshakeResult) // Tags returns the trace tags. Tags() []string // TimeSince is equivalent to Trace.TimeNow().Sub(t0). TimeSince(t0 time.Time) time.Duration // ZeroTime returns the "zero" time of this trace. ZeroTime() time.Time }
Trace collects *Observations using tracing. Specific implementations of this interface may be engineered to collect no *Observations for efficiency (i.e., when you don't care about collecting *Observations but you still want to use this package).