xref: /aosp_15_r20/external/webrtc/p2p/base/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/port.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include <math.h>
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker #include <algorithm>
16*d9f75844SAndroid Build Coastguard Worker #include <memory>
17*d9f75844SAndroid Build Coastguard Worker #include <utility>
18*d9f75844SAndroid Build Coastguard Worker #include <vector>
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker #include "absl/algorithm/container.h"
21*d9f75844SAndroid Build Coastguard Worker #include "absl/memory/memory.h"
22*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/match.h"
23*d9f75844SAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
24*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/connection.h"
25*d9f75844SAndroid Build Coastguard Worker #include "p2p/base/port_allocator.h"
26*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/checks.h"
27*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/crc32.h"
28*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/helpers.h"
29*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/logging.h"
30*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/mdns_responder_interface.h"
31*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/message_digest.h"
32*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/network.h"
33*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/numerics/safe_minmax.h"
34*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_encode.h"
35*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/string_utils.h"
36*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/strings/string_builder.h"
37*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/third_party/base64/base64.h"
38*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/trace_event.h"
39*d9f75844SAndroid Build Coastguard Worker 
40*d9f75844SAndroid Build Coastguard Worker namespace cricket {
41*d9f75844SAndroid Build Coastguard Worker namespace {
42*d9f75844SAndroid Build Coastguard Worker 
43*d9f75844SAndroid Build Coastguard Worker using ::webrtc::RTCError;
44*d9f75844SAndroid Build Coastguard Worker using ::webrtc::RTCErrorType;
45*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TaskQueueBase;
46*d9f75844SAndroid Build Coastguard Worker using ::webrtc::TimeDelta;
47*d9f75844SAndroid Build Coastguard Worker 
ConvertProtocolTypeToPacketInfoProtocolType(cricket::ProtocolType type)48*d9f75844SAndroid Build Coastguard Worker rtc::PacketInfoProtocolType ConvertProtocolTypeToPacketInfoProtocolType(
49*d9f75844SAndroid Build Coastguard Worker     cricket::ProtocolType type) {
50*d9f75844SAndroid Build Coastguard Worker   switch (type) {
51*d9f75844SAndroid Build Coastguard Worker     case cricket::ProtocolType::PROTO_UDP:
52*d9f75844SAndroid Build Coastguard Worker       return rtc::PacketInfoProtocolType::kUdp;
53*d9f75844SAndroid Build Coastguard Worker     case cricket::ProtocolType::PROTO_TCP:
54*d9f75844SAndroid Build Coastguard Worker       return rtc::PacketInfoProtocolType::kTcp;
55*d9f75844SAndroid Build Coastguard Worker     case cricket::ProtocolType::PROTO_SSLTCP:
56*d9f75844SAndroid Build Coastguard Worker       return rtc::PacketInfoProtocolType::kSsltcp;
57*d9f75844SAndroid Build Coastguard Worker     case cricket::ProtocolType::PROTO_TLS:
58*d9f75844SAndroid Build Coastguard Worker       return rtc::PacketInfoProtocolType::kTls;
59*d9f75844SAndroid Build Coastguard Worker     default:
60*d9f75844SAndroid Build Coastguard Worker       return rtc::PacketInfoProtocolType::kUnknown;
61*d9f75844SAndroid Build Coastguard Worker   }
62*d9f75844SAndroid Build Coastguard Worker }
63*d9f75844SAndroid Build Coastguard Worker 
64*d9f75844SAndroid Build Coastguard Worker // The delay before we begin checking if this port is useless. We set
65*d9f75844SAndroid Build Coastguard Worker // it to a little higher than a total STUN timeout.
66*d9f75844SAndroid Build Coastguard Worker const int kPortTimeoutDelay = cricket::STUN_TOTAL_TIMEOUT + 5000;
67*d9f75844SAndroid Build Coastguard Worker 
68*d9f75844SAndroid Build Coastguard Worker }  // namespace
69*d9f75844SAndroid Build Coastguard Worker 
70*d9f75844SAndroid Build Coastguard Worker // TODO(ronghuawu): Use "local", "srflx", "prflx" and "relay". But this requires
71*d9f75844SAndroid Build Coastguard Worker // the signaling part be updated correspondingly as well.
72*d9f75844SAndroid Build Coastguard Worker const char LOCAL_PORT_TYPE[] = "local";
73*d9f75844SAndroid Build Coastguard Worker const char STUN_PORT_TYPE[] = "stun";
74*d9f75844SAndroid Build Coastguard Worker const char PRFLX_PORT_TYPE[] = "prflx";
75*d9f75844SAndroid Build Coastguard Worker const char RELAY_PORT_TYPE[] = "relay";
76*d9f75844SAndroid Build Coastguard Worker 
77*d9f75844SAndroid Build Coastguard Worker static const char* const PROTO_NAMES[] = {UDP_PROTOCOL_NAME, TCP_PROTOCOL_NAME,
78*d9f75844SAndroid Build Coastguard Worker                                           SSLTCP_PROTOCOL_NAME,
79*d9f75844SAndroid Build Coastguard Worker                                           TLS_PROTOCOL_NAME};
80*d9f75844SAndroid Build Coastguard Worker 
ProtoToString(ProtocolType proto)81*d9f75844SAndroid Build Coastguard Worker const char* ProtoToString(ProtocolType proto) {
82*d9f75844SAndroid Build Coastguard Worker   return PROTO_NAMES[proto];
83*d9f75844SAndroid Build Coastguard Worker }
84*d9f75844SAndroid Build Coastguard Worker 
StringToProto(absl::string_view proto_name)85*d9f75844SAndroid Build Coastguard Worker absl::optional<ProtocolType> StringToProto(absl::string_view proto_name) {
86*d9f75844SAndroid Build Coastguard Worker   for (size_t i = 0; i <= PROTO_LAST; ++i) {
87*d9f75844SAndroid Build Coastguard Worker     if (absl::EqualsIgnoreCase(PROTO_NAMES[i], proto_name)) {
88*d9f75844SAndroid Build Coastguard Worker       return static_cast<ProtocolType>(i);
89*d9f75844SAndroid Build Coastguard Worker     }
90*d9f75844SAndroid Build Coastguard Worker   }
91*d9f75844SAndroid Build Coastguard Worker   return absl::nullopt;
92*d9f75844SAndroid Build Coastguard Worker }
93*d9f75844SAndroid Build Coastguard Worker 
94*d9f75844SAndroid Build Coastguard Worker // RFC 6544, TCP candidate encoding rules.
95*d9f75844SAndroid Build Coastguard Worker const int DISCARD_PORT = 9;
96*d9f75844SAndroid Build Coastguard Worker const char TCPTYPE_ACTIVE_STR[] = "active";
97*d9f75844SAndroid Build Coastguard Worker const char TCPTYPE_PASSIVE_STR[] = "passive";
98*d9f75844SAndroid Build Coastguard Worker const char TCPTYPE_SIMOPEN_STR[] = "so";
99*d9f75844SAndroid Build Coastguard Worker 
ComputeFoundation(absl::string_view type,absl::string_view protocol,absl::string_view relay_protocol,const rtc::SocketAddress & base_address)100*d9f75844SAndroid Build Coastguard Worker std::string Port::ComputeFoundation(absl::string_view type,
101*d9f75844SAndroid Build Coastguard Worker                                     absl::string_view protocol,
102*d9f75844SAndroid Build Coastguard Worker                                     absl::string_view relay_protocol,
103*d9f75844SAndroid Build Coastguard Worker                                     const rtc::SocketAddress& base_address) {
104*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/14605): ensure IceTiebreaker() is set.
105*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder sb;
106*d9f75844SAndroid Build Coastguard Worker   sb << type << base_address.ipaddr().ToString() << protocol << relay_protocol
107*d9f75844SAndroid Build Coastguard Worker      << rtc::ToString(IceTiebreaker());
108*d9f75844SAndroid Build Coastguard Worker   return rtc::ToString(rtc::ComputeCrc32(sb.Release()));
109*d9f75844SAndroid Build Coastguard Worker }
110*d9f75844SAndroid Build Coastguard Worker 
Port(TaskQueueBase * thread,absl::string_view type,rtc::PacketSocketFactory * factory,const rtc::Network * network,absl::string_view username_fragment,absl::string_view password,const webrtc::FieldTrialsView * field_trials)111*d9f75844SAndroid Build Coastguard Worker Port::Port(TaskQueueBase* thread,
112*d9f75844SAndroid Build Coastguard Worker            absl::string_view type,
113*d9f75844SAndroid Build Coastguard Worker            rtc::PacketSocketFactory* factory,
114*d9f75844SAndroid Build Coastguard Worker            const rtc::Network* network,
115*d9f75844SAndroid Build Coastguard Worker            absl::string_view username_fragment,
116*d9f75844SAndroid Build Coastguard Worker            absl::string_view password,
117*d9f75844SAndroid Build Coastguard Worker            const webrtc::FieldTrialsView* field_trials)
118*d9f75844SAndroid Build Coastguard Worker     : thread_(thread),
119*d9f75844SAndroid Build Coastguard Worker       factory_(factory),
120*d9f75844SAndroid Build Coastguard Worker       type_(type),
121*d9f75844SAndroid Build Coastguard Worker       send_retransmit_count_attribute_(false),
122*d9f75844SAndroid Build Coastguard Worker       network_(network),
123*d9f75844SAndroid Build Coastguard Worker       min_port_(0),
124*d9f75844SAndroid Build Coastguard Worker       max_port_(0),
125*d9f75844SAndroid Build Coastguard Worker       component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
126*d9f75844SAndroid Build Coastguard Worker       generation_(0),
127*d9f75844SAndroid Build Coastguard Worker       ice_username_fragment_(username_fragment),
128*d9f75844SAndroid Build Coastguard Worker       password_(password),
129*d9f75844SAndroid Build Coastguard Worker       timeout_delay_(kPortTimeoutDelay),
130*d9f75844SAndroid Build Coastguard Worker       enable_port_packets_(false),
131*d9f75844SAndroid Build Coastguard Worker       ice_role_(ICEROLE_UNKNOWN),
132*d9f75844SAndroid Build Coastguard Worker       tiebreaker_(0),
133*d9f75844SAndroid Build Coastguard Worker       shared_socket_(true),
134*d9f75844SAndroid Build Coastguard Worker       weak_factory_(this),
135*d9f75844SAndroid Build Coastguard Worker       field_trials_(field_trials) {
136*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(factory_ != NULL);
137*d9f75844SAndroid Build Coastguard Worker   Construct();
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker 
Port(TaskQueueBase * thread,absl::string_view type,rtc::PacketSocketFactory * factory,const rtc::Network * network,uint16_t min_port,uint16_t max_port,absl::string_view username_fragment,absl::string_view password,const webrtc::FieldTrialsView * field_trials)140*d9f75844SAndroid Build Coastguard Worker Port::Port(TaskQueueBase* thread,
141*d9f75844SAndroid Build Coastguard Worker            absl::string_view type,
142*d9f75844SAndroid Build Coastguard Worker            rtc::PacketSocketFactory* factory,
143*d9f75844SAndroid Build Coastguard Worker            const rtc::Network* network,
144*d9f75844SAndroid Build Coastguard Worker            uint16_t min_port,
145*d9f75844SAndroid Build Coastguard Worker            uint16_t max_port,
146*d9f75844SAndroid Build Coastguard Worker            absl::string_view username_fragment,
147*d9f75844SAndroid Build Coastguard Worker            absl::string_view password,
148*d9f75844SAndroid Build Coastguard Worker            const webrtc::FieldTrialsView* field_trials)
149*d9f75844SAndroid Build Coastguard Worker     : thread_(thread),
150*d9f75844SAndroid Build Coastguard Worker       factory_(factory),
151*d9f75844SAndroid Build Coastguard Worker       type_(type),
152*d9f75844SAndroid Build Coastguard Worker       send_retransmit_count_attribute_(false),
153*d9f75844SAndroid Build Coastguard Worker       network_(network),
154*d9f75844SAndroid Build Coastguard Worker       min_port_(min_port),
155*d9f75844SAndroid Build Coastguard Worker       max_port_(max_port),
156*d9f75844SAndroid Build Coastguard Worker       component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
157*d9f75844SAndroid Build Coastguard Worker       generation_(0),
158*d9f75844SAndroid Build Coastguard Worker       ice_username_fragment_(username_fragment),
159*d9f75844SAndroid Build Coastguard Worker       password_(password),
160*d9f75844SAndroid Build Coastguard Worker       timeout_delay_(kPortTimeoutDelay),
161*d9f75844SAndroid Build Coastguard Worker       enable_port_packets_(false),
162*d9f75844SAndroid Build Coastguard Worker       ice_role_(ICEROLE_UNKNOWN),
163*d9f75844SAndroid Build Coastguard Worker       tiebreaker_(0),
164*d9f75844SAndroid Build Coastguard Worker       shared_socket_(false),
165*d9f75844SAndroid Build Coastguard Worker       weak_factory_(this),
166*d9f75844SAndroid Build Coastguard Worker       field_trials_(field_trials) {
167*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(factory_ != NULL);
168*d9f75844SAndroid Build Coastguard Worker   Construct();
169*d9f75844SAndroid Build Coastguard Worker }
170*d9f75844SAndroid Build Coastguard Worker 
Construct()171*d9f75844SAndroid Build Coastguard Worker void Port::Construct() {
172*d9f75844SAndroid Build Coastguard Worker   // TODO(pthatcher): Remove this old behavior once we're sure no one
173*d9f75844SAndroid Build Coastguard Worker   // relies on it.  If the username_fragment and password are empty,
174*d9f75844SAndroid Build Coastguard Worker   // we should just create one.
175*d9f75844SAndroid Build Coastguard Worker   if (ice_username_fragment_.empty()) {
176*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(password_.empty());
177*d9f75844SAndroid Build Coastguard Worker     ice_username_fragment_ = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
178*d9f75844SAndroid Build Coastguard Worker     password_ = rtc::CreateRandomString(ICE_PWD_LENGTH);
179*d9f75844SAndroid Build Coastguard Worker   }
180*d9f75844SAndroid Build Coastguard Worker   network_->SignalTypeChanged.connect(this, &Port::OnNetworkTypeChanged);
181*d9f75844SAndroid Build Coastguard Worker   network_cost_ = network_->GetCost(field_trials());
182*d9f75844SAndroid Build Coastguard Worker 
183*d9f75844SAndroid Build Coastguard Worker   PostDestroyIfDead(/*delayed=*/true);
184*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Port created with network cost "
185*d9f75844SAndroid Build Coastguard Worker                    << network_cost_;
186*d9f75844SAndroid Build Coastguard Worker }
187*d9f75844SAndroid Build Coastguard Worker 
~Port()188*d9f75844SAndroid Build Coastguard Worker Port::~Port() {
189*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
190*d9f75844SAndroid Build Coastguard Worker   CancelPendingTasks();
191*d9f75844SAndroid Build Coastguard Worker   DestroyAllConnections();
192*d9f75844SAndroid Build Coastguard Worker }
193*d9f75844SAndroid Build Coastguard Worker 
Type() const194*d9f75844SAndroid Build Coastguard Worker const std::string& Port::Type() const {
195*d9f75844SAndroid Build Coastguard Worker   return type_;
196*d9f75844SAndroid Build Coastguard Worker }
Network() const197*d9f75844SAndroid Build Coastguard Worker const rtc::Network* Port::Network() const {
198*d9f75844SAndroid Build Coastguard Worker   return network_;
199*d9f75844SAndroid Build Coastguard Worker }
200*d9f75844SAndroid Build Coastguard Worker 
GetIceRole() const201*d9f75844SAndroid Build Coastguard Worker IceRole Port::GetIceRole() const {
202*d9f75844SAndroid Build Coastguard Worker   return ice_role_;
203*d9f75844SAndroid Build Coastguard Worker }
204*d9f75844SAndroid Build Coastguard Worker 
SetIceRole(IceRole role)205*d9f75844SAndroid Build Coastguard Worker void Port::SetIceRole(IceRole role) {
206*d9f75844SAndroid Build Coastguard Worker   ice_role_ = role;
207*d9f75844SAndroid Build Coastguard Worker }
208*d9f75844SAndroid Build Coastguard Worker 
SetIceTiebreaker(uint64_t tiebreaker)209*d9f75844SAndroid Build Coastguard Worker void Port::SetIceTiebreaker(uint64_t tiebreaker) {
210*d9f75844SAndroid Build Coastguard Worker   tiebreaker_ = tiebreaker;
211*d9f75844SAndroid Build Coastguard Worker }
212*d9f75844SAndroid Build Coastguard Worker 
IceTiebreaker() const213*d9f75844SAndroid Build Coastguard Worker uint64_t Port::IceTiebreaker() const {
214*d9f75844SAndroid Build Coastguard Worker   return tiebreaker_;
215*d9f75844SAndroid Build Coastguard Worker }
216*d9f75844SAndroid Build Coastguard Worker 
SharedSocket() const217*d9f75844SAndroid Build Coastguard Worker bool Port::SharedSocket() const {
218*d9f75844SAndroid Build Coastguard Worker   return shared_socket_;
219*d9f75844SAndroid Build Coastguard Worker }
220*d9f75844SAndroid Build Coastguard Worker 
SetIceParameters(int component,absl::string_view username_fragment,absl::string_view password)221*d9f75844SAndroid Build Coastguard Worker void Port::SetIceParameters(int component,
222*d9f75844SAndroid Build Coastguard Worker                             absl::string_view username_fragment,
223*d9f75844SAndroid Build Coastguard Worker                             absl::string_view password) {
224*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
225*d9f75844SAndroid Build Coastguard Worker   component_ = component;
226*d9f75844SAndroid Build Coastguard Worker   ice_username_fragment_ = std::string(username_fragment);
227*d9f75844SAndroid Build Coastguard Worker   password_ = std::string(password);
228*d9f75844SAndroid Build Coastguard Worker   for (Candidate& c : candidates_) {
229*d9f75844SAndroid Build Coastguard Worker     c.set_component(component);
230*d9f75844SAndroid Build Coastguard Worker     c.set_username(username_fragment);
231*d9f75844SAndroid Build Coastguard Worker     c.set_password(password);
232*d9f75844SAndroid Build Coastguard Worker   }
233*d9f75844SAndroid Build Coastguard Worker 
234*d9f75844SAndroid Build Coastguard Worker   // In case any connections exist make sure we update them too.
235*d9f75844SAndroid Build Coastguard Worker   for (auto& [unused, connection] : connections_) {
236*d9f75844SAndroid Build Coastguard Worker     connection->UpdateLocalIceParameters(component, username_fragment,
237*d9f75844SAndroid Build Coastguard Worker                                          password);
238*d9f75844SAndroid Build Coastguard Worker   }
239*d9f75844SAndroid Build Coastguard Worker }
240*d9f75844SAndroid Build Coastguard Worker 
Candidates() const241*d9f75844SAndroid Build Coastguard Worker const std::vector<Candidate>& Port::Candidates() const {
242*d9f75844SAndroid Build Coastguard Worker   return candidates_;
243*d9f75844SAndroid Build Coastguard Worker }
244*d9f75844SAndroid Build Coastguard Worker 
GetConnection(const rtc::SocketAddress & remote_addr)245*d9f75844SAndroid Build Coastguard Worker Connection* Port::GetConnection(const rtc::SocketAddress& remote_addr) {
246*d9f75844SAndroid Build Coastguard Worker   AddressMap::const_iterator iter = connections_.find(remote_addr);
247*d9f75844SAndroid Build Coastguard Worker   if (iter != connections_.end())
248*d9f75844SAndroid Build Coastguard Worker     return iter->second;
249*d9f75844SAndroid Build Coastguard Worker   else
250*d9f75844SAndroid Build Coastguard Worker     return NULL;
251*d9f75844SAndroid Build Coastguard Worker }
252*d9f75844SAndroid Build Coastguard Worker 
AddAddress(const rtc::SocketAddress & address,const rtc::SocketAddress & base_address,const rtc::SocketAddress & related_address,absl::string_view protocol,absl::string_view relay_protocol,absl::string_view tcptype,absl::string_view type,uint32_t type_preference,uint32_t relay_preference,absl::string_view url,bool is_final)253*d9f75844SAndroid Build Coastguard Worker void Port::AddAddress(const rtc::SocketAddress& address,
254*d9f75844SAndroid Build Coastguard Worker                       const rtc::SocketAddress& base_address,
255*d9f75844SAndroid Build Coastguard Worker                       const rtc::SocketAddress& related_address,
256*d9f75844SAndroid Build Coastguard Worker                       absl::string_view protocol,
257*d9f75844SAndroid Build Coastguard Worker                       absl::string_view relay_protocol,
258*d9f75844SAndroid Build Coastguard Worker                       absl::string_view tcptype,
259*d9f75844SAndroid Build Coastguard Worker                       absl::string_view type,
260*d9f75844SAndroid Build Coastguard Worker                       uint32_t type_preference,
261*d9f75844SAndroid Build Coastguard Worker                       uint32_t relay_preference,
262*d9f75844SAndroid Build Coastguard Worker                       absl::string_view url,
263*d9f75844SAndroid Build Coastguard Worker                       bool is_final) {
264*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
265*d9f75844SAndroid Build Coastguard Worker   if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) {
266*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(!tcptype.empty());
267*d9f75844SAndroid Build Coastguard Worker   }
268*d9f75844SAndroid Build Coastguard Worker 
269*d9f75844SAndroid Build Coastguard Worker   std::string foundation =
270*d9f75844SAndroid Build Coastguard Worker       ComputeFoundation(type, protocol, relay_protocol, base_address);
271*d9f75844SAndroid Build Coastguard Worker   Candidate c(component_, protocol, address, 0U, username_fragment(), password_,
272*d9f75844SAndroid Build Coastguard Worker               type, generation_, foundation, network_->id(), network_cost_);
273*d9f75844SAndroid Build Coastguard Worker   c.set_priority(
274*d9f75844SAndroid Build Coastguard Worker       c.GetPriority(type_preference, network_->preference(), relay_preference));
275*d9f75844SAndroid Build Coastguard Worker   c.set_relay_protocol(relay_protocol);
276*d9f75844SAndroid Build Coastguard Worker   c.set_tcptype(tcptype);
277*d9f75844SAndroid Build Coastguard Worker   c.set_network_name(network_->name());
278*d9f75844SAndroid Build Coastguard Worker   c.set_network_type(network_->type());
279*d9f75844SAndroid Build Coastguard Worker   c.set_underlying_type_for_vpn(network_->underlying_type_for_vpn());
280*d9f75844SAndroid Build Coastguard Worker   c.set_url(url);
281*d9f75844SAndroid Build Coastguard Worker   c.set_related_address(related_address);
282*d9f75844SAndroid Build Coastguard Worker 
283*d9f75844SAndroid Build Coastguard Worker   bool pending = MaybeObfuscateAddress(&c, type, is_final);
284*d9f75844SAndroid Build Coastguard Worker 
285*d9f75844SAndroid Build Coastguard Worker   if (!pending) {
286*d9f75844SAndroid Build Coastguard Worker     FinishAddingAddress(c, is_final);
287*d9f75844SAndroid Build Coastguard Worker   }
288*d9f75844SAndroid Build Coastguard Worker }
289*d9f75844SAndroid Build Coastguard Worker 
MaybeObfuscateAddress(Candidate * c,absl::string_view type,bool is_final)290*d9f75844SAndroid Build Coastguard Worker bool Port::MaybeObfuscateAddress(Candidate* c,
291*d9f75844SAndroid Build Coastguard Worker                                  absl::string_view type,
292*d9f75844SAndroid Build Coastguard Worker                                  bool is_final) {
293*d9f75844SAndroid Build Coastguard Worker   // TODO(bugs.webrtc.org/9723): Use a config to control the feature of IP
294*d9f75844SAndroid Build Coastguard Worker   // handling with mDNS.
295*d9f75844SAndroid Build Coastguard Worker   if (network_->GetMdnsResponder() == nullptr) {
296*d9f75844SAndroid Build Coastguard Worker     return false;
297*d9f75844SAndroid Build Coastguard Worker   }
298*d9f75844SAndroid Build Coastguard Worker   if (type != LOCAL_PORT_TYPE) {
299*d9f75844SAndroid Build Coastguard Worker     return false;
300*d9f75844SAndroid Build Coastguard Worker   }
301*d9f75844SAndroid Build Coastguard Worker 
302*d9f75844SAndroid Build Coastguard Worker   auto copy = *c;
303*d9f75844SAndroid Build Coastguard Worker   auto weak_ptr = weak_factory_.GetWeakPtr();
304*d9f75844SAndroid Build Coastguard Worker   auto callback = [weak_ptr, copy, is_final](const rtc::IPAddress& addr,
305*d9f75844SAndroid Build Coastguard Worker                                              absl::string_view name) mutable {
306*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK(copy.address().ipaddr() == addr);
307*d9f75844SAndroid Build Coastguard Worker     rtc::SocketAddress hostname_address(name, copy.address().port());
308*d9f75844SAndroid Build Coastguard Worker     // In Port and Connection, we need the IP address information to
309*d9f75844SAndroid Build Coastguard Worker     // correctly handle the update of candidate type to prflx. The removal
310*d9f75844SAndroid Build Coastguard Worker     // of IP address when signaling this candidate will take place in
311*d9f75844SAndroid Build Coastguard Worker     // BasicPortAllocatorSession::OnCandidateReady, via SanitizeCandidate.
312*d9f75844SAndroid Build Coastguard Worker     hostname_address.SetResolvedIP(addr);
313*d9f75844SAndroid Build Coastguard Worker     copy.set_address(hostname_address);
314*d9f75844SAndroid Build Coastguard Worker     copy.set_related_address(rtc::SocketAddress());
315*d9f75844SAndroid Build Coastguard Worker     if (weak_ptr != nullptr) {
316*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_RUN_ON(weak_ptr->thread_);
317*d9f75844SAndroid Build Coastguard Worker       weak_ptr->set_mdns_name_registration_status(
318*d9f75844SAndroid Build Coastguard Worker           MdnsNameRegistrationStatus::kCompleted);
319*d9f75844SAndroid Build Coastguard Worker       weak_ptr->FinishAddingAddress(copy, is_final);
320*d9f75844SAndroid Build Coastguard Worker     }
321*d9f75844SAndroid Build Coastguard Worker   };
322*d9f75844SAndroid Build Coastguard Worker   set_mdns_name_registration_status(MdnsNameRegistrationStatus::kInProgress);
323*d9f75844SAndroid Build Coastguard Worker   network_->GetMdnsResponder()->CreateNameForAddress(copy.address().ipaddr(),
324*d9f75844SAndroid Build Coastguard Worker                                                      callback);
325*d9f75844SAndroid Build Coastguard Worker   return true;
326*d9f75844SAndroid Build Coastguard Worker }
327*d9f75844SAndroid Build Coastguard Worker 
FinishAddingAddress(const Candidate & c,bool is_final)328*d9f75844SAndroid Build Coastguard Worker void Port::FinishAddingAddress(const Candidate& c, bool is_final) {
329*d9f75844SAndroid Build Coastguard Worker   candidates_.push_back(c);
330*d9f75844SAndroid Build Coastguard Worker   SignalCandidateReady(this, c);
331*d9f75844SAndroid Build Coastguard Worker 
332*d9f75844SAndroid Build Coastguard Worker   PostAddAddress(is_final);
333*d9f75844SAndroid Build Coastguard Worker }
334*d9f75844SAndroid Build Coastguard Worker 
PostAddAddress(bool is_final)335*d9f75844SAndroid Build Coastguard Worker void Port::PostAddAddress(bool is_final) {
336*d9f75844SAndroid Build Coastguard Worker   if (is_final) {
337*d9f75844SAndroid Build Coastguard Worker     SignalPortComplete(this);
338*d9f75844SAndroid Build Coastguard Worker   }
339*d9f75844SAndroid Build Coastguard Worker }
340*d9f75844SAndroid Build Coastguard Worker 
AddOrReplaceConnection(Connection * conn)341*d9f75844SAndroid Build Coastguard Worker void Port::AddOrReplaceConnection(Connection* conn) {
342*d9f75844SAndroid Build Coastguard Worker   auto ret = connections_.insert(
343*d9f75844SAndroid Build Coastguard Worker       std::make_pair(conn->remote_candidate().address(), conn));
344*d9f75844SAndroid Build Coastguard Worker   // If there is a different connection on the same remote address, replace
345*d9f75844SAndroid Build Coastguard Worker   // it with the new one and destroy the old one.
346*d9f75844SAndroid Build Coastguard Worker   if (ret.second == false && ret.first->second != conn) {
347*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_WARNING)
348*d9f75844SAndroid Build Coastguard Worker         << ToString()
349*d9f75844SAndroid Build Coastguard Worker         << ": A new connection was created on an existing remote address. "
350*d9f75844SAndroid Build Coastguard Worker            "New remote candidate: "
351*d9f75844SAndroid Build Coastguard Worker         << conn->remote_candidate().ToSensitiveString();
352*d9f75844SAndroid Build Coastguard Worker     std::unique_ptr<Connection> old_conn = absl::WrapUnique(ret.first->second);
353*d9f75844SAndroid Build Coastguard Worker     ret.first->second = conn;
354*d9f75844SAndroid Build Coastguard Worker     HandleConnectionDestroyed(old_conn.get());
355*d9f75844SAndroid Build Coastguard Worker     old_conn->Shutdown();
356*d9f75844SAndroid Build Coastguard Worker   }
357*d9f75844SAndroid Build Coastguard Worker }
358*d9f75844SAndroid Build Coastguard Worker 
OnReadPacket(const char * data,size_t size,const rtc::SocketAddress & addr,ProtocolType proto)359*d9f75844SAndroid Build Coastguard Worker void Port::OnReadPacket(const char* data,
360*d9f75844SAndroid Build Coastguard Worker                         size_t size,
361*d9f75844SAndroid Build Coastguard Worker                         const rtc::SocketAddress& addr,
362*d9f75844SAndroid Build Coastguard Worker                         ProtocolType proto) {
363*d9f75844SAndroid Build Coastguard Worker   // If the user has enabled port packets, just hand this over.
364*d9f75844SAndroid Build Coastguard Worker   if (enable_port_packets_) {
365*d9f75844SAndroid Build Coastguard Worker     SignalReadPacket(this, data, size, addr);
366*d9f75844SAndroid Build Coastguard Worker     return;
367*d9f75844SAndroid Build Coastguard Worker   }
368*d9f75844SAndroid Build Coastguard Worker 
369*d9f75844SAndroid Build Coastguard Worker   // If this is an authenticated STUN request, then signal unknown address and
370*d9f75844SAndroid Build Coastguard Worker   // send back a proper binding response.
371*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceMessage> msg;
372*d9f75844SAndroid Build Coastguard Worker   std::string remote_username;
373*d9f75844SAndroid Build Coastguard Worker   if (!GetStunMessage(data, size, addr, &msg, &remote_username)) {
374*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << ToString()
375*d9f75844SAndroid Build Coastguard Worker                       << ": Received non-STUN packet from unknown address: "
376*d9f75844SAndroid Build Coastguard Worker                       << addr.ToSensitiveString();
377*d9f75844SAndroid Build Coastguard Worker   } else if (!msg) {
378*d9f75844SAndroid Build Coastguard Worker     // STUN message handled already
379*d9f75844SAndroid Build Coastguard Worker   } else if (msg->type() == STUN_BINDING_REQUEST) {
380*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_INFO) << "Received " << StunMethodToString(msg->type())
381*d9f75844SAndroid Build Coastguard Worker                      << " id=" << rtc::hex_encode(msg->transaction_id())
382*d9f75844SAndroid Build Coastguard Worker                      << " from unknown address " << addr.ToSensitiveString();
383*d9f75844SAndroid Build Coastguard Worker     // We need to signal an unknown address before we handle any role conflict
384*d9f75844SAndroid Build Coastguard Worker     // below. Otherwise there would be no candidate pair and TURN entry created
385*d9f75844SAndroid Build Coastguard Worker     // to send the error response in case of a role conflict.
386*d9f75844SAndroid Build Coastguard Worker     SignalUnknownAddress(this, addr, proto, msg.get(), remote_username, false);
387*d9f75844SAndroid Build Coastguard Worker     // Check for role conflicts.
388*d9f75844SAndroid Build Coastguard Worker     if (!MaybeIceRoleConflict(addr, msg.get(), remote_username)) {
389*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_INFO) << "Received conflicting role from the peer.";
390*d9f75844SAndroid Build Coastguard Worker       return;
391*d9f75844SAndroid Build Coastguard Worker     }
392*d9f75844SAndroid Build Coastguard Worker   } else if (msg->type() == GOOG_PING_REQUEST) {
393*d9f75844SAndroid Build Coastguard Worker     // This is a PING sent to a connection that was destroyed.
394*d9f75844SAndroid Build Coastguard Worker     // Send back that this is the case and a authenticated BINDING
395*d9f75844SAndroid Build Coastguard Worker     // is needed.
396*d9f75844SAndroid Build Coastguard Worker     SendBindingErrorResponse(msg.get(), addr, STUN_ERROR_BAD_REQUEST,
397*d9f75844SAndroid Build Coastguard Worker                              STUN_ERROR_REASON_BAD_REQUEST);
398*d9f75844SAndroid Build Coastguard Worker   } else {
399*d9f75844SAndroid Build Coastguard Worker     // NOTE(tschmelcher): STUN_BINDING_RESPONSE is benign. It occurs if we
400*d9f75844SAndroid Build Coastguard Worker     // pruned a connection for this port while it had STUN requests in flight,
401*d9f75844SAndroid Build Coastguard Worker     // because we then get back responses for them, which this code correctly
402*d9f75844SAndroid Build Coastguard Worker     // does not handle.
403*d9f75844SAndroid Build Coastguard Worker     if (msg->type() != STUN_BINDING_RESPONSE &&
404*d9f75844SAndroid Build Coastguard Worker         msg->type() != GOOG_PING_RESPONSE &&
405*d9f75844SAndroid Build Coastguard Worker         msg->type() != GOOG_PING_ERROR_RESPONSE) {
406*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
407*d9f75844SAndroid Build Coastguard Worker                         << ": Received unexpected STUN message type: "
408*d9f75844SAndroid Build Coastguard Worker                         << msg->type() << " from unknown address: "
409*d9f75844SAndroid Build Coastguard Worker                         << addr.ToSensitiveString();
410*d9f75844SAndroid Build Coastguard Worker     }
411*d9f75844SAndroid Build Coastguard Worker   }
412*d9f75844SAndroid Build Coastguard Worker }
413*d9f75844SAndroid Build Coastguard Worker 
OnReadyToSend()414*d9f75844SAndroid Build Coastguard Worker void Port::OnReadyToSend() {
415*d9f75844SAndroid Build Coastguard Worker   AddressMap::iterator iter = connections_.begin();
416*d9f75844SAndroid Build Coastguard Worker   for (; iter != connections_.end(); ++iter) {
417*d9f75844SAndroid Build Coastguard Worker     iter->second->OnReadyToSend();
418*d9f75844SAndroid Build Coastguard Worker   }
419*d9f75844SAndroid Build Coastguard Worker }
420*d9f75844SAndroid Build Coastguard Worker 
AddPrflxCandidate(const Candidate & local)421*d9f75844SAndroid Build Coastguard Worker void Port::AddPrflxCandidate(const Candidate& local) {
422*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
423*d9f75844SAndroid Build Coastguard Worker   candidates_.push_back(local);
424*d9f75844SAndroid Build Coastguard Worker }
425*d9f75844SAndroid Build Coastguard Worker 
GetStunMessage(const char * data,size_t size,const rtc::SocketAddress & addr,std::unique_ptr<IceMessage> * out_msg,std::string * out_username)426*d9f75844SAndroid Build Coastguard Worker bool Port::GetStunMessage(const char* data,
427*d9f75844SAndroid Build Coastguard Worker                           size_t size,
428*d9f75844SAndroid Build Coastguard Worker                           const rtc::SocketAddress& addr,
429*d9f75844SAndroid Build Coastguard Worker                           std::unique_ptr<IceMessage>* out_msg,
430*d9f75844SAndroid Build Coastguard Worker                           std::string* out_username) {
431*d9f75844SAndroid Build Coastguard Worker   // NOTE: This could clearly be optimized to avoid allocating any memory.
432*d9f75844SAndroid Build Coastguard Worker   //       However, at the data rates we'll be looking at on the client side,
433*d9f75844SAndroid Build Coastguard Worker   //       this probably isn't worth worrying about.
434*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(out_msg != NULL);
435*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(out_username != NULL);
436*d9f75844SAndroid Build Coastguard Worker   out_username->clear();
437*d9f75844SAndroid Build Coastguard Worker 
438*d9f75844SAndroid Build Coastguard Worker   // Don't bother parsing the packet if we can tell it's not STUN.
439*d9f75844SAndroid Build Coastguard Worker   // In ICE mode, all STUN packets will have a valid fingerprint.
440*d9f75844SAndroid Build Coastguard Worker   // Except GOOG_PING_REQUEST/RESPONSE that does not send fingerprint.
441*d9f75844SAndroid Build Coastguard Worker   int types[] = {GOOG_PING_REQUEST, GOOG_PING_RESPONSE,
442*d9f75844SAndroid Build Coastguard Worker                  GOOG_PING_ERROR_RESPONSE};
443*d9f75844SAndroid Build Coastguard Worker   if (!StunMessage::IsStunMethod(types, data, size) &&
444*d9f75844SAndroid Build Coastguard Worker       !StunMessage::ValidateFingerprint(data, size)) {
445*d9f75844SAndroid Build Coastguard Worker     return false;
446*d9f75844SAndroid Build Coastguard Worker   }
447*d9f75844SAndroid Build Coastguard Worker 
448*d9f75844SAndroid Build Coastguard Worker   // Parse the request message.  If the packet is not a complete and correct
449*d9f75844SAndroid Build Coastguard Worker   // STUN message, then ignore it.
450*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<IceMessage> stun_msg(new IceMessage());
451*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferReader buf(data, size);
452*d9f75844SAndroid Build Coastguard Worker   if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {
453*d9f75844SAndroid Build Coastguard Worker     return false;
454*d9f75844SAndroid Build Coastguard Worker   }
455*d9f75844SAndroid Build Coastguard Worker 
456*d9f75844SAndroid Build Coastguard Worker   // Get list of attributes in the "comprehension-required" range that were not
457*d9f75844SAndroid Build Coastguard Worker   // comprehended. If one or more is found, the behavior differs based on the
458*d9f75844SAndroid Build Coastguard Worker   // type of the incoming message; see below.
459*d9f75844SAndroid Build Coastguard Worker   std::vector<uint16_t> unknown_attributes =
460*d9f75844SAndroid Build Coastguard Worker       stun_msg->GetNonComprehendedAttributes();
461*d9f75844SAndroid Build Coastguard Worker 
462*d9f75844SAndroid Build Coastguard Worker   if (stun_msg->type() == STUN_BINDING_REQUEST) {
463*d9f75844SAndroid Build Coastguard Worker     // Check for the presence of USERNAME and MESSAGE-INTEGRITY (if ICE) first.
464*d9f75844SAndroid Build Coastguard Worker     // If not present, fail with a 400 Bad Request.
465*d9f75844SAndroid Build Coastguard Worker     if (!stun_msg->GetByteString(STUN_ATTR_USERNAME) ||
466*d9f75844SAndroid Build Coastguard Worker         !stun_msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) {
467*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Received "
468*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type())
469*d9f75844SAndroid Build Coastguard Worker                         << " without username/M-I from: "
470*d9f75844SAndroid Build Coastguard Worker                         << addr.ToSensitiveString();
471*d9f75844SAndroid Build Coastguard Worker       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST,
472*d9f75844SAndroid Build Coastguard Worker                                STUN_ERROR_REASON_BAD_REQUEST);
473*d9f75844SAndroid Build Coastguard Worker       return true;
474*d9f75844SAndroid Build Coastguard Worker     }
475*d9f75844SAndroid Build Coastguard Worker 
476*d9f75844SAndroid Build Coastguard Worker     // If the username is bad or unknown, fail with a 401 Unauthorized.
477*d9f75844SAndroid Build Coastguard Worker     std::string local_ufrag;
478*d9f75844SAndroid Build Coastguard Worker     std::string remote_ufrag;
479*d9f75844SAndroid Build Coastguard Worker     if (!ParseStunUsername(stun_msg.get(), &local_ufrag, &remote_ufrag) ||
480*d9f75844SAndroid Build Coastguard Worker         local_ufrag != username_fragment()) {
481*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Received "
482*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type())
483*d9f75844SAndroid Build Coastguard Worker                         << " with bad local username " << local_ufrag
484*d9f75844SAndroid Build Coastguard Worker                         << " from " << addr.ToSensitiveString();
485*d9f75844SAndroid Build Coastguard Worker       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
486*d9f75844SAndroid Build Coastguard Worker                                STUN_ERROR_REASON_UNAUTHORIZED);
487*d9f75844SAndroid Build Coastguard Worker       return true;
488*d9f75844SAndroid Build Coastguard Worker     }
489*d9f75844SAndroid Build Coastguard Worker 
490*d9f75844SAndroid Build Coastguard Worker     // If ICE, and the MESSAGE-INTEGRITY is bad, fail with a 401 Unauthorized
491*d9f75844SAndroid Build Coastguard Worker     if (stun_msg->ValidateMessageIntegrity(password_) !=
492*d9f75844SAndroid Build Coastguard Worker         StunMessage::IntegrityStatus::kIntegrityOk) {
493*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Received "
494*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type())
495*d9f75844SAndroid Build Coastguard Worker                         << " with bad M-I from " << addr.ToSensitiveString()
496*d9f75844SAndroid Build Coastguard Worker                         << ", password_=" << password_;
497*d9f75844SAndroid Build Coastguard Worker       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
498*d9f75844SAndroid Build Coastguard Worker                                STUN_ERROR_REASON_UNAUTHORIZED);
499*d9f75844SAndroid Build Coastguard Worker       return true;
500*d9f75844SAndroid Build Coastguard Worker     }
501*d9f75844SAndroid Build Coastguard Worker 
502*d9f75844SAndroid Build Coastguard Worker     // If a request contains unknown comprehension-required attributes, reply
503*d9f75844SAndroid Build Coastguard Worker     // with an error. See RFC5389 section 7.3.1.
504*d9f75844SAndroid Build Coastguard Worker     if (!unknown_attributes.empty()) {
505*d9f75844SAndroid Build Coastguard Worker       SendUnknownAttributesErrorResponse(stun_msg.get(), addr,
506*d9f75844SAndroid Build Coastguard Worker                                          unknown_attributes);
507*d9f75844SAndroid Build Coastguard Worker       return true;
508*d9f75844SAndroid Build Coastguard Worker     }
509*d9f75844SAndroid Build Coastguard Worker 
510*d9f75844SAndroid Build Coastguard Worker     out_username->assign(remote_ufrag);
511*d9f75844SAndroid Build Coastguard Worker   } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) ||
512*d9f75844SAndroid Build Coastguard Worker              (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) {
513*d9f75844SAndroid Build Coastguard Worker     if (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE) {
514*d9f75844SAndroid Build Coastguard Worker       if (const StunErrorCodeAttribute* error_code = stun_msg->GetErrorCode()) {
515*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << ToString() << ": Received "
516*d9f75844SAndroid Build Coastguard Worker                           << StunMethodToString(stun_msg->type())
517*d9f75844SAndroid Build Coastguard Worker                           << ": class=" << error_code->eclass()
518*d9f75844SAndroid Build Coastguard Worker                           << " number=" << error_code->number() << " reason='"
519*d9f75844SAndroid Build Coastguard Worker                           << error_code->reason() << "' from "
520*d9f75844SAndroid Build Coastguard Worker                           << addr.ToSensitiveString();
521*d9f75844SAndroid Build Coastguard Worker         // Return message to allow error-specific processing
522*d9f75844SAndroid Build Coastguard Worker       } else {
523*d9f75844SAndroid Build Coastguard Worker         RTC_LOG(LS_ERROR) << ToString() << ": Received "
524*d9f75844SAndroid Build Coastguard Worker                           << StunMethodToString(stun_msg->type())
525*d9f75844SAndroid Build Coastguard Worker                           << " without a error code from "
526*d9f75844SAndroid Build Coastguard Worker                           << addr.ToSensitiveString();
527*d9f75844SAndroid Build Coastguard Worker         return true;
528*d9f75844SAndroid Build Coastguard Worker       }
529*d9f75844SAndroid Build Coastguard Worker     }
530*d9f75844SAndroid Build Coastguard Worker     // If a response contains unknown comprehension-required attributes, it's
531*d9f75844SAndroid Build Coastguard Worker     // simply discarded and the transaction is considered failed. See RFC5389
532*d9f75844SAndroid Build Coastguard Worker     // sections 7.3.3 and 7.3.4.
533*d9f75844SAndroid Build Coastguard Worker     if (!unknown_attributes.empty()) {
534*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
535*d9f75844SAndroid Build Coastguard Worker                         << ": Discarding STUN response due to unknown "
536*d9f75844SAndroid Build Coastguard Worker                            "comprehension-required attribute";
537*d9f75844SAndroid Build Coastguard Worker       return true;
538*d9f75844SAndroid Build Coastguard Worker     }
539*d9f75844SAndroid Build Coastguard Worker     // NOTE: Username should not be used in verifying response messages.
540*d9f75844SAndroid Build Coastguard Worker     out_username->clear();
541*d9f75844SAndroid Build Coastguard Worker   } else if (stun_msg->type() == STUN_BINDING_INDICATION) {
542*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_VERBOSE) << ToString() << ": Received "
543*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type()) << ": from "
544*d9f75844SAndroid Build Coastguard Worker                         << addr.ToSensitiveString();
545*d9f75844SAndroid Build Coastguard Worker     out_username->clear();
546*d9f75844SAndroid Build Coastguard Worker 
547*d9f75844SAndroid Build Coastguard Worker     // If an indication contains unknown comprehension-required attributes,[]
548*d9f75844SAndroid Build Coastguard Worker     // it's simply discarded. See RFC5389 section 7.3.2.
549*d9f75844SAndroid Build Coastguard Worker     if (!unknown_attributes.empty()) {
550*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString()
551*d9f75844SAndroid Build Coastguard Worker                         << ": Discarding STUN indication due to "
552*d9f75844SAndroid Build Coastguard Worker                            "unknown comprehension-required attribute";
553*d9f75844SAndroid Build Coastguard Worker       return true;
554*d9f75844SAndroid Build Coastguard Worker     }
555*d9f75844SAndroid Build Coastguard Worker     // No stun attributes will be verified, if it's stun indication message.
556*d9f75844SAndroid Build Coastguard Worker     // Returning from end of the this method.
557*d9f75844SAndroid Build Coastguard Worker   } else if (stun_msg->type() == GOOG_PING_REQUEST) {
558*d9f75844SAndroid Build Coastguard Worker     if (stun_msg->ValidateMessageIntegrity(password_) !=
559*d9f75844SAndroid Build Coastguard Worker         StunMessage::IntegrityStatus::kIntegrityOk) {
560*d9f75844SAndroid Build Coastguard Worker       RTC_LOG(LS_ERROR) << ToString() << ": Received "
561*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type())
562*d9f75844SAndroid Build Coastguard Worker                         << " with bad M-I from " << addr.ToSensitiveString()
563*d9f75844SAndroid Build Coastguard Worker                         << ", password_=" << password_;
564*d9f75844SAndroid Build Coastguard Worker       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
565*d9f75844SAndroid Build Coastguard Worker                                STUN_ERROR_REASON_UNAUTHORIZED);
566*d9f75844SAndroid Build Coastguard Worker       return true;
567*d9f75844SAndroid Build Coastguard Worker     }
568*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_VERBOSE) << ToString() << ": Received "
569*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type()) << " from "
570*d9f75844SAndroid Build Coastguard Worker                         << addr.ToSensitiveString();
571*d9f75844SAndroid Build Coastguard Worker     out_username->clear();
572*d9f75844SAndroid Build Coastguard Worker   } else if (stun_msg->type() == GOOG_PING_RESPONSE ||
573*d9f75844SAndroid Build Coastguard Worker              stun_msg->type() == GOOG_PING_ERROR_RESPONSE) {
574*d9f75844SAndroid Build Coastguard Worker     // note: the MessageIntegrity32 will be verified in Connection.cc
575*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_VERBOSE) << ToString() << ": Received "
576*d9f75844SAndroid Build Coastguard Worker                         << StunMethodToString(stun_msg->type()) << " from "
577*d9f75844SAndroid Build Coastguard Worker                         << addr.ToSensitiveString();
578*d9f75844SAndroid Build Coastguard Worker     out_username->clear();
579*d9f75844SAndroid Build Coastguard Worker   } else {
580*d9f75844SAndroid Build Coastguard Worker     RTC_LOG(LS_ERROR) << ToString()
581*d9f75844SAndroid Build Coastguard Worker                       << ": Received STUN packet with invalid type ("
582*d9f75844SAndroid Build Coastguard Worker                       << stun_msg->type() << ") from "
583*d9f75844SAndroid Build Coastguard Worker                       << addr.ToSensitiveString();
584*d9f75844SAndroid Build Coastguard Worker     return true;
585*d9f75844SAndroid Build Coastguard Worker   }
586*d9f75844SAndroid Build Coastguard Worker 
587*d9f75844SAndroid Build Coastguard Worker   // Return the STUN message found.
588*d9f75844SAndroid Build Coastguard Worker   *out_msg = std::move(stun_msg);
589*d9f75844SAndroid Build Coastguard Worker   return true;
590*d9f75844SAndroid Build Coastguard Worker }
591*d9f75844SAndroid Build Coastguard Worker 
IsCompatibleAddress(const rtc::SocketAddress & addr)592*d9f75844SAndroid Build Coastguard Worker bool Port::IsCompatibleAddress(const rtc::SocketAddress& addr) {
593*d9f75844SAndroid Build Coastguard Worker   // Get a representative IP for the Network this port is configured to use.
594*d9f75844SAndroid Build Coastguard Worker   rtc::IPAddress ip = network_->GetBestIP();
595*d9f75844SAndroid Build Coastguard Worker   // We use single-stack sockets, so families must match.
596*d9f75844SAndroid Build Coastguard Worker   if (addr.family() != ip.family()) {
597*d9f75844SAndroid Build Coastguard Worker     return false;
598*d9f75844SAndroid Build Coastguard Worker   }
599*d9f75844SAndroid Build Coastguard Worker   // Link-local IPv6 ports can only connect to other link-local IPv6 ports.
600*d9f75844SAndroid Build Coastguard Worker   if (ip.family() == AF_INET6 &&
601*d9f75844SAndroid Build Coastguard Worker       (IPIsLinkLocal(ip) != IPIsLinkLocal(addr.ipaddr()))) {
602*d9f75844SAndroid Build Coastguard Worker     return false;
603*d9f75844SAndroid Build Coastguard Worker   }
604*d9f75844SAndroid Build Coastguard Worker   return true;
605*d9f75844SAndroid Build Coastguard Worker }
606*d9f75844SAndroid Build Coastguard Worker 
StunDscpValue() const607*d9f75844SAndroid Build Coastguard Worker rtc::DiffServCodePoint Port::StunDscpValue() const {
608*d9f75844SAndroid Build Coastguard Worker   // By default, inherit from whatever the MediaChannel sends.
609*d9f75844SAndroid Build Coastguard Worker   return rtc::DSCP_NO_CHANGE;
610*d9f75844SAndroid Build Coastguard Worker }
611*d9f75844SAndroid Build Coastguard Worker 
DestroyAllConnections()612*d9f75844SAndroid Build Coastguard Worker void Port::DestroyAllConnections() {
613*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
614*d9f75844SAndroid Build Coastguard Worker   for (auto& [unused, connection] : connections_) {
615*d9f75844SAndroid Build Coastguard Worker     connection->Shutdown();
616*d9f75844SAndroid Build Coastguard Worker     delete connection;
617*d9f75844SAndroid Build Coastguard Worker   }
618*d9f75844SAndroid Build Coastguard Worker   connections_.clear();
619*d9f75844SAndroid Build Coastguard Worker }
620*d9f75844SAndroid Build Coastguard Worker 
set_timeout_delay(int delay)621*d9f75844SAndroid Build Coastguard Worker void Port::set_timeout_delay(int delay) {
622*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
623*d9f75844SAndroid Build Coastguard Worker   // Although this method is meant to only be used by tests, some downstream
624*d9f75844SAndroid Build Coastguard Worker   // projects have started using it. Ideally we should update our tests to not
625*d9f75844SAndroid Build Coastguard Worker   // require to modify this state and instead use a testing harness that allows
626*d9f75844SAndroid Build Coastguard Worker   // adjusting the clock and then just use the kPortTimeoutDelay constant
627*d9f75844SAndroid Build Coastguard Worker   // directly.
628*d9f75844SAndroid Build Coastguard Worker   timeout_delay_ = delay;
629*d9f75844SAndroid Build Coastguard Worker }
630*d9f75844SAndroid Build Coastguard Worker 
ParseStunUsername(const StunMessage * stun_msg,std::string * local_ufrag,std::string * remote_ufrag) const631*d9f75844SAndroid Build Coastguard Worker bool Port::ParseStunUsername(const StunMessage* stun_msg,
632*d9f75844SAndroid Build Coastguard Worker                              std::string* local_ufrag,
633*d9f75844SAndroid Build Coastguard Worker                              std::string* remote_ufrag) const {
634*d9f75844SAndroid Build Coastguard Worker   // The packet must include a username that either begins or ends with our
635*d9f75844SAndroid Build Coastguard Worker   // fragment.  It should begin with our fragment if it is a request and it
636*d9f75844SAndroid Build Coastguard Worker   // should end with our fragment if it is a response.
637*d9f75844SAndroid Build Coastguard Worker   local_ufrag->clear();
638*d9f75844SAndroid Build Coastguard Worker   remote_ufrag->clear();
639*d9f75844SAndroid Build Coastguard Worker   const StunByteStringAttribute* username_attr =
640*d9f75844SAndroid Build Coastguard Worker       stun_msg->GetByteString(STUN_ATTR_USERNAME);
641*d9f75844SAndroid Build Coastguard Worker   if (username_attr == NULL)
642*d9f75844SAndroid Build Coastguard Worker     return false;
643*d9f75844SAndroid Build Coastguard Worker 
644*d9f75844SAndroid Build Coastguard Worker   // RFRAG:LFRAG
645*d9f75844SAndroid Build Coastguard Worker   const absl::string_view username = username_attr->string_view();
646*d9f75844SAndroid Build Coastguard Worker   size_t colon_pos = username.find(':');
647*d9f75844SAndroid Build Coastguard Worker   if (colon_pos == absl::string_view::npos) {
648*d9f75844SAndroid Build Coastguard Worker     return false;
649*d9f75844SAndroid Build Coastguard Worker   }
650*d9f75844SAndroid Build Coastguard Worker 
651*d9f75844SAndroid Build Coastguard Worker   *local_ufrag = std::string(username.substr(0, colon_pos));
652*d9f75844SAndroid Build Coastguard Worker   *remote_ufrag = std::string(username.substr(colon_pos + 1, username.size()));
653*d9f75844SAndroid Build Coastguard Worker   return true;
654*d9f75844SAndroid Build Coastguard Worker }
655*d9f75844SAndroid Build Coastguard Worker 
MaybeIceRoleConflict(const rtc::SocketAddress & addr,IceMessage * stun_msg,absl::string_view remote_ufrag)656*d9f75844SAndroid Build Coastguard Worker bool Port::MaybeIceRoleConflict(const rtc::SocketAddress& addr,
657*d9f75844SAndroid Build Coastguard Worker                                 IceMessage* stun_msg,
658*d9f75844SAndroid Build Coastguard Worker                                 absl::string_view remote_ufrag) {
659*d9f75844SAndroid Build Coastguard Worker   // Validate ICE_CONTROLLING or ICE_CONTROLLED attributes.
660*d9f75844SAndroid Build Coastguard Worker   bool ret = true;
661*d9f75844SAndroid Build Coastguard Worker   IceRole remote_ice_role = ICEROLE_UNKNOWN;
662*d9f75844SAndroid Build Coastguard Worker   uint64_t remote_tiebreaker = 0;
663*d9f75844SAndroid Build Coastguard Worker   const StunUInt64Attribute* stun_attr =
664*d9f75844SAndroid Build Coastguard Worker       stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
665*d9f75844SAndroid Build Coastguard Worker   if (stun_attr) {
666*d9f75844SAndroid Build Coastguard Worker     remote_ice_role = ICEROLE_CONTROLLING;
667*d9f75844SAndroid Build Coastguard Worker     remote_tiebreaker = stun_attr->value();
668*d9f75844SAndroid Build Coastguard Worker   }
669*d9f75844SAndroid Build Coastguard Worker 
670*d9f75844SAndroid Build Coastguard Worker   // If `remote_ufrag` is same as port local username fragment and
671*d9f75844SAndroid Build Coastguard Worker   // tie breaker value received in the ping message matches port
672*d9f75844SAndroid Build Coastguard Worker   // tiebreaker value this must be a loopback call.
673*d9f75844SAndroid Build Coastguard Worker   // We will treat this as valid scenario.
674*d9f75844SAndroid Build Coastguard Worker   if (remote_ice_role == ICEROLE_CONTROLLING &&
675*d9f75844SAndroid Build Coastguard Worker       username_fragment() == remote_ufrag &&
676*d9f75844SAndroid Build Coastguard Worker       remote_tiebreaker == IceTiebreaker()) {
677*d9f75844SAndroid Build Coastguard Worker     return true;
678*d9f75844SAndroid Build Coastguard Worker   }
679*d9f75844SAndroid Build Coastguard Worker 
680*d9f75844SAndroid Build Coastguard Worker   stun_attr = stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLED);
681*d9f75844SAndroid Build Coastguard Worker   if (stun_attr) {
682*d9f75844SAndroid Build Coastguard Worker     remote_ice_role = ICEROLE_CONTROLLED;
683*d9f75844SAndroid Build Coastguard Worker     remote_tiebreaker = stun_attr->value();
684*d9f75844SAndroid Build Coastguard Worker   }
685*d9f75844SAndroid Build Coastguard Worker 
686*d9f75844SAndroid Build Coastguard Worker   switch (ice_role_) {
687*d9f75844SAndroid Build Coastguard Worker     case ICEROLE_CONTROLLING:
688*d9f75844SAndroid Build Coastguard Worker       if (ICEROLE_CONTROLLING == remote_ice_role) {
689*d9f75844SAndroid Build Coastguard Worker         if (remote_tiebreaker >= tiebreaker_) {
690*d9f75844SAndroid Build Coastguard Worker           SignalRoleConflict(this);
691*d9f75844SAndroid Build Coastguard Worker         } else {
692*d9f75844SAndroid Build Coastguard Worker           // Send Role Conflict (487) error response.
693*d9f75844SAndroid Build Coastguard Worker           SendBindingErrorResponse(stun_msg, addr, STUN_ERROR_ROLE_CONFLICT,
694*d9f75844SAndroid Build Coastguard Worker                                    STUN_ERROR_REASON_ROLE_CONFLICT);
695*d9f75844SAndroid Build Coastguard Worker           ret = false;
696*d9f75844SAndroid Build Coastguard Worker         }
697*d9f75844SAndroid Build Coastguard Worker       }
698*d9f75844SAndroid Build Coastguard Worker       break;
699*d9f75844SAndroid Build Coastguard Worker     case ICEROLE_CONTROLLED:
700*d9f75844SAndroid Build Coastguard Worker       if (ICEROLE_CONTROLLED == remote_ice_role) {
701*d9f75844SAndroid Build Coastguard Worker         if (remote_tiebreaker < tiebreaker_) {
702*d9f75844SAndroid Build Coastguard Worker           SignalRoleConflict(this);
703*d9f75844SAndroid Build Coastguard Worker         } else {
704*d9f75844SAndroid Build Coastguard Worker           // Send Role Conflict (487) error response.
705*d9f75844SAndroid Build Coastguard Worker           SendBindingErrorResponse(stun_msg, addr, STUN_ERROR_ROLE_CONFLICT,
706*d9f75844SAndroid Build Coastguard Worker                                    STUN_ERROR_REASON_ROLE_CONFLICT);
707*d9f75844SAndroid Build Coastguard Worker           ret = false;
708*d9f75844SAndroid Build Coastguard Worker         }
709*d9f75844SAndroid Build Coastguard Worker       }
710*d9f75844SAndroid Build Coastguard Worker       break;
711*d9f75844SAndroid Build Coastguard Worker     default:
712*d9f75844SAndroid Build Coastguard Worker       RTC_DCHECK_NOTREACHED();
713*d9f75844SAndroid Build Coastguard Worker   }
714*d9f75844SAndroid Build Coastguard Worker   return ret;
715*d9f75844SAndroid Build Coastguard Worker }
716*d9f75844SAndroid Build Coastguard Worker 
CreateStunUsername(absl::string_view remote_username) const717*d9f75844SAndroid Build Coastguard Worker std::string Port::CreateStunUsername(absl::string_view remote_username) const {
718*d9f75844SAndroid Build Coastguard Worker   return std::string(remote_username) + ":" + username_fragment();
719*d9f75844SAndroid Build Coastguard Worker }
720*d9f75844SAndroid Build Coastguard Worker 
HandleIncomingPacket(rtc::AsyncPacketSocket * socket,const char * data,size_t size,const rtc::SocketAddress & remote_addr,int64_t packet_time_us)721*d9f75844SAndroid Build Coastguard Worker bool Port::HandleIncomingPacket(rtc::AsyncPacketSocket* socket,
722*d9f75844SAndroid Build Coastguard Worker                                 const char* data,
723*d9f75844SAndroid Build Coastguard Worker                                 size_t size,
724*d9f75844SAndroid Build Coastguard Worker                                 const rtc::SocketAddress& remote_addr,
725*d9f75844SAndroid Build Coastguard Worker                                 int64_t packet_time_us) {
726*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_NOTREACHED();
727*d9f75844SAndroid Build Coastguard Worker   return false;
728*d9f75844SAndroid Build Coastguard Worker }
729*d9f75844SAndroid Build Coastguard Worker 
CanHandleIncomingPacketsFrom(const rtc::SocketAddress &) const730*d9f75844SAndroid Build Coastguard Worker bool Port::CanHandleIncomingPacketsFrom(const rtc::SocketAddress&) const {
731*d9f75844SAndroid Build Coastguard Worker   return false;
732*d9f75844SAndroid Build Coastguard Worker }
733*d9f75844SAndroid Build Coastguard Worker 
SendBindingErrorResponse(StunMessage * message,const rtc::SocketAddress & addr,int error_code,absl::string_view reason)734*d9f75844SAndroid Build Coastguard Worker void Port::SendBindingErrorResponse(StunMessage* message,
735*d9f75844SAndroid Build Coastguard Worker                                     const rtc::SocketAddress& addr,
736*d9f75844SAndroid Build Coastguard Worker                                     int error_code,
737*d9f75844SAndroid Build Coastguard Worker                                     absl::string_view reason) {
738*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(message->type() == STUN_BINDING_REQUEST ||
739*d9f75844SAndroid Build Coastguard Worker              message->type() == GOOG_PING_REQUEST);
740*d9f75844SAndroid Build Coastguard Worker 
741*d9f75844SAndroid Build Coastguard Worker   // Fill in the response message.
742*d9f75844SAndroid Build Coastguard Worker   StunMessage response(message->type() == STUN_BINDING_REQUEST
743*d9f75844SAndroid Build Coastguard Worker                            ? STUN_BINDING_ERROR_RESPONSE
744*d9f75844SAndroid Build Coastguard Worker                            : GOOG_PING_ERROR_RESPONSE,
745*d9f75844SAndroid Build Coastguard Worker                        message->transaction_id());
746*d9f75844SAndroid Build Coastguard Worker 
747*d9f75844SAndroid Build Coastguard Worker   // When doing GICE, we need to write out the error code incorrectly to
748*d9f75844SAndroid Build Coastguard Worker   // maintain backwards compatiblility.
749*d9f75844SAndroid Build Coastguard Worker   auto error_attr = StunAttribute::CreateErrorCode();
750*d9f75844SAndroid Build Coastguard Worker   error_attr->SetCode(error_code);
751*d9f75844SAndroid Build Coastguard Worker   error_attr->SetReason(std::string(reason));
752*d9f75844SAndroid Build Coastguard Worker   response.AddAttribute(std::move(error_attr));
753*d9f75844SAndroid Build Coastguard Worker 
754*d9f75844SAndroid Build Coastguard Worker   // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY,
755*d9f75844SAndroid Build Coastguard Worker   // because we don't have enough information to determine the shared secret.
756*d9f75844SAndroid Build Coastguard Worker   if (error_code != STUN_ERROR_BAD_REQUEST &&
757*d9f75844SAndroid Build Coastguard Worker       error_code != STUN_ERROR_UNAUTHORIZED &&
758*d9f75844SAndroid Build Coastguard Worker       message->type() != GOOG_PING_REQUEST) {
759*d9f75844SAndroid Build Coastguard Worker     if (message->type() == STUN_BINDING_REQUEST) {
760*d9f75844SAndroid Build Coastguard Worker       response.AddMessageIntegrity(password_);
761*d9f75844SAndroid Build Coastguard Worker     } else {
762*d9f75844SAndroid Build Coastguard Worker       response.AddMessageIntegrity32(password_);
763*d9f75844SAndroid Build Coastguard Worker     }
764*d9f75844SAndroid Build Coastguard Worker   }
765*d9f75844SAndroid Build Coastguard Worker 
766*d9f75844SAndroid Build Coastguard Worker   if (message->type() == STUN_BINDING_REQUEST) {
767*d9f75844SAndroid Build Coastguard Worker     response.AddFingerprint();
768*d9f75844SAndroid Build Coastguard Worker   }
769*d9f75844SAndroid Build Coastguard Worker 
770*d9f75844SAndroid Build Coastguard Worker   // Send the response message.
771*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferWriter buf;
772*d9f75844SAndroid Build Coastguard Worker   response.Write(&buf);
773*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions options(StunDscpValue());
774*d9f75844SAndroid Build Coastguard Worker   options.info_signaled_after_sent.packet_type =
775*d9f75844SAndroid Build Coastguard Worker       rtc::PacketType::kIceConnectivityCheckResponse;
776*d9f75844SAndroid Build Coastguard Worker   SendTo(buf.Data(), buf.Length(), addr, options, false);
777*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Sending STUN "
778*d9f75844SAndroid Build Coastguard Worker                    << StunMethodToString(response.type())
779*d9f75844SAndroid Build Coastguard Worker                    << ": reason=" << reason << " to "
780*d9f75844SAndroid Build Coastguard Worker                    << addr.ToSensitiveString();
781*d9f75844SAndroid Build Coastguard Worker }
782*d9f75844SAndroid Build Coastguard Worker 
SendUnknownAttributesErrorResponse(StunMessage * message,const rtc::SocketAddress & addr,const std::vector<uint16_t> & unknown_types)783*d9f75844SAndroid Build Coastguard Worker void Port::SendUnknownAttributesErrorResponse(
784*d9f75844SAndroid Build Coastguard Worker     StunMessage* message,
785*d9f75844SAndroid Build Coastguard Worker     const rtc::SocketAddress& addr,
786*d9f75844SAndroid Build Coastguard Worker     const std::vector<uint16_t>& unknown_types) {
787*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(message->type() == STUN_BINDING_REQUEST);
788*d9f75844SAndroid Build Coastguard Worker 
789*d9f75844SAndroid Build Coastguard Worker   // Fill in the response message.
790*d9f75844SAndroid Build Coastguard Worker   StunMessage response(STUN_BINDING_ERROR_RESPONSE, message->transaction_id());
791*d9f75844SAndroid Build Coastguard Worker 
792*d9f75844SAndroid Build Coastguard Worker   auto error_attr = StunAttribute::CreateErrorCode();
793*d9f75844SAndroid Build Coastguard Worker   error_attr->SetCode(STUN_ERROR_UNKNOWN_ATTRIBUTE);
794*d9f75844SAndroid Build Coastguard Worker   error_attr->SetReason(STUN_ERROR_REASON_UNKNOWN_ATTRIBUTE);
795*d9f75844SAndroid Build Coastguard Worker   response.AddAttribute(std::move(error_attr));
796*d9f75844SAndroid Build Coastguard Worker 
797*d9f75844SAndroid Build Coastguard Worker   std::unique_ptr<StunUInt16ListAttribute> unknown_attr =
798*d9f75844SAndroid Build Coastguard Worker       StunAttribute::CreateUnknownAttributes();
799*d9f75844SAndroid Build Coastguard Worker   for (uint16_t type : unknown_types) {
800*d9f75844SAndroid Build Coastguard Worker     unknown_attr->AddType(type);
801*d9f75844SAndroid Build Coastguard Worker   }
802*d9f75844SAndroid Build Coastguard Worker   response.AddAttribute(std::move(unknown_attr));
803*d9f75844SAndroid Build Coastguard Worker 
804*d9f75844SAndroid Build Coastguard Worker   response.AddMessageIntegrity(password_);
805*d9f75844SAndroid Build Coastguard Worker   response.AddFingerprint();
806*d9f75844SAndroid Build Coastguard Worker 
807*d9f75844SAndroid Build Coastguard Worker   // Send the response message.
808*d9f75844SAndroid Build Coastguard Worker   rtc::ByteBufferWriter buf;
809*d9f75844SAndroid Build Coastguard Worker   response.Write(&buf);
810*d9f75844SAndroid Build Coastguard Worker   rtc::PacketOptions options(StunDscpValue());
811*d9f75844SAndroid Build Coastguard Worker   options.info_signaled_after_sent.packet_type =
812*d9f75844SAndroid Build Coastguard Worker       rtc::PacketType::kIceConnectivityCheckResponse;
813*d9f75844SAndroid Build Coastguard Worker   SendTo(buf.Data(), buf.Length(), addr, options, false);
814*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_ERROR) << ToString() << ": Sending STUN binding error: reason="
815*d9f75844SAndroid Build Coastguard Worker                     << STUN_ERROR_UNKNOWN_ATTRIBUTE << " to "
816*d9f75844SAndroid Build Coastguard Worker                     << addr.ToSensitiveString();
817*d9f75844SAndroid Build Coastguard Worker }
818*d9f75844SAndroid Build Coastguard Worker 
KeepAliveUntilPruned()819*d9f75844SAndroid Build Coastguard Worker void Port::KeepAliveUntilPruned() {
820*d9f75844SAndroid Build Coastguard Worker   // If it is pruned, we won't bring it up again.
821*d9f75844SAndroid Build Coastguard Worker   if (state_ == State::INIT) {
822*d9f75844SAndroid Build Coastguard Worker     state_ = State::KEEP_ALIVE_UNTIL_PRUNED;
823*d9f75844SAndroid Build Coastguard Worker   }
824*d9f75844SAndroid Build Coastguard Worker }
825*d9f75844SAndroid Build Coastguard Worker 
Prune()826*d9f75844SAndroid Build Coastguard Worker void Port::Prune() {
827*d9f75844SAndroid Build Coastguard Worker   state_ = State::PRUNED;
828*d9f75844SAndroid Build Coastguard Worker   PostDestroyIfDead(/*delayed=*/false);
829*d9f75844SAndroid Build Coastguard Worker }
830*d9f75844SAndroid Build Coastguard Worker 
831*d9f75844SAndroid Build Coastguard Worker // Call to stop any currently pending operations from running.
CancelPendingTasks()832*d9f75844SAndroid Build Coastguard Worker void Port::CancelPendingTasks() {
833*d9f75844SAndroid Build Coastguard Worker   TRACE_EVENT0("webrtc", "Port::CancelPendingTasks");
834*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
835*d9f75844SAndroid Build Coastguard Worker   weak_factory_.InvalidateWeakPtrs();
836*d9f75844SAndroid Build Coastguard Worker }
837*d9f75844SAndroid Build Coastguard Worker 
PostDestroyIfDead(bool delayed)838*d9f75844SAndroid Build Coastguard Worker void Port::PostDestroyIfDead(bool delayed) {
839*d9f75844SAndroid Build Coastguard Worker   rtc::WeakPtr<Port> weak_ptr = NewWeakPtr();
840*d9f75844SAndroid Build Coastguard Worker   auto task = [weak_ptr = std::move(weak_ptr)] {
841*d9f75844SAndroid Build Coastguard Worker     if (weak_ptr) {
842*d9f75844SAndroid Build Coastguard Worker       weak_ptr->DestroyIfDead();
843*d9f75844SAndroid Build Coastguard Worker     }
844*d9f75844SAndroid Build Coastguard Worker   };
845*d9f75844SAndroid Build Coastguard Worker   if (delayed) {
846*d9f75844SAndroid Build Coastguard Worker     thread_->PostDelayedTask(std::move(task),
847*d9f75844SAndroid Build Coastguard Worker                              TimeDelta::Millis(timeout_delay_));
848*d9f75844SAndroid Build Coastguard Worker   } else {
849*d9f75844SAndroid Build Coastguard Worker     thread_->PostTask(std::move(task));
850*d9f75844SAndroid Build Coastguard Worker   }
851*d9f75844SAndroid Build Coastguard Worker }
852*d9f75844SAndroid Build Coastguard Worker 
DestroyIfDead()853*d9f75844SAndroid Build Coastguard Worker void Port::DestroyIfDead() {
854*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
855*d9f75844SAndroid Build Coastguard Worker   bool dead =
856*d9f75844SAndroid Build Coastguard Worker       (state_ == State::INIT || state_ == State::PRUNED) &&
857*d9f75844SAndroid Build Coastguard Worker       connections_.empty() &&
858*d9f75844SAndroid Build Coastguard Worker       rtc::TimeMillis() - last_time_all_connections_removed_ >= timeout_delay_;
859*d9f75844SAndroid Build Coastguard Worker   if (dead) {
860*d9f75844SAndroid Build Coastguard Worker     Destroy();
861*d9f75844SAndroid Build Coastguard Worker   }
862*d9f75844SAndroid Build Coastguard Worker }
863*d9f75844SAndroid Build Coastguard Worker 
SubscribePortDestroyed(std::function<void (PortInterface *)> callback)864*d9f75844SAndroid Build Coastguard Worker void Port::SubscribePortDestroyed(
865*d9f75844SAndroid Build Coastguard Worker     std::function<void(PortInterface*)> callback) {
866*d9f75844SAndroid Build Coastguard Worker   port_destroyed_callback_list_.AddReceiver(callback);
867*d9f75844SAndroid Build Coastguard Worker }
868*d9f75844SAndroid Build Coastguard Worker 
SendPortDestroyed(Port * port)869*d9f75844SAndroid Build Coastguard Worker void Port::SendPortDestroyed(Port* port) {
870*d9f75844SAndroid Build Coastguard Worker   port_destroyed_callback_list_.Send(port);
871*d9f75844SAndroid Build Coastguard Worker }
OnNetworkTypeChanged(const rtc::Network * network)872*d9f75844SAndroid Build Coastguard Worker void Port::OnNetworkTypeChanged(const rtc::Network* network) {
873*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(network == network_);
874*d9f75844SAndroid Build Coastguard Worker 
875*d9f75844SAndroid Build Coastguard Worker   UpdateNetworkCost();
876*d9f75844SAndroid Build Coastguard Worker }
877*d9f75844SAndroid Build Coastguard Worker 
ToString() const878*d9f75844SAndroid Build Coastguard Worker std::string Port::ToString() const {
879*d9f75844SAndroid Build Coastguard Worker   rtc::StringBuilder ss;
880*d9f75844SAndroid Build Coastguard Worker   ss << "Port[" << rtc::ToHex(reinterpret_cast<uintptr_t>(this)) << ":"
881*d9f75844SAndroid Build Coastguard Worker      << content_name_ << ":" << component_ << ":" << generation_ << ":" << type_
882*d9f75844SAndroid Build Coastguard Worker      << ":" << network_->ToString() << "]";
883*d9f75844SAndroid Build Coastguard Worker   return ss.Release();
884*d9f75844SAndroid Build Coastguard Worker }
885*d9f75844SAndroid Build Coastguard Worker 
886*d9f75844SAndroid Build Coastguard Worker // TODO(honghaiz): Make the network cost configurable from user setting.
UpdateNetworkCost()887*d9f75844SAndroid Build Coastguard Worker void Port::UpdateNetworkCost() {
888*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
889*d9f75844SAndroid Build Coastguard Worker   uint16_t new_cost = network_->GetCost(field_trials());
890*d9f75844SAndroid Build Coastguard Worker   if (network_cost_ == new_cost) {
891*d9f75844SAndroid Build Coastguard Worker     return;
892*d9f75844SAndroid Build Coastguard Worker   }
893*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << "Network cost changed from " << network_cost_ << " to "
894*d9f75844SAndroid Build Coastguard Worker                    << new_cost
895*d9f75844SAndroid Build Coastguard Worker                    << ". Number of candidates created: " << candidates_.size()
896*d9f75844SAndroid Build Coastguard Worker                    << ". Number of connections created: "
897*d9f75844SAndroid Build Coastguard Worker                    << connections_.size();
898*d9f75844SAndroid Build Coastguard Worker   network_cost_ = new_cost;
899*d9f75844SAndroid Build Coastguard Worker   for (cricket::Candidate& candidate : candidates_)
900*d9f75844SAndroid Build Coastguard Worker     candidate.set_network_cost(network_cost_);
901*d9f75844SAndroid Build Coastguard Worker 
902*d9f75844SAndroid Build Coastguard Worker   for (auto& [unused, connection] : connections_)
903*d9f75844SAndroid Build Coastguard Worker     connection->SetLocalCandidateNetworkCost(network_cost_);
904*d9f75844SAndroid Build Coastguard Worker }
905*d9f75844SAndroid Build Coastguard Worker 
EnablePortPackets()906*d9f75844SAndroid Build Coastguard Worker void Port::EnablePortPackets() {
907*d9f75844SAndroid Build Coastguard Worker   enable_port_packets_ = true;
908*d9f75844SAndroid Build Coastguard Worker }
909*d9f75844SAndroid Build Coastguard Worker 
OnConnectionDestroyed(Connection * conn)910*d9f75844SAndroid Build Coastguard Worker bool Port::OnConnectionDestroyed(Connection* conn) {
911*d9f75844SAndroid Build Coastguard Worker   if (connections_.erase(conn->remote_candidate().address()) == 0) {
912*d9f75844SAndroid Build Coastguard Worker     // This could indicate a programmer error outside of webrtc so while we
913*d9f75844SAndroid Build Coastguard Worker     // do have this check here to alert external developers, we also need to
914*d9f75844SAndroid Build Coastguard Worker     // handle it since it might be a corner case not caught in tests.
915*d9f75844SAndroid Build Coastguard Worker     RTC_DCHECK_NOTREACHED() << "Calling Destroy recursively?";
916*d9f75844SAndroid Build Coastguard Worker     return false;
917*d9f75844SAndroid Build Coastguard Worker   }
918*d9f75844SAndroid Build Coastguard Worker 
919*d9f75844SAndroid Build Coastguard Worker   HandleConnectionDestroyed(conn);
920*d9f75844SAndroid Build Coastguard Worker 
921*d9f75844SAndroid Build Coastguard Worker   // Ports time out after all connections fail if it is not marked as
922*d9f75844SAndroid Build Coastguard Worker   // "keep alive until pruned."
923*d9f75844SAndroid Build Coastguard Worker   // Note: If a new connection is added after this message is posted, but it
924*d9f75844SAndroid Build Coastguard Worker   // fails and is removed before kPortTimeoutDelay, then this message will
925*d9f75844SAndroid Build Coastguard Worker   // not cause the Port to be destroyed.
926*d9f75844SAndroid Build Coastguard Worker   if (connections_.empty()) {
927*d9f75844SAndroid Build Coastguard Worker     last_time_all_connections_removed_ = rtc::TimeMillis();
928*d9f75844SAndroid Build Coastguard Worker     PostDestroyIfDead(/*delayed=*/true);
929*d9f75844SAndroid Build Coastguard Worker   }
930*d9f75844SAndroid Build Coastguard Worker 
931*d9f75844SAndroid Build Coastguard Worker   return true;
932*d9f75844SAndroid Build Coastguard Worker }
933*d9f75844SAndroid Build Coastguard Worker 
DestroyConnectionInternal(Connection * conn,bool async)934*d9f75844SAndroid Build Coastguard Worker void Port::DestroyConnectionInternal(Connection* conn, bool async) {
935*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK_RUN_ON(thread_);
936*d9f75844SAndroid Build Coastguard Worker   if (!OnConnectionDestroyed(conn))
937*d9f75844SAndroid Build Coastguard Worker     return;
938*d9f75844SAndroid Build Coastguard Worker 
939*d9f75844SAndroid Build Coastguard Worker   conn->Shutdown();
940*d9f75844SAndroid Build Coastguard Worker   if (async) {
941*d9f75844SAndroid Build Coastguard Worker     // Unwind the stack before deleting the object in case upstream callers
942*d9f75844SAndroid Build Coastguard Worker     // need to refer to the Connection's state as part of teardown.
943*d9f75844SAndroid Build Coastguard Worker     // NOTE: We move ownership of `conn` into the capture section of the lambda
944*d9f75844SAndroid Build Coastguard Worker     // so that the object will always be deleted, including if PostTask fails.
945*d9f75844SAndroid Build Coastguard Worker     // In such a case (only tests), deletion would happen inside of the call
946*d9f75844SAndroid Build Coastguard Worker     // to `DestroyConnection()`.
947*d9f75844SAndroid Build Coastguard Worker     thread_->PostTask([conn = absl::WrapUnique(conn)]() {});
948*d9f75844SAndroid Build Coastguard Worker   } else {
949*d9f75844SAndroid Build Coastguard Worker     delete conn;
950*d9f75844SAndroid Build Coastguard Worker   }
951*d9f75844SAndroid Build Coastguard Worker }
952*d9f75844SAndroid Build Coastguard Worker 
Destroy()953*d9f75844SAndroid Build Coastguard Worker void Port::Destroy() {
954*d9f75844SAndroid Build Coastguard Worker   RTC_DCHECK(connections_.empty());
955*d9f75844SAndroid Build Coastguard Worker   RTC_LOG(LS_INFO) << ToString() << ": Port deleted";
956*d9f75844SAndroid Build Coastguard Worker   SendPortDestroyed(this);
957*d9f75844SAndroid Build Coastguard Worker   delete this;
958*d9f75844SAndroid Build Coastguard Worker }
959*d9f75844SAndroid Build Coastguard Worker 
username_fragment() const960*d9f75844SAndroid Build Coastguard Worker const std::string Port::username_fragment() const {
961*d9f75844SAndroid Build Coastguard Worker   return ice_username_fragment_;
962*d9f75844SAndroid Build Coastguard Worker }
963*d9f75844SAndroid Build Coastguard Worker 
CopyPortInformationToPacketInfo(rtc::PacketInfo * info) const964*d9f75844SAndroid Build Coastguard Worker void Port::CopyPortInformationToPacketInfo(rtc::PacketInfo* info) const {
965*d9f75844SAndroid Build Coastguard Worker   info->protocol = ConvertProtocolTypeToPacketInfoProtocolType(GetProtocol());
966*d9f75844SAndroid Build Coastguard Worker   info->network_id = Network()->id();
967*d9f75844SAndroid Build Coastguard Worker }
968*d9f75844SAndroid Build Coastguard Worker 
969*d9f75844SAndroid Build Coastguard Worker }  // namespace cricket
970