基础 response code
1xx:informational-已经收到请求、继续处理请求。
2xx:success-已经成功收到,理解和介绍行动。
3xx:Redirection-为完成呼叫请求,还须采取进一步地动作。
4xx:ClientError-请求有语法错误或服务器不能执行请求。
5xx:ServerError-服务器出错,不能执行合法请求。
6xx:GLOBALFAILURE-任何服务器都不能执行请求。
会话(Session): 用于进行媒体流传送。当一方发出请求,而另外一方或多方接受请求并通过信令交互成功后才能建立会话。
跟SDP内信息相关。在SDP中,多媒体会话指的是一组的媒体发送方和接收方及媒体流从发送方流向接受方。会话是由SDP里的user name, session id, network type, address type, 和源处地址元素来确定的。只有当媒体协商成功后,会话才能被建立起来。
A session is initiated with INVITE and is created by completing offer/answer exchange.
对话(Dialog): 由INVITE或者SUBSCRIBE创建
对话指的是一对一的持续一段时间的连接关系,由Call-ID, From-tag和To-tag确定。当三个元素齐全的时候,即对话处于确定阶段时,对话已经建立起来。 Dialog ID:Call-Id, 本地tag, 对端tag 组成
Dialog(会话) 会话是两个UAs(user agent) 之间持续一段时间的端到端(peer-to-peer)的SIP 关系. 一个会话由一个Call-ID, 一个local tag 和 一个remote tag来标识.会话过去也叫做 "call leg".
Dialog is a peer-to-peer SIP relationship between two user agents that persists for some time. The dialog represents
a context in which to interpret SIP messages.
Dialogs are created through the generation of non-failure responses to requests with specific methods. Only 2xx and
101-199 responses with a To tag, where the request was INVITE, will establish a dialog
事务(Transaction)
事务包括发送的请求和相应的回应,指的是UA之间的请求和应答关系。而VIA中的branch参数用于确定事务。
Transaction(事务) 事务发生于客户端和服务器端之间,包含从客户端发出请求给服务器,到服务器响应给客户端的最终消息(non-1xx message)之间的所有消息. 如果请求是一个"Invite"消息,并且最终的响应是一个non-2xx消息,那么该事务包含一个"Ack"响应消息.如果服务器的响应是一个2xx消息,那么,随后的ACK是一个单独的事务.
Branch是一个事务ID(Transaction ID),用于区分同一个Client所发起的不同Transaction。
对于遵循RFC3261规范的实现,这个branch参数的值必须用magic cookie”z9hG4bK”打头. 其它部分是对“To, From, Call-ID头域和Request-URI”按一定的算法加密后得到。
这7个字母是一个乱数cookie(定义成为7位的是为了保证旧版本的RFC2543实现不会产生这样的值),这样服务器收到请求之后,可以很方便的知道这个branch ID是否由本规范所产生的(就是说,全局唯一的)。
事务是由事件(方法)来引起的,一个方法(Method)的建立和到来都将建立新的事务。
SIP Transaction
•一个SIP事务处理包含一个请求、零个或多个临时响应和一个最终响应。
•同一个事务处理中,请求和响应的To、From、Call-ID、CSeq等头域的值相同。
•Call-ID用于标识一个会话,在同一时刻全局唯一。
•事务类型:
INVITE Client Transaction
INVITE Server Transaction
non-INVITE Client Transaction
non-INVITE Server Transaction
总的来说,
1.对话和事务处于信令层,而会话处于媒体传输层。SIP使用SDP来通知传输层(RTP)来创建、增加、移除和修改会话。
2.一般来说,在会议应用中SIP可以通过请求来让另一方加入已有会话中。在这种情况下,新的对话会被创建。
3.对话是end-point对end-point的关系,即真实的通信双方,
而transaction 是hop by hop的关系,即路由过程中交互的双方。
理解会话
一 会话的初始化
Session用于进行媒体流传送。当一方发出请求,而另外一方或多方接受请求并通过信令交互成功后才能建立会话。
一次呼叫只能建立一次会话,但可以建立多个对话(Dialog),因为接受请求的可能不止一个。
1 UAC的处理
1.1 创建初始IVITE请求
初始的IVITE可以带有消息体。SIP使用提供/回答模型来进行会话协商,即提供者发送一些提议的媒体信息,而另一方可以回应选择的媒体信息(不一定在发送来的媒体中选择)。而提供/回答的交互是在对话中进行的,所以初始请求可能造成多个独立的对话。
而提供/回答模型有多个限制,如在这个规范下,提供和回答媒体信息只能存在于INVITE和回应及ACK中。
作为初始的请求,还有以下限制:(该限制在以后的扩展中已经被修改,详见draft-ietf-sipping-sip-offeranswer-04.txt)
1)初始提供媒体信息可以出现于INVITE,否则只能在2回应中。
2)如果提供媒体信息在INVITE中,回答媒体信息可以出现在1或2回应中,1中的媒体信息只是2的拷贝。
注意,UAC只是处理第一个提供媒体信息。
3)如果初始提供媒体信息出现在2回应中,则回答媒体信息必须在对2**回应的ACK中。
- UAC不能在一个媒体提供信息正在进行处理过程中提出新的一个媒体提供信息(即不能在没收到回答媒体信息之前发送新的提供媒体信息)。
5)在一个事务之中UAS只能提供一次媒体信息,而UAC无此限制。
注:以上的限制仅作用于Content-Disposition头字段为session时(如果该字段缺失,则Content-Type字段为application/sdp时Content-Disposition头字段为session,其它时候为render)。
1.2 处理IVITE回应
2 UAS的处理
2.1 处理INVITE消息
注:此节中所说的INVITE消息均为初始化会话的INVITE。
如果INVITE中不包含会话描述,则UAS应在2的回应中加上会话描述,转变为了媒体提供信息方。
对于INVITE的处理,UAS可以回应处理、接受、重定向或者拒绝。
2.1.1 处理
如果UAS暂时无法回应请求,则可以选择回应处理中消息,特别是回铃消息。该类消息可以发送任意多次,但不是可靠性传送(无ACK回应)。
代理服务器在处理事务时,如果一段时间内没有消息回应的话则会取消该事务,而该类消息可以用于延续事务生命(除100外)。
2.1.2 拒绝
如果INVITE提供媒体信息,而UAS无法接受的话回应488,这类消息应该包括一个Warning消息头。
2.1.3 接受
2回应中应该包括Allow和Supported消息头,可能包括Accept消息头。这些告诉UAC在呼叫过程中允许的特性。
如果作为回答媒体信息方,之前的回应中没有回答媒体信息,则在2中必须包含媒体信息。
如果2没有ACK的回应,虽然建立起了对话,但也应发送BYE来结束会话。
二 会话的修改
在《理解对话》一章中说过,通过目标更新请求可以修改对话(如修改对话的远端目标)。而此节主要讲的是如何修改会话,如地址、端口、增减媒体流等。这些是通过在同一对话中发送INVITE消息来实现的,即re-INVITE(该消息可以同时修改会话和对话)。UAC和UAS都具有re-INVITE功能。
1 UAC行为
同样的提供-回应模型同样适用于re-INVITE消息。re-INVITE同样可以不带有媒体描述信息,而随后的处理(包括ACK响应)跟普通INVITE一样。
不过媒体信息提供方应该修改会话版本(如果存在的话)。
跟普通INVITE不同的是,因为是在同一对话会中发送的INVITE消息,所以是点到点的交互。即re-INVITE不会衍生(fork),Request-URI不是AOR(address of record),而是对话目标。
虽然UA可以同时建立多个事务,但在同一个对话中只允许一个事务存在,除非旧事务正处在completed、confirmed或者terminated状态中。
2 UAS行为
如果收到的新的INVITE消息中的CSeq序号比旧的要小,则回应500且带有Retry-After消息头。
三 会话的结束
对话内BYE的发送可以结束跟该对话相关的会话(如re-INVITE的协商失败,则关闭新和旧的对话及会话)。而BYE的发送必须在建立对话之后,而建立对话之前取消则应使用CANCEL方法。UAC可以在对话初始和确定状态时发送BYE,而UAS只能在对话确定状态时发送BYE。而且UAS在对话确定状态时,只能在收到对2的ACK或事务超时的时候才能发送BYE。
一般来说,呼叫发起方在最终回应未到之前使用CANCEL来结束,而最后回应到了之后使用BYE方法;被叫方只适用BYE方法,当被叫摘机之后,2将被产生所以只能等ACK到来之后才能发送BYE。
理解SIP对话
Dialog是SIP中的一个关键概念。根据RFC3261,会话是两个UA之间持续一段时间的点到点的SIP连接,即是记录两者已经连接上的相关内容实体,方便在对话中请求进行识别和处理。
对话都是有对话ID来标识的,包括Call-ID,一个本地标签(From-tag)和一个远端标签(To-tag)。即是说三者确定了某个对话的存在。
对话中还包括一些对话中的后续消息所需的状态,包括:对话ID、本地序列号、远端序列号、本地URI、远端目的、布尔型标记“secure”和路由集。路由集是一个顺序的URI集,指定发送请求到目的地所需遍历的服务器地址。
会话的状态有初始状态和确认状态。当临时的相应被创建时,即标记对话的三个因素刚齐全时为初始状态;而收到2**的最后响应到达时转为确认状态,如果是其他响应或无响应到达,初始状态终结。
如下所示
图1-1 对话建立过程
创建对话
UAS i. 路由集由请求的Record-Route头字段提供,并要保留顺序和URI参数,实时更新,如果下一轮的请求中无Record-Route头字段,则路由集变为空 ii. 本地URI填入回应的Contact头字段 iii.布尔型标记“secure”,如果请求基于TLS(传输层安全协议),则由Request-URI中的secure参数来提供 iv. 远端目的由请求的Request-URI提供 v. From-tag可能不存在,则默认为空
UAC i. 路由集必须为响应消息中的Record-Route头字段的URI列表,保持相反的顺序和保留所有的URI参数 ii. 远端目的为响应消息的Contact头字段的URI iii. 本地序列号为请求消息的CSeq头字段的序列号值 iv. 远端序列号必须为空,当远端UA发送一个本次对话中的请求后该值才能确定 v. To-tag可能不存在,则默认为空
对话中的请求
对话创建后,UA方可能需要建立新的事务,这时发起请求的UA为UAC,这可能跟对话创建之时的角色不同。re-INVITE是一种对话中修改目的URI的重新请求。
UAC行为 i. 发起请求 一个对话中的请求消息有对话所保存的状态信息来构建。 1. 请求消息的To头字段的URI必须设置为对话状态的远端URI 2. 请求消息的To头字段的标签值设置为对话ID的远端标签值 3. 请求消息的From头字段的URI必须设置为对话状态的本端URI 4. 请求消息的From头字段的标签值设置为对话ID的本端标签值 5. 请求消息的Call-ID必须设置为对话的Call-ID 而对话中的其它字段同样有限制: 6. CSeq序列号。CSeq是按照各自方向严格增1的值,如果为空则设为初始值。 7. Request-URI由远端目的指定 8. Route由路由集指定,如果路由集为空,则无Route字段。如果路由集的第一个URI中包含lr参数,UAC必须将Request-URI设置为远端目的URI值;如果路由集的第一个URI中不包含lr参数,UAC必须将Request-URI设置为路由集的第一个URI,且不允许去掉任何参数,同时Route头字段在最后增加一个目的URI。 9.Contact。对话中任何一个更新目的的请求消息包含一个Contact头字段,Contact字段内URI为对话的远端目的URI。
如果UAC收到对目的刷新请求消息的2**响应时,UAC必须将对话的远端目的URI设置为存在Contact字段的URI值。如果响应为481(呼叫/事务不存在)或408(请求超时),UAC应该终止对话;在无对方响应时也应该终止对话。
2) UAS行为
i. 如果请求To字段存在标签值。UAS内核会计算与此请求相关的对话标签值,同时与已有的对话标签值比较,如果匹配则为同一个对话中的请求。此时UAS采用与对话外请求消息处理规则相同的流程进行处理;如果不存在匹配的对话,UAS可以拒绝(481)或接受这个请求。
ii.如果远端序列号为空,则设置为请求消息中CSeq字段的序列号值;如果远端序列号存在并大于请求的CSeq序列号值,则认为请求次序颠倒,回500(服务器内不出错)消息。
终止对话
初始状态的对话不依赖于发起请求的具体方法,只要收到一个非2**的终止响应即可将其终止;确认状态的对话的终止与确切方法相关,BYE方法终止一次会话并终止与其相关的对话。
事务(Transaction)的理解
Transaction有交易的意思,Sip是个事务型的协议,因为它需要各部件间互通消息来实现。
事务所处的位置如图:
图一 事务环境图
1)事务处理主要用于处理消息的交互,它的实现使用了状态机。向上它向事务使用者(TU)提交事务的触发事件(计时器超时和传输层消息),向下把所要发送的Sip消息包传送给传输层代为转发。
2)而在事务中一定有客户端和服务器端,两者没有必然的界限。只要是发起请求的,在该事务中充当的当然是客户端,接受请求的必然是服务器端。所以对于代理服务器来说,相对下面的请求来说它是服务器端,对于上面来说却是代发请求的客户端。
事务分类
事务根据类型还分Invite和Non-Invite型,即邀请和非邀请类型。Non-Invite类型事务主要处理的是除Invite和ACK类型外的所有Sip信息。而非Invite里的ACK信息要处理的话就不属于事务处理的范围了,一般由程序自己把信息发送给传输层直接发送。Invite需要三次握手,所以需要的时间比较长;而Non-Ivite类型只需两次握手,要求回应时间短。
所以由RFC3261规定,Sip中主要有四种事务,对应有四种状态机:
Invite Client Transaction(ICT):
Non-Invite Client Transaction(NICT):
Invite Server Transaction(IST):
Non-Invite Server Transaction(NIST):
其中有个特别的地方在于:对于2**回应的ACK不属于ICT的事务处理范围
原因在于收到200(OK)的ACK上。
对于接收到这些ACK的用户来说,如果非最后的客户端,即UA接收到该消息的话将关掉该事务再转发该消息,不再理会之后的事情。而收到200的UAC可能把ACK直接发往真正的UAS,此时不再通过代理服务器或重定向服务器。而前面提到的事务的概念指的是两者之间的交互,可此时UAC要发往信息不再是之前存在的事务(交易者已变)。所以此时发送ACK已不是事务的范畴了,同样ACK的重发和UAS的200重发都不再是事务的范畴,因为发送200的UAS和接收到200的UAC的事务状态已置为结束。