本节主要是说webrtc收到turn服务器发过来的AllocateResponse后的做法过程。

接收处理AllocateResponse调用栈

image.png
最后是OnAllocateSuccess之后生成turn类型的candidate。

AllocationSequence::OnReadpacket

image.png
判断是否是某个replay服务器发过来的消息。如果不是,则判断是否是其他webrtc发过来的,会判断udpport是否创建成功。。

  1. void AllocationSequence::OnReadPacket(rtc::AsyncPacketSocket* socket,
  2. const char* data,
  3. size_t size,
  4. const rtc::SocketAddress& remote_addr,
  5. const int64_t& packet_time_us) {
  6. RTC_DCHECK(socket == udp_socket_.get());
  7. bool turn_port_found = false;
  8. // Try to find the TurnPort that matches the remote address. Note that the
  9. // message could be a STUN binding response if the TURN server is also used as
  10. // a STUN server. We don't want to parse every message here to check if it is
  11. // a STUN binding response, so we pass the message to TurnPort regardless of
  12. // the message type. The TurnPort will just ignore the message since it will
  13. // not find any request by transaction ID.
  14. for (auto* port : relay_ports_) {
  15. if (port->CanHandleIncomingPacketsFrom(remote_addr)) {
  16. if (port->HandleIncomingPacket(socket, data, size, remote_addr,
  17. packet_time_us)) {
  18. return;
  19. }
  20. turn_port_found = true;
  21. }
  22. }
  23. if (udp_port_) {
  24. const ServerAddresses& stun_servers = udp_port_->server_addresses();
  25. // Pass the packet to the UdpPort if there is no matching TurnPort, or if
  26. // the TURN server is also a STUN server.
  27. if (!turn_port_found ||
  28. stun_servers.find(remote_addr) != stun_servers.end()) {
  29. RTC_DCHECK(udp_port_->SharedSocket());
  30. udp_port_->HandleIncomingPacket(socket, data, size, remote_addr,
  31. packet_time_us);
  32. }
  33. }
  34. }

TurnPort::HandleIncomingPacket

image.png
StunRequestManager::CheckResponse(const char data, size_t size)
-》
StunRequestManager::CheckResponse(StunMessage
msg)
—》
TurnAllocateRequest::OnResponse

TurnAllocateRequest::OnResponse

image.png

1、从映射中获取本机外网的映射地址
2、获取relay服务器的地址
3、生成candidate

  1. void TurnAllocateRequest::OnResponse(StunMessage* response) {
  2. RTC_LOG(LS_INFO) << port_->ToString()
  3. << ": TURN allocate requested successfully, id="
  4. << rtc::hex_encode(id())
  5. << ", code=0" // Makes logging easier to parse.
  6. ", rtt="
  7. << Elapsed();
  8. // Check mandatory attributes as indicated in RFC5766, Section 6.3.
  9. const StunAddressAttribute* mapped_attr =
  10. response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
  11. if (!mapped_attr) {
  12. RTC_LOG(LS_WARNING) << port_->ToString()
  13. << ": Missing STUN_ATTR_XOR_MAPPED_ADDRESS "
  14. "attribute in allocate success response";
  15. return;
  16. }
  17. // Using XOR-Mapped-Address for stun.
  18. port_->OnStunAddress(mapped_attr->GetAddress());
  19. const StunAddressAttribute* relayed_attr =
  20. response->GetAddress(STUN_ATTR_XOR_RELAYED_ADDRESS);
  21. if (!relayed_attr) {
  22. RTC_LOG(LS_WARNING) << port_->ToString()
  23. << ": Missing STUN_ATTR_XOR_RELAYED_ADDRESS "
  24. "attribute in allocate success response";
  25. return;
  26. }
  27. const StunUInt32Attribute* lifetime_attr =
  28. response->GetUInt32(STUN_ATTR_TURN_LIFETIME);
  29. if (!lifetime_attr) {
  30. RTC_LOG(LS_WARNING) << port_->ToString()
  31. << ": Missing STUN_ATTR_TURN_LIFETIME attribute in "
  32. "allocate success response";
  33. return;
  34. }
  35. // Notify the port the allocate succeeded, and schedule a refresh request.
  36. port_->OnAllocateSuccess(relayed_attr->GetAddress(),
  37. mapped_attr->GetAddress());
  38. port_->ScheduleRefresh(lifetime_attr->value());
  39. }

TurnPort::OnAllocateSuccess

image.png

  1. void TurnPort::OnAllocateSuccess(const rtc::SocketAddress& address,
  2. const rtc::SocketAddress& stun_address) {
  3. state_ = STATE_READY;
  4. rtc::SocketAddress related_address = stun_address;
  5. // For relayed candidate, Base is the candidate itself.
  6. AddAddress(address, // Candidate address.
  7. address, // Base address.
  8. related_address, // Related address.
  9. UDP_PROTOCOL_NAME,
  10. ProtoToString(server_address_.proto), // The first hop protocol.
  11. "", // TCP canddiate type, empty for turn candidates.
  12. RELAY_PORT_TYPE, GetRelayPreference(server_address_.proto),
  13. server_priority_, ReconstructedServerUrl(false /* use_hostname */),
  14. true);
  15. }