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