refactor(tracex): do not depend on strings for event names (#777)
Rather than matching a string, match a type. This is more robust considering future refactorings. We're confident the names did not change in _this_ refactoring because we're still testing the same strings in the tests. Part of https://github.com/ooni/probe/issues/2121
This commit is contained in:
parent
8f7e3803eb
commit
c740be987b
|
@ -171,8 +171,8 @@ func (r runner) measure(
|
||||||
// of the latest connect time. We should have one sample in most
|
// of the latest connect time. We should have one sample in most
|
||||||
// cases, because the connection should be persistent.
|
// cases, because the connection should be persistent.
|
||||||
for _, ev := range r.saver.Read() {
|
for _, ev := range r.saver.Read() {
|
||||||
if ev.Name == netxlite.ConnectOperation {
|
if _, ok := ev.(*tracex.EventConnectOperation); ok {
|
||||||
connectTime = ev.Duration.Seconds()
|
connectTime = ev.Value().Duration.Seconds()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current.ConnectTime = connectTime
|
current.ConnectTime = connectTime
|
||||||
|
|
|
@ -14,7 +14,6 @@ import (
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/mockable"
|
"github.com/ooni/probe-cli/v3/internal/engine/mockable"
|
||||||
"github.com/ooni/probe-cli/v3/internal/engine/netx/tracex"
|
"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/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRunnerLoopLocateFailure(t *testing.T) {
|
func TestRunnerLoopLocateFailure(t *testing.T) {
|
||||||
|
@ -108,7 +107,7 @@ func TestRunnerLoopMeasureFailure(t *testing.T) {
|
||||||
func TestRunnerLoopCollectFailure(t *testing.T) {
|
func TestRunnerLoopCollectFailure(t *testing.T) {
|
||||||
expected := errors.New("mocked error")
|
expected := errors.New("mocked error")
|
||||||
saver := new(tracex.Saver)
|
saver := new(tracex.Saver)
|
||||||
saver.Write(tracex.Event{Name: netxlite.ConnectOperation, Duration: 150 * time.Millisecond})
|
saver.Write(&tracex.EventConnectOperation{V: &tracex.EventValue{Duration: 150 * time.Millisecond}})
|
||||||
r := runner{
|
r := runner{
|
||||||
callbacks: model.NewPrinterCallbacks(log.Log),
|
callbacks: model.NewPrinterCallbacks(log.Log),
|
||||||
httpClient: &http.Client{
|
httpClient: &http.Client{
|
||||||
|
@ -152,7 +151,7 @@ func TestRunnerLoopCollectFailure(t *testing.T) {
|
||||||
|
|
||||||
func TestRunnerLoopSuccess(t *testing.T) {
|
func TestRunnerLoopSuccess(t *testing.T) {
|
||||||
saver := new(tracex.Saver)
|
saver := new(tracex.Saver)
|
||||||
saver.Write(tracex.Event{Name: netxlite.ConnectOperation, Duration: 150 * time.Millisecond})
|
saver.Write(&tracex.EventConnectOperation{V: &tracex.EventValue{Duration: 150 * time.Millisecond}})
|
||||||
r := runner{
|
r := runner{
|
||||||
callbacks: model.NewPrinterCallbacks(log.Log),
|
callbacks: model.NewPrinterCallbacks(log.Log),
|
||||||
httpClient: &http.Client{
|
httpClient: &http.Client{
|
||||||
|
|
|
@ -45,10 +45,11 @@ var (
|
||||||
// NewTCPConnectList creates a new TCPConnectList
|
// NewTCPConnectList creates a new TCPConnectList
|
||||||
func NewTCPConnectList(begin time.Time, events []Event) []TCPConnectEntry {
|
func NewTCPConnectList(begin time.Time, events []Event) []TCPConnectEntry {
|
||||||
var out []TCPConnectEntry
|
var out []TCPConnectEntry
|
||||||
for _, event := range events {
|
for _, wrapper := range events {
|
||||||
if event.Name != netxlite.ConnectOperation {
|
if _, ok := wrapper.(*EventConnectOperation); !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
event := wrapper.Value()
|
||||||
if event.Proto != "tcp" {
|
if event.Proto != "tcp" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -140,31 +141,32 @@ func newRequestList(begin time.Time, events []Event) []RequestEntry {
|
||||||
out []RequestEntry
|
out []RequestEntry
|
||||||
entry RequestEntry
|
entry RequestEntry
|
||||||
)
|
)
|
||||||
for _, ev := range events {
|
for _, wrapper := range events {
|
||||||
switch ev.Name {
|
ev := wrapper.Value()
|
||||||
case "http_transaction_start":
|
switch wrapper.(type) {
|
||||||
|
case *EventHTTPTransactionStart:
|
||||||
entry = RequestEntry{}
|
entry = RequestEntry{}
|
||||||
entry.T = ev.Time.Sub(begin).Seconds()
|
entry.T = ev.Time.Sub(begin).Seconds()
|
||||||
case "http_request_body_snapshot":
|
case *EventHTTPRequestBodySnapshot:
|
||||||
entry.Request.Body.Value = string(ev.Data)
|
entry.Request.Body.Value = string(ev.Data)
|
||||||
entry.Request.BodyIsTruncated = ev.DataIsTruncated
|
entry.Request.BodyIsTruncated = ev.DataIsTruncated
|
||||||
case "http_request_metadata":
|
case *EventHTTPRequestMetadata:
|
||||||
entry.Request.Headers = make(map[string]MaybeBinaryValue)
|
entry.Request.Headers = make(map[string]MaybeBinaryValue)
|
||||||
httpAddHeaders(
|
httpAddHeaders(
|
||||||
ev.HTTPHeaders, &entry.Request.HeadersList, &entry.Request.Headers)
|
ev.HTTPHeaders, &entry.Request.HeadersList, &entry.Request.Headers)
|
||||||
entry.Request.Method = ev.HTTPMethod
|
entry.Request.Method = ev.HTTPMethod
|
||||||
entry.Request.URL = ev.HTTPURL
|
entry.Request.URL = ev.HTTPURL
|
||||||
entry.Request.Transport = ev.Transport
|
entry.Request.Transport = ev.Transport
|
||||||
case "http_response_metadata":
|
case *EventHTTPResponseMetadata:
|
||||||
entry.Response.Headers = make(map[string]MaybeBinaryValue)
|
entry.Response.Headers = make(map[string]MaybeBinaryValue)
|
||||||
httpAddHeaders(
|
httpAddHeaders(
|
||||||
ev.HTTPHeaders, &entry.Response.HeadersList, &entry.Response.Headers)
|
ev.HTTPHeaders, &entry.Response.HeadersList, &entry.Response.Headers)
|
||||||
entry.Response.Code = int64(ev.HTTPStatusCode)
|
entry.Response.Code = int64(ev.HTTPStatusCode)
|
||||||
entry.Response.Locations = ev.HTTPHeaders.Values("Location")
|
entry.Response.Locations = ev.HTTPHeaders.Values("Location")
|
||||||
case "http_response_body_snapshot":
|
case *EventHTTPResponseBodySnapshot:
|
||||||
entry.Response.Body.Value = string(ev.Data)
|
entry.Response.Body.Value = string(ev.Data)
|
||||||
entry.Response.BodyIsTruncated = ev.DataIsTruncated
|
entry.Response.BodyIsTruncated = ev.DataIsTruncated
|
||||||
case "http_transaction_done":
|
case *EventHTTPTransactionDone:
|
||||||
entry.Failure = NewFailure(ev.Err)
|
entry.Failure = NewFailure(ev.Err)
|
||||||
out = append(out, entry)
|
out = append(out, entry)
|
||||||
}
|
}
|
||||||
|
@ -178,10 +180,11 @@ type dnsQueryType string
|
||||||
func NewDNSQueriesList(begin time.Time, events []Event) []DNSQueryEntry {
|
func NewDNSQueriesList(begin time.Time, events []Event) []DNSQueryEntry {
|
||||||
// TODO(bassosimone): add support for CNAME lookups.
|
// TODO(bassosimone): add support for CNAME lookups.
|
||||||
var out []DNSQueryEntry
|
var out []DNSQueryEntry
|
||||||
for _, ev := range events {
|
for _, wrapper := range events {
|
||||||
if ev.Name != "resolve_done" {
|
if _, ok := wrapper.(*EventResolveDone); !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
ev := wrapper.Value()
|
||||||
for _, qtype := range []dnsQueryType{"A", "AAAA"} {
|
for _, qtype := range []dnsQueryType{"A", "AAAA"} {
|
||||||
entry := qtype.makeQueryEntry(begin, ev)
|
entry := qtype.makeQueryEntry(begin, ev)
|
||||||
for _, addr := range ev.Addresses {
|
for _, addr := range ev.Addresses {
|
||||||
|
@ -230,7 +233,7 @@ func (qtype dnsQueryType) makeAnswerEntry(addr string) DNSAnswerEntry {
|
||||||
return answer
|
return answer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qtype dnsQueryType) makeQueryEntry(begin time.Time, ev Event) DNSQueryEntry {
|
func (qtype dnsQueryType) makeQueryEntry(begin time.Time, ev *EventValue) DNSQueryEntry {
|
||||||
return DNSQueryEntry{
|
return DNSQueryEntry{
|
||||||
Engine: ev.Proto,
|
Engine: ev.Proto,
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
|
@ -244,60 +247,54 @@ func (qtype dnsQueryType) makeQueryEntry(begin time.Time, ev Event) DNSQueryEntr
|
||||||
// NewNetworkEventsList returns a list of DNS queries.
|
// NewNetworkEventsList returns a list of DNS queries.
|
||||||
func NewNetworkEventsList(begin time.Time, events []Event) []NetworkEvent {
|
func NewNetworkEventsList(begin time.Time, events []Event) []NetworkEvent {
|
||||||
var out []NetworkEvent
|
var out []NetworkEvent
|
||||||
for _, ev := range events {
|
for _, wrapper := range events {
|
||||||
if ev.Name == netxlite.ConnectOperation {
|
ev := wrapper.Value()
|
||||||
|
switch wrapper.(type) {
|
||||||
|
case *EventConnectOperation:
|
||||||
out = append(out, NetworkEvent{
|
out = append(out, NetworkEvent{
|
||||||
Address: ev.Address,
|
Address: ev.Address,
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
Operation: ev.Name,
|
Operation: wrapper.Name(),
|
||||||
Proto: ev.Proto,
|
Proto: ev.Proto,
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
})
|
})
|
||||||
continue
|
case *EventReadOperation:
|
||||||
}
|
|
||||||
if ev.Name == netxlite.ReadOperation {
|
|
||||||
out = append(out, NetworkEvent{
|
out = append(out, NetworkEvent{
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
Operation: ev.Name,
|
Operation: wrapper.Name(),
|
||||||
NumBytes: int64(ev.NumBytes),
|
NumBytes: int64(ev.NumBytes),
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
})
|
})
|
||||||
continue
|
case *EventWriteOperation:
|
||||||
}
|
|
||||||
if ev.Name == netxlite.WriteOperation {
|
|
||||||
out = append(out, NetworkEvent{
|
out = append(out, NetworkEvent{
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
Operation: ev.Name,
|
Operation: wrapper.Name(),
|
||||||
NumBytes: int64(ev.NumBytes),
|
NumBytes: int64(ev.NumBytes),
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
})
|
})
|
||||||
continue
|
case *EventReadFromOperation:
|
||||||
}
|
|
||||||
if ev.Name == netxlite.ReadFromOperation {
|
|
||||||
out = append(out, NetworkEvent{
|
out = append(out, NetworkEvent{
|
||||||
Address: ev.Address,
|
Address: ev.Address,
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
Operation: ev.Name,
|
Operation: wrapper.Name(),
|
||||||
NumBytes: int64(ev.NumBytes),
|
NumBytes: int64(ev.NumBytes),
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
})
|
})
|
||||||
continue
|
case *EventWriteToOperation:
|
||||||
}
|
|
||||||
if ev.Name == netxlite.WriteToOperation {
|
|
||||||
out = append(out, NetworkEvent{
|
out = append(out, NetworkEvent{
|
||||||
Address: ev.Address,
|
Address: ev.Address,
|
||||||
Failure: NewFailure(ev.Err),
|
Failure: NewFailure(ev.Err),
|
||||||
Operation: ev.Name,
|
Operation: wrapper.Name(),
|
||||||
NumBytes: int64(ev.NumBytes),
|
NumBytes: int64(ev.NumBytes),
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
})
|
})
|
||||||
continue
|
default:
|
||||||
|
out = append(out, NetworkEvent{
|
||||||
|
Failure: NewFailure(ev.Err),
|
||||||
|
Operation: wrapper.Name(),
|
||||||
|
T: ev.Time.Sub(begin).Seconds(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
out = append(out, NetworkEvent{
|
|
||||||
Failure: NewFailure(ev.Err),
|
|
||||||
Operation: ev.Name,
|
|
||||||
T: ev.Time.Sub(begin).Seconds(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
@ -305,10 +302,13 @@ func NewNetworkEventsList(begin time.Time, events []Event) []NetworkEvent {
|
||||||
// NewTLSHandshakesList creates a new TLSHandshakesList
|
// NewTLSHandshakesList creates a new TLSHandshakesList
|
||||||
func NewTLSHandshakesList(begin time.Time, events []Event) []TLSHandshake {
|
func NewTLSHandshakesList(begin time.Time, events []Event) []TLSHandshake {
|
||||||
var out []TLSHandshake
|
var out []TLSHandshake
|
||||||
for _, ev := range events {
|
for _, wrapper := range events {
|
||||||
if !strings.Contains(ev.Name, "_handshake_done") {
|
switch wrapper.(type) {
|
||||||
continue
|
case *EventQUICHandshakeDone, *EventTLSHandshakeDone: // ok
|
||||||
|
default:
|
||||||
|
continue // not interested
|
||||||
}
|
}
|
||||||
|
ev := wrapper.Value()
|
||||||
out = append(out, TLSHandshake{
|
out = append(out, TLSHandshake{
|
||||||
Address: ev.Address,
|
Address: ev.Address,
|
||||||
CipherSuite: ev.TLSCipherSuite,
|
CipherSuite: ev.TLSCipherSuite,
|
||||||
|
|
|
@ -74,31 +74,27 @@ func TestNewTCPConnectList(t *testing.T) {
|
||||||
name: "realistic run",
|
name: "realistic run",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventResolveDone{&EventValue{
|
||||||
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
||||||
Hostname: "dns.google.com",
|
Hostname: "dns.google.com",
|
||||||
Name: "resolve_done",
|
|
||||||
Time: begin.Add(100 * time.Millisecond),
|
Time: begin.Add(100 * time.Millisecond),
|
||||||
}, {
|
}}, &EventConnectOperation{&EventValue{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Duration: 30 * time.Millisecond,
|
Duration: 30 * time.Millisecond,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: "tcp",
|
Proto: "tcp",
|
||||||
Time: begin.Add(130 * time.Millisecond),
|
Time: begin.Add(130 * time.Millisecond),
|
||||||
}, {
|
}}, &EventConnectOperation{&EventValue{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Duration: 55 * time.Millisecond,
|
Duration: 55 * time.Millisecond,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: "udp",
|
Proto: "udp",
|
||||||
Time: begin.Add(130 * time.Millisecond),
|
Time: begin.Add(130 * time.Millisecond),
|
||||||
}, {
|
}}, &EventConnectOperation{&EventValue{
|
||||||
Address: "8.8.4.4:53",
|
Address: "8.8.4.4:53",
|
||||||
Duration: 50 * time.Millisecond,
|
Duration: 50 * time.Millisecond,
|
||||||
Err: io.EOF,
|
Err: io.EOF,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: "tcp",
|
Proto: "tcp",
|
||||||
Time: begin.Add(180 * time.Millisecond),
|
Time: begin.Add(180 * time.Millisecond),
|
||||||
}},
|
}}},
|
||||||
},
|
},
|
||||||
want: []TCPConnectEntry{{
|
want: []TCPConnectEntry{{
|
||||||
IP: "8.8.8.8",
|
IP: "8.8.8.8",
|
||||||
|
@ -147,46 +143,36 @@ func TestNewRequestList(t *testing.T) {
|
||||||
name: "realistic run",
|
name: "realistic run",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventHTTPTransactionStart{&EventValue{
|
||||||
Name: "http_transaction_start",
|
|
||||||
Time: begin.Add(10 * time.Millisecond),
|
Time: begin.Add(10 * time.Millisecond),
|
||||||
}, {
|
}}, &EventHTTPRequestBodySnapshot{&EventValue{
|
||||||
Name: "http_request_body_snapshot",
|
|
||||||
Data: []byte("deadbeef"),
|
Data: []byte("deadbeef"),
|
||||||
DataIsTruncated: false,
|
DataIsTruncated: false,
|
||||||
}, {
|
}}, &EventHTTPRequestMetadata{&EventValue{
|
||||||
Name: "http_request_metadata",
|
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
HTTPMethod: "POST",
|
HTTPMethod: "POST",
|
||||||
HTTPURL: "https://www.example.com/submit",
|
HTTPURL: "https://www.example.com/submit",
|
||||||
}, {
|
}}, &EventHTTPResponseMetadata{&EventValue{
|
||||||
Name: "http_response_metadata",
|
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"Server": []string{"miniooni/0.1.0-dev"},
|
"Server": []string{"miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
HTTPStatusCode: 200,
|
HTTPStatusCode: 200,
|
||||||
}, {
|
}}, &EventHTTPResponseBodySnapshot{&EventValue{
|
||||||
Name: "http_response_body_snapshot",
|
|
||||||
Data: []byte("{}"),
|
Data: []byte("{}"),
|
||||||
DataIsTruncated: false,
|
DataIsTruncated: false,
|
||||||
}, {
|
}}, &EventHTTPTransactionDone{&EventValue{}}, &EventHTTPTransactionStart{&EventValue{
|
||||||
Name: "http_transaction_done",
|
|
||||||
}, {
|
|
||||||
Name: "http_transaction_start",
|
|
||||||
Time: begin.Add(20 * time.Millisecond),
|
Time: begin.Add(20 * time.Millisecond),
|
||||||
}, {
|
}}, &EventHTTPRequestMetadata{&EventValue{
|
||||||
Name: "http_request_metadata",
|
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
HTTPMethod: "GET",
|
HTTPMethod: "GET",
|
||||||
HTTPURL: "https://www.example.com/result",
|
HTTPURL: "https://www.example.com/result",
|
||||||
}, {
|
}}, &EventHTTPTransactionDone{&EventValue{
|
||||||
Name: "http_transaction_done",
|
Err: io.EOF,
|
||||||
Err: io.EOF,
|
}}},
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
want: []RequestEntry{{
|
want: []RequestEntry{{
|
||||||
Failure: NewFailure(io.EOF),
|
Failure: NewFailure(io.EOF),
|
||||||
|
@ -245,26 +231,21 @@ func TestNewRequestList(t *testing.T) {
|
||||||
name: "run with redirect and headers to sort",
|
name: "run with redirect and headers to sort",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventHTTPTransactionStart{&EventValue{
|
||||||
Name: "http_transaction_start",
|
|
||||||
Time: begin.Add(10 * time.Millisecond),
|
Time: begin.Add(10 * time.Millisecond),
|
||||||
}, {
|
}}, &EventHTTPRequestMetadata{&EventValue{
|
||||||
Name: "http_request_metadata",
|
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
"User-Agent": []string{"miniooni/0.1.0-dev"},
|
||||||
},
|
},
|
||||||
HTTPMethod: "GET",
|
HTTPMethod: "GET",
|
||||||
HTTPURL: "https://www.example.com/",
|
HTTPURL: "https://www.example.com/",
|
||||||
}, {
|
}}, &EventHTTPResponseMetadata{&EventValue{
|
||||||
Name: "http_response_metadata",
|
|
||||||
HTTPHeaders: http.Header{
|
HTTPHeaders: http.Header{
|
||||||
"Server": []string{"miniooni/0.1.0-dev"},
|
"Server": []string{"miniooni/0.1.0-dev"},
|
||||||
"Location": []string{"https://x.example.com", "https://y.example.com"},
|
"Location": []string{"https://x.example.com", "https://y.example.com"},
|
||||||
},
|
},
|
||||||
HTTPStatusCode: 302,
|
HTTPStatusCode: 302,
|
||||||
}, {
|
}}, &EventHTTPTransactionDone{&EventValue{}}},
|
||||||
Name: "http_transaction_done",
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
want: []RequestEntry{{
|
want: []RequestEntry{{
|
||||||
Request: HTTPRequest{
|
Request: HTTPRequest{
|
||||||
|
@ -339,27 +320,24 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||||
name: "realistic run",
|
name: "realistic run",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventResolveDone{&EventValue{
|
||||||
Address: "1.1.1.1:853",
|
Address: "1.1.1.1:853",
|
||||||
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
Addresses: []string{"8.8.8.8", "8.8.4.4"},
|
||||||
Hostname: "dns.google.com",
|
Hostname: "dns.google.com",
|
||||||
Name: "resolve_done",
|
|
||||||
Proto: "dot",
|
Proto: "dot",
|
||||||
Time: begin.Add(100 * time.Millisecond),
|
Time: begin.Add(100 * time.Millisecond),
|
||||||
}, {
|
}}, &EventConnectOperation{&EventValue{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Duration: 30 * time.Millisecond,
|
Duration: 30 * time.Millisecond,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: "tcp",
|
Proto: "tcp",
|
||||||
Time: begin.Add(130 * time.Millisecond),
|
Time: begin.Add(130 * time.Millisecond),
|
||||||
}, {
|
}}, &EventConnectOperation{&EventValue{
|
||||||
Address: "8.8.4.4:53",
|
Address: "8.8.4.4:53",
|
||||||
Duration: 50 * time.Millisecond,
|
Duration: 50 * time.Millisecond,
|
||||||
Err: io.EOF,
|
Err: io.EOF,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: "tcp",
|
Proto: "tcp",
|
||||||
Time: begin.Add(180 * time.Millisecond),
|
Time: begin.Add(180 * time.Millisecond),
|
||||||
}},
|
}}},
|
||||||
},
|
},
|
||||||
want: []DNSQueryEntry{{
|
want: []DNSQueryEntry{{
|
||||||
Answers: []DNSAnswerEntry{{
|
Answers: []DNSAnswerEntry{{
|
||||||
|
@ -383,12 +361,11 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||||
name: "run with IPv6 results",
|
name: "run with IPv6 results",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventResolveDone{&EventValue{
|
||||||
Addresses: []string{"2001:4860:4860::8888"},
|
Addresses: []string{"2001:4860:4860::8888"},
|
||||||
Hostname: "dns.google.com",
|
Hostname: "dns.google.com",
|
||||||
Name: "resolve_done",
|
|
||||||
Time: begin.Add(200 * time.Millisecond),
|
Time: begin.Add(200 * time.Millisecond),
|
||||||
}},
|
}}},
|
||||||
},
|
},
|
||||||
want: []DNSQueryEntry{{
|
want: []DNSQueryEntry{{
|
||||||
Answers: []DNSAnswerEntry{{
|
Answers: []DNSAnswerEntry{{
|
||||||
|
@ -405,12 +382,11 @@ func TestNewDNSQueriesList(t *testing.T) {
|
||||||
name: "run with errors",
|
name: "run with errors",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventResolveDone{&EventValue{
|
||||||
Err: &netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError},
|
Err: &netxlite.ErrWrapper{Failure: netxlite.FailureDNSNXDOMAINError},
|
||||||
Hostname: "dns.google.com",
|
Hostname: "dns.google.com",
|
||||||
Name: "resolve_done",
|
|
||||||
Time: begin.Add(200 * time.Millisecond),
|
Time: begin.Add(200 * time.Millisecond),
|
||||||
}},
|
}}},
|
||||||
},
|
},
|
||||||
want: []DNSQueryEntry{{
|
want: []DNSQueryEntry{{
|
||||||
Answers: nil,
|
Answers: nil,
|
||||||
|
@ -459,39 +435,30 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||||
name: "realistic run",
|
name: "realistic run",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventConnectOperation{&EventValue{
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Err: io.EOF,
|
Err: io.EOF,
|
||||||
Proto: "tcp",
|
Proto: "tcp",
|
||||||
Time: begin.Add(7 * time.Millisecond),
|
Time: begin.Add(7 * time.Millisecond),
|
||||||
}, {
|
}}, &EventReadOperation{&EventValue{
|
||||||
Name: netxlite.ReadOperation,
|
|
||||||
Err: context.Canceled,
|
Err: context.Canceled,
|
||||||
NumBytes: 7117,
|
NumBytes: 7117,
|
||||||
Time: begin.Add(11 * time.Millisecond),
|
Time: begin.Add(11 * time.Millisecond),
|
||||||
}, {
|
}}, &EventReadFromOperation{&EventValue{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Name: netxlite.ReadFromOperation,
|
|
||||||
Err: context.Canceled,
|
Err: context.Canceled,
|
||||||
NumBytes: 7117,
|
NumBytes: 7117,
|
||||||
Time: begin.Add(11 * time.Millisecond),
|
Time: begin.Add(11 * time.Millisecond),
|
||||||
}, {
|
}}, &EventWriteOperation{&EventValue{
|
||||||
Name: netxlite.WriteOperation,
|
|
||||||
Err: websocket.ErrBadHandshake,
|
Err: websocket.ErrBadHandshake,
|
||||||
NumBytes: 4114,
|
NumBytes: 4114,
|
||||||
Time: begin.Add(14 * time.Millisecond),
|
Time: begin.Add(14 * time.Millisecond),
|
||||||
}, {
|
}}, &EventWriteToOperation{&EventValue{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
Name: netxlite.WriteToOperation,
|
|
||||||
Err: websocket.ErrBadHandshake,
|
Err: websocket.ErrBadHandshake,
|
||||||
NumBytes: 4114,
|
NumBytes: 4114,
|
||||||
Time: begin.Add(14 * time.Millisecond),
|
Time: begin.Add(14 * time.Millisecond),
|
||||||
}, {
|
}}},
|
||||||
Name: netxlite.CloseOperation,
|
|
||||||
Err: websocket.ErrReadLimit,
|
|
||||||
Time: begin.Add(17 * time.Millisecond),
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
want: []NetworkEvent{{
|
want: []NetworkEvent{{
|
||||||
Address: "8.8.8.8:853",
|
Address: "8.8.8.8:853",
|
||||||
|
@ -521,10 +488,6 @@ func TestNewNetworkEventsList(t *testing.T) {
|
||||||
NumBytes: 4114,
|
NumBytes: 4114,
|
||||||
Operation: netxlite.WriteToOperation,
|
Operation: netxlite.WriteToOperation,
|
||||||
T: 0.014,
|
T: 0.014,
|
||||||
}, {
|
|
||||||
Failure: NewFailure(websocket.ErrReadLimit),
|
|
||||||
Operation: netxlite.CloseOperation,
|
|
||||||
T: 0.017,
|
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
|
@ -557,13 +520,8 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||||
name: "realistic run",
|
name: "realistic run",
|
||||||
args: args{
|
args: args{
|
||||||
begin: begin,
|
begin: begin,
|
||||||
events: []Event{{
|
events: []Event{&EventTLSHandshakeDone{&EventValue{
|
||||||
Name: netxlite.CloseOperation,
|
|
||||||
Err: websocket.ErrReadLimit,
|
|
||||||
Time: begin.Add(17 * time.Millisecond),
|
|
||||||
}, {
|
|
||||||
Address: "131.252.210.176:443",
|
Address: "131.252.210.176:443",
|
||||||
Name: "tls_handshake_done",
|
|
||||||
Err: io.EOF,
|
Err: io.EOF,
|
||||||
NoTLSVerify: false,
|
NoTLSVerify: false,
|
||||||
TLSCipherSuite: "SUITE",
|
TLSCipherSuite: "SUITE",
|
||||||
|
@ -576,7 +534,7 @@ func TestNewTLSHandshakesList(t *testing.T) {
|
||||||
TLSServerName: "x.org",
|
TLSServerName: "x.org",
|
||||||
TLSVersion: "TLSv1.3",
|
TLSVersion: "TLSv1.3",
|
||||||
Time: begin.Add(55 * time.Millisecond),
|
Time: begin.Add(55 * time.Millisecond),
|
||||||
}},
|
}}},
|
||||||
},
|
},
|
||||||
want: []TLSHandshake{{
|
want: []TLSHandshake{{
|
||||||
Address: "131.252.210.176:443",
|
Address: "131.252.210.176:443",
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ooni/probe-cli/v3/internal/model"
|
"github.com/ooni/probe-cli/v3/internal/model"
|
||||||
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// SaverDialer saves events occurring during the dial
|
// SaverDialer saves events occurring during the dial
|
||||||
|
@ -52,14 +51,13 @@ func (d *SaverDialer) DialContext(ctx context.Context, network, address string)
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
conn, err := d.Dialer.DialContext(ctx, network, address)
|
conn, err := d.Dialer.DialContext(ctx, network, address)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
d.Saver.Write(Event{
|
d.Saver.Write(&EventConnectOperation{&EventValue{
|
||||||
Address: address,
|
Address: address,
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: netxlite.ConnectOperation,
|
|
||||||
Proto: network,
|
Proto: network,
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return conn, err
|
return conn, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,14 +122,13 @@ func (c *saverConn) Read(p []byte) (int, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
count, err := c.Conn.Read(p)
|
count, err := c.Conn.Read(p)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
c.saver.Write(Event{
|
c.saver.Write(&EventReadOperation{&EventValue{
|
||||||
Data: p[:count],
|
Data: p[:count],
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
NumBytes: count,
|
NumBytes: count,
|
||||||
Name: netxlite.ReadOperation,
|
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,14 +136,13 @@ func (c *saverConn) Write(p []byte) (int, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
count, err := c.Conn.Write(p)
|
count, err := c.Conn.Write(p)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
c.saver.Write(Event{
|
c.saver.Write(&EventWriteOperation{&EventValue{
|
||||||
Data: p[:count],
|
Data: p[:count],
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
NumBytes: count,
|
NumBytes: count,
|
||||||
Name: netxlite.WriteOperation,
|
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,22 +34,22 @@ func TestSaverDialerFailure(t *testing.T) {
|
||||||
if len(ev) != 1 {
|
if len(ev) != 1 {
|
||||||
t.Fatal("expected a single event here")
|
t.Fatal("expected a single event here")
|
||||||
}
|
}
|
||||||
if ev[0].Address != "www.google.com:443" {
|
if ev[0].Value().Address != "www.google.com:443" {
|
||||||
t.Fatal("unexpected Address")
|
t.Fatal("unexpected Address")
|
||||||
}
|
}
|
||||||
if ev[0].Duration <= 0 {
|
if ev[0].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if !errors.Is(ev[0].Err, expected) {
|
if !errors.Is(ev[0].Value().Err, expected) {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[0].Name != netxlite.ConnectOperation {
|
if ev[0].Name() != netxlite.ConnectOperation {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[0].Proto != "tcp" {
|
if ev[0].Value().Proto != "tcp" {
|
||||||
t.Fatal("unexpected Proto")
|
t.Fatal("unexpected Proto")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,15 +111,15 @@ func TestSaverConnDialerSuccess(t *testing.T) {
|
||||||
if len(events) != 3 {
|
if len(events) != 3 {
|
||||||
t.Fatal("unexpected number of events saved", len(events))
|
t.Fatal("unexpected number of events saved", len(events))
|
||||||
}
|
}
|
||||||
if events[0].Name != "connect" {
|
if events[0].Name() != "connect" {
|
||||||
t.Fatal("expected a connect event")
|
t.Fatal("expected a connect event")
|
||||||
}
|
}
|
||||||
saverCheckConnectEvent(t, &events[0])
|
saverCheckConnectEvent(t, &events[0])
|
||||||
if events[1].Name != "read" {
|
if events[1].Name() != "read" {
|
||||||
t.Fatal("expected a read event")
|
t.Fatal("expected a read event")
|
||||||
}
|
}
|
||||||
saverCheckReadEvent(t, &events[1])
|
saverCheckReadEvent(t, &events[1])
|
||||||
if events[2].Name != "write" {
|
if events[2].Name() != "write" {
|
||||||
t.Fatal("expected a write event")
|
t.Fatal("expected a write event")
|
||||||
}
|
}
|
||||||
saverCheckWriteEvent(t, &events[2])
|
saverCheckWriteEvent(t, &events[2])
|
||||||
|
|
|
@ -4,10 +4,268 @@ import (
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/ooni/probe-cli/v3/internal/netxlite"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Event is one of the events within a trace.
|
||||||
|
type Event interface {
|
||||||
|
// Value returns the event value
|
||||||
|
Value() *EventValue
|
||||||
|
|
||||||
|
// Name returns the event name
|
||||||
|
Name() string
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventTLSHandshakeStart is the beginning of the TLS handshake.
|
||||||
|
type EventTLSHandshakeStart struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventTLSHandshakeStart) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventTLSHandshakeStart) Name() string {
|
||||||
|
return "tls_handshake_start"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventTLSHandshakeDone is the end of the TLS handshake.
|
||||||
|
type EventTLSHandshakeDone struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventTLSHandshakeDone) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventTLSHandshakeDone) Name() string {
|
||||||
|
return "tls_handshake_done"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventResolveStart is the beginning of a DNS lookup operation.
|
||||||
|
type EventResolveStart struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventResolveStart) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventResolveStart) Name() string {
|
||||||
|
return "resolve_start"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventResolveDone is the end of a DNS lookup operation.
|
||||||
|
type EventResolveDone struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventResolveDone) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventResolveDone) Name() string {
|
||||||
|
return "resolve_done"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventDNSRoundTripStart is the start of a DNS round trip.
|
||||||
|
type EventDNSRoundTripStart struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventDNSRoundTripStart) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventDNSRoundTripStart) Name() string {
|
||||||
|
return "dns_round_trip_start"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventDNSRoundTripDone is the end of a DNS round trip.
|
||||||
|
type EventDNSRoundTripDone struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventDNSRoundTripDone) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventDNSRoundTripDone) Name() string {
|
||||||
|
return "dns_round_trip_done"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventQUICHandshakeStart is the start of a QUIC handshake.
|
||||||
|
type EventQUICHandshakeStart struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventQUICHandshakeStart) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventQUICHandshakeStart) Name() string {
|
||||||
|
return "quic_handshake_start"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventQUICHandshakeDone is the end of a QUIC handshake.
|
||||||
|
type EventQUICHandshakeDone struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventQUICHandshakeDone) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventQUICHandshakeDone) Name() string {
|
||||||
|
return "quic_handshake_done"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventWriteToOperation summarizes the WriteTo operation.
|
||||||
|
type EventWriteToOperation struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventWriteToOperation) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventWriteToOperation) Name() string {
|
||||||
|
return netxlite.WriteToOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventReadFromOperation summarizes the ReadFrom operation.
|
||||||
|
type EventReadFromOperation struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventReadFromOperation) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventReadFromOperation) Name() string {
|
||||||
|
return netxlite.ReadFromOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPRequestMetadata contains HTTP request metadata.
|
||||||
|
type EventHTTPRequestMetadata struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPRequestMetadata) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPRequestMetadata) Name() string {
|
||||||
|
return "http_request_metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPResponseMetadata contains HTTP response metadata.
|
||||||
|
type EventHTTPResponseMetadata struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPResponseMetadata) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPResponseMetadata) Name() string {
|
||||||
|
return "http_response_metadata"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPTransactionStart is the beginning of an HTTP transaction.
|
||||||
|
type EventHTTPTransactionStart struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPTransactionStart) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPTransactionStart) Name() string {
|
||||||
|
return "http_transaction_start"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPTransactionDone is the end of an HTTP transaction.
|
||||||
|
type EventHTTPTransactionDone struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPTransactionDone) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPTransactionDone) Name() string {
|
||||||
|
return "http_transaction_done"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPRequestBodySnapshot contains a snapshot of the request body.
|
||||||
|
type EventHTTPRequestBodySnapshot struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPRequestBodySnapshot) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPRequestBodySnapshot) Name() string {
|
||||||
|
return "http_request_body_snapshot"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventHTTPResponseBodySnapshot contains a snapshot of the response body.
|
||||||
|
type EventHTTPResponseBodySnapshot struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPResponseBodySnapshot) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventHTTPResponseBodySnapshot) Name() string {
|
||||||
|
return "http_response_body_snapshot"
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventConnectOperation contains information about the connect operation.
|
||||||
|
type EventConnectOperation struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventConnectOperation) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventConnectOperation) Name() string {
|
||||||
|
return netxlite.ConnectOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventReadOperation contains information about a read operation.
|
||||||
|
type EventReadOperation struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventReadOperation) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventReadOperation) Name() string {
|
||||||
|
return netxlite.ReadOperation
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventWriteOperation contains information about a write operation.
|
||||||
|
type EventWriteOperation struct {
|
||||||
|
V *EventValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventWriteOperation) Value() *EventValue {
|
||||||
|
return ev.V
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ev *EventWriteOperation) Name() string {
|
||||||
|
return netxlite.WriteOperation
|
||||||
|
}
|
||||||
|
|
||||||
// Event is one of the events within a trace
|
// Event is one of the events within a trace
|
||||||
type Event struct {
|
type EventValue struct {
|
||||||
Addresses []string `json:",omitempty"`
|
Addresses []string `json:",omitempty"`
|
||||||
Address string `json:",omitempty"`
|
Address string `json:",omitempty"`
|
||||||
DNSQuery []byte `json:",omitempty"`
|
DNSQuery []byte `json:",omitempty"`
|
||||||
|
@ -21,7 +279,6 @@ type Event struct {
|
||||||
HTTPStatusCode int `json:",omitempty"`
|
HTTPStatusCode int `json:",omitempty"`
|
||||||
HTTPURL string `json:",omitempty"`
|
HTTPURL string `json:",omitempty"`
|
||||||
Hostname string `json:",omitempty"`
|
Hostname string `json:",omitempty"`
|
||||||
Name string `json:",omitempty"`
|
|
||||||
NoTLSVerify bool `json:",omitempty"`
|
NoTLSVerify bool `json:",omitempty"`
|
||||||
NumBytes int `json:",omitempty"`
|
NumBytes int `json:",omitempty"`
|
||||||
Proto string `json:",omitempty"`
|
Proto string `json:",omitempty"`
|
||||||
|
|
|
@ -24,24 +24,22 @@ type SaverMetadataHTTPTransport struct {
|
||||||
|
|
||||||
// RoundTrip implements RoundTripper.RoundTrip
|
// RoundTrip implements RoundTripper.RoundTrip
|
||||||
func (txp SaverMetadataHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (txp SaverMetadataHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPRequestMetadata{&EventValue{
|
||||||
HTTPHeaders: httpCloneHeaders(req),
|
HTTPHeaders: httpCloneHeaders(req),
|
||||||
HTTPMethod: req.Method,
|
HTTPMethod: req.Method,
|
||||||
HTTPURL: req.URL.String(),
|
HTTPURL: req.URL.String(),
|
||||||
Transport: txp.HTTPTransport.Network(),
|
Transport: txp.HTTPTransport.Network(),
|
||||||
Name: "http_request_metadata",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
resp, err := txp.HTTPTransport.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPResponseMetadata{&EventValue{
|
||||||
HTTPHeaders: resp.Header,
|
HTTPHeaders: resp.Header,
|
||||||
HTTPStatusCode: resp.StatusCode,
|
HTTPStatusCode: resp.StatusCode,
|
||||||
Name: "http_response_metadata",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,16 +65,14 @@ type SaverTransactionHTTPTransport struct {
|
||||||
|
|
||||||
// RoundTrip implements RoundTripper.RoundTrip
|
// RoundTrip implements RoundTripper.RoundTrip
|
||||||
func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
func (txp SaverTransactionHTTPTransport) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPTransactionStart{&EventValue{
|
||||||
Name: "http_transaction_start",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
resp, err := txp.HTTPTransport.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPTransactionDone{&EventValue{
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: "http_transaction_done",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
return resp, err
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,12 +97,11 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Body = httpSaverCompose(data, req.Body)
|
req.Body = httpSaverCompose(data, req.Body)
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPRequestBodySnapshot{&EventValue{
|
||||||
DataIsTruncated: len(data) >= snapsize,
|
DataIsTruncated: len(data) >= snapsize,
|
||||||
Data: data,
|
Data: data,
|
||||||
Name: "http_request_body_snapshot",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
}
|
}
|
||||||
resp, err := txp.HTTPTransport.RoundTrip(req)
|
resp, err := txp.HTTPTransport.RoundTrip(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -118,12 +113,11 @@ func (txp SaverBodyHTTPTransport) RoundTrip(req *http.Request) (*http.Response,
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp.Body = httpSaverCompose(data, resp.Body)
|
resp.Body = httpSaverCompose(data, resp.Body)
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventHTTPResponseBodySnapshot{&EventValue{
|
||||||
DataIsTruncated: len(data) >= snapsize,
|
DataIsTruncated: len(data) >= snapsize,
|
||||||
Data: data,
|
Data: data,
|
||||||
Name: "http_response_body_snapshot",
|
|
||||||
Time: time.Now(),
|
Time: time.Now(),
|
||||||
})
|
}})
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,32 +41,32 @@ func TestSaverMetadataSuccess(t *testing.T) {
|
||||||
t.Fatal("expected two events")
|
t.Fatal("expected two events")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if ev[0].HTTPMethod != "GET" {
|
if ev[0].Value().HTTPMethod != "GET" {
|
||||||
t.Fatal("unexpected Method")
|
t.Fatal("unexpected Method")
|
||||||
}
|
}
|
||||||
if len(ev[0].HTTPHeaders) <= 0 {
|
if len(ev[0].Value().HTTPHeaders) <= 0 {
|
||||||
t.Fatal("unexpected Headers")
|
t.Fatal("unexpected Headers")
|
||||||
}
|
}
|
||||||
if ev[0].HTTPURL != "https://www.google.com" {
|
if ev[0].Value().HTTPURL != "https://www.google.com" {
|
||||||
t.Fatal("unexpected URL")
|
t.Fatal("unexpected URL")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_request_metadata" {
|
if ev[0].Name() != "http_request_metadata" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if ev[1].HTTPStatusCode != 200 {
|
if ev[1].Value().HTTPStatusCode != 200 {
|
||||||
t.Fatal("unexpected StatusCode")
|
t.Fatal("unexpected StatusCode")
|
||||||
}
|
}
|
||||||
if len(ev[1].HTTPHeaders) <= 0 {
|
if len(ev[1].Value().HTTPHeaders) <= 0 {
|
||||||
t.Fatal("unexpected Headers")
|
t.Fatal("unexpected Headers")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "http_response_metadata" {
|
if ev[1].Name() != "http_response_metadata" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -96,19 +96,19 @@ func TestSaverMetadataFailure(t *testing.T) {
|
||||||
if len(ev) != 1 {
|
if len(ev) != 1 {
|
||||||
t.Fatal("expected one event")
|
t.Fatal("expected one event")
|
||||||
}
|
}
|
||||||
if ev[0].HTTPMethod != "GET" {
|
if ev[0].Value().HTTPMethod != "GET" {
|
||||||
t.Fatal("unexpected Method")
|
t.Fatal("unexpected Method")
|
||||||
}
|
}
|
||||||
if len(ev[0].HTTPHeaders) <= 0 {
|
if len(ev[0].Value().HTTPHeaders) <= 0 {
|
||||||
t.Fatal("unexpected Headers")
|
t.Fatal("unexpected Headers")
|
||||||
}
|
}
|
||||||
if ev[0].HTTPURL != "http://www.google.com" {
|
if ev[0].Value().HTTPURL != "http://www.google.com" {
|
||||||
t.Fatal("unexpected URL")
|
t.Fatal("unexpected URL")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_request_metadata" {
|
if ev[0].Name() != "http_request_metadata" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -138,20 +138,20 @@ func TestSaverTransactionSuccess(t *testing.T) {
|
||||||
t.Fatal("expected two events")
|
t.Fatal("expected two events")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if ev[0].Name != "http_transaction_start" {
|
if ev[0].Name() != "http_transaction_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
if ev[1].Err != nil {
|
if ev[1].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "http_transaction_done" {
|
if ev[1].Name() != "http_transaction_done" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,19 +180,19 @@ func TestSaverTransactionFailure(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("expected two events")
|
t.Fatal("expected two events")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_transaction_start" {
|
if ev[0].Name() != "http_transaction_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "http_transaction_done" {
|
if ev[1].Name() != "http_transaction_done" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !errors.Is(ev[1].Err, expected) {
|
if !errors.Is(ev[1].Value().Err, expected) {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,28 +242,28 @@ func TestSaverBodySuccess(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if string(ev[0].Data) != "dead" {
|
if string(ev[0].Value().Data) != "dead" {
|
||||||
t.Fatal("invalid Data")
|
t.Fatal("invalid Data")
|
||||||
}
|
}
|
||||||
if ev[0].DataIsTruncated != true {
|
if ev[0].Value().DataIsTruncated != true {
|
||||||
t.Fatal("invalid DataIsTruncated")
|
t.Fatal("invalid DataIsTruncated")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_request_body_snapshot" {
|
if ev[0].Name() != "http_request_body_snapshot" {
|
||||||
t.Fatal("invalid Name")
|
t.Fatal("invalid Name")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("invalid Time")
|
t.Fatal("invalid Time")
|
||||||
}
|
}
|
||||||
if string(ev[1].Data) != "abad" {
|
if string(ev[1].Value().Data) != "abad" {
|
||||||
t.Fatal("invalid Data")
|
t.Fatal("invalid Data")
|
||||||
}
|
}
|
||||||
if ev[1].DataIsTruncated != true {
|
if ev[1].Value().DataIsTruncated != true {
|
||||||
t.Fatal("invalid DataIsTruncated")
|
t.Fatal("invalid DataIsTruncated")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "http_response_body_snapshot" {
|
if ev[1].Name() != "http_response_body_snapshot" {
|
||||||
t.Fatal("invalid Name")
|
t.Fatal("invalid Name")
|
||||||
}
|
}
|
||||||
if ev[1].Time.Before(ev[0].Time) {
|
if ev[1].Value().Time.Before(ev[0].Value().Time) {
|
||||||
t.Fatal("invalid Time")
|
t.Fatal("invalid Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -324,16 +324,16 @@ func TestSaverBodyRoundTripError(t *testing.T) {
|
||||||
if len(ev) != 1 {
|
if len(ev) != 1 {
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if string(ev[0].Data) != "dead" {
|
if string(ev[0].Value().Data) != "dead" {
|
||||||
t.Fatal("invalid Data")
|
t.Fatal("invalid Data")
|
||||||
}
|
}
|
||||||
if ev[0].DataIsTruncated != true {
|
if ev[0].Value().DataIsTruncated != true {
|
||||||
t.Fatal("invalid DataIsTruncated")
|
t.Fatal("invalid DataIsTruncated")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_request_body_snapshot" {
|
if ev[0].Name() != "http_request_body_snapshot" {
|
||||||
t.Fatal("invalid Name")
|
t.Fatal("invalid Name")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("invalid Time")
|
t.Fatal("invalid Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -371,16 +371,16 @@ func TestSaverBodyResponseReadError(t *testing.T) {
|
||||||
if len(ev) != 1 {
|
if len(ev) != 1 {
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if string(ev[0].Data) != "dead" {
|
if string(ev[0].Value().Data) != "dead" {
|
||||||
t.Fatal("invalid Data")
|
t.Fatal("invalid Data")
|
||||||
}
|
}
|
||||||
if ev[0].DataIsTruncated != true {
|
if ev[0].Value().DataIsTruncated != true {
|
||||||
t.Fatal("invalid DataIsTruncated")
|
t.Fatal("invalid DataIsTruncated")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "http_request_body_snapshot" {
|
if ev[0].Name() != "http_request_body_snapshot" {
|
||||||
t.Fatal("invalid Name")
|
t.Fatal("invalid Name")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("invalid Time")
|
t.Fatal("invalid Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,34 +45,31 @@ func (h *QUICHandshakeSaver) DialContext(ctx context.Context, network string,
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
// TODO(bassosimone): in the future we probably want to also save
|
// TODO(bassosimone): in the future we probably want to also save
|
||||||
// information about what versions we're willing to accept.
|
// information about what versions we're willing to accept.
|
||||||
h.Saver.Write(Event{
|
h.Saver.Write(&EventQUICHandshakeStart{&EventValue{
|
||||||
Address: host,
|
Address: host,
|
||||||
Name: "quic_handshake_start",
|
|
||||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||||
Proto: network,
|
Proto: network,
|
||||||
TLSNextProtos: tlsCfg.NextProtos,
|
TLSNextProtos: tlsCfg.NextProtos,
|
||||||
TLSServerName: tlsCfg.ServerName,
|
TLSServerName: tlsCfg.ServerName,
|
||||||
Time: start,
|
Time: start,
|
||||||
})
|
}})
|
||||||
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
sess, err := h.QUICDialer.DialContext(ctx, network, host, tlsCfg, cfg)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(bassosimone): here we should save the peer certs
|
// TODO(bassosimone): here we should save the peer certs
|
||||||
h.Saver.Write(Event{
|
h.Saver.Write(&EventQUICHandshakeDone{&EventValue{
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: "quic_handshake_done",
|
|
||||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||||
TLSNextProtos: tlsCfg.NextProtos,
|
TLSNextProtos: tlsCfg.NextProtos,
|
||||||
TLSServerName: tlsCfg.ServerName,
|
TLSServerName: tlsCfg.ServerName,
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
state := quicConnectionState(sess)
|
state := quicConnectionState(sess)
|
||||||
h.Saver.Write(Event{
|
h.Saver.Write(&EventQUICHandshakeDone{&EventValue{
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Name: "quic_handshake_done",
|
|
||||||
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
NoTLSVerify: tlsCfg.InsecureSkipVerify,
|
||||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||||
|
@ -81,7 +78,7 @@ func (h *QUICHandshakeSaver) DialContext(ctx context.Context, network string,
|
||||||
TLSServerName: tlsCfg.ServerName,
|
TLSServerName: tlsCfg.ServerName,
|
||||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return sess, nil
|
return sess, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,15 +141,14 @@ func (c *udpLikeConnSaver) WriteTo(p []byte, addr net.Addr) (int, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
count, err := c.UDPLikeConn.WriteTo(p, addr)
|
count, err := c.UDPLikeConn.WriteTo(p, addr)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
c.saver.Write(Event{
|
c.saver.Write(&EventWriteToOperation{&EventValue{
|
||||||
Address: addr.String(),
|
Address: addr.String(),
|
||||||
Data: p[:count],
|
Data: p[:count],
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
NumBytes: count,
|
NumBytes: count,
|
||||||
Name: netxlite.WriteToOperation,
|
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return count, err
|
return count, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,15 +160,14 @@ func (c *udpLikeConnSaver) ReadFrom(b []byte) (int, net.Addr, error) {
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
data = b[:n]
|
data = b[:n]
|
||||||
}
|
}
|
||||||
c.saver.Write(Event{
|
c.saver.Write(&EventReadFromOperation{&EventValue{
|
||||||
Address: c.safeAddrString(addr),
|
Address: c.safeAddrString(addr),
|
||||||
Data: data,
|
Data: data,
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
NumBytes: n,
|
NumBytes: n,
|
||||||
Name: netxlite.ReadFromOperation,
|
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return n, addr, err
|
return n, addr, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,34 +54,34 @@ func TestHandshakeSaverSuccess(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "quic_handshake_start" {
|
if ev[0].Name() != "quic_handshake_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[0].TLSServerName != quictesting.Domain {
|
if ev[0].Value().TLSServerName != quictesting.Domain {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[0].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[0].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[1].Err != nil {
|
if ev[1].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err", ev[1].Err)
|
t.Fatal("unexpected Err", ev[1].Value().Err)
|
||||||
}
|
}
|
||||||
if ev[1].Name != "quic_handshake_done" {
|
if ev[1].Name() != "quic_handshake_done" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[1].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[1].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[1].TLSServerName != quictesting.Domain {
|
if ev[1].Value().TLSServerName != quictesting.Domain {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if ev[1].Time.Before(ev[0].Time) {
|
if ev[1].Value().Time.Before(ev[0].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,14 +106,14 @@ func TestHandshakeSaverHostNameError(t *testing.T) {
|
||||||
t.Fatal("expected nil sess here")
|
t.Fatal("expected nil sess here")
|
||||||
}
|
}
|
||||||
for _, ev := range saver.Read() {
|
for _, ev := range saver.Read() {
|
||||||
if ev.Name != "quic_handshake_done" {
|
if ev.Name() != "quic_handshake_done" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.NoTLSVerify == true {
|
if ev.Value().NoTLSVerify == true {
|
||||||
t.Fatal("expected NoTLSVerify to be false")
|
t.Fatal("expected NoTLSVerify to be false")
|
||||||
}
|
}
|
||||||
if !strings.HasSuffix(ev.Err.Error(), "tls: handshake failure") {
|
if !strings.HasSuffix(ev.Value().Err.Error(), "tls: handshake failure") {
|
||||||
t.Fatal("unexpected error", ev.Err)
|
t.Fatal("unexpected error", ev.Value().Err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,25 +160,25 @@ func TestSystemDialerSuccessWithReadWrite(t *testing.T) {
|
||||||
}
|
}
|
||||||
last := len(ev) - 1
|
last := len(ev) - 1
|
||||||
for idx := 1; idx < last; idx++ {
|
for idx := 1; idx < last; idx++ {
|
||||||
if ev[idx].Data == nil {
|
if ev[idx].Value().Data == nil {
|
||||||
t.Fatal("unexpected Data")
|
t.Fatal("unexpected Data")
|
||||||
}
|
}
|
||||||
if ev[idx].Duration <= 0 {
|
if ev[idx].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[idx].Err != nil {
|
if ev[idx].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[idx].NumBytes <= 0 {
|
if ev[idx].Value().NumBytes <= 0 {
|
||||||
t.Fatal("unexpected NumBytes")
|
t.Fatal("unexpected NumBytes")
|
||||||
}
|
}
|
||||||
switch ev[idx].Name {
|
switch ev[idx].Name() {
|
||||||
case netxlite.ReadFromOperation, netxlite.WriteToOperation:
|
case netxlite.ReadFromOperation, netxlite.WriteToOperation:
|
||||||
default:
|
default:
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[idx].Time.Before(ev[idx-1].Time) {
|
if ev[idx].Value().Time.Before(ev[idx-1].Value().Time) {
|
||||||
t.Fatal("unexpected Time", ev[idx].Time, ev[idx-1].Time)
|
t.Fatal("unexpected Time", ev[idx].Value().Time, ev[idx-1].Value().Time)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,25 +39,23 @@ func (s *Saver) WrapResolver(r model.Resolver) model.Resolver {
|
||||||
// LookupHost implements Resolver.LookupHost
|
// LookupHost implements Resolver.LookupHost
|
||||||
func (r *SaverResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
|
func (r *SaverResolver) LookupHost(ctx context.Context, hostname string) ([]string, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
r.Saver.Write(Event{
|
r.Saver.Write(&EventResolveStart{&EventValue{
|
||||||
Address: r.Resolver.Address(),
|
Address: r.Resolver.Address(),
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
Name: "resolve_start",
|
|
||||||
Proto: r.Resolver.Network(),
|
Proto: r.Resolver.Network(),
|
||||||
Time: start,
|
Time: start,
|
||||||
})
|
}})
|
||||||
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
addrs, err := r.Resolver.LookupHost(ctx, hostname)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
r.Saver.Write(Event{
|
r.Saver.Write(&EventResolveDone{&EventValue{
|
||||||
Addresses: addrs,
|
Addresses: addrs,
|
||||||
Address: r.Resolver.Address(),
|
Address: r.Resolver.Address(),
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
Hostname: hostname,
|
Hostname: hostname,
|
||||||
Name: "resolve_done",
|
|
||||||
Proto: r.Resolver.Network(),
|
Proto: r.Resolver.Network(),
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return addrs, err
|
return addrs, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,25 +109,23 @@ func (s *Saver) WrapDNSTransport(txp model.DNSTransport) model.DNSTransport {
|
||||||
func (txp *SaverDNSTransport) RoundTrip(
|
func (txp *SaverDNSTransport) RoundTrip(
|
||||||
ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
ctx context.Context, query model.DNSQuery) (model.DNSResponse, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventDNSRoundTripStart{&EventValue{
|
||||||
Address: txp.DNSTransport.Address(),
|
Address: txp.DNSTransport.Address(),
|
||||||
DNSQuery: dnsMaybeQueryBytes(query),
|
DNSQuery: dnsMaybeQueryBytes(query),
|
||||||
Name: "dns_round_trip_start",
|
|
||||||
Proto: txp.DNSTransport.Network(),
|
Proto: txp.DNSTransport.Network(),
|
||||||
Time: start,
|
Time: start,
|
||||||
})
|
}})
|
||||||
response, err := txp.DNSTransport.RoundTrip(ctx, query)
|
response, err := txp.DNSTransport.RoundTrip(ctx, query)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
txp.Saver.Write(Event{
|
txp.Saver.Write(&EventDNSRoundTripDone{&EventValue{
|
||||||
Address: txp.DNSTransport.Address(),
|
Address: txp.DNSTransport.Address(),
|
||||||
DNSQuery: dnsMaybeQueryBytes(query),
|
DNSQuery: dnsMaybeQueryBytes(query),
|
||||||
DNSReply: dnsMaybeResponseBytes(response),
|
DNSReply: dnsMaybeResponseBytes(response),
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: "dns_round_trip_done",
|
|
||||||
Proto: txp.DNSTransport.Network(),
|
Proto: txp.DNSTransport.Network(),
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return response, err
|
return response, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,31 +29,31 @@ func TestSaverResolverFailure(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("expected number of events")
|
t.Fatal("expected number of events")
|
||||||
}
|
}
|
||||||
if ev[0].Hostname != "www.google.com" {
|
if ev[0].Value().Hostname != "www.google.com" {
|
||||||
t.Fatal("unexpected Hostname")
|
t.Fatal("unexpected Hostname")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "resolve_start" {
|
if ev[0].Name() != "resolve_start" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
if ev[1].Addresses != nil {
|
if ev[1].Value().Addresses != nil {
|
||||||
t.Fatal("unexpected Addresses")
|
t.Fatal("unexpected Addresses")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if !errors.Is(ev[1].Err, expected) {
|
if !errors.Is(ev[1].Value().Err, expected) {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Hostname != "www.google.com" {
|
if ev[1].Value().Hostname != "www.google.com" {
|
||||||
t.Fatal("unexpected Hostname")
|
t.Fatal("unexpected Hostname")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "resolve_done" {
|
if ev[1].Name() != "resolve_done" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -73,31 +73,31 @@ func TestSaverResolverSuccess(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("expected number of events")
|
t.Fatal("expected number of events")
|
||||||
}
|
}
|
||||||
if ev[0].Hostname != "www.google.com" {
|
if ev[0].Value().Hostname != "www.google.com" {
|
||||||
t.Fatal("unexpected Hostname")
|
t.Fatal("unexpected Hostname")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "resolve_start" {
|
if ev[0].Name() != "resolve_start" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[1].Addresses, expected) {
|
if !reflect.DeepEqual(ev[1].Value().Addresses, expected) {
|
||||||
t.Fatal("unexpected Addresses")
|
t.Fatal("unexpected Addresses")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[1].Err != nil {
|
if ev[1].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Hostname != "www.google.com" {
|
if ev[1].Value().Hostname != "www.google.com" {
|
||||||
t.Fatal("unexpected Hostname")
|
t.Fatal("unexpected Hostname")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "resolve_done" {
|
if ev[1].Name() != "resolve_done" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,31 +133,31 @@ func TestSaverDNSTransportFailure(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("expected number of events")
|
t.Fatal("expected number of events")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(ev[0].DNSQuery, rawQuery) {
|
if !bytes.Equal(ev[0].Value().DNSQuery, rawQuery) {
|
||||||
t.Fatal("unexpected DNSQuery")
|
t.Fatal("unexpected DNSQuery")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "dns_round_trip_start" {
|
if ev[0].Name() != "dns_round_trip_start" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(ev[1].DNSQuery, rawQuery) {
|
if !bytes.Equal(ev[1].Value().DNSQuery, rawQuery) {
|
||||||
t.Fatal("unexpected DNSQuery")
|
t.Fatal("unexpected DNSQuery")
|
||||||
}
|
}
|
||||||
if ev[1].DNSReply != nil {
|
if ev[1].Value().DNSReply != nil {
|
||||||
t.Fatal("unexpected DNSReply")
|
t.Fatal("unexpected DNSReply")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if !errors.Is(ev[1].Err, expected) {
|
if !errors.Is(ev[1].Value().Err, expected) {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "dns_round_trip_done" {
|
if ev[1].Name() != "dns_round_trip_done" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -198,31 +198,31 @@ func TestSaverDNSTransportSuccess(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("expected number of events")
|
t.Fatal("expected number of events")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(ev[0].DNSQuery, rawQuery) {
|
if !bytes.Equal(ev[0].Value().DNSQuery, rawQuery) {
|
||||||
t.Fatal("unexpected DNSQuery")
|
t.Fatal("unexpected DNSQuery")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "dns_round_trip_start" {
|
if ev[0].Name() != "dns_round_trip_start" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[0].Time.Before(time.Now()) {
|
if !ev[0].Value().Time.Before(time.Now()) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(ev[1].DNSQuery, rawQuery) {
|
if !bytes.Equal(ev[1].Value().DNSQuery, rawQuery) {
|
||||||
t.Fatal("unexpected DNSQuery")
|
t.Fatal("unexpected DNSQuery")
|
||||||
}
|
}
|
||||||
if !bytes.Equal(ev[1].DNSReply, expected) {
|
if !bytes.Equal(ev[1].Value().DNSReply, expected) {
|
||||||
t.Fatal("unexpected DNSReply")
|
t.Fatal("unexpected DNSReply")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[1].Err != nil {
|
if ev[1].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "dns_round_trip_done" {
|
if ev[1].Name() != "dns_round_trip_done" {
|
||||||
t.Fatal("unexpected name")
|
t.Fatal("unexpected name")
|
||||||
}
|
}
|
||||||
if !ev[1].Time.After(ev[0].Time) {
|
if !ev[1].Value().Time.After(ev[0].Value().Time) {
|
||||||
t.Fatal("the saved time is wrong")
|
t.Fatal("the saved time is wrong")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ func TestSaver(t *testing.T) {
|
||||||
wg.Add(parallel)
|
wg.Add(parallel)
|
||||||
for idx := 0; idx < parallel; idx++ {
|
for idx := 0; idx < parallel; idx++ {
|
||||||
go func() {
|
go func() {
|
||||||
saver.Write(Event{})
|
saver.Write(&EventReadFromOperation{&EventValue{}})
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,21 +44,19 @@ func (s *Saver) WrapTLSHandshaker(thx model.TLSHandshaker) model.TLSHandshaker {
|
||||||
func (h *SaverTLSHandshaker) Handshake(
|
func (h *SaverTLSHandshaker) Handshake(
|
||||||
ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
h.Saver.Write(Event{
|
h.Saver.Write(&EventTLSHandshakeStart{&EventValue{
|
||||||
Name: "tls_handshake_start",
|
|
||||||
NoTLSVerify: config.InsecureSkipVerify,
|
NoTLSVerify: config.InsecureSkipVerify,
|
||||||
TLSNextProtos: config.NextProtos,
|
TLSNextProtos: config.NextProtos,
|
||||||
TLSServerName: config.ServerName,
|
TLSServerName: config.ServerName,
|
||||||
Time: start,
|
Time: start,
|
||||||
})
|
}})
|
||||||
remoteAddr := conn.RemoteAddr().String()
|
remoteAddr := conn.RemoteAddr().String()
|
||||||
tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
|
tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
|
||||||
stop := time.Now()
|
stop := time.Now()
|
||||||
h.Saver.Write(Event{
|
h.Saver.Write(&EventTLSHandshakeDone{&EventValue{
|
||||||
Address: remoteAddr,
|
Address: remoteAddr,
|
||||||
Duration: stop.Sub(start),
|
Duration: stop.Sub(start),
|
||||||
Err: err,
|
Err: err,
|
||||||
Name: "tls_handshake_done",
|
|
||||||
NoTLSVerify: config.InsecureSkipVerify,
|
NoTLSVerify: config.InsecureSkipVerify,
|
||||||
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
TLSCipherSuite: netxlite.TLSCipherSuiteString(state.CipherSuite),
|
||||||
TLSNegotiatedProto: state.NegotiatedProtocol,
|
TLSNegotiatedProto: state.NegotiatedProtocol,
|
||||||
|
@ -67,7 +65,7 @@ func (h *SaverTLSHandshaker) Handshake(
|
||||||
TLSServerName: config.ServerName,
|
TLSServerName: config.ServerName,
|
||||||
TLSVersion: netxlite.TLSVersionString(state.Version),
|
TLSVersion: netxlite.TLSVersionString(state.Version),
|
||||||
Time: stop,
|
Time: stop,
|
||||||
})
|
}})
|
||||||
return tlsconn, state, err
|
return tlsconn, state, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,69 +39,69 @@ func TestSaverTLSHandshakerSuccessWithReadWrite(t *testing.T) {
|
||||||
// events because network conditions may influence that
|
// events because network conditions may influence that
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "tls_handshake_start" {
|
if ev[0].Name() != "tls_handshake_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[0].TLSServerName != "www.google.com" {
|
if ev[0].Value().TLSServerName != "www.google.com" {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[0].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[0].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
last := len(ev) - 1
|
last := len(ev) - 1
|
||||||
for idx := 1; idx < last; idx++ {
|
for idx := 1; idx < last; idx++ {
|
||||||
if ev[idx].Data == nil {
|
if ev[idx].Value().Data == nil {
|
||||||
t.Fatal("unexpected Data")
|
t.Fatal("unexpected Data")
|
||||||
}
|
}
|
||||||
if ev[idx].Duration <= 0 {
|
if ev[idx].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[idx].Err != nil {
|
if ev[idx].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[idx].NumBytes <= 0 {
|
if ev[idx].Value().NumBytes <= 0 {
|
||||||
t.Fatal("unexpected NumBytes")
|
t.Fatal("unexpected NumBytes")
|
||||||
}
|
}
|
||||||
switch ev[idx].Name {
|
switch ev[idx].Name() {
|
||||||
case netxlite.ReadOperation, netxlite.WriteOperation:
|
case netxlite.ReadOperation, netxlite.WriteOperation:
|
||||||
default:
|
default:
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[idx].Time.Before(ev[idx-1].Time) {
|
if ev[idx].Value().Time.Before(ev[idx-1].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ev[last].Duration <= 0 {
|
if ev[last].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[last].Err != nil {
|
if ev[last].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[last].Name != "tls_handshake_done" {
|
if ev[last].Name() != "tls_handshake_done" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[last].TLSCipherSuite == "" {
|
if ev[last].Value().TLSCipherSuite == "" {
|
||||||
t.Fatal("unexpected TLSCipherSuite")
|
t.Fatal("unexpected TLSCipherSuite")
|
||||||
}
|
}
|
||||||
if ev[last].TLSNegotiatedProto != "h2" {
|
if ev[last].Value().TLSNegotiatedProto != "h2" {
|
||||||
t.Fatal("unexpected TLSNegotiatedProto")
|
t.Fatal("unexpected TLSNegotiatedProto")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[last].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[last].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[last].TLSPeerCerts == nil {
|
if ev[last].Value().TLSPeerCerts == nil {
|
||||||
t.Fatal("unexpected TLSPeerCerts")
|
t.Fatal("unexpected TLSPeerCerts")
|
||||||
}
|
}
|
||||||
if ev[last].TLSServerName != "www.google.com" {
|
if ev[last].Value().TLSServerName != "www.google.com" {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if ev[last].TLSVersion == "" {
|
if ev[last].Value().TLSVersion == "" {
|
||||||
t.Fatal("unexpected TLSVersion")
|
t.Fatal("unexpected TLSVersion")
|
||||||
}
|
}
|
||||||
if ev[last].Time.Before(ev[last-1].Time) {
|
if ev[last].Value().Time.Before(ev[last-1].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,46 +126,46 @@ func TestSaverTLSHandshakerSuccess(t *testing.T) {
|
||||||
if len(ev) != 2 {
|
if len(ev) != 2 {
|
||||||
t.Fatal("unexpected number of events")
|
t.Fatal("unexpected number of events")
|
||||||
}
|
}
|
||||||
if ev[0].Name != "tls_handshake_start" {
|
if ev[0].Name() != "tls_handshake_start" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[0].TLSServerName != "www.google.com" {
|
if ev[0].Value().TLSServerName != "www.google.com" {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[0].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[0].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[0].Time.After(time.Now()) {
|
if ev[0].Value().Time.After(time.Now()) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
if ev[1].Duration <= 0 {
|
if ev[1].Value().Duration <= 0 {
|
||||||
t.Fatal("unexpected Duration")
|
t.Fatal("unexpected Duration")
|
||||||
}
|
}
|
||||||
if ev[1].Err != nil {
|
if ev[1].Value().Err != nil {
|
||||||
t.Fatal("unexpected Err")
|
t.Fatal("unexpected Err")
|
||||||
}
|
}
|
||||||
if ev[1].Name != "tls_handshake_done" {
|
if ev[1].Name() != "tls_handshake_done" {
|
||||||
t.Fatal("unexpected Name")
|
t.Fatal("unexpected Name")
|
||||||
}
|
}
|
||||||
if ev[1].TLSCipherSuite == "" {
|
if ev[1].Value().TLSCipherSuite == "" {
|
||||||
t.Fatal("unexpected TLSCipherSuite")
|
t.Fatal("unexpected TLSCipherSuite")
|
||||||
}
|
}
|
||||||
if ev[1].TLSNegotiatedProto != "h2" {
|
if ev[1].Value().TLSNegotiatedProto != "h2" {
|
||||||
t.Fatal("unexpected TLSNegotiatedProto")
|
t.Fatal("unexpected TLSNegotiatedProto")
|
||||||
}
|
}
|
||||||
if !reflect.DeepEqual(ev[1].TLSNextProtos, nextprotos) {
|
if !reflect.DeepEqual(ev[1].Value().TLSNextProtos, nextprotos) {
|
||||||
t.Fatal("unexpected TLSNextProtos")
|
t.Fatal("unexpected TLSNextProtos")
|
||||||
}
|
}
|
||||||
if ev[1].TLSPeerCerts == nil {
|
if ev[1].Value().TLSPeerCerts == nil {
|
||||||
t.Fatal("unexpected TLSPeerCerts")
|
t.Fatal("unexpected TLSPeerCerts")
|
||||||
}
|
}
|
||||||
if ev[1].TLSServerName != "www.google.com" {
|
if ev[1].Value().TLSServerName != "www.google.com" {
|
||||||
t.Fatal("unexpected TLSServerName")
|
t.Fatal("unexpected TLSServerName")
|
||||||
}
|
}
|
||||||
if ev[1].TLSVersion == "" {
|
if ev[1].Value().TLSVersion == "" {
|
||||||
t.Fatal("unexpected TLSVersion")
|
t.Fatal("unexpected TLSVersion")
|
||||||
}
|
}
|
||||||
if ev[1].Time.Before(ev[0].Time) {
|
if ev[1].Value().Time.Before(ev[0].Value().Time) {
|
||||||
t.Fatal("unexpected Time")
|
t.Fatal("unexpected Time")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,13 +188,13 @@ func TestSaverTLSHandshakerHostnameError(t *testing.T) {
|
||||||
t.Fatal("expected nil conn here")
|
t.Fatal("expected nil conn here")
|
||||||
}
|
}
|
||||||
for _, ev := range saver.Read() {
|
for _, ev := range saver.Read() {
|
||||||
if ev.Name != "tls_handshake_done" {
|
if ev.Name() != "tls_handshake_done" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.NoTLSVerify == true {
|
if ev.Value().NoTLSVerify == true {
|
||||||
t.Fatal("expected NoTLSVerify to be false")
|
t.Fatal("expected NoTLSVerify to be false")
|
||||||
}
|
}
|
||||||
if len(ev.TLSPeerCerts) < 1 {
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
||||||
t.Fatal("expected at least a certificate here")
|
t.Fatal("expected at least a certificate here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -218,13 +218,13 @@ func TestSaverTLSHandshakerInvalidCertError(t *testing.T) {
|
||||||
t.Fatal("expected nil conn here")
|
t.Fatal("expected nil conn here")
|
||||||
}
|
}
|
||||||
for _, ev := range saver.Read() {
|
for _, ev := range saver.Read() {
|
||||||
if ev.Name != "tls_handshake_done" {
|
if ev.Name() != "tls_handshake_done" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.NoTLSVerify == true {
|
if ev.Value().NoTLSVerify == true {
|
||||||
t.Fatal("expected NoTLSVerify to be false")
|
t.Fatal("expected NoTLSVerify to be false")
|
||||||
}
|
}
|
||||||
if len(ev.TLSPeerCerts) < 1 {
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
||||||
t.Fatal("expected at least a certificate here")
|
t.Fatal("expected at least a certificate here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -248,13 +248,13 @@ func TestSaverTLSHandshakerAuthorityError(t *testing.T) {
|
||||||
t.Fatal("expected nil conn here")
|
t.Fatal("expected nil conn here")
|
||||||
}
|
}
|
||||||
for _, ev := range saver.Read() {
|
for _, ev := range saver.Read() {
|
||||||
if ev.Name != "tls_handshake_done" {
|
if ev.Name() != "tls_handshake_done" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.NoTLSVerify == true {
|
if ev.Value().NoTLSVerify == true {
|
||||||
t.Fatal("expected NoTLSVerify to be false")
|
t.Fatal("expected NoTLSVerify to be false")
|
||||||
}
|
}
|
||||||
if len(ev.TLSPeerCerts) < 1 {
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
||||||
t.Fatal("expected at least a certificate here")
|
t.Fatal("expected at least a certificate here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,13 +280,13 @@ func TestSaverTLSHandshakerNoTLSVerify(t *testing.T) {
|
||||||
}
|
}
|
||||||
conn.Close()
|
conn.Close()
|
||||||
for _, ev := range saver.Read() {
|
for _, ev := range saver.Read() {
|
||||||
if ev.Name != "tls_handshake_done" {
|
if ev.Name() != "tls_handshake_done" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if ev.NoTLSVerify != true {
|
if ev.Value().NoTLSVerify != true {
|
||||||
t.Fatal("expected NoTLSVerify to be true")
|
t.Fatal("expected NoTLSVerify to be true")
|
||||||
}
|
}
|
||||||
if len(ev.TLSPeerCerts) < 1 {
|
if len(ev.Value().TLSPeerCerts) < 1 {
|
||||||
t.Fatal("expected at least a certificate here")
|
t.Fatal("expected at least a certificate here")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user