Thursday, October 21, 2010

Can we bypass Asterisk for RTP session?

Yesterday I had a discussion with my friends if "we could bypass Asterisk during the media session(RTP) once the signalling(SIP) is complete" which lead to the compilation of this disaster. By the way, the answer is YES we can.

I came across this nice explanation to the whole scenario and am copying it here so that when i show you the snapshots of some traces, it would be easier for us to understand.

######################################################
Source :
http://voip-info.info/wiki/view/Asterisk+sip+canreinvite
######################################################

Firstly, you need to understand how SIP itself was designed to set up calls between handsets.

The SIP 'INVITE' message says "I want to set up a call". In the body of this message is a block of SDP (Session Description Protocol) which says "my audio endpoint is IP x.x.x.x port x, and I can use codecs A, B and C".

In the intended architecture of SIP, the INVITE is forwarded via a series of proxies until it reaches the requested destination. The remote end responds with a 200 saying "OK, my audio stream is on IP y.y.y.y port y, and I choose codec B", which is sent back to the first phone. At this point, the first phone starts sending RTP audio packets from x.x.x.x:x to y.y.y.y:y, and the second phone sends them from y.y.y.y:y to x.x.x.x:x. That is, the audio path is direct, whereas the SIP messages went via intervening proxies.

[This is horrendously over-simplified, but it's enough to make the point]

Now, the second thing to understand is that Asterisk is not a SIP proxy, and its default behaviour is to set up the two legs as two separate audio streams: phone X to Asterisk and Asterisk to phone Y. The way this works is:

• Phone sends INVITE saying "I am on IP x.x.x.x:x, I can use codecs A,B,C"
• Asterisk decides where the next leg is. If it is another SIP device, it sends a fresh SIP INVITE (with a different Call-Id) to the second phone saying "I am on IP z.z.z.z:z1, I can use codecs C and D" where z.z.z.z is Asterisk's own IP address and :z1 is a port it has chosen.
• This arrives at the second phone, which says "OK, I am on IP y.y.y.y:y, I choose codec C", and sends it back to Asterisk
• Asterisk is happy, so it completes the first leg by replying to the first phone "OK, I am on IP z.z.z.z:z2, I choose codec C"

So now the first phone is sending packets between x.x.x.x:x and z.z.z.z:z2, and the second phone is sending packets between y.y.y.y:y and z.z.z.z:z1

This means that Asterisk is in the media path - each RTP packet has to be received and resent, in both directions. On the minus side, this means more workload on the Asterisk server. On the plus side, being in the media stream means that Asterisk can perform a whole bunch of useful voice services - recording, conferencing, call parking, music on hold, even codec conversion (i.e. the stream from phone X to Asterisk can be using one codec, and phone Y to Asterisk a different one)

With me so far?

The third thing to realize is that Asterisk can optimize this out so that the media path is set up directly between the endpoints. This is what it means by "
native bridging" -
connecting two compatible endpoints directly together, instead of relaying the audio via Asterisk.

So, under the right conditions, the SIP message Asterisk sends to the second phone will contain the IP address of the first phone, and vice versa. This means it looks and smells almost like a SIP proxy. Look at the headers below to find out which information is actually changed from a normal invite to a reinvite.


Note: Asterisk is still really not a SIP proxy in this case. The two legs have different Call-Ids, and so are different SIP calls. However the SDP descriptors for the audio of the two calls point directly at each other. You can see this in the sample trace below.


This does not work in certain conditions:
1) Both SIP channels must be marked "canreinvite=yes". If either has "canreinvite=no", then Asterisk falls back to the default behaviour of setting up two separate legs.
2) If one of the UAs is behind a NAT and the other is on a public IP, this will not work. i.e, If the SIP messages try to setup a direct RTP session between the 2 UAs, it wouldn’t work because the UA on the public IP cannot send an RTP packet directly to a Private IP( it will not be able to route it).


The last thing, which took me a while to figure out, is why the option which means "I prefer to use a direct RTP media path" is called "canreinvite=yes".

Even if the normal audio path for a call can be set up with native bridging, Asterisk sometimes needs to be able to re-insert itself into the media path in the middle of a call - to provide services such as music on hold, transfer, parking and so on when they are requested.

The SIP mechanism for this is called re-INVITE. Two phones which are happily talking to each other can have the media stream changed mid-call using this mechanism, so Asterisk can unstitch the direct link and re-connect the two legs to itself.

If you set
canreinvite=no on a SIP channel, it's saying "this phone doesn't support the re-INVITE mechanism for reconnecting the audio mid-call". Asterisk therefore decides that it must insert itself into the media stream for the whole duration of the call, so that it is already there if later on one of the parties requests one of these in-call features.

####################################################################

Bottom line,
* if we allow Asterisk to send reinvites(
canreinvite=yes), it will happily move out of the scene after signalling. 


Sample headers of an actual invite and a reinvite from Asterisk ----> UA2.

Actual Invite :
Request: INVITE sip:UA2@y.y.y.y:56424;rinstance=49da86dfb1f6970a, with session description



Internet Protocol, Src:z.z.z.z, Dst: y.y.y.y
User Datagram Protocol, Src Port: sip (5060), Dst Port: 56424 (56424)
Session Initiation Protocol
Request-Line: INVITE sip:UA2@y.y.y.y:56424;rinstance=49da86dfb1f6970a SIP/2.0
Message Header
Message Body
Session Description Protocol
Session Name (s): Asterisk PBX 1.6.1.20
Connection Information (c): IN IP4 z.z.z.z
Time Description, active time (t): 0 0
Media Description, name and address (m): audio 17354 RTP/AVP 0 3 101

Reinvite :
Request: INVITE sip:UA2@y.y.y.y:57717;rinstance=49da86dfb1f6970a, with session description



Internet Protocol, Src: z.z.z.z, Dst: y.y.y.y
User Datagram Protocol, Src Port: sip (5060), Dst Port: 56424 (56424)
Session Initiation Protocol
Request-Line: INVITE sip:UA2@y.y.y.y:57717;rinstance=49da86dfb1f6970a SIP/2.0
Message Header
Message Body
Session Description Protocol
Session Description Protocol Version (v): 0
Session Name (s): Asterisk PBX 1.6.1.20
Connection Information (c): IN IP4 x.x.x.x
Time Description, active time (t): 0 0
Media Description, name and address (m): audio 15094 RTP/AVP 0 3 101

The connection information suggests that in the reinvite sent by asterisk, it is telling UA2 that the audio should be sent directly to x.x.x.x:15094.

The more interesting option is newer — "directrtpsetup=yes" in sip.conf. This will cause Asterisk to behave more like a proxy does with respect to media and simply pass the SDP payloads as received to both endpoints without pivoting the media stream toward itself at any time, unless explicitly forced to do so (i.e. generating music on hold or IVR messages). 


NOTE: I have compiled this blog only to consolidate relevant things at one place so that I can refer to it in future. This has a lot of data pulled in from different sites. Hope it helps.

--SM

3 comments:

  1. great work! thanks for putting all this together..I am trying to use asterisk/a2billing for wholesale termination purpose and was thinking if we can bypass media! great help.

    ReplyDelete
  2. i am still not able to establish RTP between peers. I checked in wireshark. RTP is bw phone 1 to Astrisk and Astrisk to Phone 2.
    I did the config:
    canreinvite = yes
    Nat = no

    but no luck.

    ReplyDelete