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