前言
时序图
几个关键点
源码分析
Conductor::ConnectToPeer
void Conductor::ConnectToPeer(int peer_id) {
***
if (InitializePeerConnection()) {
peer_id_ = peer_id;
peer_connection_->CreateOffer(
this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
***
}
PeerConnection::CreateOffer
void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
const RTCOfferAnswerOptions& options) {
RTC_DCHECK_RUN_ON(signaling_thread());
sdp_handler_->CreateOffer(observer, options);
}
可以看到,第一个参数是CreateSessionDescriptionObserver观察者回调,这里输入的是this,说明Conductor也继承了webrtc::CreateSessionDescriptionObserver。
如果调用CreateOffer()方法成功创建了SDP,则WebRTC会回调Conductor对象的OnSuccess()方法,最终通过信令处理模块将创建好的SDP发送给对端;如果创建SDP失败,则会回调Conductor的OnFailure()方法。
Conductor::OnSuccess
void Conductor::OnSuccess(webrtc::SessionDescriptionInterface* desc) {
// 创建offer成功后的信息添加到本地 Description内存中
peer_connection_->SetLocalDescription(
DummySetSessionDescriptionObserver::Create(), desc);
// 将创建offer成功后的信息转换为json数据,发送出去到对端
std::string sdp;
desc->ToString(&sdp);
// For loopback test. To save some connecting delay.
if (loopback_) {
// Replace message type from "offer" to "answer"
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
webrtc::CreateSessionDescription(webrtc::SdpType::kAnswer, sdp);
peer_connection_->SetRemoteDescription(
DummySetSessionDescriptionObserver::Create(),
session_description.release());
return;
}
连接完成后,将发送创建成功的offer消息到对端。对端收到offer后,创建answer消息,并发回到本端,此时本地将调用Conductor::OnMessageFromPeer处理对端消息。
Conductor::OnMessageFromPeer
这里是收到对端消息,然后json解析,判断sdp类型是kOffer则代表是对端发起通信,需要PeerConnection::CreateAnswer 创建answer发回到对端。否则就是自己发起通信,收到的是answer,
void Conductor::OnMessageFromPeer(int peer_id, const std::string& message) {
RTC_DCHECK(peer_id_ == peer_id || peer_id_ == -1);
RTC_DCHECK(!message.empty());
if (!peer_connection_.get()) {
RTC_DCHECK(peer_id_ == -1);
peer_id_ = peer_id;
if (!InitializePeerConnection()) {
RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
client_->SignOut();
return;
}
} else if (peer_id != peer_id_) {
RTC_DCHECK(peer_id_ != -1);
RTC_LOG(WARNING)
<< "Received a message from unknown peer while already in a "
"conversation with a different peer.";
return;
}
// json解析接收到的对端消息
Json::Reader reader;
Json::Value jmessage;
if (!reader.parse(message, jmessage)) {
RTC_LOG(WARNING) << "Received unknown message. " << message;
return;
}
std::string type_str;
std::string json_object;
// 获取信令类型,type_str为answer或者offer,
// 如果是本端发起通信,第一次会收到answer类型,后面收到的就是空类型
rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionTypeName,
&type_str);
if (!type_str.empty()) { // 类型不为空
if (type_str == "offer-loopback") {
// This is a loopback call.
// Recreate the peerconnection with DTLS disabled.
if (!ReinitializePeerConnectionForLoopback()) {
RTC_LOG(LS_ERROR) << "Failed to initialize our PeerConnection instance";
DeletePeerConnection();
client_->SignOut();
}
return;
}
// 获取sdp类型
absl::optional<webrtc::SdpType> type_maybe =
webrtc::SdpTypeFromString(type_str);
if (!type_maybe) {
RTC_LOG(LS_ERROR) << "Unknown SDP type: " << type_str;
return;
}
webrtc::SdpType type = *type_maybe;
// 从json中获取sdp消息
std::string sdp;
if (!rtc::GetStringFromJsonObject(jmessage, kSessionDescriptionSdpName,
&sdp)) {
RTC_LOG(WARNING) << "Can't parse received session description message.";
return;
}
// 根据sdp创建SessionDescriptionInterface实例
webrtc::SdpParseError error;
std::unique_ptr<webrtc::SessionDescriptionInterface> session_description =
webrtc::CreateSessionDescription(type, sdp, &error);
if (!session_description) {
RTC_LOG(WARNING) << "Can't parse received session description message. "
"SdpParseError was: "
<< error.description;
return;
}
RTC_LOG(INFO) << " Received session description :" << message;
// 通过SetRemoteDescription设置对端的sdp消息保存到内存
peer_connection_->SetRemoteDescription(
DummySetSessionDescriptionObserver::Create(),
session_description.release());
// 如果是offer消息,则代表是对端发起通信,需要发给对端answer
if (type == webrtc::SdpType::kOffer) {
peer_connection_->CreateAnswer(
this, webrtc::PeerConnectionInterface::RTCOfferAnswerOptions());
}
} else {
std::string sdp_mid;
int sdp_mlineindex = 0;
// 获取sdp信息
std::string sdp;
if (!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpMidName,
&sdp_mid) ||
!rtc::GetIntFromJsonObject(jmessage, kCandidateSdpMlineIndexName,
&sdp_mlineindex) ||
!rtc::GetStringFromJsonObject(jmessage, kCandidateSdpName, &sdp)) {
RTC_LOG(WARNING) << "Can't parse received message.";
return;
}
// 根据sdp,创建candidate
webrtc::SdpParseError error;
std::unique_ptr<webrtc::IceCandidateInterface> candidate(
webrtc::CreateIceCandidate(sdp_mid, sdp_mlineindex, sdp, &error));
if (!candidate.get()) {
RTC_LOG(WARNING) << "Can't parse received candidate message. "
"SdpParseError was: "
<< error.description;
return;
}
// 添加AddIceCandidate
if (!peer_connection_->AddIceCandidate(candidate.get())) {
RTC_LOG(WARNING) << "Failed to apply the received candidate";
return;
}
RTC_LOG(INFO) << " Received candidate :" << message;
}
}