目录
【1】SIP 协议简介
SIP (会话初始协议) 是用于发起、控制、终结多媒体会话 (会话,Internet 的许多应用都需要建立和管理一个会话,会话是参与者之间的数据交换) 的信令协议,SIP 独立运行于通讯协议之下,并且不依赖建立的会话类型;
SIP 协议是 IETF 致力于将电话服务带入 IP 网络众多协议的一个组成部分 (与 SDP、RTP、RTCP、RTSP、RSVP、TRIP 等众多协议构成 SIP 系统协议栈);
SIP 协议允许使用 Internet 端点 (用户代理) 来寻找参与者并且允许建立一个可共享的会话描述;为了能够精确的定位会话参与者,SIP 允许创建基础的 network hosts (代理服务器),并且允许终端用户注册上去,发出会话邀请或者发出其他请求;
【2】SIP 协议功能概述
SIP 是一个应用层的控制协议,用于建立、修改、终止多媒体会话;SIP 可以邀请参与者参加已经存在的会话;媒体可以在一个已经存在的会话中方便地增加 (删除);
SIP 协议主要支持 5 个方面
1. 用户定位,检查终端用户的位置,用于通讯
2. 用户有效性,检查用户参与会话的意愿程度
3. 用户能力,检查媒体和媒体的参数
4. 建立会话,“振铃” 在被叫和主叫方建立会话参数
5. 会话管理,包括发送和终止会话,修改会话参数,激活服务等
注意,SIP 应该和其他的协议协作才能提供完整的对终端用户的服务
文章福利:【免费】FFmpeg/WebRTC/RTMP/NDK/Android音视频流媒体高级开发-学习视频教程-腾讯课堂
【3】SIP 中的主要概念
SIP 协议模型定义了 User Agent 和 Server 两类主要实体
SIP User Agent
SIP 协议把 User Agent (即 UA) 分为两个部分,User Agent Client 和 User Agent Server
呼叫方 (User Agent Client) 发出邀请 (呼叫)
被叫方 (User Agent Server) 接受或拒绝邀请 (呼叫)
SIP Server
代理服务器 (Proxy Server)
Proxy Server 作为 UAC 和 UAS 间的中间媒体,负责转发 UAC 发来的的邀请,在转发之前,根据被叫标识的请求位置服务器获得被叫的可能位置,然后分别发出邀请
重定向服务器 (Redirect Server)
Redirect Server 接受 UAC 发送的邀请,根据被叫标识的请求位置服务器获得被叫的可能位置,把这些信息返回给邀请的发起者 (UAC)
和 Proxy Server 的不同之处就在于其不转发邀请,邀请由主叫终端自己完成
注册服务器 (Register Server)
用于登记终端的当前位置和位置服务的原始数据
背靠背用户代理 (Back to Back)
仅仅是一对 UAS 和 UAC 的串联
【4】SIP 协议会话建立的基本过程
1. 注册,发起和定位用户
2. 进行媒体协商,通常采用 SDP 协议来携带媒体参数
3. 由被叫方来决定是否接纳该呼叫
4. 呼叫媒体流量建立并交互
5. 呼叫更改或处理
6. 呼叫终止
【5】SIP 交互详细流程分析
【5.1】注册流程
1. 终端发起请求时如果服务器端需要对用户进行认证,那么会在本地产生本次认证的 NONCE 并且通过认证请求头域 (Authorization) 将所有必要的参数返回给终端从而发起对用户的认证过程
2. 终端收到认证请求消息后根据服务器端返回的信息和用户配置等信息采用特定的算法生成加密的 RESPONSE 并且通过新的请求消息发送给服务器端
3. 服务器端在收到带有认证响应的新的请求消息后首先检查 NONCE 的正确性
如果 NONCE 不是本地产生则直接返回失败;
如果 NONCE 是本地产生,但是认证过程已经超时,则服务器端会重新产生 NONCE 并重新发起对用户的认证过程,其中老的 NONCE 会通过 CNONCE 参数返回;
4. NONCE 验证通过后服务器端会根据 NONCE、用户名、密码、URI 采用和终端相同的算法生成 RESPONSE 并且对此 RESPONSE 和请求消息中的 RESPONSE 进行比较,如果二者一致则用户认证成功,否则认证失败
【5.2】注销流程
1. 终端向代理服务器送 Register 消息注销,其中 expire 字段置 0
2. 代理服务器收到后回送 200 OK 响应,并将数据库中的用户有关信息注销
【5.3】基本呼叫流程
1. 用户摘机发起一路呼叫,终端代理 A 向该区域的代理服务器发起 Invite 请求
2. 代理服务器通过认证/计费中心确认用户认证已通过后,检查请求消息中的 Via 头域中是否已包含其地址
若已包含,说明发生环回,返回指示错误的应答;
若没有问题,代理服务器在请求消息的 Via 头域插入自身地址,并向 Invite 消息的 To 域所指示的被叫终端代理 B 转送 Invite 请求;
3. 代理服务器向终端代理 A 发送呼叫处理中的应答消息,100 Trying
4. 终端代理 B 向代理服务器发送呼叫处理中的应答消息,100 Trying
5. 终端代理 B 指示被叫用户振铃,用户振铃后,向代理服务器发送 180 Ringing 振铃信息
6. 代理服务器向终端代理 A 转发被叫用户振铃信息
7. 被叫用户摘机,终端代理 B 向代理服务器返回表示连接成功的应答 (200 OK)
8. 代理服务器向终端代理 A 转发该成功指示 (200 OK)
9. 终端代理 A 收到消息后,向代理服务器发 ACK 消息进行确认
10.代理服务器将 ACK 确认消息转发给终端代理 B
11.主被叫用户之间建立通信连接,开始通话
【5.4】会话更改流程
2. 用户代理服务端向用户代理客户端发送 Inivte 消息,带有新的 SDP 协商信息
3. 用户代理客户端回复 200 OK,并将协商后的 SDP 信息带回
4. 用户代理服务端发送 ACK 给用户代理客户端进行确认
【5.5】正常呼叫释放过程
2. 用户通话结束后,被叫用户挂机,终端代理 B 向代理服务器发送 Bye 消息
3. 代理服务器转发 Bye 消息至终端代理 A,同时向认证/计费中心送用户通话的详细信息,请求计费
4. 主叫用户挂机后,终端代理 A 向代理服务器发送确认挂断响应消息 200 OK
5. 代理服务器转发响应消息 200 OK
【5.6】被叫忙呼叫释放
1. 用户 A 发起一路呼叫,终端代理 A 向代理服务器发送 Invite 请求
2. 代理服务器收到呼叫请求后向被叫终端代理转发该 Invite 消息
3. 代理服务器向终端代理 A 回送 100 Trying,告知终端代理 A 呼叫正在处理
4. 终端代理 B 向代理服务器回送 100 Trying,告知代理服务器呼叫正在处理
5. 呼叫请求送到被叫终端代理 B 后,被叫忙,终端代理 B 向代理服务器送 486 被叫忙响应
6. 代理服务器向终端代理 A 转发该响应消息
7. 终端代理 A 向代理服务器回送 ACK 确认消息
8. 代理服务器向终端代理 B 送 ACK 确认消息
【5.7】被叫无应答流程 (一)
1. 用户 A 发起一路呼叫,终端代理 A 向代理服务器发 Invite 请求消息
2. 代理服务器向被叫用户的终端代理 B 转发该 Invite 请求
3. 代理服务器向终端代理 A 回送 100 Trying 响应,表示呼叫已在处理中
4. 终端代理 B 向代理服务器回送 100 Trying 告知代理服务器呼叫正在处理
5. 被叫用户振铃,终端代理 B 向代理服务器送 180 Ring 响应
6. 代理服务器向终端代理 A 转发该响应消息
7. 被叫久振铃无应答,终端代理 A 判断超时后,向代理服务器送 Cancel 消息放弃该呼叫
8. 代理服务器收到 Cancel 消息后,向终端代理 A 回送 200 OK 响应
9. 代理服务器将 Cancel 消息转发给终端代理 B
10.终端代理 B 向代理服务器回送 200 OK 响应
11.终端代理 B 向代理服务器送 487 请求已撤销的响应消息
12.代理服务器收到后回送 ACK 确认
13.代理服务器向终端代理 A 送 487 请求已撤销消息
14.终端代理 A 向代理服务器回送 ACK 确认
【5.8】被叫无应答流程 (二)
1. 用户 A 发起一路呼叫,终端代理 A 向代理服务器发 Invite 请求消息
2. 代理服务器向被叫用户的终端代理 B 转发该 Invite 请求
3. 代理服务器向终端代理 A 回送 100 Trying 响应,表示呼叫已在处理中
4. 终端代理 B 向代理服务器回送 100 Trying 告知代理服务器呼叫正在处理
5. 被叫用户振铃,终端代理 B 向代理服务器送 180 Ring 响应
6. 代理服务器向终端代理 A 转发该响应消息
7. 被叫久振铃无应答,终端代理 B 判断超时后,向代理服务器送 408 Request timeout 消息放弃该呼叫
8. 代理服务器收到 408 Request timeout 消息后,转发该消息给终端代理 A
9. 代理服务器收到后回送 ACK 确认给终端代理 B
10.终端代理 A 向代理服务器回送 ACK 确认
【5.9】遇忙呼叫前转
1. 用户 A 发起一路呼叫,终端代理 A 向代理服务器发 Invite 请求消息
2. 代理服务器向被叫用户的终端代理 B 转发该 Invite 请求
3. 代理服务器向终端代理 A 回送 100 Trying 响应,表示呼叫已在处理中
4. 终端代理 B 向代理服务器回送 100 Trying 告知代理服务器呼叫正在处理
5. 终端代理 B 忙线中,终端代理 B 向代理服务器送 486 Busy here 响应
6. 代理服务器向终端代理 B 发送 ACK 响应消息
7. 代理服务器对此呼叫进行前转,向终端代理 C 发送 Invite 请求消息
8. 代理终端 C 收到 Inivte 请求后,指示用户振铃,同时向代理服务器发送 180 Ringing 响应
9. 代理服务器向代理终端 A 转发收到的 180 Ringing 响应
10.被叫用户 C 摘机接听电话,代理终端 C 向代理服务器发送 200 OK 响应
11.代理服务器向代理终端 A 转发收到的 200 OK 响应
12.终端代理 A 向代理服务器回送 ACK 确认
13.代理服务器向代理终端 C 转发收到的 ACK 确认
双方开始通话
14. 主叫挂机,代理终端 A 向代理服务器发送 BYE 请求消息,请求挂机
15. 代理服务器向代理终端 C 转发收到的 BYE 请求消息,指示用户 C 挂机
16. 用户 C 放崔挂音,同时向代理服务器回应 200 OK 响应
17. 代理服务器向代理终端转发收到的 200 OK 响应
【5.10】无应答呼叫前转流程
1. 用户 A 发起一路呼叫,终端代理 A 向代理服务器发 Invite 请求消息
2. 代理服务器向被叫用户的终端代理 B 转发该 Invite 请求
3. 代理服务器向终端代理 A 回送 100 Trying 响应,表示呼叫已在处理中
4. 终端代理 B 向代理服务器回送 100 Trying 告知代理服务器呼叫正在处理
5. 被叫用户振铃,终端代理 B 向代理服务器送 180 Ring 响应
6. 代理服务器向终端代理 A 转发该响应消息
7. 被叫久振铃无应答,代理服务器判断超时后,向代理终端 B 发送 Cancel 消息放弃该呼叫
8. 代理终端 B 收到 Cancel 消息后,向代理服务器回送 200 OK 响应
9. 终端代理 B 向代理服务器送 487 请求已撤销的响应消息
10.代理服务器收到后回送 ACK 确认
11.代理服务器对此呼叫进行前转,向终端代理 C 发送 Invite 请求消息
12.代理终端 C 收到 Inivte 请求后,指示用户振铃,同时向代理服务器发送 180 Ringing 响应
13.代理服务器向代理终端 A 转发收到的 180 Ringing 响应
14.被叫用户 C 摘机接听电话,代理终端 C 向代理服务器发送 200 OK 响应
15.代理服务器向代理终端 A 转发收到的 200 OK 响应
16.终端代理 A 向代理服务器回送 ACK 确认
17.代理服务器向代理终端 C 转发收到的 ACK 确认
双方开始通话
18.主叫挂机,代理终端 A 向代理服务器发送 BYE 请求消息,请求挂机
19.代理服务器向代理终端 C 转发收到的 BYE 请求消息,指示用户 C 挂机
20.用户 C 放崔挂音,同时向代理服务器回应 200 OK 响应
21.代理服务器向代理终端转发收到的 200 OK 响应
【5.11】呼叫保持
1. 用户摘机发起一路呼叫,终端代理 A 向该区域的代理服务器发起 Invite 请求
2. 代理服务器通过认证/计费中心确认用户认证已通过后,检查请求消息中的 Via 头域中是否已包含其地址
若已包含,说明发生环回,返回指示错误的应答;
如果没有问题,代理服务器在请求消息的 Via 头域插入自身地址,并向 Invite 消息的 To 域所指示的被叫终端代理 B 转送 Invite 请求
3. 代理服务器向终端代理 A 发送呼叫处理中的应答消息,100 Trying
4. 终端代理 B 向代理服务器发送呼叫处理中的应答消息,100 Trying
5. 终端代理 B 指示被叫用户振铃,用户振铃后,向代理服务器发送 180 Ringing 振铃信息
6. 代理服务器向终端代理A 转发被叫用户振铃信息
7. 被叫用户摘机,终端代理 B 向代理服务器返回表示连接成功的应答 (200 OK)
8. 代理服务器向终端代理 A 转发该成功指示 (200 OK)
9. 终端代理 A 收到消息后,向代理服务器发 ACK 消息进行确认
10.代理服务器将 ACK 确认消息转发给终端代理 B
11.主被叫用户之间建立通信连接,开始通话
12.代理终端 B 向代理服务器发送 Reinvite 请求消息,SDP 的 c 域等于 0.0.0.0
13.代理服务器转发此消息给代理终端 A
14.代理终端 A 收到 Reinvite 后,回应 200 OK 响应,表示接受会话更改,同时根据协商结果修改会话方式
15.代理服务器转发 200 OK 给代理终端 B
16.终端代理 B 收到消息后,向代理服务器发 ACK 消息进行确认
17.代理服务器将 ACK 确认消息转发给终端代理 A
【5.12】通话的保持与恢复
2. 用户 A, B 正处于通话阶段,用户 C 向 A 发起呼叫,终端代理 C 发送 Invite 消息给代理服务器
3. 代理服务器向终端代理 C 回送 100 Trying 响应,表示呼叫已在处理中
4. 代理服务器把 Invite 消息转发给代理终端 A
5. 用户 A 振铃,终端代理 A 向代理服务器送 180 Ring 响应
6. 代理服务器向终端代理 C 转发该响应消息
7. 用户 A 按下呼叫保持键,代理终端 A 向代理服务器发送 Invite 消息,请求与代理终端呼叫保持
8. 代理服务器转发此消息给终端代理 B
9. 代理服务器向终端代理 A 回送 100 Trying 响应,表示呼叫已在处理中
10.终端代理 B 收到呼叫保持请求后,发送 200 OK 给代理服务器,表示接受呼叫保持
11.代理服务器转发 200 OK 响应给终端代理 A
12.终端代理 A 向代理服务器回送 ACK 确认
13.代理服务器向代理终端 B 转发收到的 ACK 确认
14.终端代理 A 发送 200 OK 给代理服务器,表示接受 C 的呼叫
15.代理服务器转发 200 OK 响应给终端代理 C
16.终端代理 C 向代理服务器回送 ACK 确认
17.代理服务器向代理终端 A 转发收到的 ACK 确认
A ,C 之间开始通话
18.用户 A 挂机,终端代理 A 向代理服务器发送 Bye 请求消息
19.代理服务器转发 Bye 消息给终端代理 C
20.终端代理 C 发送 200 OK 给代理服务器,表示接受请求
21.代理服务器转发 200 OK 响应给终端代理 A
22.终端代理 A 重新发送 Inivte 请求给代理服务器,请求和终端代理 B 恢复通话
23.代理服务器向代理终端 B 转发收到的 Invite 请求
【6】SIP 协议消息格式
消息格式SIP 协议是一个基于文本的协议,使用 UTF-8 字符集;一个 SIP 消息既可以是一个从客户端到服务器端的请求,也可以是一个从服务器端到客户端的一个应答;
这两种消息类型都由一个起始行,一个或者多个包头域,一个标志消息头结束的空行 (CRLF),一个可选的消息体组成;
起始行请求行 (Request-Line)
由方法名,请求目的发送地址 Request-URI,SIP 协议的版本号 (之间用空格隔开)
Request-Line = Method SP Request-URI SP SIP-Version CRLF (SP,a single space character;CRLF,回车)
请求行包含 6 种请求方法
INVITE,用于发起呼叫请求;
INVITE 消息包括消息头和数据区两部分
INVITE 消息头包含主、被呼叫的地址,呼叫主题和呼叫优先级等信息
INVITE 数据区则是关于会话媒体的信息,可由会话描述协议 SDP 来实现
BYE,用于中止会话OPTIONS,用于询问被叫端的能力信息,但 OPTIONS 本身并不能发起呼叫
ACK,对已收到的消息进行确认应答
REGISTER,用于用户向 SIP 服务器传送位置信息或地址信息
CANCEL,取消当前的请求,但并不能中止已经建立的连接
状态行 (Status-Line)由 SIP-Version,状态码 Status-Code,与状态码相关的描述性短语 Reason-Phrase 组成
Status-Line = SIP-Version SP Status-Code SP Reason-Phrase CRLF (SP,空格;CRLF,回车)
SIP 应答消息的六类应答状态编码1xx : 临时消息,表示请求消息已经收到,后面将继续处理该请求
2xx : 成功消息,表示请求已经被成功的理解、接受或执行
3xx : 重定向消息,表示为了完成请求还需采取更进一步的动作
4xx : 客户机错误,表示该请求含有语法错误或在这个服务器上不能被满足
5xx : 服务器错误,表示该服务器不能处理一个明显有效的请求
6xx : 全局性故障,表示该请求在任何服务器上都不能被实现
消息头消息头的作用是进一步提供有关消息的其他信息,使代理服务器或客户代理服务器更好地对消息进行处理;
消息头格式每个消息头都是一个“句子”,以 CRLF 行结束符表示一个头域的结束;由字段名 (field-name) 和域值 (field-value) 两部分组成,中间以 “:” 相隔
消息头分类通用头 (general-header)
描述消息基本属性的通用头域,可用于请求消息和应答消息;
包含属性 : Call-ID,From,To,Via,Contact,CSeq,Encryption,Expires,Record-Route,Timestamp,Date,Accept,Accept-Encoding,Accept-Language
请求头 (request-header)
请求头域,只可用于请求消息,被用来传递有关请求的附加信息,对请求进行补充说明
包含属性 : Subject,User-Agent,Organization,Contact,Authorization,Proxy-Authorization,Proxy-Require,Response-Key,Require,Priority,Hide,Route,Max-Forwards
响应头 (response-header)
应答头域,只可用于应答消息,被用来传递有关应答的附加信息,对应答进行补充说明
包含属性 : Proxy-Authenticate,WWW-Authenticate,Retry-After,Server,Warning,Allow,Unsupported
实体头 (entityheader)
消息体头域,用于描述消息体内容的长度、格式和编码类型等属性,可用于请求消息或应答消息
包含属性 : Content-Encoding,Content-Length,Content-Type
常见消息头说明TO
格式,TO:显示名<接收者 URI>;tag=n; 显示名和 tag 可选;接收者 URI 是 SIP 网络中唯一标识接收终端的标识符;
例,TO:DENNY<SIP:[email protected]>;TAG=11111 或 TO:sip:[email protected]
FROM
消息头 FROM 给出标识会话发起者的 URI;
例,FROM:sip:[email protected];tag=hyh8,tag 是必需的
CALL-ID
用于全局唯一标识一个请求或客户端所有的注册,随机数加 UAC 标识信息
CSeq
用于标识同一会话中不同事务的序号,通常由一个用作序号的整型数和消息类型组成,整个会话操作过程由不同的事务组成,每一事务所涉及的消息的 CSeq 序号必须相同
Via
为响应消息提供传输路径,当请求消息经过每一跳节点时,每一跳节点都把自身的 IP 地址信息放入顶层 Via 中;响应消息则沿着请求消息记录下的传输路径反向传输,首先移走指明自身 IP 地址信息的顶层消息头
消息体消息体的类型由消息头中的 Content-Type 域指定
消息体的长度由消息头中的 Content-Length 域指定