fix(measurexlite): expose TCP connect event (#934)

See https://github.com/ooni/probe/issues/2254
This commit is contained in:
Simone Basso 2022-09-05 12:21:16 +02:00 committed by GitHub
parent 3766ab2721
commit a72a9284f1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 26 deletions

View File

@ -53,6 +53,8 @@ func (tx *Trace) OnConnectDone(
started time.Time, network, domain, remoteAddr string, err error, finished time.Time) {
switch network {
case "tcp", "tcp4", "tcp6":
// insert into the tcpConnect buffer
select {
case tx.tcpConnect <- NewArchivalTCPConnectResult(
tx.Index,
@ -63,6 +65,23 @@ func (tx *Trace) OnConnectDone(
):
default: // buffer is full
}
// insert into the networkEvent buffer
// see https://github.com/ooni/probe/issues/2254
select {
case tx.networkEvent <- NewArchivalNetworkEvent(
tx.Index,
started.Sub(tx.ZeroTime),
netxlite.ConnectOperation,
"tcp",
remoteAddr,
0,
err,
finished.Sub(tx.ZeroTime),
):
default: // buffer is full
}
default:
// ignore UDP connect attempts because they cannot fail
// in interesting ways that make sense for censorship

View File

@ -97,11 +97,14 @@ func TestNewDialerWithoutResolver(t *testing.T) {
if conn != nil {
t.Fatal("expected nil conn")
}
expectedFailure := netxlite.FailureInterrupted
t.Run("for TCPConnect", func(t *testing.T) {
events := trace.TCPConnects()
if len(events) != 1 {
t.Fatal("expected to see single TCPConnect event")
}
expectedFailure := netxlite.FailureInterrupted
expect := &model.ArchivalTCPConnectResult{
IP: "1.1.1.1",
Port: 443,
@ -118,10 +121,35 @@ func TestNewDialerWithoutResolver(t *testing.T) {
}
})
t.Run("for NetworkEvents", func(t *testing.T) {
events := trace.NetworkEvents()
if len(events) != 1 {
t.Fatal("expected to see single NetworkEvent event")
}
expectedFailure := netxlite.FailureInterrupted
expect := &model.ArchivalNetworkEvent{
Address: "1.1.1.1:443",
Failure: &expectedFailure,
NumBytes: 0,
Operation: netxlite.ConnectOperation,
Proto: "tcp",
T0: 0,
T: time.Second.Seconds(),
TransactionID: 0,
Tags: []string{},
}
got := events[0]
if diff := cmp.Diff(expect, got); diff != "" {
t.Fatal(diff)
}
})
})
t.Run("DialContext discards events when buffer is full", func(t *testing.T) {
zeroTime := time.Now()
trace := NewTrace(0, zeroTime)
trace.tcpConnect = make(chan *model.ArchivalTCPConnectResult) // no buffer
trace.networkEvent = make(chan *model.ArchivalNetworkEvent) // ditto
dialer := trace.NewDialerWithoutResolver(model.DiscardLogger)
ctx, cancel := context.WithCancel(context.Background())
cancel() // we cancel immediately so connect is ~instantaneous
@ -132,12 +160,22 @@ func TestNewDialerWithoutResolver(t *testing.T) {
if conn != nil {
t.Fatal("expected nil conn")
}
t.Run("for TCPConnect", func(t *testing.T) {
events := trace.TCPConnects()
if len(events) != 0 {
t.Fatal("expected to see no TCPConnect events")
}
})
t.Run("for NetworkEvents", func(t *testing.T) {
events := trace.NetworkEvents()
if len(events) != 0 {
t.Fatal("expected to see no NetworkEvent events")
}
})
})
t.Run("DialContext ignores UDP connect attempts", func(t *testing.T) {
zeroTime := time.Now()
trace := NewTrace(0, zeroTime)
@ -151,12 +189,22 @@ func TestNewDialerWithoutResolver(t *testing.T) {
if conn != nil {
t.Fatal("expected nil conn")
}
t.Run("for TCP connect", func(t *testing.T) {
events := trace.TCPConnects()
if len(events) != 0 {
t.Fatal("expected to see no TCPConnect events")
}
})
t.Run("for NetworkEvents", func(t *testing.T) {
events := trace.NetworkEvents()
if len(events) != 0 {
t.Fatal("expected to see no NetworkEvent events")
}
})
})
t.Run("DialContext uses a dialer without a resolver", func(t *testing.T) {
zeroTime := time.Now()
trace := NewTrace(0, zeroTime)