• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "p2p/base/stun_port.h"
12 
13 #include <utility>
14 #include <vector>
15 
16 #include "api/transport/stun.h"
17 #include "p2p/base/connection.h"
18 #include "p2p/base/p2p_constants.h"
19 #include "p2p/base/port_allocator.h"
20 #include "rtc_base/checks.h"
21 #include "rtc_base/helpers.h"
22 #include "rtc_base/ip_address.h"
23 #include "rtc_base/logging.h"
24 #include "rtc_base/net_helpers.h"
25 #include "rtc_base/strings/string_builder.h"
26 
27 namespace cricket {
28 
29 // TODO(?): Move these to a common place (used in relayport too)
30 const int RETRY_TIMEOUT = 50 * 1000;  // 50 seconds
31 
32 // Stop logging errors in UDPPort::SendTo after we have logged
33 // |kSendErrorLogLimit| messages. Start again after a successful send.
34 const int kSendErrorLogLimit = 5;
35 
36 // Handles a binding request sent to the STUN server.
37 class StunBindingRequest : public StunRequest {
38  public:
StunBindingRequest(UDPPort * port,const rtc::SocketAddress & addr,int64_t start_time)39   StunBindingRequest(UDPPort* port,
40                      const rtc::SocketAddress& addr,
41                      int64_t start_time)
42       : port_(port), server_addr_(addr), start_time_(start_time) {}
43 
server_addr() const44   const rtc::SocketAddress& server_addr() const { return server_addr_; }
45 
Prepare(StunMessage * request)46   void Prepare(StunMessage* request) override {
47     request->SetType(STUN_BINDING_REQUEST);
48   }
49 
OnResponse(StunMessage * response)50   void OnResponse(StunMessage* response) override {
51     const StunAddressAttribute* addr_attr =
52         response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
53     if (!addr_attr) {
54       RTC_LOG(LS_ERROR) << "Binding response missing mapped address.";
55     } else if (addr_attr->family() != STUN_ADDRESS_IPV4 &&
56                addr_attr->family() != STUN_ADDRESS_IPV6) {
57       RTC_LOG(LS_ERROR) << "Binding address has bad family";
58     } else {
59       rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port());
60       port_->OnStunBindingRequestSucceeded(this->Elapsed(), server_addr_, addr);
61     }
62 
63     // The keep-alive requests will be stopped after its lifetime has passed.
64     if (WithinLifetime(rtc::TimeMillis())) {
65       port_->requests_.SendDelayed(
66           new StunBindingRequest(port_, server_addr_, start_time_),
67           port_->stun_keepalive_delay());
68     }
69   }
70 
OnErrorResponse(StunMessage * response)71   void OnErrorResponse(StunMessage* response) override {
72     const StunErrorCodeAttribute* attr = response->GetErrorCode();
73     if (!attr) {
74       RTC_LOG(LS_ERROR) << "Missing binding response error code.";
75     } else {
76       RTC_LOG(LS_ERROR) << "Binding error response:"
77                            " class="
78                         << attr->eclass() << " number=" << attr->number()
79                         << " reason=" << attr->reason();
80     }
81 
82     port_->OnStunBindingOrResolveRequestFailed(
83         server_addr_, attr ? attr->number() : STUN_ERROR_GLOBAL_FAILURE,
84         attr ? attr->reason()
85              : "STUN binding response with no error code attribute.");
86 
87     int64_t now = rtc::TimeMillis();
88     if (WithinLifetime(now) &&
89         rtc::TimeDiff(now, start_time_) < RETRY_TIMEOUT) {
90       port_->requests_.SendDelayed(
91           new StunBindingRequest(port_, server_addr_, start_time_),
92           port_->stun_keepalive_delay());
93     }
94   }
OnTimeout()95   void OnTimeout() override {
96     RTC_LOG(LS_ERROR) << "Binding request timed out from "
97                       << port_->GetLocalAddress().ToSensitiveString() << " ("
98                       << port_->Network()->name() << ")";
99     port_->OnStunBindingOrResolveRequestFailed(
100         server_addr_, SERVER_NOT_REACHABLE_ERROR,
101         "STUN allocate request timed out.");
102   }
103 
104  private:
105   // Returns true if |now| is within the lifetime of the request (a negative
106   // lifetime means infinite).
WithinLifetime(int64_t now) const107   bool WithinLifetime(int64_t now) const {
108     int lifetime = port_->stun_keepalive_lifetime();
109     return lifetime < 0 || rtc::TimeDiff(now, start_time_) <= lifetime;
110   }
111 
112   UDPPort* port_;
113   const rtc::SocketAddress server_addr_;
114 
115   int64_t start_time_;
116 };
117 
AddressResolver(rtc::PacketSocketFactory * factory)118 UDPPort::AddressResolver::AddressResolver(rtc::PacketSocketFactory* factory)
119     : socket_factory_(factory) {}
120 
~AddressResolver()121 UDPPort::AddressResolver::~AddressResolver() {
122   for (ResolverMap::iterator it = resolvers_.begin(); it != resolvers_.end();
123        ++it) {
124     // TODO(guoweis): Change to asynchronous DNS resolution to prevent the hang
125     // when passing true to the Destroy() which is a safer way to avoid the code
126     // unloaded before the thread exits. Please see webrtc bug 5139.
127     it->second->Destroy(false);
128   }
129 }
130 
Resolve(const rtc::SocketAddress & address)131 void UDPPort::AddressResolver::Resolve(const rtc::SocketAddress& address) {
132   if (resolvers_.find(address) != resolvers_.end())
133     return;
134 
135   rtc::AsyncResolverInterface* resolver =
136       socket_factory_->CreateAsyncResolver();
137   resolvers_.insert(std::pair<rtc::SocketAddress, rtc::AsyncResolverInterface*>(
138       address, resolver));
139 
140   resolver->SignalDone.connect(this,
141                                &UDPPort::AddressResolver::OnResolveResult);
142 
143   resolver->Start(address);
144 }
145 
GetResolvedAddress(const rtc::SocketAddress & input,int family,rtc::SocketAddress * output) const146 bool UDPPort::AddressResolver::GetResolvedAddress(
147     const rtc::SocketAddress& input,
148     int family,
149     rtc::SocketAddress* output) const {
150   ResolverMap::const_iterator it = resolvers_.find(input);
151   if (it == resolvers_.end())
152     return false;
153 
154   return it->second->GetResolvedAddress(family, output);
155 }
156 
OnResolveResult(rtc::AsyncResolverInterface * resolver)157 void UDPPort::AddressResolver::OnResolveResult(
158     rtc::AsyncResolverInterface* resolver) {
159   for (ResolverMap::iterator it = resolvers_.begin(); it != resolvers_.end();
160        ++it) {
161     if (it->second == resolver) {
162       SignalDone(it->first, resolver->GetError());
163       return;
164     }
165   }
166 }
167 
UDPPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,rtc::AsyncPacketSocket * socket,const std::string & username,const std::string & password,const std::string & origin,bool emit_local_for_anyaddress)168 UDPPort::UDPPort(rtc::Thread* thread,
169                  rtc::PacketSocketFactory* factory,
170                  rtc::Network* network,
171                  rtc::AsyncPacketSocket* socket,
172                  const std::string& username,
173                  const std::string& password,
174                  const std::string& origin,
175                  bool emit_local_for_anyaddress)
176     : Port(thread, LOCAL_PORT_TYPE, factory, network, username, password),
177       requests_(thread),
178       socket_(socket),
179       error_(0),
180       ready_(false),
181       stun_keepalive_delay_(STUN_KEEPALIVE_INTERVAL),
182       dscp_(rtc::DSCP_NO_CHANGE),
183       emit_local_for_anyaddress_(emit_local_for_anyaddress) {
184   requests_.set_origin(origin);
185 }
186 
UDPPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,uint16_t min_port,uint16_t max_port,const std::string & username,const std::string & password,const std::string & origin,bool emit_local_for_anyaddress)187 UDPPort::UDPPort(rtc::Thread* thread,
188                  rtc::PacketSocketFactory* factory,
189                  rtc::Network* network,
190                  uint16_t min_port,
191                  uint16_t max_port,
192                  const std::string& username,
193                  const std::string& password,
194                  const std::string& origin,
195                  bool emit_local_for_anyaddress)
196     : Port(thread,
197            LOCAL_PORT_TYPE,
198            factory,
199            network,
200            min_port,
201            max_port,
202            username,
203            password),
204       requests_(thread),
205       socket_(nullptr),
206       error_(0),
207       ready_(false),
208       stun_keepalive_delay_(STUN_KEEPALIVE_INTERVAL),
209       dscp_(rtc::DSCP_NO_CHANGE),
210       emit_local_for_anyaddress_(emit_local_for_anyaddress) {
211   requests_.set_origin(origin);
212 }
213 
Init()214 bool UDPPort::Init() {
215   stun_keepalive_lifetime_ = GetStunKeepaliveLifetime();
216   if (!SharedSocket()) {
217     RTC_DCHECK(socket_ == nullptr);
218     socket_ = socket_factory()->CreateUdpSocket(
219         rtc::SocketAddress(Network()->GetBestIP(), 0), min_port(), max_port());
220     if (!socket_) {
221       RTC_LOG(LS_WARNING) << ToString() << ": UDP socket creation failed";
222       return false;
223     }
224     socket_->SignalReadPacket.connect(this, &UDPPort::OnReadPacket);
225   }
226   socket_->SignalSentPacket.connect(this, &UDPPort::OnSentPacket);
227   socket_->SignalReadyToSend.connect(this, &UDPPort::OnReadyToSend);
228   socket_->SignalAddressReady.connect(this, &UDPPort::OnLocalAddressReady);
229   requests_.SignalSendPacket.connect(this, &UDPPort::OnSendPacket);
230   return true;
231 }
232 
~UDPPort()233 UDPPort::~UDPPort() {
234   if (!SharedSocket())
235     delete socket_;
236 }
237 
PrepareAddress()238 void UDPPort::PrepareAddress() {
239   RTC_DCHECK(requests_.empty());
240   if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) {
241     OnLocalAddressReady(socket_, socket_->GetLocalAddress());
242   }
243 }
244 
MaybePrepareStunCandidate()245 void UDPPort::MaybePrepareStunCandidate() {
246   // Sending binding request to the STUN server if address is available to
247   // prepare STUN candidate.
248   if (!server_addresses_.empty()) {
249     SendStunBindingRequests();
250   } else {
251     // Port is done allocating candidates.
252     MaybeSetPortCompleteOrError();
253   }
254 }
255 
CreateConnection(const Candidate & address,CandidateOrigin origin)256 Connection* UDPPort::CreateConnection(const Candidate& address,
257                                       CandidateOrigin origin) {
258   if (!SupportsProtocol(address.protocol())) {
259     return nullptr;
260   }
261 
262   if (!IsCompatibleAddress(address.address())) {
263     return nullptr;
264   }
265 
266   // In addition to DCHECK-ing the non-emptiness of local candidates, we also
267   // skip this Port with null if there are latent bugs to violate it; otherwise
268   // it would lead to a crash when accessing the local candidate of the
269   // connection that would be created below.
270   if (Candidates().empty()) {
271     RTC_NOTREACHED();
272     return nullptr;
273   }
274   // When the socket is shared, the srflx candidate is gathered by the UDPPort.
275   // The assumption here is that
276   //  1) if the IP concealment with mDNS is not enabled, the gathering of the
277   //     host candidate of this port (which is synchronous),
278   //  2) or otherwise if enabled, the start of name registration of the host
279   //     candidate (as the start of asynchronous gathering)
280   // is always before the gathering of a srflx candidate (and any prflx
281   // candidate).
282   //
283   // See also the definition of MdnsNameRegistrationStatus::kNotStarted in
284   // port.h.
285   RTC_DCHECK(!SharedSocket() || Candidates()[0].type() == LOCAL_PORT_TYPE ||
286              mdns_name_registration_status() !=
287                  MdnsNameRegistrationStatus::kNotStarted);
288 
289   Connection* conn = new ProxyConnection(this, 0, address);
290   AddOrReplaceConnection(conn);
291   return conn;
292 }
293 
SendTo(const void * data,size_t size,const rtc::SocketAddress & addr,const rtc::PacketOptions & options,bool payload)294 int UDPPort::SendTo(const void* data,
295                     size_t size,
296                     const rtc::SocketAddress& addr,
297                     const rtc::PacketOptions& options,
298                     bool payload) {
299   rtc::PacketOptions modified_options(options);
300   CopyPortInformationToPacketInfo(&modified_options.info_signaled_after_sent);
301   int sent = socket_->SendTo(data, size, addr, modified_options);
302   if (sent < 0) {
303     error_ = socket_->GetError();
304     // Rate limiting added for crbug.com/856088.
305     // TODO(webrtc:9622): Use general rate limiting mechanism once it exists.
306     if (send_error_count_ < kSendErrorLogLimit) {
307       ++send_error_count_;
308       RTC_LOG(LS_ERROR) << ToString() << ": UDP send of " << size
309                         << " bytes failed with error " << error_;
310     }
311   } else {
312     send_error_count_ = 0;
313   }
314   return sent;
315 }
316 
UpdateNetworkCost()317 void UDPPort::UpdateNetworkCost() {
318   Port::UpdateNetworkCost();
319   stun_keepalive_lifetime_ = GetStunKeepaliveLifetime();
320 }
321 
StunDscpValue() const322 rtc::DiffServCodePoint UDPPort::StunDscpValue() const {
323   return dscp_;
324 }
325 
SetOption(rtc::Socket::Option opt,int value)326 int UDPPort::SetOption(rtc::Socket::Option opt, int value) {
327   if (opt == rtc::Socket::OPT_DSCP) {
328     // Save value for future packets we instantiate.
329     dscp_ = static_cast<rtc::DiffServCodePoint>(value);
330   }
331   return socket_->SetOption(opt, value);
332 }
333 
GetOption(rtc::Socket::Option opt,int * value)334 int UDPPort::GetOption(rtc::Socket::Option opt, int* value) {
335   return socket_->GetOption(opt, value);
336 }
337 
GetError()338 int UDPPort::GetError() {
339   return error_;
340 }
341 
HandleIncomingPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,int64_t packet_time_us)342 bool UDPPort::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
343                                    const char* data,
344                                    size_t size,
345                                    const rtc::SocketAddress& remote_addr,
346                                    int64_t packet_time_us) {
347   // All packets given to UDP port will be consumed.
348   OnReadPacket(socket, data, size, remote_addr, packet_time_us);
349   return true;
350 }
351 
SupportsProtocol(const std::string & protocol) const352 bool UDPPort::SupportsProtocol(const std::string& protocol) const {
353   return protocol == UDP_PROTOCOL_NAME;
354 }
355 
GetProtocol() const356 ProtocolType UDPPort::GetProtocol() const {
357   return PROTO_UDP;
358 }
359 
GetStunStats(absl::optional<StunStats> * stats)360 void UDPPort::GetStunStats(absl::optional<StunStats>* stats) {
361   *stats = stats_;
362 }
363 
set_stun_keepalive_delay(const absl::optional<int> & delay)364 void UDPPort::set_stun_keepalive_delay(const absl::optional<int>& delay) {
365   stun_keepalive_delay_ = delay.value_or(STUN_KEEPALIVE_INTERVAL);
366 }
367 
OnLocalAddressReady(rtc::AsyncPacketSocket * socket,const rtc::SocketAddress & address)368 void UDPPort::OnLocalAddressReady(rtc::AsyncPacketSocket* socket,
369                                   const rtc::SocketAddress& address) {
370   // When adapter enumeration is disabled and binding to the any address, the
371   // default local address will be issued as a candidate instead if
372   // |emit_local_for_anyaddress| is true. This is to allow connectivity for
373   // applications which absolutely requires a HOST candidate.
374   rtc::SocketAddress addr = address;
375 
376   // If MaybeSetDefaultLocalAddress fails, we keep the "any" IP so that at
377   // least the port is listening.
378   MaybeSetDefaultLocalAddress(&addr);
379 
380   AddAddress(addr, addr, rtc::SocketAddress(), UDP_PROTOCOL_NAME, "", "",
381              LOCAL_PORT_TYPE, ICE_TYPE_PREFERENCE_HOST, 0, "", false);
382   MaybePrepareStunCandidate();
383 }
384 
PostAddAddress(bool is_final)385 void UDPPort::PostAddAddress(bool is_final) {
386   MaybeSetPortCompleteOrError();
387 }
388 
OnReadPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,const int64_t & packet_time_us)389 void UDPPort::OnReadPacket(rtc::AsyncPacketSocket* socket,
390                            const char* data,
391                            size_t size,
392                            const rtc::SocketAddress& remote_addr,
393                            const int64_t& packet_time_us) {
394   RTC_DCHECK(socket == socket_);
395   RTC_DCHECK(!remote_addr.IsUnresolvedIP());
396 
397   // Look for a response from the STUN server.
398   // Even if the response doesn't match one of our outstanding requests, we
399   // will eat it because it might be a response to a retransmitted packet, and
400   // we already cleared the request when we got the first response.
401   if (server_addresses_.find(remote_addr) != server_addresses_.end()) {
402     requests_.CheckResponse(data, size);
403     return;
404   }
405 
406   if (Connection* conn = GetConnection(remote_addr)) {
407     conn->OnReadPacket(data, size, packet_time_us);
408   } else {
409     Port::OnReadPacket(data, size, remote_addr, PROTO_UDP);
410   }
411 }
412 
OnSentPacket(rtc::AsyncPacketSocket * socket,const rtc::SentPacket & sent_packet)413 void UDPPort::OnSentPacket(rtc::AsyncPacketSocket* socket,
414                            const rtc::SentPacket& sent_packet) {
415   PortInterface::SignalSentPacket(sent_packet);
416 }
417 
OnReadyToSend(rtc::AsyncPacketSocket * socket)418 void UDPPort::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
419   Port::OnReadyToSend();
420 }
421 
SendStunBindingRequests()422 void UDPPort::SendStunBindingRequests() {
423   // We will keep pinging the stun server to make sure our NAT pin-hole stays
424   // open until the deadline (specified in SendStunBindingRequest).
425   RTC_DCHECK(requests_.empty());
426 
427   for (ServerAddresses::const_iterator it = server_addresses_.begin();
428        it != server_addresses_.end(); ++it) {
429     SendStunBindingRequest(*it);
430   }
431 }
432 
ResolveStunAddress(const rtc::SocketAddress & stun_addr)433 void UDPPort::ResolveStunAddress(const rtc::SocketAddress& stun_addr) {
434   if (!resolver_) {
435     resolver_.reset(new AddressResolver(socket_factory()));
436     resolver_->SignalDone.connect(this, &UDPPort::OnResolveResult);
437   }
438 
439   RTC_LOG(LS_INFO) << ToString() << ": Starting STUN host lookup for "
440                    << stun_addr.ToSensitiveString();
441   resolver_->Resolve(stun_addr);
442 }
443 
OnResolveResult(const rtc::SocketAddress & input,int error)444 void UDPPort::OnResolveResult(const rtc::SocketAddress& input, int error) {
445   RTC_DCHECK(resolver_.get() != nullptr);
446 
447   rtc::SocketAddress resolved;
448   if (error != 0 || !resolver_->GetResolvedAddress(
449                         input, Network()->GetBestIP().family(), &resolved)) {
450     RTC_LOG(LS_WARNING) << ToString()
451                         << ": StunPort: stun host lookup received error "
452                         << error;
453     OnStunBindingOrResolveRequestFailed(input, SERVER_NOT_REACHABLE_ERROR,
454                                         "STUN host lookup received error.");
455     return;
456   }
457 
458   server_addresses_.erase(input);
459 
460   if (server_addresses_.find(resolved) == server_addresses_.end()) {
461     server_addresses_.insert(resolved);
462     SendStunBindingRequest(resolved);
463   }
464 }
465 
SendStunBindingRequest(const rtc::SocketAddress & stun_addr)466 void UDPPort::SendStunBindingRequest(const rtc::SocketAddress& stun_addr) {
467   if (stun_addr.IsUnresolvedIP()) {
468     ResolveStunAddress(stun_addr);
469 
470   } else if (socket_->GetState() == rtc::AsyncPacketSocket::STATE_BOUND) {
471     // Check if |server_addr_| is compatible with the port's ip.
472     if (IsCompatibleAddress(stun_addr)) {
473       requests_.Send(
474           new StunBindingRequest(this, stun_addr, rtc::TimeMillis()));
475     } else {
476       // Since we can't send stun messages to the server, we should mark this
477       // port ready.
478       const char* reason = "STUN server address is incompatible.";
479       RTC_LOG(LS_WARNING) << reason;
480       OnStunBindingOrResolveRequestFailed(stun_addr, SERVER_NOT_REACHABLE_ERROR,
481                                           reason);
482     }
483   }
484 }
485 
MaybeSetDefaultLocalAddress(rtc::SocketAddress * addr) const486 bool UDPPort::MaybeSetDefaultLocalAddress(rtc::SocketAddress* addr) const {
487   if (!addr->IsAnyIP() || !emit_local_for_anyaddress_ ||
488       !Network()->default_local_address_provider()) {
489     return true;
490   }
491   rtc::IPAddress default_address;
492   bool result =
493       Network()->default_local_address_provider()->GetDefaultLocalAddress(
494           addr->family(), &default_address);
495   if (!result || default_address.IsNil()) {
496     return false;
497   }
498 
499   addr->SetIP(default_address);
500   return true;
501 }
502 
OnStunBindingRequestSucceeded(int rtt_ms,const rtc::SocketAddress & stun_server_addr,const rtc::SocketAddress & stun_reflected_addr)503 void UDPPort::OnStunBindingRequestSucceeded(
504     int rtt_ms,
505     const rtc::SocketAddress& stun_server_addr,
506     const rtc::SocketAddress& stun_reflected_addr) {
507   RTC_DCHECK(stats_.stun_binding_responses_received <
508              stats_.stun_binding_requests_sent);
509   stats_.stun_binding_responses_received++;
510   stats_.stun_binding_rtt_ms_total += rtt_ms;
511   stats_.stun_binding_rtt_ms_squared_total += rtt_ms * rtt_ms;
512   if (bind_request_succeeded_servers_.find(stun_server_addr) !=
513       bind_request_succeeded_servers_.end()) {
514     return;
515   }
516   bind_request_succeeded_servers_.insert(stun_server_addr);
517   // If socket is shared and |stun_reflected_addr| is equal to local socket
518   // address, or if the same address has been added by another STUN server,
519   // then discarding the stun address.
520   // For STUN, related address is the local socket address.
521   if ((!SharedSocket() || stun_reflected_addr != socket_->GetLocalAddress()) &&
522       !HasCandidateWithAddress(stun_reflected_addr)) {
523     rtc::SocketAddress related_address = socket_->GetLocalAddress();
524     // If we can't stamp the related address correctly, empty it to avoid leak.
525     if (!MaybeSetDefaultLocalAddress(&related_address)) {
526       related_address =
527           rtc::EmptySocketAddressWithFamily(related_address.family());
528     }
529 
530     rtc::StringBuilder url;
531     url << "stun:" << stun_server_addr.ipaddr().ToString() << ":"
532         << stun_server_addr.port();
533     AddAddress(stun_reflected_addr, socket_->GetLocalAddress(), related_address,
534                UDP_PROTOCOL_NAME, "", "", STUN_PORT_TYPE,
535                ICE_TYPE_PREFERENCE_SRFLX, 0, url.str(), false);
536   }
537   MaybeSetPortCompleteOrError();
538 }
539 
OnStunBindingOrResolveRequestFailed(const rtc::SocketAddress & stun_server_addr,int error_code,const std::string & reason)540 void UDPPort::OnStunBindingOrResolveRequestFailed(
541     const rtc::SocketAddress& stun_server_addr,
542     int error_code,
543     const std::string& reason) {
544   rtc::StringBuilder url;
545   url << "stun:" << stun_server_addr.ToString();
546   SignalCandidateError(
547       this, IceCandidateErrorEvent(GetLocalAddress().HostAsSensitiveURIString(),
548                                    GetLocalAddress().port(), url.str(),
549                                    error_code, reason));
550   if (bind_request_failed_servers_.find(stun_server_addr) !=
551       bind_request_failed_servers_.end()) {
552     return;
553   }
554   bind_request_failed_servers_.insert(stun_server_addr);
555   MaybeSetPortCompleteOrError();
556 }
557 
MaybeSetPortCompleteOrError()558 void UDPPort::MaybeSetPortCompleteOrError() {
559   if (mdns_name_registration_status() ==
560       MdnsNameRegistrationStatus::kInProgress) {
561     return;
562   }
563 
564   if (ready_) {
565     return;
566   }
567 
568   // Do not set port ready if we are still waiting for bind responses.
569   const size_t servers_done_bind_request =
570       bind_request_failed_servers_.size() +
571       bind_request_succeeded_servers_.size();
572   if (server_addresses_.size() != servers_done_bind_request) {
573     return;
574   }
575 
576   // Setting ready status.
577   ready_ = true;
578 
579   // The port is "completed" if there is no stun server provided, or the bind
580   // request succeeded for any stun server, or the socket is shared.
581   if (server_addresses_.empty() || bind_request_succeeded_servers_.size() > 0 ||
582       SharedSocket()) {
583     SignalPortComplete(this);
584   } else {
585     SignalPortError(this);
586   }
587 }
588 
589 // TODO(?): merge this with SendTo above.
OnSendPacket(const void * data,size_t size,StunRequest * req)590 void UDPPort::OnSendPacket(const void* data, size_t size, StunRequest* req) {
591   StunBindingRequest* sreq = static_cast<StunBindingRequest*>(req);
592   rtc::PacketOptions options(StunDscpValue());
593   options.info_signaled_after_sent.packet_type = rtc::PacketType::kStunMessage;
594   CopyPortInformationToPacketInfo(&options.info_signaled_after_sent);
595   if (socket_->SendTo(data, size, sreq->server_addr(), options) < 0) {
596     RTC_LOG_ERR_EX(LERROR, socket_->GetError()) << "sendto";
597   }
598   stats_.stun_binding_requests_sent++;
599 }
600 
HasCandidateWithAddress(const rtc::SocketAddress & addr) const601 bool UDPPort::HasCandidateWithAddress(const rtc::SocketAddress& addr) const {
602   const std::vector<Candidate>& existing_candidates = Candidates();
603   std::vector<Candidate>::const_iterator it = existing_candidates.begin();
604   for (; it != existing_candidates.end(); ++it) {
605     if (it->address() == addr)
606       return true;
607   }
608   return false;
609 }
610 
Create(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,uint16_t min_port,uint16_t max_port,const std::string & username,const std::string & password,const ServerAddresses & servers,const std::string & origin,absl::optional<int> stun_keepalive_interval)611 std::unique_ptr<StunPort> StunPort::Create(
612     rtc::Thread* thread,
613     rtc::PacketSocketFactory* factory,
614     rtc::Network* network,
615     uint16_t min_port,
616     uint16_t max_port,
617     const std::string& username,
618     const std::string& password,
619     const ServerAddresses& servers,
620     const std::string& origin,
621     absl::optional<int> stun_keepalive_interval) {
622   // Using `new` to access a non-public constructor.
623   auto port = absl::WrapUnique(new StunPort(thread, factory, network, min_port,
624                                             max_port, username, password,
625                                             servers, origin));
626   port->set_stun_keepalive_delay(stun_keepalive_interval);
627   if (!port->Init()) {
628     return nullptr;
629   }
630   return port;
631 }
632 
StunPort(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,uint16_t min_port,uint16_t max_port,const std::string & username,const std::string & password,const ServerAddresses & servers,const std::string & origin)633 StunPort::StunPort(rtc::Thread* thread,
634                    rtc::PacketSocketFactory* factory,
635                    rtc::Network* network,
636                    uint16_t min_port,
637                    uint16_t max_port,
638                    const std::string& username,
639                    const std::string& password,
640                    const ServerAddresses& servers,
641                    const std::string& origin)
642     : UDPPort(thread,
643               factory,
644               network,
645               min_port,
646               max_port,
647               username,
648               password,
649               origin,
650               false) {
651   // UDPPort will set these to local udp, updating these to STUN.
652   set_type(STUN_PORT_TYPE);
653   set_server_addresses(servers);
654 }
655 
PrepareAddress()656 void StunPort::PrepareAddress() {
657   SendStunBindingRequests();
658 }
659 
660 }  // namespace cricket
661