zoukankan      html  css  js  c++  java
  • 直播推流兼容性问题追踪

          好久没有写了。说说最近遇到的一个坑吧。
          很多直播产品都用的librtmp来做rtmp流的传输。
          关于RTMP的协议,在官方文档rtmp_specification_1.0.pdf中有具体的说明。
    首先建立一个RTMP链接,建立链接的步骤先要handshake,需要客户端向服务器发送C0,C1,C2三个RTMP Chunk。
    rtmp_specification_1.0中规定C0是RTMP version,一个字节。目前一般使用的0x03,1和2废弃了,超过4预留。


    C1是1536个字节,由4个字节的时间戳、4个字节的0和1528个字节的随机数组成。
    一般定义#define RTMP_SIG_SIZE 1536


          通常在客户端中C0和C1是同时发送,这里通常的代码是:

    char clientbuf[RTMP_SIG_SIZE + 1], *clientsig = clientbuf + 1;
    //clientbuf中存有C0和C1数据,clientsig只含有C1数据
    char serversig[RTMP_SIG_SIZE];
    // RTMP协议版本号为0x03,即C0数据 
    clientbuf[0] = 0x03; /* not encrypted,没有加密 */
    // 获取系统时间(毫秒为单位),将其写入到C1中,占4个字节
    uptime = htonl(RTMP_GetTime());
    memcpy(clientsig, &uptime, 4);
    // 系统时间之后是4个字节的0,固定的 
    memset(&clientsig[4], 0, 4);
    
    #ifdef _DEBUG
    // debug版,后面的1528个随机数简单的都设为0xff
    for (i = 8; i < RTMP_SIG_SIZE; i++)
    clientsig[i] = 0xff;
    #else
    // release版,使用rand()循环生成1528个伪随机数
    for (i = 8; i < RTMP_SIG_SIZE; i++)
    clientsig[i] = (char)(rand() % 256);
    #endif

          而百度出来结果还一种错误的写法类似,

    conn->clientbuf[0] = 0x03;
    uptime = htonl( RTMP_GetTime() );
    memcpy( conn->clientbuf + 1, &uptime, 4 );
    memset( conn->clientbuf + 4, 0, 4 );
    for( i = 8; i < RTMP_SIG_SIZE; i++ )
    conn->clientbuf[i] = ( char )( rand() % 256 );

          很不幸,我们最初版本的代码就是百度出来的这个版本。
          早期的直播产品使用simple handshake,都没有做握手协议校验。甚至使用了几家CDN也是同样没做校验。
    于是,从未怀疑过这段代码。至少从我接手后,从未改过这几句。

          一次做迅雷星域CDN推流兼容的时候,发现我们的直播产品推流失败。
    进一步查看,发现握手都未成功。抓包后发现C0C1发送后,并未收到服务器发来的S0S1chunk。
    和星域CDN的技术沟通后发现才发现问题所在。
    原来CDN做了simple handshake和complex handshake校验,验证handshake中的C0C1。而我的代码
    C1错位了一个字节。正确的写法如下:

    memcpy( conn->clientbuf + 1, &uptime, 4 );
    memset( conn->clientbuf + 5, 0, 4 );
    
    for( i = 9; i < RTMP_SIG_SIZE; i++ )
    conn->clientbuf[i] = ( char )( rand() % 256 );

    修改后,推流到星域CDN完全没问题了。

    这个问题相信不少人都遇到过。轻易的发布博客或者转帖而没有验证具体代码的执行结果,导致看到博客的人信以为真。为了避免类似的问题,还需要每一个开发者谨慎对待自己发出去的技术博客。我的每篇博客都是自己验证了代码的。

  • 相关阅读:
    Metasploit命令大全
    nmap所有参数详解
    Kali Linux 命令集
    十大编程算法助程序员走上大神之路
    新入行程序员需要知道的十个秘密
    浅谈c#枚举
    php 常用的系统函数
    php大型网站如何提高性能和并发访问
    【转】Oracle + PHP Cookbook(php oracle clob 长度超过4000如何写入)
    干货:小程序开发文档和设计指南要点详解
  • 原文地址:https://www.cnblogs.com/zzugyl/p/6676549.html
Copyright © 2011-2022 走看看