mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-29 16:06:36 +08:00
112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
package local
|
|
|
|
import (
|
|
"bufio"
|
|
"context"
|
|
"net"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/go-gost/core/chain"
|
|
"github.com/go-gost/core/handler"
|
|
"github.com/go-gost/core/hop"
|
|
xlogger "github.com/go-gost/x/logger"
|
|
xmd "github.com/go-gost/x/metadata"
|
|
proxyproto "github.com/pires/go-proxyproto"
|
|
)
|
|
|
|
type proxyProtocolTestHop struct {
|
|
node *chain.Node
|
|
}
|
|
|
|
func (h proxyProtocolTestHop) Select(context.Context, ...hop.SelectOption) *chain.Node {
|
|
return h.node
|
|
}
|
|
|
|
func (h proxyProtocolTestHop) Nodes() []*chain.Node {
|
|
return []*chain.Node{h.node}
|
|
}
|
|
|
|
type proxyProtocolTestRouter struct{}
|
|
|
|
func (r proxyProtocolTestRouter) Options() *chain.RouterOptions {
|
|
return &chain.RouterOptions{}
|
|
}
|
|
|
|
func (r proxyProtocolTestRouter) Dial(ctx context.Context, network, address string) (net.Conn, error) {
|
|
var d net.Dialer
|
|
return d.DialContext(ctx, network, address)
|
|
}
|
|
|
|
func (r proxyProtocolTestRouter) Bind(context.Context, string, string, ...chain.BindOption) (net.Listener, error) {
|
|
return nil, net.ErrClosed
|
|
}
|
|
|
|
func TestLocalForwardHandlerSendsProxyProtocolToTarget(t *testing.T) {
|
|
targetListener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("listen target: %v", err)
|
|
}
|
|
defer targetListener.Close()
|
|
|
|
entryListener, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("listen entry: %v", err)
|
|
}
|
|
defer entryListener.Close()
|
|
|
|
h := NewHandler(
|
|
handler.RouterOption(proxyProtocolTestRouter{}),
|
|
handler.LoggerOption(xlogger.Nop()),
|
|
)
|
|
forwarder := h.(handler.Forwarder)
|
|
forwarder.Forward(proxyProtocolTestHop{node: chain.NewNode("target", targetListener.Addr().String())})
|
|
if err := h.Init(xmd.NewMetadata(map[string]any{"proxyProtocol": 2})); err != nil {
|
|
t.Fatalf("init handler: %v", err)
|
|
}
|
|
|
|
handleErr := make(chan error, 1)
|
|
acceptErr := make(chan error, 1)
|
|
go func() {
|
|
serverConn, err := entryListener.Accept()
|
|
if err != nil {
|
|
acceptErr <- err
|
|
return
|
|
}
|
|
handleErr <- h.Handle(context.Background(), serverConn)
|
|
}()
|
|
|
|
clientConn, err := net.Dial("tcp", entryListener.Addr().String())
|
|
if err != nil {
|
|
t.Fatalf("dial entry: %v", err)
|
|
}
|
|
defer clientConn.Close()
|
|
|
|
targetConn, err := targetListener.Accept()
|
|
if err != nil {
|
|
t.Fatalf("accept target: %v", err)
|
|
}
|
|
defer targetConn.Close()
|
|
if err := targetConn.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil {
|
|
t.Fatalf("set target deadline: %v", err)
|
|
}
|
|
|
|
header, err := proxyproto.Read(bufio.NewReader(targetConn))
|
|
if err != nil {
|
|
t.Fatalf("read proxy protocol header: %v", err)
|
|
}
|
|
if header.Version != 2 {
|
|
t.Fatalf("expected proxy protocol v2, got v%d", header.Version)
|
|
}
|
|
|
|
_ = clientConn.Close()
|
|
_ = targetConn.Close()
|
|
select {
|
|
case err := <-acceptErr:
|
|
t.Fatalf("accept entry: %v", err)
|
|
case <-handleErr:
|
|
case <-time.After(2 * time.Second):
|
|
t.Fatal("handler did not return after closing connections")
|
|
}
|
|
}
|