model

package
v0.27.0 Latest Latest
Warning

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

Go to latest
Published: Dec 13, 2023 License: GPL-3.0 Imports: 19 Imported by: 13

README

Package github.com/ooni/probe-cli/v3/internal/model

Shared data structures and interfaces. We include in this package the most fundamental types. Use go doc to get more thorough documentation about what is inside this package and when to put a type inside this package.

Documentation

Overview

Package model contains the shared interfaces and data structures.

Criteria for adding a type to this package

This package should contain two types:

1. important interfaces that are shared by several packages within the codebase, with the objective of separating unrelated pieces of code and making unit testing easier;

2. important pieces of data that are shared across different packages (e.g., the representation of a Measurement).

In general, this package should not contain logic, unless this logic is strictly related to data structures and we cannot implement this logic elsewhere.

Content of this package

The following list (which may not always be up-to-date) summarizes the categories of types that currently belong here and names the files in which they are implemented:

- experiment.go: generic definition of a network experiment and all the required support types;

- keyvaluestore.go: generic definition of a key-value store, used in several places across the codebase;

- logger.go: generic definition of an apex/log compatible logger, used in several places across the codebase;

- measurement.go: data type representing the result of a network measurement, used in many many places;

- netx.go: network extension interfaces and data used everywhere we need to perform network operations;

- ooapi.go: types to communicate with the OONI API.

Index

Constants

View Source
const (
	// InputOrQueryBackend indicates that the experiment requires
	// external input to run and that this kind of input is URLs
	// from the citizenlab/test-lists repository. If this input
	// not provided to the experiment, then the code that runs the
	// experiment is supposed to fetch from URLs from OONI's backends.
	InputOrQueryBackend = InputPolicy("or_query_backend")

	// InputStrictlyRequired indicates that the experiment
	// requires input and we currently don't have an API for
	// fetching such input. Therefore, either the user specifies
	// input or the experiment will fail for the lack of input.
	InputStrictlyRequired = InputPolicy("strictly_required")

	// InputOptional indicates that the experiment handles input,
	// if any; otherwise it fetchs input/uses a default.
	InputOptional = InputPolicy("optional")

	// InputNone indicates that the experiment does not want any
	// input and ignores the input if provided with it.
	InputNone = InputPolicy("none")

	// We gather input from StaticInput and SourceFiles. If there is
	// input, we return it. Otherwise, we return an internal static
	// list of inputs to be used with this experiment.
	InputOrStaticDefault = InputPolicy("or_static_default")
)
View Source
const (
	// HTTPHeaderAccept is the Accept header used for measuring.
	HTTPHeaderAccept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"

	// HTTPHeaderAcceptLanguage is the Accept-Language header used for measuring.
	HTTPHeaderAcceptLanguage = "en-US,en;q=0.9"

	// HTTPHeaderUserAgent is the User-Agent header used for measuring. The current header
	// is 17.34% of the browser population as of 2023-12-13 according to the
	// https://www.useragents.me/ webpage.
	HTTPHeaderUserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.3"
)

Headers we use for measuring.

View Source
const (
	// DefaultProbeASN is the default probe ASN as a number.
	DefaultProbeASN uint = 0

	// DefaultProbeCC is the default probe CC.
	DefaultProbeCC = "ZZ"

	// DefaultProbeIP is the default probe IP.
	DefaultProbeIP = "127.0.0.1"

	// DefaultProbeNetworkName is the default probe network name.
	DefaultProbeNetworkName = ""

	// DefaultResolverASN is the default resolver ASN.
	DefaultResolverASN uint = 0

	// DefaultResolverIP is the default resolver IP.
	DefaultResolverIP = "127.0.0.2"

	// DefaultResolverNetworkName is the default resolver network name.
	DefaultResolverNetworkName = ""
)
View Source
const (
	// OOAPIReportDefaultDataFormatVersion is the default data format version.
	//
	// See https://github.com/ooni/spec/tree/master/data-formats#history.
	OOAPIReportDefaultDataFormatVersion = "0.2.0"

	// DefaultFormat is the default format
	OOAPIReportDefaultFormat = "json"
)
View Source
const (
	// RunTypeManual indicates that the user manually run `ooniprobe run`. Command
	// line tools such as miniooni should always use this run type.
	RunTypeManual = RunType("manual")

	// RunTypeTimed indicates that the user run `ooniprobe run unattended`, which
	// is the correct way to run ooniprobe from scripts and cronjobs.
	RunTypeTimed = RunType("timed")
)
View Source
const (
	// THIPInfoFlagResolvedByProbe indicates that the probe has
	// resolved this IP address.
	THIPInfoFlagResolvedByProbe = 1 << iota

	// THIPInfoFlagResolvedByTH indicates that the test helper
	// has resolved this IP address.
	THIPInfoFlagResolvedByTH

	// THIPInfoFlagIsBogon indicates that the address is a bogon
	THIPInfoFlagIsBogon

	// THIPInfoFlagValidForDomain indicates that an IP address
	// is valid for the domain because it works with TLS
	THIPInfoFlagValidForDomain
)
View Source
const MeasurementDateFormat = "2006-01-02 15:04:05"

MeasurementDateFormat is the data format used by a measurement.

View Source
const Scrubbed = `[scrubbed]`

Scrubbed is the string that replaces IP addresses.

View Source
const THDNSNameError = "dns_name_error"

THDNSNameError is the error returned by the control on NXDOMAIN

Variables

View Source
var (
	// ArchivalExtDNS is the version of df-002-dnst.md
	ArchivalExtDNS = ArchivalExtSpec{Name: "dnst", V: 0}

	// ArchivalExtNetevents is the version of df-008-netevents.md
	ArchivalExtNetevents = ArchivalExtSpec{Name: "netevents", V: 0}

	// ArchivalExtHTTP is the version of df-001-httpt.md
	ArchivalExtHTTP = ArchivalExtSpec{Name: "httpt", V: 0}

	// ArchivalExtTCPConnect is the version of df-005-tcpconnect.md
	ArchivalExtTCPConnect = ArchivalExtSpec{Name: "tcpconnect", V: 0}

	// ArchivalExtTLSHandshake is the version of df-006-tlshandshake.md
	ArchivalExtTLSHandshake = ArchivalExtSpec{Name: "tlshandshake", V: 0}

	// ArchivalExtTunnel is the version of df-009-tunnel.md
	ArchivalExtTunnel = ArchivalExtSpec{Name: "tunnel", V: 0}
)
View Source
var (
	// HTTPUnexpectedStatusCode indicates that we re not getting
	// the expected (range of) HTTP status code(s).
	HTTPUnexpectedStatusCode = "http_unexpected_status_code"

	// HTTPUnexpectedRedirectURL indicates that the redirect URL
	// returned by the server is not the expected one.
	HTTPUnexpectedRedirectURL = "http_unexpected_redirect_url"
)

Additional strings used to report HTTP errors. They're currently only used by experiment/whatsapp but may be used by more experiments in the future. They must be addressable (i.e., var and not const) because experiments typically want to take their addresses to fill fields with `string|null` type.

View Source
var (
	// DefaultProbeASNString is the default probe ASN as a string.
	DefaultProbeASNString = fmt.Sprintf("AS%d", DefaultProbeASN)

	// DefaultResolverASNString is the default resolver ASN as a string.
	DefaultResolverASNString = fmt.Sprintf("AS%d", DefaultResolverASN)
)
View Source
var ErrInvalidBinaryDataFormat = errors.New("model: invalid binary data format")

ErrInvalidBinaryDataFormat is the format returned when marshaling and unmarshaling binary data and the value of "format" is unknown.

View Source
var ErrInvalidProbeIP = errors.New("model: invalid probe IP")

ErrInvalidProbeIP indicates that we're dealing with a string that is not the valid serialization of an IP address.

Functions

func ArchivalNewHTTPHeadersMap added in v0.26.0

func ArchivalNewHTTPHeadersMap(header http.Header) (out map[string]ArchivalScrubbedMaybeBinaryString)

ArchivalNewHTTPHeadersMap creates a map representation of HTTP headers

func ErrorToStringOrOK

func ErrorToStringOrOK(err error) string

ErrorToStringOrOK emits "ok" on "<nil>"" values for success.

func MeasurementFormatTimeNowUTC added in v0.26.0

func MeasurementFormatTimeNowUTC() string

MeasurementFormatTimeNowUTC formats the current time as UTC using the MeasurementDateFormat.

func ScrubMeasurement

func ScrubMeasurement(m *Measurement, currentIP string) error

ScrubMeasurement removes [currentIP] from [m] by rewriting it in place while preserving the underlying types

Types

type ArchivalBinaryData added in v0.26.0

type ArchivalBinaryData []byte

ArchivalBinaryData is a wrapper for bytes that serializes the enclosed data using the specific ooni/spec data format for binary data.

See https://github.com/ooni/spec/blob/master/data-formats/df-001-httpt.md#maybebinarydata.

func (ArchivalBinaryData) MarshalJSON added in v0.26.0

func (value ArchivalBinaryData) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*ArchivalBinaryData) UnmarshalJSON added in v0.26.0

func (value *ArchivalBinaryData) UnmarshalJSON(raw []byte) error

UnmarshalJSON implements json.Unmarshaler.

type ArchivalDNSAnswer

type ArchivalDNSAnswer struct {
	ASN        int64   `json:"asn,omitempty"`
	ASOrgName  string  `json:"as_org_name,omitempty"`
	AnswerType string  `json:"answer_type"`
	Hostname   string  `json:"hostname,omitempty"`
	IPv4       string  `json:"ipv4,omitempty"`
	IPv6       string  `json:"ipv6,omitempty"`
	TTL        *uint32 `json:"ttl"`
}

ArchivalDNSAnswer is a DNS answer.

type ArchivalDNSLookupResult

type ArchivalDNSLookupResult struct {
	Answers          []ArchivalDNSAnswer `json:"answers"`
	Engine           string              `json:"engine"`
	Failure          *string             `json:"failure"`
	GetaddrinfoError int64               `json:"getaddrinfo_error,omitempty"`
	Hostname         string              `json:"hostname"`
	QueryType        string              `json:"query_type"`
	RawResponse      []byte              `json:"raw_response,omitempty"`
	Rcode            int64               `json:"rcode,omitempty"`
	ResolverHostname *string             `json:"resolver_hostname"`
	ResolverPort     *string             `json:"resolver_port"`
	ResolverAddress  string              `json:"resolver_address"`
	T0               float64             `json:"t0,omitempty"`
	T                float64             `json:"t"`
	Tags             []string            `json:"tags"`
	TransactionID    int64               `json:"transaction_id,omitempty"`
}

ArchivalDNSLookupResult is the result of a DNS lookup.

See https://github.com/ooni/spec/blob/master/data-formats/df-002-dnst.md.

type ArchivalExtSpec

type ArchivalExtSpec struct {
	Name string // extension name
	V    int64  // extension version
}

ArchivalExtSpec describes a data format extension

func (ArchivalExtSpec) AddTo

func (spec ArchivalExtSpec) AddTo(m *Measurement)

AddTo adds the current ExtSpec to the specified measurement

type ArchivalHTTPHeader

type ArchivalHTTPHeader [2]ArchivalScrubbedMaybeBinaryString

ArchivalHTTPHeader is a single HTTP header.

func ArchivalNewHTTPHeadersList added in v0.26.0

func ArchivalNewHTTPHeadersList(source http.Header) (out []ArchivalHTTPHeader)

ArchivalNewHTTPHeadersList constructs a new ArchivalHTTPHeader list given HTTP headers.

func (*ArchivalHTTPHeader) UnmarshalJSON

func (ahh *ArchivalHTTPHeader) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler.

type ArchivalHTTPRequest

type ArchivalHTTPRequest struct {
	Body            ArchivalScrubbedMaybeBinaryString            `json:"body"`
	BodyIsTruncated bool                                         `json:"body_is_truncated"`
	HeadersList     []ArchivalHTTPHeader                         `json:"headers_list"`
	Headers         map[string]ArchivalScrubbedMaybeBinaryString `json:"headers"`
	Method          string                                       `json:"method"`
	Tor             ArchivalHTTPTor                              `json:"tor"`
	Transport       string                                       `json:"x_transport"`
	URL             string                                       `json:"url"`
}

ArchivalHTTPRequest contains an HTTP request.

Headers are a map in Web Connectivity data format but we have added support for a list since January 2020.

type ArchivalHTTPRequestResult

type ArchivalHTTPRequestResult struct {
	Network       string               `json:"network,omitempty"`
	Address       string               `json:"address,omitempty"`
	ALPN          string               `json:"alpn,omitempty"`
	Failure       *string              `json:"failure"`
	Request       ArchivalHTTPRequest  `json:"request"`
	Response      ArchivalHTTPResponse `json:"response"`
	T0            float64              `json:"t0,omitempty"`
	T             float64              `json:"t"`
	Tags          []string             `json:"tags"`
	TransactionID int64                `json:"transaction_id,omitempty"`
}

ArchivalHTTPRequestResult is the result of sending an HTTP request.

See https://github.com/ooni/spec/blob/master/data-formats/df-001-httpt.md.

type ArchivalHTTPResponse

type ArchivalHTTPResponse struct {
	Body            ArchivalScrubbedMaybeBinaryString            `json:"body"`
	BodyIsTruncated bool                                         `json:"body_is_truncated"`
	Code            int64                                        `json:"code"`
	HeadersList     []ArchivalHTTPHeader                         `json:"headers_list"`
	Headers         map[string]ArchivalScrubbedMaybeBinaryString `json:"headers"`

	// The following fields are not serialised but are useful to simplify
	// analysing the measurements in telegram, whatsapp, etc.
	Locations []string `json:"-"`
}

ArchivalHTTPResponse contains an HTTP response.

Headers are a map in Web Connectivity data format but we have added support for a list since January 2020.

type ArchivalHTTPTor

type ArchivalHTTPTor struct {
	ExitIP   *string `json:"exit_ip"`
	ExitName *string `json:"exit_name"`
	IsTor    bool    `json:"is_tor"`
}

ArchivalHTTPTor contains Tor information.

type ArchivalNetworkEvent

type ArchivalNetworkEvent struct {
	Address       string   `json:"address,omitempty"`
	Failure       *string  `json:"failure"`
	NumBytes      int64    `json:"num_bytes,omitempty"`
	Operation     string   `json:"operation"`
	Proto         string   `json:"proto,omitempty"`
	T0            float64  `json:"t0,omitempty"`
	T             float64  `json:"t"`
	TransactionID int64    `json:"transaction_id,omitempty"`
	Tags          []string `json:"tags,omitempty"`
}

ArchivalNetworkEvent is a network event. It contains all the possible fields and most fields are optional. They are only added when it makes sense for them to be there _and_ we have data to show.

See https://github.com/ooni/spec/blob/master/data-formats/df-008-netevents.md.

type ArchivalScrubbedMaybeBinaryString added in v0.26.0

type ArchivalScrubbedMaybeBinaryString string

ArchivalScrubbedMaybeBinaryString is a possibly-binary string. When the string is valid UTF-8 we serialize it as itself. Otherwise, we use the binary data format defined by https://github.com/ooni/spec/blob/master/data-formats/df-001-httpt.md#maybebinarydata

As the name implies, the data contained by this type is scrubbed to remove IPv4 and IPv6 addresses and endpoints during JSON serialization, to make it less likely that OONI leaks IP addresses in textual or binary fields such as HTTP headers and bodies.

func (ArchivalScrubbedMaybeBinaryString) MarshalJSON added in v0.26.0

func (value ArchivalScrubbedMaybeBinaryString) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler.

func (*ArchivalScrubbedMaybeBinaryString) UnmarshalJSON added in v0.26.0

func (value *ArchivalScrubbedMaybeBinaryString) UnmarshalJSON(rawData []byte) error

UnmarshalJSON implements json.Unmarshaler.

type ArchivalTCPConnectResult

type ArchivalTCPConnectResult struct {
	IP            string                   `json:"ip"`
	Port          int                      `json:"port"`
	Status        ArchivalTCPConnectStatus `json:"status"`
	T0            float64                  `json:"t0,omitempty"`
	T             float64                  `json:"t"`
	Tags          []string                 `json:"tags"`
	TransactionID int64                    `json:"transaction_id,omitempty"`
}

ArchivalTCPConnectResult contains the result of a TCP connect.

See https://github.com/ooni/spec/blob/master/data-formats/df-005-tcpconnect.md.

type ArchivalTCPConnectStatus

type ArchivalTCPConnectStatus struct {
	Blocked *bool   `json:"blocked,omitempty"`
	Failure *string `json:"failure"`
	Success bool    `json:"success"`
}

ArchivalTCPConnectStatus is the status of ArchivalTCPConnectResult.

type ArchivalTLSOrQUICHandshakeResult

type ArchivalTLSOrQUICHandshakeResult struct {
	Network            string               `json:"network"`
	Address            string               `json:"address"`
	CipherSuite        string               `json:"cipher_suite"`
	Failure            *string              `json:"failure"`
	SoError            *string              `json:"so_error,omitempty"`
	NegotiatedProtocol string               `json:"negotiated_protocol"`
	NoTLSVerify        bool                 `json:"no_tls_verify"`
	PeerCertificates   []ArchivalBinaryData `json:"peer_certificates"`
	ServerName         string               `json:"server_name"`
	T0                 float64              `json:"t0,omitempty"`
	T                  float64              `json:"t"`
	Tags               []string             `json:"tags"`
	TLSVersion         string               `json:"tls_version"`
	TransactionID      int64                `json:"transaction_id,omitempty"`
}

ArchivalTLSOrQUICHandshakeResult is the result of a TLS or QUIC handshake.

See https://github.com/ooni/spec/blob/master/data-formats/df-006-tlshandshake.md

type DNSDecoder

type DNSDecoder interface {
	// DecodeResponse decodes a DNS response message.
	//
	// Arguments:
	//
	// - data is the raw reply
	//
	// This function fails if we cannot parse data as a DNS
	// message or the message is not a response.
	//
	// Regarding the returned response, remember that the Rcode
	// MAY still be nonzero (this method does not treat a nonzero
	// Rcode as an error when parsing the response).
	DecodeResponse(data []byte, query DNSQuery) (DNSResponse, error)
}

The DNSDecoder decodes DNS responses.

type DNSEncoder

type DNSEncoder interface {
	// Encode transforms its arguments into a serialized DNS query.
	//
	// Every time you call Encode, you get a new DNSQuery value
	// using a query ID selected at random.
	//
	// Serialization to bytes is lazy to acommodate DNS transports that
	// do not need to serialize and send bytes, e.g., getaddrinfo.
	//
	// You serialize to bytes using DNSQuery.Bytes. This operation MAY fail
	// if the domain name cannot be packed into a DNS message (e.g., it is
	// too long to fit into the message).
	//
	// Arguments:
	//
	// - domain is the domain for the query (e.g., x.org);
	//
	// - qtype is the query type (e.g., dns.TypeA);
	//
	// - padding is whether to add padding to the query.
	//
	// This function will transform the domain into an FQDN is it's not
	// already expressed in the FQDN format.
	Encode(domain string, qtype uint16, padding bool) DNSQuery
}

The DNSEncoder encodes DNS queries to bytes

type DNSQuery

type DNSQuery interface {
	// Domain is the domain we're querying for.
	Domain() string

	// Type is the query type.
	Type() uint16

	// Bytes serializes the query to bytes. This function may fail if we're not
	// able to correctly encode the domain into a query message.
	//
	// The value returned by this function WILL be memoized after the first call,
	// so you SHOULD create a new DNSQuery if you need to retry a query.
	Bytes() ([]byte, error)

	// ID returns the query ID.
	ID() uint16
}

DNSQuery is an encoded DNS query ready to be sent using a DNSTransport.

type DNSResponse

type DNSResponse interface {
	// Query is the query associated with this response.
	Query() DNSQuery

	// Bytes returns the bytes from which we parsed the query.
	Bytes() []byte

	// Rcode returns the response's Rcode.
	Rcode() int

	// DecodeHTTPS returns information gathered from all the HTTPS
	// records found inside of this response.
	DecodeHTTPS() (*HTTPSSvc, error)

	// DecodeLookupHost returns the addresses in the response matching
	// the original query type (one of A and AAAA).
	DecodeLookupHost() ([]string, error)

	// DecodeNS returns all the NS entries in this response.
	DecodeNS() ([]*net.NS, error)

	// DecodeCNAME returns the first CNAME entry in this response.
	DecodeCNAME() (string, error)
}

DNSResponse is a parsed DNS response ready for further processing.

type DNSTransport

type DNSTransport interface {
	// RoundTrip sends a DNS query and receives the reply.
	RoundTrip(ctx context.Context, query DNSQuery) (DNSResponse, error)

	// RequiresPadding returns whether this transport needs padding.
	RequiresPadding() bool

	// Network is the network of the round tripper (e.g. "dot").
	Network() string

	// Address is the address of the round tripper (e.g. "1.1.1.1:853").
	Address() string

	// CloseIdleConnections closes idle connections, if any.
	CloseIdleConnections()
}

DNSTransport represents an abstract DNS transport.

type DatabaseMeasurement

type DatabaseMeasurement struct {
	ID               int64          `db:"measurement_id,omitempty"`
	TestName         string         `db:"test_name"`
	StartTime        time.Time      `db:"measurement_start_time"`
	Runtime          float64        `db:"measurement_runtime"` // Fractional number of seconds
	IsDone           bool           `db:"measurement_is_done"`
	IsUploaded       bool           `db:"measurement_is_uploaded"`
	IsFailed         bool           `db:"measurement_is_failed"`
	FailureMsg       sql.NullString `db:"measurement_failure_msg,omitempty"`
	IsUploadFailed   bool           `db:"measurement_is_upload_failed"`
	UploadFailureMsg sql.NullString `db:"measurement_upload_failure_msg,omitempty"`
	IsRerun          bool           `db:"measurement_is_rerun"`
	ReportID         sql.NullString `db:"report_id,omitempty"`
	URLID            sql.NullInt64  `db:"url_id,omitempty"` // Used to reference URL
	MeasurementID    sql.NullInt64  `db:"collector_measurement_id,omitempty"`
	IsAnomaly        sql.NullBool   `db:"is_anomaly,omitempty"`
	// FIXME we likely want to support JSON. See: https://github.com/upper/db/issues/462
	TestKeys            string         `db:"test_keys"`
	ResultID            int64          `db:"result_id"`
	ReportFilePath      sql.NullString `db:"report_file_path,omitempty"`
	MeasurementFilePath sql.NullString `db:"measurement_file_path,omitempty"`
}

Database Measurement model

type DatabaseMeasurementURLNetwork

type DatabaseMeasurementURLNetwork struct {
	DatabaseMeasurement `db:",inline"`
	DatabaseNetwork     `db:",inline"`
	DatabaseResult      `db:",inline"`
	DatabaseURL         `db:",inline"`
}

MeasurementURLNetwork is used for the JOIN between Measurement and URL

type DatabaseNetwork

type DatabaseNetwork struct {
	ID          int64  `db:"network_id,omitempty"`
	NetworkName string `db:"network_name"`
	NetworkType string `db:"network_type"`
	IP          string `db:"ip"`
	ASN         uint   `db:"asn"`
	CountryCode string `db:"network_country_code"`
}

DatabaseNetwork represents a network tested by the user

type DatabaseResult

type DatabaseResult struct {
	ID             int64     `db:"result_id,omitempty"`
	TestGroupName  string    `db:"test_group_name"`
	StartTime      time.Time `db:"result_start_time"`
	NetworkID      int64     `db:"network_id"`     // Used to include a Network
	Runtime        float64   `db:"result_runtime"` // Runtime is expressed in fractional seconds
	IsViewed       bool      `db:"result_is_viewed"`
	IsDone         bool      `db:"result_is_done"`
	IsUploaded     bool      `db:"result_is_uploaded"`
	DataUsageUp    float64   `db:"result_data_usage_up"`
	DataUsageDown  float64   `db:"result_data_usage_down"`
	MeasurementDir string    `db:"measurement_dir"`
}

Database Result model

type DatabaseResultNetwork

type DatabaseResultNetwork struct {
	DatabaseResult  `db:",inline"`
	DatabaseNetwork `db:",inline"`
	AnomalyCount    uint64 `db:"anomaly_count"`
	TotalCount      uint64 `db:"total_count"`
	TestKeys        string `db:"test_keys"`
}

ResultNetwork is used to represent the structure made from the JOIN between the results and networks tables.

type DatabaseURL

type DatabaseURL struct {
	ID           sql.NullInt64  `db:"url_id,omitempty"`
	URL          sql.NullString `db:"url"`
	CategoryCode sql.NullString `db:"category_code"`
	CountryCode  sql.NullString `db:"url_country_code"`
}

DatabaseURL represents URLs from the testing lists

type DebugLogger

type DebugLogger interface {
	// Debug emits a debug message.
	Debug(msg string)

	// Debugf formats and emits a debug message.
	Debugf(format string, v ...interface{})
}

DebugLogger is a logger emitting only debug messages.

type Dialer

type Dialer interface {
	// A Dialer is also a SimpleDialer.
	SimpleDialer

	// CloseIdleConnections closes idle connections, if any.
	CloseIdleConnections()
}

Dialer is a SimpleDialer with the possibility of closing open connections.

type DialerWrapper

type DialerWrapper interface {
	WrapDialer(d Dialer) Dialer
}

DialerWrapper is a type that takes in input a Dialer and returns in output a wrapped Dialer.

type Experiment

type Experiment interface {
	// KibiBytesReceived accounts for the KibiBytes received by the experiment.
	KibiBytesReceived() float64

	// KibiBytesSent is like KibiBytesReceived but for the bytes sent.
	KibiBytesSent() float64

	// Name returns the experiment name.
	Name() string

	// GetSummaryKeys returns a data structure containing a
	// summary of the test keys for ooniprobe.
	GetSummaryKeys(m *Measurement) (any, error)

	// ReportID returns the open report's ID, if we have opened a report
	// successfully before, or an empty string, otherwise.
	//
	// Deprecated: new code should use a Submitter.
	ReportID() string

	// MeasureAsync runs an async measurement. This operation could post
	// one or more measurements onto the returned channel. We'll close the
	// channel when we've emitted all the measurements.
	//
	// Arguments:
	//
	// - ctx is the context for deadline/cancellation/timeout;
	//
	// - input is the input (typically a URL but it could also be
	// just an endpoint or an empty string for input-less experiments
	// such as, e.g., ndt7 and dash).
	//
	// Return value:
	//
	// - on success, channel where to post measurements (the channel
	// will be closed when done) and nil error;
	//
	// - on failure, nil channel and non-nil error.
	MeasureAsync(ctx context.Context, input string) (<-chan *Measurement, error)

	// MeasureWithContext performs a synchronous measurement.
	//
	// Return value: strictly either a non-nil measurement and
	// a nil error or a nil measurement and a non-nil error.
	//
	// CAVEAT: while this API is perfectly fine for experiments that
	// return a single measurement, it will only return the first measurement
	// when used with an asynchronous experiment.
	MeasureWithContext(ctx context.Context, input string) (measurement *Measurement, err error)

	// SaveMeasurement saves a measurement on the specified file path.
	//
	// Deprecated: new code should use a Saver.
	SaveMeasurement(measurement *Measurement, filePath string) error

	// SubmitAndUpdateMeasurementContext submits a measurement and updates the
	// fields whose value has changed as part of the submission.
	//
	// Deprecated: new code should use a Submitter.
	SubmitAndUpdateMeasurementContext(
		ctx context.Context, measurement *Measurement) error

	// OpenReportContext will open a report using the given context
	// to possibly limit the lifetime of this operation.
	//
	// Deprecated: new code should use a Submitter.
	OpenReportContext(ctx context.Context) error
}

Experiment is an experiment instance.

type ExperimentArgs

type ExperimentArgs struct {
	// Callbacks contains MANDATORY experiment callbacks.
	Callbacks ExperimentCallbacks

	// Measurement is the MANDATORY measurement in which the experiment
	// must write the results of the measurement.
	Measurement *Measurement

	// Session is the MANDATORY session the experiment can use.
	Session ExperimentSession
}

ExperimentArgs contains the arguments passed to an experiment.

type ExperimentAsyncTestKeys

type ExperimentAsyncTestKeys struct {
	// Extensions contains the extensions used by this experiment.
	Extensions map[string]int64

	// Input is the input this measurement refers to.
	Input MeasurementTarget

	// MeasurementRuntime is the total measurement runtime.
	MeasurementRuntime float64

	// TestHelpers contains the test helpers used in the experiment
	TestHelpers map[string]interface{}

	// TestKeys contains the actual test keys.
	TestKeys interface{}
}

ExperimentAsyncTestKeys is the type of test keys returned by an experiment when running in async fashion rather than in sync fashion.

type ExperimentBuilder

type ExperimentBuilder interface {
	// Interruptible tells you whether this is an interruptible experiment. This kind
	// of experiments (e.g. ndt7) may be interrupted mid way.
	Interruptible() bool

	// InputPolicy returns the experiment input policy.
	InputPolicy() InputPolicy

	// Options returns information about the experiment's options.
	Options() (map[string]ExperimentOptionInfo, error)

	// SetOptionAny sets an option whose value is an any value. We will use reasonable
	// heuristics to convert the any value to the proper type of the field whose name is
	// contained by the key variable. If we cannot convert the provided any value to
	// the proper type, then this function returns an error.
	SetOptionAny(key string, value any) error

	// SetOptionsAny sets options from a map[string]any. See the documentation of
	// the SetOptionAny method for more information.
	SetOptionsAny(options map[string]any) error

	// SetCallbacks sets the experiment's interactive callbacks.
	SetCallbacks(callbacks ExperimentCallbacks)

	// NewExperiment creates the experiment instance.
	NewExperiment() Experiment
}

ExperimentBuilder builds an experiment.

type ExperimentCallbacks

type ExperimentCallbacks interface {
	// OnProgress provides information about an experiment progress.
	OnProgress(percentage float64, message string)
}

ExperimentCallbacks contains experiment event-handling callbacks

type ExperimentInputLoader

type ExperimentInputLoader interface {
	Load(ctx context.Context) ([]OOAPIURLInfo, error)
}

ExperimentInputLoader loads inputs from local or remote sources.

type ExperimentInputProcessor

type ExperimentInputProcessor interface {
	Run(ctx context.Context) error
}

ExperimentInputProcessor processes inputs for an experiment.

type ExperimentMeasurer

type ExperimentMeasurer interface {
	// ExperimentName returns the experiment name.
	ExperimentName() string

	// ExperimentVersion returns the experiment version.
	ExperimentVersion() string

	// Run runs the experiment with the specified context, session,
	// measurement, and experiment calbacks. This method should only
	// return an error in case the experiment could not run (e.g.,
	// a required input is missing). Otherwise, the code should just
	// set the relevant OONI error inside of the measurement and
	// return nil. This is important because the caller WILL NOT submit
	// the measurement if this method returns an error.
	Run(ctx context.Context, args *ExperimentArgs) error

	// GetSummaryKeys returns summary keys expected by ooni/probe-cli.
	GetSummaryKeys(*Measurement) (interface{}, error)
}

ExperimentMeasurer is the interface that allows to run a measurement for a specific experiment.

type ExperimentMeasurerAsync

type ExperimentMeasurerAsync interface {
	// RunAsync runs the experiment in async fashion.
	//
	// Arguments:
	//
	// - ctx is the context for deadline/timeout/cancellation
	//
	// - sess is the measurement session
	//
	// - input is the input URL to measure
	//
	// - callbacks contains the experiment callbacks
	//
	// Returns either a channel where TestKeys are posted or an error.
	//
	// An error indicates that specific preconditions for running the experiment
	// are not met (e.g., the input URL is invalid).
	//
	// On success, the experiment will post on the channel each new
	// measurement until it is done and closes the channel.
	RunAsync(ctx context.Context, sess ExperimentSession, input string,
		callbacks ExperimentCallbacks) (<-chan *ExperimentAsyncTestKeys, error)
}

ExperimentMeasurerAsync is a measurer that can run in async fashion.

Currently this functionality is optional, but we will likely migrate all experiments to use this functionality in 2022.

type ExperimentOptionInfo

type ExperimentOptionInfo struct {
	// Doc contains the documentation.
	Doc string

	// Type contains the type.
	Type string
}

ExperimentOptionInfo contains info about an experiment option.

type ExperimentSession

type ExperimentSession interface {
	// GetTestHelpersByName returns a list of test helpers with the given name.
	GetTestHelpersByName(name string) ([]OOAPIService, bool)

	// DefaultHTTPClient returns the default HTTPClient used by the session.
	DefaultHTTPClient() HTTPClient

	// FetchPsiphonConfig returns psiphon's config as a serialized JSON or an error.
	FetchPsiphonConfig(ctx context.Context) ([]byte, error)

	// FetchTorTargets returns the targets for the Tor experiment or an error.
	FetchTorTargets(ctx context.Context, cc string) (map[string]OOAPITorTarget, error)

	// Logger returns the logger used by the session.
	Logger() Logger

	// ProbeCC returns the country code.
	ProbeCC() string

	// ResolverIP returns the resolver's IP.
	ResolverIP() string

	// TempDir returns the session's temporary directory.
	TempDir() string

	// TorArgs returns the arguments we should pass to tor when executing it.
	TorArgs() []string

	// TorBinary returns the path of the tor binary.
	TorBinary() string

	// TunnelDir is the directory where to store tunnel information.
	TunnelDir() string

	// UserAgent returns the user agent we should be using when we're fine
	// with identifying ourselves as ooniprobe.
	UserAgent() string
}

ExperimentSession is the experiment's view of a session.

type GeoIPASNLookupper added in v0.26.0

type GeoIPASNLookupper interface {
	LookupASN(ip string) (asn uint, org string, err error)
}

GeoIPASNlookupper performs ASN lookups.

type GeoIPASNLookupperFunc added in v0.26.0

type GeoIPASNLookupperFunc func(ip string) (asn uint, org string, err error)

GeoIPASNLookupperFunc transforms a func into a GeoIPASNLookupper.

func (GeoIPASNLookupperFunc) LookupASN added in v0.26.0

func (fx GeoIPASNLookupperFunc) LookupASN(ip string) (asn uint, org string, err error)

LookupASN implements GeoIPASNLookupper.

type HTTPClient

type HTTPClient interface {
	Do(req *http.Request) (*http.Response, error)
	CloseIdleConnections()
}

HTTPClient is an http.Client-like interface.

type HTTPSSvc

type HTTPSSvc struct {
	// ALPN contains the ALPNs inside the HTTPS reply.
	ALPN []string

	// IPv4 contains the IPv4 hints (which may be empty).
	IPv4 []string

	// IPv6 contains the IPv6 hints (which may be empty).
	IPv6 []string
}

HTTPSSvc is the reply to an HTTPS DNS query.

type HTTPTransport

type HTTPTransport interface {
	// Network returns the network used by the transport, which
	// should be one of "tcp" and "udp".
	Network() string

	// RoundTrip performs the HTTP round trip.
	RoundTrip(req *http.Request) (*http.Response, error)

	// CloseIdleConnections closes idle connections.
	CloseIdleConnections()
}

HTTPTransport is an http.Transport-like structure.

type InfoLogger

type InfoLogger interface {
	// An InfoLogger is also a DebugLogger.
	DebugLogger

	// Info emits an informational message.
	Info(msg string)

	// Infof formats and emits an informational message.
	Infof(format string, v ...interface{})
}

InfoLogger is a logger emitting debug and infor messages.

type InputPolicy

type InputPolicy string

InputPolicy describes the experiment policy with respect to input. That is whether it requires input, optionally accepts input, does not want input.

type KeyValueStore

type KeyValueStore interface {
	// Get gets the value of the given key or returns an
	// error if there is no such key or we cannot read
	// from the key-value store.
	Get(key string) (value []byte, err error)

	// Set sets the value of the given key and returns
	// whether the operation was successful or not.
	Set(key string, value []byte) (err error)
}

KeyValueStore is a generic key-value store.

type LocationASN added in v0.26.0

type LocationASN struct {
	ASNumber     uint
	Organization string
}

LocationASN contains ASN information related to a location.

type LocationProvider

type LocationProvider interface {
	ProbeASN() uint
	ProbeASNString() string
	ProbeCC() string
	ProbeIP() string
	ProbeNetworkName() string
	ResolverIP() string
}

LocationProvider is an interface that returns the current location. The [engine.Session] struct implements this interface.

type Logger

type Logger interface {
	// A Logger is also an InfoLogger.
	InfoLogger

	// Warn emits a warning message.
	Warn(msg string)

	// Warnf formats and emits a warning message.
	Warnf(format string, v ...interface{})
}

Logger defines the common interface that a logger should have. It is out of the box compatible with `log.Log` in `apex/log`.

var DiscardLogger Logger = logDiscarder{}

DiscardLogger is the default logger that discards its input

func ValidLoggerOrDefault

func ValidLoggerOrDefault(logger Logger) Logger

ValidLoggerOrDefault is a factory that either returns the logger provided as argument, if not nil, or DiscardLogger.

type Measurement

type Measurement struct {
	// Annotations contains results annotations
	Annotations map[string]string `json:"annotations,omitempty"`

	// DataFormatVersion is the version of the data format
	DataFormatVersion string `json:"data_format_version"`

	// Extensions contains information about the extensions included
	// into the test_keys of this measurement.
	Extensions map[string]int64 `json:"extensions,omitempty"`

	// ID is the locally generated measurement ID
	ID string `json:"id,omitempty"`

	// Input is the measurement input
	Input MeasurementTarget `json:"input"`

	// InputHashes contains input hashes
	InputHashes []string `json:"input_hashes,omitempty"`

	// MeasurementStartTime is the time when the measurement started
	MeasurementStartTime string `json:"measurement_start_time"`

	// MeasurementStartTimeSaved is the moment in time when we
	// started the measurement. This is not included into the JSON
	// and is only used within the ./internal pkg as a "zero" time.
	MeasurementStartTimeSaved time.Time `json:"-"`

	// Options contains command line options
	Options []string `json:"options,omitempty"`

	// ProbeASN contains the probe autonomous system number
	ProbeASN string `json:"probe_asn"`

	// ProbeCC contains the probe country code
	ProbeCC string `json:"probe_cc"`

	// ProbeCity contains the probe city
	ProbeCity string `json:"probe_city,omitempty"`

	// ProbeIP contains the probe IP
	ProbeIP string `json:"probe_ip,omitempty"`

	// ProbeNetworkName contains the probe network name
	ProbeNetworkName string `json:"probe_network_name"`

	// ReportID contains the report ID
	ReportID string `json:"report_id"`

	// ResolverASN is the ASN of the resolver
	ResolverASN string `json:"resolver_asn"`

	// ResolverIP is the resolver IP
	ResolverIP string `json:"resolver_ip"`

	// ResolverNetworkName is the network name of the resolver.
	ResolverNetworkName string `json:"resolver_network_name"`

	// SoftwareName contains the software name
	SoftwareName string `json:"software_name"`

	// SoftwareVersion contains the software version
	SoftwareVersion string `json:"software_version"`

	// TestHelpers contains the test helpers. It seems this structure is more
	// complex than we would like. In particular, using a map from string to
	// string does not fit into the web_connectivity use case. Hence, for now
	// we're going to represent this using interface{}. In going forward we
	// may probably want to have more uniform test helpers.
	TestHelpers map[string]interface{} `json:"test_helpers,omitempty"`

	// TestKeys contains the real test result. This field is opaque because
	// each experiment will insert here a different structure.
	TestKeys interface{} `json:"test_keys"`

	// TestName contains the test name
	TestName string `json:"test_name"`

	// MeasurementRuntime contains the measurement runtime. The JSON name
	// is test_runtime because this is the name expected by the OONI backend
	// even though that name is clearly a misleading one.
	MeasurementRuntime float64 `json:"test_runtime"`

	// TestStartTime contains the test start time
	TestStartTime string `json:"test_start_time"`

	// TestVersion contains the test version
	TestVersion string `json:"test_version"`
}

Measurement is a OONI measurement.

This structure is compatible with the definition of the base data format in https://github.com/ooni/spec/blob/master/data-formats/df-000-base.md.

func (*Measurement) AddAnnotation

func (m *Measurement) AddAnnotation(key, value string)

AddAnnotation adds a single annotations to m.Annotations.

func (*Measurement) AddAnnotations

func (m *Measurement) AddAnnotations(input map[string]string)

AddAnnotations adds the annotations from input to m.Annotations.

type MeasurementTarget

type MeasurementTarget string

MeasurementTarget is the target of a OONI measurement.

func (MeasurementTarget) MarshalJSON

func (t MeasurementTarget) MarshalJSON() ([]byte, error)

MarshalJSON serializes the MeasurementTarget.

type MeasuringNetwork added in v0.26.0

type MeasuringNetwork interface {
	// NewDialerWithoutResolver creates a [Dialer] with error wrapping and without an attached
	// resolver, meaning that you MUST pass TCP or UDP endpoint addresses to this dialer.
	//
	// The [DialerWrapper] arguments wraps the returned dialer in such a way that we can implement
	// the legacy [netx] package. New code MUST NOT use this functionality, which we'd like to remove ASAP.
	NewDialerWithoutResolver(dl DebugLogger, w ...DialerWrapper) Dialer

	// NewParallelDNSOverHTTPSResolver creates a new DNS-over-HTTPS resolver with error wrapping.
	NewParallelDNSOverHTTPSResolver(logger DebugLogger, URL string) Resolver

	// NewParallelUDPResolver creates a new Resolver using DNS-over-UDP
	// that performs parallel A/AAAA lookups during LookupHost.
	//
	// The address argument is the UDP endpoint address (e.g., 1.1.1.1:53, [::1]:53).
	NewParallelUDPResolver(logger DebugLogger, dialer Dialer, address string) Resolver

	// NewQUICDialerWithoutResolver creates a [QUICDialer] with error wrapping and without an attached
	// resolver, meaning that you MUST pass UDP endpoint addresses to this dialer.
	//
	// The [QUICDialerWrapper] arguments wraps the returned dialer in such a way
	// that we can implement the legacy [netx] package. New code MUST NOT
	// use this functionality, which we'd like to remove ASAP.
	NewQUICDialerWithoutResolver(
		listener UDPListener, logger DebugLogger, w ...QUICDialerWrapper) QUICDialer

	// NewStdlibResolver creates a new Resolver with error wrapping using
	// getaddrinfo or &net.Resolver{} depending on `-tags netgo`.
	NewStdlibResolver(logger DebugLogger) Resolver

	// NewTLSHandshakerStdlib creates a new TLSHandshaker with error wrapping
	// that is using the go standard library to manage TLS.
	NewTLSHandshakerStdlib(logger DebugLogger) TLSHandshaker

	// NewTLSHandshakerUTLS creates a new TLS handshaker using
	// gitlab.com/yawning/utls for TLS that implements error wrapping.
	//
	// The id is the address of something like utls.HelloFirefox_55.
	//
	// Passing a nil `id` will make this function panic.
	NewTLSHandshakerUTLS(logger DebugLogger, id *utls.ClientHelloID) TLSHandshaker

	// NewUDPListener creates a new UDPListener with error wrapping.
	NewUDPListener() UDPListener
}

MeasuringNetwork defines the constructors required for implementing OONI experiments. All these constructors MUST guarantee proper error wrapping to map Go errors to OONI errors as documented by the [netxlite] package. The [*netxlite.Netx] type is currently the default implementation of this interface. This interface SHOULD always be implemented in terms of an UnderlyingNetwork that allows to switch between the host network and [netemx].

type OOAPICheckInConfig

type OOAPICheckInConfig struct {
	// Charging indicate whether the phone is charging.
	Charging bool `json:"charging"`

	// OnWiFi indicate if the phone is connected to a WiFi.
	OnWiFi bool `json:"on_wifi"`

	// Platform of the probe.
	Platform string `json:"platform"`

	// ProbeASN is the probe ASN.
	ProbeASN string `json:"probe_asn"`

	// ProbeCC is the probe country code.
	ProbeCC string `json:"probe_cc"`

	// RunType indicated whether the run is "timed" or "manual".
	RunType RunType `json:"run_type"`

	// SoftwareName of the probe.
	SoftwareName string `json:"software_name"`

	// SoftwareVersion of the probe.
	SoftwareVersion string `json:"software_version"`

	// WebConnectivity contains WebConnectivity information.
	WebConnectivity OOAPICheckInConfigWebConnectivity `json:"web_connectivity"`
}

OOAPICheckInConfig contains config for a checkin API call.

type OOAPICheckInConfigWebConnectivity

type OOAPICheckInConfigWebConnectivity struct {
	// CategoryCodes contains an array of category codes
	CategoryCodes []string `json:"category_codes"`
}

OOAPICheckInConfigWebConnectivity is the WebConnectivity portion of OOAPICheckInConfig.

type OOAPICheckInInfoWebConnectivity

type OOAPICheckInInfoWebConnectivity struct {
	// ReportID is the report ID the probe should use.
	ReportID string `json:"report_id"`

	// URLs contains the URL to measure.
	URLs []OOAPIURLInfo `json:"urls"`
}

OOAPICheckInInfoWebConnectivity contains the WebConnectivity part of OOAPICheckInInfo.

type OOAPICheckInResult

type OOAPICheckInResult struct {
	// Conf contains configuration.
	Conf OOAPICheckInResultConfig `json:"conf"`

	// ProbeASN contains the probe's ASN.
	ProbeASN string `json:"probe_asn"`

	// ProbeCC contains the probe's CC.
	ProbeCC string `json:"probe_cc"`

	// Tests contains information about nettests.
	Tests OOAPICheckInResultNettests `json:"tests"`

	// UTCTime contains the time in UTC.
	UTCTime time.Time `json:"utc_time"`

	// V is the version.
	V int64 `json:"v"`
}

OOAPICheckInResult is the result returned by the checkin API.

type OOAPICheckInResultConfig

type OOAPICheckInResultConfig struct {
	// Features contains feature flags.
	Features map[string]bool `json:"features"`

	// TestHelpers contains test-helpers information.
	TestHelpers map[string][]OOAPIService `json:"test_helpers"`
}

OOAPICheckInResultConfig contains configuration.

type OOAPICheckInResultNettests

type OOAPICheckInResultNettests struct {
	// WebConnectivity contains WebConnectivity related information.
	WebConnectivity *OOAPICheckInInfoWebConnectivity `json:"web_connectivity"`
}

OOAPICheckInResultNettests contains nettests information returned by the checkin API call.

type OOAPICheckReportIDResponse

type OOAPICheckReportIDResponse struct {
	Error string `json:"error"`
	Found bool   `json:"found"`
	V     int64  `json:"v"`
}

OOAPICheckReportIDResponse is the check-report-id API response.

type OOAPICollectorOpenResponse

type OOAPICollectorOpenResponse struct {
	// BackendVersion is the backend version.
	BackendVersion string `json:"backend_version"`

	// ReportID is the report ID.
	ReportID string `json:"report_id"`

	// SupportedFormats contains supported formats.
	SupportedFormats []string `json:"supported_formats"`
}

OOAPICollectorOpenResponse is the response returned by the open report API.

type OOAPICollectorUpdateRequest

type OOAPICollectorUpdateRequest struct {
	// Format is the Content's data format
	Format string `json:"format"`

	// Content is the actual report
	Content any `json:"content"`
}

OOAPICollectorUpdateRequest is a request for the collector update API.

type OOAPICollectorUpdateResponse

type OOAPICollectorUpdateResponse struct {
	// MeasurementID is the measurement ID.
	MeasurementID string `json:"measurement_id"`
}

OOAPICollectorUpdateResponse is the response from the collector update API.

type OOAPILoginAuth

type OOAPILoginAuth struct {
	Expire time.Time `json:"expire"`
	Token  string    `json:"token"`
}

OOAPILoginAuth contains authentication info

type OOAPILoginCredentials

type OOAPILoginCredentials struct {
	Username string `json:"username"`
	Password string `json:"password"`
}

OOAPILoginCredentials contains the login credentials

type OOAPIMeasurementMeta

type OOAPIMeasurementMeta struct {
	// Fields returned by the API server whenever we are
	// calling /api/v1/measurement_meta.
	Anomaly              bool      `json:"anomaly"`
	CategoryCode         string    `json:"category_code"`
	Confirmed            bool      `json:"confirmed"`
	Failure              bool      `json:"failure"`
	Input                *string   `json:"input"`
	MeasurementStartTime time.Time `json:"measurement_start_time"`
	ProbeASN             int64     `json:"probe_asn"`
	ProbeCC              string    `json:"probe_cc"`
	ReportID             string    `json:"report_id"`
	Scores               string    `json:"scores"`
	TestName             string    `json:"test_name"`
	TestStartTime        time.Time `json:"test_start_time"`

	// This field is only included if the user has specified
	// the config.Full option, otherwise it's empty.
	RawMeasurement string `json:"raw_measurement"`
}

OOAPIMeasurementMeta contains measurement metadata.

type OOAPIMeasurementMetaConfig

type OOAPIMeasurementMetaConfig struct {
	// ReportID is the mandatory report ID.
	ReportID string

	// Full indicates whether we also want the full measurement body.
	Full bool

	// Input is the optional input.
	Input string
}

OOAPIMeasurementMetaConfig contains configuration for GetMeasurementMeta.

type OOAPIProbeMetadata

type OOAPIProbeMetadata struct {
	AvailableBandwidth string   `json:"available_bandwidth,omitempty"`
	DeviceToken        string   `json:"device_token,omitempty"`
	Language           string   `json:"language,omitempty"`
	NetworkType        string   `json:"network_type,omitempty"`
	Platform           string   `json:"platform"`
	ProbeASN           string   `json:"probe_asn"`
	ProbeCC            string   `json:"probe_cc"`
	ProbeFamily        string   `json:"probe_family,omitempty"`
	ProbeTimezone      string   `json:"probe_timezone,omitempty"`
	SoftwareName       string   `json:"software_name"`
	SoftwareVersion    string   `json:"software_version"`
	SupportedTests     []string `json:"supported_tests"`
}

OOAPIProbeMetadata contains metadata about a probe. This message is included into a bunch of messages sent to orchestra.

func (OOAPIProbeMetadata) Valid

func (m OOAPIProbeMetadata) Valid() bool

Valid returns true if metadata is valid, false otherwise. Metadata is considered valid if all the mandatory fields are not empty. If a field is marked `json:",omitempty"` in the structure definition, then it's for sure mandatory. The "device_token" field is mandatory only if the platform is "ios" or "android", because there's currently no device token that we know of for desktop devices.

type OOAPIRegisterRequest

type OOAPIRegisterRequest struct {
	OOAPIProbeMetadata
	Password string `json:"password"`
}

OOAPIRegisterRequest is a request to the register API.

type OOAPIRegisterResponse

type OOAPIRegisterResponse struct {
	ClientID string `json:"client_id"`
}

OOAPIRegisterResponse is a reponse from the register API.

type OOAPIReportTemplate

type OOAPIReportTemplate struct {
	// DataFormatVersion is unconditionally set to DefaultDataFormatVersion
	// and you don't need to be concerned about it.
	DataFormatVersion string `json:"data_format_version"`

	// Format is unconditionally set to `json` and you don't need
	// to be concerned about it.
	Format string `json:"format"`

	// ProbeASN is the probe's autonomous system number (e.g. `AS1234`)
	ProbeASN string `json:"probe_asn"`

	// ProbeCC is the probe's country code (e.g. `IT`)
	ProbeCC string `json:"probe_cc"`

	// SoftwareName is the app name (e.g. `measurement-kit`)
	SoftwareName string `json:"software_name"`

	// SoftwareVersion is the app version (e.g. `0.9.1`)
	SoftwareVersion string `json:"software_version"`

	// TestName is the test name (e.g. `ndt`)
	TestName string `json:"test_name"`

	// TestStartTime contains the test start time
	TestStartTime string `json:"test_start_time"`

	// TestVersion is the test version (e.g. `1.0.1`)
	TestVersion string `json:"test_version"`
}

OOAPIReportTemplate is the template for opening a report

type OOAPIService

type OOAPIService struct {
	// Address is the address of the server.
	Address string `json:"address"`

	// Type is the type of the service.
	Type string `json:"type"`

	// Front is the front to use with "cloudfront" type entries.
	Front string `json:"front,omitempty"`
}

OOAPIService describes a backend service.

The fields of this struct have the meaning described in v2.0.0 of the OONI bouncer specification defined by https://github.com/ooni/spec/blob/master/backends/bk-004-bouncer.md.

type OOAPITorTarget

type OOAPITorTarget struct {
	// Address is the address of the target.
	Address string `json:"address"`

	// Name is the name of the target.
	Name string `json:"name"`

	// Params contains optional params for, e.g., pluggable transports.
	Params map[string][]string `json:"params"`

	// Protocol is the protocol to use with the target.
	Protocol string `json:"protocol"`

	// Source is the source from which we fetched this specific
	// target. Whenever the source is non-empty, we will treat
	// this specific target as a private target.
	Source string `json:"source"`
}

OOAPITorTarget is a target for the tor experiment.

type OOAPIURLInfo

type OOAPIURLInfo struct {
	// CategoryCode is the URL's category (e.g., FEXP, POLT, HUMR).
	CategoryCode string `json:"category_code"`

	// CountryCode is the URL's ISO country code or ZZ for global URLs.
	CountryCode string `json:"country_code"`

	// URL is the string-serialized URL.
	URL string `json:"url"`
}

OOAPIURLInfo contains information on a test lists URL.

type PerformanceTestKeys

type PerformanceTestKeys struct {
	Upload   float64 `json:"upload"`
	Download float64 `json:"download"`
	Ping     float64 `json:"ping"`
	Bitrate  float64 `json:"median_bitrate"`
}

PerformanceTestKeys is the result summary for a performance test

type PrinterCallbacks

type PrinterCallbacks struct {
	Logger
}

PrinterCallbacks is the default event handler

func NewPrinterCallbacks

func NewPrinterCallbacks(logger Logger) PrinterCallbacks

NewPrinterCallbacks returns a new default callback handler

func (PrinterCallbacks) OnProgress

func (d PrinterCallbacks) OnProgress(percentage float64, message string)

OnProgress provides information about an experiment progress.

type QUICDialer

type QUICDialer interface {
	// DialContext establishes a new QUIC session using the given
	// network and address. The tlsConfig and the quicConfig arguments
	// MUST NOT be nil. Returns either the session or an error.
	//
	// Recommended tlsConfig setup:
	//
	// - set ServerName to be the SNI;
	//
	// - set RootCAs to nil (which causes us to use the default cert pool);
	//
	// - set NextProtos to []string{"h3"}.
	//
	// Typically, you want to pass `&quic.Config{}` as quicConfig.
	DialContext(ctx context.Context, address string,
		tlsConfig *tls.Config, quicConfig *quic.Config) (quic.EarlyConnection, error)

	// CloseIdleConnections closes idle connections, if any.
	CloseIdleConnections()
}

QUICDialer dials QUIC sessions.

type QUICDialerWrapper

type QUICDialerWrapper interface {
	WrapQUICDialer(qd QUICDialer) QUICDialer
}

QUICDialerWrapper is a type that takes in input a QUICDialer and returns in output a wrapped QUICDialer.

type ReadableDatabase

type ReadableDatabase interface {
	// ListResults return the list of results
	//
	// Arguments:
	//
	// Returns either the complete and incomplete database results or an error
	ListResults() ([]DatabaseResultNetwork, []DatabaseResultNetwork, error)

	// ListMeasurements given a result ID
	//
	// Arguments:
	//
	// - resultID is the id of the result to search measurements from
	//
	// Returns the measurements under the given result or an error
	ListMeasurements(resultID int64) ([]DatabaseMeasurementURLNetwork, error)

	// GetMeasurementJSON returns a map[string]interface{} given a database and a measurementID
	//
	// Arguments:
	//
	// - msmtID is the measurement id to generate JSON
	//
	// Returns the measurement JSON or an error
	GetMeasurementJSON(msmtID int64) (map[string]interface{}, error)
}

ReadableDatabase only supports reading data.

type Resolver

type Resolver interface {
	// LookupHost resolves the given hostname to IP addreses. This function SHOULD handle the
	// case in which hostname is an IP address by returning a 1-element list containing the hostname,
	// for consistency with [net.Resolver] behaviour.
	LookupHost(ctx context.Context, hostname string) (addrs []string, err error)

	// Network returns the resolver type. It should be one of:
	//
	// - go: means we're using whatever resolver the Go stdlib uses
	// depending on the current build configuration;
	//
	// - system: means we've been compiled with `CGO_ENABLED=1`
	// so we can bypass the go resolver and call getaddrinfo directly;
	//
	// - udp: is a custom DNS-over-UDP resolver;
	//
	// - tcp: is a custom DNS-over-TCP resolver;
	//
	// - dot: is a custom DNS-over-TLS resolver;
	//
	// - doh: is a custom DNS-over-HTTPS resolver;
	//
	// - doh3: is a custom DNS-over-HTTP3 resolver.
	//
	// See https://github.com/ooni/probe/issues/2029#issuecomment-1140805266
	// for an explanation of why it would not be proper to call "netgo" the
	// resolver we get by default from the standard library.
	Network() string

	// Address returns the resolver address (e.g., 8.8.8.8:53).
	Address() string

	// CloseIdleConnections closes idle connections, if any.
	CloseIdleConnections()

	// LookupHTTPS issues an HTTPS query for a domain.
	LookupHTTPS(
		ctx context.Context, domain string) (*HTTPSSvc, error)

	// LookupNS issues a NS query for a domain.
	LookupNS(ctx context.Context, domain string) ([]*net.NS, error)
}

Resolver performs domain name resolutions.

type RunType

type RunType string

RunType describes the type of a ooniprobe run.

type Saver

type Saver interface {
	SaveMeasurement(m *Measurement) error
}

Saver saves a measurement on some persistent storage.

type SimpleDialer

type SimpleDialer interface {
	// DialContext creates a new TCP/UDP connection like [net.DialContext] would do.
	//
	// The endpoint is an endpoint like the ones accepted by [net.DialContext]. For example,
	// x.org:443, 130.192.91.211:443 and [::1]:443. Note that IPv6 addrs are quoted.
	//
	// This function MUST gracefully handle the case where the endpoint contains an IPv4
	// or IPv6 address by skipping DNS resolution and directly using the endpoint.
	//
	// See https://github.com/ooni/probe-cli/pull/1295#issuecomment-1731243994 for more
	// details on why DialContext MUST do that.
	DialContext(ctx context.Context, network, endpoint string) (net.Conn, error)
}

SimpleDialer establishes network connections.

type Submitter

type Submitter interface {
	// Submit submits the measurement and updates its
	// report ID field in case of success.
	Submit(ctx context.Context, m *Measurement) error
}

Submitter submits a measurement to the OONI collector.

type THDNSResult

type THDNSResult struct {
	Failure *string  `json:"failure"`
	Addrs   []string `json:"addrs"`
	ASNs    []int64  `json:"-"` // not visible from the JSON
}

THDNSResult is the result of the DNS lookup performed by the control vantage point.

type THHTTPRequestResult

type THHTTPRequestResult struct {
	BodyLength           int64             `json:"body_length"`
	DiscoveredH3Endpoint string            `json:"discovered_h3_endpoint"`
	Failure              *string           `json:"failure"`
	Title                string            `json:"title"`
	Headers              map[string]string `json:"headers"`
	StatusCode           int64             `json:"status_code"`
}

THHTTPRequestResult is the result of the HTTP request performed by the control vantage point.

type THIPInfo

type THIPInfo struct {
	// ASN contains the address' AS number.
	ASN int64 `json:"asn"`

	// Flags contains flags describing this address.
	Flags int64 `json:"flags"`
}

THIPInfo contains information about IP addresses resolved either by the probe or by the TH and processed by the TH.

type THRequest

type THRequest struct {
	HTTPRequest        string              `json:"http_request"`
	HTTPRequestHeaders map[string][]string `json:"http_request_headers"`
	TCPConnect         []string            `json:"tcp_connect"`

	// XQUICEnabled is a feature flag that tells the oohelperd to
	// conditionally enable QUIC measurements, which are otherwise
	// disabled by default. We will honour this flag during the
	// v3.17.x release cycle and possibly also for v3.18.x but we
	// will eventually enable QUIC for all clients.
	XQUICEnabled bool `json:"x_quic_enabled"`
}

THRequest is the request that we send to the control.

See https://github.com/ooni/spec/blob/master/nettests/ts-017-web-connectivity.md

type THResponse

type THResponse struct {
	TCPConnect    map[string]THTCPConnectResult   `json:"tcp_connect"`
	TLSHandshake  map[string]THTLSHandshakeResult `json:"tls_handshake,omitempty"`
	QUICHandshake map[string]THTLSHandshakeResult `json:"quic_handshake"`
	HTTPRequest   THHTTPRequestResult             `json:"http_request"`
	HTTP3Request  *THHTTPRequestResult            `json:"http3_request"` // optional!
	DNS           THDNSResult                     `json:"dns"`
	IPInfo        map[string]*THIPInfo            `json:"ip_info,omitempty"`
}

THResponse is the response from the control service.

type THTCPConnectResult

type THTCPConnectResult struct {
	Status  bool    `json:"status"`
	Failure *string `json:"failure"`
}

THTCPConnectResult is the result of the TCP connect attempt performed by the control vantage point.

type THTLSHandshakeResult

type THTLSHandshakeResult struct {
	ServerName string  `json:"server_name"`
	Status     bool    `json:"status"`
	Failure    *string `json:"failure"`
}

THTLSHandshakeResult is the result of the TLS handshake attempt performed by the control vantage point.

type TLSConn added in v0.26.0

type TLSConn = oohttp.TLSConn

TLSConn is the type of connection that oohttp expects from any library that implements TLS functionality. By using this kind of TLSConn we're able to use both the standard library and gitlab.com/yawning/utls.git to perform TLS operations. Note that the stdlib's tls.Conn implements this interface.

type TLSDialer

type TLSDialer interface {
	// CloseIdleConnections closes idle connections, if any.
	CloseIdleConnections()

	// DialTLSContext dials a TLS connection. This method will always return
	// to you a oohttp.TLSConn, so you can always safely cast to it.
	//
	// The endpoint is an endpoint like the ones accepted by [net.DialContext]. For example,
	// x.org:443, 130.192.91.211:443 and [::1]:443. Note that IPv6 addrs are quoted.
	//
	// This function MUST gracefully handle the case where the endpoint contains an IPv4
	// or IPv6 address by skipping DNS resolution and directly using the endpoint.
	//
	// See https://github.com/ooni/probe-cli/pull/1295#issuecomment-1731243994 for more
	// details on why DialTLSContext MUST do that.
	DialTLSContext(ctx context.Context, network, address string) (net.Conn, error)
}

TLSDialer is a Dialer dialing TLS connections.

type TLSHandshaker

type TLSHandshaker interface {
	// Handshake creates a new TLS connection from the given connection and
	// the given config. This function DOES NOT take ownership of the connection
	// and it's your responsibility to close it on failure.
	//
	// Recommended tlsConfig setup:
	//
	// - set ServerName to be the SNI;
	//
	// - set RootCAs to nil (which causes us to use the default cert pool);
	//
	// - set NextProtos to []string{"h2", "http/1.1"} for HTTPS
	// and []string{"dot"} for DNS-over-TLS.
	Handshake(ctx context.Context, conn net.Conn, tlsConfig *tls.Config) (TLSConn, error)
}

TLSHandshaker is the generic TLS handshaker.

type Trace

type Trace interface {
	// TimeNow returns the current time. Normally, this should be the same
	// value returned by time.Now but you may want to manipulate the time
	// returned when testing to have deterministic tests. To this end, you
	// can use functionality exported by the ./internal/testingx pkg.
	TimeNow() time.Time

	// MaybeWrapNetConn possibly wraps a net.Conn with the caller trace. If there's no
	// desire to wrap the net.Conn, this function just returns the original net.Conn.
	//
	// Arguments:
	//
	// - conn is the non-nil underlying net.Conn to be wrapped
	MaybeWrapNetConn(conn net.Conn) net.Conn

	// MaybeWrapUDPLikeConn is like MaybeWrapNetConn but for UDPLikeConn.
	//
	// Arguments:
	//
	// - conn is the non-nil underlying UDPLikeConn to be wrapped
	MaybeWrapUDPLikeConn(conn UDPLikeConn) UDPLikeConn

	// OnDNSRoundTripForLookupHost is used with a DNSTransport and called
	// when the RoundTrip terminates.
	//
	// Arguments:
	//
	// - started is when we called transport.RoundTrip
	//
	// - reso is the parent resolver for the trace;
	//
	// - query is the non-nil DNS query we use for the RoundTrip
	//
	// - response is a valid DNS response, obtained after the RoundTrip;
	//
	// - addrs is the list of addresses obtained after the RoundTrip, which
	// is empty if the RoundTrip failed
	//
	// - err is the result of DNSLookup; either an error or nil
	//
	// - finished is the time right after the RoundTrip
	OnDNSRoundTripForLookupHost(started time.Time, reso Resolver, query DNSQuery,
		response DNSResponse, addrs []string, err error, finished time.Time)

	// OnDelayedDNSResponse is used with a DNSOverUDPTransport and called
	// when we get delayed, unexpected DNS responses.
	//
	// Arguments:
	//
	// - started is when we started reading the delayed response;
	//
	// - txp is the DNS transport used with the resolver;
	//
	// - query is the non-nil DNS query we use for the RoundTrip;
	//
	// - response is the non-nil valid DNS response, obtained after some delay;
	//
	// - addrs is the list of addresses obtained after decoding the delayed response,
	// which is empty if the response did not contain any addresses, which we
	// extract by calling the DecodeLookupHost method.
	//
	// - err is the result of DecodeLookupHost: either an error or nil;
	//
	// - finished is when we have read the delayed response.
	OnDelayedDNSResponse(started time.Time, txp DNSTransport, query DNSQuery,
		resp DNSResponse, addrs []string, err error, finsihed time.Time) error

	// OnConnectDone is called when connect terminates.
	//
	// Arguments:
	//
	// - started is when we called connect;
	//
	// - network is the network we're using (one of "tcp" and "udp");
	//
	// - domain is the domain for which we're calling connect. If the user called
	// connect for an IP address and a port, then domain will be an IP address;
	//
	// - remoteAddr is the TCP endpoint with which we are connecting: it will
	// consist of an IP address and a port (e.g., 8.8.8.8:443, [::1]:5421);
	//
	// - err is the result of connect: either an error or nil;
	//
	// - finished is when connect returned.
	//
	// The error passed to this function will always be wrapped such that the
	// string returned by Error is an OONI error.
	OnConnectDone(
		started time.Time, network, domain, remoteAddr string, err error, finished time.Time)

	// OnTLSHandshakeStart is called when the TLS handshake starts.
	//
	// Arguments:
	//
	// - now is the moment before we start the handshake;
	//
	// - remoteAddr is the TCP endpoint with which we are connecting: it will
	// consist of an IP address and a port (e.g., 8.8.8.8:443, [::1]:5421);
	//
	// - config is the non-nil TLS config we're using.
	OnTLSHandshakeStart(now time.Time, remoteAddr string, config *tls.Config)

	// OnTLSHandshakeDone is called when the TLS handshake terminates.
	//
	// Arguments:
	//
	// - started is when we started the handshake;
	//
	// - remoteAddr is the TCP endpoint with which we are connecting: it will
	// consist of an IP address and a port (e.g., 8.8.8.8:443, [::1]:5421);
	//
	// - config is the non-nil TLS config we're using;
	//
	// - state is the state of the TLS connection after the handshake, where all
	// fields are zero-initialized if the handshake failed;
	//
	// - err is the result of the handshake: either an error or nil;
	//
	// - finished is right after the handshake.
	//
	// The error passed to this function will always be wrapped such that the
	// string returned by Error is an OONI error.
	OnTLSHandshakeDone(started time.Time, remoteAddr string, config *tls.Config,
		state tls.ConnectionState, err error, finished time.Time)

	// OnQUICHandshakeStart is called before the QUIC handshake.
	//
	// Arguments:
	//
	// - now is the moment before we start the handshake;
	//
	// - remoteAddr is the QUIC endpoint with which we are connecting: it will
	// consist of an IP address and a port (e.g., 8.8.8.8:443, [::1]:5421);
	//
	// - config is the possibly-nil QUIC config we're using.
	OnQUICHandshakeStart(now time.Time, remoteAddr string, quicConfig *quic.Config)

	// OnQUICHandshakeDone is called after the QUIC handshake.
	//
	// Arguments:
	//
	// - started is when we started the handshake;
	//
	// - remoteAddr is the QUIC endpoint with which we are connecting: it will
	// consist of an IP address and a port (e.g., 8.8.8.8:443, [::1]:5421);
	//
	// - qconn is the QUIC connection we receive after the handshake: either
	// a valid quic.EarlyConnection or nil;
	//
	// - config is the non-nil TLS config we are using;
	//
	// - err is the result of the handshake: either an error or nil;
	//
	// - finished is right after the handshake.
	//
	// The error passed to this function will always be wrapped such that the
	// string returned by Error is an OONI error.
	OnQUICHandshakeDone(started time.Time, remoteAddr string, qconn quic.EarlyConnection,
		config *tls.Config, err error, finished time.Time)
}

Trace allows to collect measurement traces. A trace is injected into netx operations using context.WithValue. Netx code retrieves the trace using context.Value. See docs/design/dd-003-step-by-step.md for the design document explaining why we implemented context-based tracing.

type UDPLikeConn

type UDPLikeConn interface {
	// An UDPLikeConn is a net.PacketConn conn.
	net.PacketConn

	// SetReadBuffer allows setting the read buffer.
	SetReadBuffer(bytes int) error

	// SyscallConn returns a conn suitable for calling syscalls,
	// which is also instrumental to setting the read buffer.
	SyscallConn() (syscall.RawConn, error)
}

UDPLikeConn is a net.PacketConn with some extra functions required to convince the QUIC library (quic-go/quic-go) to inflate the receive buffer of the connection.

The QUIC library will treat this connection as a "dumb" net.PacketConn, calling its ReadFrom and WriteTo methods as opposed to more efficient methods that are available under Linux and (maybe?) FreeBSD.

It seems fine to avoid performance optimizations, because they would complicate the implementation on our side and our use cases (blocking and heavy throttling) do not seem to require such optimizations.

See https://github.com/ooni/probe/issues/1754 for a more comprehensive discussion of UDPLikeConn.

type UDPListener added in v0.26.0

type UDPListener interface {
	// Listen creates a new listening UDPLikeConn.
	Listen(addr *net.UDPAddr) (UDPLikeConn, error)
}

UDPListener listens for connections over UDP, e.g. QUIC.

type UnderlyingNetwork

type UnderlyingNetwork interface {
	// DefaultCertPool returns the underlying cert pool used by the
	// network extensions library. You MUST NOT use this function to
	// modify the default cert pool since this would lead to a data
	// race. Use [netxlite.netxlite.NewMozillaCertPool] if you wish to get
	// a copy of the default cert pool that you can modify.
	DefaultCertPool() *x509.CertPool

	// DialTimeout returns the default timeout to use for dialing.
	DialTimeout() time.Duration

	// DialContext is equivalent to net.Dialer.DialContext.
	DialContext(ctx context.Context, network, address string) (net.Conn, error)

	// GetaddrinfoLookupANY is like net.Resolver.LookupHost except that it
	// also returns to the caller the CNAME when it is available.
	GetaddrinfoLookupANY(ctx context.Context, domain string) ([]string, string, error)

	// GetaddrinfoResolverNetwork returns the resolver network.
	GetaddrinfoResolverNetwork() string

	// ListenTCP is equivalent to net.ListenTCP.
	ListenTCP(network string, addr *net.TCPAddr) (net.Listener, error)

	// ListenUDP is equivalent to net.ListenUDP.
	ListenUDP(network string, addr *net.UDPAddr) (UDPLikeConn, error)
}

UnderlyingNetwork implements the underlying network APIs on top of which we implement network extensions such as MeasuringNetwork.

type UploadedTotalCount

type UploadedTotalCount struct {
	UploadedCount int64 `db:",inline"`
	TotalCount    int64 `db:",inline"`
}

UploadedTotalCount is the count of the measurements which have been uploaded vs the total measurements in a given result set

type WritableDatabase

type WritableDatabase interface {
	// CreateNetwork will create a new network in the network table
	//
	// Arguments:
	//
	// - loc: loc is the location provider used to instantiate the network
	//
	// Returns either a database network instance or an error
	CreateNetwork(loc LocationProvider) (*DatabaseNetwork, error)

	// CreateOrUpdateURL will create a new URL entry to the urls table if it doesn't
	// exists, otherwise it will update the category code of the one already in
	// there.
	//
	// Arguments:
	//
	// - urlStr is the URL string to create or update
	//
	// - categoryCode is the category code to update
	//
	// - countryCode is the country code to update
	//
	// Returns either the new URL id or an error
	CreateOrUpdateURL(urlStr string, categoryCode string, countryCode string) (int64, error)

	// CreateResult writes the Result to the database a returns a pointer
	// to the Result
	//
	// Arguments:
	//
	// - homePath is the home directory path to make the results directory
	//
	// - testGroupName is used to annotate the database the result
	//
	// - networkID is the id of the underlying network
	//
	// Returns either a database result instance or an error
	CreateResult(homePath string, testGroupName string, networkID int64) (*DatabaseResult, error)

	// UpdateUploadedStatus will check if all the measurements inside of a given result set have been
	// uploaded and if so will set the is_uploaded flag to true
	//
	// Arguments:
	//
	// - result is the database result to update
	//
	// Returns a non-nil error if update failed
	UpdateUploadedStatus(result *DatabaseResult) error

	// Finished marks the result as done and sets the runtime
	//
	// Arguments:
	//
	// - result is the database result to mark as done
	//
	// Returns a non-nil error if result could not be marked as done
	Finished(result *DatabaseResult) error

	// DeleteResult will delete a particular result and the relative measurement on
	// disk.
	//
	// Arguments:
	//
	// - resultID is the id of the database result to be deleted
	//
	// Returns a non-nil error if result could not be deleted
	DeleteResult(resultID int64) error

	// CreateMeasurement writes the measurement to the database a returns a pointer
	// to the Measurement
	//
	// Arguments:
	//
	// - reportID is the report id to annotate
	//
	// - testName is the experiment name to use
	//
	// - measurementDir is the measurement directory path
	//
	// - resultID is the result id to annotate
	//
	// - urlID is the id of the URL input
	//
	// Returns either a database measurement or an error
	CreateMeasurement(reportID sql.NullString, testName string, measurementDir string, idx int,
		resultID int64, urlID sql.NullInt64) (*DatabaseMeasurement, error)

	// AddTestKeys writes the summary to the measurement
	//
	// Arguments:
	//
	// - msmt is the database measurement to update
	//
	// - tk is the testkeys
	//
	// Returns a non-nil error if measurement update failed
	AddTestKeys(msmt *DatabaseMeasurement, tk any) error

	// Done marks the measurement as completed
	//
	// Arguments:
	//
	// - msmt is the database measurement to update
	//
	// Returns a non-nil error if the measurement could not be marked as done
	Done(msmt *DatabaseMeasurement) error

	// UploadFailed writes the error string for the upload failure to the measurement
	//
	// Arguments:
	//
	// - msmt is the database measurement to update
	//
	// - failure is the error string to use
	//
	// Returns a non-nil error if the measurement update failed
	UploadFailed(msmt *DatabaseMeasurement, failure string) error

	// UploadSucceeded writes the error string for the upload failure to the measurement
	//
	// Arguments:
	//
	// - msmt is the database measurement to update
	//
	// Returns a non-nil error is measurement update failed
	UploadSucceeded(msmt *DatabaseMeasurement) error

	// Failed writes the error string to the measurement
	//
	// Arguments:
	//
	// - msmt is the database measurement to update
	//
	// - failure is the error string to use
	//
	// Returns a non-nil error if the measurement update failed
	Failed(msmt *DatabaseMeasurement, failure string) error
}

WritableDatabase supports writing and updating data.

Jump to

Keyboard shortcuts

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