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