From a033cfb9a2097365e144fa79a55ecaf12dc07c3e Mon Sep 17 00:00:00 2001 From: samosvalishe Date: Mon, 17 Aug 2026 17:13:44 +0300 Subject: [PATCH] =?UTF-8?q?fix(udprelay):=20=D1=80=D0=B5=D1=86=D0=B8=D0=BA?= =?UTF-8?q?=D0=BB=20=D0=B0=D0=BB=D0=BB=D0=BE=D0=BA=D0=B0=D1=86=D0=B8=D0=B8?= =?UTF-8?q?=20=D0=BD=D0=B0=20=D0=BF=D1=80=D0=BE=D1=81=D1=82=D0=BE=D0=B5=20?= =?UTF-8?q?=D1=82=D1=83=D0=BD=D0=BD=D0=B5=D0=BB=D1=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/proxy/udprelay/loop.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/internal/proxy/udprelay/loop.go b/internal/proxy/udprelay/loop.go index c66faa6..b91e28c 100644 --- a/internal/proxy/udprelay/loop.go +++ b/internal/proxy/udprelay/loop.go @@ -46,14 +46,15 @@ func DTLSLoop(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr } // TURNLoop управляет жизненным циклом одной TURN-аллокации. -func TURNLoop(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr, connchan <-chan net.PacketConn, t <-chan time.Time, streamID int) { +func TURNLoop(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr, connchan <-chan net.PacketConn, streamID int) { for { select { case <-ctx.Done(): return case conn2 := <-connchan: + // Джиттер разводит Allocate соседних стримов во времени. select { - case <-t: + case <-time.After(time.Duration(randx.Intn(400)+100) * time.Millisecond): case <-ctx.Done(): return } @@ -250,6 +251,11 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr, deps.log().Warnf("[STREAM %d] Пробуждение устройства - рецикл allocation", streamID) turncancel() } + // conn2 молчит, пока приложение не шлёт: без дедлайна его читатель досидел бы + // до первого пакета, а рецикл на простое висел бы вечно (тоннель без трафика) + if err := conn2.SetDeadline(time.Now()); err != nil { + deps.log().Errorf("[STREAM %d] Failed to set pipe deadline: %s", streamID, err) + } }) wg.Go(func() { @@ -341,4 +347,8 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr, if err := relayConn.SetDeadline(time.Time{}); err != nil { deps.log().Errorf("Failed to clear relay deadline: %s", err) } + // conn2 достаётся следующей аллокации - с истёкшим дедлайном она читала бы пустоту + if err := conn2.SetDeadline(time.Time{}); err != nil { + deps.log().Errorf("Failed to clear pipe deadline: %s", err) + } }