diff --git a/core/client/client.go b/core/client/client.go index 6602b87..69a9a68 100644 --- a/core/client/client.go +++ b/core/client/client.go @@ -109,12 +109,12 @@ func (c *clientImpl) connect() error { _ = conn.CloseWithError(closeErrCodeProtocolError, "") } _ = pktConn.Close() - return &coreErrs.ConnectError{Err: err} + return coreErrs.ConnectError{Err: err} } if resp.StatusCode != protocol.StatusAuthOK { _ = conn.CloseWithError(closeErrCodeProtocolError, "") _ = pktConn.Close() - return &coreErrs.AuthError{StatusCode: resp.StatusCode} + return coreErrs.AuthError{StatusCode: resp.StatusCode} } // Auth OK udpEnabled, serverRx := protocol.AuthResponseDataFromHeader(resp.Header) diff --git a/core/internal/integration_tests/close_test.go b/core/internal/integration_tests/close_test.go index 531deb2..9216ede 100644 --- a/core/internal/integration_tests/close_test.go +++ b/core/internal/integration_tests/close_test.go @@ -92,8 +92,8 @@ func TestClientServerTCPClose(t *testing.T) { _ = conn.Close() } -// TestServerUDPIdleTimeout tests whether the server's UDP idle timeout works correctly. -func TestServerUDPIdleTimeout(t *testing.T) { +// TestClientServerUDPIdleTimeout tests whether the server's UDP idle timeout works correctly. +func TestClientServerUDPIdleTimeout(t *testing.T) { // Create server udpConn, udpAddr, err := serverConn() assert.NoError(t, err) diff --git a/core/internal/integration_tests/masq_test.go b/core/internal/integration_tests/masq_test.go index fb12e8f..894baf0 100644 --- a/core/internal/integration_tests/masq_test.go +++ b/core/internal/integration_tests/masq_test.go @@ -22,7 +22,7 @@ import ( // TestServerMasquerade is a test to ensure that the server behaves as a normal // HTTP/3 server when dealing with an unauthenticated client. This is mainly to -// confirm that the server does not expose itself to active probers. +// confirm that the server does not expose itself to active probing. func TestServerMasquerade(t *testing.T) { // Create server udpConn, udpAddr, err := serverConn() diff --git a/core/internal/integration_tests/smoke_test.go b/core/internal/integration_tests/smoke_test.go index 30984f9..146a8dd 100644 --- a/core/internal/integration_tests/smoke_test.go +++ b/core/internal/integration_tests/smoke_test.go @@ -1,43 +1,30 @@ package integration_tests import ( - "errors" "io" "net" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/apernet/hysteria/core/client" coreErrs "github.com/apernet/hysteria/core/errors" + "github.com/apernet/hysteria/core/internal/integration_tests/mocks" "github.com/apernet/hysteria/core/server" ) // Smoke tests that act as a sanity check for client & server to ensure they can talk to each other correctly. -// TestClientNoServer tests how the client handles a server that doesn't exist. -// The client should still be able to be created, but TCP & UDP requests should fail. +// TestClientNoServer tests how the client handles a server address it cannot connect to. +// NewClient should return a ConnectError. func TestClientNoServer(t *testing.T) { - // Create client c, err := client.NewClient(&client.Config{ - ServerAddr: &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}, + ServerAddr: &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55666}, }) - if err != nil { - t.Fatal("error creating client:", err) - } - defer c.Close() - - var cErr *coreErrs.ConnectError - - // Try TCP - _, err = c.TCP("google.com:443") - if !errors.As(err, &cErr) { - t.Fatal("expected connect error from TCP") - } - - // Try UDP - _, err = c.UDP() - if !errors.As(err, &cErr) { - t.Fatal("expected connect error from DialUDP") - } + assert.Nil(t, c) + _, ok := err.(coreErrs.ConnectError) + assert.True(t, ok) } // TestClientServerBadAuth tests two things: @@ -45,79 +32,82 @@ func TestClientNoServer(t *testing.T) { // - How the client handles failed authentication. func TestClientServerBadAuth(t *testing.T) { // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, "badpassword", uint64(0)).Return(false, "").Once() s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "correct password", - ID: "nobody", - }, + TLSConfig: serverTLSConfig(), + Conn: udpConn, + Authenticator: auth, }) - if err != nil { - t.Fatal("error creating server:", err) - } + assert.NoError(t, err) defer s.Close() go s.Serve() // Create client c, err := client.NewClient(&client.Config{ ServerAddr: udpAddr, - Auth: "wrong password", + Auth: "badpassword", TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, }) - if err != nil { - t.Fatal("error creating client:", err) - } + assert.Nil(t, c) + _, ok := err.(coreErrs.AuthError) + assert.True(t, ok) +} + +// TestClientServerUDPDisabled tests how the client handles a server that does not support UDP. +// UDP should return a DialError. +func TestClientServerUDPDisabled(t *testing.T) { + // Create server + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody") + s, err := server.NewServer(&server.Config{ + TLSConfig: serverTLSConfig(), + Conn: udpConn, + DisableUDP: true, + Authenticator: auth, + }) + assert.NoError(t, err) + defer s.Close() + go s.Serve() + + // Create client + c, err := client.NewClient(&client.Config{ + ServerAddr: udpAddr, + TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, + }) + assert.NoError(t, err) defer c.Close() - var aErr *coreErrs.AuthError - - // Try TCP - _, err = c.TCP("google.com:443") - if !errors.As(err, &aErr) { - t.Fatal("expected auth error from TCP") - } - - // Try UDP - _, err = c.UDP() - if !errors.As(err, &aErr) { - t.Fatal("expected auth error from DialUDP") - } + conn, err := c.UDP() + assert.Nil(t, conn) + _, ok := err.(coreErrs.DialError) + assert.True(t, ok) } // TestClientServerTCPEcho tests TCP forwarding using a TCP echo server. func TestClientServerTCPEcho(t *testing.T) { // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody") s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "password", - ID: "nobody", - }, + TLSConfig: serverTLSConfig(), + Conn: udpConn, + Authenticator: auth, }) - if err != nil { - t.Fatal("error creating server:", err) - } + assert.NoError(t, err) defer s.Close() go s.Serve() // Create TCP echo server - echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} - echoListener, err := net.ListenTCP("tcp", echoTCPAddr) - if err != nil { - t.Fatal("error creating TCP echo server:", err) - } + echoAddr := "127.0.0.1:22333" + echoListener, err := net.Listen("tcp", echoAddr) + assert.NoError(t, err) echoServer := &tcpEchoServer{Listener: echoListener} defer echoServer.Close() go echoServer.Serve() @@ -125,65 +115,46 @@ func TestClientServerTCPEcho(t *testing.T) { // Create client c, err := client.NewClient(&client.Config{ ServerAddr: udpAddr, - Auth: "password", TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, }) - if err != nil { - t.Fatal("error creating client:", err) - } + assert.NoError(t, err) defer c.Close() // Dial TCP - conn, err := c.TCP(echoTCPAddr.String()) - if err != nil { - t.Fatal("error dialing TCP:", err) - } + conn, err := c.TCP(echoAddr) + assert.NoError(t, err) defer conn.Close() // Send and receive data sData := []byte("hello world") _, err = conn.Write(sData) - if err != nil { - t.Fatal("error writing to TCP:", err) - } + assert.NoError(t, err) rData := make([]byte, len(sData)) _, err = io.ReadFull(conn, rData) - if err != nil { - t.Fatal("error reading from TCP:", err) - } - if string(rData) != string(sData) { - t.Fatalf("expected %q, got %q", sData, rData) - } + assert.NoError(t, err) + assert.Equal(t, sData, rData) } // TestClientServerUDPEcho tests UDP forwarding using a UDP echo server. func TestClientServerUDPEcho(t *testing.T) { // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody") s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "password", - ID: "nobody", - }, + TLSConfig: serverTLSConfig(), + Conn: udpConn, + Authenticator: auth, }) - if err != nil { - t.Fatal("error creating server:", err) - } + assert.NoError(t, err) defer s.Close() go s.Serve() // Create UDP echo server - echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55555} - echoConn, err := net.ListenUDP("udp", echoUDPAddr) - if err != nil { - t.Fatal("error creating UDP echo server:", err) - } + echoAddr := "127.0.0.1:22333" + echoConn, err := net.ListenPacket("udp", echoAddr) + assert.NoError(t, err) echoServer := &udpEchoServer{Conn: echoConn} defer echoServer.Close() go echoServer.Serve() @@ -191,35 +162,22 @@ func TestClientServerUDPEcho(t *testing.T) { // Create client c, err := client.NewClient(&client.Config{ ServerAddr: udpAddr, - Auth: "password", TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, }) - if err != nil { - t.Fatal("error creating client:", err) - } + assert.NoError(t, err) defer c.Close() // Listen UDP conn, err := c.UDP() - if err != nil { - t.Fatal("error listening UDP:", err) - } + assert.NoError(t, err) defer conn.Close() // Send and receive data sData := []byte("hello world") - err = conn.Send(sData, echoUDPAddr.String()) - if err != nil { - t.Fatal("error sending UDP:", err) - } + err = conn.Send(sData, echoAddr) + assert.NoError(t, err) rData, rAddr, err := conn.Receive() - if err != nil { - t.Fatal("error receiving UDP:", err) - } - if string(rData) != string(sData) { - t.Fatalf("expected %q, got %q", sData, rData) - } - if rAddr != echoUDPAddr.String() { - t.Fatalf("expected %q, got %q", echoUDPAddr.String(), rAddr) - } + assert.NoError(t, err) + assert.Equal(t, sData, rData) + assert.Equal(t, echoAddr, rAddr) } diff --git a/core/internal/integration_tests/stress_test.go b/core/internal/integration_tests/stress_test.go index 247d0c2..fa8f248 100644 --- a/core/internal/integration_tests/stress_test.go +++ b/core/internal/integration_tests/stress_test.go @@ -9,9 +9,12 @@ import ( "sync" "testing" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" "golang.org/x/time/rate" "github.com/apernet/hysteria/core/client" + "github.com/apernet/hysteria/core/internal/integration_tests/mocks" "github.com/apernet/hysteria/core/server" ) @@ -26,9 +29,7 @@ func (s *tcpStressor) Run(t *testing.T) { // Make some random data sData := make([]byte, s.Size) _, err := rand.Read(sData) - if err != nil { - t.Fatal("error generating random data:", err) - } + assert.NoError(t, err) // Run iterations for i := 0; i < s.Iterations; i++ { @@ -57,9 +58,7 @@ func (s *tcpStressor) Run(t *testing.T) { } wg.Wait() - if len(errChan) > 0 { - t.Fatal("error reading from TCP:", <-errChan) - } + assert.Empty(t, errChan) } } @@ -76,9 +75,7 @@ func (s *udpStressor) Run(t *testing.T) { // Make some random data sData := make([]byte, s.Size) _, err := rand.Read(sData) - if err != nil { - t.Fatal("error generating random data:", err) - } + assert.NoError(t, err) // Due to UDP's unreliability, we need to limit the rate of sending // to reduce packet loss. This is hardcoded to 1 MiB/s for now. @@ -123,39 +120,29 @@ func (s *udpStressor) Run(t *testing.T) { } wg.Wait() - if len(errChan) > 0 { - t.Fatal("error reading from UDP:", <-errChan) - } + assert.Empty(t, errChan) } } func TestClientServerTCPStress(t *testing.T) { // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody") s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "password", - ID: "nobody", - }, + TLSConfig: serverTLSConfig(), + Conn: udpConn, + Authenticator: auth, }) - if err != nil { - t.Fatal("error creating server:", err) - } + assert.NoError(t, err) defer s.Close() go s.Serve() // Create TCP echo server - echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} - echoListener, err := net.ListenTCP("tcp", echoTCPAddr) - if err != nil { - t.Fatal("error creating TCP echo server:", err) - } + echoAddr := "127.0.0.1:22333" + echoListener, err := net.Listen("tcp", echoAddr) + assert.NoError(t, err) echoServer := &tcpEchoServer{Listener: echoListener} defer echoServer.Close() go echoServer.Serve() @@ -163,16 +150,13 @@ func TestClientServerTCPStress(t *testing.T) { // Create client c, err := client.NewClient(&client.Config{ ServerAddr: udpAddr, - Auth: "password", TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, }) - if err != nil { - t.Fatal("error creating client:", err) - } + assert.NoError(t, err) defer c.Close() dialFunc := func() (net.Conn, error) { - return c.TCP(echoTCPAddr.String()) + return c.TCP(echoAddr) } t.Run("Single 500m", (&tcpStressor{DialFunc: dialFunc, Size: 524288000, Parallel: 1, Iterations: 1}).Run) @@ -186,49 +170,38 @@ func TestClientServerTCPStress(t *testing.T) { func TestClientServerUDPStress(t *testing.T) { // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } + udpConn, udpAddr, err := serverConn() + assert.NoError(t, err) + auth := mocks.NewMockAuthenticator(t) + auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody") s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "password", - ID: "nobody", - }, + TLSConfig: serverTLSConfig(), + Conn: udpConn, + Authenticator: auth, }) - if err != nil { - t.Fatal("error creating server:", err) - } + assert.NoError(t, err) defer s.Close() go s.Serve() // Create UDP echo server - echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} - echoListener, err := net.ListenUDP("udp", echoUDPAddr) - if err != nil { - t.Fatal("error creating UDP echo server:", err) - } - echoServer := &udpEchoServer{Conn: echoListener} + echoAddr := "127.0.0.1:22333" + echoConn, err := net.ListenPacket("udp", echoAddr) + assert.NoError(t, err) + echoServer := &udpEchoServer{Conn: echoConn} defer echoServer.Close() go echoServer.Serve() // Create client c, err := client.NewClient(&client.Config{ ServerAddr: udpAddr, - Auth: "password", TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, }) - if err != nil { - t.Fatal("error creating client:", err) - } + assert.NoError(t, err) defer c.Close() t.Run("Single 1000x100b", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 100, Count: 1000, Parallel: 1, @@ -236,7 +209,7 @@ func TestClientServerUDPStress(t *testing.T) { }).Run) t.Run("Single 1000x3k", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 3000, Count: 1000, Parallel: 1, @@ -245,7 +218,7 @@ func TestClientServerUDPStress(t *testing.T) { t.Run("5 Sequential 1000x100b", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 100, Count: 1000, Parallel: 1, @@ -253,7 +226,7 @@ func TestClientServerUDPStress(t *testing.T) { }).Run) t.Run("5 Sequential 200x3k", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 3000, Count: 200, Parallel: 1, @@ -262,7 +235,7 @@ func TestClientServerUDPStress(t *testing.T) { t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 100, Count: 1000, Parallel: 5, @@ -271,19 +244,10 @@ func TestClientServerUDPStress(t *testing.T) { t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{ ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), + ServerAddr: echoAddr, Size: 3000, Count: 200, Parallel: 5, Iterations: 2, }).Run) - - t.Run("10 Sequential 5 Parallel 200x3k", (&udpStressor{ - ListenFunc: c.UDP, - ServerAddr: echoUDPAddr.String(), - Size: 3000, - Count: 200, - Parallel: 5, - Iterations: 10, - }).Run) } diff --git a/core/internal/integration_tests/trafficlogger_test.go b/core/internal/integration_tests/trafficlogger_test.go deleted file mode 100644 index 6787042..0000000 --- a/core/internal/integration_tests/trafficlogger_test.go +++ /dev/null @@ -1,173 +0,0 @@ -package integration_tests - -import ( - "io" - "net" - "sync/atomic" - "testing" - - "github.com/apernet/hysteria/core/client" - "github.com/apernet/hysteria/core/server" -) - -type testTrafficLogger struct { - Tx, Rx uint64 - Block atomic.Bool -} - -func (l *testTrafficLogger) Log(id string, tx, rx uint64) bool { - atomic.AddUint64(&l.Tx, tx) - atomic.AddUint64(&l.Rx, rx) - return !l.Block.Load() -} - -func (l *testTrafficLogger) Get() (tx, rx uint64) { - return atomic.LoadUint64(&l.Tx), atomic.LoadUint64(&l.Rx) -} - -func (l *testTrafficLogger) SetBlock(block bool) { - l.Block.Store(block) -} - -func (l *testTrafficLogger) Reset() { - atomic.StoreUint64(&l.Tx, 0) - atomic.StoreUint64(&l.Rx, 0) -} - -// TestServerTrafficLogger tests that the server's TrafficLogger interface is working correctly. -// More specifically, it tests that the server is correctly logging traffic in both directions, -// and that it is correctly disconnecting clients when the traffic logger returns false. -func TestServerTrafficLogger(t *testing.T) { - tl := &testTrafficLogger{} - - // Create server - udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514} - udpConn, err := net.ListenUDP("udp", udpAddr) - if err != nil { - t.Fatal("error creating server:", err) - } - s, err := server.NewServer(&server.Config{ - TLSConfig: serverTLSConfig(), - Conn: udpConn, - Authenticator: &pwAuthenticator{ - Password: "password", - ID: "nobody", - }, - TrafficLogger: tl, - }) - if err != nil { - t.Fatal("error creating server:", err) - } - defer s.Close() - go s.Serve() - - // Create TCP double echo server - // We use double echo to test that the traffic logger is correctly logging both directions. - echoTCPAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14515} - echoListener, err := net.ListenTCP("tcp", echoTCPAddr) - if err != nil { - t.Fatal("error creating TCP echo server:", err) - } - tEchoServer := &tcpDoubleEchoServer{Listener: echoListener} - defer tEchoServer.Close() - go tEchoServer.Serve() - - // Create client - c, err := client.NewClient(&client.Config{ - ServerAddr: udpAddr, - Auth: "password", - TLSConfig: client.TLSConfig{InsecureSkipVerify: true}, - }) - if err != nil { - t.Fatal("error creating client:", err) - } - defer c.Close() - - // Dial TCP - tConn, err := c.TCP(echoTCPAddr.String()) - if err != nil { - t.Fatal("error dialing TCP:", err) - } - defer tConn.Close() - - // Send and receive TCP data - sData := []byte("1234") - _, err = tConn.Write(sData) - if err != nil { - t.Fatal("error writing to TCP:", err) - } - rData := make([]byte, len(sData)*2) - _, err = io.ReadFull(tConn, rData) - if err != nil { - t.Fatal("error reading from TCP:", err) - } - expected := string(sData) + string(sData) - if string(rData) != expected { - t.Fatalf("expected %q, got %q", expected, string(rData)) - } - - // Check traffic logger - tx, rx := tl.Get() - if tx != uint64(len(sData)) || rx != uint64(len(rData)) { - t.Fatalf("expected TrafficLogger Tx=%d, Rx=%d, got Tx=%d, Rx=%d", len(sData), len(rData), tx, rx) - } - tl.Reset() - - // Create UDP double echo server - echoUDPAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 55555} - echoConn, err := net.ListenUDP("udp", echoUDPAddr) - if err != nil { - t.Fatal("error creating UDP echo server:", err) - } - uEchoServer := &udpDoubleEchoServer{Conn: echoConn} - defer uEchoServer.Close() - go uEchoServer.Serve() - - // Listen UDP - uConn, err := c.UDP() - if err != nil { - t.Fatal("error listening UDP:", err) - } - defer uConn.Close() - - // Send and receive UDP data - sData = []byte("gucci gang") - err = uConn.Send(sData, echoUDPAddr.String()) - if err != nil { - t.Fatal("error sending UDP:", err) - } - for i := 0; i < 2; i++ { - rData, rAddr, err := uConn.Receive() - if err != nil { - t.Fatal("error receiving UDP:", err) - } - if string(rData) != string(sData) { - t.Fatalf("expected %q, got %q", string(sData), string(rData)) - } - if rAddr != echoUDPAddr.String() { - t.Fatalf("expected %q, got %q", echoUDPAddr.String(), rAddr) - } - } - - // Check traffic logger - tx, rx = tl.Get() - if tx != uint64(len(sData)) || rx != uint64(len(sData)*2) { - t.Fatalf("expected TrafficLogger Tx=%d, Rx=%d, got Tx=%d, Rx=%d", len(sData), len(sData)*2, tx, rx) - } - - // Check the disconnect client functionality - tl.SetBlock(true) - - // Send and receive TCP data again - sData = []byte("1234") - _, err = tConn.Write(sData) - if err != nil { - t.Fatal("error writing to TCP:", err) - } - // This should fail instantly without reading any data - // io.Copy should return nil as EOF is treated as a non-error though - n, err := io.Copy(io.Discard, tConn) - if n != 0 || err != nil { - t.Fatal("expected 0 bytes read and nil error, got", n, err) - } -} diff --git a/core/internal/integration_tests/utils_test.go b/core/internal/integration_tests/utils_test.go index 60bfc52..a1aa160 100644 --- a/core/internal/integration_tests/utils_test.go +++ b/core/internal/integration_tests/utils_test.go @@ -1,7 +1,6 @@ package integration_tests import ( - "bytes" "crypto/tls" "io" "net" @@ -35,18 +34,6 @@ func serverConn() (net.PacketConn, net.Addr, error) { return udpConn, udpAddr, nil } -type pwAuthenticator struct { - Password string - ID string -} - -func (a *pwAuthenticator) Authenticate(addr net.Addr, auth string, tx uint64) (ok bool, id string) { - if auth != a.Password { - return false, "" - } - return true, a.ID -} - // tcpEchoServer is a TCP server that echoes what it reads from the connection. // It will never actively close the connection. type tcpEchoServer struct { @@ -70,92 +57,6 @@ func (s *tcpEchoServer) Close() error { return s.Listener.Close() } -// tcpDoubleEchoServer is a TCP server that echoes twice what it reads from the connection. -// It will never actively close the connection. -type tcpDoubleEchoServer struct { - Listener net.Listener -} - -func (s *tcpDoubleEchoServer) Serve() error { - for { - conn, err := s.Listener.Accept() - if err != nil { - return err - } - go func() { - buf := make([]byte, 1024) - for { - n, err := conn.Read(buf) - if err != nil { - _ = conn.Close() - return - } - _, _ = conn.Write(buf[:n]) - _, _ = conn.Write(buf[:n]) - } - }() - } -} - -func (s *tcpDoubleEchoServer) Close() error { - return s.Listener.Close() -} - -type sinkEvent struct { - Data []byte - Err error -} - -// tcpSinkServer is a TCP server that reads data from the connection, -// and sends what it read to the channel when the connection is closed. -type tcpSinkServer struct { - Listener net.Listener - Ch chan<- sinkEvent -} - -func (s *tcpSinkServer) Serve() error { - for { - conn, err := s.Listener.Accept() - if err != nil { - return err - } - go func() { - var buf bytes.Buffer - _, err := io.Copy(&buf, conn) - _ = conn.Close() - s.Ch <- sinkEvent{Data: buf.Bytes(), Err: err} - }() - } -} - -func (s *tcpSinkServer) Close() error { - return s.Listener.Close() -} - -// tcpSenderServer is a TCP server that sends data to the connection, -// and closes the connection when all data has been sent. -type tcpSenderServer struct { - Listener net.Listener - Data []byte -} - -func (s *tcpSenderServer) Serve() error { - for { - conn, err := s.Listener.Accept() - if err != nil { - return err - } - go func() { - _, _ = conn.Write(s.Data) - _ = conn.Close() - }() - } -} - -func (s *tcpSenderServer) Close() error { - return s.Listener.Close() -} - // udpEchoServer is a UDP server that echoes what it reads from the connection. // It will never actively close the connection. type udpEchoServer struct { @@ -179,140 +80,3 @@ func (s *udpEchoServer) Serve() error { func (s *udpEchoServer) Close() error { return s.Conn.Close() } - -// udpDoubleEchoServer is a UDP server that echoes twice what it reads from the connection. -// It will never actively close the connection. -type udpDoubleEchoServer struct { - Conn net.PacketConn -} - -func (s *udpDoubleEchoServer) Serve() error { - buf := make([]byte, 65536) - for { - n, addr, err := s.Conn.ReadFrom(buf) - if err != nil { - return err - } - _, err = s.Conn.WriteTo(buf[:n], addr) - if err != nil { - return err - } - _, err = s.Conn.WriteTo(buf[:n], addr) - if err != nil { - return err - } - } -} - -func (s *udpDoubleEchoServer) Close() error { - return s.Conn.Close() -} - -type connectEvent struct { - Addr net.Addr - ID string - TX uint64 -} - -type disconnectEvent struct { - Addr net.Addr - ID string - Err error -} - -type tcpRequestEvent struct { - Addr net.Addr - ID string - ReqAddr string -} - -type tcpErrorEvent struct { - Addr net.Addr - ID string - ReqAddr string - Err error -} - -type udpRequestEvent struct { - Addr net.Addr - ID string - SessionID uint32 -} - -type udpErrorEvent struct { - Addr net.Addr - ID string - SessionID uint32 - Err error -} - -type channelEventLogger struct { - ConnectEventCh chan connectEvent - DisconnectEventCh chan disconnectEvent - TCPRequestEventCh chan tcpRequestEvent - TCPErrorEventCh chan tcpErrorEvent - UDPRequestEventCh chan udpRequestEvent - UDPErrorEventCh chan udpErrorEvent -} - -func (l *channelEventLogger) Connect(addr net.Addr, id string, tx uint64) { - if l.ConnectEventCh != nil { - l.ConnectEventCh <- connectEvent{ - Addr: addr, - ID: id, - TX: tx, - } - } -} - -func (l *channelEventLogger) Disconnect(addr net.Addr, id string, err error) { - if l.DisconnectEventCh != nil { - l.DisconnectEventCh <- disconnectEvent{ - Addr: addr, - ID: id, - Err: err, - } - } -} - -func (l *channelEventLogger) TCPRequest(addr net.Addr, id, reqAddr string) { - if l.TCPRequestEventCh != nil { - l.TCPRequestEventCh <- tcpRequestEvent{ - Addr: addr, - ID: id, - ReqAddr: reqAddr, - } - } -} - -func (l *channelEventLogger) TCPError(addr net.Addr, id, reqAddr string, err error) { - if l.TCPErrorEventCh != nil { - l.TCPErrorEventCh <- tcpErrorEvent{ - Addr: addr, - ID: id, - ReqAddr: reqAddr, - Err: err, - } - } -} - -func (l *channelEventLogger) UDPRequest(addr net.Addr, id string, sessionID uint32, reqAddr string) { - if l.UDPRequestEventCh != nil { - l.UDPRequestEventCh <- udpRequestEvent{ - Addr: addr, - ID: id, - SessionID: sessionID, - } - } -} - -func (l *channelEventLogger) UDPError(addr net.Addr, id string, sessionID uint32, err error) { - if l.UDPErrorEventCh != nil { - l.UDPErrorEventCh <- udpErrorEvent{ - Addr: addr, - ID: id, - SessionID: sessionID, - Err: err, - } - } -}