package archival // // Saves dial and net.Conn events // import ( "context" "net" "time" "github.com/ooni/probe-cli/v3/internal/model" "github.com/ooni/probe-cli/v3/internal/netxlite" ) // NetworkEvent contains a network event. This kind of events // are generated by Dialer, QUICDialer, Conn, QUICConn. type NetworkEvent struct { Count int Failure error Finished time.Time Network string Operation string RemoteAddr string Started time.Time } // DialContext dials with the given dialer with the given arguments // and stores the dial result inside of this saver. func (s *Saver) DialContext(ctx context.Context, dialer model.Dialer, network, address string) (net.Conn, error) { started := time.Now() conn, err := dialer.DialContext(ctx, network, address) s.appendNetworkEvent(&NetworkEvent{ Count: 0, Failure: err, Finished: time.Now(), Network: network, Operation: netxlite.ConnectOperation, RemoteAddr: address, Started: started, }) return conn, err } // Read reads from the given conn and stores the results in the saver. func (s *Saver) Read(conn net.Conn, buf []byte) (int, error) { network := conn.RemoteAddr().Network() remoteAddr := conn.RemoteAddr().String() started := time.Now() count, err := conn.Read(buf) s.appendNetworkEvent(&NetworkEvent{ Count: count, Failure: err, Finished: time.Now(), Network: network, Operation: netxlite.ReadOperation, RemoteAddr: remoteAddr, Started: started, }) return count, err } // Write writes to the given conn and stores the results into the saver. func (s *Saver) Write(conn net.Conn, buf []byte) (int, error) { network := conn.RemoteAddr().Network() remoteAddr := conn.RemoteAddr().String() started := time.Now() count, err := conn.Write(buf) s.appendNetworkEvent(&NetworkEvent{ Count: count, Failure: err, Finished: time.Now(), Network: network, Operation: netxlite.WriteOperation, RemoteAddr: remoteAddr, Started: started, }) return count, err } func (s *Saver) appendNetworkEvent(ev *NetworkEvent) { s.mu.Lock() s.trace.Network = append(s.trace.Network, ev) s.mu.Unlock() }