http://sofia-sip.sourceforge.net/refdocs/soa/index.html,翻译自官网的这张网页。
模块信息
Sofia SIP soa模块是一个异步的SDP Offer/Answer引擎库。库的接口在<sofia-sip/soa.h>头文件中被定义。
-
联系人:
- Pekka Pessi < Pekka.Pessi@nokia-email.address.hidden>
-
状态:
- Sofia SIP Core library
-
许可:
- LGPL
使用soa引擎
SIP协议会使用SDP,以及一个被称为“SDP Offer-Answer Model”的协商过程用来建立多媒体会话。RFC 3264中规定了SDP Offer-Answer的协商具体细节。
soa引擎以面向对象方式实现。缺省的soa对象实现了基本的SDP协商和基本的SIP呼叫模型。更复杂的soa对象实现可以控制呼叫模型,并且可以代替应用程序执行初始化操作。
SDP Offer/Answer模型
Offer/Answer机制提供的基本功能包括
- 生成SDP offer (section 5)
- 处理SDP offer,生成SDP answer (section 6)
- 处理SDP answer (section 7)
- 修改会话session (section 8)
- 确定功能 (section 9)
offerer可以告知它有哪些能力:
- 它想建立的媒体流
- 它用来接收媒体流的传输地址(IP地址,断口号,传输协议)
- 特定媒体流相关的编码
- 编码参数(例如,H.263使用的编码配置)
answerer告知offer中的哪一部分是可以接受的:
- 它同意建立的媒体流
- 它用来接收媒体流的传输地址
- 特定媒体流的编码方式以及编码参数
能力指出生成SDP参与方可以接收哪些。他们可以发送对方可以接收的任何东西。
在会话描述中还可以包括加密秘钥等信息。
更高级能力也许需要包括两次或者更多轮次的负责协商。例如,RFC 3312中定义的会话前提条件扩展。另一个两阶段协商的例子在RFC 3264的10.2节,那展示了单个编码如何被选中。
SOA设计
为什么选择简单的接口?它是不是太简单了而没法在你的INVITE小时中包括SDP offer或者在200 OK消息中包括SDP answer。
我们的设计目标是让程序可以遵循简单的呼叫模型,即便底层非常复杂-早期会话、预设条件、会话计时器、第三方呼叫控制等。我们倾向于向没有经验的应用程序提供简单的接口,即便底层的呼叫遵循着3GPP选择的复杂的呼叫模型。
在SIP中使用SDP Offer/Answer
在SIP中使用SDP Offer/Answer是在RFC 3261,RFC 3262和RFC 3311中说明。
有一张列出很多包括SDP Offer/Answer的呼叫场景的页面,http://sofia-sip.sourceforge.net/refdocs/soa/soa_sdp_oa_use_cases.html。
发送offers的规则是:
- 可以在INVITE消息中发送offer
- 如果INVITE消息中没有offer,offer必须出现在第一个INVITE响应消息中
- offer可以出现在100rel (可靠的1XX系列响应消息)
- offer可以出现在PRACK消息中
- offer可以出现在UPDATE消息中
PRACK消息当未确认的100rel消息(可靠的1XX系列响应)收到后才可发送。UPDATE消息在早期对话或者已建立好的对话期间才可发送。
只能有一条INVITE请求可在对话期间被挂起。只能有一条非INVITE请求可在对话期间被挂起(在一个方向上):如果对应PRACK消息的最终响应消息没收到那么不可以发送UPDATE消息。
如果offer/answer协商过程还在进行中,可以不发送offer。下面两种情况说明Offer/answer协商过程还在继续:offer已发送但answer未收到;offer已收到但响应还未生成。
发送answer的规则:
- 当从INVITE消息中收到offer
- 在下一个端到端的1XX或2XX响应中可发送answer
- answer必须在一个可靠的响应中发送(100rel或2XX)
- 在2XX响应消息中收到了offer response
- 在ACK消息中必须发送answer
- 100rel响应消息中收到了offer
- 在PRACK消息中必须发送answer
- 在PRACK或UPDATE消息中收到了offer
- 必须在针对PRACK或UPDATE的2XX响应消息中发送answer
即便已经针对INVITE发送了2XX消息,在PRACK消息中的offer或answer也必须处理。
接收answer的规则:
- 如果INVITE消息中发送了offer,针对INVITE消息的任何非错误响应消息的第一个会话描述都被认定为是answer
- 如果2XX响应消息中发送了offer,ACK消息中的会话描述被认定为是answer
- 如果100rel响应消息中发送了offer,PRACK消息中的会话描述被认定为是answer
- 如果PRACK或UPDATE消息中发送了offer,2XX响应消息中的会话描述被认定为是answer
终端必须忽略SDP的规则、条件:
- 如果INVITE消息中发送了offer,针对INVITE消息的任何非错误响应消息的第一个会话描述都必须处理,其他的忽略
- 如果2XX响应消息中没有发送offer,忽略ACK消息中的SDP
- 如果PRACK消息中没有发送offer,忽略针对它的响应消息中的SDP
- 如果UPATE消息中没有发送offer,忽略针对它的响应消息中的SDP
发送re-INVITE和UPDATE消息有两个目的:更新或修改SIP状态,或者更新或修改相关的会话。会话定时器扩展(还未形成RFC)是第一个目的的例子。将一个Call置成保持,或者为一个语音会话增加视频功能是第二个目的的例子。因此,针对收到的re-INVITE消息必须做一些事情。应用程序可以只是携带着之前的SDP返回200 OK消息,有时必须指出Call已处于保持状态,有时会向使用人员询问授权(增加视频)。
解决冲突的规则(两个对端试图同时发送offer):
- 当UAS已生成offer又收到了一个offer,必须拒绝那个收到的offer(返回SIP 49响应消息)。
SOA以及SDP Offer/Answer场景
注意由于空间限制因素
- soa_set_params()
被称为set_params
- soa_set_remote_sdp()被称为
set_remote
- soa_generate_offer()紧跟soa_get_session_sdp()之后的被称为
gen_offer
- soa_generate_answer()紧跟soa_get_session_sdp()之后的被称为
gen_answer
- soa_process_answer()被称为
proc_answer
Basic Call Out
这是一个基本的外呼呼叫模型。
APPL NUA SOA REMOTE | | | | 0 | | | | 1 |----INVITE---->| | | 2 | |--set_params-->| | 3 | |---gen_offer-->| | 4 | | | | 5 | |-------------------INVITE(sdp offer)-->| 6 | | | | 7 | | | | 8 | | | | 9 | |< - - - - - - - - - - 180 Ringing - - -| 10 |< - - 180 - - -| | | 11 | | | | 12 | |<-------------------200(sdp answer)----| 13 | |--set_remote-->| | 14 | |--proc_answer->| | 15 |<-----200------| | | 16 | | | | 17 | |----activate-->| | 18 |<----active----| | | 19 | |-------------------------ACK---------->| 20 | | | | 21 | | | | 22 | | | | | | | |
Basic Call In
这是一个基本的呼入呼叫模型。
APPL NUA SOA REMOTE | | | | 0 | | | | 1 | |<------------------INVITE(sdp offer)---| 2 | | | | 3 | |--set_remote-->| | 4 | | | | 5 |<---INVITE-----| | | 6 | | | | 7 | | | | 8 |- - -180- - - >| | | 9 | |- - - - - - - - - - 180 Ringing - - - >| 10 | | | | 11 | | | | 12 |-----200------>| | | 13 | |--set_params-->| | 14 | | | | 15 | |--gen_answer-->| | 16 | | | | 17 |<----active----| | | 18 | |----activate-->| | 19 | |--------------------200 (sdp answer)-->| 20 | | | | 21 | | | | 22 | |<------------------------ACK-----------| 23 |<-----ACK------| | | 24 | | | | | | | |
3rd Party Call In
第三方呼叫模型只是反转下呼叫方和被叫方的Offer/Answer角色。
t APPL NUA SOA REMOTE | | | | 0 | | | | 1 | |<----------------------INVITE----------| 2 | | | | 3 |<---INVITE-----| | | 4 | | | | 5 | | | | 6 | | | | 7 |----200 OK---->| | | 8 | |--set_params-->| | 9 | | | | 10 | |--gen_offer--->| | 11 | | | | 12 | | | | 13 | |----------------------200 (off) ------>| 14 | | | | 15 | | | | 16 | |<---------------------ACK (ans)--------| 17 | |--set_remote-->| | 18 | |--proc_answer->| | 19 |<----ACK-------| | | 20 |<----active----| | | 21 | |----activate-->| | 22 | | | | | | | |
Callout with Early Media
在呼叫建立完成前构建起媒体会话是可能的。在这种情况下,180 Ringing消息中会携带SDP Answer。但在200 OK消息中还是会携带同样一份SDP Answer,因为180 Ringing消息是不需要回复确认消息的、它是有可能丢失的。
如果Ringing消息丢失了,就变成了上面所述的基本呼叫模型,这样终端就有多个机会来构建媒体会话。
t APPL NUA SOA REMOTE | | | | 0 | | | | 1 |----INVITE---->| | | 2 | |--set_params-->| | 3 | | | | 4 | |--gen_offer--->| | 5 | | | | 6 | | | | 7 | |-------------------INVITE(sdp offer)-->| 8 | | | | 9 | | | | 10 | | | | 11 | |<-------------------180(sdp answer)----| 12 | |--set_remote-->| | 13 |<-----180------|--proc_answer->| | 14 | | | | 15 | | | | 16 | | | | 17 | |<-----------------200(copy of answer)--| 18 | (copy is ignored) | | 19 | | | | 20 |<-----200------| | | 21 | |----activate-->| | 22 |<----active----| | | 23 | |-------------------------ACK---------->| 24 | | | | | | | |
Call In Establishing Early Media
与上一场景一致,只不过两个场景就像是在镜子里互相看自己:
t APPL NUA SOA REMOTE | | | | 0 | | | | 1 | |<------------------INVITE(sdp offer)---| 2 | |--set_remote-->| | 3 |<---INVITE-----| | | 4 | | | | 5 | | | | 6 |---180 Ring--->| | | 7 | |--set_params-->| | 8 | |--gen_offer--->| | 9 | | (Note 1) | 10 | | | | 11 | |-------------------180 (sdp answer)--->| 12 | | | | 13 | | | | 14 | | | | 15 |----200 OK---->| | | 16 | |--set_params-->| | 17 | | | | 18 | | | | 19 | |-----------------200 (copy of answer)->| 20 | |----activate-->| | 21 |<----active----| | | 22 | |<------------------------ACK-----------| 23 |<-----ACK------| | | 24 | | | | | | | |
注1: 被叫方发送振铃音给呼叫方,被叫方将忽略呼叫方法送的媒体数据直到通话真正建立(向呼叫方法送了200 OK消息)。
Call Out with PRACK
这里展示的是呼叫建立完成前第二种构建媒体会话的机会。在这个场景下,180 Ringing消息会包含SDP Answer。180 Ringing消息被可靠传送,即它被一个PRACK消息确认。
t APPL NUA SOA REMOTE | | | | 0 | | | | 1 |----INVITE---->| | | 2 | |--set_params-->| | 3 | | | | 4 | |--gen_offer--->| | 5 | | | | 6 | | | | 7 | |-------------------INVITE(sdp offer)-->| 8 | | | | 9 | | | | 10 | |<-------------------183(sdp answer)----| 11 | |--set_remote-->| | 12 | |--proc_answer->| | 13 |<-----183------| | | 14 | | | | 15 | |-----------------------PRACK---------->| 16 | |<--------------------200/PRACK---------| 17 |<--200/PRACK---| | | 18 | | | | 19 | | | | 20 | |<--------------------180 Ringing-------| 21 |<-----180------| | | 22 | |-----------------------PRACK---------->| 23 | |<--------------------200/PRACK---------| 24 |<--200/PRACK---| | | 25 | | | | 26 | | | | 27 | |<----------------------200 OK----------| 28 |<--200/INVITE--| | | 29 | |----activate-->| | 30 |<----active----| | | 31 | |-----------------------ACK------------>| 32 | | | | | | | |
Call In with PRACK
与上一场景一致,只不过两个场景就像是在镜子里互相看自己:
t APPL NUA SOA REMOTE | | | | 0 | | | | 1 | |<------------------INVITE(sdp offer)---| 2 | |--set_remote-->| | 3 |<---INVITE-----| | | 4 | | | | 5 | | | | 6 |-183 Progress->| | | 7 | |--set_params-->| | 8 | |--gen_answer-->| | 9 | | | | 10 | |-------------------183 (sdp answer)--->| 11 | | | | 12 | |<----------------------PRACK-----------| 13 |<----PRACK-----| | | 14 | |---------------------200/PRACK-------->| 15 | | | | 16 |--180 Ringing->| | | 17 | |---------------------180 Ringing------>| 18 | | | | 19 | |<----------------------PRACK-----------| 20 |<----PRACK-----| | | 21 | |---------------------200/PRACK-------->| 22 | | | | 23 | | | | 24 | | | | 25 |----200 OK---->| | | 26 | |----activate-->| | 27 |<----active----| | | 28 | |---------------------200/INVITE------->| 29 | | | | 30 | |<-----------------------ACK------------| 31 |<-----ACK------| | | 32 | | | | | | | |
注 1:the被叫方发送振铃音给呼叫方,被叫方将忽略呼叫方法送的媒体数据直到通话真正建立在时序26步(向呼叫方法送了200 OK消息)。
应用程序在时序13步就开始向用户提示振铃,因为它已经意识到媒体会话已经成功构建。