ROAP
ROAP 就是 RTCWeb Offer/Answer Protocol 实时网页提议应答协议
这是一个新协议, 目的是为了搭建媒体通道, 由思科,谷歌及Mozilla的几位工程师提出, 还在草案阶段, 并未正式发布.
这本应该是 SIP(Session Initiation Protocol) 协议之所长, 为什么不是 SIP, 我想还是在于 SIP 太重了
WebRTC所提供的 API 本来就比较简单, 没必要为了搭媒体就引入 SIP 这样复杂的一个协议.
先看下在 SIP 中如何搭建媒体通道
Web一般是基于HTTP的, 为什么不能简单地通过 HTTP request/response 来协商搭建媒体通道呢
主要是因为搭建媒体通道需要协商很多参数
这种协商需要一个讨价还价和确认的过程, 所以需要三步, 而不能仅仅一来一回两条消息, 例如
- 张三问李四水果一斤多少钱, 2) 李四说苹果三元, 桔子四元, 香蕉五元, 3) 张三说那就来斤苹果吧
消息 Messages
-
提议 Offer
{ "messageType":"OFFER", "offererSessionId":"13456789ABCDEF", "seq": 1, "sdp":" v=0\n o=- 2890844526 2890842807 IN IP4 192.0.2.1\n s= \n c=IN IP4 192.0.2.1\n t=2873397496 2873404696\n m=audio 49170 RTP/AVP 0" }
-
应答 Answer
{ "messageType":"ANSWER", "offererSessionId":"13456789ABCDEF", "answererSessionId":"abc1234356", "seq": 1, "sdp":" v=0\n o=- 2890844526 2890842807 IN IP4 192.0.2.3\n s= \n c=IN IP4 192.0.2.3\n t=2873397496 2873404696\n m=audio 49175 RTP/AVP 0" }
-
确认 Confirm
{ "messageType":"OK", "offererSessionId":"13456789ABCDEF", "answererSessionId":"abc1234356", "seq": 1 }
通过以上的消息交互流程, 最终协商出 在 192.0.2.1:49170 和 192.0.2.3:49175 之间传输 audio , codec 是 PCMU (g.711 u-law)
ROAP 消息一般都通过可靠的通道传输, 比如通过 XMLHttpRequst 或者 WebSocket 承载的 HTTP 消息
通用字段
会话标识 Session IDs
Each call is identified by a pair of session identifiers:
每个呼叫由一对 ID 来标识, 要求它们是全局唯一的, 所有的消息都要有 offererSessionId, 响应式消息都还要有 answererSessionId
- offererSessionId
- answererSessionId
序列号 Seq
消息的序列编号, 是一个32位的无符号整数, 每个新的 Offer 都会加1
会话令牌 Session Tokens
session ID用来唯一标识一个session, session token则用标识一个会话的生命周期
如收到带有 setSessionToken 的字段则以 sessionToken 回应, 没有则忽略
Response Tokens
response token则用标识一个请求/应答的生命周期
如收到带有 setResponseToken 的字段则以 responseToken 回应, 没有则忽略
媒体通道搭建过程 Media Setup
上图显示了用于媒体协商的简单消息流:
提议者发送 OFFER 来发起呼叫; 此时,ICE协商开始;
一旦浏览器授权向远端发送媒体,应答者就发送包含媒体参数的 ANSWER;
最后,一旦 ICE 完成并收到对于 ANSWER 的 OK 消息,双方就都知道媒体通道搭建成功了。
Offer 消息
第一个OFFER消息包含一个给定的 offererSessionId, 它用来指示期望开始一个媒体会话
Offerer 行为
为了开始一个新的媒体会话,提议者使用新的 offerefereSessionId 来构造一个新的OFFER消息。 这时 answererSessionId 字段必须为空。 像所有SDP Offer 的那样,消息体必须包含一个带有提议者所提议的“sdp”字段。 它还必须包含 tieBreaker字段,包含一个用于解决冲突的32位随机整数 ( ROAP 中称冲突的 OFFERS 为 glare)
Answerer 行为
一个回应者可以在以下三种情况下收到一个提议 OFFER:
- 一个新的会话(通过查看是否有新的 offerefereSessionId 值来检测;
- 一个新的 OFFER的重传(已知的 offererSessionId,空的answererSessionId;
- 一个更改媒体参数的请求(已知 offererSessionId,已知的 answererSessionId,新的 seq值)。
除了上述三种情况, 任何其他条件所表示的外来数据包应被拒绝为错误:NOMATCH
如果不存在具有给定 “offererSessionId” 值的媒体会话,那么这就是新的媒体会话。 回应者有以下三个主要的选项:
- 拒绝请求,或者不回响应, 或者回复错误:REFUSED消息;
- 使用最终的 ANSWER 消息来回复OFFER消息;
- 先回复非最终的 ANSWER消息,然后再回复最终的 ANSWER 响应。
在后而两者中的任何一种情况下,回应者执行以下步骤:
- 生成一个 “answererSessionId”值;
- 创建一些本地呼叫状态 call state(即 PeerConnection对象)并将其绑定到 “offererSessionId/answererSessionId” 这一对值上面。 此会话中后续的所有消息必须传递给该PeerConnection对象;
- 与提议者开始 ICE 握手; 最后,
4.在 “sdp” 字段中回复包含 SDP 响应的消息, 包含回应者(可能带有 moreComing = true)媒体信息和ICE参数。
如果收到一个在这之前已经收到并回复的 OFFER, 并且媒体会话仍然存在,那么回应者必须
回复与以前相同的消息。 如果会话已在此期间终止,则应回复 Error:NOMATCH消息。
Answer 消息
OFFER 消息的接收者使用ANSWER消息来指示该提议已被接受。 ANSWER消息必须包含该媒体会话的 answererSessionId , ICE候选者的 sdp参数, 以及会话的最终媒体参数(当然这些参数可以通过新的OFFER / ANSWER交换进行调整)
此外,ANSWER可以包含moreComing标志,如下所述。
- moreComing Flag
这个flag表示这个应答消息是否为最终响应, moreComing=true代表此应答消息不是最终响应, 默认为false
OK
无错响应ERROR
有错响应
媒体通道冲突协商流程
媒体通道关闭流程
提示 Hints
当在浏览器中创建对端连接时, 应用程序需要能提供可选的媒体选项提示, 以供协商
- 是否会议包含音频,视频,或者二者都有
- 音频是语音还是音乐
- 期望的视频精度和帧率 (或许就从 MediaTrack 对象中获取);
- 是否视频有期望的时间或空间精度;
- 等等
参考链接
- ROAP protocol
- An Offer/Answer Model with the Session Description Protocol (SDP)
- RTP Profile for Audio and Video Conferences with Minimal Control
- SDP: Session Description Protocol
- WebRTC introduction
- WebRTC basic tutorial
- WebRTC infrastructure tutorial