当前位置: 首页 > news >正文

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

相关文章:

  • Xcode定期清理文件
  • 一种基于深度学习的织物缺陷检测方法
  • 工厂如何实现智能制造?有哪些需要注意的?
  • 如何提高自己的软件测试水平之bug定位
  • 2、一起探讨MySQL 安装
  • 北大肖臻老师《区块链技术与应用》系列课程学习笔记[26]以太坊-TheDao
  • openlayers 绘制tin数据导文
  • Web字体的使用
  • [设计模式]单例模式的详解与用法
  • Polygon zkEVM zkASM编译器——zkasmcom
  • 社交媒体用户信息回避行为的影响因素分析
  • 你期待在海上坐高铁吗?中国首条跨海高铁——福厦高铁来了
  • 种草营销怎么玩?如何借小红书KOL、KOC笔记种草提升转化效果
  • GBase 8s 的导入导出工具介绍
  • Delegation in C++
  • @angular/forms 源码解析之双向绑定
  • 【RocksDB】TransactionDB源码分析
  • C++类的相互关联
  • LeetCode18.四数之和 JavaScript
  • leetcode98. Validate Binary Search Tree
  • SpringCloud(第 039 篇)链接Mysql数据库,通过JpaRepository编写数据库访问
  • Wamp集成环境 添加PHP的新版本
  • 从零开始在ubuntu上搭建node开发环境
  • 个人博客开发系列:评论功能之GitHub账号OAuth授权
  • 携程小程序初体验
  • #设计模式#4.6 Flyweight(享元) 对象结构型模式
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (1)Map集合 (2)异常机制 (3)File类 (4)I/O流
  • (175)FPGA门控时钟技术
  • (C语言)二分查找 超详细
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (小白学Java)Java简介和基本配置
  • (转)nsfocus-绿盟科技笔试题目
  • ../depcomp: line 571: exec: g++: not found
  • ..回顾17,展望18
  • .\OBJ\test1.axf: Error: L6230W: Ignoring --entry command. Cannot find argumen 'Reset_Handler'
  • .net core开源商城系统源码,支持可视化布局小程序
  • .NET 反射的使用
  • .NET成年了,然后呢?
  • .net对接阿里云CSB服务
  • .NET开源全面方便的第三方登录组件集合 - MrHuo.OAuth
  • .net之微信企业号开发(一) 所使用的环境与工具以及准备工作
  • /etc/sudoers (root权限管理)
  • /usr/lib/mysql/plugin权限_给数据库增加密码策略遇到的权限问题
  • @Controller和@RestController的区别?
  • @JoinTable会自动删除关联表的数据
  • @取消转义
  • [ 数据结构 - C++] AVL树原理及实现
  • [20150707]外部表与rowid.txt
  • [AI]ChatGPT4 与 ChatGPT3.5 区别有多大
  • [Android] 修改设备访问权限
  • [Angularjs]ng-select和ng-options
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [C#]winform制作圆形进度条好用的圆环圆形进度条控件和使用方法
  • [C++]:for循环for(int num : nums)