refactor(netx): merge archival, trace, and the savers (#772)
This diff creates a new package under netx called tracex that contains everything we need to perform measurements using events tracing and postprocessing (which is the technique with which we implement most network experiments). The general idea here is to (1) create a unique package out of all of these packages; (2) clean up the code a bit (improve tests, docs, apply more recent code patterns); (3) move the resulting code as a toplevel package inside of internal. Once this is done, netx can be further refactored to avoid subpackages and we can search for more code to salvage/refactor. See https://github.com/ooni/probe/issues/2121
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
package archival
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestDNSQueryIPOfType(t *testing.T) {
|
||||
type expectation struct {
|
||||
qtype dnsQueryType
|
||||
ip string
|
||||
output bool
|
||||
}
|
||||
var expectations = []expectation{{
|
||||
qtype: "A",
|
||||
ip: "8.8.8.8",
|
||||
output: true,
|
||||
}, {
|
||||
qtype: "A",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "AAAA",
|
||||
ip: "8.8.8.8",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "AAAA",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: true,
|
||||
}, {
|
||||
qtype: "ANTANI",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "ANTANI",
|
||||
ip: "8.8.8.8",
|
||||
output: false,
|
||||
}}
|
||||
for _, exp := range expectations {
|
||||
if exp.qtype.ipoftype(exp.ip) != exp.output {
|
||||
t.Fatalf("failure for %+v", exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"net/url"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -35,7 +35,7 @@ type Config struct {
|
||||
|
||||
// DialSaver is the optional saver for dialing events. If not
|
||||
// set, we will not save any dialing event.
|
||||
DialSaver *trace.Saver
|
||||
DialSaver *tracex.Saver
|
||||
|
||||
// Logger is the optional logger. If not set, there
|
||||
// will be no logging from the new dialer.
|
||||
@@ -45,7 +45,7 @@ type Config struct {
|
||||
ProxyURL *url.URL
|
||||
|
||||
// ReadWriteSaver is like DialSaver but for I/O events.
|
||||
ReadWriteSaver *trace.Saver
|
||||
ReadWriteSaver *tracex.Saver
|
||||
}
|
||||
|
||||
// New creates a new Dialer from the specified config and resolver.
|
||||
@@ -57,13 +57,13 @@ func New(config *Config, resolver model.Resolver) model.Dialer {
|
||||
modifiers := []netxlite.DialerWrapper{
|
||||
func(dialer model.Dialer) model.Dialer {
|
||||
if config.DialSaver != nil {
|
||||
dialer = &saverDialer{Dialer: dialer, Saver: config.DialSaver}
|
||||
dialer = &tracex.SaverDialer{Dialer: dialer, Saver: config.DialSaver}
|
||||
}
|
||||
return dialer
|
||||
},
|
||||
func(dialer model.Dialer) model.Dialer {
|
||||
if config.ReadWriteSaver != nil {
|
||||
dialer = &saverConnDialer{Dialer: dialer, Saver: config.ReadWriteSaver}
|
||||
dialer = &tracex.SaverConnDialer{Dialer: dialer, Saver: config.ReadWriteSaver}
|
||||
}
|
||||
return dialer
|
||||
},
|
||||
|
||||
@@ -7,12 +7,12 @@ import (
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestNewCreatesTheExpectedChain(t *testing.T) {
|
||||
saver := &trace.Saver{}
|
||||
saver := &tracex.Saver{}
|
||||
dlr := New(&Config{
|
||||
ContextByteCounting: true,
|
||||
DialSaver: saver,
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -24,12 +24,12 @@ func TestSuccess(t *testing.T) {
|
||||
ByteCounter: counter,
|
||||
CacheResolutions: true,
|
||||
ContextByteCounting: true,
|
||||
DialSaver: &trace.Saver{},
|
||||
HTTPSaver: &trace.Saver{},
|
||||
DialSaver: &tracex.Saver{},
|
||||
HTTPSaver: &tracex.Saver{},
|
||||
Logger: log.Log,
|
||||
ReadWriteSaver: &trace.Saver{},
|
||||
ResolveSaver: &trace.Saver{},
|
||||
TLSSaver: &trace.Saver{},
|
||||
ReadWriteSaver: &tracex.Saver{},
|
||||
ResolveSaver: &tracex.Saver{},
|
||||
TLSSaver: &tracex.Saver{},
|
||||
}
|
||||
txp := netx.NewHTTPTransport(config)
|
||||
client := &http.Client{Transport: txp}
|
||||
@@ -67,7 +67,7 @@ func TestSuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBogonResolutionNotBroken(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
r := netx.NewResolver(netx.Config{
|
||||
BogonIsError: true,
|
||||
DNSCache: map[string][]string{
|
||||
|
||||
@@ -33,10 +33,8 @@ import (
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -54,20 +52,20 @@ type Config struct {
|
||||
CertPool *x509.CertPool // default: use vendored gocertifi
|
||||
ContextByteCounting bool // default: no implicit byte counting
|
||||
DNSCache map[string][]string // default: cache is empty
|
||||
DialSaver *trace.Saver // default: not saving dials
|
||||
DialSaver *tracex.Saver // default: not saving dials
|
||||
Dialer model.Dialer // default: dialer.DNSDialer
|
||||
FullResolver model.Resolver // default: base resolver + goodies
|
||||
QUICDialer model.QUICDialer // default: quicdialer.DNSDialer
|
||||
HTTP3Enabled bool // default: disabled
|
||||
HTTPSaver *trace.Saver // default: not saving HTTP
|
||||
HTTPSaver *tracex.Saver // default: not saving HTTP
|
||||
Logger model.DebugLogger // default: no logging
|
||||
NoTLSVerify bool // default: perform TLS verify
|
||||
ProxyURL *url.URL // default: no proxy
|
||||
ReadWriteSaver *trace.Saver // default: not saving read/write
|
||||
ResolveSaver *trace.Saver // default: not saving resolves
|
||||
ReadWriteSaver *tracex.Saver // default: not saving read/write
|
||||
ResolveSaver *tracex.Saver // default: not saving resolves
|
||||
TLSConfig *tls.Config // default: attempt using h2
|
||||
TLSDialer model.TLSDialer // default: dialer.TLSDialer
|
||||
TLSSaver *trace.Saver // default: not saving TLS
|
||||
TLSSaver *tracex.Saver // default: not saving TLS
|
||||
}
|
||||
|
||||
type tlsHandshaker interface {
|
||||
@@ -107,7 +105,7 @@ func NewResolver(config Config) model.Resolver {
|
||||
}
|
||||
}
|
||||
if config.ResolveSaver != nil {
|
||||
r = resolver.SaverResolver{Resolver: r, Saver: config.ResolveSaver}
|
||||
r = tracex.SaverResolver{Resolver: r, Saver: config.ResolveSaver}
|
||||
}
|
||||
return &netxlite.ResolverIDNA{Resolver: r}
|
||||
}
|
||||
@@ -133,7 +131,7 @@ func NewQUICDialer(config Config) model.QUICDialer {
|
||||
}
|
||||
ql := netxlite.NewQUICListener()
|
||||
if config.ReadWriteSaver != nil {
|
||||
ql = &quicdialer.QUICListenerSaver{
|
||||
ql = &tracex.QUICListenerSaver{
|
||||
QUICListener: ql,
|
||||
Saver: config.ReadWriteSaver,
|
||||
}
|
||||
@@ -145,7 +143,7 @@ func NewQUICDialer(config Config) model.QUICDialer {
|
||||
extensions := []netxlite.QUICDialerWrapper{
|
||||
func(dialer model.QUICDialer) model.QUICDialer {
|
||||
if config.TLSSaver != nil {
|
||||
dialer = quicdialer.HandshakeSaver{Saver: config.TLSSaver, QUICDialer: dialer}
|
||||
dialer = tracex.QUICHandshakeSaver{Saver: config.TLSSaver, QUICDialer: dialer}
|
||||
}
|
||||
return dialer
|
||||
},
|
||||
@@ -164,7 +162,7 @@ func NewTLSDialer(config Config) model.TLSDialer {
|
||||
h = &netxlite.TLSHandshakerLogger{DebugLogger: config.Logger, TLSHandshaker: h}
|
||||
}
|
||||
if config.TLSSaver != nil {
|
||||
h = tlsdialer.SaverTLSHandshaker{TLSHandshaker: h, Saver: config.TLSSaver}
|
||||
h = tracex.SaverTLSHandshaker{TLSHandshaker: h, Saver: config.TLSSaver}
|
||||
}
|
||||
if config.TLSConfig == nil {
|
||||
config.TLSConfig = &tls.Config{NextProtos: []string{"h2", "http/1.1"}}
|
||||
@@ -207,11 +205,11 @@ func NewHTTPTransport(config Config) model.HTTPTransport {
|
||||
txp = &netxlite.HTTPTransportLogger{Logger: config.Logger, HTTPTransport: txp}
|
||||
}
|
||||
if config.HTTPSaver != nil {
|
||||
txp = httptransport.SaverMetadataHTTPTransport{
|
||||
txp = tracex.SaverMetadataHTTPTransport{
|
||||
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||
txp = httptransport.SaverBodyHTTPTransport{
|
||||
txp = tracex.SaverBodyHTTPTransport{
|
||||
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||
txp = httptransport.SaverTransactionHTTPTransport{
|
||||
txp = tracex.SaverTransactionHTTPTransport{
|
||||
HTTPTransport: txp, Saver: config.HTTPSaver}
|
||||
}
|
||||
return txp
|
||||
@@ -287,7 +285,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||
var txp model.DNSTransport = netxlite.NewDNSOverHTTPSTransportWithHostOverride(
|
||||
httpClient, URL, hostOverride)
|
||||
if config.ResolveSaver != nil {
|
||||
txp = resolver.SaverDNSTransport{
|
||||
txp = tracex.SaverDNSTransport{
|
||||
DNSTransport: txp,
|
||||
Saver: config.ResolveSaver,
|
||||
}
|
||||
@@ -302,7 +300,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||
var txp model.DNSTransport = netxlite.NewDNSOverUDPTransport(
|
||||
dialer, endpoint)
|
||||
if config.ResolveSaver != nil {
|
||||
txp = resolver.SaverDNSTransport{
|
||||
txp = tracex.SaverDNSTransport{
|
||||
DNSTransport: txp,
|
||||
Saver: config.ResolveSaver,
|
||||
}
|
||||
@@ -318,7 +316,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||
var txp model.DNSTransport = netxlite.NewDNSOverTLSTransport(
|
||||
tlsDialer.DialTLSContext, endpoint)
|
||||
if config.ResolveSaver != nil {
|
||||
txp = resolver.SaverDNSTransport{
|
||||
txp = tracex.SaverDNSTransport{
|
||||
DNSTransport: txp,
|
||||
Saver: config.ResolveSaver,
|
||||
}
|
||||
@@ -333,7 +331,7 @@ func NewDNSClientWithOverrides(config Config, URL, hostOverride, SNIOverride,
|
||||
var txp model.DNSTransport = netxlite.NewDNSOverTCPTransport(
|
||||
dialer.DialContext, endpoint)
|
||||
if config.ResolveSaver != nil {
|
||||
txp = resolver.SaverDNSTransport{
|
||||
txp = tracex.SaverDNSTransport{
|
||||
DNSTransport: txp,
|
||||
Saver: config.ResolveSaver,
|
||||
}
|
||||
|
||||
@@ -12,10 +12,8 @@ import (
|
||||
"github.com/apex/log"
|
||||
"github.com/ooni/probe-cli/v3/internal/bytecounter"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -120,7 +118,7 @@ func TestNewResolverWithLogging(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewResolverWithSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
r := netx.NewResolver(netx.Config{
|
||||
ResolveSaver: saver,
|
||||
})
|
||||
@@ -128,7 +126,7 @@ func TestNewResolverWithSaver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
sr, ok := ir.Resolver.(resolver.SaverResolver)
|
||||
sr, ok := ir.Resolver.(tracex.SaverResolver)
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
@@ -311,7 +309,7 @@ func TestNewTLSDialerWithLogging(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewTLSDialerWithSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
td := netx.NewTLSDialer(netx.Config{
|
||||
TLSSaver: saver,
|
||||
})
|
||||
@@ -334,7 +332,7 @@ func TestNewTLSDialerWithSaver(t *testing.T) {
|
||||
if rtd.TLSHandshaker == nil {
|
||||
t.Fatal("invalid TLSHandshaker")
|
||||
}
|
||||
sth, ok := rtd.TLSHandshaker.(tlsdialer.SaverTLSHandshaker)
|
||||
sth, ok := rtd.TLSHandshaker.(tracex.SaverTLSHandshaker)
|
||||
if !ok {
|
||||
t.Fatal("not the TLSHandshaker we expected")
|
||||
}
|
||||
@@ -502,25 +500,25 @@ func TestNewWithLogger(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewWithSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
txp := netx.NewHTTPTransport(netx.Config{
|
||||
HTTPSaver: saver,
|
||||
})
|
||||
stxptxp, ok := txp.(httptransport.SaverTransactionHTTPTransport)
|
||||
stxptxp, ok := txp.(tracex.SaverTransactionHTTPTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
if stxptxp.Saver != saver {
|
||||
t.Fatal("not the logger we expected")
|
||||
}
|
||||
sbtxp, ok := stxptxp.HTTPTransport.(httptransport.SaverBodyHTTPTransport)
|
||||
sbtxp, ok := stxptxp.HTTPTransport.(tracex.SaverBodyHTTPTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
if sbtxp.Saver != saver {
|
||||
t.Fatal("not the logger we expected")
|
||||
}
|
||||
smtxp, ok := sbtxp.HTTPTransport.(httptransport.SaverMetadataHTTPTransport)
|
||||
smtxp, ok := sbtxp.HTTPTransport.(tracex.SaverMetadataHTTPTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
@@ -625,7 +623,7 @@ func TestNewDNSClientCloudflareDoH(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDNSClientCloudflareDoHSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
dnsclient, err := netx.NewDNSClient(
|
||||
netx.Config{ResolveSaver: saver}, "doh://cloudflare")
|
||||
if err != nil {
|
||||
@@ -635,7 +633,7 @@ func TestNewDNSClientCloudflareDoHSaver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
txp, ok := r.Transport().(resolver.SaverDNSTransport)
|
||||
txp, ok := r.Transport().(tracex.SaverDNSTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
@@ -662,7 +660,7 @@ func TestNewDNSClientUDP(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDNSClientUDPDNSSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
dnsclient, err := netx.NewDNSClient(
|
||||
netx.Config{ResolveSaver: saver}, "udp://8.8.8.8:53")
|
||||
if err != nil {
|
||||
@@ -672,7 +670,7 @@ func TestNewDNSClientUDPDNSSaver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
txp, ok := r.Transport().(resolver.SaverDNSTransport)
|
||||
txp, ok := r.Transport().(tracex.SaverDNSTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
@@ -703,7 +701,7 @@ func TestNewDNSClientTCP(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDNSClientTCPDNSSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
dnsclient, err := netx.NewDNSClient(
|
||||
netx.Config{ResolveSaver: saver}, "tcp://8.8.8.8:53")
|
||||
if err != nil {
|
||||
@@ -713,7 +711,7 @@ func TestNewDNSClientTCPDNSSaver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
txp, ok := r.Transport().(resolver.SaverDNSTransport)
|
||||
txp, ok := r.Transport().(tracex.SaverDNSTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
@@ -748,7 +746,7 @@ func TestNewDNSClientDoT(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNewDNSClientDoTDNSSaver(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(tracex.Saver)
|
||||
dnsclient, err := netx.NewDNSClient(
|
||||
netx.Config{ResolveSaver: saver}, "dot://8.8.8.8:53")
|
||||
if err != nil {
|
||||
@@ -758,7 +756,7 @@ func TestNewDNSClientDoTDNSSaver(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("not the resolver we expected")
|
||||
}
|
||||
txp, ok := r.Transport().(resolver.SaverDNSTransport)
|
||||
txp, ok := r.Transport().(tracex.SaverDNSTransport)
|
||||
if !ok {
|
||||
t.Fatal("not the transport we expected")
|
||||
}
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
package quicdialer
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// HandshakeSaver saves events occurring during the handshake
|
||||
type HandshakeSaver struct {
|
||||
Saver *trace.Saver
|
||||
model.QUICDialer
|
||||
}
|
||||
|
||||
// DialContext implements ContextDialer.DialContext
|
||||
func (h HandshakeSaver) DialContext(ctx context.Context, network string,
|
||||
host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||
start := time.Now()
|
||||
// TODO(bassosimone): in the future we probably want to also save
|
||||
// information about what versions we're willing to accept.
|
||||
h.Saver.Write(trace.Event{
|
||||
Address: host,
|
||||
Name: "quic_handshake_start",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
Proto: network,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
Time: start,
|
||||
})
|
||||
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||
stop := time.Now()
|
||||
if err != nil {
|
||||
h.Saver.Write(trace.Event{
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
Name: "quic_handshake_done",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
Time: stop,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
state := connectionState(sess)
|
||||
h.Saver.Write(trace.Event{
|
||||
Duration: stop.Sub(start),
|
||||
Name: "quic_handshake_done",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSPeerCerts: trace.PeerCerts(state, err),
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
})
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// connectionState returns the ConnectionState of a QUIC Session.
|
||||
func connectionState(sess quic.EarlyConnection) tls.ConnectionState {
|
||||
return sess.ConnectionState().TLS.ConnectionState
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package quicdialer
|
||||
|
||||
import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// QUICListenerSaver is a QUICListener that also implements saving events.
|
||||
type QUICListenerSaver struct {
|
||||
// QUICListener is the underlying QUICListener.
|
||||
model.QUICListener
|
||||
|
||||
// Saver is the underlying Saver.
|
||||
Saver *trace.Saver
|
||||
}
|
||||
|
||||
// Listen implements QUICListener.Listen.
|
||||
func (qls *QUICListenerSaver) Listen(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
pconn, err := qls.QUICListener.Listen(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &saverUDPConn{
|
||||
UDPLikeConn: pconn,
|
||||
saver: qls.Saver,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type saverUDPConn struct {
|
||||
model.UDPLikeConn
|
||||
saver *trace.Saver
|
||||
}
|
||||
|
||||
var _ model.UDPLikeConn = &saverUDPConn{}
|
||||
|
||||
func (c *saverUDPConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
start := time.Now()
|
||||
count, err := c.UDPLikeConn.WriteTo(p, addr)
|
||||
stop := time.Now()
|
||||
c.saver.Write(trace.Event{
|
||||
Address: addr.String(),
|
||||
Data: p[:count],
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: count,
|
||||
Name: netxlite.WriteToOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (c *saverUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
start := time.Now()
|
||||
n, addr, err := c.UDPLikeConn.ReadFrom(b)
|
||||
stop := time.Now()
|
||||
var data []byte
|
||||
if n > 0 {
|
||||
data = b[:n]
|
||||
}
|
||||
c.saver.Write(trace.Event{
|
||||
Address: c.safeAddrString(addr),
|
||||
Data: data,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: n,
|
||||
Name: netxlite.ReadFromOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
func (c *saverUDPConn) safeAddrString(addr net.Addr) (out string) {
|
||||
if addr != nil {
|
||||
out = addr.String()
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package quicdialer_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||
)
|
||||
|
||||
func TestQUICListenerSaverCannotListen(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
qls := &quicdialer.QUICListenerSaver{
|
||||
QUICListener: &mocks.QUICListener{
|
||||
MockListen: func(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
return nil, expected
|
||||
},
|
||||
},
|
||||
Saver: &trace.Saver{},
|
||||
}
|
||||
pconn, err := qls.Listen(&net.UDPAddr{
|
||||
IP: []byte{},
|
||||
Port: 8080,
|
||||
Zone: "",
|
||||
})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if pconn != nil {
|
||||
t.Fatal("expected nil pconn here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||
// This is the most common use case for collecting reads, writes
|
||||
tlsConf := &tls.Config{
|
||||
NextProtos: []string{"h3"},
|
||||
ServerName: quictesting.Domain,
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
systemdialer := &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &quicdialer.QUICListenerSaver{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
Saver: saver,
|
||||
},
|
||||
}
|
||||
_, err := systemdialer.DialContext(context.Background(), "udp",
|
||||
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ev := saver.Read()
|
||||
if len(ev) < 2 {
|
||||
t.Fatal("unexpected number of events")
|
||||
}
|
||||
last := len(ev) - 1
|
||||
for idx := 1; idx < last; idx++ {
|
||||
if ev[idx].Data == nil {
|
||||
t.Fatal("unexpected Data")
|
||||
}
|
||||
if ev[idx].Duration <= 0 {
|
||||
t.Fatal("unexpected Duration")
|
||||
}
|
||||
if ev[idx].Err != nil {
|
||||
t.Fatal("unexpected Err")
|
||||
}
|
||||
if ev[idx].NumBytes <= 0 {
|
||||
t.Fatal("unexpected NumBytes")
|
||||
}
|
||||
switch ev[idx].Name {
|
||||
case netxlite.ReadFromOperation, netxlite.WriteToOperation:
|
||||
default:
|
||||
t.Fatal("unexpected Name")
|
||||
}
|
||||
if ev[idx].Time.Before(ev[idx-1].Time) {
|
||||
t.Fatal("unexpected Time", ev[idx].Time, ev[idx-1].Time)
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
-12
@@ -1,7 +1,4 @@
|
||||
// Package archival contains data formats used for archival.
|
||||
//
|
||||
// See https://github.com/ooni/spec.
|
||||
package archival
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"crypto/x509"
|
||||
@@ -14,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/geolocate"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -47,7 +43,7 @@ var (
|
||||
)
|
||||
|
||||
// NewTCPConnectList creates a new TCPConnectList
|
||||
func NewTCPConnectList(begin time.Time, events []trace.Event) []TCPConnectEntry {
|
||||
func NewTCPConnectList(begin time.Time, events []Event) []TCPConnectEntry {
|
||||
var out []TCPConnectEntry
|
||||
for _, event := range events {
|
||||
if event.Name != netxlite.ConnectOperation {
|
||||
@@ -129,7 +125,7 @@ func addheaders(
|
||||
}
|
||||
|
||||
// NewRequestList returns the list for "requests"
|
||||
func NewRequestList(begin time.Time, events []trace.Event) []RequestEntry {
|
||||
func NewRequestList(begin time.Time, events []Event) []RequestEntry {
|
||||
// OONI wants the last request to appear first
|
||||
var out []RequestEntry
|
||||
tmp := newRequestList(begin, events)
|
||||
@@ -139,7 +135,7 @@ func NewRequestList(begin time.Time, events []trace.Event) []RequestEntry {
|
||||
return out
|
||||
}
|
||||
|
||||
func newRequestList(begin time.Time, events []trace.Event) []RequestEntry {
|
||||
func newRequestList(begin time.Time, events []Event) []RequestEntry {
|
||||
var (
|
||||
out []RequestEntry
|
||||
entry RequestEntry
|
||||
@@ -179,7 +175,7 @@ func newRequestList(begin time.Time, events []trace.Event) []RequestEntry {
|
||||
type dnsQueryType string
|
||||
|
||||
// NewDNSQueriesList returns a list of DNS queries.
|
||||
func NewDNSQueriesList(begin time.Time, events []trace.Event) []DNSQueryEntry {
|
||||
func NewDNSQueriesList(begin time.Time, events []Event) []DNSQueryEntry {
|
||||
// TODO(bassosimone): add support for CNAME lookups.
|
||||
var out []DNSQueryEntry
|
||||
for _, ev := range events {
|
||||
@@ -234,7 +230,7 @@ func (qtype dnsQueryType) makeanswerentry(addr string) DNSAnswerEntry {
|
||||
return answer
|
||||
}
|
||||
|
||||
func (qtype dnsQueryType) makequeryentry(begin time.Time, ev trace.Event) DNSQueryEntry {
|
||||
func (qtype dnsQueryType) makequeryentry(begin time.Time, ev Event) DNSQueryEntry {
|
||||
return DNSQueryEntry{
|
||||
Engine: ev.Proto,
|
||||
Failure: NewFailure(ev.Err),
|
||||
@@ -246,7 +242,7 @@ func (qtype dnsQueryType) makequeryentry(begin time.Time, ev trace.Event) DNSQue
|
||||
}
|
||||
|
||||
// NewNetworkEventsList returns a list of DNS queries.
|
||||
func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent {
|
||||
func NewNetworkEventsList(begin time.Time, events []Event) []NetworkEvent {
|
||||
var out []NetworkEvent
|
||||
for _, ev := range events {
|
||||
if ev.Name == netxlite.ConnectOperation {
|
||||
@@ -307,7 +303,7 @@ func NewNetworkEventsList(begin time.Time, events []trace.Event) []NetworkEvent
|
||||
}
|
||||
|
||||
// NewTLSHandshakesList creates a new TLSHandshakesList
|
||||
func NewTLSHandshakesList(begin time.Time, events []trace.Event) []TLSHandshake {
|
||||
func NewTLSHandshakesList(begin time.Time, events []Event) []TLSHandshake {
|
||||
var out []TLSHandshake
|
||||
for _, ev := range events {
|
||||
if !strings.Contains(ev.Name, "_handshake_done") {
|
||||
+112
-76
@@ -1,4 +1,4 @@
|
||||
package archival_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -12,21 +12,57 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/archival"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestDNSQueryIPOfType(t *testing.T) {
|
||||
type expectation struct {
|
||||
qtype dnsQueryType
|
||||
ip string
|
||||
output bool
|
||||
}
|
||||
var expectations = []expectation{{
|
||||
qtype: "A",
|
||||
ip: "8.8.8.8",
|
||||
output: true,
|
||||
}, {
|
||||
qtype: "A",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "AAAA",
|
||||
ip: "8.8.8.8",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "AAAA",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: true,
|
||||
}, {
|
||||
qtype: "ANTANI",
|
||||
ip: "2a00:1450:4002:801::2004",
|
||||
output: false,
|
||||
}, {
|
||||
qtype: "ANTANI",
|
||||
ip: "8.8.8.8",
|
||||
output: false,
|
||||
}}
|
||||
for _, exp := range expectations {
|
||||
if exp.qtype.ipoftype(exp.ip) != exp.output {
|
||||
t.Fatalf("failure for %+v", exp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewTCPConnectList(t *testing.T) {
|
||||
begin := time.Now()
|
||||
type args struct {
|
||||
begin time.Time
|
||||
events []trace.Event
|
||||
events []Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []archival.TCPConnectEntry
|
||||
want []TCPConnectEntry
|
||||
}{{
|
||||
name: "empty run",
|
||||
args: args{
|
||||
@@ -38,7 +74,7 @@ func TestNewTCPConnectList(t *testing.T) {
|
||||
name: "realistic run",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
||||
Hostname: "dns.google.com",
|
||||
Name: "resolve_done",
|
||||
@@ -64,18 +100,18 @@ func TestNewTCPConnectList(t *testing.T) {
|
||||
Time: begin.Add(180 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.TCPConnectEntry{{
|
||||
want: []TCPConnectEntry{{
|
||||
IP: "8.8.8.8",
|
||||
Port: 853,
|
||||
Status: archival.TCPConnectStatus{
|
||||
Status: TCPConnectStatus{
|
||||
Success: true,
|
||||
},
|
||||
T: 0.13,
|
||||
}, {
|
||||
IP: "8.8.4.4",
|
||||
Port: 53,
|
||||
Status: archival.TCPConnectStatus{
|
||||
Failure: archival.NewFailure(io.EOF),
|
||||
Status: TCPConnectStatus{
|
||||
Failure: NewFailure(io.EOF),
|
||||
Success: false,
|
||||
},
|
||||
T: 0.18,
|
||||
@@ -83,7 +119,7 @@ func TestNewTCPConnectList(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := archival.NewTCPConnectList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := NewTCPConnectList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Error(cmp.Diff(got, tt.want))
|
||||
}
|
||||
})
|
||||
@@ -94,12 +130,12 @@ func TestNewRequestList(t *testing.T) {
|
||||
begin := time.Now()
|
||||
type args struct {
|
||||
begin time.Time
|
||||
events []trace.Event
|
||||
events []Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []archival.RequestEntry
|
||||
want []RequestEntry
|
||||
}{{
|
||||
name: "empty run",
|
||||
args: args{
|
||||
@@ -111,7 +147,7 @@ func TestNewRequestList(t *testing.T) {
|
||||
name: "realistic run",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Name: "http_transaction_start",
|
||||
Time: begin.Add(10 * time.Millisecond),
|
||||
}, {
|
||||
@@ -152,16 +188,16 @@ func TestNewRequestList(t *testing.T) {
|
||||
Err: io.EOF,
|
||||
}},
|
||||
},
|
||||
want: []archival.RequestEntry{{
|
||||
Failure: archival.NewFailure(io.EOF),
|
||||
Request: archival.HTTPRequest{
|
||||
HeadersList: []archival.HTTPHeader{{
|
||||
want: []RequestEntry{{
|
||||
Failure: NewFailure(io.EOF),
|
||||
Request: HTTPRequest{
|
||||
HeadersList: []HTTPHeader{{
|
||||
Key: "User-Agent",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "miniooni/0.1.0-dev",
|
||||
},
|
||||
}},
|
||||
Headers: map[string]archival.MaybeBinaryValue{
|
||||
Headers: map[string]MaybeBinaryValue{
|
||||
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
||||
},
|
||||
Method: "GET",
|
||||
@@ -169,34 +205,34 @@ func TestNewRequestList(t *testing.T) {
|
||||
},
|
||||
T: 0.02,
|
||||
}, {
|
||||
Request: archival.HTTPRequest{
|
||||
Body: archival.MaybeBinaryValue{
|
||||
Request: HTTPRequest{
|
||||
Body: MaybeBinaryValue{
|
||||
Value: "deadbeef",
|
||||
},
|
||||
HeadersList: []archival.HTTPHeader{{
|
||||
HeadersList: []HTTPHeader{{
|
||||
Key: "User-Agent",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "miniooni/0.1.0-dev",
|
||||
},
|
||||
}},
|
||||
Headers: map[string]archival.MaybeBinaryValue{
|
||||
Headers: map[string]MaybeBinaryValue{
|
||||
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
||||
},
|
||||
Method: "POST",
|
||||
URL: "https://www.example.com/submit",
|
||||
},
|
||||
Response: archival.HTTPResponse{
|
||||
Body: archival.MaybeBinaryValue{
|
||||
Response: HTTPResponse{
|
||||
Body: MaybeBinaryValue{
|
||||
Value: "{}",
|
||||
},
|
||||
Code: 200,
|
||||
HeadersList: []archival.HTTPHeader{{
|
||||
HeadersList: []HTTPHeader{{
|
||||
Key: "Server",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "miniooni/0.1.0-dev",
|
||||
},
|
||||
}},
|
||||
Headers: map[string]archival.MaybeBinaryValue{
|
||||
Headers: map[string]MaybeBinaryValue{
|
||||
"Server": {Value: "miniooni/0.1.0-dev"},
|
||||
},
|
||||
Locations: nil,
|
||||
@@ -209,7 +245,7 @@ func TestNewRequestList(t *testing.T) {
|
||||
name: "run with redirect and headers to sort",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Name: "http_transaction_start",
|
||||
Time: begin.Add(10 * time.Millisecond),
|
||||
}, {
|
||||
@@ -230,39 +266,39 @@ func TestNewRequestList(t *testing.T) {
|
||||
Name: "http_transaction_done",
|
||||
}},
|
||||
},
|
||||
want: []archival.RequestEntry{{
|
||||
Request: archival.HTTPRequest{
|
||||
HeadersList: []archival.HTTPHeader{{
|
||||
want: []RequestEntry{{
|
||||
Request: HTTPRequest{
|
||||
HeadersList: []HTTPHeader{{
|
||||
Key: "User-Agent",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "miniooni/0.1.0-dev",
|
||||
},
|
||||
}},
|
||||
Headers: map[string]archival.MaybeBinaryValue{
|
||||
Headers: map[string]MaybeBinaryValue{
|
||||
"User-Agent": {Value: "miniooni/0.1.0-dev"},
|
||||
},
|
||||
Method: "GET",
|
||||
URL: "https://www.example.com/",
|
||||
},
|
||||
Response: archival.HTTPResponse{
|
||||
Response: HTTPResponse{
|
||||
Code: 302,
|
||||
HeadersList: []archival.HTTPHeader{{
|
||||
HeadersList: []HTTPHeader{{
|
||||
Key: "Location",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "https://x.example.com",
|
||||
},
|
||||
}, {
|
||||
Key: "Location",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "https://y.example.com",
|
||||
},
|
||||
}, {
|
||||
Key: "Server",
|
||||
Value: archival.MaybeBinaryValue{
|
||||
Value: MaybeBinaryValue{
|
||||
Value: "miniooni/0.1.0-dev",
|
||||
},
|
||||
}},
|
||||
Headers: map[string]archival.MaybeBinaryValue{
|
||||
Headers: map[string]MaybeBinaryValue{
|
||||
"Server": {Value: "miniooni/0.1.0-dev"},
|
||||
"Location": {Value: "https://x.example.com"},
|
||||
},
|
||||
@@ -275,7 +311,7 @@ func TestNewRequestList(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := archival.NewRequestList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := NewRequestList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Error(cmp.Diff(got, tt.want))
|
||||
}
|
||||
})
|
||||
@@ -286,12 +322,12 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
begin := time.Now()
|
||||
type args struct {
|
||||
begin time.Time
|
||||
events []trace.Event
|
||||
events []Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []archival.DNSQueryEntry
|
||||
want []DNSQueryEntry
|
||||
}{{
|
||||
name: "empty run",
|
||||
args: args{
|
||||
@@ -303,7 +339,7 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
name: "realistic run",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Address: "1.1.1.1:853",
|
||||
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
||||
Hostname: "dns.google.com",
|
||||
@@ -325,8 +361,8 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
Time: begin.Add(180 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.DNSQueryEntry{{
|
||||
Answers: []archival.DNSAnswerEntry{{
|
||||
want: []DNSQueryEntry{{
|
||||
Answers: []DNSAnswerEntry{{
|
||||
ASN: 15169,
|
||||
ASOrgName: "Google LLC",
|
||||
AnswerType: "A",
|
||||
@@ -347,15 +383,15 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
name: "run with IPv6 results",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Addresses: []string{"2001:4860:4860::8888"},
|
||||
Hostname: "dns.google.com",
|
||||
Name: "resolve_done",
|
||||
Time: begin.Add(200 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.DNSQueryEntry{{
|
||||
Answers: []archival.DNSAnswerEntry{{
|
||||
want: []DNSQueryEntry{{
|
||||
Answers: []DNSAnswerEntry{{
|
||||
ASN: 15169,
|
||||
ASOrgName: "Google LLC",
|
||||
AnswerType: "AAAA",
|
||||
@@ -369,23 +405,23 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
name: "run with errors",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Err: &netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError},
|
||||
Hostname: "dns.google.com",
|
||||
Name: "resolve_done",
|
||||
Time: begin.Add(200 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.DNSQueryEntry{{
|
||||
want: []DNSQueryEntry{{
|
||||
Answers: nil,
|
||||
Failure: archival.NewFailure(
|
||||
Failure: NewFailure(
|
||||
&netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError}),
|
||||
Hostname: "dns.google.com",
|
||||
QueryType: "A",
|
||||
T: 0.2,
|
||||
}, {
|
||||
Answers: nil,
|
||||
Failure: archival.NewFailure(
|
||||
Failure: NewFailure(
|
||||
&netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError}),
|
||||
Hostname: "dns.google.com",
|
||||
QueryType: "AAAA",
|
||||
@@ -394,7 +430,7 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := archival.NewDNSQueriesList(tt.args.begin, tt.args.events)
|
||||
got := NewDNSQueriesList(tt.args.begin, tt.args.events)
|
||||
if diff := cmp.Diff(tt.want, got); diff != "" {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
@@ -406,12 +442,12 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||
begin := time.Now()
|
||||
type args struct {
|
||||
begin time.Time
|
||||
events []trace.Event
|
||||
events []Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []archival.NetworkEvent
|
||||
want []NetworkEvent
|
||||
}{{
|
||||
name: "empty run",
|
||||
args: args{
|
||||
@@ -423,7 +459,7 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||
name: "realistic run",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Name: netxlite.ConnectOperation,
|
||||
Address: "8.8.8.8:853",
|
||||
Err: io.EOF,
|
||||
@@ -457,43 +493,43 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||
Time: begin.Add(17 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.NetworkEvent{{
|
||||
want: []NetworkEvent{{
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(io.EOF),
|
||||
Failure: NewFailure(io.EOF),
|
||||
Operation: netxlite.ConnectOperation,
|
||||
Proto: "tcp",
|
||||
T: 0.007,
|
||||
}, {
|
||||
Failure: archival.NewFailure(context.Canceled),
|
||||
Failure: NewFailure(context.Canceled),
|
||||
NumBytes: 7117,
|
||||
Operation: netxlite.ReadOperation,
|
||||
T: 0.011,
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(context.Canceled),
|
||||
Failure: NewFailure(context.Canceled),
|
||||
NumBytes: 7117,
|
||||
Operation: netxlite.ReadFromOperation,
|
||||
T: 0.011,
|
||||
}, {
|
||||
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
||||
Failure: NewFailure(websocket.ErrBadHandshake),
|
||||
NumBytes: 4114,
|
||||
Operation: netxlite.WriteOperation,
|
||||
T: 0.014,
|
||||
}, {
|
||||
Address: "8.8.8.8:853",
|
||||
Failure: archival.NewFailure(websocket.ErrBadHandshake),
|
||||
Failure: NewFailure(websocket.ErrBadHandshake),
|
||||
NumBytes: 4114,
|
||||
Operation: netxlite.WriteToOperation,
|
||||
T: 0.014,
|
||||
}, {
|
||||
Failure: archival.NewFailure(websocket.ErrReadLimit),
|
||||
Failure: NewFailure(websocket.ErrReadLimit),
|
||||
Operation: netxlite.CloseOperation,
|
||||
T: 0.017,
|
||||
}},
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := archival.NewNetworkEventsList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := NewNetworkEventsList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Error(cmp.Diff(got, tt.want))
|
||||
}
|
||||
})
|
||||
@@ -504,12 +540,12 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||
begin := time.Now()
|
||||
type args struct {
|
||||
begin time.Time
|
||||
events []trace.Event
|
||||
events []Event
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want []archival.TLSHandshake
|
||||
want []TLSHandshake
|
||||
}{{
|
||||
name: "empty run",
|
||||
args: args{
|
||||
@@ -521,7 +557,7 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||
name: "realistic run",
|
||||
args: args{
|
||||
begin: begin,
|
||||
events: []trace.Event{{
|
||||
events: []Event{{
|
||||
Name: netxlite.CloseOperation,
|
||||
Err: websocket.ErrReadLimit,
|
||||
Time: begin.Add(17 * time.Millisecond),
|
||||
@@ -542,13 +578,13 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||
Time: begin.Add(55 * time.Millisecond),
|
||||
}},
|
||||
},
|
||||
want: []archival.TLSHandshake{{
|
||||
want: []TLSHandshake{{
|
||||
Address: "131.252.210.176:443",
|
||||
CipherSuite: "SUITE",
|
||||
Failure: archival.NewFailure(io.EOF),
|
||||
Failure: NewFailure(io.EOF),
|
||||
NegotiatedProtocol: "h2",
|
||||
NoTLSVerify: false,
|
||||
PeerCertificates: []archival.MaybeBinaryValue{{
|
||||
PeerCertificates: []MaybeBinaryValue{{
|
||||
Value: "deadbeef",
|
||||
}, {
|
||||
Value: "abad1dea",
|
||||
@@ -560,7 +596,7 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := archival.NewTLSHandshakesList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
if got := NewTLSHandshakesList(tt.args.begin, tt.args.events); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Error(cmp.Diff(got, tt.want))
|
||||
}
|
||||
})
|
||||
@@ -620,7 +656,7 @@ func TestNewFailure(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := archival.NewFailure(tt.args.err)
|
||||
got := NewFailure(tt.args.err)
|
||||
if tt.want == nil && got == nil {
|
||||
return
|
||||
}
|
||||
@@ -689,7 +725,7 @@ func TestNewFailedOperation(t *testing.T) {
|
||||
}}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := archival.NewFailedOperation(tt.args.err)
|
||||
got := NewFailedOperation(tt.args.err)
|
||||
if got == nil && tt.want == nil {
|
||||
return
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
package dialer
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// saverDialer saves events occurring during the dial
|
||||
type saverDialer struct {
|
||||
// SaverDialer saves events occurring during the dial
|
||||
type SaverDialer struct {
|
||||
model.Dialer
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// DialContext implements Dialer.DialContext
|
||||
func (d *saverDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
func (d *SaverDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
start := time.Now()
|
||||
conn, err := d.Dialer.DialContext(ctx, network, address)
|
||||
stop := time.Now()
|
||||
d.Saver.Write(trace.Event{
|
||||
d.Saver.Write(Event{
|
||||
Address: address,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
@@ -32,15 +31,15 @@ func (d *saverDialer) DialContext(ctx context.Context, network, address string)
|
||||
return conn, err
|
||||
}
|
||||
|
||||
// saverConnDialer wraps the returned connection such that we
|
||||
// SaverConnDialer wraps the returned connection such that we
|
||||
// collect all the read/write events that occur.
|
||||
type saverConnDialer struct {
|
||||
type SaverConnDialer struct {
|
||||
model.Dialer
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// DialContext implements Dialer.DialContext
|
||||
func (d *saverConnDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
func (d *SaverConnDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
conn, err := d.Dialer.DialContext(ctx, network, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -50,14 +49,14 @@ func (d *saverConnDialer) DialContext(ctx context.Context, network, address stri
|
||||
|
||||
type saverConn struct {
|
||||
net.Conn
|
||||
saver *trace.Saver
|
||||
saver *Saver
|
||||
}
|
||||
|
||||
func (c *saverConn) Read(p []byte) (int, error) {
|
||||
start := time.Now()
|
||||
count, err := c.Conn.Read(p)
|
||||
stop := time.Now()
|
||||
c.saver.Write(trace.Event{
|
||||
c.saver.Write(Event{
|
||||
Data: p[:count],
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
@@ -72,7 +71,7 @@ func (c *saverConn) Write(p []byte) (int, error) {
|
||||
start := time.Now()
|
||||
count, err := c.Conn.Write(p)
|
||||
stop := time.Now()
|
||||
c.saver.Write(trace.Event{
|
||||
c.saver.Write(Event{
|
||||
Data: p[:count],
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
@@ -83,6 +82,6 @@ func (c *saverConn) Write(p []byte) (int, error) {
|
||||
return count, err
|
||||
}
|
||||
|
||||
var _ model.Dialer = &saverDialer{}
|
||||
var _ model.Dialer = &saverConnDialer{}
|
||||
var _ model.Dialer = &SaverDialer{}
|
||||
var _ model.Dialer = &SaverConnDialer{}
|
||||
var _ net.Conn = &saverConn{}
|
||||
+11
-12
@@ -1,4 +1,4 @@
|
||||
package dialer
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,15 +8,14 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
func TestSaverDialerFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
dlr := &saverDialer{
|
||||
saver := &Saver{}
|
||||
dlr := &SaverDialer{
|
||||
Dialer: &mocks.Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return nil, expected
|
||||
@@ -57,8 +56,8 @@ func TestSaverDialerFailure(t *testing.T) {
|
||||
|
||||
func TestSaverConnDialerFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
dlr := &saverConnDialer{
|
||||
saver := &Saver{}
|
||||
dlr := &SaverConnDialer{
|
||||
Dialer: &mocks.Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return nil, expected
|
||||
@@ -76,9 +75,9 @@ func TestSaverConnDialerFailure(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSaverConnDialerSuccess(t *testing.T) {
|
||||
saver := &trace.Saver{}
|
||||
dlr := &saverConnDialer{
|
||||
Dialer: &saverDialer{
|
||||
saver := &Saver{}
|
||||
dlr := &SaverConnDialer{
|
||||
Dialer: &SaverDialer{
|
||||
Dialer: &mocks.Dialer{
|
||||
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
|
||||
return &mocks.Conn{
|
||||
@@ -126,14 +125,14 @@ func TestSaverConnDialerSuccess(t *testing.T) {
|
||||
saverCheckWriteEvent(t, &events[2])
|
||||
}
|
||||
|
||||
func saverCheckConnectEvent(t *testing.T, ev *trace.Event) {
|
||||
func saverCheckConnectEvent(t *testing.T, ev *Event) {
|
||||
// TODO(bassosimone): implement
|
||||
}
|
||||
|
||||
func saverCheckReadEvent(t *testing.T, ev *trace.Event) {
|
||||
func saverCheckReadEvent(t *testing.T, ev *Event) {
|
||||
// TODO(bassosimone): implement
|
||||
}
|
||||
|
||||
func saverCheckWriteEvent(t *testing.T, ev *trace.Event) {
|
||||
func saverCheckWriteEvent(t *testing.T, ev *Event) {
|
||||
// TODO(bassosimone): implement
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
// Package tracex contains code to perform measurements using tracing.
|
||||
package tracex
|
||||
@@ -1,4 +1,4 @@
|
||||
package trace
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
@@ -1,4 +1,4 @@
|
||||
package httptransport
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -16,12 +15,12 @@ import (
|
||||
// events related to HTTP request and response metadata
|
||||
type SaverMetadataHTTPTransport struct {
|
||||
model.HTTPTransport
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// RoundTrip implements RoundTripper.RoundTrip
|
||||
func (txp SaverMetadataHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
HTTPHeaders: txp.CloneHeaders(req),
|
||||
HTTPMethod: req.Method,
|
||||
HTTPURL: req.URL.String(),
|
||||
@@ -33,7 +32,7 @@ func (txp SaverMetadataHTTPTransport) RoundTrip(req *http.Request) (*http.Respon
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
HTTPHeaders: resp.Header,
|
||||
HTTPStatusCode: resp.StatusCode,
|
||||
Name: "http_response_metadata",
|
||||
@@ -59,17 +58,17 @@ func (txp SaverMetadataHTTPTransport) CloneHeaders(req *http.Request) http.Heade
|
||||
// events related to the HTTP transaction
|
||||
type SaverTransactionHTTPTransport struct {
|
||||
model.HTTPTransport
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// RoundTrip implements RoundTripper.RoundTrip
|
||||
func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
Name: "http_transaction_start",
|
||||
Time: time.Now(),
|
||||
})
|
||||
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
Err: err,
|
||||
Name: "http_transaction_done",
|
||||
Time: time.Now(),
|
||||
@@ -81,7 +80,7 @@ func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Res
|
||||
// body events occurring during the round trip
|
||||
type SaverBodyHTTPTransport struct {
|
||||
model.HTTPTransport
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
SnapshotSize int
|
||||
}
|
||||
|
||||
@@ -98,7 +97,7 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
|
||||
return nil, err
|
||||
}
|
||||
req.Body = saverCompose(data, req.Body)
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
DataIsTruncated: len(data) >= snapsize,
|
||||
Data: data,
|
||||
Name: "http_request_body_snapshot",
|
||||
@@ -115,7 +114,7 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
|
||||
return nil, err
|
||||
}
|
||||
resp.Body = saverCompose(data, resp.Body)
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
DataIsTruncated: len(data) >= snapsize,
|
||||
Data: data,
|
||||
Name: "http_response_body_snapshot",
|
||||
+19
-21
@@ -1,4 +1,4 @@
|
||||
package httptransport_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -11,8 +11,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/httptransport"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -21,8 +19,8 @@ func TestSaverMetadataSuccess(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverMetadataHTTPTransport{
|
||||
saver := &Saver{}
|
||||
txp := SaverMetadataHTTPTransport{
|
||||
HTTPTransport: netxlite.NewHTTPTransportStdlib(model.DiscardLogger),
|
||||
Saver: saver,
|
||||
}
|
||||
@@ -75,8 +73,8 @@ func TestSaverMetadataSuccess(t *testing.T) {
|
||||
|
||||
func TestSaverMetadataFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverMetadataHTTPTransport{
|
||||
saver := &Saver{}
|
||||
txp := SaverMetadataHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
@@ -119,8 +117,8 @@ func TestSaverTransactionSuccess(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverTransactionHTTPTransport{
|
||||
saver := &Saver{}
|
||||
txp := SaverTransactionHTTPTransport{
|
||||
HTTPTransport: netxlite.NewHTTPTransportStdlib(model.DiscardLogger),
|
||||
Saver: saver,
|
||||
}
|
||||
@@ -160,8 +158,8 @@ func TestSaverTransactionSuccess(t *testing.T) {
|
||||
|
||||
func TestSaverTransactionFailure(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
saver := &trace.Saver{}
|
||||
txp := httptransport.SaverTransactionHTTPTransport{
|
||||
saver := &Saver{}
|
||||
txp := SaverTransactionHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
@@ -200,8 +198,8 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSaverBodySuccess(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
saver := new(Saver)
|
||||
txp := SaverBodyHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
data, err := netxlite.ReadAllContext(context.Background(), req.Body)
|
||||
@@ -271,8 +269,8 @@ func TestSaverBodySuccess(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSaverBodyRequestReadError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
saver := new(Saver)
|
||||
txp := SaverBodyHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
panic("should not be called")
|
||||
@@ -301,9 +299,9 @@ func TestSaverBodyRequestReadError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSaverBodyRoundTripError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(Saver)
|
||||
expected := errors.New("mocked error")
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
txp := SaverBodyHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Err: expected,
|
||||
},
|
||||
@@ -341,9 +339,9 @@ func TestSaverBodyRoundTripError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSaverBodyResponseReadError(t *testing.T) {
|
||||
saver := new(trace.Saver)
|
||||
saver := new(Saver)
|
||||
expected := errors.New("mocked error")
|
||||
txp := httptransport.SaverBodyHTTPTransport{
|
||||
txp := SaverBodyHTTPTransport{
|
||||
HTTPTransport: FakeTransport{
|
||||
Func: func(req *http.Request) (*http.Response, error) {
|
||||
return &http.Response{
|
||||
@@ -396,7 +394,7 @@ func TestCloneHeaders(t *testing.T) {
|
||||
},
|
||||
Header: http.Header{},
|
||||
}
|
||||
txp := httptransport.SaverMetadataHTTPTransport{}
|
||||
txp := SaverMetadataHTTPTransport{}
|
||||
header := txp.CloneHeaders(req)
|
||||
if header.Get("Host") != "www.example.com" {
|
||||
t.Fatal("did not set Host header correctly")
|
||||
@@ -411,7 +409,7 @@ func TestCloneHeaders(t *testing.T) {
|
||||
},
|
||||
Header: http.Header{},
|
||||
}
|
||||
txp := httptransport.SaverMetadataHTTPTransport{}
|
||||
txp := SaverMetadataHTTPTransport{}
|
||||
header := txp.CloneHeaders(req)
|
||||
if header.Get("Host") != "www.kernel.org" {
|
||||
t.Fatal("did not set Host header correctly")
|
||||
@@ -0,0 +1,139 @@
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
// QUICHandshakeSaver saves events occurring during the handshake
|
||||
type QUICHandshakeSaver struct {
|
||||
Saver *Saver
|
||||
model.QUICDialer
|
||||
}
|
||||
|
||||
// DialContext implements ContextDialer.DialContext
|
||||
func (h QUICHandshakeSaver) DialContext(ctx context.Context, network string,
|
||||
host string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) {
|
||||
start := time.Now()
|
||||
// TODO(bassosimone): in the future we probably want to also save
|
||||
// information about what versions we're willing to accept.
|
||||
h.Saver.Write(Event{
|
||||
Address: host,
|
||||
Name: "quic_handshake_start",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
Proto: network,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
Time: start,
|
||||
})
|
||||
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||
stop := time.Now()
|
||||
if err != nil {
|
||||
h.Saver.Write(Event{
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
Name: "quic_handshake_done",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
Time: stop,
|
||||
})
|
||||
return nil, err
|
||||
}
|
||||
state := quicConnectionState(sess)
|
||||
h.Saver.Write(Event{
|
||||
Duration: stop.Sub(start),
|
||||
Name: "quic_handshake_done",
|
||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: tlsCfg.NextProtos,
|
||||
TLSPeerCerts: PeerCerts(state, err),
|
||||
TLSServerName: tlsCfg.ServerName,
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
})
|
||||
return sess, nil
|
||||
}
|
||||
|
||||
// quicConnectionState returns the ConnectionState of a QUIC Session.
|
||||
func quicConnectionState(sess quic.EarlyConnection) tls.ConnectionState {
|
||||
return sess.ConnectionState().TLS.ConnectionState
|
||||
}
|
||||
|
||||
// QUICListenerSaver is a QUICListener that also implements saving events.
|
||||
type QUICListenerSaver struct {
|
||||
// QUICListener is the underlying QUICListener.
|
||||
model.QUICListener
|
||||
|
||||
// Saver is the underlying Saver.
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// Listen implements QUICListener.Listen.
|
||||
func (qls *QUICListenerSaver) Listen(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
pconn, err := qls.QUICListener.Listen(addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &saverUDPConn{
|
||||
UDPLikeConn: pconn,
|
||||
saver: qls.Saver,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type saverUDPConn struct {
|
||||
model.UDPLikeConn
|
||||
saver *Saver
|
||||
}
|
||||
|
||||
var _ model.UDPLikeConn = &saverUDPConn{}
|
||||
|
||||
func (c *saverUDPConn) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||
start := time.Now()
|
||||
count, err := c.UDPLikeConn.WriteTo(p, addr)
|
||||
stop := time.Now()
|
||||
c.saver.Write(Event{
|
||||
Address: addr.String(),
|
||||
Data: p[:count],
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: count,
|
||||
Name: netxlite.WriteToOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return count, err
|
||||
}
|
||||
|
||||
func (c *saverUDPConn) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||
start := time.Now()
|
||||
n, addr, err := c.UDPLikeConn.ReadFrom(b)
|
||||
stop := time.Now()
|
||||
var data []byte
|
||||
if n > 0 {
|
||||
data = b[:n]
|
||||
}
|
||||
c.saver.Write(Event{
|
||||
Address: c.safeAddrString(addr),
|
||||
Data: data,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
NumBytes: n,
|
||||
Name: netxlite.ReadFromOperation,
|
||||
Time: stop,
|
||||
})
|
||||
return n, addr, err
|
||||
}
|
||||
|
||||
func (c *saverUDPConn) safeAddrString(addr net.Addr) (out string) {
|
||||
if addr != nil {
|
||||
out = addr.String()
|
||||
}
|
||||
return
|
||||
}
|
||||
+78
-7
@@ -1,17 +1,18 @@
|
||||
package quicdialer_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/lucas-clemente/quic-go"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/quicdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite/quictesting"
|
||||
)
|
||||
@@ -37,8 +38,8 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||
NextProtos: nextprotos,
|
||||
ServerName: servername,
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
dlr := quicdialer.HandshakeSaver{
|
||||
saver := &Saver{}
|
||||
dlr := QUICHandshakeSaver{
|
||||
QUICDialer: &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
},
|
||||
@@ -95,8 +96,8 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||
NextProtos: nextprotos,
|
||||
ServerName: servername,
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
dlr := quicdialer.HandshakeSaver{
|
||||
saver := &Saver{}
|
||||
dlr := QUICHandshakeSaver{
|
||||
QUICDialer: &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
},
|
||||
@@ -122,3 +123,73 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestQUICListenerSaverCannotListen(t *testing.T) {
|
||||
expected := errors.New("mocked error")
|
||||
qls := &QUICListenerSaver{
|
||||
QUICListener: &mocks.QUICListener{
|
||||
MockListen: func(addr *net.UDPAddr) (model.UDPLikeConn, error) {
|
||||
return nil, expected
|
||||
},
|
||||
},
|
||||
Saver: &Saver{},
|
||||
}
|
||||
pconn, err := qls.Listen(&net.UDPAddr{
|
||||
IP: []byte{},
|
||||
Port: 8080,
|
||||
Zone: "",
|
||||
})
|
||||
if !errors.Is(err, expected) {
|
||||
t.Fatal("unexpected error", err)
|
||||
}
|
||||
if pconn != nil {
|
||||
t.Fatal("expected nil pconn here")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||
// This is the most common use case for collecting reads, writes
|
||||
tlsConf := &tls.Config{
|
||||
NextProtos: []string{"h3"},
|
||||
ServerName: quictesting.Domain,
|
||||
}
|
||||
saver := &Saver{}
|
||||
systemdialer := &netxlite.QUICDialerQUICGo{
|
||||
QUICListener: &QUICListenerSaver{
|
||||
QUICListener: &netxlite.QUICListenerStdlib{},
|
||||
Saver: saver,
|
||||
},
|
||||
}
|
||||
_, err := systemdialer.DialContext(context.Background(), "udp",
|
||||
quictesting.Endpoint("443"), tlsConf, &quic.Config{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ev := saver.Read()
|
||||
if len(ev) < 2 {
|
||||
t.Fatal("unexpected number of events")
|
||||
}
|
||||
last := len(ev) - 1
|
||||
for idx := 1; idx < last; idx++ {
|
||||
if ev[idx].Data == nil {
|
||||
t.Fatal("unexpected Data")
|
||||
}
|
||||
if ev[idx].Duration <= 0 {
|
||||
t.Fatal("unexpected Duration")
|
||||
}
|
||||
if ev[idx].Err != nil {
|
||||
t.Fatal("unexpected Err")
|
||||
}
|
||||
if ev[idx].NumBytes <= 0 {
|
||||
t.Fatal("unexpected NumBytes")
|
||||
}
|
||||
switch ev[idx].Name {
|
||||
case netxlite.ReadFromOperation, netxlite.WriteToOperation:
|
||||
default:
|
||||
t.Fatal("unexpected Name")
|
||||
}
|
||||
if ev[idx].Time.Before(ev[idx-1].Time) {
|
||||
t.Fatal("unexpected Time", ev[idx].Time, ev[idx-1].Time)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
package resolver
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
)
|
||||
|
||||
// SaverResolver is a resolver that saves events
|
||||
type SaverResolver struct {
|
||||
model.Resolver
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// LookupHost implements Resolver.LookupHost
|
||||
func (r SaverResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
|
||||
start := time.Now()
|
||||
r.Saver.Write(trace.Event{
|
||||
r.Saver.Write(Event{
|
||||
Address: r.Resolver.Address(),
|
||||
Hostname: hostname,
|
||||
Name: "resolve_start",
|
||||
@@ -26,7 +25,7 @@ func (r SaverResolver) LookupHost(ctx context.Context, hostname string) ([]strin
|
||||
})
|
||||
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
||||
stop := time.Now()
|
||||
r.Saver.Write(trace.Event{
|
||||
r.Saver.Write(Event{
|
||||
Addresses: addrs,
|
||||
Address: r.Resolver.Address(),
|
||||
Duration: stop.Sub(start),
|
||||
@@ -42,14 +41,14 @@ func (r SaverResolver) LookupHost(ctx context.Context, hostname string) ([]strin
|
||||
// SaverDNSTransport is a DNS transport that saves events
|
||||
type SaverDNSTransport struct {
|
||||
model.DNSTransport
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// RoundTrip implements RoundTripper.RoundTrip
|
||||
func (txp SaverDNSTransport) RoundTrip(
|
||||
ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
||||
start := time.Now()
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
Address: txp.Address(),
|
||||
DNSQuery: txp.maybeQueryBytes(query),
|
||||
Name: "dns_round_trip_start",
|
||||
@@ -58,7 +57,7 @@ func (txp SaverDNSTransport) RoundTrip(
|
||||
})
|
||||
response, err := txp.DNSTransport.RoundTrip(ctx, query)
|
||||
stop := time.Now()
|
||||
txp.Saver.Write(trace.Event{
|
||||
txp.Saver.Write(Event{
|
||||
Address: txp.Address(),
|
||||
DNSQuery: txp.maybeQueryBytes(query),
|
||||
DNSReply: txp.maybeResponseBytes(response),
|
||||
+60
-13
@@ -1,24 +1,24 @@
|
||||
package resolver_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"net"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/resolver"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/model/mocks"
|
||||
"github.com/ooni/probe-cli/v3/internal/runtimex"
|
||||
)
|
||||
|
||||
func TestSaverResolverFailure(t *testing.T) {
|
||||
expected := errors.New("no such host")
|
||||
saver := &trace.Saver{}
|
||||
reso := resolver.SaverResolver{
|
||||
Resolver: resolver.NewFakeResolverWithExplicitError(expected),
|
||||
saver := &Saver{}
|
||||
reso := SaverResolver{
|
||||
Resolver: NewFakeResolverWithExplicitError(expected),
|
||||
Saver: saver,
|
||||
}
|
||||
addrs, err := reso.LookupHost(context.Background(), "www.google.com")
|
||||
@@ -63,9 +63,9 @@ func TestSaverResolverFailure(t *testing.T) {
|
||||
|
||||
func TestSaverResolverSuccess(t *testing.T) {
|
||||
expected := []string{"8.8.8.8", "8.8.4.4"}
|
||||
saver := &trace.Saver{}
|
||||
reso := resolver.SaverResolver{
|
||||
Resolver: resolver.NewFakeResolverWithResult(expected),
|
||||
saver := &Saver{}
|
||||
reso := SaverResolver{
|
||||
Resolver: NewFakeResolverWithResult(expected),
|
||||
Saver: saver,
|
||||
}
|
||||
addrs, err := reso.LookupHost(context.Background(), "www.google.com")
|
||||
@@ -110,8 +110,8 @@ func TestSaverResolverSuccess(t *testing.T) {
|
||||
|
||||
func TestSaverDNSTransportFailure(t *testing.T) {
|
||||
expected := errors.New("no such host")
|
||||
saver := &trace.Saver{}
|
||||
txp := resolver.SaverDNSTransport{
|
||||
saver := &Saver{}
|
||||
txp := SaverDNSTransport{
|
||||
DNSTransport: &mocks.DNSTransport{
|
||||
MockRoundTrip: func(ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
||||
return nil, expected
|
||||
@@ -173,13 +173,13 @@ func TestSaverDNSTransportFailure(t *testing.T) {
|
||||
|
||||
func TestSaverDNSTransportSuccess(t *testing.T) {
|
||||
expected := []byte{0xef, 0xbe, 0xad, 0xde}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
response := &mocks.DNSResponse{
|
||||
MockBytes: func() []byte {
|
||||
return expected
|
||||
},
|
||||
}
|
||||
txp := resolver.SaverDNSTransport{
|
||||
txp := SaverDNSTransport{
|
||||
DNSTransport: &mocks.DNSTransport{
|
||||
MockRoundTrip: func(ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
||||
return response, nil
|
||||
@@ -238,3 +238,50 @@ func TestSaverDNSTransportSuccess(t *testing.T) {
|
||||
t.Fatal("the saved time is wrong")
|
||||
}
|
||||
}
|
||||
|
||||
func NewFakeResolverWithExplicitError(err error) model.Resolver {
|
||||
runtimex.PanicIfNil(err, "passed nil error")
|
||||
return &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return nil, err
|
||||
},
|
||||
MockNetwork: func() string {
|
||||
return "fake"
|
||||
},
|
||||
MockAddress: func() string {
|
||||
return ""
|
||||
},
|
||||
MockCloseIdleConnections: func() {
|
||||
// nothing
|
||||
},
|
||||
MockLookupHTTPS: func(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
},
|
||||
MockLookupNS: func(ctx context.Context, domain string) ([]*net.NS, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewFakeResolverWithResult(r []string) model.Resolver {
|
||||
return &mocks.Resolver{
|
||||
MockLookupHost: func(ctx context.Context, domain string) ([]string, error) {
|
||||
return r, nil
|
||||
},
|
||||
MockNetwork: func() string {
|
||||
return "fake"
|
||||
},
|
||||
MockAddress: func() string {
|
||||
return ""
|
||||
},
|
||||
MockCloseIdleConnections: func() {
|
||||
// nothing
|
||||
},
|
||||
MockLookupHTTPS: func(ctx context.Context, domain string) (*model.HTTPSSvc, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
},
|
||||
MockLookupNS: func(ctx context.Context, domain string) ([]*net.NS, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package trace
|
||||
package tracex
|
||||
|
||||
import "sync"
|
||||
|
||||
+3
-5
@@ -1,20 +1,18 @@
|
||||
package trace_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
)
|
||||
|
||||
func TestGood(t *testing.T) {
|
||||
saver := trace.Saver{}
|
||||
saver := Saver{}
|
||||
var wg sync.WaitGroup
|
||||
const parallel = 10
|
||||
wg.Add(parallel)
|
||||
for idx := 0; idx < parallel; idx++ {
|
||||
go func() {
|
||||
saver.Write(trace.Event{})
|
||||
saver.Write(Event{})
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package tlsdialer
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
@@ -14,7 +13,7 @@ import (
|
||||
// SaverTLSHandshaker saves events occurring during the handshake
|
||||
type SaverTLSHandshaker struct {
|
||||
model.TLSHandshaker
|
||||
Saver *trace.Saver
|
||||
Saver *Saver
|
||||
}
|
||||
|
||||
// Handshake implements TLSHandshaker.Handshake
|
||||
@@ -22,7 +21,7 @@ func (h SaverTLSHandshaker) Handshake(
|
||||
ctx context.Context, conn net.Conn, config *tls.Config,
|
||||
) (net.Conn, tls.ConnectionState, error) {
|
||||
start := time.Now()
|
||||
h.Saver.Write(trace.Event{
|
||||
h.Saver.Write(Event{
|
||||
Name: "tls_handshake_start",
|
||||
NoTLSVerify: config.InsecureSkipVerify,
|
||||
TLSNextProtos: config.NextProtos,
|
||||
@@ -32,7 +31,7 @@ func (h SaverTLSHandshaker) Handshake(
|
||||
remoteAddr := conn.RemoteAddr().String()
|
||||
tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
|
||||
stop := time.Now()
|
||||
h.Saver.Write(trace.Event{
|
||||
h.Saver.Write(Event{
|
||||
Address: remoteAddr,
|
||||
Duration: stop.Sub(start),
|
||||
Err: err,
|
||||
@@ -41,7 +40,7 @@ func (h SaverTLSHandshaker) Handshake(
|
||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||
TLSNextProtos: config.NextProtos,
|
||||
TLSPeerCerts: trace.PeerCerts(state, err),
|
||||
TLSPeerCerts: PeerCerts(state, err),
|
||||
TLSServerName: config.ServerName,
|
||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||
Time: stop,
|
||||
+24
-17
@@ -1,4 +1,4 @@
|
||||
package tlsdialer_test
|
||||
package tracex
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,9 +7,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
|
||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/trace"
|
||||
"github.com/ooni/probe-cli/v3/internal/model"
|
||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||
)
|
||||
|
||||
@@ -19,11 +17,20 @@ func TestSaverTLSHandshakerSuccessWithReadWrite(t *testing.T) {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
nextprotos := []string{"h2"}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Config: &tls.Config{NextProtos: nextprotos},
|
||||
Dialer: dialer.New(&dialer.Config{ReadWriteSaver: saver}, netxlite.DefaultResolver),
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
Dialer: netxlite.NewDialerWithResolver(
|
||||
model.DiscardLogger,
|
||||
netxlite.NewResolverStdlib(model.DiscardLogger),
|
||||
func(dialer model.Dialer) model.Dialer {
|
||||
return &SaverConnDialer{
|
||||
Dialer: dialer,
|
||||
Saver: saver,
|
||||
}
|
||||
},
|
||||
),
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
@@ -112,11 +119,11 @@ func TestSaverTLSHandshakerSuccess(t *testing.T) {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
nextprotos := []string{"h2"}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Config: &tls.Config{NextProtos: nextprotos},
|
||||
Dialer: netxlite.DefaultDialer,
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
@@ -178,10 +185,10 @@ func TestSaverTLSHandshakerHostnameError(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Dialer: netxlite.DefaultDialer,
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
@@ -211,10 +218,10 @@ func TestSaverTLSHandshakerInvalidCertError(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Dialer: netxlite.DefaultDialer,
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
@@ -244,10 +251,10 @@ func TestSaverTLSHandshakerAuthorityError(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Dialer: netxlite.DefaultDialer,
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
@@ -277,11 +284,11 @@ func TestSaverTLSHandshakerNoTLSVerify(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skip test in short mode")
|
||||
}
|
||||
saver := &trace.Saver{}
|
||||
saver := &Saver{}
|
||||
tlsdlr := &netxlite.TLSDialerLegacy{
|
||||
Config: &tls.Config{InsecureSkipVerify: true},
|
||||
Dialer: netxlite.DefaultDialer,
|
||||
TLSHandshaker: tlsdialer.SaverTLSHandshaker{
|
||||
TLSHandshaker: SaverTLSHandshaker{
|
||||
TLSHandshaker: &netxlite.TLSHandshakerConfigurable{},
|
||||
Saver: saver,
|
||||
},
|
||||
Reference in New Issue
Block a user