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