mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
fix(udp): датаграммы до 2048 байт на всём пути
This commit is contained in:
@@ -22,7 +22,7 @@ type Packet struct {
|
||||
|
||||
// packetPool переиспользует буферы датаграмм.
|
||||
var packetPool = sync.Pool{
|
||||
New: func() any { return &Packet{Data: make([]byte, 2048)} },
|
||||
New: func() any { return &Packet{Data: make([]byte, maxDatagramLen)} },
|
||||
}
|
||||
|
||||
func runListener(ctx context.Context, listenConn net.PacketConn, activeLocalPeer *atomic.Value, inboundChan chan<- *Packet) error {
|
||||
|
||||
@@ -24,6 +24,10 @@ var errPairRecycled = errors.New("udprelay: stream pair recycled")
|
||||
|
||||
const (
|
||||
pipeBufLimit = 256 << 10
|
||||
// maxDatagramLen - бюджет локальной датаграммы (WG/AWG) по всей цепочке, как у сервера.
|
||||
maxDatagramLen = 2048
|
||||
// maxRecordLen - та же датаграмма в DTLS-записи: заголовок с CID, явный nonce, тег GCM.
|
||||
maxRecordLen = maxDatagramLen + 64
|
||||
)
|
||||
|
||||
// streamPair связывает DTLS-сессию с аллокацией, поверх которой она поднята. Смерть
|
||||
@@ -188,7 +192,7 @@ func dtlsSession(dtlsctx context.Context, dtlscancel context.CancelFunc, deps *D
|
||||
forwardDone := make(chan struct{})
|
||||
go func() {
|
||||
defer close(forwardDone)
|
||||
var buf [2048]byte
|
||||
var buf [maxDatagramLen]byte
|
||||
for {
|
||||
n, err := dtlsConn.Read(buf[:])
|
||||
if err != nil {
|
||||
@@ -284,8 +288,6 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
return
|
||||
}
|
||||
|
||||
const maxPayload = 1600
|
||||
|
||||
wg.Go(func() {
|
||||
select {
|
||||
case <-turnctx.Done():
|
||||
@@ -304,10 +306,10 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
defer turncancel()
|
||||
var buf, readSlot []byte
|
||||
if obfConn != nil {
|
||||
buf = make([]byte, obfConn.MaxWire(maxPayload))
|
||||
readSlot = buf[obfConn.HeaderLen() : obfConn.HeaderLen()+maxPayload]
|
||||
buf = make([]byte, obfConn.MaxWire(maxRecordLen))
|
||||
readSlot = buf[obfConn.HeaderLen() : obfConn.HeaderLen()+maxRecordLen]
|
||||
} else {
|
||||
buf = make([]byte, maxPayload)
|
||||
buf = make([]byte, maxRecordLen)
|
||||
readSlot = buf
|
||||
}
|
||||
addrStored := false
|
||||
@@ -350,9 +352,9 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
|
||||
wg.Go(func() {
|
||||
defer turncancel()
|
||||
readBufLen := maxPayload
|
||||
readBufLen := maxRecordLen
|
||||
if obfConn != nil {
|
||||
readBufLen = obfConn.MaxWire(maxPayload)
|
||||
readBufLen = obfConn.MaxWire(maxRecordLen)
|
||||
}
|
||||
buf := make([]byte, readBufLen)
|
||||
for {
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
udpRelayBufSize = 1600
|
||||
udpRelayBufSize = 2048
|
||||
udpIdleTimeout = 30 * time.Minute
|
||||
udpDeadlineRefresh = time.Minute
|
||||
)
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package udpserver
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/pion/dtls/v3"
|
||||
|
||||
"github.com/samosvalishe/free-turn-proxy/internal/logx"
|
||||
"github.com/samosvalishe/free-turn-proxy/internal/transport/dtlsdial"
|
||||
)
|
||||
|
||||
func echoBackend(t *testing.T) string {
|
||||
t.Helper()
|
||||
pc, err := (&net.ListenConfig{}).ListenPacket(t.Context(), "udp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = pc.Close() })
|
||||
go func() {
|
||||
buf := make([]byte, 64<<10)
|
||||
for {
|
||||
n, addr, err := pc.ReadFrom(buf)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, _ = pc.WriteTo(buf[:n], addr)
|
||||
}
|
||||
}()
|
||||
return pc.LocalAddr().String()
|
||||
}
|
||||
|
||||
func dtlsPair(t *testing.T, ctx context.Context, backend string) net.Conn {
|
||||
t.Helper()
|
||||
cert, err := dtlsdial.GenerateSelfSignedCert()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ln, err := dtls.ListenWithOptions("udp", &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1)}, dtls.WithCertificates(cert))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = ln.Close() })
|
||||
go func() {
|
||||
conn, aerr := ln.Accept()
|
||||
if aerr != nil {
|
||||
return
|
||||
}
|
||||
Handle(ctx, logx.Nop(), conn, backend)
|
||||
}()
|
||||
|
||||
pc, err := (&net.ListenConfig{}).ListenPacket(ctx, "udp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
serverAddr, ok := ln.Addr().(*net.UDPAddr)
|
||||
if !ok {
|
||||
t.Fatalf("listener addr %T", ln.Addr())
|
||||
}
|
||||
dialer := &dtlsdial.Dialer{HandshakeTimeout: 5 * time.Second}
|
||||
conn, err := dialer.Dial(ctx, pc, serverAddr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Cleanup(func() { _ = conn.Close() })
|
||||
return conn
|
||||
}
|
||||
|
||||
// Датаграмма в пределах клиентского буфера 2048 проходит сервер в обе стороны целиком.
|
||||
func TestHandleRelaysLargeDatagram(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(t.Context(), 10*time.Second)
|
||||
defer cancel()
|
||||
conn := dtlsPair(t, ctx, echoBackend(t))
|
||||
|
||||
for _, size := range []int{1200, 1800, 2048} {
|
||||
payload := bytes.Repeat([]byte{0x5a}, size)
|
||||
if _, err := conn.Write(payload); err != nil {
|
||||
t.Fatalf("size %d: write: %v", size, err)
|
||||
}
|
||||
_ = conn.SetReadDeadline(time.Now().Add(2 * time.Second))
|
||||
buf := make([]byte, 4096)
|
||||
n, err := conn.Read(buf)
|
||||
if err != nil || !bytes.Equal(buf[:n], payload) {
|
||||
t.Fatalf("size %d: echo n=%d err=%v", size, n, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user