ICE (native client): relay-only connections time out against a real TURN server; host-socket checks starve the relay pairs
Maintainer thường phản hồi trong vòng 2 ngày
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 79/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- cpp
- Lĩnh vực
- backend-api-design, networking
Hướng nghiên cứu
Bắt đầu tại src/steamnetworkingsockets/clientlib/steamnetworkingsockets_ice_client.cpp, trong Think_TestPeerConnectivity(), và lần theo cách các loại candidate được cho phép xác định các candidate cục bộ. Tái hiện với cấu hình relay-only đã mô tả và so sánh hành vi kết nối khi có và không có điều kiện host-candidate được đề xuất. Hoàn thành khi các peer relay-only trên những máy khác nhau kết nối qua TURN mà không bị các kiểm tra host-socket làm chậm các cặp relay.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- C++
- Star
- 10k
- Fork
- 767
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của ValveSoftware/GameNetworkingSockets
-
Độ khó 4/5 Hơn một tuần Mức phù hợp với người mới 12/100
ValveSoftware/GameNetworkingSockets#465 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 18/100
ValveSoftware/GameNetworkingSockets#464 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
Assertion Failed: pSock->m_callback.m_fnCallback (socketthread.cpp:2609) after re-initializing the library with GameNetworkingSockets_Kill + GameNetworkingSockets_InitCó thể đã có người làm @siddiqueirshad đã nhận 10 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 45/100
ValveSoftware/GameNetworkingSockets#458 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
ISteamNetworkingSockets: Trying to use over 8 network lanes/channels failsCó thể đã có người làm @jpggvilaca đã nhận 14 ngày trước. Đang mở
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 55/100
ValveSoftware/GameNetworkingSockets#455 ·
Maintainer thường phản hồi trong vòng 2 ngày
-
ConfigureConnectionLanes: reconfiguring lanes can leave one lane in a stale priority classCó thể đã có người làm @sebxt đã nhận 18 ngày trước. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 35/100
ValveSoftware/GameNetworkingSockets#453 ·
Maintainer thường phản hồi trong vòng 2 ngày
Tất cả issue của ValveSoftware/GameNetworkingSockets
Issue tương tự
-
bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Sunrisepeak/mcpp-language-server#80 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
#2754 make deepseek api not workĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
xiaoyifang/goldendict-ng#3148 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 91/100
triton-inference-server/server#9069 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
Maintainer thường phản hồi trong vòng 4 ngày