前言image.png

image.png

时序图

image.png

几个关键点

image.png

源码分析

Conductor::ConnectToPeer

  1. void Conductor::ConnectToPeer(int peer_id) {
  2. ***
  3. if (InitializePeerConnection()) {
  4. peer_id_ = peer_id;
  5. peer_connection_->CreateOffer(
  6. this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
  7. ***
  8. }

这里主要是CreateOffer,通过看该函数定义。

PeerConnection::CreateOffer

  1. void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
  2. const RTCOfferAnswerOptions& options) {
  3. RTC_DCHECK_RUN_ON(signaling_thread());
  4. sdp_handler_->CreateOffer(observer, options);
  5. }

image.png
可以看到,第一个参数是CreateSessionDescriptionObserver观察者回调,这里输入的是this,说明Conductor也继承了webrtc::CreateSessionDescriptionObserver。
如果调用CreateOffer()方法成功创建了SDP,则WebRTC会回调Conductor对象的OnSuccess()方法,最终通过信令处理模块将创建好的SDP发送给对端;如果创建SDP失败,则会回调Conductor的OnFailure()方法。

Conductor::OnSuccess

image.png

  1. void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
  2. // 创建offer成功后的信息添加到本地 Description内存中
  3. peer_connection_->SetLocalDescription(
  4. DummySetSessionDescriptionObserver::Create(), desc);
  5. // 将创建offer成功后的信息转换为json数据,发送出去到对端
  6. std::string sdp;
  7. desc->ToString(&sdp);
  8. // For loopback test. To save some connecting delay.
  9. if (loopback_) {
  10. // Replace message type from "offer" to "answer"
  11. std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
  12. webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp);
  13. peer_connection_->SetRemoteDescription(
  14. DummySetSessionDescriptionObserver::Create(),
  15. session_description.release());
  16. return;
  17. }

连接完成后,将发送创建成功的offer消息到对端。对端收到offer后,创建answer消息,并发回到本端,此时本地将调用Conductor::OnMessageFromPeer处理对端消息。

Conductor::OnMessageFromPeer

image.png
这里是收到对端消息,然后json解析,判断sdp类型是kOffer则代表是对端发起通信,需要PeerConnection::CreateAnswer 创建answer发回到对端。否则就是自己发起通信,收到的是answer,

  1. void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
  2. RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1);
  3. RTC_DCHECK(!message.empty());
  4. if (!peer_connection_.get()) {
  5. RTC_DCHECK(peer_id_ == -1);
  6. peer_id_ = peer_id;
  7. if (!InitializePeerConnection()) {
  8. RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
  9. client_->SignOut();
  10. return;
  11. }
  12. } else if (peer_id != peer_id_) {
  13. RTC_DCHECK(peer_id_ != -1);
  14. RTC_LOG(WARNING)
  15. << "Received a message from unknown peer while already in a "
  16. "conversation with a different peer.";
  17. return;
  18. }
  19. // json解析接收到的对端消息
  20. Json::Reader reader;
  21. Json::Value jmessage;
  22. if (!reader.parse(message, jmessage)) {
  23. RTC_LOG(WARNING) << "Received unknown message. " << message;
  24. return;
  25. }
  26. std::string type_str;
  27. std::string json_object;
  28. // 获取信令类型,type_str为answer或者offer,
  29. // 如果是本端发起通信,第一次会收到answer类型,后面收到的就是空类型
  30. rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName,
  31. &type_str);
  32. if (!type_str.empty()) { // 类型不为空
  33. if (type_str == "offer-loopback") {
  34. // This is a loopback call.
  35. // Recreate the peerconnection with DTLS disabled.
  36. if (!ReinitializePeerConnectionForLoopback()) {
  37. RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
  38. DeletePeerConnection();
  39. client_->SignOut();
  40. }
  41. return;
  42. }
  43. // 获取sdp类型
  44. absl::optional<webrtc::SdpType> type_maybe =
  45. webrtc::SdpTypeFromString(type_str);
  46. if (!type_maybe) {
  47. RTC_LOG(LS_ERROR) << "Unknown SDP type: " << type_str;
  48. return;
  49. }
  50. webrtc::SdpType type = *type_maybe;
  51. // 从json中获取sdp消息
  52. std::string sdp;
  53. if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
  54. &sdp)) {
  55. RTC_LOG(WARNING) << "Can't parse received session description message.";
  56. return;
  57. }
  58. // 根据sdp创建SessionDescriptionInterface实例
  59. webrtc::SdpParseError error;
  60. std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
  61. webrtc::CreateSessionDescription(type, sdp, &error);
  62. if (!session_description) {
  63. RTC_LOG(WARNING) << "Can't parse received session description message. "
  64. "SdpParseError was: "
  65. << error.description;
  66. return;
  67. }
  68. RTC_LOG(INFO) << " Received session description :" << message;
  69. // 通过SetRemoteDescription设置对端的sdp消息保存到内存
  70. peer_connection_->SetRemoteDescription(
  71. DummySetSessionDescriptionObserver::Create(),
  72. session_description.release());
  73. // 如果是offer消息,则代表是对端发起通信,需要发给对端answer
  74. if (type == webrtc::SdpType::kOffer) {
  75. peer_connection_->CreateAnswer(
  76. this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
  77. }
  78. } else {
  79. std::string sdp_mid;
  80. int sdp_mlineindex = 0;
  81. // 获取sdp信息
  82. std::string sdp;
  83. if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
  84. &sdp_mid) ||
  85. !rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
  86. &sdp_mlineindex) ||
  87. !rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
  88. RTC_LOG(WARNING) << "Can't parse received message.";
  89. return;
  90. }
  91. // 根据sdp,创建candidate
  92. webrtc::SdpParseError error;
  93. std::unique_ptr<webrtc::IceCandidateInterface> candidate(
  94. webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
  95. if (!candidate.get()) {
  96. RTC_LOG(WARNING) << "Can't parse received candidate message. "
  97. "SdpParseError was: "
  98. << error.description;
  99. return;
  100. }
  101. // 添加AddIceCandidate
  102. if (!peer_connection_->AddIceCandidate(candidate.get())) {
  103. RTC_LOG(WARNING) << "Failed to apply the received candidate";
  104. return;
  105. }
  106. RTC_LOG(INFO) << " Received candidate :" << message;
  107. }
  108. }