Server Reflexive Candidate,是通过主机候选地址向STUN服务器发送STUN请求获得的网络地址。实际上就是终端的网络包经过一重或多重NAT穿透之后,由STUN服务器观察到的经过NAT转换之后的地址。
解析StunBindingResponse过程
UDPPort::OnReadPacket
如果之前有向stun 服务器发送过请求,则serveraddresses会有记录,可以直接查找得到,这里得到的是reponse消息。UDPPort::OnResolveResult中插入到serveraddresses。
StunBindingRequest::OnResponse
H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\stun_port.cc
class StunBindingRequest : public StunRequest {
void OnResponse(StunMessage* response) override {
const StunAddressAttribute* addr_attr =
response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
if (!addr_attr) {
RTC_LOG(LS_ERROR) << "Binding response missing mapped address.";
} else if (addr_attr->family() != STUN_ADDRESS_IPV4 &&
addr_attr->family() != STUN_ADDRESS_IPV6) {
RTC_LOG(LS_ERROR) << "Binding address has bad family";
} else {
rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port());
port_->OnStunBindingRequestSucceeded(this->Elapsed(), server_addr_, addr);
}
// The keep-alive requests will be stopped after its lifetime has passed.
if (WithinLifetime(rtc::TimeMillis())) {
port_->requests_.SendDelayed(
new StunBindingRequest(port_, server_addr_, start_time_),
port_->stun_keepalive_delay());
}
}
}
UDPPort::OnStunBindingRequestSucceeded
void UDPPort::OnStunBindingRequestSucceeded(
int rtt_ms,
const rtc::SocketAddress& stun_server_addr,
const rtc::SocketAddress& stun_reflected_addr) {
RTC_DCHECK(stats_.stun_binding_responses_received <
stats_.stun_binding_requests_sent);
stats_.stun_binding_responses_received++;
stats_.stun_binding_rtt_ms_total += rtt_ms;
stats_.stun_binding_rtt_ms_squared_total += rtt_ms * rtt_ms;
if (bind_request_succeeded_servers_.find(stun_server_addr) !=
bind_request_succeeded_servers_.end()) {
return;
}
bind_request_succeeded_servers_.insert(stun_server_addr);
// If socket is shared and |stun_reflected_addr| is equal to local socket
// address, or if the same address has been added by another STUN server,
// then discarding the stun address.
// For STUN, related address is the local socket address.
if ((!SharedSocket() || stun_reflected_addr != socket_->GetLocalAddress()) &&
!HasCandidateWithAddress(stun_reflected_addr)) {
rtc::SocketAddress related_address = socket_->GetLocalAddress();
// If we can't stamp the related address correctly, empty it to avoid leak.
if (!MaybeSetDefaultLocalAddress(&related_address)) {
related_address =
rtc::EmptySocketAddressWithFamily(related_address.family());
}
rtc::StringBuilder url;
url << "stun:" << stun_server_addr.ipaddr().ToString() << ":"
<< stun_server_addr.port();
AddAddress(stun_reflected_addr, socket_->GetLocalAddress(), related_address,
UDP_PROTOCOL_NAME, "", "", STUN_PORT_TYPE,
ICE_TYPE_PREFERENCE_SRFLX, 0, url.str(), false);
}
MaybeSetPortCompleteOrError();
}