« Previous - Version 29/61 (diff) - Next » - Current version
Adrian Georgescu, 02/18/2010 06:55 pm


= ICE negotiation through OpenSIPS/Mediaproxy =

Background

ICE negotiation is used to solve the NAT traversal issue of RTP media as much as possible in the SIP end-points. Where the topology does not allow, a TURN server has been standardized to provide end-points with a visible public presence that can be used to relay traffic to SIP end-points behind an unfriendly NAT type (e.g. symmetric). TURN servers are not widely deployed today whereas solutions like SIP Proxies in tandem with RTP relays are.

RTP relays that work in tandem with SIP Proxies perform similar function to the TURN protocol except that the reservation is done by the SIP Proxy rather than by the user agent. The SIP User Agent does not need to support TURN protocol in order to use the relay, which makes it compatible with any SIP User Agent available today. Such solution used widely today is the tandem OpenSIPS/MediaProxy.

MediaProxy module rewrites the SDP in order to present to the destination SIP User Agent a reachable IP:port number for sending RTP/RTCP. This has the dis-advantage that is always using a relay and is mutually exclusive with the use of ICE. The rewriting of the SDP and the missing candiate correspondent to the c= line of the SDP causes the target SIP end-point to reply with ICE missmatch and the ICE negotiation fails in its tracks.

Requirements for the implementor

To circumvent the failure of ICE negotiation, mediaproxy module must:

  • Create a proper candidate based on the media relay IP:port allocation
  • Append the candidate to the offer/answer of the SDP
  • Allow an administrator to set a policy about when to use of the relay candidate
  • Solve the accounting issues and BYE sending depending on the use of ICE
Implementation

Add new setting to mediaproxy module:

{{{
ice_priority_avp=$avp(s:ice_priority)
}}}

This module parameter defines which AVP should be used to set the ICE candidates priority. It can take 3 different values: "none", "low" or "high". None means no candidate will be added at all, and low or high affect on the priority field of the ICE candidate being inserted. Example:

{{{
route {
...
$avp(s:ice_priority) := "low";
...
}
}}}

For the initial INVITE and its reply append an ICE candidate to the SDP as follows:

{{{
if (ice_priority_avp != none and
SDP offer contains a=ice-pwd and a=ice-ufrag and a=candidate line(s) then
append to the SDP the following line:
a=candidate:R 1 UDP PRIORITY MP_IP MP_PORT typ relay
a=candidate:R 2 UDP PRIORITY MP_IP MP_RTCP_PORT typ relay
}}}

where

  • R (foundation) = we'll use 'R' to represent we are emulating a relayed candidate
  • PRIORITY = 2!^24 * POLICY + 2!^8 * 65535 + 2!^0 * 256 - Candidate ID (1 for RTP, 2 for RTCP) * POLICY = 0 if $avp(s:ice_priority) low and POLICY = 126 if $avp(s:ice_priority) high.

Once the ICE negotiation is completed and if the transport address for the IP selected for media differs from the default transport (what it was indicated in the c= line of the original INVITE), a re-INVITE initiated by the controlling (in the sense of ICE) agent indicates this fact. The re-INVITE contains the selected candidate in the c= line. If ICE negotiation succeeds MediaProxy should deallocate its ports and cancel subsequent actions related to the accounting and dialog terminating purposes. MediaProxy will decide that ICE negotiation succeeded for a stream if both SDP offer and answer have ICE support and if STUN binding requests (which correspond to ICE probing) have been detected. In that case MediaProxy will not continue to be in the middle of the call by any means.