一、握手:
1、C0:C—>S
2、S0: S—>C
名称:C0 S0
长度:1字节
对于版本号的定义:当前rtmp协议的版本号一致为“3”,0、1、2是旧版本号,已经弃用。4-31被保留为rtmp协议的未来实现版本使用;32-255不允许使用。如果服务器端或者客户端收到的C0字段解析出为非03,如果是0x06考虑使用openssl进行解密C1 C2 S1 S2,如果对端不支持加密字段可以选择以版本3来响应,也可以放弃握手。
简单握手:
作用:C0和S0一致,都是一个字节,都代表当前使用的rtmp协议的版本号。如果服务器端或者客户端收到的C0/S0字段解析出为非03,对端可以选择以版本3来响应,也可以放弃握手。
复杂握手:
作用:说明是明文还是密文。如果使用的是明文(0X03),同时代表当前使用的rtmp协议的版本号。如果是密文,该位为0x06
3、C1: C—>S
4、S1: S—>C
名称:C1 & S1
长度:1536字节
简单握手:
作用:
包结构:
time(4字节)+zero(4字节)+ random data(1528字节)。
Time(4字节):这个字段包含一个timestamp,用于本终端发送的所有后续块的时间起点。这个值可以是0,或者一些任意值。要同步多个块流,终端可以发送其他块流当前的timestamp的值,以此让当前流跟要同步的流保持时间上的同步。
Zero (4个字节):这个字段必须都是0。如果不是0,代表要使用complex handshack。
Random data (1528个字节):这个字段可以包含任意值。终端需要区分出响应来自它发起的握手还是对端发起的握手,这个数据应该发送一些足够随机的数。这个不需要对随机数进行加密保护,也不需要动态值。
复杂握手:
作用:用于验证服务器端或者client端的有效性。
包结构:
time(4字节)+version(4字节)+key(764字节)+digest(764字节)。总共1536字节
其中,key和digest可能会交换位置,也就如下图有两种格式:schemal0&schemal1。
客户端决定使用哪种schema方式,服务器端比较倒霉,需要将两种方式都尝试,一般是先按照schema0解析,失败则使用schema1解析。但是无论key和digest位置如何,它们的结构是不变的。
Time(4字节):这个字段包含一个timestamp,用于本终端发送的所有后续块的时间起点。这个值可以是0,或者一些任意值。要同步多个块流,终端可以发送其他块流当前的timestamp的值,以此让当前流跟要同步的流保持时间上的同步。
Version(4个字节):4bytes 为程序版本。C1一般是0x80000702。S1是0x04050001。貌似这个可以随意填写,但是要采用非0值跟simple handshack区分。
Key(764个字节):
random-data:长度由这个字段的最后4个byte决定,即761-764
key-data:128个字节。Key字段对应C1和S1有不同的算法,这个需要注意。后面会详细解释。发送端(C1)中的Key应该是随机的,接收端(S1)的key需要按照发送端的key去计算然后返回给发送端。
random-data:(764-offset-128-4)个字节
key_offset:4字节, 最后4字节定义了key的offset(相对于KeyBlock开头而言,相当于第一个random_data的长度)
Digest(764个字节):
offset:4字节, 开头4字节定义了digest的offset(相对于DigestBlock的第5字节而言,offset=3表示digestBlock[7~38]为digest,【4-6】即为第一个random_data)
random-data:长度由这个字段起始的4个byte决定
digest-data:32个字节。Digest字段对应C1和S1有不同的算法,这个需要注意。后面会详细解释。
random-data:(764-4-offset-32)个字节
算法:
C1的key为128bytes随机数。C1_32bytes_digest= HMACsha256(P1+P2, 1504, FPKey, 30) ,其中P1为digest之前的部分,P2为digest之后的部分,P1+P2是将这两部分拷贝到新的数组,共1536-32长度。S1的key根据 C1的key算出来。
S1的digest算法同C1。注意,必须先计算S1的key,因为key变化后digest也重新计算。
5、C2: c—>s
6、S2: s—>c
名称:C2 & S2
长度:1536字节。
简单握手:
作用:基本是C1&S1的副本
包结构:
time(4字节)+ Time2(4字节)+randomecho(1528字节)。
Time(4个字节):这个字段必须包含终端在S1 (给 C2) 或者 C1 (给 S2) 发的 timestamp。
Time2 (4个字节):这个字段必须包含终端先前发出数据包 (s1 或者 c1) timestamp。
Randomecho (1528个字节):这个字段必须包含终端发的 S1 (给 C2) 或者 S2 (给 C1) 的随机数。两端都可以一起使用 time 和 time2 字段再加当前 timestamp 以快速估算带宽和/或者连接延迟,但这不太可能是有多大用处。
复杂握手:
作用:主要是用来提供对C1 S1的验证
包结构: