PeerConnection中对SDP的认证过程

        在PeerConnection中无论是SetLocalDescription还是SetRemoteDescription,里面的第一个都是对SDP进行认证检测即调用ValidateSessionDescription,在ValidateSessionDescription中主要对如下三个方面进行了认证:
1 加密信息认证 
2 ice信息认证
3 m-section中track个数进行认证

1 加密信息认证,即VerifyCrypto函数

RTCError VerifyCrypto(const SessionDescription* desc, bool dtls_enabled)
{
  const cricket::ContentGroup* bundle = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  for (const cricket::ContentInfo& content_info : desc->contents())
  {
    1 被拒绝的直接忽略
    if (content_info.rejected)
    {
      continue;
    }

    // Note what media is used with each crypto protocol, for all sections.
    NoteKeyProtocolAndMedia(dtls_enabled ? webrtc::kEnumCounterKeyProtocolDtls
                                         : webrtc::kEnumCounterKeyProtocolSdes,
                            content_info.media_description()->type());
    const std::string& mid = content_info.name;
    if (bundle && bundle->HasContentName(mid) && mid != *(bundle->FirstContentName()))
    {
      // This isn't the first media section in the BUNDLE group, so it's not
      // required to have crypto attributes, since only the crypto attributes
      // from the first section actually get used.
      continue;
    }

    2 如果开启BUNDLE,则看看第一个是否包含fingerprint,没有则返回false

    // If the content isn't rejected or bundled into another m= section, crypto
    // must be present.
    const MediaContentDescription* media = content_info.media_description();
    const TransportInfo* tinfo = desc->GetTransportInfoByName(mid);
    if (!media || !tinfo)
    {
      // Something is not right.
      LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, kInvalidSdp);
    }
    if (dtls_enabled)
    {
      if (!tinfo->description.identity_fingerprint)
      {
        RTC_LOG(LS_WARNING)
            << "Session description must have DTLS fingerprint if "
               "DTLS enabled.";
        return RTCError(RTCErrorType::INVALID_PARAMETER, kSdpWithoutDtlsFingerprint);
      }
    }
    else
    {
      if (media->cryptos().empty())
      {
        RTC_LOG(LS_WARNING)
            << "Session description must have SDES when DTLS disabled.";
        return RTCError(RTCErrorType::INVALID_PARAMETER, kSdpWithoutSdesCrypto);
      }
    }
  }
  return RTCError::OK();
}

代码中已做标注

2 ice信息认证,即VerifyIceUfragPwdPresent

bool VerifyIceUfragPwdPresent(const SessionDescription* desc)
{
  0 判断是否有BUNDLE,并获取BUNDLE列表即mid列表
  const cricket::ContentGroup* bundle = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
  for (const cricket::ContentInfo& content_info : desc->contents())
  {
    1 被拒绝的m-section直接continue
    if (content_info.rejected)
    {
      continue;
    }
    
    2 如果开启了BUNDLE,并且当前m-section在BUNDLE中,但不是第一个m-section则直接continue

    const std::string& mid = content_info.name;
    if (bundle && bundle->HasContentName(mid) && mid != *(bundle->FirstContentName()))
    {
      // This isn't the first media section in the BUNDLE group, so it's not
      // required to have ufrag/password, since only the ufrag/password from
      // the first section actually get used.
      continue;
    }

    3 如果第一个m-section中获取不到ice信息
    // If the content isn't rejected or bundled into another m= section,
    // ice-ufrag and ice-pwd must be present.
    const TransportInfo* tinfo = desc->GetTransportInfoByName(mid);
    if (!tinfo)
    {
      // Something is not right.
      RTC_LOG(LS_ERROR) << kInvalidSdp;
      return false;
    }

    4 如果ice_ufrag或ice_pwd任意一个为空 则返回false
    if (tinfo->description.ice_ufrag.empty() || tinfo->description.ice_pwd.empty())
    {
      RTC_LOG(LS_ERROR) << "Session description must have ice ufrag and pwd.";
      return false;
    }
  }
  return true;
}

3 m-section中track个数进行认证

if (IsUnifiedPlan())
{
    // Ensure that each audio and video media section has at most one
    // "StreamParams". This will return an error if receiving a session
    // description from a "Plan B" endpoint which adds multiple tracks of the
    // same type. With Unified Plan, there can only be at most one track per
    // media section.
    for (const ContentInfo& content : sdesc->description()->contents())
    {
      const MediaContentDescription& desc = *content.description;
      if ((desc.type() == cricket::MEDIA_TYPE_AUDIO ||
           desc.type() == cricket::MEDIA_TYPE_VIDEO) &&
          desc.streams().size() > 1u) {
        LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                             "Media section has more than one track specified "
                             "with a=ssrc lines which is not supported with "
                             "Unified Plan.");
      }
    }
}

这里只列出了公共认证部分,针对answer还有一个m-section个数和顺序的认证,详见如下两个函数:

MediaSectionsHaveSameCount()和MediaSectionsInSameOrder()

        从上可以得出,UnifiedPlan下开启BUNDLE时其认证的过程可以总结为:

1 加密信息在第一个m-section中必须有,其他m-section随意
2 同上,ice信息在第一个m-section中必须有,其他m-section随意
3 如果开启BUNDLE,每个m-section中必须有a=rtcp-mux属性
4 UnifiedPlan中,每个m-section中只能有一个track

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

airmanisvip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值