• PeerConnection中对SDP的认证过程


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

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

    1. RTCError VerifyCrypto(const SessionDescription* desc, bool dtls_enabled)
    2. {
    3. const cricket::ContentGroup* bundle = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
    4. for (const cricket::ContentInfo& content_info : desc->contents())
    5. {
    6. 1 被拒绝的直接忽略
    7. if (content_info.rejected)
    8. {
    9. continue;
    10. }
    11. // Note what media is used with each crypto protocol, for all sections.
    12. NoteKeyProtocolAndMedia(dtls_enabled ? webrtc::kEnumCounterKeyProtocolDtls
    13. : webrtc::kEnumCounterKeyProtocolSdes,
    14. content_info.media_description()->type());
    15. const std::string& mid = content_info.name;
    16. if (bundle && bundle->HasContentName(mid) && mid != *(bundle->FirstContentName()))
    17. {
    18. // This isn't the first media section in the BUNDLE group, so it's not
    19. // required to have crypto attributes, since only the crypto attributes
    20. // from the first section actually get used.
    21. continue;
    22. }
    23. 2 如果开启BUNDLE,则看看第一个是否包含fingerprint,没有则返回false
    24. // If the content isn't rejected or bundled into another m= section, crypto
    25. // must be present.
    26. const MediaContentDescription* media = content_info.media_description();
    27. const TransportInfo* tinfo = desc->GetTransportInfoByName(mid);
    28. if (!media || !tinfo)
    29. {
    30. // Something is not right.
    31. LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER, kInvalidSdp);
    32. }
    33. if (dtls_enabled)
    34. {
    35. if (!tinfo->description.identity_fingerprint)
    36. {
    37. RTC_LOG(LS_WARNING)
    38. << "Session description must have DTLS fingerprint if "
    39. "DTLS enabled.";
    40. return RTCError(RTCErrorType::INVALID_PARAMETER, kSdpWithoutDtlsFingerprint);
    41. }
    42. }
    43. else
    44. {
    45. if (media->cryptos().empty())
    46. {
    47. RTC_LOG(LS_WARNING)
    48. << "Session description must have SDES when DTLS disabled.";
    49. return RTCError(RTCErrorType::INVALID_PARAMETER, kSdpWithoutSdesCrypto);
    50. }
    51. }
    52. }
    53. return RTCError::OK();
    54. }

    代码中已做标注

    2 ice信息认证,即VerifyIceUfragPwdPresent

    1. bool VerifyIceUfragPwdPresent(const SessionDescription* desc)
    2. {
    3. 0 判断是否有BUNDLE,并获取BUNDLE列表即mid列表
    4. const cricket::ContentGroup* bundle = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE);
    5. for (const cricket::ContentInfo& content_info : desc->contents())
    6. {
    7. 1 被拒绝的m-section直接continue
    8. if (content_info.rejected)
    9. {
    10. continue;
    11. }
    12. 2 如果开启了BUNDLE,并且当前m-section在BUNDLE中,但不是第一个m-section则直接continue
    13. const std::string& mid = content_info.name;
    14. if (bundle && bundle->HasContentName(mid) && mid != *(bundle->FirstContentName()))
    15. {
    16. // This isn't the first media section in the BUNDLE group, so it's not
    17. // required to have ufrag/password, since only the ufrag/password from
    18. // the first section actually get used.
    19. continue;
    20. }
    21. 3 如果第一个m-section中获取不到ice信息
    22. // If the content isn't rejected or bundled into another m= section,
    23. // ice-ufrag and ice-pwd must be present.
    24. const TransportInfo* tinfo = desc->GetTransportInfoByName(mid);
    25. if (!tinfo)
    26. {
    27. // Something is not right.
    28. RTC_LOG(LS_ERROR) << kInvalidSdp;
    29. return false;
    30. }
    31. 4 如果ice_ufrag或ice_pwd任意一个为空 则返回false
    32. if (tinfo->description.ice_ufrag.empty() || tinfo->description.ice_pwd.empty())
    33. {
    34. RTC_LOG(LS_ERROR) << "Session description must have ice ufrag and pwd.";
    35. return false;
    36. }
    37. }
    38. return true;
    39. }

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

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

    这里只列出了公共认证部分,针对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

  • 相关阅读:
    对分段有序的数组排序(前、后部分分别递增)
    【前端知识】Three 学习日志(五)—— 点光源辅助观察
    编程高手必学的内存知识05:深入理解页中断
    升级cordova-ios 6以上版本 Xcode打开xcodeproj文件
    嵌入式应用开发之环境搭建及体验
    表格数据方法、分页方法及组件的封装和分页组件的复用
    【Java】Netty创建网络服务端客户端(TCP/UDP)
    《Head First HTML5 javascript》第1章 交互式网络 知识点总结
    二叉树的遍历 中序线索二叉树
    Opengl绘制三角形
  • 原文地址:https://blog.csdn.net/airmanisvip/article/details/126623423