Skip to main content
Pion ICE provides comprehensive support for TCP candidates in addition to UDP, enabling connectivity in network environments where UDP traffic is blocked or restricted. TCP support follows RFC 6544.

TCP Candidate Types

There are three types of TCP candidates, defined by the TCPType enum:
tcptype.go

Active TCP Candidates

Active TCP candidates initiate outbound connections to remote passive candidates. The activeTCPConn type handles connection establishment:
The ICE agent automatically ignores remote candidates with TCPTypeActive since they don’t accept inbound connections.

Passive TCP Candidates

Passive TCP candidates listen for incoming connections. They are the server-side counterpart to active candidates:
When a passive TCP candidate is added to a remote agent with active TCP support enabled (default), the agent automatically attempts to establish a connection:
agent.go

Simultaneous-Open (SO) Candidates

SO candidates can both initiate and accept connections, useful for NAT traversal scenarios where both peers attempt to connect simultaneously:

TCP Packet Framing

TCP is a stream-oriented protocol, so Pion ICE implements packet framing according to RFC 4571. Each packet is prefixed with a 2-byte length header:
The framing is handled automatically by readStreamingPacket and writeStreamingPacket functions:
tcp_mux.go

TCP Multiplexing

The tcpPacketConn type manages multiple TCP connections to different remote addresses, providing a packet-oriented interface over stream-based TCP:
tcp_packet_conn.go

Adding Connections

Connections are added dynamically as peers connect:
The TCP packet connection supports optional write buffering via bufferedConn to optimize small writes.

Configuration Parameters

Active TCP Connection Lifecycle

The activeTCPConn type manages outbound TCP connections with buffered I/O:
active_tcp.go

Connection Establishment

The RemoteAddr() method may return :0 before the connection completes. Check connection status before relying on the remote address.

When to Use TCP vs UDP

Use TCP Candidates When:

  • UDP is blocked: Corporate firewalls or restrictive networks
  • Reliable delivery needed: Application requires in-order, reliable delivery at the transport layer
  • Firewall traversal: TCP is more likely to traverse certain enterprise firewalls
  • Port restrictions: Only TCP ports are available

Use UDP Candidates When:

  • Low latency is critical: UDP has less overhead and no head-of-line blocking
  • Packet loss is acceptable: Real-time media can handle some loss
  • Network supports it: Most internet connections allow UDP
  • Best performance: UDP is preferred for WebRTC and real-time applications
Pion ICE can gather both TCP and UDP candidates simultaneously. The ICE agent will automatically select the best path based on connectivity checks and candidate pair priorities.

Configuration Example

Disabling Active TCP

If you want to prevent the agent from establishing outbound TCP connections:
With DisableActiveTCP: true, your agent will only gather passive and simultaneous-open TCP candidates, not active ones.

SDP Representation

TCP candidates are represented in SDP with the tcptype extension:

Reference

  • Active TCP: active_tcp.go:18 - activeTCPConn implementation
  • TCP Packet Conn: tcp_packet_conn.go:81 - tcpPacketConn multiplexer
  • TCP Types: tcptype.go:10 - TCPType enum definition
  • Streaming Packets: tcp_mux.go:436 - readStreamingPacket and writeStreamingPacket