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