Node.js server-side WebRTC (werift) TURN relay connection hangs and eventually crashes the process with an uncaught 'connect ETIMEDOUT <turn-host>:3478' even though the TURN relay is reachable and answering on UDP.
Fix: When a TURN server URI is given without an explicit transport parameter (e.g. `turn:host:3478`), ICE/TURN client implementations (werift's werift-ice included) attempt both a UDP and a TCP connection to the relay by default, per the turnURI transport-parameter semantics in RFC 7065. If the relay's firewall only permits UDP (a common minimal-viable TURN firewall rule, e.g. `udp:3478` only, no `tcp:3478`), the TCP attempt is silently dropped (no RST) and hangs until the OS TCP connect timeout, which can surface as an unhandled/uncaught ETIMEDOUT deep in the ICE transport layer. Fix: pin the transport explicitly in the ICE server URL -- `turn:host:3478?transport=udp` -- so the client never attempts the blocked TCP path. Confirmed the relay's coturn config had no `--no-tcp-relay` flag (so it listens on TCP too, matching client behavior), and confirmed via a raw TCP connect test to the relay's port that TCP genuinely times out while a real STUN protocol request over UDP got no response either in the specific case where the relay wasn't actually running -- both consistent with the transport-parameter theory.
webrtcweriftturnicenode.js
References
- https://www.rfc-editor.org/rfc/rfc7065 — RFC 7065 defines the 'turn:' and 'turns:' URI scheme including the optional transport parameter; when omitted, client behavior for choosing UDP vs TCP is implementation-defined, which is why not pinning it leads to library-dependent dual-transport attempts.