refactor(netx): move tlshandshaker logger to netxlite (#402)
Part of https://github.com/ooni/probe/issues/1505
This commit is contained in:
		
							parent
							
								
									acef18a955
								
							
						
					
					
						commit
						f1ee763f94
					
				@ -179,7 +179,7 @@ func NewTLSDialer(config Config) TLSDialer {
 | 
			
		||||
	var h tlsHandshaker = &netxlite.TLSHandshakerStdlib{}
 | 
			
		||||
	h = tlsdialer.ErrorWrapperTLSHandshaker{TLSHandshaker: h}
 | 
			
		||||
	if config.Logger != nil {
 | 
			
		||||
		h = tlsdialer.LoggingTLSHandshaker{Logger: config.Logger, TLSHandshaker: h}
 | 
			
		||||
		h = &netxlite.TLSHandshakerLogger{Logger: config.Logger, TLSHandshaker: h}
 | 
			
		||||
	}
 | 
			
		||||
	if config.TLSSaver != nil {
 | 
			
		||||
		h = tlsdialer.SaverTLSHandshaker{TLSHandshaker: h, Saver: config.TLSSaver}
 | 
			
		||||
 | 
			
		||||
@ -292,7 +292,7 @@ func TestNewTLSDialerWithLogging(t *testing.T) {
 | 
			
		||||
	if rtd.TLSHandshaker == nil {
 | 
			
		||||
		t.Fatal("invalid TLSHandshaker")
 | 
			
		||||
	}
 | 
			
		||||
	lth, ok := rtd.TLSHandshaker.(tlsdialer.LoggingTLSHandshaker)
 | 
			
		||||
	lth, ok := rtd.TLSHandshaker.(*netxlite.TLSHandshakerLogger)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		t.Fatal("not the TLSHandshaker we expected")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -17,7 +17,7 @@ func TestTLSDialerSuccess(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
	log.SetLevel(log.DebugLevel)
 | 
			
		||||
	dialer := tlsdialer.TLSDialer{Dialer: new(net.Dialer),
 | 
			
		||||
		TLSHandshaker: tlsdialer.LoggingTLSHandshaker{
 | 
			
		||||
		TLSHandshaker: &netxlite.TLSHandshakerLogger{
 | 
			
		||||
			TLSHandshaker: &netxlite.TLSHandshakerStdlib{},
 | 
			
		||||
			Logger:        log.Log,
 | 
			
		||||
		},
 | 
			
		||||
 | 
			
		||||
@ -1,39 +1,7 @@
 | 
			
		||||
package tlsdialer
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Logger is the logger assumed by this package
 | 
			
		||||
type Logger interface {
 | 
			
		||||
	Debugf(format string, v ...interface{})
 | 
			
		||||
	Debug(message string)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoggingTLSHandshaker is a TLSHandshaker with logging
 | 
			
		||||
type LoggingTLSHandshaker struct {
 | 
			
		||||
	TLSHandshaker
 | 
			
		||||
	Logger Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handshake implements Handshaker.Handshake
 | 
			
		||||
func (h LoggingTLSHandshaker) Handshake(
 | 
			
		||||
	ctx context.Context, conn net.Conn, config *tls.Config,
 | 
			
		||||
) (net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
	h.Logger.Debugf("tls {sni=%s next=%+v}...", config.ServerName, config.NextProtos)
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
 | 
			
		||||
	stop := time.Now()
 | 
			
		||||
	h.Logger.Debugf(
 | 
			
		||||
		"tls {sni=%s next=%+v}... %+v in %s {next=%s cipher=%s v=%s}", config.ServerName,
 | 
			
		||||
		config.NextProtos, err, stop.Sub(start), state.NegotiatedProtocol,
 | 
			
		||||
		tlsx.CipherSuiteString(state.CipherSuite), tlsx.VersionString(state.Version))
 | 
			
		||||
	return tlsconn, state, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ TLSHandshaker = LoggingTLSHandshaker{}
 | 
			
		||||
 | 
			
		||||
@ -1,28 +0,0 @@
 | 
			
		||||
package tlsdialer_test
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/apex/log"
 | 
			
		||||
	"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsdialer"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestLoggingTLSHandshakerFailure(t *testing.T) {
 | 
			
		||||
	h := tlsdialer.LoggingTLSHandshaker{
 | 
			
		||||
		TLSHandshaker: tlsdialer.EOFTLSHandshaker{},
 | 
			
		||||
		Logger:        log.Log,
 | 
			
		||||
	}
 | 
			
		||||
	tlsconn, _, err := h.Handshake(context.Background(), tlsdialer.EOFConn{}, &tls.Config{
 | 
			
		||||
		ServerName: "www.google.com",
 | 
			
		||||
	})
 | 
			
		||||
	if !errors.Is(err, io.EOF) {
 | 
			
		||||
		t.Fatal("not the error we expected")
 | 
			
		||||
	}
 | 
			
		||||
	if tlsconn != nil {
 | 
			
		||||
		t.Fatal("expected nil tlsconn here")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -5,6 +5,8 @@ import (
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/ooni/probe-cli/v3/internal/engine/netx/tlsx"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLSHandshaker is the generic TLS handshaker.
 | 
			
		||||
@ -44,3 +46,37 @@ func (h *TLSHandshakerStdlib) Handshake(
 | 
			
		||||
 | 
			
		||||
// DefaultTLSHandshaker is the default TLS handshaker.
 | 
			
		||||
var DefaultTLSHandshaker = &TLSHandshakerStdlib{}
 | 
			
		||||
 | 
			
		||||
// TLSHandshakerLogger is a TLSHandshaker with logging.
 | 
			
		||||
type TLSHandshakerLogger struct {
 | 
			
		||||
	// TLSHandshaker is the underlying handshaker.
 | 
			
		||||
	TLSHandshaker TLSHandshaker
 | 
			
		||||
 | 
			
		||||
	// Logger is the underlying logger.
 | 
			
		||||
	Logger Logger
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handshake implements Handshaker.Handshake
 | 
			
		||||
func (h *TLSHandshakerLogger) Handshake(
 | 
			
		||||
	ctx context.Context, conn net.Conn, config *tls.Config,
 | 
			
		||||
) (net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
	h.Logger.Debugf(
 | 
			
		||||
		"tls {sni=%s next=%+v}...", config.ServerName, config.NextProtos)
 | 
			
		||||
	start := time.Now()
 | 
			
		||||
	tlsconn, state, err := h.TLSHandshaker.Handshake(ctx, conn, config)
 | 
			
		||||
	elapsed := time.Since(start)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		h.Logger.Debugf(
 | 
			
		||||
			"tls {sni=%s next=%+v}... %s in %s", config.ServerName,
 | 
			
		||||
			config.NextProtos, err, elapsed)
 | 
			
		||||
		return nil, tls.ConnectionState{}, err
 | 
			
		||||
	}
 | 
			
		||||
	h.Logger.Debugf(
 | 
			
		||||
		"tls {sni=%s next=%+v}... ok in %s {next=%s cipher=%s v=%s}",
 | 
			
		||||
		config.ServerName, config.NextProtos, elapsed, state.NegotiatedProtocol,
 | 
			
		||||
		tlsx.CipherSuiteString(state.CipherSuite),
 | 
			
		||||
		tlsx.VersionString(state.Version))
 | 
			
		||||
	return tlsconn, state, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ TLSHandshaker = &TLSHandshakerLogger{}
 | 
			
		||||
 | 
			
		||||
@ -3,14 +3,17 @@ package netxlite
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"io"
 | 
			
		||||
	"net"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/http/httptest"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/apex/log"
 | 
			
		||||
	"github.com/ooni/probe-cli/v3/internal/netxmocks"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -79,3 +82,60 @@ func TestTLSHandshakerStdlibSuccess(t *testing.T) {
 | 
			
		||||
		t.Fatal("unexpected TLS version")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTLSHandshakerLoggerSuccess(t *testing.T) {
 | 
			
		||||
	th := &TLSHandshakerLogger{
 | 
			
		||||
		TLSHandshaker: &netxmocks.TLSHandshaker{
 | 
			
		||||
			MockHandshake: func(ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
				return tls.Client(conn, config), tls.ConnectionState{}, nil
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Logger: log.Log,
 | 
			
		||||
	}
 | 
			
		||||
	conn := &netxmocks.Conn{
 | 
			
		||||
		MockClose: func() error {
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	config := &tls.Config{}
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	tlsConn, connState, err := th.Handshake(ctx, conn, config)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	if err := tlsConn.Close(); err != nil {
 | 
			
		||||
		t.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	if !reflect.ValueOf(connState).IsZero() {
 | 
			
		||||
		t.Fatal("expected zero ConnectionState here")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestTLSHandshakerLoggerFailure(t *testing.T) {
 | 
			
		||||
	expected := errors.New("mocked error")
 | 
			
		||||
	th := &TLSHandshakerLogger{
 | 
			
		||||
		TLSHandshaker: &netxmocks.TLSHandshaker{
 | 
			
		||||
			MockHandshake: func(ctx context.Context, conn net.Conn, config *tls.Config) (net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
				return nil, tls.ConnectionState{}, expected
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		Logger: log.Log,
 | 
			
		||||
	}
 | 
			
		||||
	conn := &netxmocks.Conn{
 | 
			
		||||
		MockClose: func() error {
 | 
			
		||||
			return nil
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	config := &tls.Config{}
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	tlsConn, connState, err := th.Handshake(ctx, conn, config)
 | 
			
		||||
	if !errors.Is(err, expected) {
 | 
			
		||||
		t.Fatal("not the error we expected", err)
 | 
			
		||||
	}
 | 
			
		||||
	if tlsConn != nil {
 | 
			
		||||
		t.Fatal("expected nil conn here")
 | 
			
		||||
	}
 | 
			
		||||
	if !reflect.ValueOf(connState).IsZero() {
 | 
			
		||||
		t.Fatal("expected zero ConnectionState here")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,11 +5,6 @@ import (
 | 
			
		||||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// dialer is the interface we expect from a dialer
 | 
			
		||||
type dialer interface {
 | 
			
		||||
	DialContext(ctx context.Context, network, address string) (net.Conn, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dialer is a mockable Dialer.
 | 
			
		||||
type Dialer struct {
 | 
			
		||||
	MockDialContext func(ctx context.Context, network, address string) (net.Conn, error)
 | 
			
		||||
@ -19,5 +14,3 @@ type Dialer struct {
 | 
			
		||||
func (d *Dialer) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
 | 
			
		||||
	return d.MockDialContext(ctx, network, address)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ dialer = &Dialer{}
 | 
			
		||||
 | 
			
		||||
@ -2,13 +2,6 @@ package netxmocks
 | 
			
		||||
 | 
			
		||||
import "context"
 | 
			
		||||
 | 
			
		||||
// resolver is the interface we expect from a resolver
 | 
			
		||||
type resolver interface {
 | 
			
		||||
	LookupHost(ctx context.Context, domain string) ([]string, error)
 | 
			
		||||
	Network() string
 | 
			
		||||
	Address() string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Resolver is a mockable Resolver.
 | 
			
		||||
type Resolver struct {
 | 
			
		||||
	MockLookupHost func(ctx context.Context, domain string) ([]string, error)
 | 
			
		||||
@ -30,5 +23,3 @@ func (r *Resolver) Address() string {
 | 
			
		||||
func (r *Resolver) Network() string {
 | 
			
		||||
	return r.MockNetwork()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ resolver = &Resolver{}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								internal/netxmocks/tlshandshaker.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								internal/netxmocks/tlshandshaker.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
package netxmocks
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"net"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TLSHandshaker is a mockable TLS handshaker.
 | 
			
		||||
type TLSHandshaker struct {
 | 
			
		||||
	MockHandshake func(ctx context.Context, conn net.Conn, config *tls.Config) (
 | 
			
		||||
		net.Conn, tls.ConnectionState, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handshake calls MockHandshake.
 | 
			
		||||
func (th *TLSHandshaker) Handshake(ctx context.Context, conn net.Conn, config *tls.Config) (
 | 
			
		||||
	net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
	return th.MockHandshake(ctx, conn, config)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										33
									
								
								internal/netxmocks/tlshandshaker_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								internal/netxmocks/tlshandshaker_test.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,33 @@
 | 
			
		||||
package netxmocks
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"crypto/tls"
 | 
			
		||||
	"errors"
 | 
			
		||||
	"net"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestTLSHandshakerHandshake(t *testing.T) {
 | 
			
		||||
	expected := errors.New("mocked error")
 | 
			
		||||
	conn := &Conn{}
 | 
			
		||||
	ctx := context.Background()
 | 
			
		||||
	config := &tls.Config{}
 | 
			
		||||
	th := &TLSHandshaker{
 | 
			
		||||
		MockHandshake: func(ctx context.Context, conn net.Conn,
 | 
			
		||||
			config *tls.Config) (net.Conn, tls.ConnectionState, error) {
 | 
			
		||||
			return nil, tls.ConnectionState{}, expected
 | 
			
		||||
		},
 | 
			
		||||
	}
 | 
			
		||||
	tlsConn, connState, err := th.Handshake(ctx, conn, config)
 | 
			
		||||
	if !errors.Is(err, expected) {
 | 
			
		||||
		t.Fatal("not the error we expected", err)
 | 
			
		||||
	}
 | 
			
		||||
	if !reflect.ValueOf(connState).IsZero() {
 | 
			
		||||
		t.Fatal("expected zero ConnectionState here")
 | 
			
		||||
	}
 | 
			
		||||
	if tlsConn != nil {
 | 
			
		||||
		t.Fatal("expected nil conn here")
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user