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