refactor(netx): towards removing connid, dialid, etc (#369)

I have verified that experiment/tor does not depend on this
functionality, therefore we can safely remove it.

Part of https://github.com/ooni/probe-engine/issues/897
This commit is contained in:
Simone Basso
2021-06-09 00:15:33 +02:00
committed by GitHub
parent 5b73230a6d
commit 3672e14d3e
4 changed files with 21 additions and 50 deletions
+1 -1
View File
@@ -66,7 +66,7 @@ func maybeWithMeasurementRoot(
// If you have others needs, manually build the chain you need.
func newDNSDialer(resolver dialer.Resolver) dialer.DNSDialer {
return dialer.DNSDialer{
Dialer: dialer.EmitterDialer{
Dialer: EmitterDialer{
Dialer: dialer.ErrorWrapperDialer{
Dialer: dialer.ByteCounterDialer{
Dialer: dialer.Default,
@@ -0,0 +1,116 @@
package netx
import (
"context"
"net"
"time"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/connid"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/dialid"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/modelx"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/transactionid"
"github.com/ooni/probe-cli/v3/internal/engine/netx/dialer"
)
// EmitterDialer is a Dialer that emits events
type EmitterDialer struct {
dialer.Dialer
}
// DialContext implements Dialer.DialContext
func (d EmitterDialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
start := time.Now()
conn, err := d.Dialer.DialContext(ctx, network, address)
stop := time.Now()
root := modelx.ContextMeasurementRootOrDefault(ctx)
root.Handler.OnMeasurement(modelx.Measurement{
Connect: &modelx.ConnectEvent{
ConnID: safeConnID(network, conn),
DialID: dialid.ContextDialID(ctx),
DurationSinceBeginning: stop.Sub(root.Beginning),
Error: err,
Network: network,
RemoteAddress: address,
SyscallDuration: stop.Sub(start),
TransactionID: transactionid.ContextTransactionID(ctx),
},
})
if err != nil {
return nil, err
}
return EmitterConn{
Conn: conn,
Beginning: root.Beginning,
Handler: root.Handler,
ID: safeConnID(network, conn),
}, nil
}
// EmitterConn is a net.Conn used to emit events
type EmitterConn struct {
net.Conn
Beginning time.Time
Handler modelx.Handler
ID int64
}
// Read implements net.Conn.Read
func (c EmitterConn) Read(b []byte) (n int, err error) {
start := time.Now()
n, err = c.Conn.Read(b)
stop := time.Now()
c.Handler.OnMeasurement(modelx.Measurement{
Read: &modelx.ReadEvent{
ConnID: c.ID,
DurationSinceBeginning: stop.Sub(c.Beginning),
Error: err,
NumBytes: int64(n),
SyscallDuration: stop.Sub(start),
},
})
return
}
// Write implements net.Conn.Write
func (c EmitterConn) Write(b []byte) (n int, err error) {
start := time.Now()
n, err = c.Conn.Write(b)
stop := time.Now()
c.Handler.OnMeasurement(modelx.Measurement{
Write: &modelx.WriteEvent{
ConnID: c.ID,
DurationSinceBeginning: stop.Sub(c.Beginning),
Error: err,
NumBytes: int64(n),
SyscallDuration: stop.Sub(start),
},
})
return
}
// Close implements net.Conn.Close
func (c EmitterConn) Close() (err error) {
start := time.Now()
err = c.Conn.Close()
stop := time.Now()
c.Handler.OnMeasurement(modelx.Measurement{
Close: &modelx.CloseEvent{
ConnID: c.ID,
DurationSinceBeginning: stop.Sub(c.Beginning),
Error: err,
SyscallDuration: stop.Sub(start),
},
})
return
}
func safeLocalAddress(conn net.Conn) (s string) {
if conn != nil && conn.LocalAddr() != nil {
s = conn.LocalAddr().String()
}
return
}
func safeConnID(network string, conn net.Conn) int64 {
return connid.Compute(network, safeLocalAddress(conn))
}
@@ -0,0 +1,188 @@
package netx
import (
"context"
"errors"
"io"
"net"
"testing"
"time"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/dialid"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/handlers"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/modelx"
"github.com/ooni/probe-cli/v3/internal/engine/legacy/netx/transactionid"
"github.com/ooni/probe-cli/v3/internal/engine/netx/mockablex"
)
func TestEmitterFailure(t *testing.T) {
ctx := dialid.WithDialID(context.Background())
saver := &handlers.SavingHandler{}
ctx = modelx.WithMeasurementRoot(ctx, &modelx.MeasurementRoot{
Beginning: time.Now(),
Handler: saver,
})
ctx = transactionid.WithTransactionID(ctx)
d := EmitterDialer{Dialer: mockablex.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return nil, io.EOF
},
}}
conn, err := d.DialContext(ctx, "tcp", "www.google.com:443")
if !errors.Is(err, io.EOF) {
t.Fatal("not the error we expected")
}
if conn != nil {
t.Fatal("expected a nil conn here")
}
events := saver.Read()
if len(events) != 1 {
t.Fatal("unexpected number of events saved")
}
if events[0].Connect == nil {
t.Fatal("expected non nil Connect")
}
conninfo := events[0].Connect
if conninfo.ConnID != 0 {
t.Fatal("unexpected ConnID value")
}
emitterCheckConnectEventCommon(t, conninfo, io.EOF)
}
func emitterCheckConnectEventCommon(
t *testing.T, conninfo *modelx.ConnectEvent, err error) {
if conninfo.DialID == 0 {
t.Fatal("unexpected DialID value")
}
if conninfo.DurationSinceBeginning == 0 {
t.Fatal("unexpected DurationSinceBeginning value")
}
if !errors.Is(conninfo.Error, err) {
t.Fatal("unexpected Error value")
}
if conninfo.Network != "tcp" {
t.Fatal("unexpected Network value")
}
if conninfo.RemoteAddress != "www.google.com:443" {
t.Fatal("unexpected Network value")
}
if conninfo.SyscallDuration == 0 {
t.Fatal("unexpected SyscallDuration value")
}
if conninfo.TransactionID == 0 {
t.Fatal("unexpected TransactionID value")
}
}
func TestEmitterSuccess(t *testing.T) {
ctx := dialid.WithDialID(context.Background())
saver := &handlers.SavingHandler{}
ctx = modelx.WithMeasurementRoot(ctx, &modelx.MeasurementRoot{
Beginning: time.Now(),
Handler: saver,
})
ctx = transactionid.WithTransactionID(ctx)
d := EmitterDialer{Dialer: mockablex.Dialer{
MockDialContext: func(ctx context.Context, network string, address string) (net.Conn, error) {
return &mockablex.Conn{
MockRead: func(b []byte) (int, error) {
return 0, io.EOF
},
MockWrite: func(b []byte) (int, error) {
return 0, io.EOF
},
MockClose: func() error {
return io.EOF
},
MockLocalAddr: func() net.Addr {
return &net.TCPAddr{Port: 12345}
},
}, nil
},
}}
conn, err := d.DialContext(ctx, "tcp", "www.google.com:443")
if err != nil {
t.Fatal("we expected no error")
}
if conn == nil {
t.Fatal("expected a non-nil conn here")
}
conn.Read(nil)
conn.Write(nil)
conn.Close()
events := saver.Read()
if len(events) != 4 {
t.Fatal("unexpected number of events saved")
}
if events[0].Connect == nil {
t.Fatal("expected non nil Connect")
}
conninfo := events[0].Connect
if conninfo.ConnID == 0 {
t.Fatal("unexpected ConnID value")
}
emitterCheckConnectEventCommon(t, conninfo, nil)
if events[1].Read == nil {
t.Fatal("expected non nil Read")
}
emitterCheckReadEvent(t, events[1].Read)
if events[2].Write == nil {
t.Fatal("expected non nil Write")
}
emitterCheckWriteEvent(t, events[2].Write)
if events[3].Close == nil {
t.Fatal("expected non nil Close")
}
emitterCheckCloseEvent(t, events[3].Close)
}
func emitterCheckReadEvent(t *testing.T, ev *modelx.ReadEvent) {
if ev.ConnID == 0 {
t.Fatal("unexpected ConnID")
}
if ev.DurationSinceBeginning == 0 {
t.Fatal("unexpected DurationSinceBeginning")
}
if !errors.Is(ev.Error, io.EOF) {
t.Fatal("unexpected Error")
}
if ev.NumBytes != 0 {
t.Fatal("unexpected NumBytes")
}
if ev.SyscallDuration == 0 {
t.Fatal("unexpected SyscallDuration")
}
}
func emitterCheckWriteEvent(t *testing.T, ev *modelx.WriteEvent) {
if ev.ConnID == 0 {
t.Fatal("unexpected ConnID")
}
if ev.DurationSinceBeginning == 0 {
t.Fatal("unexpected DurationSinceBeginning")
}
if !errors.Is(ev.Error, io.EOF) {
t.Fatal("unexpected Error")
}
if ev.NumBytes != 0 {
t.Fatal("unexpected NumBytes")
}
if ev.SyscallDuration == 0 {
t.Fatal("unexpected SyscallDuration")
}
}
func emitterCheckCloseEvent(t *testing.T, ev *modelx.CloseEvent) {
if ev.ConnID == 0 {
t.Fatal("unexpected ConnID")
}
if ev.DurationSinceBeginning == 0 {
t.Fatal("unexpected DurationSinceBeginning")
}
if !errors.Is(ev.Error, io.EOF) {
t.Fatal("unexpected Error")
}
if ev.SyscallDuration == 0 {
t.Fatal("unexpected SyscallDuration")
}
}