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