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/base/asyncpacketsocket.h"
     29 #include "talk/base/helpers.h"
     30 #include "talk/base/logging.h"
     31 #include "talk/p2p/base/relayport.h"
     32 
     33 namespace cricket {
     34 
     35 static const uint32 kMessageConnectTimeout = 1;
     36 static const int kKeepAliveDelay           = 10 * 60 * 1000;
     37 static const int kRetryTimeout             = 50 * 1000;  // ICE says 50 secs
     38 // How long to wait for a socket to connect to remote host in milliseconds
     39 // before trying another connection.
     40 static const int kSoftConnectTimeoutMs     = 3 * 1000;
     41 
     42 // Handles a connection to one address/port/protocol combination for a
     43 // particular RelayEntry.
     44 class RelayConnection : public sigslot::has_slots<> {
     45  public:
     46   RelayConnection(const ProtocolAddress* protocol_address,
     47                   talk_base::AsyncPacketSocket* socket,
     48                   talk_base::Thread* thread);
     49   ~RelayConnection();
     50   talk_base::AsyncPacketSocket* socket() const { return socket_; }
     51 
     52   const ProtocolAddress* protocol_address() {
     53     return protocol_address_;
     54   }
     55 
     56   talk_base::SocketAddress GetAddress() const {
     57     return protocol_address_->address;
     58   }
     59 
     60   ProtocolType GetProtocol() const {
     61     return protocol_address_->proto;
     62   }
     63 
     64   int SetSocketOption(talk_base::Socket::Option opt, int value);
     65 
     66   // Validates a response to a STUN allocate request.
     67   bool CheckResponse(StunMessage* msg);
     68 
     69   // Sends data to the relay server.
     70   int Send(const void* pv, size_t cb);
     71 
     72   // Sends a STUN allocate request message to the relay server.
     73   void SendAllocateRequest(RelayEntry* entry, int delay);
     74 
     75   // Return the latest error generated by the socket.
     76   int GetError() { return socket_->GetError(); }
     77 
     78   // Called on behalf of a StunRequest to write data to the socket.  This is
     79   // already STUN intended for the server, so no wrapping is necessary.
     80   void OnSendPacket(const void* data, size_t size, StunRequest* req);
     81 
     82  private:
     83   talk_base::AsyncPacketSocket* socket_;
     84   const ProtocolAddress* protocol_address_;
     85   StunRequestManager *request_manager_;
     86 };
     87 
     88 // Manages a number of connections to the relayserver, one for each
     89 // available protocol. We aim to use each connection for only a
     90 // specific destination address so that we can avoid wrapping every
     91 // packet in a STUN send / data indication.
     92 class RelayEntry : public talk_base::MessageHandler,
     93                    public sigslot::has_slots<> {
     94  public:
     95   RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr);
     96   ~RelayEntry();
     97 
     98   RelayPort* port() { return port_; }
     99 
    100   const talk_base::SocketAddress& address() const { return ext_addr_; }
    101   void set_address(const talk_base::SocketAddress& addr) { ext_addr_ = addr; }
    102 
    103   bool connected() const { return connected_; }
    104   bool locked() const { return locked_; }
    105 
    106   // Returns the last error on the socket of this entry.
    107   int GetError();
    108 
    109   // Returns the most preferred connection of the given
    110   // ones. Connections are rated based on protocol in the order of:
    111   // UDP, TCP and SSLTCP, where UDP is the most preferred protocol
    112   static RelayConnection* GetBestConnection(RelayConnection* conn1,
    113                                             RelayConnection* conn2);
    114 
    115   // Sends the STUN requests to the server to initiate this connection.
    116   void Connect();
    117 
    118   // Called when this entry becomes connected.  The address given is the one
    119   // exposed to the outside world on the relay server.
    120   void OnConnect(const talk_base::SocketAddress& mapped_addr,
    121                  RelayConnection* socket);
    122 
    123   // Sends a packet to the given destination address using the socket of this
    124   // entry.  This will wrap the packet in STUN if necessary.
    125   int SendTo(const void* data, size_t size,
    126     const talk_base::SocketAddress& addr);
    127 
    128   // Schedules a keep-alive allocate request.
    129   void ScheduleKeepAlive();
    130 
    131   void SetServerIndex(size_t sindex) { server_index_ = sindex; }
    132 
    133   // Sets this option on the socket of each connection.
    134   int SetSocketOption(talk_base::Socket::Option opt, int value);
    135 
    136   size_t ServerIndex() const { return server_index_; }
    137 
    138   // Try a different server address
    139   void HandleConnectFailure(talk_base::AsyncPacketSocket* socket);
    140 
    141   // Implementation of the MessageHandler Interface.
    142   virtual void OnMessage(talk_base::Message *pmsg);
    143 
    144  private:
    145   RelayPort* port_;
    146   talk_base::SocketAddress ext_addr_;
    147   size_t server_index_;
    148   bool connected_;
    149   bool locked_;
    150   RelayConnection* current_connection_;
    151 
    152   // Called when a TCP connection is established or fails
    153   void OnSocketConnect(talk_base::AsyncPacketSocket* socket);
    154   void OnSocketClose(talk_base::AsyncPacketSocket* socket, int error);
    155 
    156   // Called when a packet is received on this socket.
    157   void OnReadPacket(talk_base::AsyncPacketSocket* socket,
    158                     const char* data, size_t size,
    159                     const talk_base::SocketAddress& remote_addr);
    160 
    161   // Sends the given data on the socket to the server with no wrapping.  This
    162   // returns the number of bytes written or -1 if an error occurred.
    163   int SendPacket(const void* data, size_t size);
    164 };
    165 
    166 // Handles an allocate request for a particular RelayEntry.
    167 class AllocateRequest : public StunRequest {
    168  public:
    169   AllocateRequest(RelayEntry* entry, RelayConnection* connection);
    170   virtual ~AllocateRequest() {}
    171 
    172   virtual void Prepare(StunMessage* request);
    173 
    174   virtual int GetNextDelay();
    175 
    176   virtual void OnResponse(StunMessage* response);
    177   virtual void OnErrorResponse(StunMessage* response);
    178   virtual void OnTimeout();
    179 
    180  private:
    181   RelayEntry* entry_;
    182   RelayConnection* connection_;
    183   uint32 start_time_;
    184 };
    185 
    186 const std::string RELAY_PORT_TYPE("relay");
    187 
    188 RelayPort::RelayPort(
    189     talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
    190     talk_base::Network* network, uint32 ip, int min_port, int max_port,
    191     const std::string& username, const std::string& password,
    192     const std::string& magic_cookie)
    193     : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port),
    194       ready_(false),
    195       magic_cookie_(magic_cookie),
    196       error_(0) {
    197   entries_.push_back(
    198       new RelayEntry(this, talk_base::SocketAddress()));
    199 
    200   set_username_fragment(username);
    201   set_password(password);
    202   if (magic_cookie_.size() == 0)
    203     magic_cookie_.append(STUN_MAGIC_COOKIE_VALUE, 4);
    204 }
    205 
    206 RelayPort::~RelayPort() {
    207   for (size_t i = 0; i < entries_.size(); ++i)
    208     delete entries_[i];
    209   thread_->Clear(this);
    210 }
    211 
    212 void RelayPort::AddServerAddress(const ProtocolAddress& addr) {
    213   // Since HTTP proxies usually only allow 443,
    214   // let's up the priority on PROTO_SSLTCP
    215   if (addr.proto == PROTO_SSLTCP &&
    216       (proxy().type == talk_base::PROXY_HTTPS ||
    217        proxy().type == talk_base::PROXY_UNKNOWN)) {
    218     server_addr_.push_front(addr);
    219   } else {
    220     server_addr_.push_back(addr);
    221   }
    222 }
    223 
    224 void RelayPort::AddExternalAddress(const ProtocolAddress& addr) {
    225   std::string proto_name = ProtoToString(addr.proto);
    226   for (std::vector<Candidate>::const_iterator it = candidates().begin();
    227        it != candidates().end(); ++it) {
    228     if ((it->address() == addr.address) && (it->protocol() == proto_name)) {
    229       LOG(INFO) << "Redundant relay address: " << proto_name
    230                 << " @ " << addr.address.ToString();
    231       return;
    232     }
    233   }
    234   AddAddress(addr.address, proto_name, false);
    235 }
    236 
    237 void RelayPort::SetReady() {
    238   if (!ready_) {
    239     ready_ = true;
    240     SignalAddressReady(this);
    241   }
    242 }
    243 
    244 const ProtocolAddress * RelayPort::ServerAddress(size_t index) const {
    245   if (index < server_addr_.size())
    246     return &server_addr_[index];
    247   return NULL;
    248 }
    249 
    250 bool RelayPort::HasMagicCookie(const char* data, size_t size) {
    251   if (size < 24 + magic_cookie_.size()) {
    252     return false;
    253   } else {
    254     return 0 == std::memcmp(data + 24,
    255                             magic_cookie_.c_str(),
    256                             magic_cookie_.size());
    257   }
    258 }
    259 
    260 void RelayPort::PrepareAddress() {
    261   // We initiate a connect on the first entry.  If this completes, it will fill
    262   // in the server address as the address of this port.
    263   ASSERT(entries_.size() == 1);
    264   entries_[0]->Connect();
    265   ready_ = false;
    266 }
    267 
    268 Connection* RelayPort::CreateConnection(const Candidate& address,
    269                                         CandidateOrigin origin) {
    270   // We only create conns to non-udp sockets if they are incoming on this port
    271   if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT)) {
    272     return 0;
    273   }
    274 
    275   // We don't support loopback on relays
    276   if (address.type() == type()) {
    277     return 0;
    278   }
    279 
    280   size_t index = 0;
    281   for (size_t i = 0; i < candidates().size(); ++i) {
    282     const Candidate& local = candidates()[i];
    283     if (local.protocol() == address.protocol()) {
    284       index = i;
    285       break;
    286     }
    287   }
    288 
    289   Connection * conn = new ProxyConnection(this, index, address);
    290   AddConnection(conn);
    291   return conn;
    292 }
    293 
    294 int RelayPort::SendTo(const void* data, size_t size,
    295                       const talk_base::SocketAddress& addr, bool payload) {
    296   // Try to find an entry for this specific address.  Note that the first entry
    297   // created was not given an address initially, so it can be set to the first
    298   // address that comes along.
    299   RelayEntry* entry = 0;
    300 
    301   for (size_t i = 0; i < entries_.size(); ++i) {
    302     if (entries_[i]->address().IsAny() && payload) {
    303       entry = entries_[i];
    304       entry->set_address(addr);
    305       break;
    306     } else if (entries_[i]->address() == addr) {
    307       entry = entries_[i];
    308       break;
    309     }
    310   }
    311 
    312   // If we did not find one, then we make a new one.  This will not be useable
    313   // until it becomes connected, however.
    314   if (!entry && payload) {
    315     entry = new RelayEntry(this, addr);
    316     if (!entries_.empty()) {
    317       entry->SetServerIndex(entries_[0]->ServerIndex());
    318     }
    319     entry->Connect();
    320     entries_.push_back(entry);
    321   }
    322 
    323   // If the entry is connected, then we can send on it (though wrapping may
    324   // still be necessary).  Otherwise, we can't yet use this connection, so we
    325   // default to the first one.
    326   if (!entry || !entry->connected()) {
    327     ASSERT(!entries_.empty());
    328     entry = entries_[0];
    329     if (!entry->connected()) {
    330       error_ = EWOULDBLOCK;
    331       return SOCKET_ERROR;
    332     }
    333   }
    334 
    335   // Send the actual contents to the server using the usual mechanism.
    336   int sent = entry->SendTo(data, size, addr);
    337   if (sent <= 0) {
    338     ASSERT(sent < 0);
    339     error_ = entry->GetError();
    340     return SOCKET_ERROR;
    341   }
    342   // The caller of the function is expecting the number of user data bytes,
    343   // rather than the size of the packet.
    344   return size;
    345 }
    346 
    347 int RelayPort::SetOption(talk_base::Socket::Option opt, int value) {
    348   int result = 0;
    349   for (size_t i = 0; i < entries_.size(); ++i) {
    350     if (entries_[i]->SetSocketOption(opt, value) < 0) {
    351       result = -1;
    352       error_ = entries_[i]->GetError();
    353     }
    354   }
    355   options_.push_back(OptionValue(opt, value));
    356   return result;
    357 }
    358 
    359 int RelayPort::GetError() {
    360   return error_;
    361 }
    362 
    363 void RelayPort::OnReadPacket(
    364     const char* data, size_t size,
    365     const talk_base::SocketAddress& remote_addr) {
    366   if (Connection* conn = GetConnection(remote_addr)) {
    367     conn->OnReadPacket(data, size);
    368   } else {
    369     Port::OnReadPacket(data, size, remote_addr);
    370   }
    371 }
    372 
    373 RelayConnection::RelayConnection(const ProtocolAddress* protocol_address,
    374                                  talk_base::AsyncPacketSocket* socket,
    375                                  talk_base::Thread* thread)
    376     : socket_(socket),
    377       protocol_address_(protocol_address) {
    378   request_manager_ = new StunRequestManager(thread);
    379   request_manager_->SignalSendPacket.connect(this,
    380                                              &RelayConnection::OnSendPacket);
    381 }
    382 
    383 RelayConnection::~RelayConnection() {
    384   delete request_manager_;
    385   delete socket_;
    386 }
    387 
    388 int RelayConnection::SetSocketOption(talk_base::Socket::Option opt,
    389                                      int value) {
    390   if (socket_) {
    391     return socket_->SetOption(opt, value);
    392   }
    393   return 0;
    394 }
    395 
    396 bool RelayConnection::CheckResponse(StunMessage* msg) {
    397   return request_manager_->CheckResponse(msg);
    398 }
    399 
    400 void RelayConnection::OnSendPacket(const void* data, size_t size,
    401                                    StunRequest* req) {
    402   int sent = socket_->SendTo(data, size, GetAddress());
    403   if (sent <= 0) {
    404     LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " << GetAddress() <<
    405         std::strerror(socket_->GetError());
    406     ASSERT(sent < 0);
    407   }
    408 }
    409 
    410 int RelayConnection::Send(const void* pv, size_t cb) {
    411   return socket_->SendTo(pv, cb, GetAddress());
    412 }
    413 
    414 void RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) {
    415   request_manager_->SendDelayed(new AllocateRequest(entry, this), delay);
    416 }
    417 
    418 RelayEntry::RelayEntry(RelayPort* port,
    419                        const talk_base::SocketAddress& ext_addr)
    420     : port_(port), ext_addr_(ext_addr),
    421       server_index_(0), connected_(false), locked_(false),
    422       current_connection_(NULL) {
    423 }
    424 
    425 RelayEntry::~RelayEntry() {
    426   // Remove all RelayConnections and dispose sockets.
    427   delete current_connection_;
    428   current_connection_ = NULL;
    429 }
    430 
    431 void RelayEntry::Connect() {
    432   // If we're already connected, return.
    433   if (connected_)
    434     return;
    435 
    436   // If we've exhausted all options, bail out.
    437   const ProtocolAddress* ra = port()->ServerAddress(server_index_);
    438   if (!ra) {
    439     LOG(LS_WARNING) << "No more relay addresses left to try";
    440     return;
    441   }
    442 
    443   // Remove any previous connection.
    444   if (current_connection_) {
    445     port()->thread()->Dispose(current_connection_);
    446     current_connection_ = NULL;
    447   }
    448 
    449   // Try to set up our new socket.
    450   LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) <<
    451       " @ " << ra->address.ToString();
    452 
    453   talk_base::AsyncPacketSocket* socket = NULL;
    454 
    455   if (ra->proto == PROTO_UDP) {
    456     // UDP sockets are simple.
    457     socket = port_->socket_factory()->CreateUdpSocket(
    458         talk_base::SocketAddress(port_->ip_, 0),
    459         port_->min_port_, port_->max_port_);
    460   } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) {
    461     socket = port_->socket_factory()->CreateClientTcpSocket(
    462         talk_base::SocketAddress(port_->ip_, 0), ra->address,
    463         port_->proxy(), port_->user_agent(), ra->proto == PROTO_SSLTCP);
    464   } else {
    465     LOG(LS_WARNING) << "Unknown protocol (" << ra->proto << ")";
    466   }
    467 
    468   if (!socket) {
    469     LOG(LS_WARNING) << "Socket creation failed";
    470   }
    471 
    472   // If we failed to get a socket, move on to the next protocol.
    473   if (!socket) {
    474     port()->thread()->Post(this, kMessageConnectTimeout);
    475     return;
    476   }
    477 
    478   // Otherwise, create the new connection and configure any socket options.
    479   socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
    480   current_connection_ = new RelayConnection(ra, socket, port()->thread());
    481   for (size_t i = 0; i < port_->options().size(); ++i) {
    482     current_connection_->SetSocketOption(port_->options()[i].first,
    483                                          port_->options()[i].second);
    484   }
    485 
    486   // If we're trying UDP, start binding requests.
    487   // If we're trying TCP, wait for connection with a fixed timeout.
    488   if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) {
    489     socket->SignalClose.connect(this, &RelayEntry::OnSocketClose);
    490     socket->SignalConnect.connect(this, &RelayEntry::OnSocketConnect);
    491     port()->thread()->PostDelayed(kSoftConnectTimeoutMs, this,
    492                                   kMessageConnectTimeout);
    493   } else {
    494     current_connection_->SendAllocateRequest(this, 0);
    495   }
    496 }
    497 
    498 int RelayEntry::GetError() {
    499   if (current_connection_ != NULL) {
    500     return current_connection_->GetError();
    501   }
    502   return 0;
    503 }
    504 
    505 RelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1,
    506                                                RelayConnection* conn2) {
    507   return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2;
    508 }
    509 
    510 void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr,
    511                            RelayConnection* connection) {
    512   // We are connected, notify our parent.
    513   ProtocolType proto = PROTO_UDP;
    514   LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto)
    515             << " @ " << mapped_addr.ToString();
    516   connected_ = true;
    517 
    518   port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
    519   port_->SetReady();
    520 }
    521 
    522 int RelayEntry::SendTo(const void* data, size_t size,
    523                        const talk_base::SocketAddress& addr) {
    524   // If this connection is locked to the address given, then we can send the
    525   // packet with no wrapper.
    526   if (locked_ && (ext_addr_ == addr))
    527     return SendPacket(data, size);
    528 
    529   // Otherwise, we must wrap the given data in a STUN SEND request so that we
    530   // can communicate the destination address to the server.
    531   //
    532   // Note that we do not use a StunRequest here.  This is because there is
    533   // likely no reason to resend this packet. If it is late, we just drop it.
    534   // The next send to this address will try again.
    535 
    536   StunMessage request;
    537   request.SetType(STUN_SEND_REQUEST);
    538   request.SetTransactionID(talk_base::CreateRandomString(16));
    539 
    540   StunByteStringAttribute* magic_cookie_attr =
    541       StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
    542   magic_cookie_attr->CopyBytes(port_->magic_cookie().c_str(),
    543                                port_->magic_cookie().size());
    544   request.AddAttribute(magic_cookie_attr);
    545 
    546   StunByteStringAttribute* username_attr =
    547       StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
    548   username_attr->CopyBytes(port_->username_fragment().c_str(),
    549                            port_->username_fragment().size());
    550   request.AddAttribute(username_attr);
    551 
    552   StunAddressAttribute* addr_attr =
    553       StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
    554   addr_attr->SetFamily(1);
    555   addr_attr->SetIP(addr.ip());
    556   addr_attr->SetPort(addr.port());
    557   request.AddAttribute(addr_attr);
    558 
    559   // Attempt to lock
    560   if (ext_addr_ == addr) {
    561     StunUInt32Attribute* options_attr =
    562       StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
    563     options_attr->SetValue(0x1);
    564     request.AddAttribute(options_attr);
    565   }
    566 
    567   StunByteStringAttribute* data_attr =
    568       StunAttribute::CreateByteString(STUN_ATTR_DATA);
    569   data_attr->CopyBytes(data, size);
    570   request.AddAttribute(data_attr);
    571 
    572   // TODO: compute the HMAC.
    573 
    574   talk_base::ByteBuffer buf;
    575   request.Write(&buf);
    576 
    577   return SendPacket(buf.Data(), buf.Length());
    578 }
    579 
    580 void RelayEntry::ScheduleKeepAlive() {
    581   if (current_connection_) {
    582     current_connection_->SendAllocateRequest(this, kKeepAliveDelay);
    583   }
    584 }
    585 
    586 int RelayEntry::SetSocketOption(talk_base::Socket::Option opt, int value) {
    587   // Set the option on all available sockets.
    588   int socket_error = 0;
    589   if (current_connection_) {
    590     socket_error = current_connection_->SetSocketOption(opt, value);
    591   }
    592   return socket_error;
    593 }
    594 
    595 void RelayEntry::HandleConnectFailure(
    596     talk_base::AsyncPacketSocket* socket) {
    597   // Make sure it's the current connection that has failed, it might
    598   // be an old socked that has not yet been disposed.
    599   if (!socket || socket == current_connection_->socket()) {
    600     if (current_connection_)
    601       port()->SignalConnectFailure(current_connection_->protocol_address());
    602 
    603     // Try to connect to the next server address.
    604     server_index_ += 1;
    605     Connect();
    606   }
    607 }
    608 
    609 void RelayEntry::OnMessage(talk_base::Message *pmsg) {
    610   ASSERT(pmsg->message_id == kMessageConnectTimeout);
    611   if (current_connection_) {
    612     const ProtocolAddress* ra = current_connection_->protocol_address();
    613     LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " <<
    614         ra->address << " timed out";
    615 
    616     // Currently we connect to each server address in sequence. If we
    617     // have more addresses to try, treat this is an error and move on to
    618     // the next address, otherwise give this connection more time and
    619     // await the real timeout.
    620     //
    621     // TODO: Connect to servers in parallel to speed up connect time
    622     // and to avoid giving up too early.
    623     port_->SignalSoftTimeout(ra);
    624     HandleConnectFailure(current_connection_->socket());
    625   } else {
    626     HandleConnectFailure(NULL);
    627   }
    628 }
    629 
    630 void RelayEntry::OnSocketConnect(talk_base::AsyncPacketSocket* socket) {
    631   LOG(INFO) << "relay tcp connected to " <<
    632       socket->GetRemoteAddress().ToString();
    633   if (current_connection_ != NULL) {
    634     current_connection_->SendAllocateRequest(this, 0);
    635   }
    636 }
    637 
    638 void RelayEntry::OnSocketClose(talk_base::AsyncPacketSocket* socket,
    639                                int error) {
    640   PLOG(LERROR, error) << "Relay connection failed: socket closed";
    641   HandleConnectFailure(socket);
    642 }
    643 
    644 void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket,
    645                               const char* data, size_t size,
    646                               const talk_base::SocketAddress& remote_addr) {
    647   // ASSERT(remote_addr == port_->server_addr());
    648   // TODO: are we worried about this?
    649 
    650   if (current_connection_ == NULL || socket != current_connection_->socket()) {
    651     // This packet comes from an unknown address.
    652     LOG(WARNING) << "Dropping packet: unknown address";
    653     return;
    654   }
    655 
    656   // If the magic cookie is not present, then this is an unwrapped packet sent
    657   // by the server,  The actual remote address is the one we recorded.
    658   if (!port_->HasMagicCookie(data, size)) {
    659     if (locked_) {
    660       port_->OnReadPacket(data, size, ext_addr_);
    661     } else {
    662       LOG(WARNING) << "Dropping packet: entry not locked";
    663     }
    664     return;
    665   }
    666 
    667   talk_base::ByteBuffer buf(data, size);
    668   StunMessage msg;
    669   if (!msg.Read(&buf)) {
    670     LOG(INFO) << "Incoming packet was not STUN";
    671     return;
    672   }
    673 
    674   // The incoming packet should be a STUN ALLOCATE response, SEND response, or
    675   // DATA indication.
    676   if (current_connection_->CheckResponse(&msg)) {
    677     return;
    678   } else if (msg.type() == STUN_SEND_RESPONSE) {
    679     if (const StunUInt32Attribute* options_attr =
    680         msg.GetUInt32(STUN_ATTR_OPTIONS)) {
    681       if (options_attr->value() & 0x1) {
    682         locked_ = true;
    683       }
    684     }
    685     return;
    686   } else if (msg.type() != STUN_DATA_INDICATION) {
    687     LOG(INFO) << "Received BAD stun type from server: " << msg.type();
    688     return;
    689   }
    690 
    691   // This must be a data indication.
    692 
    693   const StunAddressAttribute* addr_attr =
    694       msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
    695   if (!addr_attr) {
    696     LOG(INFO) << "Data indication has no source address";
    697     return;
    698   } else if (addr_attr->family() != 1) {
    699     LOG(INFO) << "Source address has bad family";
    700     return;
    701   }
    702 
    703   talk_base::SocketAddress remote_addr2(addr_attr->ip(), addr_attr->port());
    704 
    705   const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
    706   if (!data_attr) {
    707     LOG(INFO) << "Data indication has no data";
    708     return;
    709   }
    710 
    711   // Process the actual data and remote address in the normal manner.
    712   port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2);
    713 }
    714 
    715 int RelayEntry::SendPacket(const void* data, size_t size) {
    716   int sent = 0;
    717   if (current_connection_) {
    718     // We are connected, no need to send packets anywere else than to
    719     // the current connection.
    720     sent = current_connection_->Send(data, size);
    721   }
    722   return sent;
    723 }
    724 
    725 AllocateRequest::AllocateRequest(RelayEntry* entry,
    726                                  RelayConnection* connection) :
    727     entry_(entry), connection_(connection) {
    728   start_time_ = talk_base::Time();
    729 }
    730 
    731 void AllocateRequest::Prepare(StunMessage* request) {
    732   request->SetType(STUN_ALLOCATE_REQUEST);
    733 
    734   StunByteStringAttribute* magic_cookie_attr =
    735       StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
    736   magic_cookie_attr->CopyBytes(
    737       entry_->port()->magic_cookie().c_str(),
    738       entry_->port()->magic_cookie().size());
    739   request->AddAttribute(magic_cookie_attr);
    740 
    741   StunByteStringAttribute* username_attr =
    742       StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
    743   username_attr->CopyBytes(
    744       entry_->port()->username_fragment().c_str(),
    745       entry_->port()->username_fragment().size());
    746   request->AddAttribute(username_attr);
    747 }
    748 
    749 int AllocateRequest::GetNextDelay() {
    750   int delay = 100 * talk_base::_max(1 << count_, 2);
    751   count_ += 1;
    752   if (count_ == 5)
    753     timeout_ = true;
    754   return delay;
    755 }
    756 
    757 void AllocateRequest::OnResponse(StunMessage* response) {
    758   const StunAddressAttribute* addr_attr =
    759       response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
    760   if (!addr_attr) {
    761     LOG(INFO) << "Allocate response missing mapped address.";
    762   } else if (addr_attr->family() != 1) {
    763     LOG(INFO) << "Mapped address has bad family";
    764   } else {
    765     talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
    766     entry_->OnConnect(addr, connection_);
    767   }
    768 
    769   // We will do a keep-alive regardless of whether this request suceeds.
    770   // This should have almost no impact on network usage.
    771   entry_->ScheduleKeepAlive();
    772 }
    773 
    774 void AllocateRequest::OnErrorResponse(StunMessage* response) {
    775   const StunErrorCodeAttribute* attr = response->GetErrorCode();
    776   if (!attr) {
    777     LOG(INFO) << "Bad allocate response error code";
    778   } else {
    779     LOG(INFO) << "Allocate error response:"
    780               << " code=" << static_cast<int>(attr->error_code())
    781               << " reason='" << attr->reason() << "'";
    782   }
    783 
    784   if (talk_base::TimeSince(start_time_) <= kRetryTimeout)
    785     entry_->ScheduleKeepAlive();
    786 }
    787 
    788 void AllocateRequest::OnTimeout() {
    789   LOG(INFO) << "Allocate request timed out";
    790   entry_->HandleConnectFailure(connection_->socket());
    791 }
    792 
    793 }  // namespace cricket
    794