WebRTC的ICE之STUN协议

ICE、STUN、媒体协商

Posted by chensong on 2022-05-20 17::29::37

WebRTC源码之视频质量统计数据的数据结构分析

WebRTC专题开嗨鸭 !!!

一、 WebRTC 线程模型

1、WebRTC中线程模型和常见线程模型介绍

2、WebRTC网络PhysicalSocketServer之WSAEventselect模型使用

二、 WebRTC媒体协商

1、WebRTC媒体协商之SDP中JsepSessionDescription类结构分析

三、 WebRTC 音频数据采集

1、WebRTC源码之音频设备播放流程源码分析

2、WebRTC源码之音频设备的录制流程源码分析

四、 WebRTC 音频引擎(编解码和3A算法)

五、 WebRTC 视频数据采集

六、 WebRTC 视频引擎( 编解码)

七、 WebRTC 网络传输

1、WebRTC的ICE之STUN协议

2、WebRTC的ICE之Dtls/SSL/TLSv1.x协议详解

八、 WebRTC服务质量(Qos)

1、WebRTC中RTCP协议详解

2、WebRTC中RTP协议详解

3、WebRTC之NACK、RTX 在什么时机判断丢包发送NACK请求和RTX丢包重传

4、WebRTC源码之视频质量统计数据的数据结构分析

九、 NetEQ

十、 Simulcast与SVC

前言

WebRTC是音视频行业的标杆, 如果要学习音视频, WebRTC是进入音视频行业最好方法, 里面可以有成熟方案, 例如:音频中3A 算法、网络评估、自适应码流、Simulcast、SVC等等 , 非常适合刚刚进入音视频行业小伙伴哈^_^ 我也是哦, 以后再音视频行业长期打算的小伙伴的学习项目。 里面有大量知识点

在这里插入图片描述

一、 STUN协议

在这里插入图片描述

STUN header和STUN Body组成的
  1. 包括20字节的STUN header
  2. Body中可以有0个或多个Attribute

二、 STUN协议头格式

在这里插入图片描述

三、 STUN Header

  1. 2个字节

    (16bit)类型

  2. 2个字节

    (16bit)信息长度、不包括信息头

  3. 16个字节

    (128bit)事务ID、请求与响应事务ID相同

四、STUN Message Type

  1. 前两位必须是00、以区分复用同一个端口时STUN协议
  2. 2位用于分类、即C0和C1
  3. 12 位用于定义请求/指示
C表示分类,M 表示方法

在这里插入图片描述

1 、C0C1

  1. 0b00: 表示是一个请求
  2. 0b01: 表示是一个指示
  3. 0b10: 表式是请求成功的响应
  4. 0b11: 表示是请求失败的响应

2、 STUN信息类型

在这里插入图片描述

3 、大小端模式

大端模式: 数据的高字节保存在内存的低地址中

小端模式: 数据的高字节保存在内存的高地址中

网络字节顺序: 采用大端排序方式

五、 StunMagicCookie

4字节、32位、固定值0x2112A442。通过它可以判断客户端是否可以支持某些属性

六、Transaction ID事务ID

12字节、96位、标识同一个事物的请求和响应

七、STUN Message Body

  1. 信息头后有0或多个属性
  2. 每个塑性进行TLV编码: Type、Length、Value

在这里插入图片描述

八、RFC 3489定义的属性

在这里插入图片描述

九、 WebRTC中代码


bool StunMessage::Read(ByteBufferReader* buf) {
  if (!buf->ReadUInt16(&type_))
    return false;

  if (type_ & 0x8000) {
    // RTP and RTCP set the MSB of first byte, since first two bits are version,
    // and version is always 2 (10). If set, this is not a STUN packet.
    return false;
  }

  if (!buf->ReadUInt16(&length_))
    return false;

  std::string magic_cookie;//0x2112A442
  if (!buf->ReadString(&magic_cookie, kStunMagicCookieLength))
    return false;

  std::string transaction_id; // 12bit
  if (!buf->ReadString(&transaction_id, kStunTransactionIdLength))
    return false;

  uint32_t magic_cookie_int;
  static_assert(sizeof(magic_cookie_int) == kStunMagicCookieLength,
                "Integer size mismatch: magic_cookie_int and kStunMagicCookie");
  std::memcpy(&magic_cookie_int, magic_cookie.data(), sizeof(magic_cookie_int));
  if (rtc::NetworkToHost32(magic_cookie_int) != kStunMagicCookie) {
    // If magic cookie is invalid it means that the peer implements
    // RFC3489 instead of RFC5389.
    transaction_id.insert(0, magic_cookie);
  }
  RTC_DCHECK(IsValidTransactionId(transaction_id));
  transaction_id_ = transaction_id;
  reduced_transaction_id_ = ReduceTransactionId(transaction_id_);
  printf(
      "type_ = %u, magic_cookie = %s, transaction_id = %s, magic_cookie_int = "
      "%u\n ",
      type_, magic_cookie.c_str(), transaction_id.c_str(), magic_cookie_int);
  if (length_ != buf->Length())
    return false;

  attrs_.resize(0);

  size_t rest = buf->Length() - length_;
  while (buf->Length() > rest) {
    uint16_t attr_type, attr_length;
    if (!buf->ReadUInt16(&attr_type))
      return false;
    if (!buf->ReadUInt16(&attr_length))
      return false;

    std::unique_ptr<StunAttribute> attr(
        CreateAttribute(attr_type, attr_length));
    if (!attr) {
      // Skip any unknown or malformed attributes.
      if ((attr_length % 4) != 0) {
        attr_length += (4 - (attr_length % 4));
      }
      if (!buf->Consume(attr_length))
        return false;
    } else {
      if (!attr->Read(buf))
        return false;
      attrs_.push_back(std::move(attr));
    }
  }

  RTC_DCHECK(buf->Length() == rest);
  return true;
}

总结:

WebRTC源码分析地址:https://github.com/chensongpoixs/cwebrtc