mirror of
https://github.com/hackdiaz-dev/free-turn-proxy.git
synced 2026-10-12 09:41:53 +02:00
fix(turndial): детект блэкхола по ChannelBind, не CreatePermission refresh
VK реджектит standalone CreatePermission refresh с 400 независимо от здоровья стрима, поэтому permWatch ложно рециклил здоровые аллокации каждые ~60s. Permission держится живым через ChannelBind refresh (RFC 8656 §11), стандартный для VK путь, потому отдельный CreatePermission refresh глушим (PermissionRefreshInterval 24h). Реальный блэкхол ловим по провалу ChannelBind refresh (data-path), сброс на успешном байнде.
This commit is contained in:
@@ -271,13 +271,13 @@ func oneTURN(ctx context.Context, deps *Deps, params *Params, peer *net.UDPAddr,
|
||||
|
||||
const maxPayload = 1600
|
||||
|
||||
// PermDead закрывается при блэкхоле permission (см. turndial/permwatch.go) —
|
||||
// PermDead закрывается при блэкхоле data-path (см. turndial/permwatch.go) —
|
||||
// отменяем turnctx, TURNLoop делает свежий allocate.
|
||||
wg.Go(func() {
|
||||
select {
|
||||
case <-turnctx.Done():
|
||||
case <-stream.PermDead:
|
||||
deps.log().Warnf("[STREAM %d] TURN permission refresh умер — рецикл allocation", streamID)
|
||||
deps.log().Warnf("[STREAM %d] TURN channel-bind умер — рецикл allocation", streamID)
|
||||
turncancel()
|
||||
}
|
||||
})
|
||||
|
||||
@@ -7,15 +7,11 @@ import (
|
||||
"github.com/pion/logging"
|
||||
)
|
||||
|
||||
// VK relay при дропе permission молча роняет пакеты к peer без ошибки записи.
|
||||
// pion на каждый проваленный цикл refresh пишет permFailMarker (Warnf, scope
|
||||
// "turnc"). Считаем провалы подряд — точный per-stream детект блэкхола вместо
|
||||
// трафик-эвристики (обратный путь WG привязан к endpoint, не к стриму).
|
||||
const (
|
||||
permFailMarker = "Failed to refresh permissions"
|
||||
permOKMarker = "Refresh permissions successful"
|
||||
permFailMarker = "Failed to bind channel"
|
||||
permOKMarker = "Channel binding successful"
|
||||
turncScope = "turnc"
|
||||
// ~60s при PermissionRefreshInterval=30s, внутри 5-мин lifetime permission.
|
||||
// ChannelBind refresh идёт ~раз в 5 мин (binding lifetime); 2 провала подряд.
|
||||
permFailThreshold = 2
|
||||
)
|
||||
|
||||
|
||||
@@ -37,8 +37,8 @@ type Stream struct {
|
||||
Relay net.PacketConn
|
||||
// ServerUDPAddr — резолвнутый UDP-адрес TURN-сервера (host:port).
|
||||
ServerUDPAddr *net.UDPAddr
|
||||
// PermDead закрывается при стойком провале refresh permission (relay
|
||||
// блэкхолит) — вызывающий рециклит allocation. См. permwatch.go.
|
||||
// PermDead закрывается при стойком провале ChannelBind refresh (relay
|
||||
// блэкхолит data-path) - вызывающий рециклит allocation. См. permwatch.go.
|
||||
PermDead <-chan struct{}
|
||||
close func() error
|
||||
}
|
||||
@@ -108,7 +108,9 @@ func Open(ctx context.Context, cfg Config, peer *net.UDPAddr, user, pass, rawAdd
|
||||
addrFamily = turn.RequestedAddressFamilyIPv6
|
||||
}
|
||||
|
||||
// RefreshInterval 120s→30s: быстрее ловим блэкхол, внутри 5-мин lifetime.
|
||||
// Standalone CreatePermission refresh VK реджектит 400 — глушим (24h).
|
||||
// Permission держится живым через ChannelBind refresh (RFC 8656 §11);
|
||||
// блэкхол ловим по провалу этого байнда (см. permwatch.go).
|
||||
permDead := make(chan struct{})
|
||||
var permOnce sync.Once
|
||||
loggerFactory := &permWatchFactory{
|
||||
@@ -124,7 +126,7 @@ func Open(ctx context.Context, cfg Config, peer *net.UDPAddr, user, pass, rawAdd
|
||||
Username: user,
|
||||
Password: pass,
|
||||
RequestedAddressFamily: addrFamily,
|
||||
PermissionRefreshInterval: 30 * time.Second,
|
||||
PermissionRefreshInterval: 24 * time.Hour,
|
||||
LoggerFactory: loggerFactory,
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user