Skip to content

Add RFC 6062 TURN TCP relay support (server + client)#1532

Open
CraziestPower wants to merge 4 commits intosipsorcery-org:masterfrom
CraziestPower:feature/rfc6062-turn-tcp
Open

Add RFC 6062 TURN TCP relay support (server + client)#1532
CraziestPower wants to merge 4 commits intosipsorcery-org:masterfrom
CraziestPower:feature/rfc6062-turn-tcp

Conversation

@CraziestPower
Copy link
Copy Markdown
Contributor

@CraziestPower CraziestPower commented Feb 21, 2026

Summary

  • Extends the lightweight in-process TurnServer (Add lightweight in-process TURN relay server (RFC 5766) #1513) with RFC 6062 TCP relay support
  • Adds client-side ICE stack support for requesting and using TCP relay candidates
  • Fixes STUN message type parsing for RFC 6062 message types
  • 15 new tests including end-to-end TCP relay with TLS encryption

Server-side (TurnServer)

  • Allocate with RequestedTransport=TCP (0x06) creates a TCP relay listener
  • Connect (0x000a): opens TCP connection to peer, returns ConnectionId
  • ConnectionBind (0x000b): pairs a client data connection with a peer connection, starts bidirectional raw byte relay
  • ConnectionAttemptIndication (0x001c): sent to client when a peer connects to the TCP relay listener
  • Unsupported transport protocol returns error 442

Client-side (ICE)

  • RTCIceServer.X_ICERelayProtocol configuration option to request TCP relay
  • IceServer.IceRelayProtocol property wired through IceServerResolver
  • IceChecklistEntry TCP relay state machine (Connect → ConnectionBind → raw data)
  • RtpIceChannel TCP relay send/receive paths
  • IceTcpReceiver.RawMode for post-ConnectionBind raw byte passthrough

STUN layer

  • Add ConnectSuccessResponse, ConnectErrorResponse, ConnectionBindSuccessResponse, ConnectionBindErrorResponse, ConnectionAttemptIndication enum values
  • Fix GetSTUNMessageTypeForId crash on unknown message type IDs (now returns 0 instead of throwing)

Tests (15 new)

Test What it covers
GetSTUNMessageTypeForId_UnknownValue_ReturnsZero STUN parsing fix
GetSTUNMessageTypeForId_ConnectSuccessResponse_ReturnsCorrectEnum New enum values
TcpAllocateSucceeds TCP relay allocation
ConnectWithoutAllocationReturns437 Error path
ConnectToPeerSucceeds Full Connect flow
ConnectionBindPairsDataConnection ConnectionBind pairing
RawDataRelaysAfterConnectionBind Raw bidirectional relay
ConnectionAttemptIndicationSentOnPeerConnect Peer-initiated flow
AllocateUnsupportedTransportReturns442 Error path
ChecklistEntryHandlesConnectSuccess Client state machine
ChecklistEntryHandlesConnectionBindSuccess Client state machine
TcpRelayEndToEnd_ClientInitiatedConnect Full e2e with 5 round-trips
TcpRelayEndToEnd_PeerInitiatedConnect Full e2e peer-initiated flow
TcpRelayEndToEnd_LargePayload 64 KB transfer both directions
TcpRelayEndToEnd_WithTls TLS handshake + encrypted data over relay

Acknowledgements

Client-side ICE-TCP/TURN-TCP work is based on @ha-ves's draft PR #1362. Thank you for the foundational work on the client-side RFC 6062 implementation.

References

Fixes #1531. Fixes #1294. Related: #1362.

🤖 Generated with Claude Code

CraziestPower and others added 4 commits February 21, 2026 16:13
Extends the lightweight TurnServer with RFC 6062 TCP relay:
- Allocate with RequestedTransport=TCP creates a TCP relay listener
- Connect (0x000a): server opens TCP to peer, returns ConnectionId
- ConnectionBind (0x000b): pairs data connection with peer, starts
  bidirectional raw byte relay
- ConnectionAttemptIndication (0x001c): sent when peer connects to
  the relay listener
- Unsupported transport returns 442

Client-side ICE changes:
- IceServer.IceRelayProtocol and RTCIceServer.X_ICERelayProtocol
  configuration for requesting TCP relay
- IceChecklistEntry TCP relay state machine
- RtpIceChannel TCP relay send/receive paths
- IceTcpReceiver.RawMode for post-ConnectionBind passthrough

STUN layer:
- Add ConnectSuccessResponse, ConnectErrorResponse,
  ConnectionBindSuccessResponse, ConnectionBindErrorResponse,
  ConnectionAttemptIndication enum values
- Fix GetSTUNMessageTypeForId crash on unknown message type IDs

15 new tests including end-to-end TCP relay with TLS.

Fixes sipsorcery-org#1531.

Based on client-side work by @ha-ves (sipsorcery-org#1362).

Co-Authored-By: Haves Irfan <haves@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The self-signed certificate from CreateSelfSigned() needs to be
exported/reimported as PFX with Exportable flag for SslStream to
access the private key on Windows. Also increases handshake timeout
to 10s and adds diagnostic info on timeout failure.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The X509Certificate2(byte[], string, flags) constructor is obsolete
(SYSLIB0057) on .NET 10. Use X509CertificateLoader.LoadPkcs12 on
net10.0+ with a preprocessor guard.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
X509CertificateLoader was introduced in .NET 9 and the obsolete
X509Certificate2 constructor is an error on both net9 and net10.
Widen the preprocessor guard from NET10_0_OR_GREATER to
NET9_0_OR_GREATER.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@sipsorcery
Copy link
Copy Markdown
Member

Thanks for the PR. A code restructure has taken place and the source files for this PR are now in src/SIPSorcery. Can this PR be rebased?

1 similar comment
@sipsorcery
Copy link
Copy Markdown
Member

Thanks for the PR. A code restructure has taken place and the source files for this PR are now in src/SIPSorcery. Can this PR be rebased?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add RFC 6062 TURN TCP relay support to TurnServer and ICE client WebRTC TURN over TCP needs adjust

2 participants