///
接收 TurnAllocateRequest 响应 (第二次)
这里直接到达和第一次处理 TurnAllocateRequest 响应不同的地方 //
bool StunRequestManager::CheckResponse(StunMessage* msg)
===>
request->OnResponse(msg);
void TurnAllocateRequest::OnResponse(StunMessage* response) {
RTC_LOG(LS_INFO) << port_->ToString()
<< ": TURN allocate requested successfully, id="
<< rtc::hex_encode(id())
<< ", code=0" // Makes logging easier to parse.
", rtt="
<< Elapsed();
// Check mandatory attributes as indicated in RFC5766, Section 6.3.
const StunAddressAttribute* mapped_attr =
response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
if (!mapped_attr) {
RTC_LOG(LS_WARNING) << port_->ToString()
<< ": Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
"attribute in allocate success response";
return;
}
// Using XOR-Mapped-Address for stun.
port_->OnStunAddress(mapped_attr->GetAddress()); /// TurnPort::OnStunAddress
const StunAddressAttribute* relayed_attr =
response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
if (!relayed_attr) {
RTC_LOG(LS_WARNING) << port_->ToString()
<< ": Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
"attribute in allocate success response";
return;
}
const StunUInt32Attribute* lifetime_attr =
response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
if (!lifetime_attr) {
RTC_LOG(LS_WARNING) << port_->ToString()
<< ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
"allocate success response";
return;
}
// Notify the port the allocate succeeded, and schedule a refresh request.
port_->OnAllocateSuccess(relayed_attr->GetAddress(),
mapped_attr->GetAddress()); /// TurnPort::OnAllocateSuccess
port_->ScheduleRefresh(lifetime_attr->value()); /// TurnPort::ScheduleRefresh
}
void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
const rtc::SocketAddress& stun_address) {
state_ = STATE_READY;
rtc::SocketAddress related_address = stun_address;
// For relayed candidate, Base is the candidate itself.
AddAddress(address, // Candidate address.
address, // Base address.
related_address, // Related address.
UDP_PROTOCOL_NAME,
ProtoToString(server_address_.proto), // The first hop protocol.
"", // TCP canddiate type, empty for turn candidates.
RELAY_PORT_TYPE, GetRelayPreference(server_address_.proto),
server_priority_, ReconstructedServerUrl(false /* use_hostname */),
true); /// 注意注意注意,这里 is_final 传递的是 true /
}
void Port::AddAddress(const rtc::SocketAddress& address,
const rtc::SocketAddress& base_address,
const rtc::SocketAddress& related_address,
const std::string& protocol,
const std::string& relay_protocol,
const std::string& tcptype,
const std::string& type,
uint32_t type_preference,
uint32_t relay_preference,
const std::string& url,
bool is_final) { // 这里 is_final 传递的是 true /
if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) {
RTC_DCHECK(!tcptype.empty());
}
std::string foundation =
ComputeFoundation(type, protocol, relay_protocol, base_address);
Candidate c(component_, protocol, address, 0U, username_fragment(), password_, // 创建 candidate
type, generation_, foundation, network_->id(), network_cost_);
c.set_priority(
c.GetPriority(type_preference, network_->preference(), relay_preference));
c.set_relay_protocol(relay_protocol);
c.set_tcptype(tcptype);
c.set_network_name(network_->name());
c.set_network_type(network_->type());
c.set_url(url);
c.set_related_address(related_address);
bool pending = MaybeObfuscateAddress(&c, type, is_final);
if (!pending) {
FinishAddingAddress(c, is_final); // 这里 is_final 传递的是 true /
}
}
void Port::FinishAddingAddress(const Candidate& c, bool is_final) {
candidates_.push_back(c);
SignalCandidateReady(this, c); / BasicPortAllocatorSession::OnCandidateReady 具体参考下面分析
/// 注意这里的 this 是 Port 的指针,而实际上指向的是 TurnPort (收集 relay candidate 使用的就是 TurnPort)
/// 这里触发调用 BasicPortAllocatorSession::OnCandidateReady , 此函数内部又触发 SignalPortReady(this, port);
/// 从而再次引发槽函数 P2PTransportChannel::OnPortReady 的调用,执行 ports_.push_back(port) ,从而将指向 TurnPort 的 Port
/// 指针保存到 ports_ ,所以在 P2PTransportChannel::CreateConnection 中调用 port->CreateConnection 创建 connection 时
会调用 UDPPort::CreateConnection 或者 TurnPort::CreateConnection
PostAddAddress(is_final);
}
//
/// UDPPort::OnSentPacket /
//
void UDPPort::OnSentPacket(rtc::AsyncPacketSocket* socket,
const rtc::SentPacket& sent_packet) {
PortInterface::SignalSentPacket(sent_packet); / 这个信号在哪里绑定的?绑定到哪一个槽里呢? 见 P2PTransportChannel::OnPortReady
} 经过下面的分析这里就会调用到 P2PTransportChannel::OnSentPacket (具体见下部的 P2PTransportChannel::OnPortReady )
class Port : public PortInterface,
public rtc::MessageHandlerAutoCleanup,
public sigslot::has_slots<>
class UDPPort : public Port
什么时候会调用 P2PTransportChannel::OnPortReady ??
在 BasicPortAllocatorSession::OnCandidateReady 中发送这个信号 SignalPortReady , 就会调用到 P2PTransportChannel::OnPortReady
这个绑定关系是在 P2PTransportChannel::AddAllocatorSession 中确定的,具体见前面分析
// A new port is available, attempt to make connections for it
void P2PTransportChannel::OnPortReady(PortAllocatorSession* session,
PortInterface* port) { 这里的 port 实际上就是 Port 的指针
RTC_DCHECK_RUN_ON(network_thread_); / 这个 Port 的指针具体可以指向 UDPPort 和 TurnPort
// Set in-effect options on the new port
for (OptionMap::const_iterator it = options_.begin(); it != options_.end();
++it) {
int val = port->SetOption(it->first, it->second);
if (val < 0) {
// Errors are frequent, so use LS_INFO. bugs.webrtc.org/9221
RTC_LOG(LS_INFO) << port->ToString() << ": SetOption(" << it->first
<< ", " << it->second
<< ") failed: " << port->GetError();
}
}
// Remember the ports and candidates, and signal that candidates are ready.
// The session will handle this, and send an initiate/accept/modify message
// if one is pending.
port->SetIceRole(ice_role_);
port->SetIceTiebreaker(tiebreaker_);
ports_.push_back(port); // 将收集的 candidate 的 port 保存下来,后面会使用,比如: P2PTransportChannel::CreateConnections
port->SignalUnknownAddress.connect(this,
&P2PTransportChannel::OnUnknownAddress);
port->SignalDestroyed.connect(this, &P2PTransportChannel::OnPortDestroyed);
port->SignalRoleConflict.connect(this, &P2PTransportChannel::OnRoleConflict);
port->SignalSentPacket.connect(this, &P2PTransportChannel::OnSentPacket); / 就是在这里对 Port 的 SignalSentPacket 事件进行了绑定 //
// Attempt to create a connection from this new port to all of the remote
// candidates that we were given so far.
std::vector<RemoteCandidate>::iterator iter;
for (iter = remote_candidates_.begin(); iter != remote_candidates_.end();
++iter) {
CreateConnection(port, *iter, iter->origin_port());
}
SortConnectionsAndUpdateState( 连通性检测
IceControllerEvent::NEW_CONNECTION_FROM_LOCAL_CANDIDATE);
}
void P2PTransportChannel::OnSentPacket(const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(network_thread_);
SignalSentPacket(this, sent_packet); / 此信号来自 PacketTransportInternal ,经过下面的分析实际上是会触发 DtlsTransport::OnSentPacket /
}
// P2PTransportChannel 的继承关系
class RTC_EXPORT IceTransportInternal : public rtc::PacketTransportInternal
class RTC_EXPORT P2PTransportChannel : public IceTransportInternal
JsepTransportController::MaybeCreateJsepTransport 中调用 如下内容:
====>
rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
CreateIceTransport(content_info.name, /*rtcp=*/false); / 返回的是包裹了 cricket::P2PTransportChannel 的 DefaultIceTransport 实例对象
RTC_DCHECK(ice); ice->internal() 返回的就是 DefaultIceTransport 包裹的 cricket::P2PTransportChannel 指针
std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport = CreateDtlsTransport返回的是 cricket::DtlsTransport
CreateDtlsTransport(content_info, ice->internal()); /// ice->internal() 返回的就是 DefaultIceTransport 包裹的 cricket::P2PTransportChannel 指针
std::unique_ptr<cricket::DtlsTransportInternal>
JsepTransportController::CreateDtlsTransport(
const cricket::ContentInfo& content_info,
cricket::IceTransportInternal* ice) {
RTC_DCHECK(network_thread_->IsCurrent());
std::unique_ptr<cricket::DtlsTransportInternal> dtls;
if (config_.dtls_transport_factory) {
dtls = config_.dtls_transport_factory->CreateDtlsTransport(
ice, config_.crypto_options);
} else {
dtls = std::make_unique<cricket::DtlsTransport>(ice, config_.crypto_options,
config_.event_log); / 将 ice 也就是 cricket::P2PTransportChannel 传递到 DtlsTransport 中的成变 ice_transport_
}
RTC_DCHECK(dtls); /// dtls->ice_transport() 返回的就是 创建 DtlsTransport 时传递进去的参数 ice
dtls->SetSslMaxProtocolVersion(config_.ssl_max_version);
dtls->ice_transport()->SetIceRole(ice_role_);
dtls->ice_transport()->SetIceTiebreaker(ice_tiebreaker_);
dtls->ice_transport()->SetIceConfig(ice_config_);
if (certificate_) {
bool set_cert_success = dtls->SetLocalCertificate(certificate_);
RTC_DCHECK(set_cert_success);
}
// Connect to signals offered by the DTLS and ICE transport.
dtls->SignalWritableState.connect(
this, &JsepTransportController::OnTransportWritableState_n);
dtls->SignalReceivingState.connect(
this, &JsepTransportController::OnTransportReceivingState_n);
dtls->SignalDtlsHandshakeError.connect(
this, &JsepTransportController::OnDtlsHandshakeError);
dtls->ice_transport()->SignalGatheringState.connect(
this, &JsepTransportController::OnTransportGatheringState_n);
dtls->ice_transport()->SignalCandidateGathered.connect( 在这里设置了 cricket::P2PTransportChannel SignalCandidateGathered 信号的槽函数
this, &JsepTransportController::OnTransportCandidateGathered_n);
dtls->ice_transport()->SignalCandidateError.connect(
this, &JsepTransportController::OnTransportCandidateError_n);
dtls->ice_transport()->SignalCandidatesRemoved.connect(
this, &JsepTransportController::OnTransportCandidatesRemoved_n);
dtls->ice_transport()->SignalRoleConflict.connect(
this, &JsepTransportController::OnTransportRoleConflict_n);
dtls->ice_transport()->SignalStateChanged.connect(
this, &JsepTransportController::OnTransportStateChanged_n);
dtls->ice_transport()->SignalIceTransportStateChanged.connect(
this, &JsepTransportController::OnTransportStateChanged_n);
dtls->ice_transport()->SignalCandidatePairChanged.connect(
this, &JsepTransportController::OnTransportCandidatePairChanged_n);
return dtls;
}
DtlsTransport::DtlsTransport(IceTransportInternal* ice_transport,
const webrtc::CryptoOptions& crypto_options,
webrtc::RtcEventLog* event_log)
: transport_name_(ice_transport->transport_name()),
component_(ice_transport->component()),
ice_transport_(ice_transport), / ice_transport 实际上就是 cricket::P2PTransportChannel
downward_(NULL),
srtp_ciphers_(crypto_options.GetSupportedDtlsSrtpCryptoSuites()),
ssl_max_version_(rtc::SSL_PROTOCOL_DTLS_12),
crypto_options_(crypto_options),
event_log_(event_log) {
RTC_DCHECK(ice_transport_);
ConnectToIceTransport(); //
}
void DtlsTransport::ConnectToIceTransport() {
RTC_DCHECK(ice_transport_); / ice_transport_ 实际上就是 cricket::P2PTransportChannel
ice_transport_->SignalWritableState.connect(this,
&DtlsTransport::OnWritableState);
ice_transport_->SignalReadPacket.connect(this, &DtlsTransport::OnReadPacket);
ice_transport_->SignalSentPacket.connect(this, &DtlsTransport::OnSentPacket); // 就是在这里设置了 cricket::P2PTransportChannel 的 信号-槽 函数
ice_transport_->SignalReadyToSend.connect(this,
&DtlsTransport::OnReadyToSend); 在这里设置了 cricket::P2PTransportChannel 的 SignalReadyToSend 信号-槽 函数
ice_transport_->SignalReceivingState.connect(
this, &DtlsTransport::OnReceivingState);
ice_transport_->SignalNetworkRouteChanged.connect(
this, &DtlsTransport::OnNetworkRouteChanged);
}
这里的 DtlsTransport 是 circket::DtlsTransport , 下面的 circket:: 是自己加上的,方便自己的理解
// class circket::DtlsTransportInternal : public rtc::PacketTransportInternal
// class circket::DtlsTransport : public circket::DtlsTransportInternal
// 下面的 SignalSentPacket 来自 circket::DtlsTransport 的父类 rtc::PacketTransportInternal
void DtlsTransport::OnSentPacket(rtc::PacketTransportInternal* transport,
const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(&thread_checker_);
SignalSentPacket(this, sent_packet); / DtlsTransport 中的 SignalSentPacket 是在哪里绑定的呢? 具体见下面分析
} /// 分析结果就是链接到了槽 RtpTransport::OnSentPacket 中
//
/// DtlsTransport 中的 SignalSentPacket 信号绑定分析
//
JsepTransportController::MaybeCreateJsepTransport
===>
rtc::scoped_refptr<webrtc::IceTransportInterface> ice =
CreateIceTransport(content_info.name, /*rtcp=*/false); / 返回的是包裹了 cricket::P2PTransportChannel 的 DefaultIceTransport 实例对象
RTC_DCHECK(ice); /// ice->internal() 返回的就是 DefaultIceTransport 包裹的 cricket::P2PTransportChannel 指针
std::unique_ptr<cricket::DtlsTransportInternal> rtp_dtls_transport =
CreateDtlsTransport(content_info, ice->internal()); / 这里返回的是 cricket::DtlsTransport
if (config_.disable_encryption) { /// config_.disable_encryption 默认为 false 所以这里不会创建 不加密 的 rtp transport
RTC_LOG(LS_INFO)
<< "Creating UnencryptedRtpTransport, becayse encryption is disabled.";
unencrypted_rtp_transport = CreateUnencryptedRtpTransport( / 返回 webrtc::RtpTransport
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get()); / 这里将 rtp_dtls_transport 传递进去,也就是将 cricket::DtlsTransport 传递进去
} else if (!content_desc->cryptos().empty()) { /// class webrtc::SrtpTransport : public webrtc::RtpTransport , 而 class webrtc::RtpTransport : public webrtc::RtpTransportInternal
sdes_transport = CreateSdesTransport( 返回 webrtc::SrtpTransport
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
RTC_LOG(LS_INFO) << "Creating SdesTransport.";
} else { class webrtc::DtlsSrtpTransport : public webrtc::SrtpTransport
RTC_LOG(LS_INFO) << "Creating DtlsSrtpTransport.";
dtls_srtp_transport = CreateDtlsSrtpTransport( / 返回 webrtc::DtlsSrtpTransport
content_info.name, rtp_dtls_transport.get(), rtcp_dtls_transport.get());
}
// class circket::DtlsTransport 的继承关系
// class circket::DtlsTransportInternal : public rtc::PacketTransportInternal
// class circket::DtlsTransport : public circket::DtlsTransportInternal
std::unique_ptr<webrtc::RtpTransport>
JsepTransportController::CreateUnencryptedRtpTransport(
const std::string& transport_name,
rtc::PacketTransportInternal* rtp_packet_transport, // 这里传递进来的实际上是 cricket::DtlsTransport
rtc::PacketTransportInternal* rtcp_packet_transport) {
RTC_DCHECK(network_thread_->IsCurrent());
auto unencrypted_rtp_transport =
std::make_unique<RtpTransport>(rtcp_packet_transport == nullptr); // class webrtc::RtpTransport : public webrtc::RtpTransportInternal
unencrypted_rtp_transport->SetRtpPacketTransport(rtp_packet_transport); rtp_packet_transport 就是 cricket::DtlsTransport 的指针
if (rtcp_packet_transport) {
unencrypted_rtp_transport->SetRtcpPacketTransport(rtcp_packet_transport);
}
return unencrypted_rtp_transport;
}
void RtpTransport::SetRtpPacketTransport(
rtc::PacketTransportInternal* new_packet_transport) { / 这里传递进来的 new_packet_transport 实际上是 cricket::DtlsTransport
if (new_packet_transport == rtp_packet_transport_) {
return;
}
if (rtp_packet_transport_) { / 这里传递进来的 new_packet_transport 实际上是 cricket::DtlsTransport
rtp_packet_transport_->SignalReadyToSend.disconnect(this);
rtp_packet_transport_->SignalReadPacket.disconnect(this);
rtp_packet_transport_->SignalNetworkRouteChanged.disconnect(this);
rtp_packet_transport_->SignalWritableState.disconnect(this);
rtp_packet_transport_->SignalSentPacket.disconnect(this);
// Reset the network route of the old transport.
SignalNetworkRouteChanged(absl::optional<rtc::NetworkRoute>()); /// SignalNetworkRouteChanged 来自 RtpTransport 的父类 webrtc::RtpTransportInternal
}
if (new_packet_transport) {
new_packet_transport->SignalReadyToSend.connect( 就是在这里设置了 cricket::DtlsTransport 的 SignalReadyToSend 信号的槽函数: RtpTransport::OnReadyToSend
this, &RtpTransport::OnReadyToSend);
new_packet_transport->SignalReadPacket.connect(this,
&RtpTransport::OnReadPacket);
new_packet_transport->SignalNetworkRouteChanged.connect(
this, &RtpTransport::OnNetworkRouteChanged);
new_packet_transport->SignalWritableState.connect(
this, &RtpTransport::OnWritableState);
new_packet_transport->SignalSentPacket.connect(this,
&RtpTransport::OnSentPacket); / 就是在这里设置的 cricket::DtlsTransport 的 SignalSentPacket 信号绑定关系
// Set the network route for the new transport.
SignalNetworkRouteChanged(new_packet_transport->network_route()); /// SignalNetworkRouteChanged 来自 RtpTransport 的父类 webrtc::RtpTransportInternal
}
rtp_packet_transport_ = new_packet_transport;
// Assumes the transport is ready to send if it is writable. If we are wrong,
// ready to send will be updated the next time we try to send.
SetReadyToSend(false,
rtp_packet_transport_ && rtp_packet_transport_->writable());
}
/ class webrtc::RtpTransport : public webrtc::RtpTransportInternal
/ webrtc::RtpTransport 中的信号 SignalSentPacket 实际上就是来自其父类 webrtc::RtpTransportInternal
/ JsepTransportController::CreateUnencryptedRtpTransport 中创建的 webrtc::RtpTransport
void RtpTransport::OnSentPacket(rtc::PacketTransportInternal* packet_transport, / 这里的 packet_transport 就是 cricket::DtlsTransport
const rtc::SentPacket& sent_packet) {
RTC_DCHECK(packet_transport == rtp_packet_transport_ ||
packet_transport == rtcp_packet_transport_);
SignalSentPacket(sent_packet); // 这里又来了一个信号, 这个信号在哪里设置的?见下面分析, 这个地方有点绕的
} / 提示: PeerConnection::CreateVoiceChannel PeerConnection::CreateVideoChannel PeerConnection::CreateDataChannel 中都会触发这个信号-槽的绑定关系 ,分析一个就行了
/// 实际上会触发 BaseChannel::SignalSentPacket_n
void BaseChannel::SignalSentPacket_n(const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(network_thread());
invoker_.AsyncInvoke<void>(RTC_FROM_HERE, worker_thread_,
[this, sent_packet] {
RTC_DCHECK_RUN_ON(worker_thread());
SignalSentPacket(sent_packet); 又来了。。。。。。 SignalSentPacket 就是来自 BaseChannel
}); PeerConnection::CreateVideoChannel 中在创建 ricket::VideoChannel 时就对 cricket::VideoChannel 进行了 SignalSentPacket 信号的绑定,
将其绑定到了 PeerConnection::OnSentPacket_w
}
void PeerConnection::OnSentPacket_w(const rtc::SentPacket& sent_packet) {
RTC_DCHECK_RUN_ON(worker_thread());
RTC_DCHECK(call_);
call_->OnSentPacket(sent_packet); / 至此终于没有信号了。。。。。。 在下面会分析 call 的创建以及使用,具体见下方的 “ PeerConnection 中的 call ”
} 这里的 call_ 实际上就是 internal::Call 具体见下面分析
/// internal::Call 的继承关系
class internal::Call final : public webrtc::Call,
public PacketReceiver,
public RecoveredPacketReceiver,
public TargetTransferRateObserver,
public BitrateAllocator::LimitObserver
void internal::Call::OnSentPacket(const rtc::SentPacket& sent_packet) {
video_send_delay_stats_->OnSentPacket(sent_packet.packet_id,
clock_->TimeInMilliseconds());
transport_send_ptr_->OnSentPacket(sent_packet); / 这些地方就用到 internal::Call 里面详细的细节了
} /// transport_send_ptr_ 实际上就是 webrtc::RtpTransportControllerSend 指针, 具体见下面分析
void RtpTransportControllerSend::OnSentPacket(
const rtc::SentPacket& sent_packet) {
task_queue_.PostTask([this, sent_packet]() {
RTC_DCHECK_RUN_ON(&task_queue_);
absl::optional<SentPacket> packet_msg =
transport_feedback_adapter_.ProcessSentPacket(sent_packet); /// 这里后面再进行分析
pacer()->UpdateOutstandingData(
transport_feedback_adapter_.GetOutstandingData()); // 这里后面再进行分析
if (packet_msg && controller_)
PostUpdates(controller_->OnSentPacket(*packet_msg)); 这里后面再进行分析
});
}
/// AllocationSequence::CreateStunPorts /
void AllocationSequence::CreateStunPorts() {
if (IsFlagSet(PORTALLOCATOR_DISABLE_STUN)) {
RTC_LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
return;
}
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET)) { // PeerConnection::InitializePortAllocator_n 中针对 allocator 设置了新的 flags_ , 见上面分析 ///
return; // 此处会进入这个分支,也就是直接返回
}
if (!(config_ && !config_->StunServers().empty())) {
RTC_LOG(LS_WARNING)
<< "AllocationSequence: No STUN server configured, skipping.";
return;
}
std::unique_ptr<StunPort> port = StunPort::Create(
session_->network_thread(), session_->socket_factory(), network_,
session_->allocator()->min_port(), session_->allocator()->max_port(),
session_->username(), session_->password(), config_->StunServers(),
session_->allocator()->origin(),
session_->allocator()->stun_candidate_keepalive_interval());
if (port) {
session_->AddAllocatedPort(port.release(), this, true); //
// Since StunPort is not created using shared socket, |port| will not be
// added to the dequeue.
}
}