10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/*
20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle
30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2004--2005, Google Inc.
40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without
60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met:
70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer.
100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     this list of conditions and the following disclaimer in the documentation
120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     and/or other materials provided with the distribution.
130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *  3. The name of the author may not be used to endorse or promote products
140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *     derived from this software without specific prior written permission.
150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *
160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */
270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
28cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/p2p/base/relayport.h"
292a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/asyncpacketsocket.h"
302a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/helpers.h"
312a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h"
320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket {
340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const uint32 kMessageConnectTimeout = 1;
360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kKeepAliveDelay           = 10 * 60 * 1000;
370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kRetryTimeout             = 50 * 1000;  // ICE says 50 secs
380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// How long to wait for a socket to connect to remote host in milliseconds
390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// before trying another connection.
400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kSoftConnectTimeoutMs     = 3 * 1000;
410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Handles a connection to one address/port/protocol combination for a
430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// particular RelayEntry.
440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass RelayConnection : public sigslot::has_slots<> {
450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayConnection(const ProtocolAddress* protocol_address,
472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                  rtc::AsyncPacketSocket* socket,
482a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                  rtc::Thread* thread);
490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~RelayConnection();
502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::AsyncPacketSocket* socket() const { return socket_; }
510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const ProtocolAddress* protocol_address() {
530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return protocol_address_;
540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
562a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SocketAddress GetAddress() const {
570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return protocol_address_->address;
580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ProtocolType GetProtocol() const {
610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return protocol_address_->proto;
620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
642a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int SetSocketOption(rtc::Socket::Option opt, int value);
650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Validates a response to a STUN allocate request.
670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool CheckResponse(StunMessage* msg);
680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sends data to the relay server.
702a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int Send(const void* pv, size_t cb, const rtc::PacketOptions& options);
710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sends a STUN allocate request message to the relay server.
730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void SendAllocateRequest(RelayEntry* entry, int delay);
740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Return the latest error generated by the socket.
760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int GetError() { return socket_->GetError(); }
770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Called on behalf of a StunRequest to write data to the socket.  This is
790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // already STUN intended for the server, so no wrapping is necessary.
800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void OnSendPacket(const void* data, size_t size, StunRequest* req);
810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
832a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::AsyncPacketSocket* socket_;
840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const ProtocolAddress* protocol_address_;
850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunRequestManager *request_manager_;
860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Manages a number of connections to the relayserver, one for each
890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// available protocol. We aim to use each connection for only a
900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// specific destination address so that we can avoid wrapping every
910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// packet in a STUN send / data indication.
922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgclass RelayEntry : public rtc::MessageHandler,
930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                   public sigslot::has_slots<> {
940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
952a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  RelayEntry(RelayPort* port, const rtc::SocketAddress& ext_addr);
960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ~RelayEntry();
970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayPort* port() { return port_; }
990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  const rtc::SocketAddress& address() const { return ext_addr_; }
1012a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void set_address(const rtc::SocketAddress& addr) { ext_addr_ = addr; }
1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool connected() const { return connected_; }
1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool locked() const { return locked_; }
1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Returns the last error on the socket of this entry.
1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int GetError();
1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Returns the most preferred connection of the given
1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ones. Connections are rated based on protocol in the order of:
1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // UDP, TCP and SSLTCP, where UDP is the most preferred protocol
1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  static RelayConnection* GetBestConnection(RelayConnection* conn1,
1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                            RelayConnection* conn2);
1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sends the STUN requests to the server to initiate this connection.
1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void Connect();
1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Called when this entry becomes connected.  The address given is the one
1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // exposed to the outside world on the relay server.
1202a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void OnConnect(const rtc::SocketAddress& mapped_addr,
1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                 RelayConnection* socket);
1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sends a packet to the given destination address using the socket of this
1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // entry.  This will wrap the packet in STUN if necessary.
1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int SendTo(const void* data, size_t size,
1262a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org             const rtc::SocketAddress& addr,
1272a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org             const rtc::PacketOptions& options);
1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Schedules a keep-alive allocate request.
1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void ScheduleKeepAlive();
1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  void SetServerIndex(size_t sindex) { server_index_ = sindex; }
1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sets this option on the socket of each connection.
1352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int SetSocketOption(rtc::Socket::Option opt, int value);
1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t ServerIndex() const { return server_index_; }
1380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Try a different server address
1402a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void HandleConnectFailure(rtc::AsyncPacketSocket* socket);
1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Implementation of the MessageHandler Interface.
1432a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  virtual void OnMessage(rtc::Message *pmsg);
1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayPort* port_;
1472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SocketAddress ext_addr_;
1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t server_index_;
1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool connected_;
1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  bool locked_;
1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayConnection* current_connection_;
1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Called when a TCP connection is established or fails
1542a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void OnSocketConnect(rtc::AsyncPacketSocket* socket);
1552a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void OnSocketClose(rtc::AsyncPacketSocket* socket, int error);
1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Called when a packet is received on this socket.
158f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org  void OnReadPacket(
1592a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::AsyncPacketSocket* socket,
160f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    const char* data, size_t size,
1612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::SocketAddress& remote_addr,
1622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time);
1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Called when the socket is currently able to send.
1642a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  void OnReadyToSend(rtc::AsyncPacketSocket* socket);
1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Sends the given data on the socket to the server with no wrapping.  This
1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // returns the number of bytes written or -1 if an error occurred.
168391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org  int SendPacket(const void* data, size_t size,
1692a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                 const rtc::PacketOptions& options);
1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Handles an allocate request for a particular RelayEntry.
1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgclass AllocateRequest : public StunRequest {
1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org public:
1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AllocateRequest(RelayEntry* entry, RelayConnection* connection);
1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual ~AllocateRequest() {}
1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void Prepare(StunMessage* request);
1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual int GetNextDelay();
1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void OnResponse(StunMessage* response);
1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void OnErrorResponse(StunMessage* response);
1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  virtual void OnTimeout();
1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org private:
1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayEntry* entry_;
1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayConnection* connection_;
1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  uint32 start_time_;
1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org};
1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayPort::RelayPort(
1932a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Thread* thread, rtc::PacketSocketFactory* factory,
1942a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::Network* network, const rtc::IPAddress& ip,
1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int min_port, int max_port, const std::string& username,
1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const std::string& password)
1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port,
1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org           username, password),
1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      ready_(false),
2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      error_(0) {
2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  entries_.push_back(
2022a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      new RelayEntry(this, rtc::SocketAddress()));
2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: set local preference value for TCP based candidates.
2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayPort::~RelayPort() {
2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < entries_.size(); ++i)
2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    delete entries_[i];
2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  thread()->Clear(this);
2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayPort::AddServerAddress(const ProtocolAddress& addr) {
2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Since HTTP proxies usually only allow 443,
2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // let's up the priority on PROTO_SSLTCP
2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (addr.proto == PROTO_SSLTCP &&
2162a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      (proxy().type == rtc::PROXY_HTTPS ||
2172a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org       proxy().type == rtc::PROXY_UNKNOWN)) {
2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    server_addr_.push_front(addr);
2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    server_addr_.push_back(addr);
2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayPort::AddExternalAddress(const ProtocolAddress& addr) {
2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::string proto_name = ProtoToString(addr.proto);
2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (std::vector<ProtocolAddress>::iterator it = external_addr_.begin();
2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org       it != external_addr_.end(); ++it) {
2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if ((it->address == addr.address) && (it->proto == addr.proto)) {
2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(INFO) << "Redundant relay address: " << proto_name
2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                << " @ " << addr.address.ToSensitiveString();
2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return;
2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  external_addr_.push_back(addr);
2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayPort::SetReady() {
2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ready_) {
2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    std::vector<ProtocolAddress>::iterator iter;
2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    for (iter = external_addr_.begin();
2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org         iter != external_addr_.end(); ++iter) {
2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      std::string proto_name = ProtoToString(iter->proto);
243afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // In case of Gturn, related address is set to null socket address.
244afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // This is due to as mapped address stun attribute is used for allocated
245afaf4d10603cf012a13d43a62fbc43c0757ec3b9buildbot@webrtc.org      // address.
2462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org      AddAddress(iter->address, iter->address, rtc::SocketAddress(),
24758c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org                 proto_name, "", RELAY_PORT_TYPE,
24858c89b128d6e4dbe00a9a18bb3029f63bd43ce6dmallinath@webrtc.org                 ICE_TYPE_PREFERENCE_RELAY, 0, false);
2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ready_ = true;
2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    SignalPortComplete(this);
2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst ProtocolAddress * RelayPort::ServerAddress(size_t index) const {
2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (index < server_addr_.size())
2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return &server_addr_[index];
2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return NULL;
2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool RelayPort::HasMagicCookie(const char* data, size_t size) {
2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (size < 24 + sizeof(TURN_MAGIC_COOKIE_VALUE)) {
2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return false;
2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
265b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org    return memcmp(data + 24,
266b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org                  TURN_MAGIC_COOKIE_VALUE,
267b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org                  sizeof(TURN_MAGIC_COOKIE_VALUE)) == 0;
2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayPort::PrepareAddress() {
2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We initiate a connect on the first entry.  If this completes, it will fill
2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // in the server address as the address of this port.
2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(entries_.size() == 1);
2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  entries_[0]->Connect();
2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ready_ = false;
2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgConnection* RelayPort::CreateConnection(const Candidate& address,
2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                        CandidateOrigin origin) {
2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We only create conns to non-udp sockets if they are incoming on this port
2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((address.protocol() != UDP_PROTOCOL_NAME) &&
2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (origin != ORIGIN_THIS_PORT)) {
2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return 0;
2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We don't support loopback on relays
2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (address.type() == Type()) {
2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return 0;
2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!IsCompatibleAddress(address.address())) {
2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return 0;
2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  size_t index = 0;
2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < Candidates().size(); ++i) {
2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const Candidate& local = Candidates()[i];
2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (local.protocol() == address.protocol()) {
3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      index = i;
3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  Connection * conn = new ProxyConnection(this, index, address);
3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  AddConnection(conn);
3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return conn;
3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RelayPort::SendTo(const void* data, size_t size,
3112a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                      const rtc::SocketAddress& addr,
3122a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                      const rtc::PacketOptions& options,
313391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org                      bool payload) {
3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Try to find an entry for this specific address.  Note that the first entry
3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // created was not given an address initially, so it can be set to the first
3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // address that comes along.
3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayEntry* entry = 0;
3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < entries_.size(); ++i) {
3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (entries_[i]->address().IsNil() && payload) {
3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry = entries_[i];
3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry->set_address(addr);
3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else if (entries_[i]->address() == addr) {
3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry = entries_[i];
3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      break;
3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we did not find one, then we make a new one.  This will not be useable
3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // until it becomes connected, however.
3320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!entry && payload) {
3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entry = new RelayEntry(this, addr);
3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!entries_.empty()) {
3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry->SetServerIndex(entries_[0]->ServerIndex());
3360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entry->Connect();
3380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entries_.push_back(entry);
3390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If the entry is connected, then we can send on it (though wrapping may
3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // still be necessary).  Otherwise, we can't yet use this connection, so we
3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // default to the first one.
3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!entry || !entry->connected()) {
3450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(!entries_.empty());
3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entry = entries_[0];
3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (!entry->connected()) {
3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      error_ = EWOULDBLOCK;
3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return SOCKET_ERROR;
3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Send the actual contents to the server using the usual mechanism.
354f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  int sent = entry->SendTo(data, size, addr, options);
3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sent <= 0) {
3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(sent < 0);
3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    error_ = entry->GetError();
3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return SOCKET_ERROR;
3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The caller of the function is expecting the number of user data bytes,
3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // rather than the size of the packet.
3621a04b881e0ef480802fb01b4fbe9bcd5388d2c69henrike@webrtc.org  return static_cast<int>(size);
3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3652a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgint RelayPort::SetOption(rtc::Socket::Option opt, int value) {
3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int result = 0;
3670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < entries_.size(); ++i) {
3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (entries_[i]->SetSocketOption(opt, value) < 0) {
3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      result = -1;
3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      error_ = entries_[i]->GetError();
3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  options_.push_back(OptionValue(opt, value));
3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return result;
3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3772a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgint RelayPort::GetOption(rtc::Socket::Option opt, int* value) {
3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  std::vector<OptionValue>::iterator it;
3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (it = options_.begin(); it < options_.end(); ++it) {
3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (it->first == opt) {
3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      *value = it->second;
3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      return 0;
3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
3840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return SOCKET_ERROR;
3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RelayPort::GetError() {
3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return error_;
3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayPort::OnReadPacket(
3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const char* data, size_t size,
3942a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::SocketAddress& remote_addr,
395f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    ProtocolType proto,
3962a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (Connection* conn = GetConnection(remote_addr)) {
398f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    conn->OnReadPacket(data, size, packet_time);
3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Port::OnReadPacket(data, size, remote_addr, proto);
4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayConnection::RelayConnection(const ProtocolAddress* protocol_address,
4052a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                 rtc::AsyncPacketSocket* socket,
4062a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                                 rtc::Thread* thread)
4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : socket_(socket),
4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      protocol_address_(protocol_address) {
4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request_manager_ = new StunRequestManager(thread);
4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request_manager_->SignalSendPacket.connect(this,
4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                             &RelayConnection::OnSendPacket);
4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayConnection::~RelayConnection() {
4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete request_manager_;
4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete socket_;
4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4192a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgint RelayConnection::SetSocketOption(rtc::Socket::Option opt,
4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                     int value) {
4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (socket_) {
4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return socket_->SetOption(opt, value);
4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return 0;
4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool RelayConnection::CheckResponse(StunMessage* msg) {
4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return request_manager_->CheckResponse(msg);
4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayConnection::OnSendPacket(const void* data, size_t size,
4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                   StunRequest* req) {
433391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.org  // TODO(mallinath) Find a way to get DSCP value from Port.
4342a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::PacketOptions options;  // Default dscp set to NO_CHANGE.
435f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  int sent = socket_->SendTo(data, size, GetAddress(), options);
4360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (sent <= 0) {
4370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " << GetAddress() <<
438b9518277716cf5081d3058d86ab7d98b78f696e8pbos@webrtc.org        strerror(socket_->GetError());
4390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    ASSERT(sent < 0);
4400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
443391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.orgint RelayConnection::Send(const void* pv, size_t cb,
4442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                          const rtc::PacketOptions& options) {
445f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  return socket_->SendTo(pv, cb, GetAddress(), options);
4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) {
4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request_manager_->SendDelayed(new AllocateRequest(entry, this), delay);
4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayEntry::RelayEntry(RelayPort* port,
4532a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                       const rtc::SocketAddress& ext_addr)
4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : port_(port), ext_addr_(ext_addr),
4550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      server_index_(0), connected_(false), locked_(false),
4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      current_connection_(NULL) {
4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayEntry::~RelayEntry() {
4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Remove all RelayConnections and dispose sockets.
4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  delete current_connection_;
4620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  current_connection_ = NULL;
4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayEntry::Connect() {
4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we're already connected, return.
4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connected_)
4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we've exhausted all options, bail out.
4710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const ProtocolAddress* ra = port()->ServerAddress(server_index_);
4720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!ra) {
4730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "No more relay addresses left to try";
4740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
4750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Remove any previous connection.
4780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_) {
4790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port()->thread()->Dispose(current_connection_);
4800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    current_connection_ = NULL;
4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Try to set up our new socket.
4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) <<
4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      " @ " << ra->address.ToSensitiveString();
4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4872a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::AsyncPacketSocket* socket = NULL;
4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ra->proto == PROTO_UDP) {
4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // UDP sockets are simple.
4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket = port_->socket_factory()->CreateUdpSocket(
4922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        rtc::SocketAddress(port_->ip(), 0),
4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        port_->min_port(), port_->max_port());
4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) {
4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    int opts = (ra->proto == PROTO_SSLTCP) ?
4962a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org     rtc::PacketSocketFactory::OPT_SSLTCP : 0;
4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket = port_->socket_factory()->CreateClientTcpSocket(
4982a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org        rtc::SocketAddress(port_->ip(), 0), ra->address,
4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        port_->proxy(), port_->user_agent(), opts);
5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Unknown protocol (" << ra->proto << ")";
5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!socket) {
5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Socket creation failed";
5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we failed to get a socket, move on to the next protocol.
5090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!socket) {
5100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port()->thread()->Post(this, kMessageConnectTimeout);
5110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
5120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Otherwise, create the new connection and configure any socket options.
5150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
5160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  socket->SignalReadyToSend.connect(this, &RelayEntry::OnReadyToSend);
5170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  current_connection_ = new RelayConnection(ra, socket, port()->thread());
5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  for (size_t i = 0; i < port_->options().size(); ++i) {
5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    current_connection_->SetSocketOption(port_->options()[i].first,
5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                         port_->options()[i].second);
5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we're trying UDP, start binding requests.
5240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If we're trying TCP, wait for connection with a fixed timeout.
5250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) {
5260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket->SignalClose.connect(this, &RelayEntry::OnSocketClose);
5270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket->SignalConnect.connect(this, &RelayEntry::OnSocketConnect);
5280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port()->thread()->PostDelayed(kSoftConnectTimeoutMs, this,
5290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                  kMessageConnectTimeout);
5300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
5310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    current_connection_->SendAllocateRequest(this, 0);
5320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RelayEntry::GetError() {
5360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_ != NULL) {
5370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return current_connection_->GetError();
5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
5390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return 0;
5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgRelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1,
5430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                               RelayConnection* conn2) {
5440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2;
5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid RelayEntry::OnConnect(const rtc::SocketAddress& mapped_addr,
5480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           RelayConnection* connection) {
5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We are connected, notify our parent.
5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ProtocolType proto = PROTO_UDP;
5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto)
5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org            << " @ " << mapped_addr.ToSensitiveString();
5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  connected_ = true;
5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_->SetReady();
5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint RelayEntry::SendTo(const void* data, size_t size,
5602a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                       const rtc::SocketAddress& addr,
5612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                       const rtc::PacketOptions& options) {
5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If this connection is locked to the address given, then we can send the
5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // packet with no wrapper.
5640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (locked_ && (ext_addr_ == addr))
565f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    return SendPacket(data, size, options);
5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Otherwise, we must wrap the given data in a STUN SEND request so that we
5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // can communicate the destination address to the server.
5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  //
5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Note that we do not use a StunRequest here.  This is because there is
5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // likely no reason to resend this packet. If it is late, we just drop it.
5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The next send to this address will try again.
5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayMessage request;
5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request.SetType(STUN_SEND_REQUEST);
5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunByteStringAttribute* magic_cookie_attr =
5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  magic_cookie_attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE,
5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               sizeof(TURN_MAGIC_COOKIE_VALUE));
5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  VERIFY(request.AddAttribute(magic_cookie_attr));
5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunByteStringAttribute* username_attr =
5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  username_attr->CopyBytes(port_->username_fragment().c_str(),
5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                           port_->username_fragment().size());
5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  VERIFY(request.AddAttribute(username_attr));
5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunAddressAttribute* addr_attr =
5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  addr_attr->SetIP(addr.ipaddr());
5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  addr_attr->SetPort(addr.port());
5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  VERIFY(request.AddAttribute(addr_attr));
5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Attempt to lock
5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (ext_addr_ == addr) {
5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    StunUInt32Attribute* options_attr =
5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    options_attr->SetValue(0x1);
6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    VERIFY(request.AddAttribute(options_attr));
6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunByteStringAttribute* data_attr =
6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateByteString(STUN_ATTR_DATA);
6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  data_attr->CopyBytes(data, size);
6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  VERIFY(request.AddAttribute(data_attr));
6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: compute the HMAC.
6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6102a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::ByteBuffer buf;
6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request.Write(&buf);
6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
613f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org  return SendPacket(buf.Data(), buf.Length(), options);
6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayEntry::ScheduleKeepAlive() {
6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_) {
6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    current_connection_->SendAllocateRequest(this, kKeepAliveDelay);
6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6222a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgint RelayEntry::SetSocketOption(rtc::Socket::Option opt, int value) {
6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Set the option on all available sockets.
6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int socket_error = 0;
6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_) {
6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    socket_error = current_connection_->SetSocketOption(opt, value);
6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return socket_error;
6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid RelayEntry::HandleConnectFailure(
6322a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::AsyncPacketSocket* socket) {
6330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Make sure it's the current connection that has failed, it might
6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // be an old socked that has not yet been disposed.
6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!socket ||
6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      (current_connection_ && socket == current_connection_->socket())) {
6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (current_connection_)
6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      port()->SignalConnectFailure(current_connection_->protocol_address());
6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Try to connect to the next server address.
6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    server_index_ += 1;
6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    Connect();
6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6462a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid RelayEntry::OnMessage(rtc::Message *pmsg) {
6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  ASSERT(pmsg->message_id == kMessageConnectTimeout);
6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_) {
6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    const ProtocolAddress* ra = current_connection_->protocol_address();
6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " <<
6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        ra->address << " timed out";
6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // Currently we connect to each server address in sequence. If we
6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // have more addresses to try, treat this is an error and move on to
6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // the next address, otherwise give this connection more time and
6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // await the real timeout.
6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    //
6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // TODO: Connect to servers in parallel to speed up connect time
6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // and to avoid giving up too early.
6600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port_->SignalSoftTimeout(ra);
6610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    HandleConnectFailure(current_connection_->socket());
6620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    HandleConnectFailure(NULL);
6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid RelayEntry::OnSocketConnect(rtc::AsyncPacketSocket* socket) {
6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(INFO) << "relay tcp connected to " <<
6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      socket->GetRemoteAddress().ToSensitiveString();
6700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_ != NULL) {
6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    current_connection_->SendAllocateRequest(this, 0);
6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6752a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid RelayEntry::OnSocketClose(rtc::AsyncPacketSocket* socket,
6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                               int error) {
6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  PLOG(LERROR, error) << "Relay connection failed: socket closed";
6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  HandleConnectFailure(socket);
6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
681f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.orgvoid RelayEntry::OnReadPacket(
6822a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::AsyncPacketSocket* socket,
683f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org    const char* data, size_t size,
6842a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::SocketAddress& remote_addr,
6852a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // ASSERT(remote_addr == port_->server_addr());
6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // TODO: are we worried about this?
6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_ == NULL || socket != current_connection_->socket()) {
6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // This packet comes from an unknown address.
6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(WARNING) << "Dropping packet: unknown address";
6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // If the magic cookie is not present, then this is an unwrapped packet sent
6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // by the server,  The actual remote address is the one we recorded.
6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!port_->HasMagicCookie(data, size)) {
6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (locked_) {
699f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org      port_->OnReadPacket(data, size, ext_addr_, PROTO_UDP, packet_time);
7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    } else {
7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      LOG(WARNING) << "Dropping packet: entry not locked";
7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7062a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::ByteBuffer buf(data, size);
7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  RelayMessage msg;
7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!msg.Read(&buf)) {
7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Incoming packet was not STUN";
7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // The incoming packet should be a STUN ALLOCATE response, SEND response, or
7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // DATA indication.
7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_->CheckResponse(&msg)) {
7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (msg.type() == STUN_SEND_RESPONSE) {
7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    if (const StunUInt32Attribute* options_attr =
7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        msg.GetUInt32(STUN_ATTR_OPTIONS)) {
7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      if (options_attr->value() & 0x1) {
7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org        locked_ = true;
7220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      }
7230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    }
7240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (msg.type() != STUN_DATA_INDICATION) {
7260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Received BAD stun type from server: " << msg.type();
7270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This must be a data indication.
7310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const StunAddressAttribute* addr_attr =
7330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
7340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!addr_attr) {
7350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Data indication has no source address";
7360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (addr_attr->family() != 1) {
7380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Source address has bad family";
7390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7422a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  rtc::SocketAddress remote_addr2(addr_attr->ipaddr(), addr_attr->port());
7430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
7450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!data_attr) {
7460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Data indication has no data";
7470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    return;
7480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // Process the actual data and remote address in the normal manner.
7510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2,
752f89a403cd8db88001322bbb0765c4636fd123700wu@webrtc.org                      PROTO_UDP, packet_time);
7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7552a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid RelayEntry::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
7560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (connected()) {
7570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    port_->OnReadyToSend();
7580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
761391247d05a663265807c400947ab6eb01ae3d690mallinath@webrtc.orgint RelayEntry::SendPacket(const void* data, size_t size,
7622a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org                           const rtc::PacketOptions& options) {
7630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  int sent = 0;
7640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (current_connection_) {
7650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // We are connected, no need to send packets anywere else than to
7660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    // the current connection.
767f5e5b3a9ce372d0e3cc594bf0036dda64a57d81dmallinath@webrtc.org    sent = current_connection_->Send(data, size, options);
7680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
7690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return sent;
7700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgAllocateRequest::AllocateRequest(RelayEntry* entry,
7730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org                                 RelayConnection* connection)
7740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    : StunRequest(new RelayMessage()),
7750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry_(entry),
7760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      connection_(connection) {
7772a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  start_time_ = rtc::Time();
7780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocateRequest::Prepare(StunMessage* request) {
7810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  request->SetType(STUN_ALLOCATE_REQUEST);
7820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  StunByteStringAttribute* username_attr =
7840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
7850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  username_attr->CopyBytes(
7860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry_->port()->username_fragment().c_str(),
7870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      entry_->port()->username_fragment().size());
7880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  VERIFY(request->AddAttribute(username_attr));
7890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint AllocateRequest::GetNextDelay() {
7922a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  int delay = 100 * rtc::_max(1 << count_, 2);
7930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  count_ += 1;
7940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (count_ == 5)
7950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    timeout_ = true;
7960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  return delay;
7970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
7980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
7990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocateRequest::OnResponse(StunMessage* response) {
8000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const StunAddressAttribute* addr_attr =
8010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org      response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
8020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!addr_attr) {
8030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Allocate response missing mapped address.";
8040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else if (addr_attr->family() != 1) {
8050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Mapped address has bad family";
8060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8072a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org    rtc::SocketAddress addr(addr_attr->ipaddr(), addr_attr->port());
8080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entry_->OnConnect(addr, connection_);
8090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // We will do a keep-alive regardless of whether this request suceeds.
8120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  // This should have almost no impact on network usage.
8130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  entry_->ScheduleKeepAlive();
8140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocateRequest::OnErrorResponse(StunMessage* response) {
8170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  const StunErrorCodeAttribute* attr = response->GetErrorCode();
8180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  if (!attr) {
8190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Bad allocate response error code";
8200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  } else {
8210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    LOG(INFO) << "Allocate error response:"
8220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org              << " code=" << attr->code()
8230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org              << " reason='" << attr->reason() << "'";
8240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  }
8250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8262a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org  if (rtc::TimeSince(start_time_) <= kRetryTimeout)
8270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org    entry_->ScheduleKeepAlive();
8280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid AllocateRequest::OnTimeout() {
8310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  LOG(INFO) << "Allocate request timed out";
8320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org  entry_->HandleConnectFailure(connection_->socket());
8330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}
8340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org
8350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}  // namespace cricket
836