• 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 "webrtc/p2p/base/port.h"
12 
13 #include <algorithm>
14 #include <vector>
15 
16 #include "webrtc/p2p/base/common.h"
17 #include "webrtc/p2p/base/portallocator.h"
18 #include "webrtc/base/base64.h"
19 #include "webrtc/base/crc32.h"
20 #include "webrtc/base/helpers.h"
21 #include "webrtc/base/logging.h"
22 #include "webrtc/base/messagedigest.h"
23 #include "webrtc/base/scoped_ptr.h"
24 #include "webrtc/base/stringencode.h"
25 #include "webrtc/base/stringutils.h"
26 
27 namespace {
28 
29 // Determines whether we have seen at least the given maximum number of
30 // pings fail to have a response.
TooManyFailures(const std::vector<cricket::Connection::SentPing> & pings_since_last_response,uint32_t maximum_failures,uint32_t rtt_estimate,uint32_t now)31 inline bool TooManyFailures(
32     const std::vector<cricket::Connection::SentPing>& pings_since_last_response,
33     uint32_t maximum_failures,
34     uint32_t rtt_estimate,
35     uint32_t now) {
36   // If we haven't sent that many pings, then we can't have failed that many.
37   if (pings_since_last_response.size() < maximum_failures)
38     return false;
39 
40   // Check if the window in which we would expect a response to the ping has
41   // already elapsed.
42   uint32_t expected_response_time =
43       pings_since_last_response[maximum_failures - 1].sent_time + rtt_estimate;
44   return now > expected_response_time;
45 }
46 
47 // Determines whether we have gone too long without seeing any response.
TooLongWithoutResponse(const std::vector<cricket::Connection::SentPing> & pings_since_last_response,uint32_t maximum_time,uint32_t now)48 inline bool TooLongWithoutResponse(
49     const std::vector<cricket::Connection::SentPing>& pings_since_last_response,
50     uint32_t maximum_time,
51     uint32_t now) {
52   if (pings_since_last_response.size() == 0)
53     return false;
54 
55   auto first = pings_since_last_response[0];
56   return now > (first.sent_time + maximum_time);
57 }
58 
59 // We will restrict RTT estimates (when used for determining state) to be
60 // within a reasonable range.
61 const uint32_t MINIMUM_RTT = 100;   // 0.1 seconds
62 const uint32_t MAXIMUM_RTT = 3000;  // 3 seconds
63 
64 // When we don't have any RTT data, we have to pick something reasonable.  We
65 // use a large value just in case the connection is really slow.
66 const uint32_t DEFAULT_RTT = MAXIMUM_RTT;
67 
68 // Computes our estimate of the RTT given the current estimate.
ConservativeRTTEstimate(uint32_t rtt)69 inline uint32_t ConservativeRTTEstimate(uint32_t rtt) {
70   return std::max(MINIMUM_RTT, std::min(MAXIMUM_RTT, 2 * rtt));
71 }
72 
73 // Weighting of the old rtt value to new data.
74 const int RTT_RATIO = 3;  // 3 : 1
75 
76 // The delay before we begin checking if this port is useless.
77 const int kPortTimeoutDelay = 30 * 1000;  // 30 seconds
78 }
79 
80 namespace cricket {
81 
82 // TODO(ronghuawu): Use "host", "srflx", "prflx" and "relay". But this requires
83 // the signaling part be updated correspondingly as well.
84 const char LOCAL_PORT_TYPE[] = "local";
85 const char STUN_PORT_TYPE[] = "stun";
86 const char PRFLX_PORT_TYPE[] = "prflx";
87 const char RELAY_PORT_TYPE[] = "relay";
88 
89 const char UDP_PROTOCOL_NAME[] = "udp";
90 const char TCP_PROTOCOL_NAME[] = "tcp";
91 const char SSLTCP_PROTOCOL_NAME[] = "ssltcp";
92 
93 static const char* const PROTO_NAMES[] = { UDP_PROTOCOL_NAME,
94                                            TCP_PROTOCOL_NAME,
95                                            SSLTCP_PROTOCOL_NAME };
96 
ProtoToString(ProtocolType proto)97 const char* ProtoToString(ProtocolType proto) {
98   return PROTO_NAMES[proto];
99 }
100 
StringToProto(const char * value,ProtocolType * proto)101 bool StringToProto(const char* value, ProtocolType* proto) {
102   for (size_t i = 0; i <= PROTO_LAST; ++i) {
103     if (_stricmp(PROTO_NAMES[i], value) == 0) {
104       *proto = static_cast<ProtocolType>(i);
105       return true;
106     }
107   }
108   return false;
109 }
110 
111 // RFC 6544, TCP candidate encoding rules.
112 const int DISCARD_PORT = 9;
113 const char TCPTYPE_ACTIVE_STR[] = "active";
114 const char TCPTYPE_PASSIVE_STR[] = "passive";
115 const char TCPTYPE_SIMOPEN_STR[] = "so";
116 
117 // Foundation:  An arbitrary string that is the same for two candidates
118 //   that have the same type, base IP address, protocol (UDP, TCP,
119 //   etc.), and STUN or TURN server.  If any of these are different,
120 //   then the foundation will be different.  Two candidate pairs with
121 //   the same foundation pairs are likely to have similar network
122 //   characteristics.  Foundations are used in the frozen algorithm.
ComputeFoundation(const std::string & type,const std::string & protocol,const rtc::SocketAddress & base_address)123 static std::string ComputeFoundation(
124     const std::string& type,
125     const std::string& protocol,
126     const rtc::SocketAddress& base_address) {
127   std::ostringstream ost;
128   ost << type << base_address.ipaddr().ToString() << protocol;
129   return rtc::ToString<uint32_t>(rtc::ComputeCrc32(ost.str()));
130 }
131 
Port(rtc::Thread * thread,rtc::PacketSocketFactory * factory,rtc::Network * network,const rtc::IPAddress & ip,const std::string & username_fragment,const std::string & password)132 Port::Port(rtc::Thread* thread,
133            rtc::PacketSocketFactory* factory,
134            rtc::Network* network,
135            const rtc::IPAddress& ip,
136            const std::string& username_fragment,
137            const std::string& password)
138     : thread_(thread),
139       factory_(factory),
140       send_retransmit_count_attribute_(false),
141       network_(network),
142       ip_(ip),
143       min_port_(0),
144       max_port_(0),
145       component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
146       generation_(0),
147       ice_username_fragment_(username_fragment),
148       password_(password),
149       timeout_delay_(kPortTimeoutDelay),
150       enable_port_packets_(false),
151       ice_role_(ICEROLE_UNKNOWN),
152       tiebreaker_(0),
153       shared_socket_(true),
154       candidate_filter_(CF_ALL) {
155   Construct();
156 }
157 
Port(rtc::Thread * thread,const std::string & type,rtc::PacketSocketFactory * factory,rtc::Network * network,const rtc::IPAddress & ip,uint16_t min_port,uint16_t max_port,const std::string & username_fragment,const std::string & password)158 Port::Port(rtc::Thread* thread,
159            const std::string& type,
160            rtc::PacketSocketFactory* factory,
161            rtc::Network* network,
162            const rtc::IPAddress& ip,
163            uint16_t min_port,
164            uint16_t max_port,
165            const std::string& username_fragment,
166            const std::string& password)
167     : thread_(thread),
168       factory_(factory),
169       type_(type),
170       send_retransmit_count_attribute_(false),
171       network_(network),
172       ip_(ip),
173       min_port_(min_port),
174       max_port_(max_port),
175       component_(ICE_CANDIDATE_COMPONENT_DEFAULT),
176       generation_(0),
177       ice_username_fragment_(username_fragment),
178       password_(password),
179       timeout_delay_(kPortTimeoutDelay),
180       enable_port_packets_(false),
181       ice_role_(ICEROLE_UNKNOWN),
182       tiebreaker_(0),
183       shared_socket_(false),
184       candidate_filter_(CF_ALL) {
185   ASSERT(factory_ != NULL);
186   Construct();
187 }
188 
Construct()189 void Port::Construct() {
190   // TODO(pthatcher): Remove this old behavior once we're sure no one
191   // relies on it.  If the username_fragment and password are empty,
192   // we should just create one.
193   if (ice_username_fragment_.empty()) {
194     ASSERT(password_.empty());
195     ice_username_fragment_ = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
196     password_ = rtc::CreateRandomString(ICE_PWD_LENGTH);
197   }
198   LOG_J(LS_INFO, this) << "Port created";
199 }
200 
~Port()201 Port::~Port() {
202   // Delete all of the remaining connections.  We copy the list up front
203   // because each deletion will cause it to be modified.
204 
205   std::vector<Connection*> list;
206 
207   AddressMap::iterator iter = connections_.begin();
208   while (iter != connections_.end()) {
209     list.push_back(iter->second);
210     ++iter;
211   }
212 
213   for (uint32_t i = 0; i < list.size(); i++)
214     delete list[i];
215 }
216 
GetConnection(const rtc::SocketAddress & remote_addr)217 Connection* Port::GetConnection(const rtc::SocketAddress& remote_addr) {
218   AddressMap::const_iterator iter = connections_.find(remote_addr);
219   if (iter != connections_.end())
220     return iter->second;
221   else
222     return NULL;
223 }
224 
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,bool final)225 void Port::AddAddress(const rtc::SocketAddress& address,
226                       const rtc::SocketAddress& base_address,
227                       const rtc::SocketAddress& related_address,
228                       const std::string& protocol,
229                       const std::string& relay_protocol,
230                       const std::string& tcptype,
231                       const std::string& type,
232                       uint32_t type_preference,
233                       uint32_t relay_preference,
234                       bool final) {
235   if (protocol == TCP_PROTOCOL_NAME && type == LOCAL_PORT_TYPE) {
236     ASSERT(!tcptype.empty());
237   }
238 
239   Candidate c;
240   c.set_id(rtc::CreateRandomString(8));
241   c.set_component(component_);
242   c.set_type(type);
243   c.set_protocol(protocol);
244   c.set_relay_protocol(relay_protocol);
245   c.set_tcptype(tcptype);
246   c.set_address(address);
247   c.set_priority(c.GetPriority(type_preference, network_->preference(),
248                                relay_preference));
249   c.set_username(username_fragment());
250   c.set_password(password_);
251   c.set_network_name(network_->name());
252   c.set_network_type(network_->type());
253   c.set_generation(generation_);
254   c.set_related_address(related_address);
255   c.set_foundation(ComputeFoundation(type, protocol, base_address));
256   candidates_.push_back(c);
257   SignalCandidateReady(this, c);
258 
259   if (final) {
260     SignalPortComplete(this);
261   }
262 }
263 
AddConnection(Connection * conn)264 void Port::AddConnection(Connection* conn) {
265   connections_[conn->remote_candidate().address()] = conn;
266   conn->SignalDestroyed.connect(this, &Port::OnConnectionDestroyed);
267   SignalConnectionCreated(this, conn);
268 }
269 
OnReadPacket(const char * data,size_t size,const rtc::SocketAddress & addr,ProtocolType proto)270 void Port::OnReadPacket(
271     const char* data, size_t size, const rtc::SocketAddress& addr,
272     ProtocolType proto) {
273   // If the user has enabled port packets, just hand this over.
274   if (enable_port_packets_) {
275     SignalReadPacket(this, data, size, addr);
276     return;
277   }
278 
279   // If this is an authenticated STUN request, then signal unknown address and
280   // send back a proper binding response.
281   rtc::scoped_ptr<IceMessage> msg;
282   std::string remote_username;
283   if (!GetStunMessage(data, size, addr, msg.accept(), &remote_username)) {
284     LOG_J(LS_ERROR, this) << "Received non-STUN packet from unknown address ("
285                           << addr.ToSensitiveString() << ")";
286   } else if (!msg) {
287     // STUN message handled already
288   } else if (msg->type() == STUN_BINDING_REQUEST) {
289     LOG(LS_INFO) << "Received STUN ping "
290                  << " id=" << rtc::hex_encode(msg->transaction_id())
291                  << " from unknown address " << addr.ToSensitiveString();
292 
293     // Check for role conflicts.
294     if (!MaybeIceRoleConflict(addr, msg.get(), remote_username)) {
295       LOG(LS_INFO) << "Received conflicting role from the peer.";
296       return;
297     }
298 
299     SignalUnknownAddress(this, addr, proto, msg.get(), remote_username, false);
300   } else {
301     // NOTE(tschmelcher): STUN_BINDING_RESPONSE is benign. It occurs if we
302     // pruned a connection for this port while it had STUN requests in flight,
303     // because we then get back responses for them, which this code correctly
304     // does not handle.
305     if (msg->type() != STUN_BINDING_RESPONSE) {
306       LOG_J(LS_ERROR, this) << "Received unexpected STUN message type ("
307                             << msg->type() << ") from unknown address ("
308                             << addr.ToSensitiveString() << ")";
309     }
310   }
311 }
312 
OnReadyToSend()313 void Port::OnReadyToSend() {
314   AddressMap::iterator iter = connections_.begin();
315   for (; iter != connections_.end(); ++iter) {
316     iter->second->OnReadyToSend();
317   }
318 }
319 
AddPrflxCandidate(const Candidate & local)320 size_t Port::AddPrflxCandidate(const Candidate& local) {
321   candidates_.push_back(local);
322   return (candidates_.size() - 1);
323 }
324 
GetStunMessage(const char * data,size_t size,const rtc::SocketAddress & addr,IceMessage ** out_msg,std::string * out_username)325 bool Port::GetStunMessage(const char* data, size_t size,
326                           const rtc::SocketAddress& addr,
327                           IceMessage** out_msg, std::string* out_username) {
328   // NOTE: This could clearly be optimized to avoid allocating any memory.
329   //       However, at the data rates we'll be looking at on the client side,
330   //       this probably isn't worth worrying about.
331   ASSERT(out_msg != NULL);
332   ASSERT(out_username != NULL);
333   *out_msg = NULL;
334   out_username->clear();
335 
336   // Don't bother parsing the packet if we can tell it's not STUN.
337   // In ICE mode, all STUN packets will have a valid fingerprint.
338   if (!StunMessage::ValidateFingerprint(data, size)) {
339     return false;
340   }
341 
342   // Parse the request message.  If the packet is not a complete and correct
343   // STUN message, then ignore it.
344   rtc::scoped_ptr<IceMessage> stun_msg(new IceMessage());
345   rtc::ByteBuffer buf(data, size);
346   if (!stun_msg->Read(&buf) || (buf.Length() > 0)) {
347     return false;
348   }
349 
350   if (stun_msg->type() == STUN_BINDING_REQUEST) {
351     // Check for the presence of USERNAME and MESSAGE-INTEGRITY (if ICE) first.
352     // If not present, fail with a 400 Bad Request.
353     if (!stun_msg->GetByteString(STUN_ATTR_USERNAME) ||
354         !stun_msg->GetByteString(STUN_ATTR_MESSAGE_INTEGRITY)) {
355       LOG_J(LS_ERROR, this) << "Received STUN request without username/M-I "
356                             << "from " << addr.ToSensitiveString();
357       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_BAD_REQUEST,
358                                STUN_ERROR_REASON_BAD_REQUEST);
359       return true;
360     }
361 
362     // If the username is bad or unknown, fail with a 401 Unauthorized.
363     std::string local_ufrag;
364     std::string remote_ufrag;
365     if (!ParseStunUsername(stun_msg.get(), &local_ufrag, &remote_ufrag) ||
366         local_ufrag != username_fragment()) {
367       LOG_J(LS_ERROR, this) << "Received STUN request with bad local username "
368                             << local_ufrag << " from "
369                             << addr.ToSensitiveString();
370       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
371                                STUN_ERROR_REASON_UNAUTHORIZED);
372       return true;
373     }
374 
375     // If ICE, and the MESSAGE-INTEGRITY is bad, fail with a 401 Unauthorized
376     if (!stun_msg->ValidateMessageIntegrity(data, size, password_)) {
377       LOG_J(LS_ERROR, this) << "Received STUN request with bad M-I "
378                             << "from " << addr.ToSensitiveString()
379                             << ", password_=" << password_;
380       SendBindingErrorResponse(stun_msg.get(), addr, STUN_ERROR_UNAUTHORIZED,
381                                STUN_ERROR_REASON_UNAUTHORIZED);
382       return true;
383     }
384     out_username->assign(remote_ufrag);
385   } else if ((stun_msg->type() == STUN_BINDING_RESPONSE) ||
386              (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE)) {
387     if (stun_msg->type() == STUN_BINDING_ERROR_RESPONSE) {
388       if (const StunErrorCodeAttribute* error_code = stun_msg->GetErrorCode()) {
389         LOG_J(LS_ERROR, this) << "Received STUN binding error:"
390                               << " class=" << error_code->eclass()
391                               << " number=" << error_code->number()
392                               << " reason='" << error_code->reason() << "'"
393                               << " from " << addr.ToSensitiveString();
394         // Return message to allow error-specific processing
395       } else {
396         LOG_J(LS_ERROR, this) << "Received STUN binding error without a error "
397                               << "code from " << addr.ToSensitiveString();
398         return true;
399       }
400     }
401     // NOTE: Username should not be used in verifying response messages.
402     out_username->clear();
403   } else if (stun_msg->type() == STUN_BINDING_INDICATION) {
404     LOG_J(LS_VERBOSE, this) << "Received STUN binding indication:"
405                             << " from " << addr.ToSensitiveString();
406     out_username->clear();
407     // No stun attributes will be verified, if it's stun indication message.
408     // Returning from end of the this method.
409   } else {
410     LOG_J(LS_ERROR, this) << "Received STUN packet with invalid type ("
411                           << stun_msg->type() << ") from "
412                           << addr.ToSensitiveString();
413     return true;
414   }
415 
416   // Return the STUN message found.
417   *out_msg = stun_msg.release();
418   return true;
419 }
420 
IsCompatibleAddress(const rtc::SocketAddress & addr)421 bool Port::IsCompatibleAddress(const rtc::SocketAddress& addr) {
422   int family = ip().family();
423   // We use single-stack sockets, so families must match.
424   if (addr.family() != family) {
425     return false;
426   }
427   // Link-local IPv6 ports can only connect to other link-local IPv6 ports.
428   if (family == AF_INET6 &&
429       (IPIsLinkLocal(ip()) != IPIsLinkLocal(addr.ipaddr()))) {
430     return false;
431   }
432   return true;
433 }
434 
ParseStunUsername(const StunMessage * stun_msg,std::string * local_ufrag,std::string * remote_ufrag) const435 bool Port::ParseStunUsername(const StunMessage* stun_msg,
436                              std::string* local_ufrag,
437                              std::string* remote_ufrag) const {
438   // The packet must include a username that either begins or ends with our
439   // fragment.  It should begin with our fragment if it is a request and it
440   // should end with our fragment if it is a response.
441   local_ufrag->clear();
442   remote_ufrag->clear();
443   const StunByteStringAttribute* username_attr =
444         stun_msg->GetByteString(STUN_ATTR_USERNAME);
445   if (username_attr == NULL)
446     return false;
447 
448   // RFRAG:LFRAG
449   const std::string username = username_attr->GetString();
450   size_t colon_pos = username.find(":");
451   if (colon_pos == std::string::npos) {
452     return false;
453   }
454 
455   *local_ufrag = username.substr(0, colon_pos);
456   *remote_ufrag = username.substr(colon_pos + 1, username.size());
457   return true;
458 }
459 
MaybeIceRoleConflict(const rtc::SocketAddress & addr,IceMessage * stun_msg,const std::string & remote_ufrag)460 bool Port::MaybeIceRoleConflict(
461     const rtc::SocketAddress& addr, IceMessage* stun_msg,
462     const std::string& remote_ufrag) {
463   // Validate ICE_CONTROLLING or ICE_CONTROLLED attributes.
464   bool ret = true;
465   IceRole remote_ice_role = ICEROLE_UNKNOWN;
466   uint64_t remote_tiebreaker = 0;
467   const StunUInt64Attribute* stun_attr =
468       stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLING);
469   if (stun_attr) {
470     remote_ice_role = ICEROLE_CONTROLLING;
471     remote_tiebreaker = stun_attr->value();
472   }
473 
474   // If |remote_ufrag| is same as port local username fragment and
475   // tie breaker value received in the ping message matches port
476   // tiebreaker value this must be a loopback call.
477   // We will treat this as valid scenario.
478   if (remote_ice_role == ICEROLE_CONTROLLING &&
479       username_fragment() == remote_ufrag &&
480       remote_tiebreaker == IceTiebreaker()) {
481     return true;
482   }
483 
484   stun_attr = stun_msg->GetUInt64(STUN_ATTR_ICE_CONTROLLED);
485   if (stun_attr) {
486     remote_ice_role = ICEROLE_CONTROLLED;
487     remote_tiebreaker = stun_attr->value();
488   }
489 
490   switch (ice_role_) {
491     case ICEROLE_CONTROLLING:
492       if (ICEROLE_CONTROLLING == remote_ice_role) {
493         if (remote_tiebreaker >= tiebreaker_) {
494           SignalRoleConflict(this);
495         } else {
496           // Send Role Conflict (487) error response.
497           SendBindingErrorResponse(stun_msg, addr,
498               STUN_ERROR_ROLE_CONFLICT, STUN_ERROR_REASON_ROLE_CONFLICT);
499           ret = false;
500         }
501       }
502       break;
503     case ICEROLE_CONTROLLED:
504       if (ICEROLE_CONTROLLED == remote_ice_role) {
505         if (remote_tiebreaker < tiebreaker_) {
506           SignalRoleConflict(this);
507         } else {
508           // Send Role Conflict (487) error response.
509           SendBindingErrorResponse(stun_msg, addr,
510               STUN_ERROR_ROLE_CONFLICT, STUN_ERROR_REASON_ROLE_CONFLICT);
511           ret = false;
512         }
513       }
514       break;
515     default:
516       ASSERT(false);
517   }
518   return ret;
519 }
520 
CreateStunUsername(const std::string & remote_username,std::string * stun_username_attr_str) const521 void Port::CreateStunUsername(const std::string& remote_username,
522                               std::string* stun_username_attr_str) const {
523   stun_username_attr_str->clear();
524   *stun_username_attr_str = remote_username;
525   stun_username_attr_str->append(":");
526   stun_username_attr_str->append(username_fragment());
527 }
528 
SendBindingResponse(StunMessage * request,const rtc::SocketAddress & addr)529 void Port::SendBindingResponse(StunMessage* request,
530                                const rtc::SocketAddress& addr) {
531   ASSERT(request->type() == STUN_BINDING_REQUEST);
532 
533   // Retrieve the username from the request.
534   const StunByteStringAttribute* username_attr =
535       request->GetByteString(STUN_ATTR_USERNAME);
536   ASSERT(username_attr != NULL);
537   if (username_attr == NULL) {
538     // No valid username, skip the response.
539     return;
540   }
541 
542   // Fill in the response message.
543   StunMessage response;
544   response.SetType(STUN_BINDING_RESPONSE);
545   response.SetTransactionID(request->transaction_id());
546   const StunUInt32Attribute* retransmit_attr =
547       request->GetUInt32(STUN_ATTR_RETRANSMIT_COUNT);
548   if (retransmit_attr) {
549     // Inherit the incoming retransmit value in the response so the other side
550     // can see our view of lost pings.
551     response.AddAttribute(new StunUInt32Attribute(
552         STUN_ATTR_RETRANSMIT_COUNT, retransmit_attr->value()));
553 
554     if (retransmit_attr->value() > CONNECTION_WRITE_CONNECT_FAILURES) {
555       LOG_J(LS_INFO, this)
556           << "Received a remote ping with high retransmit count: "
557           << retransmit_attr->value();
558     }
559   }
560 
561   response.AddAttribute(
562       new StunXorAddressAttribute(STUN_ATTR_XOR_MAPPED_ADDRESS, addr));
563   response.AddMessageIntegrity(password_);
564   response.AddFingerprint();
565 
566   // Send the response message.
567   rtc::ByteBuffer buf;
568   response.Write(&buf);
569   rtc::PacketOptions options(DefaultDscpValue());
570   auto err = SendTo(buf.Data(), buf.Length(), addr, options, false);
571   if (err < 0) {
572     LOG_J(LS_ERROR, this)
573         << "Failed to send STUN ping response"
574         << ", to=" << addr.ToSensitiveString()
575         << ", err=" << err
576         << ", id=" << rtc::hex_encode(response.transaction_id());
577   } else {
578     // Log at LS_INFO if we send a stun ping response on an unwritable
579     // connection.
580     Connection* conn = GetConnection(addr);
581     rtc::LoggingSeverity sev = (conn && !conn->writable()) ?
582         rtc::LS_INFO : rtc::LS_VERBOSE;
583     LOG_JV(sev, this)
584         << "Sent STUN ping response"
585         << ", to=" << addr.ToSensitiveString()
586         << ", id=" << rtc::hex_encode(response.transaction_id());
587   }
588 }
589 
SendBindingErrorResponse(StunMessage * request,const rtc::SocketAddress & addr,int error_code,const std::string & reason)590 void Port::SendBindingErrorResponse(StunMessage* request,
591                                     const rtc::SocketAddress& addr,
592                                     int error_code, const std::string& reason) {
593   ASSERT(request->type() == STUN_BINDING_REQUEST);
594 
595   // Fill in the response message.
596   StunMessage response;
597   response.SetType(STUN_BINDING_ERROR_RESPONSE);
598   response.SetTransactionID(request->transaction_id());
599 
600   // When doing GICE, we need to write out the error code incorrectly to
601   // maintain backwards compatiblility.
602   StunErrorCodeAttribute* error_attr = StunAttribute::CreateErrorCode();
603   error_attr->SetCode(error_code);
604   error_attr->SetReason(reason);
605   response.AddAttribute(error_attr);
606 
607   // Per Section 10.1.2, certain error cases don't get a MESSAGE-INTEGRITY,
608   // because we don't have enough information to determine the shared secret.
609   if (error_code != STUN_ERROR_BAD_REQUEST &&
610       error_code != STUN_ERROR_UNAUTHORIZED)
611     response.AddMessageIntegrity(password_);
612   response.AddFingerprint();
613 
614   // Send the response message.
615   rtc::ByteBuffer buf;
616   response.Write(&buf);
617   rtc::PacketOptions options(DefaultDscpValue());
618   SendTo(buf.Data(), buf.Length(), addr, options, false);
619   LOG_J(LS_INFO, this) << "Sending STUN binding error: reason=" << reason
620                        << " to " << addr.ToSensitiveString();
621 }
622 
OnMessage(rtc::Message * pmsg)623 void Port::OnMessage(rtc::Message *pmsg) {
624   ASSERT(pmsg->message_id == MSG_DEAD);
625   if (dead()) {
626     Destroy();
627   }
628 }
629 
ToString() const630 std::string Port::ToString() const {
631   std::stringstream ss;
632   ss << "Port[" << content_name_ << ":" << component_
633      << ":" << generation_ << ":" << type_
634      << ":" << network_->ToString() << "]";
635   return ss.str();
636 }
637 
EnablePortPackets()638 void Port::EnablePortPackets() {
639   enable_port_packets_ = true;
640 }
641 
OnConnectionDestroyed(Connection * conn)642 void Port::OnConnectionDestroyed(Connection* conn) {
643   AddressMap::iterator iter =
644       connections_.find(conn->remote_candidate().address());
645   ASSERT(iter != connections_.end());
646   connections_.erase(iter);
647 
648   // On the controlled side, ports time out after all connections fail.
649   // Note: If a new connection is added after this message is posted, but it
650   // fails and is removed before kPortTimeoutDelay, then this message will
651   // still cause the Port to be destroyed.
652   if (dead()) {
653     thread_->PostDelayed(timeout_delay_, this, MSG_DEAD);
654   }
655 }
656 
Destroy()657 void Port::Destroy() {
658   ASSERT(connections_.empty());
659   LOG_J(LS_INFO, this) << "Port deleted";
660   SignalDestroyed(this);
661   delete this;
662 }
663 
username_fragment() const664 const std::string Port::username_fragment() const {
665   return ice_username_fragment_;
666 }
667 
668 // A ConnectionRequest is a simple STUN ping used to determine writability.
669 class ConnectionRequest : public StunRequest {
670  public:
ConnectionRequest(Connection * connection)671   explicit ConnectionRequest(Connection* connection)
672       : StunRequest(new IceMessage()),
673         connection_(connection) {
674   }
675 
~ConnectionRequest()676   virtual ~ConnectionRequest() {
677   }
678 
Prepare(StunMessage * request)679   void Prepare(StunMessage* request) override {
680     request->SetType(STUN_BINDING_REQUEST);
681     std::string username;
682     connection_->port()->CreateStunUsername(
683         connection_->remote_candidate().username(), &username);
684     request->AddAttribute(
685         new StunByteStringAttribute(STUN_ATTR_USERNAME, username));
686 
687     // connection_ already holds this ping, so subtract one from count.
688     if (connection_->port()->send_retransmit_count_attribute()) {
689       request->AddAttribute(new StunUInt32Attribute(
690           STUN_ATTR_RETRANSMIT_COUNT,
691           static_cast<uint32_t>(connection_->pings_since_last_response_.size() -
692                                 1)));
693     }
694 
695     // Adding ICE_CONTROLLED or ICE_CONTROLLING attribute based on the role.
696     if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLING) {
697       request->AddAttribute(new StunUInt64Attribute(
698           STUN_ATTR_ICE_CONTROLLING, connection_->port()->IceTiebreaker()));
699       // Since we are trying aggressive nomination, sending USE-CANDIDATE
700       // attribute in every ping.
701       // If we are dealing with a ice-lite end point, nomination flag
702       // in Connection will be set to false by default. Once the connection
703       // becomes "best connection", nomination flag will be turned on.
704       if (connection_->use_candidate_attr()) {
705         request->AddAttribute(new StunByteStringAttribute(
706             STUN_ATTR_USE_CANDIDATE));
707       }
708     } else if (connection_->port()->GetIceRole() == ICEROLE_CONTROLLED) {
709       request->AddAttribute(new StunUInt64Attribute(
710           STUN_ATTR_ICE_CONTROLLED, connection_->port()->IceTiebreaker()));
711     } else {
712       ASSERT(false);
713     }
714 
715     // Adding PRIORITY Attribute.
716     // Changing the type preference to Peer Reflexive and local preference
717     // and component id information is unchanged from the original priority.
718     // priority = (2^24)*(type preference) +
719     //           (2^8)*(local preference) +
720     //           (2^0)*(256 - component ID)
721     uint32_t prflx_priority =
722         ICE_TYPE_PREFERENCE_PRFLX << 24 |
723         (connection_->local_candidate().priority() & 0x00FFFFFF);
724     request->AddAttribute(
725         new StunUInt32Attribute(STUN_ATTR_PRIORITY, prflx_priority));
726 
727     // Adding Message Integrity attribute.
728     request->AddMessageIntegrity(connection_->remote_candidate().password());
729     // Adding Fingerprint.
730     request->AddFingerprint();
731   }
732 
OnResponse(StunMessage * response)733   void OnResponse(StunMessage* response) override {
734     connection_->OnConnectionRequestResponse(this, response);
735   }
736 
OnErrorResponse(StunMessage * response)737   void OnErrorResponse(StunMessage* response) override {
738     connection_->OnConnectionRequestErrorResponse(this, response);
739   }
740 
OnTimeout()741   void OnTimeout() override {
742     connection_->OnConnectionRequestTimeout(this);
743   }
744 
OnSent()745   void OnSent() override {
746     connection_->OnConnectionRequestSent(this);
747     // Each request is sent only once.  After a single delay , the request will
748     // time out.
749     timeout_ = true;
750   }
751 
resend_delay()752   int resend_delay() override {
753     return CONNECTION_RESPONSE_TIMEOUT;
754   }
755 
756  private:
757   Connection* connection_;
758 };
759 
760 //
761 // Connection
762 //
763 
Connection(Port * port,size_t index,const Candidate & remote_candidate)764 Connection::Connection(Port* port,
765                        size_t index,
766                        const Candidate& remote_candidate)
767     : port_(port),
768       local_candidate_index_(index),
769       remote_candidate_(remote_candidate),
770       write_state_(STATE_WRITE_INIT),
771       receiving_(false),
772       connected_(true),
773       pruned_(false),
774       use_candidate_attr_(false),
775       nominated_(false),
776       remote_ice_mode_(ICEMODE_FULL),
777       requests_(port->thread()),
778       rtt_(DEFAULT_RTT),
779       last_ping_sent_(0),
780       last_ping_received_(0),
781       last_data_received_(0),
782       last_ping_response_received_(0),
783       recv_rate_tracker_(100u, 10u),
784       send_rate_tracker_(100u, 10u),
785       sent_packets_discarded_(0),
786       sent_packets_total_(0),
787       reported_(false),
788       state_(STATE_WAITING),
789       receiving_timeout_(WEAK_CONNECTION_RECEIVE_TIMEOUT),
790       time_created_ms_(rtc::Time()) {
791   // All of our connections start in WAITING state.
792   // TODO(mallinath) - Start connections from STATE_FROZEN.
793   // Wire up to send stun packets
794   requests_.SignalSendPacket.connect(this, &Connection::OnSendStunPacket);
795   LOG_J(LS_INFO, this) << "Connection created";
796 }
797 
~Connection()798 Connection::~Connection() {
799 }
800 
local_candidate() const801 const Candidate& Connection::local_candidate() const {
802   ASSERT(local_candidate_index_ < port_->Candidates().size());
803   return port_->Candidates()[local_candidate_index_];
804 }
805 
priority() const806 uint64_t Connection::priority() const {
807   uint64_t priority = 0;
808   // RFC 5245 - 5.7.2.  Computing Pair Priority and Ordering Pairs
809   // Let G be the priority for the candidate provided by the controlling
810   // agent.  Let D be the priority for the candidate provided by the
811   // controlled agent.
812   // pair priority = 2^32*MIN(G,D) + 2*MAX(G,D) + (G>D?1:0)
813   IceRole role = port_->GetIceRole();
814   if (role != ICEROLE_UNKNOWN) {
815     uint32_t g = 0;
816     uint32_t d = 0;
817     if (role == ICEROLE_CONTROLLING) {
818       g = local_candidate().priority();
819       d = remote_candidate_.priority();
820     } else {
821       g = remote_candidate_.priority();
822       d = local_candidate().priority();
823     }
824     priority = std::min(g, d);
825     priority = priority << 32;
826     priority += 2 * std::max(g, d) + (g > d ? 1 : 0);
827   }
828   return priority;
829 }
830 
set_write_state(WriteState value)831 void Connection::set_write_state(WriteState value) {
832   WriteState old_value = write_state_;
833   write_state_ = value;
834   if (value != old_value) {
835     LOG_J(LS_VERBOSE, this) << "set_write_state from: " << old_value << " to "
836                             << value;
837     SignalStateChange(this);
838   }
839 }
840 
set_receiving(bool value)841 void Connection::set_receiving(bool value) {
842   if (value != receiving_) {
843     LOG_J(LS_VERBOSE, this) << "set_receiving to " << value;
844     receiving_ = value;
845     SignalStateChange(this);
846   }
847 }
848 
set_state(State state)849 void Connection::set_state(State state) {
850   State old_state = state_;
851   state_ = state;
852   if (state != old_state) {
853     LOG_J(LS_VERBOSE, this) << "set_state";
854   }
855 }
856 
set_connected(bool value)857 void Connection::set_connected(bool value) {
858   bool old_value = connected_;
859   connected_ = value;
860   if (value != old_value) {
861     LOG_J(LS_VERBOSE, this) << "set_connected from: " << old_value << " to "
862                             << value;
863   }
864 }
865 
set_use_candidate_attr(bool enable)866 void Connection::set_use_candidate_attr(bool enable) {
867   use_candidate_attr_ = enable;
868 }
869 
OnSendStunPacket(const void * data,size_t size,StunRequest * req)870 void Connection::OnSendStunPacket(const void* data, size_t size,
871                                   StunRequest* req) {
872   rtc::PacketOptions options(port_->DefaultDscpValue());
873   auto err = port_->SendTo(
874       data, size, remote_candidate_.address(), options, false);
875   if (err < 0) {
876     LOG_J(LS_WARNING, this) << "Failed to send STUN ping "
877                             << " err=" << err
878                             << " id=" << rtc::hex_encode(req->id());
879   }
880 }
881 
OnReadPacket(const char * data,size_t size,const rtc::PacketTime & packet_time)882 void Connection::OnReadPacket(
883   const char* data, size_t size, const rtc::PacketTime& packet_time) {
884   rtc::scoped_ptr<IceMessage> msg;
885   std::string remote_ufrag;
886   const rtc::SocketAddress& addr(remote_candidate_.address());
887   if (!port_->GetStunMessage(data, size, addr, msg.accept(), &remote_ufrag)) {
888     // The packet did not parse as a valid STUN message
889     // This is a data packet, pass it along.
890     set_receiving(true);
891     last_data_received_ = rtc::Time();
892     recv_rate_tracker_.AddSamples(size);
893     SignalReadPacket(this, data, size, packet_time);
894 
895     // If timed out sending writability checks, start up again
896     if (!pruned_ && (write_state_ == STATE_WRITE_TIMEOUT)) {
897       LOG(LS_WARNING) << "Received a data packet on a timed-out Connection. "
898                       << "Resetting state to STATE_WRITE_INIT.";
899       set_write_state(STATE_WRITE_INIT);
900     }
901   } else if (!msg) {
902     // The packet was STUN, but failed a check and was handled internally.
903   } else {
904     // The packet is STUN and passed the Port checks.
905     // Perform our own checks to ensure this packet is valid.
906     // If this is a STUN request, then update the receiving bit and respond.
907     // If this is a STUN response, then update the writable bit.
908     // Log at LS_INFO if we receive a ping on an unwritable connection.
909     rtc::LoggingSeverity sev = (!writable() ? rtc::LS_INFO : rtc::LS_VERBOSE);
910     switch (msg->type()) {
911       case STUN_BINDING_REQUEST:
912         LOG_JV(sev, this) << "Received STUN ping"
913                           << ", id=" << rtc::hex_encode(msg->transaction_id());
914 
915         if (remote_ufrag == remote_candidate_.username()) {
916           HandleBindingRequest(msg.get());
917         } else {
918           // The packet had the right local username, but the remote username
919           // was not the right one for the remote address.
920           LOG_J(LS_ERROR, this)
921             << "Received STUN request with bad remote username "
922             << remote_ufrag;
923           port_->SendBindingErrorResponse(msg.get(), addr,
924                                           STUN_ERROR_UNAUTHORIZED,
925                                           STUN_ERROR_REASON_UNAUTHORIZED);
926 
927         }
928         break;
929 
930       // Response from remote peer. Does it match request sent?
931       // This doesn't just check, it makes callbacks if transaction
932       // id's match.
933       case STUN_BINDING_RESPONSE:
934       case STUN_BINDING_ERROR_RESPONSE:
935         if (msg->ValidateMessageIntegrity(
936                 data, size, remote_candidate().password())) {
937           requests_.CheckResponse(msg.get());
938         }
939         // Otherwise silently discard the response message.
940         break;
941 
942       // Remote end point sent an STUN indication instead of regular binding
943       // request. In this case |last_ping_received_| will be updated but no
944       // response will be sent.
945       case STUN_BINDING_INDICATION:
946         ReceivedPing();
947         break;
948 
949       default:
950         ASSERT(false);
951         break;
952     }
953   }
954 }
955 
HandleBindingRequest(IceMessage * msg)956 void Connection::HandleBindingRequest(IceMessage* msg) {
957   // This connection should now be receiving.
958   ReceivedPing();
959 
960   const rtc::SocketAddress& remote_addr = remote_candidate_.address();
961   const std::string& remote_ufrag = remote_candidate_.username();
962   // Check for role conflicts.
963   if (!port_->MaybeIceRoleConflict(remote_addr, msg, remote_ufrag)) {
964     // Received conflicting role from the peer.
965     LOG(LS_INFO) << "Received conflicting role from the peer.";
966     return;
967   }
968 
969   // This is a validated stun request from remote peer.
970   port_->SendBindingResponse(msg, remote_addr);
971 
972   // If it timed out on writing check, start up again
973   if (!pruned_ && write_state_ == STATE_WRITE_TIMEOUT) {
974     set_write_state(STATE_WRITE_INIT);
975   }
976 
977   if (port_->GetIceRole() == ICEROLE_CONTROLLED) {
978     const StunByteStringAttribute* use_candidate_attr =
979         msg->GetByteString(STUN_ATTR_USE_CANDIDATE);
980     if (use_candidate_attr) {
981       set_nominated(true);
982       SignalNominated(this);
983     }
984   }
985 }
986 
OnReadyToSend()987 void Connection::OnReadyToSend() {
988   if (write_state_ == STATE_WRITABLE) {
989     SignalReadyToSend(this);
990   }
991 }
992 
Prune()993 void Connection::Prune() {
994   if (!pruned_ || active()) {
995     LOG_J(LS_VERBOSE, this) << "Connection pruned";
996     pruned_ = true;
997     requests_.Clear();
998     set_write_state(STATE_WRITE_TIMEOUT);
999   }
1000 }
1001 
Destroy()1002 void Connection::Destroy() {
1003   LOG_J(LS_VERBOSE, this) << "Connection destroyed";
1004   port_->thread()->Post(this, MSG_DELETE);
1005 }
1006 
FailAndDestroy()1007 void Connection::FailAndDestroy() {
1008   set_state(Connection::STATE_FAILED);
1009   Destroy();
1010 }
1011 
PrintPingsSinceLastResponse(std::string * s,size_t max)1012 void Connection::PrintPingsSinceLastResponse(std::string* s, size_t max) {
1013   std::ostringstream oss;
1014   oss << std::boolalpha;
1015   if (pings_since_last_response_.size() > max) {
1016     for (size_t i = 0; i < max; i++) {
1017       const SentPing& ping = pings_since_last_response_[i];
1018       oss << rtc::hex_encode(ping.id) << " ";
1019     }
1020     oss << "... " << (pings_since_last_response_.size() - max) << " more";
1021   } else {
1022     for (const SentPing& ping : pings_since_last_response_) {
1023       oss << rtc::hex_encode(ping.id) << " ";
1024     }
1025   }
1026   *s = oss.str();
1027 }
1028 
UpdateState(uint32_t now)1029 void Connection::UpdateState(uint32_t now) {
1030   uint32_t rtt = ConservativeRTTEstimate(rtt_);
1031 
1032   if (LOG_CHECK_LEVEL(LS_VERBOSE)) {
1033     std::string pings;
1034     PrintPingsSinceLastResponse(&pings, 5);
1035     LOG_J(LS_VERBOSE, this) << "UpdateState()"
1036                             << ", ms since last received response="
1037                             << now - last_ping_response_received_
1038                             << ", ms since last received data="
1039                             << now - last_data_received_
1040                             << ", rtt=" << rtt
1041                             << ", pings_since_last_response=" << pings;
1042   }
1043 
1044   // Check the writable state.  (The order of these checks is important.)
1045   //
1046   // Before becoming unwritable, we allow for a fixed number of pings to fail
1047   // (i.e., receive no response).  We also have to give the response time to
1048   // get back, so we include a conservative estimate of this.
1049   //
1050   // Before timing out writability, we give a fixed amount of time.  This is to
1051   // allow for changes in network conditions.
1052 
1053   if ((write_state_ == STATE_WRITABLE) &&
1054       TooManyFailures(pings_since_last_response_,
1055                       CONNECTION_WRITE_CONNECT_FAILURES,
1056                       rtt,
1057                       now) &&
1058       TooLongWithoutResponse(pings_since_last_response_,
1059                              CONNECTION_WRITE_CONNECT_TIMEOUT,
1060                              now)) {
1061     uint32_t max_pings = CONNECTION_WRITE_CONNECT_FAILURES;
1062     LOG_J(LS_INFO, this) << "Unwritable after " << max_pings
1063                          << " ping failures and "
1064                          << now - pings_since_last_response_[0].sent_time
1065                          << " ms without a response,"
1066                          << " ms since last received ping="
1067                          << now - last_ping_received_
1068                          << " ms since last received data="
1069                          << now - last_data_received_
1070                          << " rtt=" << rtt;
1071     set_write_state(STATE_WRITE_UNRELIABLE);
1072   }
1073   if ((write_state_ == STATE_WRITE_UNRELIABLE ||
1074        write_state_ == STATE_WRITE_INIT) &&
1075       TooLongWithoutResponse(pings_since_last_response_,
1076                              CONNECTION_WRITE_TIMEOUT,
1077                              now)) {
1078     LOG_J(LS_INFO, this) << "Timed out after "
1079                          << now - pings_since_last_response_[0].sent_time
1080                          << " ms without a response"
1081                          << ", rtt=" << rtt;
1082     set_write_state(STATE_WRITE_TIMEOUT);
1083   }
1084 
1085   // Check the receiving state.
1086   uint32_t last_recv_time = last_received();
1087   bool receiving = now <= last_recv_time + receiving_timeout_;
1088   set_receiving(receiving);
1089   if (dead(now)) {
1090     Destroy();
1091   }
1092 }
1093 
Ping(uint32_t now)1094 void Connection::Ping(uint32_t now) {
1095   last_ping_sent_ = now;
1096   ConnectionRequest *req = new ConnectionRequest(this);
1097   pings_since_last_response_.push_back(SentPing(req->id(), now));
1098   LOG_J(LS_VERBOSE, this) << "Sending STUN ping "
1099                           << ", id=" << rtc::hex_encode(req->id());
1100   requests_.Send(req);
1101   state_ = STATE_INPROGRESS;
1102 }
1103 
ReceivedPing()1104 void Connection::ReceivedPing() {
1105   set_receiving(true);
1106   last_ping_received_ = rtc::Time();
1107 }
1108 
ReceivedPingResponse()1109 void Connection::ReceivedPingResponse() {
1110   // We've already validated that this is a STUN binding response with
1111   // the correct local and remote username for this connection.
1112   // So if we're not already, become writable. We may be bringing a pruned
1113   // connection back to life, but if we don't really want it, we can always
1114   // prune it again.
1115   set_receiving(true);
1116   set_write_state(STATE_WRITABLE);
1117   set_state(STATE_SUCCEEDED);
1118   pings_since_last_response_.clear();
1119   last_ping_response_received_ = rtc::Time();
1120 }
1121 
dead(uint32_t now) const1122 bool Connection::dead(uint32_t now) const {
1123   if (last_received() > 0) {
1124     // If it has ever received anything, we keep it alive until it hasn't
1125     // received anything for DEAD_CONNECTION_RECEIVE_TIMEOUT. This covers the
1126     // normal case of a successfully used connection that stops working. This
1127     // also allows a remote peer to continue pinging over a locally inactive
1128     // (pruned) connection.
1129     return (now > (last_received() + DEAD_CONNECTION_RECEIVE_TIMEOUT));
1130   }
1131 
1132   if (active()) {
1133     // If it has never received anything, keep it alive as long as it is
1134     // actively pinging and not pruned. Otherwise, the connection might be
1135     // deleted before it has a chance to ping. This is the normal case for a
1136     // new connection that is pinging but hasn't received anything yet.
1137     return false;
1138   }
1139 
1140   // If it has never received anything and is not actively pinging (pruned), we
1141   // keep it around for at least MIN_CONNECTION_LIFETIME to prevent connections
1142   // from being pruned too quickly during a network change event when two
1143   // networks would be up simultaneously but only for a brief period.
1144   return now > (time_created_ms_ + MIN_CONNECTION_LIFETIME);
1145 }
1146 
ToDebugId() const1147 std::string Connection::ToDebugId() const {
1148   std::stringstream ss;
1149   ss << std::hex << this;
1150   return ss.str();
1151 }
1152 
ToString() const1153 std::string Connection::ToString() const {
1154   const char CONNECT_STATE_ABBREV[2] = {
1155     '-',  // not connected (false)
1156     'C',  // connected (true)
1157   };
1158   const char RECEIVE_STATE_ABBREV[2] = {
1159     '-',  // not receiving (false)
1160     'R',  // receiving (true)
1161   };
1162   const char WRITE_STATE_ABBREV[4] = {
1163     'W',  // STATE_WRITABLE
1164     'w',  // STATE_WRITE_UNRELIABLE
1165     '-',  // STATE_WRITE_INIT
1166     'x',  // STATE_WRITE_TIMEOUT
1167   };
1168   const std::string ICESTATE[4] = {
1169     "W",  // STATE_WAITING
1170     "I",  // STATE_INPROGRESS
1171     "S",  // STATE_SUCCEEDED
1172     "F"   // STATE_FAILED
1173   };
1174   const Candidate& local = local_candidate();
1175   const Candidate& remote = remote_candidate();
1176   std::stringstream ss;
1177   ss << "Conn[" << ToDebugId()
1178      << ":" << port_->content_name()
1179      << ":" << local.id() << ":" << local.component()
1180      << ":" << local.generation()
1181      << ":" << local.type() << ":" << local.protocol()
1182      << ":" << local.address().ToSensitiveString()
1183      << "->" << remote.id() << ":" << remote.component()
1184      << ":" << remote.priority()
1185      << ":" << remote.type() << ":"
1186      << remote.protocol() << ":" << remote.address().ToSensitiveString() << "|"
1187      << CONNECT_STATE_ABBREV[connected()]
1188      << RECEIVE_STATE_ABBREV[receiving()]
1189      << WRITE_STATE_ABBREV[write_state()]
1190      << ICESTATE[state()] << "|"
1191      << priority() << "|";
1192   if (rtt_ < DEFAULT_RTT) {
1193     ss << rtt_ << "]";
1194   } else {
1195     ss << "-]";
1196   }
1197   return ss.str();
1198 }
1199 
ToSensitiveString() const1200 std::string Connection::ToSensitiveString() const {
1201   return ToString();
1202 }
1203 
OnConnectionRequestResponse(ConnectionRequest * request,StunMessage * response)1204 void Connection::OnConnectionRequestResponse(ConnectionRequest* request,
1205                                              StunMessage* response) {
1206   // Log at LS_INFO if we receive a ping response on an unwritable
1207   // connection.
1208   rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1209 
1210   uint32_t rtt = request->Elapsed();
1211 
1212   ReceivedPingResponse();
1213 
1214   if (LOG_CHECK_LEVEL_V(sev)) {
1215     bool use_candidate = (
1216         response->GetByteString(STUN_ATTR_USE_CANDIDATE) != nullptr);
1217     std::string pings;
1218     PrintPingsSinceLastResponse(&pings, 5);
1219     LOG_JV(sev, this) << "Received STUN ping response"
1220                       << ", id=" << rtc::hex_encode(request->id())
1221                       << ", code=0"  // Makes logging easier to parse.
1222                       << ", rtt=" << rtt
1223                       << ", use_candidate=" << use_candidate
1224                       << ", pings_since_last_response=" << pings;
1225   }
1226 
1227   rtt_ = (RTT_RATIO * rtt_ + rtt) / (RTT_RATIO + 1);
1228 
1229   MaybeAddPrflxCandidate(request, response);
1230 }
1231 
OnConnectionRequestErrorResponse(ConnectionRequest * request,StunMessage * response)1232 void Connection::OnConnectionRequestErrorResponse(ConnectionRequest* request,
1233                                                   StunMessage* response) {
1234   const StunErrorCodeAttribute* error_attr = response->GetErrorCode();
1235   int error_code = STUN_ERROR_GLOBAL_FAILURE;
1236   if (error_attr) {
1237     error_code = error_attr->code();
1238   }
1239 
1240   LOG_J(LS_INFO, this) << "Received STUN error response"
1241                        << " id=" << rtc::hex_encode(request->id())
1242                        << " code=" << error_code
1243                        << " rtt=" << request->Elapsed();
1244 
1245   if (error_code == STUN_ERROR_UNKNOWN_ATTRIBUTE ||
1246       error_code == STUN_ERROR_SERVER_ERROR ||
1247       error_code == STUN_ERROR_UNAUTHORIZED) {
1248     // Recoverable error, retry
1249   } else if (error_code == STUN_ERROR_STALE_CREDENTIALS) {
1250     // Race failure, retry
1251   } else if (error_code == STUN_ERROR_ROLE_CONFLICT) {
1252     HandleRoleConflictFromPeer();
1253   } else {
1254     // This is not a valid connection.
1255     LOG_J(LS_ERROR, this) << "Received STUN error response, code="
1256                           << error_code << "; killing connection";
1257     FailAndDestroy();
1258   }
1259 }
1260 
OnConnectionRequestTimeout(ConnectionRequest * request)1261 void Connection::OnConnectionRequestTimeout(ConnectionRequest* request) {
1262   // Log at LS_INFO if we miss a ping on a writable connection.
1263   rtc::LoggingSeverity sev = writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1264   LOG_JV(sev, this) << "Timing-out STUN ping "
1265                     << rtc::hex_encode(request->id())
1266                     << " after " << request->Elapsed() << " ms";
1267 }
1268 
OnConnectionRequestSent(ConnectionRequest * request)1269 void Connection::OnConnectionRequestSent(ConnectionRequest* request) {
1270   // Log at LS_INFO if we send a ping on an unwritable connection.
1271   rtc::LoggingSeverity sev = !writable() ? rtc::LS_INFO : rtc::LS_VERBOSE;
1272   bool use_candidate = use_candidate_attr();
1273   LOG_JV(sev, this) << "Sent STUN ping"
1274                     << ", id=" << rtc::hex_encode(request->id())
1275                     << ", use_candidate=" << use_candidate;
1276 }
1277 
HandleRoleConflictFromPeer()1278 void Connection::HandleRoleConflictFromPeer() {
1279   port_->SignalRoleConflict(port_);
1280 }
1281 
MaybeSetRemoteIceCredentials(const std::string & ice_ufrag,const std::string & ice_pwd)1282 void Connection::MaybeSetRemoteIceCredentials(const std::string& ice_ufrag,
1283                                               const std::string& ice_pwd) {
1284   if (remote_candidate_.username() == ice_ufrag &&
1285       remote_candidate_.password().empty()) {
1286     remote_candidate_.set_password(ice_pwd);
1287   }
1288 }
1289 
MaybeUpdatePeerReflexiveCandidate(const Candidate & new_candidate)1290 void Connection::MaybeUpdatePeerReflexiveCandidate(
1291     const Candidate& new_candidate) {
1292   if (remote_candidate_.type() == PRFLX_PORT_TYPE &&
1293       new_candidate.type() != PRFLX_PORT_TYPE &&
1294       remote_candidate_.protocol() == new_candidate.protocol() &&
1295       remote_candidate_.address() == new_candidate.address() &&
1296       remote_candidate_.username() == new_candidate.username() &&
1297       remote_candidate_.password() == new_candidate.password() &&
1298       remote_candidate_.generation() == new_candidate.generation()) {
1299     remote_candidate_ = new_candidate;
1300   }
1301 }
1302 
OnMessage(rtc::Message * pmsg)1303 void Connection::OnMessage(rtc::Message *pmsg) {
1304   ASSERT(pmsg->message_id == MSG_DELETE);
1305   LOG_J(LS_INFO, this) << "Connection deleted";
1306   SignalDestroyed(this);
1307   delete this;
1308 }
1309 
last_received() const1310 uint32_t Connection::last_received() const {
1311   return std::max(last_data_received_,
1312              std::max(last_ping_received_, last_ping_response_received_));
1313 }
1314 
recv_bytes_second()1315 size_t Connection::recv_bytes_second() {
1316   return round(recv_rate_tracker_.ComputeRate());
1317 }
1318 
recv_total_bytes()1319 size_t Connection::recv_total_bytes() {
1320   return recv_rate_tracker_.TotalSampleCount();
1321 }
1322 
sent_bytes_second()1323 size_t Connection::sent_bytes_second() {
1324   return round(send_rate_tracker_.ComputeRate());
1325 }
1326 
sent_total_bytes()1327 size_t Connection::sent_total_bytes() {
1328   return send_rate_tracker_.TotalSampleCount();
1329 }
1330 
sent_discarded_packets()1331 size_t Connection::sent_discarded_packets() {
1332   return sent_packets_discarded_;
1333 }
1334 
sent_total_packets()1335 size_t Connection::sent_total_packets() {
1336   return sent_packets_total_;
1337 }
1338 
MaybeAddPrflxCandidate(ConnectionRequest * request,StunMessage * response)1339 void Connection::MaybeAddPrflxCandidate(ConnectionRequest* request,
1340                                         StunMessage* response) {
1341   // RFC 5245
1342   // The agent checks the mapped address from the STUN response.  If the
1343   // transport address does not match any of the local candidates that the
1344   // agent knows about, the mapped address represents a new candidate -- a
1345   // peer reflexive candidate.
1346   const StunAddressAttribute* addr =
1347       response->GetAddress(STUN_ATTR_XOR_MAPPED_ADDRESS);
1348   if (!addr) {
1349     LOG(LS_WARNING) << "Connection::OnConnectionRequestResponse - "
1350                     << "No MAPPED-ADDRESS or XOR-MAPPED-ADDRESS found in the "
1351                     << "stun response message";
1352     return;
1353   }
1354 
1355   bool known_addr = false;
1356   for (size_t i = 0; i < port_->Candidates().size(); ++i) {
1357     if (port_->Candidates()[i].address() == addr->GetAddress()) {
1358       known_addr = true;
1359       break;
1360     }
1361   }
1362   if (known_addr) {
1363     return;
1364   }
1365 
1366   // RFC 5245
1367   // Its priority is set equal to the value of the PRIORITY attribute
1368   // in the Binding request.
1369   const StunUInt32Attribute* priority_attr =
1370       request->msg()->GetUInt32(STUN_ATTR_PRIORITY);
1371   if (!priority_attr) {
1372     LOG(LS_WARNING) << "Connection::OnConnectionRequestResponse - "
1373                     << "No STUN_ATTR_PRIORITY found in the "
1374                     << "stun response message";
1375     return;
1376   }
1377   const uint32_t priority = priority_attr->value();
1378   std::string id = rtc::CreateRandomString(8);
1379 
1380   Candidate new_local_candidate;
1381   new_local_candidate.set_id(id);
1382   new_local_candidate.set_component(local_candidate().component());
1383   new_local_candidate.set_type(PRFLX_PORT_TYPE);
1384   new_local_candidate.set_protocol(local_candidate().protocol());
1385   new_local_candidate.set_address(addr->GetAddress());
1386   new_local_candidate.set_priority(priority);
1387   new_local_candidate.set_username(local_candidate().username());
1388   new_local_candidate.set_password(local_candidate().password());
1389   new_local_candidate.set_network_name(local_candidate().network_name());
1390   new_local_candidate.set_network_type(local_candidate().network_type());
1391   new_local_candidate.set_related_address(local_candidate().address());
1392   new_local_candidate.set_foundation(
1393       ComputeFoundation(PRFLX_PORT_TYPE, local_candidate().protocol(),
1394                         local_candidate().address()));
1395 
1396   // Change the local candidate of this Connection to the new prflx candidate.
1397   local_candidate_index_ = port_->AddPrflxCandidate(new_local_candidate);
1398 
1399   // SignalStateChange to force a re-sort in P2PTransportChannel as this
1400   // Connection's local candidate has changed.
1401   SignalStateChange(this);
1402 }
1403 
ProxyConnection(Port * port,size_t index,const Candidate & remote_candidate)1404 ProxyConnection::ProxyConnection(Port* port,
1405                                  size_t index,
1406                                  const Candidate& remote_candidate)
1407     : Connection(port, index, remote_candidate) {}
1408 
Send(const void * data,size_t size,const rtc::PacketOptions & options)1409 int ProxyConnection::Send(const void* data, size_t size,
1410                           const rtc::PacketOptions& options) {
1411   if (write_state_ == STATE_WRITE_INIT || write_state_ == STATE_WRITE_TIMEOUT) {
1412     error_ = EWOULDBLOCK;
1413     return SOCKET_ERROR;
1414   }
1415   sent_packets_total_++;
1416   int sent = port_->SendTo(data, size, remote_candidate_.address(),
1417                            options, true);
1418   if (sent <= 0) {
1419     ASSERT(sent < 0);
1420     error_ = port_->GetError();
1421     sent_packets_discarded_++;
1422   } else {
1423     send_rate_tracker_.AddSamples(sent);
1424   }
1425   return sent;
1426 }
1427 
1428 }  // namespace cricket
1429