The example diagrams below try to present how to use NUA API with different SIP use cases.
The SIP following event diagram shows a pretty simple, succesful call case. The nua events and nua function calls are show in the diagram below as well as the SIP messages.
The call setup above assumes parameters NUTAG_AUTOALERT(0), NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side.
Alice Proxy Bob 0 | | | 1 nua_handle() | | | 2 nua_invite() -> |-----INVITE---->| | 3 nua_i_state <- | | | 4 | |-----INVITE---->| -> nua_i_invite 5 |<--100 Trying---| | -> nua_i_state 6 | | | 7 | | | 8 | | | 9 | |<--180 Ringing--| <- nua_respond(180) 10 nua_i_invite <- |<--180 Ringing--| | -> nua_i_state 11 nua_i_state <- | | | 12 | |<--200 OK-------| <- nua_respond(200) 13 nua_i_invite <- |<---200 OK------| | -> nua_i_state 14 nua_i_state <- | | | 15 nua_ack() -> |-----ACK------->| | 16 nua_i_state <- | |-----ACK------->| -> nua_i_ack 17 | | | -> nua_i_state 18 | | | 19 <<====== SIP Session Established =======>> 20 | | | 21 | | | 22 nua_bye() -> |-----BYE------->| | 23 | |-----BYE------->| -> nua_i_bye 24 | |<----200 OK-----| -> nua_i_state 25 nua_r_bye <- |<---200 OK------| | 26 nua_i_state <- | | | | | |
The media (audio, video) can be put on hold. In SIP system this means that application can indicate to the remote end that it is engaged in other activity (another call, for instance) and does not wish to receive media from the remove end.
The call hold is usully implemented using re-INVITE. Re-INVITE is an INVITE request sent on existing SIP session. Both original caller and callee can send re-INVITEs. The main use of re-INVITE is modifying sessions: adding media lines to the session, changing codecs on existing media, and, as you might expect, putting existing media on hold as well as resuming media from hold.
A re-INVITE is sent by calling nua_invite() on handle with existing call. When putting call on hold, the application can include SOATAG_HOLD("audio") or SOATAG_HOLD("video") or SOATAG_HOLD("audio, video") or SOATAG_HOLD("*") as parameters to re-INVITE nua_invite(). (Note that last SOATAG_HOLD() in the tag list will override the SOATAG_HOLD() tags before it.)
Another feature where nua tries to be helpful is autoanswer and auto-ACK on existing sessions: the re-INVITE is automatically responded with 200 OK and ACK is automatically sent. (If the application wants to respond and ACK by itself, it should explicitly set NUTAG_AUTOANSWER(0) and/or NUTAG_AUTOACK(0) in the handle; either include them in nua_invite() or nua_respond() parameters or call nua_set_hparams() explicitly.
Alice Proxy Bob 0 nua_handle() | | | 1 | | | 2 nua_invite() -> |-----INVITE---->| | 3 nua_i_state <- | | | 4 | |-----INVITE---->| -> nua_i_invite 5 |<--100 Trying---| | -> nua_i_state 6 | | | 7 | | | 8 | | | 9 | |<--180 Ringing--| <- nua_respond(180) 10 nua_i_invite <- |<--180 Ringing--| | -> nua_i_state 11 nua_i_state <- | | | 12 | |<--200 OK-------| <- nua_respond(200) 13 nua_i_invite <- |<---200 OK------| | -> nua_i_state 14 nua_i_state <- | | | 15 nua_ack() -> |-----ACK------->| | 16 nua_i_state <- | |-----ACK------->| -> nua_i_ack 17 | | | -> nua_i_state 18 | | | 19 <<== Bi-Directional RTP Established ==>> 20 | | | 21 | | | 22 | |<--INVITE(hold)-| <- nua_invite(.. 21 | | | NUTAG_HOLD("*")..) 23 nua_i_invite <- |<-INVITE(hold)--| | -> nua_i_state 25 nua_i_state <- |----200 OK----->| | 26 | |----200 OK----->| -> nua_i_invite 28 | |<-----ACK-------| -> nua_i_state 29 nua_i_ack <- |<----ACK--------| | 24 | | | 30 <<== Uni-Directional RTP Established ==>> 24 | | | 31 | | | 32 | |<--INVITE-------| <- nua_invite(.. 21 | | | NUTAG_HOLD(NULL)..) 33 nua_i_invite <- |<--INVITE-------| | -> nua_i_state 35 nua_i_state <- |---200 OK------>| | 36 | |---200 OK------>| -> nua_i_invite 38 | |<----ACK--------| -> nua_i_state 39 nua_i_ack <- |<----ACK--------| | 40 nua_i_state <- | | | 19 <<== Bi-Directional RTP Established ==>> 42 | | | 43 nua_bye() -> |-----BYE------->| | 44 nua_i_state <- | |-----BYE------->| -> nua_i_bye 46 | |<----200 OK-----| -> nua_i_state 47 |<---200 OK------| | | | |
This is the unattended call transfer case.
1st MSC showing Alice's end:
Alice Bob Carol 0 | | | 1 nua_i_invite <- |<-----INVITE--------| | 2 nua_i_state <- | | | 2 | | | 3 nua_respond(180) -> |----180 Ringing---->| | 2 nua_i_state <- | | | 4 | | | 5 nua_respond(200) -> |------200 OK------->| | 6 nua_i_state <- | | | 8 | | | 7 nua_i_ack <- |<-------ACK---------| | 8 nua_i_state <- | | | 9 |<========RTP=======>| | 10 | | | 11 << Alice performs unattended transfer >> | 12 | | | 13 | | | 14 nua_refer() -> |---REFER("r: C")--->| | 15 | | | 16 nua_r_refer <- |<---202 Accepted----| | 17 | | | 18 nua_i_notify <- |<-----NOTIFY--------| | 19 | | | 20 |------200 OK------->| | 21 | |---INVITE("b: A")-->| 23 | | | 22 nua_bye() -> |-------BYE--------->| | 23 | | | 24 nua_r_bye <- |<----200 OK---------| | 25 nua_i_state <- | No RTP Session | | 28 | |<----180 Ringing----| 26 nua_i_notify <- |<- - -NOTIFY - - - -| | 27 | | | 20 |- - - 200 OK- - - ->| | 29 | | | 30 | |<------200 OK-------| 31 | | | 32 | |---------ACK------->| 33 | | RTP | 34 | |<==================>| 35 | | | 36 |<-----NOTIFY--------| | 37 | | | 38 |------200 OK------->| | | | |
2nd MSC showing Bobs's end:
Alice Bob (nh1) Bob (nh2) Carol 0 | | | | 1 |<-----INVITE--------| | | 2 | | | | 3 |---180 Ringing----->| | | 4 | | | | 5 |------200 OK------->| | | 6 | | | | 7 |<-------ACK---------| | | 8 | RTP | | | 9 |<==================>| | | 10 | | | | 11<< Alice performs unattended transfer >> | | 12 | | | | 13 | Refer-To:C F5| | | 14 |-REFER------------->| -> nua_i_refer | | 15 | | | | 16 |<-202 Accepted------| | | 17 | | | | 18 |<-----NOTIFY--------| | | 19 | | | | 20 |------200 OK------->| -> nua_r_notify | | 21 | | | | 22 |-------BYE--------->| -> nua_i_bye | | 23 | | -> nua_i_state | | 24 |<----200 OK---------| nua_handle() -> | | 25 | No RTP Session | nua_invite() -> | | 26 | | |--INVITE("b: A")--->| 27 | | | | 28 | | nua_i_invite <- |<--180 Ringing------| 29 | | nua_i_state <- | | 30 | | nua_i_invite <- |<----200 OK---------| 31 | | nua_i_state <- | | 32 | | nua_ack -> |-------ACK--------->| 33 | | | | 34 | | |<=======RTP========>| 35 | | | | 36 |<-----NOTIFY--------| | | 37 | | 38 |------200 OK------->| -> nua_r_notify 39 | | <- nua_handle_destroy | |
Bob includes nh1 in nua_invite()/25 as NUTAG_NOTIFY_REFER() parameter.
Open Issue 1:
The 3GPP call model is defined in 3GPP TS 24.229. In order to select only a single codec and ensure that the QoS reservationa are made before the call is alerting, the 3GPP call model employs multiple offer/answer exchanges. It uses 100rel and PRACK (RFC 3262), UPDATE (RFC 3311) and preconditions (RFC 3312) extensions specified by IETF.
The call setup below assumes parameters NUTAG_AUTOALERT(0), NUTAG_AUTOANSWER(0) on B side, NUTAG_AUTOACK(0) on A side.
A B 0 nua_handle() | | 1 nua_invite() -> | | 2 nua_i_state <- |----INVITE (offer)---->| 3 | | -> nua_i_invite 4 | | -> nua_i_state 5 | | 6 | | <- nua_respond(183) 7 nua_i_invite <- |<----183 (answer)------| -> nua_i_state 8 nua_i_state <- | | 9 << single codec is selected now >> 10 |-----PRACK(offer2)---->| -> nua_i_prack 11 | | -> nua_i_state 12 nua_r_prack <- |<--200/PRACK(answer2)--| 13 | | 14 | | 15 << resource reservations are done now >> 16 | | 17 nua_update() -> |----UPDATE (offer3)--->| 18 nua_i_state <- | | 19 nua_i_state <- |<-200/UPDATE (answer3)-| -> nua_i_update 20 | | -> nua_i_state 21 | | 22 | | << B rings >> 23 | | 24 | | <- nua_respond(180) 25 nua_i_invite <- |<---------180----------| 26 nua_i_state <- | | 27 |--------PRACK--------->| -> nua_i_prack 28 nua_r_prack <- |<-----200/PRACK------->| -> nua_i_state 29 | | 30 | | <- nua_respond(200) 31 nua_i_invite <- |<---------200----------| -> nua_i_state 32 nua_i_state <- | | 33 nua_ack() -> | | 34 nua_i_state <- |----------ACK--------->| -> nua_i_ack 35 | | -> nua_i_state | |