sipsorcery
sipsorcery copied to clipboard
Enables ICE-TCP of TURN for WebRTC
This enables TCP relay communication.
The justification was that the network--even the TURN server network, only allows TCP.
Though, as it currently stands, the RFC is quite new and the browsers don't seem to be implementing it anytime soon, this mode will not support connection with browser-based WebRTC peers.
may close #1294
remaining drafts:
- [ ] SecureContext (replacing DTLS handshake?)
New public APIs:
X_ICEForceTCPonRTCConfigurationofboolX_ICERelayProtocolonRTCIceServerofRTCIceProtocol
Dev notes:
IceServerclass additional_secondaryRelayUrifor TURN-TCP
refs:
Hi @sipsorcery ,
I did a whole PR rebase and merged with v8.0.12 https://github.com/sipsorcery-org/sipsorcery/commit/bdbb80fde8b3d1362cb2a4b820af8b9f3d2dc26b.
After reading for quite a while, I'm stuck on the DTLS handshake part. What I found is that the networking part of the library is quite low-level. Once it hits the DTLS handshake as a server, it disconnects the TCP Socket.
I'm guessing it has something to do with context switching and threading and the such, it will need more than enough time to figure out what to do, so what I'd like to know is:
- What did you have in mind on this matter?
- Do you mind if I try to add a separate codebase for TCP implementation?
That said, both still require a lot of time with the legend Stephen's blog on C# .NET async stuff and sockets. So I might close the PR or just leave it as is until that time comes around. There is so much potential with this library.
Thanks,
@ha-ves it takes a bit of mental gymnastics to work out how TCP TURN is meant to work for WebRTC. I think this statement from the Transports for WebRTC best explains it:
If TCP connections are used, RTP framing according to [RFC4571] MUST be used for all packets. This includes the RTP packets, DTLS packets used to carry data channels, and STUN connectivity check packets.
So it seems that once the TCP TURN connection is established all packets need to be sent in an RTP packet. This includes the DTLS packets, STUN checks and SCTP (data channel packets).
In theory it shouldn't be too difficult to manage the RTP framing given all the packet formats are already supported in this library. I suspect the hardest bit will be managing the TCP connections, particularly edge cases around dropping, re-connecting etc. I always found the TCP/TLS connection management problematic with the SIP transport purely because there is so much more state required to manage timeouts etc. etc. See the SIPTCPChannel class header for lots of gory details.
In theory to implement the TCP TURN mechanism what's required is a new implementation of the RTPChannel class that uses a TCP socket instead of the current UDP socket. The RTP framing mechanism could then be completely handled in the RTPTCPChannel. I'd classify it as a medium sized task where the SCTP protocol implementation was a big task (took me 6-7 weeks of full time effort).
Apart from that, if it is the case that as you say the support is not yet there in the browsers hard to see it being worth the effort...
@sipsorcery I see, I think I understand it now.
It does seem like there's not quite a way to just replace the network layer if in the end it'll need to be deriving the RTPChannel class.
Thanks, it's really helpful to know what you'd expect.
I'll port the current PR and see where it goes from there.
As for the browser peer, they don't support it, though RTP middlebox apps usually do support it, and as some people mentioned, their case wants TCP-only connection with the middlebox.
And I think especially in industrial areas they only use TCP because they need the connection state. In such cases they usually don't traverse the uncontrollable network called The Internet so it'll make the PR start in a more ideal conditions.
@ha-ves Hello, in my project, I want to use TCP for communication between TURN and WebRTC. I noticed that ICE specifies TCP by setting "transport=tcp". I would like to ask what the mechanism of this is? And if I want to use TCP for communication, what steps should I take? thank you!
@Forever-OnLine
I noticed that ICE specifies TCP by setting "transport=tcp".
That parameter only controls the connection with the relay server, not the resulting ICE candidate. I believe TCP with a relay server is already implemented in this library.
I would like to ask what the mechanism of this is? And if I want to use TCP for communication, what steps should I take?
This PR enables that, but is still stuck on the DTLS part and no direct TCP-TCP yet.
ChatGPT:
How to use TCP with this library
- Ensure your TURN server supports TCP relaying (RFC 6062). With coturn, do not set
no-tcporno-tcp-relay; expose TCP port (e.g., 3478) and, if needed, TLS (5349). - Configure ICE servers to use TCP when talking to TURN and allow TCP relayed candidates.
var pc = new RTCPeerConnection(new()
{
iceServers =
[
new()
{
urls = "turn:turn.example.com:3478?transport=tcp",
username = "user",
credential = "pass",
credentialType = RTCIceCredentialType.password,
X_ICERelayProtocol = RTCIceProtocol.tcp
},
],
iceTransportPolicy = RTCIceTransportPolicy.relay,
//X_ICEForceTCP = true
});
Notes
- RFC 6062 (TURN-TCP) is different from RFC 6544 (ICE-TCP host/srflx over TCP). This change is about TURN relayed TCP, not advertising host TCP candidates.
- Browser JS usually doesn’t expose ICE-TCP candidates; many stacks use TURN over TCP to reach the server but still relay UDP for media. TURN-TCP is most useful for native/interop scenarios.
- In TCP mode the agent handles TURN permissions first, then Connect/ConnectionBind, and only then proceeds with the connectivity checks over the established relay.