SIP协议

SIP协议  

2011-04-15 23:21:29|  分类: FreeSWITCH |字号 订阅html

 

在 继续学习 FreeSWITCH 以前咱们有必要来学习一下 SIP 协议,由于它是 FreeSWITCH 的核心。但即便如此,讲清楚 SIP 必然须要很大篇幅,本书是关于 FreeSWITCH 的,而重点不是 SIP。所以,我将仅就理解 FreeSWITCH 必需的一些概念加以通俗的解释,更严肃一些的请参阅其它资料或 RFC(Request For Comments)。数据库


SIP 的概念和相关元素
安全

会 话初始协议(Session Initiation Protocol)是一个控制发起、修改和终结交互式多媒体会话的信令协议。它是由 IETF(Internet Engineering Task Force,Internet工程任务组)在 RFC 2543 中定义的。最先发布于 1999 年 3 月,后来在 2002 年 6 月又发布了一个新的标准 RFC 2361。服务器

SIP 是一个基于文本的协议,在这一点上与 HTTP 和 SMTP 类似。咱们来对比一个简单的 SIP 请求与 HTTP 请求:网络

GET /index.html HTTP/1.1    INVITE sip:seven@freeswitch.org.cn SIP/2.0

请 求由三部分组成。在 HTTP 中, GET 指明一个获取资源(文件)的动做,而 /index.html 则是资源的地址,最后是协议版本号。而在 SIP 中,INVITE 表示发起一次请求,seven@freeswitch.org.cn 为请求的地址,称为 SIP URI,最后也是版本号。其中,SIP URI很相似一个电子邮件,其格式为“协议:名称@主机”。与 HTTP 和 HTTPS 相对应,有 SIP 和 SIPS,后者是加密的;名称能够是一串数字的电话号码,也能够是字母表示的名称;而主机能够是一个域名,也能够是一个IP地址。session

SIP 是一个对等的协议,相似 P2P。不像传统电话那样必须有一个中心的交换机,它能够在不须要服务器的状况下进行通讯,只要通讯双方都彼此知道对方地址(或者,只有一方知道另外一方地 址),以下图,bob 给 alice 发送一个 INVITE 请求,说“Hi, 一块儿吃饭吧...”,alice 说"好的,OK",电话就通了。并发

在 SIP 网络中,alice 和 bob 都叫作用户代理(UA, User Agent)。UA 是在 SIP 网络中发起或响应 SIP 处理的逻辑功能。UA是有状态的,也就是说,它维护会话(或称对话)的状态。UA 有两种功能:一种是 UAC(UA Client用户代理客户端),它是发起 SIP 请求的一方,如上图的 bob。另外一种是 UAS(UA Server),它是接受请求并发送响应的一方,如上图中的 alice。因为 SIP 是对等的,若是 alice 呼叫 bob 时(有时候 alice 也主动叫 bob 一块儿吃饭),alice 就称为 UAC,而 bob 则执行 UAS的功能。通常来讲,UA 都会实现上述两种功能。app

设 想 bob 和 alice 是经人介绍认识的,而他们还不熟悉,bob 想请 alice 吃饭就须要一个中间人(M)传话,而这个中间人就叫代理服务器(Proxy Server)。还有另外一种中间人叫作重定向服务器(Redirect Server),它相似于这样的方式工做──中间人 M 告诉 bob,我也不知道 alice 在哪里,但我老婆知道,要否则我告诉你我老婆的电话,你直接问她吧,我老婆叫 W。这样,M 就成了一个重定向服务器,而他老婆 W 则是真正的代理服务器。这两种服务器都是 UAS,它们主要是提供一对欲通话的 UA 之间的路由选择功能。具备这种功能的设备一般称为边界会话控制器(SBC,Service Border Controller)。学习

还 有一种 UAS 叫作注册服务器。试想这样一种状况,alice 仍是个学生,没有本身的手机,但它又但愿 bob 能随时找到她,因而当她在学校时就告诉中间人 M 说她在学校,若是有事打她能够打宿舍的电话;而当她回家时也通知 M 说有事打家里电话。只要 alice 换一个新的位置,它就要向 M 从新“注册”新位置的电话,以让 M 能随时找到她,这时候 M 就是一个注册服务器。ui

最 后一种叫作背靠背用户代理(B2BUA,Back-to-Back UA)。须要指出,其实 RFC 3261 并无定义 B2BUA的功能,它只是一对 UAS 和 UAC的串联。FreeSWITCH 就是一个典型的 B2BUA,事实上,B2BUA 的概念会贯穿本书始终,因此,在此咱们须要多花一点笔墨来解释。

咱们来看上述故 事的另外一个版本:M 和 W 是一对恩爱夫妻。M 认识 bob 而 W 认识 alice。M 和 W 有意搓合两个年轻人,但见面时因为两人太腼腆而互相没留电话号码。过后 bob 相知道 alice 对他感受如何,因而打电话问 M,M 不认识 alice,就转身问老婆 W (注意此次 M 没有直接把 W 电话给 bob),W 接着打电话给 alice,alice 说印象还不错,W 就把这句话告诉 M, M 又转过身告诉 bob。 M 和 W 一个面向 bob,一个对着 alice,他们两个合在一块儿,称做 B2BUA。在这里,bob 是 UAC,由于他发起请求;M 是 UAS,由于他接受 bob 的请求并为他服务;咱们把 M 和 W 看作一个总体,他们背靠着背(站着坐着躺着都行),W 是 UAC,由于她又向 alice 发起了请求,最后 alice 是 UAS。其实这里UAC 和 UAS 的概念也不是那么重要,重要的是要理解这个背靠背的用户代理。由于事情尚未完,bob 一据说 alice 对他印象还不错,心花盛开,便想请 alice 吃饭,他告诉 M, M 告诉 W, W 又告诉 alice,alice 问去哪吃,W 又只好问 M, M 再问 bob…… 在这对年轻人挂断电话这前, M 和 W 只能“背对背”的工做。

从 上图能够看出,四我的其实全是 UA。从上面故事能够看出,虽然 FreeSWITCH 是 B2BUA,但也能够通过特殊的配置,实现一些代理服务器和重定向服务器的功能,甚至也能够从中间劈开,两边分别做为一个普通的 UA 来工做。这没有什么奇怪的,在 SIP 世界中,全部 UA 都是平等的。具体到实物,则 M 和 W 就组成了实现软交换功能的交换机,它们对外说的语言是 SIP,而在内部,它们则使用本身家的语言沟通。bob 和 alice 就分别成了咱们常见的软电话,或者硬件的 SIP 电话。


SIP 注册

不像普通的固定电话网中,电话的地址都是固定的。因特网是开放的,alice 的 UA 可能在家也可能在学校,或者,在世界是任何角落,只要能上网,它就能与世界通讯。为了让咱们的 FreeSWITCH 服务器能找到它,它必须向服务器进行注册。一般的注册流程是:

Alice FreeSWITCH ||    |  REGISTER  |    |------------------------------->|    |   SIP/2.0 401 Unauthorized     |    |<-------------------------------|    |  REGISTER             |    |------------------------------->|    |   SIP/2.0 200 OK               |    |                                |

我 们用真正的注册流程进行说明。下面的 SIP 消息是在真正的 FreeSWITCH 中 trace 出来的。其中 FreeSWITCH 服务器的 IP 地址是 192.168.4.4,使用默认的端口号 5060,在这里,咱们使用的是 UDP 协议。 alice 使用的 UAC 是 Zoiper,端口号是 5090(在我写做时它与 FreeSWITCH 在同一台机器上,因此不能再使用端口 5060)。其中每一个消息短横线之间的内容都是 FreeSWITCH 中输出的调试信息,不是 SIP 的一部分。

------------------------------------------------------------------------  recv 584 bytes from udp/[192.168.4.4]:5090 at 12:30:57.916812:  ------------- REGISTER sip:192.168.4.4;transport=UDP SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-d9ed3bbae47e568b-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:alice@192.168.4.4:5090;rinstance=d42207a765c0626b;transport=UDP>  To: <sip:alice@192.168.4.4;transport=UDP>  From: <sip:alice@192.168.4.4;transport=UDP>;tag=9c709222  Call-ID: NmFjNzA3MWY1MDI3NGViMjY1N2QwZDlmZWQ5ZGY2OGE.  CSeq: 1 REGISTER  Expires: 3600  Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE  User-Agent: Zoiper rev.5415  Allow-Events: presence  Content-Length: 0

recv 代表 FreeSWITCH 收到来自 alice 的消息。咱们前面已经说进,SIP 是纯文本的协议,相似 HTTP,因此很容易阅读。


第一行的 REGISTER 表示是一条注册消息。
Via 是 SIP 的消息路由,若是 SIP 通过好多代理服务器转发,则会有多条 Via 记录。
Max-forwards 指出消息最多能够通过多少次转发,主要是为了防止产生死循环。
Contact 是 alice 家的地址,本例中,FreeSWITCH 应该能在 192.168.4.4 这台机器上的 5090 端口找到她。
To 和 From 先无论。
Call-ID 是本次 SIP 会话(Session)的标志。
CSeq 是一个序号,因为 UDP 是不可靠的协议,在不可靠的网络上可能丢包,因此有些包须要重发,该序号则能够防止重发引发的消息重复。
Expires 是说明本次注册的有效期,单位是秒。在本例中,alice 应该在一小时内再次向 FreeSWITCH 注册,防止 FreeSWITCH 忘掉她。实际上,大部分 UA 的实现都会在几十秒内就从新发一次注册请求,这在 NAT 的网络中有助于保持链接。
Allow 是说明 alice 的 UA 所能支持的功能,某些 UA 功能丰富,而某些 UA 仅有有限的功能。
User-Agent 是 UA 的型号。
Allow-Events 则是说明她容许哪些事件通知。
Content-Length 是消息体(Body)的长度,在这里,只有消息头(Header),没有消息体,所以长度为 0 。

.

------------------------------------------------------------------------  send 664 bytes to udp/[192.168.4.4]:5090 at 12:30:57.919364:  ------------------------------------------------------------------------  SIP/2.0 401 Unauthorized  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-d9ed3bbae47e568b-1---d8754z-;rport=5090  From: <sip:alice@192.168.4.4;transport=UDP>;tag=9c709222  To: <sip:alice@192.168.4.4;transport=UDP>;tag=QFXyg6gcByvUH  Call-ID: NmFjNzA3MWY1MDI3NGViMjY1N2QwZDlmZWQ5ZGY2OGE.  CSeq: 1 REGISTER  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  WWW-Authenticate: Digest realm="192.168.4.4",      nonce="62fb812c-71d2-4a36-93d6-e0008e6a63ee", algorithm=MD5, qop="auth"  Content-Length: 0

FreeSWITCH 须要验证 alice 的身分才容许她注册。在 SIP 中,没有发明新的认证方式,而是使用已有的 HTTP 摘要(Digest)方式来认证。401 消息表示未认证,它是 FreeSWITCH 对 alice 的响应。同时,它在本端生成一个认证摘要(WWW-Authenticate),一齐发送给 alice。

------------------------------------------------------------------------  recv 846 bytes from udp/[192.168.4.4]:5090 at 12:30:57.921011:  ------------------------------------------------------------------------  REGISTER sip:192.168.4.4;transport=UDP SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-dae1693be9f8c10d-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:alice@192.168.4.4:5090;rinstance=d42207a765c0626b;transport=UDP>  To: <sip:alice@192.168.4.4;transport=UDP>  From: <sip:alice@192.168.4.4;transport=UDP>;tag=9c709222  Call-ID: NmFjNzA3MWY1MDI3NGViMjY1N2QwZDlmZWQ5ZGY2OGE.  CSeq: 2 REGISTER  Expires: 3600  Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE  User-Agent: Zoiper rev.5415  Authorization: Digest username="alice",realm="192.168.4.4",      nonce="62fb812c-71d2-4a36-93d6-e0008e6a63ee",      uri="sip:192.168.4.4;transport=UDP",response="32b5ddaea8647a3becd25cb84346b1c3",      cnonce="b4c6ac7e57fc76b85df9440994e2ede8",nc=00000001,qop=auth,algorithm=MD5  Allow-Events: presence  Content-Length: 0

alice 收到带有摘要的 401 后,后新发起注册请求,这一次,加上了根据收到的摘要和它本身的密码生成的认证信息(Authorization)。而且,你能够看到,CSeq 序号变成了 2。

------------------------------------------------------------------------  send 665 bytes to udp/[192.168.4.4]:5090 at 12:30:57.936940:  ------------------------------------------------------------------------  SIP/2.0 200 OK  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-dae1693be9f8c10d-1---d8754z-;rport=5090  From: <sip:alice@192.168.4.4;transport=UDP>;tag=9c709222  To: <sip:alice@192.168.4.4;transport=UDP>;tag=rrpQj11F86jeD  Call-ID: NmFjNzA3MWY1MDI3NGViMjY1N2QwZDlmZWQ5ZGY2OGE.  CSeq: 2 REGISTER  Contact: <sip:alice@192.168.4.4:5090;rinstance=d42207a765c0626b;transport=UDP>;expires=3600  Date: Tue, 27 Apr 2010 12:30:57 GMT  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Content-Length: 0

FreeSWITCH 收到带有认证的注册消息后,核实 alice 身份,认证经过,回应 200 OK。 若是失败,则回应 403 Forbidden 或其它失败消息,以下。

------------------------------------------------------------------------  send 542 bytes to udp/[192.168.4.4]:5090 at 13:22:49.195554:  ------------------------------------------------------------------------  SIP/2.0 403 Forbidden  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-d447f43b66912a1b-1---d8754z-;rport=5090  From: <sip:alice@192.168.4.4;transport=UDP>;tag=c097e17f  To: <sip:alice@192.168.4.4;transport=UDP>;tag=yeecX364pvryj  Call-ID: ZjkxMGJmMjE4Y2ZiNjU5MzM5NDZkMTE5NzMzMzM0Mjc.  CSeq: 2 REGISTER  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Content-Length: 0

你能够看到,alice 的密码是不会直接在 SIP 中传送的,于是必定程序上保证了安全(固然仍是会有中间人,重放之类的攻击,咱们留到后面讨论)。


SIP 呼叫流程
UA 间直接呼叫

上 面咱们说过,SIP 的 UA 是平等的,若是一方知道另外一方的地址,就能够通讯。咱们先来作一个实验。在笔者的机器上,我启动了两个软电话(UA), 一个是 bob 的 X-Lite(左),另外一个是 alice 是 Zoiper。它们的 IP 地址都是 192.168.4.4,而端口号分别是 26000 和 5090,当 bob 呼叫 alice 时,它只需直接呼叫 alice 的 SIP 地址:sip:alice@192.168.4.4:5090。如图,alice 的电话正在振铃:

 

详细的呼叫流程图为:

bob               alice  |                     |  |    INVITE           |  |-------------------->|  |    100 Trying       |  |<--------------------|  |    180 Ringing      |  |<--------------------|  |    200 OK           |  |<--------------------|  |    ACK              |  |-------------------->|  |                     |  |<---RTP------------->|  |<---RTP------------->|  |<---RTP------------->|  |    ...              |  |                     |  |    BYE              |  |<--------------------|  |    200 OK           |  |-------------------->|  |                     |

首 先 bob 向 alice 发送 INVITE 请求创建 SIP 链接,alice 的 UA 回 100 Trying 说我收到你的请求了,先等会,接着 alice 的电话开始振铃,并给对回消息 180 Ringing 说我这边已经振铃了,alice 一会就过来接电话,bob 的 UA 收到该消息后能够播放回铃音。接着 alice 接了电话,她发送 200 OK 消息给 bob,该消息是对 INVITE 消息的最终响应,而先前的 100 和 180 消息都是临时状态,只是代表呼叫进展的状况。 bob 收到 200 后向 alice 回 ACK 证明消息。 INVITE - 200 - ACK 完成三次握手,它们合在一块儿称做一个对话(Dialogue)。这时候 bob 已经在跟 alice 能通话了,他们通话的内容(语音数据)是在SIP以外的 RTP 包中传递的,咱们后面再详细讨论。

最后,alice 挂断电话,向 bob 送 BYE 消息,bob 收到 BYE 后回送 200 OK,通话完毕。其中 BYE 和 200 OK 也是一个对话,而上面的全部消息,称做一个会话(Session)。

反过来也同样,alice 能够直接呼叫 bob 的地址: sip:bob@192.168.4.4:26000。

上 面描述了一个最简单的 SIP 呼叫流程。实际上,SIP 还有其它一些消息,它们大体可分为请求和响应两类。请求由 UAC 发出,到达 UAS 后, UAS 回送响应消息。某些响应消息须要证明(ACK),以完成三次握手。其中请求消息包括 INVITE、ACK、OPTIOS、BYE、CANCEL、REGISTER 以及一些扩展 re-INVITE、PRACK、SUBSCRIBE、NOTIFY、UPDATE、MESSAGE、REFER等。而响应消息则都包含一个状态码。跟 HTTP 响应相似,状态码有三位数字组成。其中,1xx 组的响应为临时状态,代表呼叫进展的状况;2xx 代表请求已成功处理;3xx 代表 SIP 请求须要转向到另外一个 UAS 处理;4xx 代表请求失败,这种失败通常是由客户端或网络引发的,如密码错误等;5xx 为服务器内部错误;6xx 为更严重的错误。


经过 B2BUA 呼叫

在真实世界中,bob 和 alice 确定要常常改变位置,那么它们的 SIP 地址也会相应改变,而且,若是他们之中有一个或两个处于 NAT 的网络中时,直接通讯就更困难了。因此,他们一般会借助于一个服务器来相互通讯。经过注册到服务器上,他们均可以得到一个服务器上的 SIP 地址。注册服务器的地址通常是不变的,所以他们的 SIP 地址就不会发生变化,于是,他们老是可以进行通讯。

我 们让他们两个都注册到 FreeSWITCH 上。上面已经说过,FreeSWITCH 监听的端口是 SIP 默认的端口 5060。bob 和 alice 注册后,他们分别得到了一个服务器的地址(SIP URI):sip:bob@192.168.4.4 和 sip:alice@192.168.4.4(默认的端口号 5060 能够省略)。

下面是 bob 呼叫 alice 的流程。须要指出,若是 bob 只是发起呼叫而不接收呼叫,他并不须要向 FreeSWITCH 注册(有些软交换服务器须要先注册才能发起呼叫,但 SIP 是不强制这么作的)。

------------------------------------------------------------------------  recv 1118 bytes from udp/[192.168.4.4]:26000 at 13:31:39.938891:  ------------------------------------------------------------------------  INVITE sip:alice@192.168.4.4 SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-56adad736231f024-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:bob@192.168.4.4:26000>  To: "alice"<sip:alice@192.168.4.4>  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 1 INVITE  Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO  Content-Type: application/sdp  User-Agent: X-Lite release 1014k stamp 47051  Content-Length: 594

上 面的消息中省略了 SDP 的内容,咱们将留到之后再探讨。bob 的 UAC 经过 INVITE 消息向 FreeSWITCH 发起请求。bob 的 UAC 用的是 X-Lite(User-Agent),它运行在端口 26000 上(实际上,它默认在端口也是 5060,但因为在个人实验环境下它也是跟 FreeSWITCH 运行在一台机器上,已被占用,所以它须要选择另外一个端口)。其中,From 为主叫用户的地址,To 为被叫用户的地址。此时 FreeSWITCH 做为一个 UAS 接受请求并进行响应。它得知 bob 要呼叫 alice,须要在本身的数据库中查找 alice 是否已在服务器上注册,好知道应该怎么找到 alice。但在此以前,它先通知 bob 它已经收到了他的请求。

------------------------------------------------------------------------  send 345 bytes to udp/[192.168.4.4]:26000 at 13:31:39.940278:  ------------------------------------------------------------------------  SIP/2.0 100 Trying  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-56adad736231f024-1---d8754z-;rport=26000  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  To: "alice"<sip:alice@192.168.4.4>  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 1 INVITE  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Content-Length: 0

FreeSWITCH 经过 100 Trying 消息告诉 bob “我已经收到你的消息了,别着急,我正在联系 alice 呢...” 该消息称为呼叫进展消息。

------------------------------------------------------------------------  send 826 bytes to udp/[192.168.4.4]:26000 at 13:31:39.943392:  ------------------------------------------------------------------------  SIP/2.0 407 Proxy Authentication Required  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-56adad736231f024-1---d8754z-;rport=26000  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  To: "alice" <sip:alice@192.168.4.4>;tag=B4pem31jHgtHS  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 1 INVITE  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Accept: application/sdp  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Allow-Events: talk, presence, dialog, line-seize, call-info, sla,      include-session-description, presence.winfo, message-summary, refer  Proxy-Authenticate: Digest realm="192.168.4.4",      nonce="31c5c3e0-cc6e-46c8-a661-599b0c7f87d8", algorithm=MD5, qop="auth"  Content-Length: 0

但就在此时,FreeSWITCH 发现 bob 并非受权用户,于是它须要确认 bob 的身份。它经过发送带有 Digest 验证信息的 407 消息来通知 bob(注意,这里与注册流程中的 401 不一样)。

------------------------------------------------------------------------  recv 319 bytes from udp/[192.168.4.4]:26000 at 13:31:39.945314:  ------------------------------------------------------------------------  ACK sip:alice@192.168.4.4 SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-56adad736231f024-1---d8754z-;rport  To: "alice" <sip:alice@192.168.4.4>;tag=B4pem31jHgtHS  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 1 ACK  Content-Length: 0

bob 回送 ACK 证明消息向 FreeSWITCH 证明已收到认证要求。并从新发送 INVITE,此次,附带了验证信息。

------------------------------------------------------------------------  recv 1376 bytes from udp/[192.168.4.4]:26000 at 13:31:39.945526:  ------------------------------------------------------------------------  INVITE sip:alice@192.168.4.4 SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-87d60b47b6627c3a-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:bob@192.168.4.4:26000>  To: "alice"<sip:alice@192.168.4.4>  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 2 INVITE  Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, NOTIFY, MESSAGE, SUBSCRIBE, INFO  Content-Type: application/sdp  Proxy-Authorization: Digest username="bob",realm="192.168.4.4",      nonce="31c5c3e0-cc6e-46c8-a661-599b0c7f87d8",      uri="sip:alice@192.168.4.4",response="327887635344405bcd545da06763c466",      cnonce="c164b74f625ff2161bd8d47dba3a0ee2",nc=00000001,qop=auth,      algorithm=MD5  User-Agent: X-Lite release 1014k stamp 47051  Content-Length: 594

这里也省略了 SDP 消息体。

------------------------------------------------------------------------  send 345 bytes to udp/[192.168.4.4]:26000 at 13:31:39.946349:  ------------------------------------------------------------------------  SIP/2.0 100 Trying  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-87d60b47b6627c3a-1---d8754z-;rport=26000  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  To: "alice"<sip:alice@192.168.4.4>  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 2 INVITE  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Content-Length: 0

FreeSWITCH 从新回 100 Trying,告诉 bob 呼叫进展状况。

至此,bob 与 FreeSWITCH 之间的通讯已经初步创建,这种通讯的通道称做一个信道(channel)。该信道是由 bob 的 UA 和 FreeSWITCH 的一个 UA 构成的,咱们称它为 FreeSWITCH 的一条腿,叫作 a-leg。

接下来 FreeSWITCH 要创建另外一条腿,称为 b-leg。它经过查打本地数据库,获得了 alice 的位置,接着启动一个 UA(用做 UAC),向 alice 发送 INVITE 消息。以下:

------------------------------------------------------------------------  send 1340 bytes to udp/[192.168.4.4]:5090 at 13:31:40.028988:  ------------------------------------------------------------------------  INVITE sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4;rport;branch=z9hG4bKey90QUyHZQXNN  Route: <sip:alice@192.168.4.4:5090>;rinstance=e7d5364c81f2b879;transport=UDP  Max-Forwards: 69  From: "Bob" <sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  To: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 130069214 INVITE  Contact: <sip:mod_sofia@192.168.4.4:5060>  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Allow-Events: talk, presence, dialog, line-seize, call-info, sla,      include-session-description, presence.winfo, message-summary, refer  Content-Type: application/sdp  Content-Disposition: session  Content-Length: 313  X-FS-Support: update_display  Remote-Party-ID: "Bob" <sip:bob@192.168.4.4>;party=calling;screen=yes;privacy=off

你 能够看到,该INVITE 的 Call-ID 与前面的不一样,说明这是另外一个 SIP 会话(Session)。另外,它还多了一个 Remote-Party-ID,它主要是用来支持来电显示。由于,在 alice 的话机上,但愿显示 bob 的号码,显示呼叫它的那个 UA(负责 b-leg的那个 UA)没什么意义。与普通的 POTS 电话不一样,在 SIP 电话中,不只能显示电话号码(这里是 bob),还能显示一个可选的名字(“Bob”)。这也说明了 FreeSWITCH 这个 B2BUA 自己是一个总体,它虽然是以一个单独的 UA 呼叫 alice,但仍是跟负责 bob 的那个 UA 有联系--就是这种背靠背的串联。

------------------------------------------------------------------------  recv 309 bytes from udp/[192.168.4.4]:5090 at 13:31:40.193634:  ------------------------------------------------------------------------  SIP/2.0 100 Trying  Via: SIP/2.0/UDP 192.168.4.4;rport=5060;branch=z9hG4bKey90QUyHZQXNN  To: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>  From: "Bob" <sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 130069214 INVITE  Content-Length: 0

跟上面的流程差很少,alice回的呼叫进展。此时,alice 的 UA 开始振铃。

------------------------------------------------------------------------  recv 431 bytes from udp/[192.168.4.4]:5090 at 13:31:40.193816:  ------------------------------------------------------------------------  SIP/2.0 180 Ringing  Via: SIP/2.0/UDP 192.168.4.4;rport=5060;branch=z9hG4bKey90QUyHZQXNN  Contact: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>  To: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>;tag=3813e926  From: "Bob"<sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 130069214 INVITE  User-Agent: Zoiper rev.5415  Content-Length: 0

180也是呼叫进展消息,它说明,我这边已经准备好了,alice 的电话已经响了,她听到了一会就会接听。

send 1125 bytes to udp/[192.168.4.4]:26000 at 13:31:40.270533:  ------------------------------------------------------------------------  SIP/2.0 183 Session Progress  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-87d60b47b6627c3a-1---d8754z-;rport=26000  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  To: "alice" <sip:alice@192.168.4.4>;tag=cDg7NyjpeSg4m  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 2 INVITE  Contact: <sip:alice@192.168.4.4:5060;transport=udp>  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Accept: application/sdp  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Allow-Events: talk, presence, dialog, line-seize, call-info, sla,      include-session-description, presence.winfo, message-summary, refer  Content-Type: application/sdp  Content-Disposition: session  Content-Length: 267  Remote-Party-ID: "alice" <sip:alice@192.168.4.4>

FreeSWITCH 在收到 alice 的 180 Ringing 消息后,便告诉 bob 呼叫进展状况,183 与 180 不一样的是,它包含 SDP,即接下来它会向 bob 发送 RTP 的媒体流,就是回铃音。

------------------------------------------------------------------------  recv 768 bytes from udp/[192.168.4.4]:5090 at 13:31:43.251980:  ------------------------------------------------------------------------  SIP/2.0 200 OK  Via: SIP/2.0/UDP 192.168.4.4;rport=5060;branch=z9hG4bKey90QUyHZQXNN  Contact: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>  To: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>;tag=3813e926  From: "Bob"<sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 130069214 INVITE  Allow: INVITE, ACK, CANCEL, BYE, NOTIFY, REFER, MESSAGE, OPTIONS, INFO, SUBSCRIBE  Content-Type: application/sdp  User-Agent: Zoiper rev.5415  Content-Length: 226

alice 接听电话之后,其 UA 向 FreeSWITCH 送 200 OK,即应答消息。

------------------------------------------------------------------------  send 436 bytes to udp/[192.168.4.4]:5090 at 13:31:43.256692:  ------------------------------------------------------------------------  ACK sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4;rport;branch=z9hG4bKF72SSpFNv0K8g  Max-Forwards: 70  From: "Bob" <sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  To: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>;tag=3813e926  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 130069214 ACK  Contact: <sip:mod_sofia@192.168.4.4:5060>  Content-Length: 0

FreeSWITCH 向 alice 回送证明消息,证明已经知道了。至此,b-leg已经彻底创建完毕,多半这时 alice 已经开始说话了:“Hi, bob,你好……”

------------------------------------------------------------------------  send 1135 bytes to udp/[192.168.4.4]:26000 at 13:31:43.293311:  ------------------------------------------------------------------------  SIP/2.0 200 OK  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-87d60b47b6627c3a-1---d8754z-;rport=26000  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  To: "alice" <sip:alice@192.168.4.4>;tag=cDg7NyjpeSg4m  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 2 INVITE  Contact: <sip:alice@192.168.4.4:5060;transport=udp>  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Allow-Events: talk, presence, dialog, line-seize, call-info, sla,      include-session-description, presence.winfo, message-summary, refer  Session-Expires: 120;refresher=uas  Min-SE: 120  Content-Type: application/sdp  Content-Disposition: session  Content-Length: 267  Remote-Party-ID: "alice" <sip:alice@192.168.4.4>

与此同时,它也给 bob 送应答消息,告诉他电话已经接通了,能够跟 alice 说话了。在须要计费的状况下,应该今后时开始对 bob 的电话计费。bob 的 UA 收到该消息后启动麦克风让 bob 讲话。

------------------------------------------------------------------------  recv 697 bytes from udp/[192.168.4.4]:26000 at 13:31:43.413025:  ------------------------------------------------------------------------  ACK sip:alice@192.168.4.4:5060;transport=udp SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:26000;branch=z9hG4bK-d8754z-ef53864320037c04-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:bob@192.168.4.4:26000>  To: "alice"<sip:alice@192.168.4.4>;tag=cDg7NyjpeSg4m  From: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 2 ACK  Proxy-Authorization: Digest username="bob",realm="192.168.4.4",      nonce="31c5c3e0-cc6e-46c8-a661-599b0c7f87d8",      uri="sip:alice@192.168.4.4",response="327887635344405bcd545da06763c466",      cnonce="c164b74f625ff2161bd8d47dba3a0ee2",nc=00000001,qop=auth,      algorithm=MD5  User-Agent: X-Lite release 1014k stamp 47051  Content-Length: 0

bob 在收到应答消息后也须要回送证明消息。至此 a-leg 也创建完毕。双方正常通话。

[][][][][][] 此处省略 5000 字 [][][][][]

------------------------------------------------------------------------  recv 484 bytes from udp/[192.168.4.4]:5090 at 13:31:49.949240:  ------------------------------------------------------------------------  BYE sip:mod_sofia@192.168.4.4:5060 SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-2146ae0ddd113efe-1---d8754z-;rport  Max-Forwards: 70  Contact: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>  To: "Bob"<sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  From: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>;tag=3813e926  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 2 BYE  User-Agent: Zoiper rev.5415  Content-Length: 0

终于聊完了,alice 挂断电话,发送 BYE 消息。

------------------------------------------------------------------------  send 543 bytes to udp/[192.168.4.4]:5090 at 13:31:49.950425:  ------------------------------------------------------------------------  SIP/2.0 200 OK  Via: SIP/2.0/UDP 192.168.4.4:5090;branch=z9hG4bK-d8754z-2146ae0ddd113efe-1---d8754z-;rport=5090  From: <sip:alice@192.168.4.4:5090;rinstance=e7d5364c81f2b879;transport=UDP>;tag=3813e926  To: "Bob"<sip:bob@192.168.4.4>;tag=Dp9ZQS3SB26pg  Call-ID: 0d74ac35-cca4-122d-81a2-2990e5b2bd3e  CSeq: 2 BYE  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Content-Length: 0

FreeSWITCH 返回 OK,b-leg 释放完毕。

------------------------------------------------------------------------  send 630 bytes to udp/[192.168.4.4]:26000 at 13:31:50.003165:  ------------------------------------------------------------------------  BYE sip:bob@192.168.4.4:26000 SIP/2.0  Via: SIP/2.0/UDP 192.168.4.4;rport;branch=z9hG4bKggvjUH0rS99tc  Max-Forwards: 70  From: "alice" <sip:alice@192.168.4.4>;tag=cDg7NyjpeSg4m  To: "Bob" <sip:bob@192.168.4.4>;tag=15c8325a  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 130069219 BYE  Contact: <sip:alice@192.168.4.4:5060;transport=udp>  User-Agent: FreeSWITCH-mod_sofia/1.0.trunk-16981M  Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, UPDATE, INFO, REGISTER, REFER,      NOTIFY, PUBLISH, SUBSCRIBE  Supported: timer, precondition, path, replaces  Reason: Q.850;cause=16;text="NORMAL_CLEARING"  Content-Length: 0

接下来 FreeSWITCH 给 bob 发送 BYE,通知要拆线了。出于对 bob 负责,它包含了挂机缘由(Hangup Cause),此处 NOMAL_CLEARING 表示正常释放。

------------------------------------------------------------------------  recv 367 bytes from udp/[192.168.4.4]:26000 at 13:31:50.111765:  ------------------------------------------------------------------------  SIP/2.0 200 OK  Via: SIP/2.0/UDP 192.168.4.4;rport=5060;branch=z9hG4bKggvjUH0rS99tc  Contact: <sip:bob@192.168.4.4:26000>  To: "Bob"<sip:bob@192.168.4.4>;tag=15c8325a  From: "alice"<sip:alice@192.168.4.4>;tag=cDg7NyjpeSg4m  Call-ID: YWEwYjNlZTZjOWZjNDg3ZjU3MjQ3MTA1ZmQ1MDM5YmQ.  CSeq: 130069219 BYE  User-Agent: X-Lite release 1014k stamp 47051  Content-Length: 0

bob 回送 OK,a-leg 释放完毕,通话结束。从下图能够很形象地看出 FreeSWITCH 的两条“腿”-- a-leg 和 b-leg。

整个呼叫流程图示以下:

bob (UAC)           [ UAS-UAC ]          (UAS) alice   |                     |   |                     |   |   INVITE            |   |                     |   |-------------------->|   |                     |   |   100 Trying        |   |                     |   |<--------------------|   |                     |   |   407 Authentication Required                 |   |<--------------------|   |                     |   |   ACK               |   |                     |   |-------------------->|   |                     |   |   INVITE            |   |                     |   |-------------------->|   |                     |   |   100 Trying        |   |    INVITE           |   |<--------------------<   >-------------------->|   |                     |   |    100 Trying       |   |                     |   |<--------------------|   |   183 Progress      |   |    180 Ringing      |   |<--------------------<   |<--------------------|   |                     |   |    200 OK           |   |                     |   |<--------------------|   |   200 OK            |   |    ACK              |   |<--------------------<   >-------------------->|   |   ACK               |   |                     |   |-------------------->|   |                     |   |                                               |   |                Call Connected                 |   |                                               |   |                     |   |     BYE             |   |                     |   |<--------------------|   |   BYE               |   |    200 OK           |   |<--------------------<   >-------------------->|   |   200 OK            |   |                     |   |-------------------->|   |                     |   |                     |   |                     |

从流程图能够看出,右半部分跟上一节“UA间直接呼叫”同样,而左半部分也相似。这就更好的说明了实际上有 4 个 UA (两对)参与到了通讯中,而且,有两个 Session。


再论 SIP URI

上面咱们介绍了一些 FreeSWITCH 的基本概念,并经过一个真正的呼叫流程讲解了一下 SIP。因为实验中全部 UA 都 运行在一台机器上,这可能会引发迷惑,若是咱们有三台服务器,那么状况多是:

                    /---------------\                      |  FreeSWITCH   |                      |  192.168.0.1  |                      \ --------------/  sip:bob@192.168.0.1    /          \     sip:alice@192.168.0.1                        /            \                       /              \    /-----------------\               /-----------------\    |  bob            |               |  alice          |    |  192.168.0.100  |               |  192.168.0.200  |    \-----------------/               \-----------------/      sip:bob@192.168.0.100                sip:alice@192.168.0.200

alice 注册到 FreeSWITCH,bob呼叫她时,使用她的服务器地址,即 sip:alice@192.168.0.1,FreeSWITCH 接到请求后,查找本地数据库,发现 alice 的实际地址是 sip:alice@192.168.0.200,即可以创建呼叫。

SIP URI 除使用 IP 地址外,也可使用域名,如 sip:alice@freeswitch.org.cn。更高级也更复杂的配置则须要 DNS 的 SRV 记录,在此就不作讨论了。

相关文章
相关标签/搜索