一个数据源可能发现自己的或者别人的报文被循环发送了。无论是报文循环还是 SSRC 的碰撞都会导致同一个现象,即 SSRC 相同但是传输地址不同的报文。因此,如果数据源改变了自己的传输地址,那它就需要同时改变自己的 SSRC 来避免被检测成环形报文。有一个需要注意的内容是,如果一个 Translator 再重启的过程中改变了自己的传输地址,那么这个 Translator 转发的所有数据都会被检测成环。这类情况的解决方案一般有如下两个:
重启的时候不改变传输地址。
接收者的超时机制。
如果循环或者碰撞发生在离 Translator 和 Mixer 很远的地方,我们就不能通过传输地址来发现。但是我们仍然可以通过 CNAME 的不同来发现 SSRC 碰撞。
为了解决上述问题,RTP 的实现必须包含一个类似如下的算法。这个算法不包括多个数据源 SSRC 碰撞的情况,这类情况通常下都是先用原来的 SSRC 发送一个 BYE 然后重新选择一个新的 SSRC。
这个算法需要维护一个 SSRC 和传输地址的映射关系。因为 RTP 的数据和 RTCP 传输使用的是两个不同的端口,所以一个 SSRC 对应的是两个传输地址。
每次收到 RTP 报文和 RTCP 报文都会将其 SSRC 和 CSRC 在上述的表中进行比对。如果发现了传输地址对不上的情况,我们就可以说发现了一个循环或者碰撞。对于 RTCP 数据来说,可能每个数据块都有自己独立的 SSRC,比如 SDES 数据,对于这种情况就需要分别比对。如果没有在表中找到这个 SSRC 或者 CSRC,就需要新添加一项。当收到 BYE 报文时,需要先比对这个 BYE 的传输地址,如果传输地址匹配上了,就将这一项从表中删除。或者基于超时机制,将超时的数据从表中移除。
为了追踪自己的数据报文循环情况,必须维护另一个列表,这个表存储冲突报文的传输地址和收到该报文的时间。如果超过 10 个 RTCP 周期都没有收到这个传输地址的冲突报文,就将该项从表中删除。
下面的算法还假设参与者自己的 SSRC 和状态都包含在 SSRC 表中,它会先比对自己的 SSRC。
if (SSRC or CSRC identifier is not found in the source identifier table) { create a new entry storing the data or control source transport address, the SSRC or CSRC and other state; } /* Identifier is found in the table */ else if (table entry was created on receipt of a control packet and this is the first data packet or vice versa) { store the source transport address from this packet; } else if (source transport address from the packet does not match the one saved in the table entry for this identifier) { /* An identifier collision or a loop is indicated */ if (source identifier is not the participant's own) { /* OPTIONAL error counter step */ if (source identifier is from an RTCP SDES chunk containing a CNAME item that differs from the CNAME in the table entry) { count a third-party collision; } else { count a third-party loop; } abort processing of data packet or control element; /* MAY choose a different policy to keep new source */ } /* A collision or loop of the participant's own packets */ else if (source transport address is found in the list of conflicting data or control source transport addresses) { /* OPTIONAL error counter step */ if (source identifier is not from an RTCP SDES chunk containing a CNAME item or CNAME is the participant's own) { count occurrence of own traffic looped; } mark current time in conflicting address list entry; abort processing of data packet or control element; } /* New collision, change SSRC identifier */ else { log occurrence of a collision; create a new entry in the conflicting data or control source transport address list and mark current time; send an RTCP BYE packet with the old SSRC identifier; choose a new SSRC identifier; create a new entry in the source identifier table with the old SSRC plus the source transport address from the data or control packet being processed; } } 层级编码对于不同 Session 的层级编码传输,一般都是所有层都使用同一个 SSRC,如果其中某一层发现了 SSRC 冲突,那么只改变这一层的 SSRC,而且他层的 SSRC 不做改变。
安全下层协议可能会提供 RTP 应用所需要的所有安全服务,包括认证,数据完整性,数据保密性。这些服务在 IP 协议中都有解决方案。因为 Audio 和 Video 初始化过程中需要数据加密,而这时候 IP 协议这一层的安全服务还没有提供。所以,RTP 需要实现一个 RTP 专用的保密服务。这个保密服务是非常轻量级的,而且保密部分的服务向后兼容,以后可以随时进行更换。或者,某些预设会提供这部分加密服务,比如 SRTP(Secure Real-time Transport Protocol),SRTP 是基于 Advanced Encryption Standard (AES) 提供了一个比 RTP 默认加密服务更强大的实现。
保密性保密性是指我们的报文只希望一些特定的接收者可以解码成明文,而其他人只能得到无用的信息,保密性是通过加密编码来提供的。