ICE (native client): relay-only connections time out against a real TURN server; host-socket checks starve the relay pairs
Los mantenedores suelen responder en 2 días
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 79/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Stack tecnológico
- cpp
- Área
- backend-api-design, networking
Línea de trabajo
Empieza en src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp, en Think_TestPeerConnectivity(), y sigue cómo los tipos de candidatos permitidos determinan los candidatos locales. Reproduce el problema con la configuración relay-only descrita y compara el comportamiento de la conexión con y sin la condición propuesta para los candidatos host. Se considera terminado cuando los peers relay-only en máquinas distintas se conectan a través de TURN sin que las comprobaciones de host-socket retrasen los pares relay.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Version: master at d534c19 (1.6.x), native ICE client (steamnetworkingsockets_ice_client.cpp, ENABLE_ICE=ON, USE_STEAMWEBRTC=OFF), custom signaling.
Setup: k_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = k_nSteamNetworkingConfig_P2P_Transport_ICE_Enable_Relay, no STUN servers, one TURN server (coturn 4.6.3, use-auth-secret) with P2P_TURN_ServerList/UserList/PassList set. Both peers relay-only, on different machines, both allocate on the same TURN server.
What happens: allocations and CreatePermission succeed on both sides, the relay candidates are exchanged, and then the connection fails after the initial timeout with 5008: Timed out attempting to negotiate rendezvous ("Guessed ICE failure to be 5009: NAT traversal failed"). Verbose logging shows only ICE: STUN request 0x1 to <peer relay addr> timed out for every remote candidate. A packet capture on the TURN server shows no Send indications at all after CreatePermission: only binding requests sent directly from each peer's own socket to the other peer's relayed address, which the TURN server (correctly) drops, as it has no permission for the sender's address.
Why (as far as I can tell):
Think_TestPeerConnectivity()always adds the interface's host socket as a local candidate (// Host candidate -- always present.), even whenm_nPermittedCandidateTypespermits only relay candidates. So every remote relay candidate gets a host-socket pair, besides the relay pair. In relay-only mode those host pairs can't succeed: they send straight to a relayed address.- Pairs are unfrozen one per remote foundation at a time (
vecFoundationsUsed, keyed onm_remoteCandidate.m_sFoundationonly), and host pairs sort first. So the relay pair for a remote candidate waits until every host pair for it (one per local interface) has timed out, which takes longer than the connection's initial timeout. (RFC 8445 6.1.2.6 makes a pair's foundation from both the local and the remote candidate's foundations, so host and relay pairs to the same remote candidate wouldn't share one.)
Why it's easy to miss: with both peers (or a peer and the TURN server) on one machine, the relayed address is a local address, so a "direct" host-socket check can be sent from that address and passes the TURN server's permission check as if it were relayed. Everything works until the peers are on different machines.
Repro on one machine: run coturn with its relays on an address that's also local (e.g. ip addr add 5.5.5.5/32 dev lo, --relay-ip=5.5.5.5), and drop packets that arrive on lo for the relay ports from anything but the relay ports (nft ... iifname "lo" ip daddr 5.5.5.5 udp dport 49160-49659 udp sport != 49160-49659 drop), as a real network would. Two relay-only peers then never connect; with the patch below they connect at once.
Patch (what we ship): don't add the host local candidate when only relay candidates are permitted.
--- a/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp
+++ b/src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp
@@ -2385,8 +2385,12 @@ void CSteamNetworkingICESession::Think_TestPeerConnectivity()
ICELocalCandidate localCandidates[2];
int nLocalCandidates = 0;
- // Host candidate -- always present.
- localCandidates[nLocalCandidates++] = { pIntf.get(), {} };
+ // Host candidate -- unless only relay candidates are permitted. Then checks from the
+ // host socket would go straight to the peer's relay candidates, whose TURN server drops
+ // them (no permission for this address), and they'd hold up the relay pairs to the same
+ // remote candidates (one pair per foundation at a time) until the connection times out.
+ if ( m_nPermittedCandidateTypes & ~k_EICECandidate_Any_Relay )
+ localCandidates[nLocalCandidates++] = { pIntf.get(), {} };
The foundation point (2) probably deserves a fix of its own: in "all" mode it still delays the relay fallback behind every host pair to the same remote candidate.
Happy to open a PR with the patch if that's useful.
- Lenguaje dominante
- C++
- Estrellas
- 10k
- Forks
- 767
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de ValveSoftware/GameNetworkingSockets
-
Dificultad 4/5 Más de una semana Aptitud para principiantes 12/100
ValveSoftware/GameNetworkingSockets#465 ·
Los mantenedores suelen responder en 2 días
-
Dificultad 4/5 3-5 días Aptitud para principiantes 18/100
ValveSoftware/GameNetworkingSockets#464 ·
Los mantenedores suelen responder en 2 días
-
Assertion Failed: pSock->m_callback.m_fnCallback (socketthread.cpp:2609) after re-initializing the library with GameNetworkingSockets_Kill + GameNetworkingSockets_InitPosiblemente ocupada @siddiqueirshad la tomó hace 10 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 45/100
ValveSoftware/GameNetworkingSockets#458 ·
Los mantenedores suelen responder en 2 días
-
ISteamNetworkingSockets: Trying to use over 8 network lanes/channels failsPosiblemente ocupada @jpggvilaca la tomó hace 14 días. Abierto
Dificultad 4/5 1-2 días Aptitud para principiantes 55/100
ValveSoftware/GameNetworkingSockets#455 ·
Los mantenedores suelen responder en 2 días
-
ConfigureConnectionLanes: reconfiguring lanes can leave one lane in a stale priority classPosiblemente ocupada @sebxt la tomó hace 18 días. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 35/100
ValveSoftware/GameNetworkingSockets#453 ·
Los mantenedores suelen responder en 2 días
Todos los issues de ValveSoftware/GameNetworkingSockets
Issues similares
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Sunrisepeak/mcpp-language-server#80 ·
Los mantenedores suelen responder en 1 día
-
#2754 make deepseek api not workAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
xiaoyifang/goldendict-ng#3148 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 91/100
triton-inference-server/server#9069 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 66/100
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 76/100
Los mantenedores suelen responder en 4 días