本节主要说的是发送AllocateRequest到turn服务器的过程。
STUN/TURN消息类型
发送AllocateRequest调用栈
AllocationSequence::CreateRelayPorts
h:\webrtc-20210315\webrtc-20210315\webrtc\webrtc-checkout\src\p2p\client\basic_port_allocator.cc
AllocationSequence::CreateTurnPort
一般只有一个ports,所以循环一般只执行一遍。
void AllocationSequence::CreateTurnPort(const RelayServerConfig& config) {
PortList::const_iterator relay_port;
for (relay_port = config.ports.begin(); relay_port != config.ports.end();
++relay_port) {
// Skip UDP connections to relay servers if it's disallowed.
if (IsFlagSet(PORTALLOCATOR_DISABLE_UDP_RELAY) &&
relay_port->proto == PROTO_UDP) {
continue;
}
// Do not create a port if the server address family is known and does
// not match the local IP address family.
int server_ip_family = relay_port->address.ipaddr().family();
int local_ip_family = network_->GetBestIP().family();
if (server_ip_family != AF_UNSPEC && server_ip_family != local_ip_family) {
RTC_LOG(LS_INFO)
<< "Server and local address families are not compatible. "
"Server address: "
<< relay_port->address.ipaddr().ToSensitiveString()
<< " Local address: " << network_->GetBestIP().ToSensitiveString();
continue;
}
CreateRelayPortArgs args;
args.network_thread = session_->network_thread();
args.socket_factory = session_->socket_factory();
args.network = network_;
args.username = session_->username();
args.password = session_->password();
args.server_address = &(*relay_port);
args.config = &config;
args.origin = session_->allocator()->origin();
args.turn_customizer = session_->allocator()->turn_customizer();
std::unique_ptr<cricket::Port> port;
// Shared socket mode must be enabled only for UDP based ports. Hence
// don't pass shared socket for ports which will create TCP sockets.
// TODO(mallinath) - Enable shared socket mode for TURN ports. Disabled
// due to webrtc bug https://code.google.com/p/webrtc/issues/detail?id=3537
if (IsFlagSet(PORTALLOCATOR_ENABLE_SHARED_SOCKET) &&
relay_port->proto == PROTO_UDP && udp_socket_) {
port = session_->allocator()->relay_port_factory()->Create(
args, udp_socket_.get());
if (!port) {
RTC_LOG(LS_WARNING) << "Failed to create relay port with "
<< args.server_address->address.ToSensitiveString();
continue;
}
relay_ports_.push_back(port.get());
// Listen to the port destroyed signal, to allow AllocationSequence to
// remove the entry from it's map.
port->SubscribePortDestroyed(
[this](PortInterface* port) { OnPortDestroyed(port); });
} else {
port = session_->allocator()->relay_port_factory()->Create(
args, session_->allocator()->min_port(),
session_->allocator()->max_port());
if (!port) {
RTC_LOG(LS_WARNING) << "Failed to create relay port with "
<< args.server_address->address.ToSensitiveString();
continue;
}
}
RTC_DCHECK(port != NULL);
session_->AddAllocatedPort(port.release(), this, true);
}
}
BasicPortAllocatorSession::AddAllocatedPort
void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
AllocationSequence* seq,
bool prepare_address) {
RTC_DCHECK_RUN_ON(network_thread_);
if (!port)
return;
RTC_LOG(LS_INFO) << "Adding allocated port for " << content_name();
port->set_content_name(content_name());
port->set_component(component());
port->set_generation(generation());
if (allocator_->proxy().type != rtc::PROXY_NONE)
port->set_proxy(allocator_->user_agent(), allocator_->proxy());
port->set_send_retransmit_count_attribute(
(flags() & PORTALLOCATOR_ENABLE_STUN_RETRANSMIT_ATTRIBUTE) != 0);
PortData data(port, seq);
ports_.push_back(data);
port->SignalCandidateReady.connect(
this, &BasicPortAllocatorSession::OnCandidateReady);
port->SignalCandidateError.connect(
this, &BasicPortAllocatorSession::OnCandidateError);
port->SignalPortComplete.connect(this,
&BasicPortAllocatorSession::OnPortComplete);
port->SubscribePortDestroyed(
[this](PortInterface* port) { OnPortDestroyed(port); });
port->SignalPortError.connect(this, &BasicPortAllocatorSession::OnPortError);
RTC_LOG(LS_INFO) << port->ToString() << ": Added port to allocator";
if (prepare_address)
port->PrepareAddress();
}
TurnPort::PrepareAddress
void TurnPort::PrepareAddress() {
if (credentials_.username.empty() || credentials_.password.empty()) {
RTC_LOG(LS_ERROR) << "Allocation can't be started without setting the"
" TURN server credentials for the user.";
OnAllocateError(STUN_ERROR_UNAUTHORIZED,
"Missing TURN server credentials.");
return;
}
if (!server_address_.address.port()) {
// We will set default TURN port, if no port is set in the address.
server_address_.address.SetPort(TURN_DEFAULT_PORT);
}
if (!AllowedTurnPort(server_address_.address.port())) {
// This can only happen after a 300 ALTERNATE SERVER, since the port can't
// be created with a disallowed port number.
RTC_LOG(LS_ERROR) << "Attempt to start allocation with disallowed port# "
<< server_address_.address.port();
OnAllocateError(STUN_ERROR_SERVER_ERROR,
"Attempt to start allocation to a disallowed port");
return;
}
if (server_address_.address.IsUnresolvedIP()) {
ResolveTurnAddress(server_address_.address);
} else {
// If protocol family of server address doesn't match with local, return.
if (!IsCompatibleAddress(server_address_.address)) {
RTC_LOG(LS_ERROR) << "IP address family does not match. server: "
<< server_address_.address.family()
<< " local: " << Network()->GetBestIP().family();
OnAllocateError(STUN_ERROR_GLOBAL_FAILURE,
"IP address family does not match.");
return;
}
// Insert the current address to prevent redirection pingpong.
attempted_server_addresses_.insert(server_address_.address);
RTC_LOG(LS_INFO) << ToString() << ": Trying to connect to TURN server via "
<< ProtoToString(server_address_.proto) << " @ "
<< server_address_.address.ToSensitiveString();
if (!CreateTurnClientSocket()) {
RTC_LOG(LS_ERROR) << "Failed to create TURN client socket";
OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
"Failed to create TURN client socket.");
return;
}
if (server_address_.proto == PROTO_UDP) {
// If its UDP, send AllocateRequest now.
// For TCP and TLS AllcateRequest will be sent by OnSocketConnect.
SendRequest(new TurnAllocateRequest(this), 0);
}
}
}
TurnPort::ResolveTurnAddress域名解析
TurnPort::OnResolveResult
void TurnPort::OnResolveResult(rtc::AsyncResolverInterface* resolver) {
RTC_DCHECK(resolver == resolver_);
// If DNS resolve is failed when trying to connect to the server using TCP,
// one of the reason could be due to DNS queries blocked by firewall.
// In such cases we will try to connect to the server with hostname, assuming
// socket layer will resolve the hostname through a HTTP proxy (if any).
if (resolver_->GetError() != 0 && (server_address_.proto == PROTO_TCP ||
server_address_.proto == PROTO_TLS)) {
if (!CreateTurnClientSocket()) {
OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
"TURN host lookup received error.");
}
return;
}
// Copy the original server address in |resolved_address|. For TLS based
// sockets we need hostname along with resolved address.
rtc::SocketAddress resolved_address = server_address_.address;
if (resolver_->GetError() != 0 ||
!resolver_->GetResolvedAddress(Network()->GetBestIP().family(),
&resolved_address)) {
RTC_LOG(LS_WARNING) << ToString() << ": TURN host lookup received error "
<< resolver_->GetError();
error_ = resolver_->GetError();
OnAllocateError(SERVER_NOT_REACHABLE_ERROR,
"TURN host lookup received error.");
return;
}
// Signal needs both resolved and unresolved address. After signal is sent
// we can copy resolved address back into |server_address_|.
SignalResolvedServerAddress(this, server_address_.address, resolved_address);
server_address_.address = resolved_address;
PrepareAddress();
}
域名解析完成后,再次回到 TurnPort::PrepareAddress