ICE (RFC 5245) stands for interactive connectivity establishment. It is a standard that allows the local addresses, external addresses, and relay addresses (collectively known as candidates) to be exchanged with a remote endpoint and ultimately tested for viable communication with the endpoint. Once exchanged STUN is used as the protocol to test whether the address is reachable and whether two-way connectivity can be achieved. Once all potential candidates are tested a final choice is selected from the viable options and used for communication.
STUN (RFC 5389) stands for session traversal utilities for NAT. It is a standard that allows the type of NAT an endpoint is behind to be determined and ultimately the visible external address information to be retrieved.
TURN (RFC 5766) stands for traversal using relays behind NAT. It is a standard for managing (allocating, using, and destroying) a relay session on a remote external server that can be used to communicate with an endpoint behind a NAT. As this naturally introduces delay it is usually a last choice option when all others have failed.
An optional interface has been defined as an add-on to the RTP engine API which provides the ability to set candidate information, get candidate information, and start ICE negotiation. If this is not present the user of the RTP engine API should not use ICE at all.
Support for the optional ICE interface has been added to res_rtp_asterisk using the pjnath library from pjproject.
When an RTP instance is allocated within res_rtp_asterisk all possible ICE candidates are determined and a TURN relay session allocated if present. Queries for local candidates return a list of these which is placed into the SDP. If remote SDP is parsed and ICE candidates present these are passed into res_rtp_asterisk which stores them until ICE negotiation should occur. After all ICE candidates are parsed negotiation and connectivity checks begin.
ICE support uses the ICE session API and has been added into the set of operations for sending and receiving packets. This incurs little performance penalty. When receiving a packet it is initially passed to the ICE session API if a session is present. If the packet is a STUN message it is handled internally by the ICE session and ignored by res_rtp_asterisk. If it is not a STUN message it is passed through and handled normally. When sending a packet if an ICE session is present it is passed to the ICE session API which determines the actual address and transport to use to send the packet. The transport is used and the packet sent to this address.
TURN support uses the TURN socket API and is more expensive to use. When the ICE session determines that the TURN session should be used the packet is passed to the TURN socket API with the address it should be sent to. For receiving though... it is not possible to easily integrate more transports so the TURN support internally relays received traffic to the normal RTP socket. As TURN support should not be commonly used I felt this was an acceptable option.
By default ICE support is enabled in res_rtp_asterisk. It can be explicitly disabled by setting icesupport to no in the rtp.conf configuration file.
The rtp.conf configuration file also now contains settings for a STUN server and TURN server. If these settings are not set support for the respective item is disable.
If enabled attributes like the following are added to the SDP which contain the ICE candidates, username, and password.