Server Reflexive Candidate,是通过主机候选地址向STUN服务器发送STUN请求获得的网络地址。实际上就是终端的网络包经过一重或多重NAT穿透之后,由STUN服务器观察到的经过NAT转换之后的地址。

解析StunBindingResponse过程image.png

UDPPort::OnReadPacket

image.png
如果之前有向stun 服务器发送过请求,则serveraddresses会有记录,可以直接查找得到,这里得到的是reponse消息。UDPPort::OnResolveResult中插入到serveraddresses

StunBindingRequest::OnResponse

H:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\base\stun_port.cc
image.png

  1. class StunBindingRequest : public StunRequest {
  2. void OnResponse(StunMessage* response) override {
  3. const StunAddressAttribute* addr_attr =
  4. response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
  5. if (!addr_attr) {
  6. RTC_LOG(LS_ERROR) << "Binding response missing mapped address.";
  7. } else if (addr_attr->family() != STUN_ADDRESS_IPV4 &&
  8. addr_attr->family() != STUN_ADDRESS_IPV6) {
  9. RTC_LOG(LS_ERROR) << "Binding address has bad family";
  10. } else {
  11. rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port());
  12. port_->OnStunBindingRequestSucceeded(this->Elapsed(), server_addr_, addr);
  13. }
  14. // The keep-alive requests will be stopped after its lifetime has passed.
  15. if (WithinLifetime(rtc::TimeMillis())) {
  16. port_->requests_.SendDelayed(
  17. new StunBindingRequest(port_, server_addr_, start_time_),
  18. port_->stun_keepalive_delay());
  19. }
  20. }
  21. }

UDPPort::OnStunBindingRequestSucceeded

image.png

  1. void UDPPort::OnStunBindingRequestSucceeded(
  2. int rtt_ms,
  3. const rtc::SocketAddress& stun_server_addr,
  4. const rtc::SocketAddress& stun_reflected_addr) {
  5. RTC_DCHECK(stats_.stun_binding_responses_received <
  6. stats_.stun_binding_requests_sent);
  7. stats_.stun_binding_responses_received++;
  8. stats_.stun_binding_rtt_ms_total += rtt_ms;
  9. stats_.stun_binding_rtt_ms_squared_total += rtt_ms * rtt_ms;
  10. if (bind_request_succeeded_servers_.find(stun_server_addr) !=
  11. bind_request_succeeded_servers_.end()) {
  12. return;
  13. }
  14. bind_request_succeeded_servers_.insert(stun_server_addr);
  15. // If socket is shared and |stun_reflected_addr| is equal to local socket
  16. // address, or if the same address has been added by another STUN server,
  17. // then discarding the stun address.
  18. // For STUN, related address is the local socket address.
  19. if ((!SharedSocket() || stun_reflected_addr != socket_->GetLocalAddress()) &&
  20. !HasCandidateWithAddress(stun_reflected_addr)) {
  21. rtc::SocketAddress related_address = socket_->GetLocalAddress();
  22. // If we can't stamp the related address correctly, empty it to avoid leak.
  23. if (!MaybeSetDefaultLocalAddress(&related_address)) {
  24. related_address =
  25. rtc::EmptySocketAddressWithFamily(related_address.family());
  26. }
  27. rtc::StringBuilder url;
  28. url << "stun:" << stun_server_addr.ipaddr().ToString() << ":"
  29. << stun_server_addr.port();
  30. AddAddress(stun_reflected_addr, socket_->GetLocalAddress(), related_address,
  31. UDP_PROTOCOL_NAME, "", "", STUN_PORT_TYPE,
  32. ICE_TYPE_PREFERENCE_SRFLX, 0, url.str(), false);
  33. }
  34. MaybeSetPortCompleteOrError();
  35. }