mirror of
https://github.com/apernet/hysteria.git
synced 2025-04-04 13:07:39 +03:00
feat(wip): test reworks
This commit is contained in:
parent
55fb903192
commit
dd836b4496
22 changed files with 934 additions and 185 deletions
|
@ -50,7 +50,7 @@ func runPing(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
logger.Info("connecting", zap.String("address", addr))
|
logger.Info("connecting", zap.String("address", addr))
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
conn, err := c.DialTCP(addr)
|
conn, err := c.TCP(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Fatal("failed to connect", zap.Error(err), zap.String("time", time.Since(start).String()))
|
logger.Fatal("failed to connect", zap.Error(err), zap.String("time", time.Since(start).String()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func (t *TCPTunnel) handle(conn net.Conn) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
rc, err := t.HyClient.DialTCP(t.Remote)
|
rc, err := t.HyClient.TCP(t.Remote)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
closeErr = err
|
closeErr = err
|
||||||
return
|
return
|
||||||
|
|
|
@ -118,7 +118,7 @@ func (t *UDPTunnel) handle(l net.PacketConn, sm *sessionManager, addr net.Addr,
|
||||||
if t.EventLogger != nil {
|
if t.EventLogger != nil {
|
||||||
t.EventLogger.Connect(addr)
|
t.EventLogger.Connect(addr)
|
||||||
}
|
}
|
||||||
hyConn, err := t.HyClient.ListenUDP()
|
hyConn, err := t.HyClient.UDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if t.EventLogger != nil {
|
if t.EventLogger != nil {
|
||||||
t.EventLogger.Error(addr, err)
|
t.EventLogger.Error(addr, err)
|
||||||
|
|
|
@ -156,7 +156,7 @@ func (s *Server) handleConnect(conn net.Conn, req *http.Request) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Dial
|
// Dial
|
||||||
rConn, err := s.HyClient.DialTCP(reqAddr)
|
rConn, err := s.HyClient.TCP(reqAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = sendSimpleResponse(conn, req, http.StatusBadGateway)
|
_ = sendSimpleResponse(conn, req, http.StatusBadGateway)
|
||||||
closeErr = err
|
closeErr = err
|
||||||
|
@ -233,7 +233,7 @@ func (s *Server) initHTTPClient() {
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
// HyClient doesn't support context for now
|
// HyClient doesn't support context for now
|
||||||
return s.HyClient.DialTCP(addr)
|
return s.HyClient.TCP(addr)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
|
|
|
@ -17,11 +17,11 @@ const (
|
||||||
|
|
||||||
type mockHyClient struct{}
|
type mockHyClient struct{}
|
||||||
|
|
||||||
func (c *mockHyClient) DialTCP(addr string) (net.Conn, error) {
|
func (c *mockHyClient) TCP(addr string) (net.Conn, error) {
|
||||||
return net.Dial("tcp", addr)
|
return net.Dial("tcp", addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *mockHyClient) ListenUDP() (client.HyUDPConn, error) {
|
func (c *mockHyClient) UDP() (client.HyUDPConn, error) {
|
||||||
// Not implemented
|
// Not implemented
|
||||||
return nil, errors.New("not implemented")
|
return nil, errors.New("not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,7 @@ func (s *Server) handleTCP(conn net.Conn, req *socks5.Request) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Dial
|
// Dial
|
||||||
rConn, err := s.HyClient.DialTCP(addr)
|
rConn, err := s.HyClient.TCP(addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = sendSimpleReply(conn, socks5.RepHostUnreachable)
|
_ = sendSimpleReply(conn, socks5.RepHostUnreachable)
|
||||||
closeErr = err
|
closeErr = err
|
||||||
|
@ -196,7 +196,7 @@ func (s *Server) handleUDP(conn net.Conn, req *socks5.Request) {
|
||||||
defer udpConn.Close()
|
defer udpConn.Close()
|
||||||
|
|
||||||
// HyClient UDP session
|
// HyClient UDP session
|
||||||
hyUDP, err := s.HyClient.ListenUDP()
|
hyUDP, err := s.HyClient.UDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = sendSimpleReply(conn, socks5.RepServerFailure)
|
_ = sendSimpleReply(conn, socks5.RepServerFailure)
|
||||||
closeErr = err
|
closeErr = err
|
||||||
|
|
|
@ -10,13 +10,13 @@ import (
|
||||||
|
|
||||||
type MockEchoHyClient struct{}
|
type MockEchoHyClient struct{}
|
||||||
|
|
||||||
func (c *MockEchoHyClient) DialTCP(addr string) (net.Conn, error) {
|
func (c *MockEchoHyClient) TCP(addr string) (net.Conn, error) {
|
||||||
return &mockEchoTCPConn{
|
return &mockEchoTCPConn{
|
||||||
BufChan: make(chan []byte, 10),
|
BufChan: make(chan []byte, 10),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *MockEchoHyClient) ListenUDP() (client.HyUDPConn, error) {
|
func (c *MockEchoHyClient) UDP() (client.HyUDPConn, error) {
|
||||||
return &mockEchoUDPConn{
|
return &mockEchoUDPConn{
|
||||||
BufChan: make(chan mockEchoUDPPacket, 10),
|
BufChan: make(chan mockEchoUDPPacket, 10),
|
||||||
}, nil
|
}, nil
|
||||||
|
|
|
@ -23,8 +23,8 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Client interface {
|
type Client interface {
|
||||||
DialTCP(addr string) (net.Conn, error)
|
TCP(addr string) (net.Conn, error)
|
||||||
ListenUDP() (HyUDPConn, error)
|
UDP() (HyUDPConn, error)
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +146,7 @@ func (c *clientImpl) openStream() (quic.Stream, error) {
|
||||||
return &utils.QStream{Stream: stream}, nil
|
return &utils.QStream{Stream: stream}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientImpl) DialTCP(addr string) (net.Conn, error) {
|
func (c *clientImpl) TCP(addr string) (net.Conn, error) {
|
||||||
stream, err := c.openStream()
|
stream, err := c.openStream()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if netErr, ok := err.(net.Error); ok && !netErr.Temporary() {
|
if netErr, ok := err.(net.Error); ok && !netErr.Temporary() {
|
||||||
|
@ -190,7 +190,7 @@ func (c *clientImpl) DialTCP(addr string) (net.Conn, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *clientImpl) ListenUDP() (HyUDPConn, error) {
|
func (c *clientImpl) UDP() (HyUDPConn, error) {
|
||||||
if c.udpSM == nil {
|
if c.udpSM == nil {
|
||||||
return nil, coreErrs.DialError{Message: "UDP not enabled"}
|
return nil, coreErrs.DialError{Message: "UDP not enabled"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,19 @@ with-expecter: true
|
||||||
dir: mocks
|
dir: mocks
|
||||||
outpkg: mocks
|
outpkg: mocks
|
||||||
packages:
|
packages:
|
||||||
|
net:
|
||||||
|
interfaces:
|
||||||
|
Conn:
|
||||||
|
config:
|
||||||
|
mockname: MockConn
|
||||||
github.com/apernet/hysteria/core/server:
|
github.com/apernet/hysteria/core/server:
|
||||||
interfaces:
|
interfaces:
|
||||||
|
Outbound:
|
||||||
|
config:
|
||||||
|
mockname: MockOutbound
|
||||||
|
UDPConn:
|
||||||
|
config:
|
||||||
|
mockname: MockUDPConn
|
||||||
Authenticator:
|
Authenticator:
|
||||||
config:
|
config:
|
||||||
mockname: MockAuthenticator
|
mockname: MockAuthenticator
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
package integration_tests
|
package integration_tests
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"io"
|
"io"
|
||||||
"net"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/mock"
|
"github.com/stretchr/testify/mock"
|
||||||
|
@ -15,17 +14,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestClientServerTCPClose tests whether the client/server propagates the close of a connection correctly.
|
// TestClientServerTCPClose tests whether the client/server propagates the close of a connection correctly.
|
||||||
// In other words, closing one of the client/remote connections should cause the other to close as well.
|
// Closing one side of the connection should close the other side as well.
|
||||||
func TestClientServerTCPClose(t *testing.T) {
|
func TestClientServerTCPClose(t *testing.T) {
|
||||||
// Create server
|
// Create server
|
||||||
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
|
udpConn, udpAddr, err := serverConn()
|
||||||
udpConn, err := net.ListenUDP("udp", udpAddr)
|
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
serverOb := mocks.NewMockOutbound(t)
|
||||||
auth := mocks.NewMockAuthenticator(t)
|
auth := mocks.NewMockAuthenticator(t)
|
||||||
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
|
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
|
||||||
s, err := server.NewServer(&server.Config{
|
s, err := server.NewServer(&server.Config{
|
||||||
TLSConfig: serverTLSConfig(),
|
TLSConfig: serverTLSConfig(),
|
||||||
Conn: udpConn,
|
Conn: udpConn,
|
||||||
|
Outbound: serverOb,
|
||||||
Authenticator: auth,
|
Authenticator: auth,
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -40,123 +40,137 @@ func TestClientServerTCPClose(t *testing.T) {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
t.Run("Close local", func(t *testing.T) {
|
addr := "hi-and-goodbye:2333"
|
||||||
// TCP sink server
|
|
||||||
sinkAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 33344}
|
|
||||||
sinkListener, err := net.ListenTCP("tcp", sinkAddr)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
sinkCh := make(chan sinkEvent, 1)
|
|
||||||
sinkServer := &tcpSinkServer{
|
|
||||||
Listener: sinkListener,
|
|
||||||
Ch: sinkCh,
|
|
||||||
}
|
|
||||||
defer sinkServer.Close()
|
|
||||||
go sinkServer.Serve()
|
|
||||||
|
|
||||||
// Generate some random data
|
// Test close from client side:
|
||||||
sData := make([]byte, 1024000)
|
// Client creates a connection, writes something, then closes it.
|
||||||
_, err = rand.Read(sData)
|
// Server outbound connection should write the same thing, then close.
|
||||||
assert.NoError(t, err)
|
sobConn := mocks.NewMockConn(t)
|
||||||
|
sobConnCh := make(chan struct{}) // For close signal only
|
||||||
// Dial and send data to TCP sink server
|
sobConn.EXPECT().Read(mock.Anything).RunAndReturn(func(bs []byte) (int, error) {
|
||||||
conn, err := c.DialTCP(sinkAddr.String())
|
<-sobConnCh
|
||||||
assert.NoError(t, err)
|
return 0, io.EOF
|
||||||
_, err = conn.Write(sData)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// Close the connection
|
|
||||||
// This should cause the sink server to send an event to the channel
|
|
||||||
_ = conn.Close()
|
|
||||||
event := <-sinkCh
|
|
||||||
assert.NoError(t, event.Err)
|
|
||||||
assert.Equal(t, sData, event.Data)
|
|
||||||
})
|
})
|
||||||
|
sobConn.EXPECT().Write([]byte("happy")).Return(5, nil)
|
||||||
t.Run("Close remote", func(t *testing.T) {
|
sobConn.EXPECT().Close().RunAndReturn(func() error {
|
||||||
// Generate some random data
|
close(sobConnCh)
|
||||||
sData := make([]byte, 1024000)
|
return nil
|
||||||
_, err = rand.Read(sData)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
// TCP sender server
|
|
||||||
senderAddr := &net.TCPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 33345}
|
|
||||||
senderListener, err := net.ListenTCP("tcp", senderAddr)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
senderServer := &tcpSenderServer{
|
|
||||||
Listener: senderListener,
|
|
||||||
Data: sData,
|
|
||||||
}
|
|
||||||
defer senderServer.Close()
|
|
||||||
go senderServer.Serve()
|
|
||||||
|
|
||||||
// Dial and read data from TCP sender server
|
|
||||||
conn, err := c.DialTCP(senderAddr.String())
|
|
||||||
assert.NoError(t, err)
|
|
||||||
defer conn.Close()
|
|
||||||
rData, err := io.ReadAll(conn)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Equal(t, sData, rData)
|
|
||||||
})
|
})
|
||||||
|
serverOb.EXPECT().TCP(addr).Return(sobConn, nil).Once()
|
||||||
|
conn, err := c.TCP(addr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
_, err = conn.Write([]byte("happy"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = conn.Close()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
mock.AssertExpectationsForObjects(t, sobConn, serverOb)
|
||||||
|
|
||||||
|
// Test close from server side:
|
||||||
|
// Client creates a connection.
|
||||||
|
// Server outbound connection reads something, then closes.
|
||||||
|
// Client connection should read the same thing, then close.
|
||||||
|
sobConn = mocks.NewMockConn(t)
|
||||||
|
sobConnCh2 := make(chan []byte, 1)
|
||||||
|
sobConn.EXPECT().Read(mock.Anything).RunAndReturn(func(bs []byte) (int, error) {
|
||||||
|
d := <-sobConnCh2
|
||||||
|
if d == nil {
|
||||||
|
return 0, io.EOF
|
||||||
|
} else {
|
||||||
|
return copy(bs, d), nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sobConn.EXPECT().Close().Return(nil)
|
||||||
|
serverOb.EXPECT().TCP(addr).Return(sobConn, nil).Once()
|
||||||
|
conn, err = c.TCP(addr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
sobConnCh2 <- []byte("happy")
|
||||||
|
close(sobConnCh2)
|
||||||
|
bs, err := io.ReadAll(conn)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "happy", string(bs))
|
||||||
|
_ = conn.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestClientServerUDPClose is the same as TestClientServerTCPClose, but for UDP.
|
// TestServerUDPIdleTimeout tests whether the server's UDP idle timeout works correctly.
|
||||||
// Checking for UDP close is a bit tricky, so we will rely on the server event for now.
|
func TestServerUDPIdleTimeout(t *testing.T) {
|
||||||
func TestClientServerUDPClose(t *testing.T) {
|
|
||||||
urCh := make(chan udpRequestEvent, 1)
|
|
||||||
ueCh := make(chan udpErrorEvent, 1)
|
|
||||||
|
|
||||||
// Create server
|
// Create server
|
||||||
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
|
udpConn, udpAddr, err := serverConn()
|
||||||
udpConn, err := net.ListenUDP("udp", udpAddr)
|
assert.NoError(t, err)
|
||||||
if err != nil {
|
serverOb := mocks.NewMockOutbound(t)
|
||||||
t.Fatal("error creating server:", err)
|
auth := mocks.NewMockAuthenticator(t)
|
||||||
}
|
auth.EXPECT().Authenticate(mock.Anything, mock.Anything, mock.Anything).Return(true, "nobody")
|
||||||
|
eventLogger := mocks.NewMockEventLogger(t)
|
||||||
|
eventLogger.EXPECT().Connect(mock.Anything, "nobody", mock.Anything).Once()
|
||||||
|
eventLogger.EXPECT().Disconnect(mock.Anything, "nobody", mock.Anything).Maybe() // Depends on the timing, don't care
|
||||||
s, err := server.NewServer(&server.Config{
|
s, err := server.NewServer(&server.Config{
|
||||||
TLSConfig: serverTLSConfig(),
|
TLSConfig: serverTLSConfig(),
|
||||||
Conn: udpConn,
|
Conn: udpConn,
|
||||||
Authenticator: &pwAuthenticator{
|
Outbound: serverOb,
|
||||||
Password: "password",
|
UDPIdleTimeout: 2 * time.Second,
|
||||||
ID: "nobody",
|
Authenticator: auth,
|
||||||
},
|
EventLogger: eventLogger,
|
||||||
EventLogger: &channelEventLogger{
|
|
||||||
UDPRequestEventCh: urCh,
|
|
||||||
UDPErrorEventCh: ueCh,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error creating server:", err)
|
|
||||||
}
|
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
go s.Serve()
|
go s.Serve()
|
||||||
|
|
||||||
// Create client
|
// Create client
|
||||||
c, err := client.NewClient(&client.Config{
|
c, err := client.NewClient(&client.Config{
|
||||||
ServerAddr: udpAddr,
|
ServerAddr: udpAddr,
|
||||||
Auth: "password",
|
|
||||||
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
|
TLSConfig: client.TLSConfig{InsecureSkipVerify: true},
|
||||||
})
|
})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error creating client:", err)
|
|
||||||
}
|
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
// Listen UDP and close it, then check the server events
|
addr := "spy.x.family:2023"
|
||||||
conn, err := c.ListenUDP()
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("error listening UDP:", err)
|
|
||||||
}
|
|
||||||
_ = conn.Close()
|
|
||||||
|
|
||||||
reqEvent := <-urCh
|
// On the client side, create a UDP session and send a packet every 1 second,
|
||||||
if reqEvent.ID != "nobody" {
|
// 4 packets in total. The server should have one UDP session and receive all
|
||||||
t.Fatal("incorrect ID in request event")
|
// 4 packets. Then the UDP connection on the server side will receive a packet
|
||||||
|
// every 1 second, 4 packets in total. The client session should receive all
|
||||||
|
// 4 packets. Then the session will be idle for 3 seconds - should be enough
|
||||||
|
// to trigger the server's UDP idle timeout.
|
||||||
|
sobConn := mocks.NewMockUDPConn(t)
|
||||||
|
sobConnCh := make(chan []byte, 1)
|
||||||
|
sobConn.EXPECT().ReadFrom(mock.Anything).RunAndReturn(func(bs []byte) (int, string, error) {
|
||||||
|
d := <-sobConnCh
|
||||||
|
if d == nil {
|
||||||
|
return 0, "", io.EOF
|
||||||
|
} else {
|
||||||
|
return copy(bs, d), addr, nil
|
||||||
|
}
|
||||||
|
})
|
||||||
|
sobConn.EXPECT().WriteTo([]byte("happy"), addr).Return(5, nil).Times(4)
|
||||||
|
serverOb.EXPECT().UDP(addr).Return(sobConn, nil).Once()
|
||||||
|
eventLogger.EXPECT().UDPRequest(mock.Anything, mock.Anything, uint32(1), addr).Once()
|
||||||
|
cu, err := c.UDP()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
// Client sends 4 packets
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
err = cu.Send([]byte("happy"), addr)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
}
|
}
|
||||||
errEvent := <-ueCh
|
// Client receives 4 packets
|
||||||
if errEvent.ID != "nobody" {
|
go func() {
|
||||||
t.Fatal("incorrect ID in error event")
|
for i := 0; i < 4; i++ {
|
||||||
}
|
sobConnCh <- []byte("sad")
|
||||||
if errEvent.Err != nil {
|
time.Sleep(1 * time.Second)
|
||||||
t.Fatal("non-nil error received from server:", errEvent.Err)
|
}
|
||||||
|
}()
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
bs, rAddr, err := cu.Receive()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, "sad", string(bs))
|
||||||
|
assert.Equal(t, addr, rAddr)
|
||||||
}
|
}
|
||||||
|
// Now we wait for 3 seconds, the server should close the UDP session.
|
||||||
|
sobConn.EXPECT().Close().RunAndReturn(func() error {
|
||||||
|
close(sobConnCh)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
eventLogger.EXPECT().UDPError(mock.Anything, mock.Anything, uint32(1), nil).Once()
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
|
mock.AssertExpectationsForObjects(t, sobConn, serverOb, eventLogger)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,13 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
"github.com/apernet/hysteria/core/internal/integration_tests/mocks"
|
||||||
"github.com/apernet/hysteria/core/internal/protocol"
|
"github.com/apernet/hysteria/core/internal/protocol"
|
||||||
"github.com/apernet/hysteria/core/server"
|
"github.com/apernet/hysteria/core/server"
|
||||||
|
|
||||||
|
@ -22,22 +25,16 @@ import (
|
||||||
// confirm that the server does not expose itself to active probers.
|
// confirm that the server does not expose itself to active probers.
|
||||||
func TestServerMasquerade(t *testing.T) {
|
func TestServerMasquerade(t *testing.T) {
|
||||||
// Create server
|
// Create server
|
||||||
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
|
udpConn, udpAddr, err := serverConn()
|
||||||
udpConn, err := net.ListenUDP("udp", udpAddr)
|
assert.NoError(t, err)
|
||||||
if err != nil {
|
auth := mocks.NewMockAuthenticator(t)
|
||||||
t.Fatal("error creating server:", err)
|
auth.EXPECT().Authenticate(mock.Anything, "", uint64(0)).Return(false, "").Once()
|
||||||
}
|
|
||||||
s, err := server.NewServer(&server.Config{
|
s, err := server.NewServer(&server.Config{
|
||||||
TLSConfig: serverTLSConfig(),
|
TLSConfig: serverTLSConfig(),
|
||||||
Conn: udpConn,
|
Conn: udpConn,
|
||||||
Authenticator: &pwAuthenticator{
|
Authenticator: auth,
|
||||||
Password: "password",
|
|
||||||
ID: "nobody",
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error creating server:", err)
|
|
||||||
}
|
|
||||||
defer s.Close()
|
defer s.Close()
|
||||||
go s.Serve()
|
go s.Serve()
|
||||||
|
|
||||||
|
@ -71,39 +68,27 @@ func TestServerMasquerade(t *testing.T) {
|
||||||
Header: make(http.Header),
|
Header: make(http.Header),
|
||||||
}
|
}
|
||||||
resp, err := rt.RoundTrip(req)
|
resp, err := rt.RoundTrip(req)
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error sending request:", err)
|
assert.Equal(t, http.StatusNotFound, resp.StatusCode)
|
||||||
}
|
|
||||||
if resp.StatusCode != http.StatusNotFound {
|
|
||||||
t.Fatalf("expected status %d, got %d", http.StatusNotFound, resp.StatusCode)
|
|
||||||
}
|
|
||||||
for k := range resp.Header {
|
for k := range resp.Header {
|
||||||
// Make sure no strange headers are sent
|
// Make sure no strange headers are sent by the server
|
||||||
if strings.Contains(k, "Hysteria") {
|
assert.NotContains(t, k, "Hysteria")
|
||||||
t.Fatal("expected no Hysteria headers, got", k)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
|
|
||||||
// We send a TCP request anyway, see if we get a response
|
// We send a TCP request anyway, see if we get a response
|
||||||
tcpStream, err := conn.OpenStream()
|
tcpStream, err := conn.OpenStream()
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error opening stream:", err)
|
|
||||||
}
|
|
||||||
defer tcpStream.Close()
|
defer tcpStream.Close()
|
||||||
err = protocol.WriteTCPRequest(tcpStream, "www.google.com:443")
|
err = protocol.WriteTCPRequest(tcpStream, "www.google.com:443")
|
||||||
if err != nil {
|
assert.NoError(t, err)
|
||||||
t.Fatal("error sending request:", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We should receive nothing
|
// We should receive nothing
|
||||||
_ = tcpStream.SetReadDeadline(time.Now().Add(2 * time.Second))
|
_ = tcpStream.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||||
n, err := tcpStream.Read(buf)
|
n, err := tcpStream.Read(buf)
|
||||||
if n != 0 {
|
assert.Equal(t, 0, n)
|
||||||
t.Fatal("expected no response, got", n)
|
nErr, ok := err.(net.Error)
|
||||||
}
|
assert.True(t, ok)
|
||||||
if nErr, ok := err.(net.Error); !ok || !nErr.Timeout() {
|
assert.True(t, nErr.Timeout())
|
||||||
t.Fatal("expected timeout, got", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
395
core/internal/integration_tests/mocks/mock_Conn.go
Normal file
395
core/internal/integration_tests/mocks/mock_Conn.go
Normal file
|
@ -0,0 +1,395 @@
|
||||||
|
// Code generated by mockery v2.32.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
net "net"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
time "time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockConn is an autogenerated mock type for the Conn type
|
||||||
|
type MockConn struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockConn_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockConn) EXPECT() *MockConn_Expecter {
|
||||||
|
return &MockConn_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close provides a mock function with given fields:
|
||||||
|
func (_m *MockConn) Close() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||||
|
type MockConn_Close_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close is a helper method to define mock.On call
|
||||||
|
func (_e *MockConn_Expecter) Close() *MockConn_Close_Call {
|
||||||
|
return &MockConn_Close_Call{Call: _e.mock.On("Close")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Close_Call) Run(run func()) *MockConn_Close_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Close_Call) Return(_a0 error) *MockConn_Close_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Close_Call) RunAndReturn(run func() error) *MockConn_Close_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalAddr provides a mock function with given fields:
|
||||||
|
func (_m *MockConn) LocalAddr() net.Addr {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 net.Addr
|
||||||
|
if rf, ok := ret.Get(0).(func() net.Addr); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(net.Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_LocalAddr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'LocalAddr'
|
||||||
|
type MockConn_LocalAddr_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocalAddr is a helper method to define mock.On call
|
||||||
|
func (_e *MockConn_Expecter) LocalAddr() *MockConn_LocalAddr_Call {
|
||||||
|
return &MockConn_LocalAddr_Call{Call: _e.mock.On("LocalAddr")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_LocalAddr_Call) Run(run func()) *MockConn_LocalAddr_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_LocalAddr_Call) Return(_a0 net.Addr) *MockConn_LocalAddr_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_LocalAddr_Call) RunAndReturn(run func() net.Addr) *MockConn_LocalAddr_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read provides a mock function with given fields: b
|
||||||
|
func (_m *MockConn) Read(b []byte) (int, error) {
|
||||||
|
ret := _m.Called(b)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok {
|
||||||
|
return rf(b)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) int); ok {
|
||||||
|
r0 = rf(b)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(b)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_Read_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Read'
|
||||||
|
type MockConn_Read_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read is a helper method to define mock.On call
|
||||||
|
// - b []byte
|
||||||
|
func (_e *MockConn_Expecter) Read(b interface{}) *MockConn_Read_Call {
|
||||||
|
return &MockConn_Read_Call{Call: _e.mock.On("Read", b)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Read_Call) Run(run func(b []byte)) *MockConn_Read_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Read_Call) Return(n int, err error) *MockConn_Read_Call {
|
||||||
|
_c.Call.Return(n, err)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Read_Call) RunAndReturn(run func([]byte) (int, error)) *MockConn_Read_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr provides a mock function with given fields:
|
||||||
|
func (_m *MockConn) RemoteAddr() net.Addr {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 net.Addr
|
||||||
|
if rf, ok := ret.Get(0).(func() net.Addr); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(net.Addr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_RemoteAddr_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoteAddr'
|
||||||
|
type MockConn_RemoteAddr_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// RemoteAddr is a helper method to define mock.On call
|
||||||
|
func (_e *MockConn_Expecter) RemoteAddr() *MockConn_RemoteAddr_Call {
|
||||||
|
return &MockConn_RemoteAddr_Call{Call: _e.mock.On("RemoteAddr")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_RemoteAddr_Call) Run(run func()) *MockConn_RemoteAddr_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_RemoteAddr_Call) Return(_a0 net.Addr) *MockConn_RemoteAddr_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_RemoteAddr_Call) RunAndReturn(run func() net.Addr) *MockConn_RemoteAddr_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline provides a mock function with given fields: t
|
||||||
|
func (_m *MockConn) SetDeadline(t time.Time) error {
|
||||||
|
ret := _m.Called(t)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(time.Time) error); ok {
|
||||||
|
r0 = rf(t)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_SetDeadline_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetDeadline'
|
||||||
|
type MockConn_SetDeadline_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDeadline is a helper method to define mock.On call
|
||||||
|
// - t time.Time
|
||||||
|
func (_e *MockConn_Expecter) SetDeadline(t interface{}) *MockConn_SetDeadline_Call {
|
||||||
|
return &MockConn_SetDeadline_Call{Call: _e.mock.On("SetDeadline", t)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetDeadline_Call) Run(run func(t time.Time)) *MockConn_SetDeadline_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(time.Time))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetDeadline_Call) Return(_a0 error) *MockConn_SetDeadline_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetDeadline_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline provides a mock function with given fields: t
|
||||||
|
func (_m *MockConn) SetReadDeadline(t time.Time) error {
|
||||||
|
ret := _m.Called(t)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(time.Time) error); ok {
|
||||||
|
r0 = rf(t)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_SetReadDeadline_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetReadDeadline'
|
||||||
|
type MockConn_SetReadDeadline_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetReadDeadline is a helper method to define mock.On call
|
||||||
|
// - t time.Time
|
||||||
|
func (_e *MockConn_Expecter) SetReadDeadline(t interface{}) *MockConn_SetReadDeadline_Call {
|
||||||
|
return &MockConn_SetReadDeadline_Call{Call: _e.mock.On("SetReadDeadline", t)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetReadDeadline_Call) Run(run func(t time.Time)) *MockConn_SetReadDeadline_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(time.Time))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetReadDeadline_Call) Return(_a0 error) *MockConn_SetReadDeadline_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetReadDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetReadDeadline_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline provides a mock function with given fields: t
|
||||||
|
func (_m *MockConn) SetWriteDeadline(t time.Time) error {
|
||||||
|
ret := _m.Called(t)
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func(time.Time) error); ok {
|
||||||
|
r0 = rf(t)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_SetWriteDeadline_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'SetWriteDeadline'
|
||||||
|
type MockConn_SetWriteDeadline_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetWriteDeadline is a helper method to define mock.On call
|
||||||
|
// - t time.Time
|
||||||
|
func (_e *MockConn_Expecter) SetWriteDeadline(t interface{}) *MockConn_SetWriteDeadline_Call {
|
||||||
|
return &MockConn_SetWriteDeadline_Call{Call: _e.mock.On("SetWriteDeadline", t)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetWriteDeadline_Call) Run(run func(t time.Time)) *MockConn_SetWriteDeadline_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(time.Time))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetWriteDeadline_Call) Return(_a0 error) *MockConn_SetWriteDeadline_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_SetWriteDeadline_Call) RunAndReturn(run func(time.Time) error) *MockConn_SetWriteDeadline_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write provides a mock function with given fields: b
|
||||||
|
func (_m *MockConn) Write(b []byte) (int, error) {
|
||||||
|
ret := _m.Called(b)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) (int, error)); ok {
|
||||||
|
return rf(b)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) int); ok {
|
||||||
|
r0 = rf(b)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||||
|
r1 = rf(b)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockConn_Write_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Write'
|
||||||
|
type MockConn_Write_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write is a helper method to define mock.On call
|
||||||
|
// - b []byte
|
||||||
|
func (_e *MockConn_Expecter) Write(b interface{}) *MockConn_Write_Call {
|
||||||
|
return &MockConn_Write_Call{Call: _e.mock.On("Write", b)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Write_Call) Run(run func(b []byte)) *MockConn_Write_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Write_Call) Return(n int, err error) *MockConn_Write_Call {
|
||||||
|
_c.Call.Return(n, err)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockConn_Write_Call) RunAndReturn(run func([]byte) (int, error)) *MockConn_Write_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockConn creates a new instance of MockConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockConn(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockConn {
|
||||||
|
mock := &MockConn{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
146
core/internal/integration_tests/mocks/mock_Outbound.go
Normal file
146
core/internal/integration_tests/mocks/mock_Outbound.go
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
// Code generated by mockery v2.32.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import (
|
||||||
|
net "net"
|
||||||
|
|
||||||
|
mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
server "github.com/apernet/hysteria/core/server"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockOutbound is an autogenerated mock type for the Outbound type
|
||||||
|
type MockOutbound struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockOutbound_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockOutbound) EXPECT() *MockOutbound_Expecter {
|
||||||
|
return &MockOutbound_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCP provides a mock function with given fields: reqAddr
|
||||||
|
func (_m *MockOutbound) TCP(reqAddr string) (net.Conn, error) {
|
||||||
|
ret := _m.Called(reqAddr)
|
||||||
|
|
||||||
|
var r0 net.Conn
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string) (net.Conn, error)); ok {
|
||||||
|
return rf(reqAddr)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(string) net.Conn); ok {
|
||||||
|
r0 = rf(reqAddr)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(net.Conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||||
|
r1 = rf(reqAddr)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockOutbound_TCP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'TCP'
|
||||||
|
type MockOutbound_TCP_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// TCP is a helper method to define mock.On call
|
||||||
|
// - reqAddr string
|
||||||
|
func (_e *MockOutbound_Expecter) TCP(reqAddr interface{}) *MockOutbound_TCP_Call {
|
||||||
|
return &MockOutbound_TCP_Call{Call: _e.mock.On("TCP", reqAddr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_TCP_Call) Run(run func(reqAddr string)) *MockOutbound_TCP_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_TCP_Call) Return(_a0 net.Conn, _a1 error) *MockOutbound_TCP_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_TCP_Call) RunAndReturn(run func(string) (net.Conn, error)) *MockOutbound_TCP_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDP provides a mock function with given fields: reqAddr
|
||||||
|
func (_m *MockOutbound) UDP(reqAddr string) (server.UDPConn, error) {
|
||||||
|
ret := _m.Called(reqAddr)
|
||||||
|
|
||||||
|
var r0 server.UDPConn
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func(string) (server.UDPConn, error)); ok {
|
||||||
|
return rf(reqAddr)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func(string) server.UDPConn); ok {
|
||||||
|
r0 = rf(reqAddr)
|
||||||
|
} else {
|
||||||
|
if ret.Get(0) != nil {
|
||||||
|
r0 = ret.Get(0).(server.UDPConn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func(string) error); ok {
|
||||||
|
r1 = rf(reqAddr)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockOutbound_UDP_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UDP'
|
||||||
|
type MockOutbound_UDP_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// UDP is a helper method to define mock.On call
|
||||||
|
// - reqAddr string
|
||||||
|
func (_e *MockOutbound_Expecter) UDP(reqAddr interface{}) *MockOutbound_UDP_Call {
|
||||||
|
return &MockOutbound_UDP_Call{Call: _e.mock.On("UDP", reqAddr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_UDP_Call) Run(run func(reqAddr string)) *MockOutbound_UDP_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_UDP_Call) Return(_a0 server.UDPConn, _a1 error) *MockOutbound_UDP_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockOutbound_UDP_Call) RunAndReturn(run func(string) (server.UDPConn, error)) *MockOutbound_UDP_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockOutbound creates a new instance of MockOutbound. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockOutbound(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockOutbound {
|
||||||
|
mock := &MockOutbound{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
185
core/internal/integration_tests/mocks/mock_UDPConn.go
Normal file
185
core/internal/integration_tests/mocks/mock_UDPConn.go
Normal file
|
@ -0,0 +1,185 @@
|
||||||
|
// Code generated by mockery v2.32.0. DO NOT EDIT.
|
||||||
|
|
||||||
|
package mocks
|
||||||
|
|
||||||
|
import mock "github.com/stretchr/testify/mock"
|
||||||
|
|
||||||
|
// MockUDPConn is an autogenerated mock type for the UDPConn type
|
||||||
|
type MockUDPConn struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
type MockUDPConn_Expecter struct {
|
||||||
|
mock *mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_m *MockUDPConn) EXPECT() *MockUDPConn_Expecter {
|
||||||
|
return &MockUDPConn_Expecter{mock: &_m.Mock}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close provides a mock function with given fields:
|
||||||
|
func (_m *MockUDPConn) Close() error {
|
||||||
|
ret := _m.Called()
|
||||||
|
|
||||||
|
var r0 error
|
||||||
|
if rf, ok := ret.Get(0).(func() error); ok {
|
||||||
|
r0 = rf()
|
||||||
|
} else {
|
||||||
|
r0 = ret.Error(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUDPConn_Close_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'Close'
|
||||||
|
type MockUDPConn_Close_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close is a helper method to define mock.On call
|
||||||
|
func (_e *MockUDPConn_Expecter) Close() *MockUDPConn_Close_Call {
|
||||||
|
return &MockUDPConn_Close_Call{Call: _e.mock.On("Close")}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_Close_Call) Run(run func()) *MockUDPConn_Close_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run()
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_Close_Call) Return(_a0 error) *MockUDPConn_Close_Call {
|
||||||
|
_c.Call.Return(_a0)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_Close_Call) RunAndReturn(run func() error) *MockUDPConn_Close_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFrom provides a mock function with given fields: b
|
||||||
|
func (_m *MockUDPConn) ReadFrom(b []byte) (int, string, error) {
|
||||||
|
ret := _m.Called(b)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 string
|
||||||
|
var r2 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) (int, string, error)); ok {
|
||||||
|
return rf(b)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte) int); ok {
|
||||||
|
r0 = rf(b)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte) string); ok {
|
||||||
|
r1 = rf(b)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Get(1).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(2).(func([]byte) error); ok {
|
||||||
|
r2 = rf(b)
|
||||||
|
} else {
|
||||||
|
r2 = ret.Error(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1, r2
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUDPConn_ReadFrom_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ReadFrom'
|
||||||
|
type MockUDPConn_ReadFrom_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFrom is a helper method to define mock.On call
|
||||||
|
// - b []byte
|
||||||
|
func (_e *MockUDPConn_Expecter) ReadFrom(b interface{}) *MockUDPConn_ReadFrom_Call {
|
||||||
|
return &MockUDPConn_ReadFrom_Call{Call: _e.mock.On("ReadFrom", b)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_ReadFrom_Call) Run(run func(b []byte)) *MockUDPConn_ReadFrom_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].([]byte))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_ReadFrom_Call) Return(_a0 int, _a1 string, _a2 error) *MockUDPConn_ReadFrom_Call {
|
||||||
|
_c.Call.Return(_a0, _a1, _a2)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_ReadFrom_Call) RunAndReturn(run func([]byte) (int, string, error)) *MockUDPConn_ReadFrom_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo provides a mock function with given fields: b, addr
|
||||||
|
func (_m *MockUDPConn) WriteTo(b []byte, addr string) (int, error) {
|
||||||
|
ret := _m.Called(b, addr)
|
||||||
|
|
||||||
|
var r0 int
|
||||||
|
var r1 error
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte, string) (int, error)); ok {
|
||||||
|
return rf(b, addr)
|
||||||
|
}
|
||||||
|
if rf, ok := ret.Get(0).(func([]byte, string) int); ok {
|
||||||
|
r0 = rf(b, addr)
|
||||||
|
} else {
|
||||||
|
r0 = ret.Get(0).(int)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rf, ok := ret.Get(1).(func([]byte, string) error); ok {
|
||||||
|
r1 = rf(b, addr)
|
||||||
|
} else {
|
||||||
|
r1 = ret.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r0, r1
|
||||||
|
}
|
||||||
|
|
||||||
|
// MockUDPConn_WriteTo_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'WriteTo'
|
||||||
|
type MockUDPConn_WriteTo_Call struct {
|
||||||
|
*mock.Call
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteTo is a helper method to define mock.On call
|
||||||
|
// - b []byte
|
||||||
|
// - addr string
|
||||||
|
func (_e *MockUDPConn_Expecter) WriteTo(b interface{}, addr interface{}) *MockUDPConn_WriteTo_Call {
|
||||||
|
return &MockUDPConn_WriteTo_Call{Call: _e.mock.On("WriteTo", b, addr)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_WriteTo_Call) Run(run func(b []byte, addr string)) *MockUDPConn_WriteTo_Call {
|
||||||
|
_c.Call.Run(func(args mock.Arguments) {
|
||||||
|
run(args[0].([]byte), args[1].(string))
|
||||||
|
})
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_WriteTo_Call) Return(_a0 int, _a1 error) *MockUDPConn_WriteTo_Call {
|
||||||
|
_c.Call.Return(_a0, _a1)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_c *MockUDPConn_WriteTo_Call) RunAndReturn(run func([]byte, string) (int, error)) *MockUDPConn_WriteTo_Call {
|
||||||
|
_c.Call.Return(run)
|
||||||
|
return _c
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockUDPConn creates a new instance of MockUDPConn. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||||
|
// The first argument is typically a *testing.T value.
|
||||||
|
func NewMockUDPConn(t interface {
|
||||||
|
mock.TestingT
|
||||||
|
Cleanup(func())
|
||||||
|
}) *MockUDPConn {
|
||||||
|
mock := &MockUDPConn{}
|
||||||
|
mock.Mock.Test(t)
|
||||||
|
|
||||||
|
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||||
|
|
||||||
|
return mock
|
||||||
|
}
|
|
@ -28,13 +28,13 @@ func TestClientNoServer(t *testing.T) {
|
||||||
var cErr *coreErrs.ConnectError
|
var cErr *coreErrs.ConnectError
|
||||||
|
|
||||||
// Try TCP
|
// Try TCP
|
||||||
_, err = c.DialTCP("google.com:443")
|
_, err = c.TCP("google.com:443")
|
||||||
if !errors.As(err, &cErr) {
|
if !errors.As(err, &cErr) {
|
||||||
t.Fatal("expected connect error from DialTCP")
|
t.Fatal("expected connect error from TCP")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try UDP
|
// Try UDP
|
||||||
_, err = c.ListenUDP()
|
_, err = c.UDP()
|
||||||
if !errors.As(err, &cErr) {
|
if !errors.As(err, &cErr) {
|
||||||
t.Fatal("expected connect error from DialUDP")
|
t.Fatal("expected connect error from DialUDP")
|
||||||
}
|
}
|
||||||
|
@ -78,13 +78,13 @@ func TestClientServerBadAuth(t *testing.T) {
|
||||||
var aErr *coreErrs.AuthError
|
var aErr *coreErrs.AuthError
|
||||||
|
|
||||||
// Try TCP
|
// Try TCP
|
||||||
_, err = c.DialTCP("google.com:443")
|
_, err = c.TCP("google.com:443")
|
||||||
if !errors.As(err, &aErr) {
|
if !errors.As(err, &aErr) {
|
||||||
t.Fatal("expected auth error from DialTCP")
|
t.Fatal("expected auth error from TCP")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try UDP
|
// Try UDP
|
||||||
_, err = c.ListenUDP()
|
_, err = c.UDP()
|
||||||
if !errors.As(err, &aErr) {
|
if !errors.As(err, &aErr) {
|
||||||
t.Fatal("expected auth error from DialUDP")
|
t.Fatal("expected auth error from DialUDP")
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ func TestClientServerTCPEcho(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
// Dial TCP
|
// Dial TCP
|
||||||
conn, err := c.DialTCP(echoTCPAddr.String())
|
conn, err := c.TCP(echoTCPAddr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("error dialing TCP:", err)
|
t.Fatal("error dialing TCP:", err)
|
||||||
}
|
}
|
||||||
|
@ -200,7 +200,7 @@ func TestClientServerUDPEcho(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
// Listen UDP
|
// Listen UDP
|
||||||
conn, err := c.ListenUDP()
|
conn, err := c.UDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("error listening UDP:", err)
|
t.Fatal("error listening UDP:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -172,7 +172,7 @@ func TestClientServerTCPStress(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
dialFunc := func() (net.Conn, error) {
|
dialFunc := func() (net.Conn, error) {
|
||||||
return c.DialTCP(echoTCPAddr.String())
|
return c.TCP(echoTCPAddr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("Single 500m", (&tcpStressor{DialFunc: dialFunc, Size: 524288000, Parallel: 1, Iterations: 1}).Run)
|
t.Run("Single 500m", (&tcpStressor{DialFunc: dialFunc, Size: 524288000, Parallel: 1, Iterations: 1}).Run)
|
||||||
|
@ -227,7 +227,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
t.Run("Single 1000x100b", (&udpStressor{
|
t.Run("Single 1000x100b", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Count: 1000,
|
Count: 1000,
|
||||||
|
@ -235,7 +235,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
Iterations: 1,
|
Iterations: 1,
|
||||||
}).Run)
|
}).Run)
|
||||||
t.Run("Single 1000x3k", (&udpStressor{
|
t.Run("Single 1000x3k", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 3000,
|
Size: 3000,
|
||||||
Count: 1000,
|
Count: 1000,
|
||||||
|
@ -244,7 +244,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
}).Run)
|
}).Run)
|
||||||
|
|
||||||
t.Run("5 Sequential 1000x100b", (&udpStressor{
|
t.Run("5 Sequential 1000x100b", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Count: 1000,
|
Count: 1000,
|
||||||
|
@ -252,7 +252,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
Iterations: 5,
|
Iterations: 5,
|
||||||
}).Run)
|
}).Run)
|
||||||
t.Run("5 Sequential 200x3k", (&udpStressor{
|
t.Run("5 Sequential 200x3k", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 3000,
|
Size: 3000,
|
||||||
Count: 200,
|
Count: 200,
|
||||||
|
@ -261,7 +261,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
}).Run)
|
}).Run)
|
||||||
|
|
||||||
t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{
|
t.Run("2 Sequential 5 Parallel 1000x100b", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 100,
|
Size: 100,
|
||||||
Count: 1000,
|
Count: 1000,
|
||||||
|
@ -270,7 +270,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
}).Run)
|
}).Run)
|
||||||
|
|
||||||
t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{
|
t.Run("2 Sequential 5 Parallel 200x3k", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 3000,
|
Size: 3000,
|
||||||
Count: 200,
|
Count: 200,
|
||||||
|
@ -279,7 +279,7 @@ func TestClientServerUDPStress(t *testing.T) {
|
||||||
}).Run)
|
}).Run)
|
||||||
|
|
||||||
t.Run("10 Sequential 5 Parallel 200x3k", (&udpStressor{
|
t.Run("10 Sequential 5 Parallel 200x3k", (&udpStressor{
|
||||||
ListenFunc: c.ListenUDP,
|
ListenFunc: c.UDP,
|
||||||
ServerAddr: echoUDPAddr.String(),
|
ServerAddr: echoUDPAddr.String(),
|
||||||
Size: 3000,
|
Size: 3000,
|
||||||
Count: 200,
|
Count: 200,
|
||||||
|
|
|
@ -84,7 +84,7 @@ func TestServerTrafficLogger(t *testing.T) {
|
||||||
defer c.Close()
|
defer c.Close()
|
||||||
|
|
||||||
// Dial TCP
|
// Dial TCP
|
||||||
tConn, err := c.DialTCP(echoTCPAddr.String())
|
tConn, err := c.TCP(echoTCPAddr.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("error dialing TCP:", err)
|
t.Fatal("error dialing TCP:", err)
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ func TestServerTrafficLogger(t *testing.T) {
|
||||||
go uEchoServer.Serve()
|
go uEchoServer.Serve()
|
||||||
|
|
||||||
// Listen UDP
|
// Listen UDP
|
||||||
uConn, err := c.ListenUDP()
|
uConn, err := c.UDP()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("error listening UDP:", err)
|
t.Fatal("error listening UDP:", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,6 +26,15 @@ func serverTLSConfig() server.TLSConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func serverConn() (net.PacketConn, net.Addr, error) {
|
||||||
|
udpAddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 14514}
|
||||||
|
udpConn, err := net.ListenUDP("udp", udpAddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
return udpConn, udpAddr, nil
|
||||||
|
}
|
||||||
|
|
||||||
type pwAuthenticator struct {
|
type pwAuthenticator struct {
|
||||||
Password string
|
Password string
|
||||||
ID string
|
ID string
|
||||||
|
|
|
@ -15,6 +15,7 @@ const (
|
||||||
defaultConnReceiveWindow = defaultStreamReceiveWindow * 5 / 2 // 20MB
|
defaultConnReceiveWindow = defaultStreamReceiveWindow * 5 / 2 // 20MB
|
||||||
defaultMaxIdleTimeout = 30 * time.Second
|
defaultMaxIdleTimeout = 30 * time.Second
|
||||||
defaultMaxIncomingStreams = 1024
|
defaultMaxIncomingStreams = 1024
|
||||||
|
defaultUDPIdleTimeout = 60 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
@ -24,6 +25,7 @@ type Config struct {
|
||||||
Outbound Outbound
|
Outbound Outbound
|
||||||
BandwidthConfig BandwidthConfig
|
BandwidthConfig BandwidthConfig
|
||||||
DisableUDP bool
|
DisableUDP bool
|
||||||
|
UDPIdleTimeout time.Duration
|
||||||
Authenticator Authenticator
|
Authenticator Authenticator
|
||||||
EventLogger EventLogger
|
EventLogger EventLogger
|
||||||
TrafficLogger TrafficLogger
|
TrafficLogger TrafficLogger
|
||||||
|
@ -79,6 +81,11 @@ func (c *Config) fill() error {
|
||||||
if c.BandwidthConfig.MaxRx != 0 && c.BandwidthConfig.MaxRx < 65536 {
|
if c.BandwidthConfig.MaxRx != 0 && c.BandwidthConfig.MaxRx < 65536 {
|
||||||
return errors.ConfigError{Field: "BandwidthConfig.MaxRx", Reason: "must be at least 65536"}
|
return errors.ConfigError{Field: "BandwidthConfig.MaxRx", Reason: "must be at least 65536"}
|
||||||
}
|
}
|
||||||
|
if c.UDPIdleTimeout == 0 {
|
||||||
|
c.UDPIdleTimeout = defaultUDPIdleTimeout
|
||||||
|
} else if c.UDPIdleTimeout < 2*time.Second || c.UDPIdleTimeout > 600*time.Second {
|
||||||
|
return errors.ConfigError{Field: "UDPIdleTimeout", Reason: "must be between 2s and 600s"}
|
||||||
|
}
|
||||||
if c.Authenticator == nil {
|
if c.Authenticator == nil {
|
||||||
return errors.ConfigError{Field: "Authenticator", Reason: "must be set"}
|
return errors.ConfigError{Field: "Authenticator", Reason: "must be set"}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,21 +5,18 @@ import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"net/http"
|
"net/http"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
"github.com/quic-go/quic-go"
|
||||||
|
"github.com/quic-go/quic-go/http3"
|
||||||
|
|
||||||
"github.com/apernet/hysteria/core/internal/congestion"
|
"github.com/apernet/hysteria/core/internal/congestion"
|
||||||
"github.com/apernet/hysteria/core/internal/protocol"
|
"github.com/apernet/hysteria/core/internal/protocol"
|
||||||
"github.com/apernet/hysteria/core/internal/utils"
|
"github.com/apernet/hysteria/core/internal/utils"
|
||||||
|
|
||||||
"github.com/quic-go/quic-go"
|
|
||||||
"github.com/quic-go/quic-go/http3"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
closeErrCodeOK = 0x100 // HTTP3 ErrCodeNoError
|
closeErrCodeOK = 0x100 // HTTP3 ErrCodeNoError
|
||||||
closeErrCodeTrafficLimitReached = 0x107 // HTTP3 ErrCodeExcessiveLoad
|
closeErrCodeTrafficLimitReached = 0x107 // HTTP3 ErrCodeExcessiveLoad
|
||||||
|
|
||||||
udpSessionIdleTimeout = 60 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Server interface {
|
type Server interface {
|
||||||
|
@ -148,7 +145,7 @@ func (h *h3sHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
sm := newUDPSessionManager(
|
sm := newUDPSessionManager(
|
||||||
&udpIOImpl{h.conn, id, h.config.TrafficLogger, h.config.Outbound},
|
&udpIOImpl{h.conn, id, h.config.TrafficLogger, h.config.Outbound},
|
||||||
&udpEventLoggerImpl{h.conn, id, h.config.EventLogger},
|
&udpEventLoggerImpl{h.conn, id, h.config.EventLogger},
|
||||||
udpSessionIdleTimeout)
|
h.config.UDPIdleTimeout)
|
||||||
h.udpSM = sm
|
h.udpSM = sm
|
||||||
go sm.Run()
|
go sm.Run()
|
||||||
})
|
})
|
||||||
|
|
|
@ -170,6 +170,6 @@ func TestUDPSessionManager(t *testing.T) {
|
||||||
// Leak checks
|
// Leak checks
|
||||||
close(msgCh) // This will return error from ReceiveMessage(), should stop the session manager
|
close(msgCh) // This will return error from ReceiveMessage(), should stop the session manager
|
||||||
time.Sleep(1 * time.Second) // Wait one more second just to be sure
|
time.Sleep(1 * time.Second) // Wait one more second just to be sure
|
||||||
assert.Equal(t, sm.Count(), 0, "session count should be 0")
|
assert.Zero(t, sm.Count(), "session count should be 0")
|
||||||
goleak.VerifyNone(t)
|
goleak.VerifyNone(t)
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,15 +58,15 @@ func TestPluggableOutboundAdapter(t *testing.T) {
|
||||||
adapter := &PluggableOutboundAdapter{
|
adapter := &PluggableOutboundAdapter{
|
||||||
PluggableOutbound: &mockPluggableOutbound{},
|
PluggableOutbound: &mockPluggableOutbound{},
|
||||||
}
|
}
|
||||||
// DialTCP with correct addr
|
// TCP with correct addr
|
||||||
_, err := adapter.DialTCP("correct_host_1:34567")
|
_, err := adapter.DialTCP("correct_host_1:34567")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("DialTCP with correct addr failed", err)
|
t.Fatal("TCP with correct addr failed", err)
|
||||||
}
|
}
|
||||||
// DialTCP with wrong addr
|
// TCP with wrong addr
|
||||||
_, err = adapter.DialTCP("wrong_host_1:34567")
|
_, err = adapter.DialTCP("wrong_host_1:34567")
|
||||||
if err != errWrongAddr {
|
if err != errWrongAddr {
|
||||||
t.Fatal("DialTCP with wrong addr should fail, got", err)
|
t.Fatal("TCP with wrong addr should fail, got", err)
|
||||||
}
|
}
|
||||||
// DialUDP
|
// DialUDP
|
||||||
uConn, err := adapter.DialUDP()
|
uConn, err := adapter.DialUDP()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue