/*
 * libjingle
 * Copyright 2004--2005, Google Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  1. Redistributions of source code must retain the above copyright notice,
 *     this list of conditions and the following disclaimer.
 *  2. Redistributions in binary form must reproduce the above copyright notice,
 *     this list of conditions and the following disclaimer in the documentation
 *     and/or other materials provided with the distribution.
 *  3. The name of the author may not be used to endorse or promote products
 *     derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "talk/base/asyncpacketsocket.h"
#include "talk/base/helpers.h"
#include "talk/base/logging.h"
#include "talk/p2p/base/relayport.h"

namespace cricket {

static const uint32 kMessageConnectTimeout = 1;
static const int kKeepAliveDelay           = 10 * 60 * 1000;
static const int kRetryTimeout             = 50 * 1000;  // ICE says 50 secs
// How long to wait for a socket to connect to remote host in milliseconds
// before trying another connection.
static const int kSoftConnectTimeoutMs     = 3 * 1000;

// Handles a connection to one address/port/protocol combination for a
// particular RelayEntry.
class RelayConnection : public sigslot::has_slots<> {
 public:
  RelayConnection(const ProtocolAddress* protocol_address,
                  talk_base::AsyncPacketSocket* socket,
                  talk_base::Thread* thread);
  ~RelayConnection();
  talk_base::AsyncPacketSocket* socket() const { return socket_; }

  const ProtocolAddress* protocol_address() {
    return protocol_address_;
  }

  talk_base::SocketAddress GetAddress() const {
    return protocol_address_->address;
  }

  ProtocolType GetProtocol() const {
    return protocol_address_->proto;
  }

  int SetSocketOption(talk_base::Socket::Option opt, int value);

  // Validates a response to a STUN allocate request.
  bool CheckResponse(StunMessage* msg);

  // Sends data to the relay server.
  int Send(const void* pv, size_t cb);

  // Sends a STUN allocate request message to the relay server.
  void SendAllocateRequest(RelayEntry* entry, int delay);

  // Return the latest error generated by the socket.
  int GetError() { return socket_->GetError(); }

  // Called on behalf of a StunRequest to write data to the socket.  This is
  // already STUN intended for the server, so no wrapping is necessary.
  void OnSendPacket(const void* data, size_t size, StunRequest* req);

 private:
  talk_base::AsyncPacketSocket* socket_;
  const ProtocolAddress* protocol_address_;
  StunRequestManager *request_manager_;
};

// Manages a number of connections to the relayserver, one for each
// available protocol. We aim to use each connection for only a
// specific destination address so that we can avoid wrapping every
// packet in a STUN send / data indication.
class RelayEntry : public talk_base::MessageHandler,
                   public sigslot::has_slots<> {
 public:
  RelayEntry(RelayPort* port, const talk_base::SocketAddress& ext_addr);
  ~RelayEntry();

  RelayPort* port() { return port_; }

  const talk_base::SocketAddress& address() const { return ext_addr_; }
  void set_address(const talk_base::SocketAddress& addr) { ext_addr_ = addr; }

  bool connected() const { return connected_; }
  bool locked() const { return locked_; }

  // Returns the last error on the socket of this entry.
  int GetError();

  // Returns the most preferred connection of the given
  // ones. Connections are rated based on protocol in the order of:
  // UDP, TCP and SSLTCP, where UDP is the most preferred protocol
  static RelayConnection* GetBestConnection(RelayConnection* conn1,
                                            RelayConnection* conn2);

  // Sends the STUN requests to the server to initiate this connection.
  void Connect();

  // Called when this entry becomes connected.  The address given is the one
  // exposed to the outside world on the relay server.
  void OnConnect(const talk_base::SocketAddress& mapped_addr,
                 RelayConnection* socket);

  // Sends a packet to the given destination address using the socket of this
  // entry.  This will wrap the packet in STUN if necessary.
  int SendTo(const void* data, size_t size,
    const talk_base::SocketAddress& addr);

  // Schedules a keep-alive allocate request.
  void ScheduleKeepAlive();

  void SetServerIndex(size_t sindex) { server_index_ = sindex; }

  // Sets this option on the socket of each connection.
  int SetSocketOption(talk_base::Socket::Option opt, int value);

  size_t ServerIndex() const { return server_index_; }

  // Try a different server address
  void HandleConnectFailure(talk_base::AsyncPacketSocket* socket);

  // Implementation of the MessageHandler Interface.
  virtual void OnMessage(talk_base::Message *pmsg);

 private:
  RelayPort* port_;
  talk_base::SocketAddress ext_addr_;
  size_t server_index_;
  bool connected_;
  bool locked_;
  RelayConnection* current_connection_;

  // Called when a TCP connection is established or fails
  void OnSocketConnect(talk_base::AsyncPacketSocket* socket);
  void OnSocketClose(talk_base::AsyncPacketSocket* socket, int error);

  // Called when a packet is received on this socket.
  void OnReadPacket(talk_base::AsyncPacketSocket* socket,
                    const char* data, size_t size,
                    const talk_base::SocketAddress& remote_addr);

  // Sends the given data on the socket to the server with no wrapping.  This
  // returns the number of bytes written or -1 if an error occurred.
  int SendPacket(const void* data, size_t size);
};

// Handles an allocate request for a particular RelayEntry.
class AllocateRequest : public StunRequest {
 public:
  AllocateRequest(RelayEntry* entry, RelayConnection* connection);
  virtual ~AllocateRequest() {}

  virtual void Prepare(StunMessage* request);

  virtual int GetNextDelay();

  virtual void OnResponse(StunMessage* response);
  virtual void OnErrorResponse(StunMessage* response);
  virtual void OnTimeout();

 private:
  RelayEntry* entry_;
  RelayConnection* connection_;
  uint32 start_time_;
};

const std::string RELAY_PORT_TYPE("relay");

RelayPort::RelayPort(
    talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
    talk_base::Network* network, uint32 ip, int min_port, int max_port,
    const std::string& username, const std::string& password,
    const std::string& magic_cookie)
    : Port(thread, RELAY_PORT_TYPE, factory, network, ip, min_port, max_port),
      ready_(false),
      magic_cookie_(magic_cookie),
      error_(0) {
  entries_.push_back(
      new RelayEntry(this, talk_base::SocketAddress()));

  set_username_fragment(username);
  set_password(password);
  if (magic_cookie_.size() == 0) {
    magic_cookie_.append(TURN_MAGIC_COOKIE_VALUE,
                         sizeof(TURN_MAGIC_COOKIE_VALUE));
  }
}

RelayPort::~RelayPort() {
  for (size_t i = 0; i < entries_.size(); ++i)
    delete entries_[i];
  thread_->Clear(this);
}

void RelayPort::AddServerAddress(const ProtocolAddress& addr) {
  // Since HTTP proxies usually only allow 443,
  // let's up the priority on PROTO_SSLTCP
  if (addr.proto == PROTO_SSLTCP &&
      (proxy().type == talk_base::PROXY_HTTPS ||
       proxy().type == talk_base::PROXY_UNKNOWN)) {
    server_addr_.push_front(addr);
  } else {
    server_addr_.push_back(addr);
  }
}

void RelayPort::AddExternalAddress(const ProtocolAddress& addr) {
  std::string proto_name = ProtoToString(addr.proto);
  for (std::vector<Candidate>::const_iterator it = candidates().begin();
       it != candidates().end(); ++it) {
    if ((it->address() == addr.address) && (it->protocol() == proto_name)) {
      LOG(INFO) << "Redundant relay address: " << proto_name
                << " @ " << addr.address.ToString();
      return;
    }
  }
  AddAddress(addr.address, proto_name, false);
}

void RelayPort::SetReady() {
  if (!ready_) {
    ready_ = true;
    SignalAddressReady(this);
  }
}

const ProtocolAddress * RelayPort::ServerAddress(size_t index) const {
  if (index < server_addr_.size())
    return &server_addr_[index];
  return NULL;
}

bool RelayPort::HasMagicCookie(const char* data, size_t size) {
  if (size < 24 + magic_cookie_.size()) {
    return false;
  } else {
    return 0 == std::memcmp(data + 24,
                            magic_cookie_.c_str(),
                            magic_cookie_.size());
  }
}

void RelayPort::PrepareAddress() {
  // We initiate a connect on the first entry.  If this completes, it will fill
  // in the server address as the address of this port.
  ASSERT(entries_.size() == 1);
  entries_[0]->Connect();
  ready_ = false;
}

Connection* RelayPort::CreateConnection(const Candidate& address,
                                        CandidateOrigin origin) {
  // We only create conns to non-udp sockets if they are incoming on this port
  if ((address.protocol() != "udp") && (origin != ORIGIN_THIS_PORT)) {
    return 0;
  }

  // We don't support loopback on relays
  if (address.type() == type()) {
    return 0;
  }

  size_t index = 0;
  for (size_t i = 0; i < candidates().size(); ++i) {
    const Candidate& local = candidates()[i];
    if (local.protocol() == address.protocol()) {
      index = i;
      break;
    }
  }

  Connection * conn = new ProxyConnection(this, index, address);
  AddConnection(conn);
  return conn;
}

int RelayPort::SendTo(const void* data, size_t size,
                      const talk_base::SocketAddress& addr, bool payload) {
  // Try to find an entry for this specific address.  Note that the first entry
  // created was not given an address initially, so it can be set to the first
  // address that comes along.
  RelayEntry* entry = 0;

  for (size_t i = 0; i < entries_.size(); ++i) {
    if (entries_[i]->address().IsAny() && payload) {
      entry = entries_[i];
      entry->set_address(addr);
      break;
    } else if (entries_[i]->address() == addr) {
      entry = entries_[i];
      break;
    }
  }

  // If we did not find one, then we make a new one.  This will not be useable
  // until it becomes connected, however.
  if (!entry && payload) {
    entry = new RelayEntry(this, addr);
    if (!entries_.empty()) {
      entry->SetServerIndex(entries_[0]->ServerIndex());
    }
    entry->Connect();
    entries_.push_back(entry);
  }

  // If the entry is connected, then we can send on it (though wrapping may
  // still be necessary).  Otherwise, we can't yet use this connection, so we
  // default to the first one.
  if (!entry || !entry->connected()) {
    ASSERT(!entries_.empty());
    entry = entries_[0];
    if (!entry->connected()) {
      error_ = EWOULDBLOCK;
      return SOCKET_ERROR;
    }
  }

  // Send the actual contents to the server using the usual mechanism.
  int sent = entry->SendTo(data, size, addr);
  if (sent <= 0) {
    ASSERT(sent < 0);
    error_ = entry->GetError();
    return SOCKET_ERROR;
  }
  // The caller of the function is expecting the number of user data bytes,
  // rather than the size of the packet.
  return size;
}

int RelayPort::SetOption(talk_base::Socket::Option opt, int value) {
  int result = 0;
  for (size_t i = 0; i < entries_.size(); ++i) {
    if (entries_[i]->SetSocketOption(opt, value) < 0) {
      result = -1;
      error_ = entries_[i]->GetError();
    }
  }
  options_.push_back(OptionValue(opt, value));
  return result;
}

int RelayPort::GetError() {
  return error_;
}

void RelayPort::OnReadPacket(
    const char* data, size_t size,
    const talk_base::SocketAddress& remote_addr) {
  if (Connection* conn = GetConnection(remote_addr)) {
    conn->OnReadPacket(data, size);
  } else {
    Port::OnReadPacket(data, size, remote_addr);
  }
}

RelayConnection::RelayConnection(const ProtocolAddress* protocol_address,
                                 talk_base::AsyncPacketSocket* socket,
                                 talk_base::Thread* thread)
    : socket_(socket),
      protocol_address_(protocol_address) {
  request_manager_ = new StunRequestManager(thread);
  request_manager_->SignalSendPacket.connect(this,
                                             &RelayConnection::OnSendPacket);
}

RelayConnection::~RelayConnection() {
  delete request_manager_;
  delete socket_;
}

int RelayConnection::SetSocketOption(talk_base::Socket::Option opt,
                                     int value) {
  if (socket_) {
    return socket_->SetOption(opt, value);
  }
  return 0;
}

bool RelayConnection::CheckResponse(StunMessage* msg) {
  return request_manager_->CheckResponse(msg);
}

void RelayConnection::OnSendPacket(const void* data, size_t size,
                                   StunRequest* req) {
  int sent = socket_->SendTo(data, size, GetAddress());
  if (sent <= 0) {
    LOG(LS_VERBOSE) << "OnSendPacket: failed sending to " << GetAddress() <<
        std::strerror(socket_->GetError());
    ASSERT(sent < 0);
  }
}

int RelayConnection::Send(const void* pv, size_t cb) {
  return socket_->SendTo(pv, cb, GetAddress());
}

void RelayConnection::SendAllocateRequest(RelayEntry* entry, int delay) {
  request_manager_->SendDelayed(new AllocateRequest(entry, this), delay);
}

RelayEntry::RelayEntry(RelayPort* port,
                       const talk_base::SocketAddress& ext_addr)
    : port_(port), ext_addr_(ext_addr),
      server_index_(0), connected_(false), locked_(false),
      current_connection_(NULL) {
}

RelayEntry::~RelayEntry() {
  // Remove all RelayConnections and dispose sockets.
  delete current_connection_;
  current_connection_ = NULL;
}

void RelayEntry::Connect() {
  // If we're already connected, return.
  if (connected_)
    return;

  // If we've exhausted all options, bail out.
  const ProtocolAddress* ra = port()->ServerAddress(server_index_);
  if (!ra) {
    LOG(LS_WARNING) << "No more relay addresses left to try";
    return;
  }

  // Remove any previous connection.
  if (current_connection_) {
    port()->thread()->Dispose(current_connection_);
    current_connection_ = NULL;
  }

  // Try to set up our new socket.
  LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto) <<
      " @ " << ra->address.ToString();

  talk_base::AsyncPacketSocket* socket = NULL;

  if (ra->proto == PROTO_UDP) {
    // UDP sockets are simple.
    socket = port_->socket_factory()->CreateUdpSocket(
        talk_base::SocketAddress(port_->ip_, 0),
        port_->min_port_, port_->max_port_);
  } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) {
    socket = port_->socket_factory()->CreateClientTcpSocket(
        talk_base::SocketAddress(port_->ip_, 0), ra->address,
        port_->proxy(), port_->user_agent(), ra->proto == PROTO_SSLTCP);
  } else {
    LOG(LS_WARNING) << "Unknown protocol (" << ra->proto << ")";
  }

  if (!socket) {
    LOG(LS_WARNING) << "Socket creation failed";
  }

  // If we failed to get a socket, move on to the next protocol.
  if (!socket) {
    port()->thread()->Post(this, kMessageConnectTimeout);
    return;
  }

  // Otherwise, create the new connection and configure any socket options.
  socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
  current_connection_ = new RelayConnection(ra, socket, port()->thread());
  for (size_t i = 0; i < port_->options().size(); ++i) {
    current_connection_->SetSocketOption(port_->options()[i].first,
                                         port_->options()[i].second);
  }

  // If we're trying UDP, start binding requests.
  // If we're trying TCP, wait for connection with a fixed timeout.
  if ((ra->proto == PROTO_TCP) || (ra->proto == PROTO_SSLTCP)) {
    socket->SignalClose.connect(this, &RelayEntry::OnSocketClose);
    socket->SignalConnect.connect(this, &RelayEntry::OnSocketConnect);
    port()->thread()->PostDelayed(kSoftConnectTimeoutMs, this,
                                  kMessageConnectTimeout);
  } else {
    current_connection_->SendAllocateRequest(this, 0);
  }
}

int RelayEntry::GetError() {
  if (current_connection_ != NULL) {
    return current_connection_->GetError();
  }
  return 0;
}

RelayConnection* RelayEntry::GetBestConnection(RelayConnection* conn1,
                                               RelayConnection* conn2) {
  return conn1->GetProtocol() <= conn2->GetProtocol() ? conn1 : conn2;
}

void RelayEntry::OnConnect(const talk_base::SocketAddress& mapped_addr,
                           RelayConnection* connection) {
  // We are connected, notify our parent.
  ProtocolType proto = PROTO_UDP;
  LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto)
            << " @ " << mapped_addr.ToString();
  connected_ = true;

  port_->AddExternalAddress(ProtocolAddress(mapped_addr, proto));
  port_->SetReady();
}

int RelayEntry::SendTo(const void* data, size_t size,
                       const talk_base::SocketAddress& addr) {
  // If this connection is locked to the address given, then we can send the
  // packet with no wrapper.
  if (locked_ && (ext_addr_ == addr))
    return SendPacket(data, size);

  // Otherwise, we must wrap the given data in a STUN SEND request so that we
  // can communicate the destination address to the server.
  //
  // Note that we do not use a StunRequest here.  This is because there is
  // likely no reason to resend this packet. If it is late, we just drop it.
  // The next send to this address will try again.

  StunMessage request;
  request.SetType(STUN_SEND_REQUEST);
  request.SetTransactionID(
      talk_base::CreateRandomString(kStunTransactionIdLength));

  StunByteStringAttribute* magic_cookie_attr =
      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
  magic_cookie_attr->CopyBytes(port_->magic_cookie().c_str(),
                               port_->magic_cookie().size());
  request.AddAttribute(magic_cookie_attr);

  StunByteStringAttribute* username_attr =
      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
  username_attr->CopyBytes(port_->username_fragment().c_str(),
                           port_->username_fragment().size());
  request.AddAttribute(username_attr);

  StunAddressAttribute* addr_attr =
      StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
  addr_attr->SetFamily(1);
  addr_attr->SetIP(addr.ip());
  addr_attr->SetPort(addr.port());
  request.AddAttribute(addr_attr);

  // Attempt to lock
  if (ext_addr_ == addr) {
    StunUInt32Attribute* options_attr =
      StunAttribute::CreateUInt32(STUN_ATTR_OPTIONS);
    options_attr->SetValue(0x1);
    request.AddAttribute(options_attr);
  }

  StunByteStringAttribute* data_attr =
      StunAttribute::CreateByteString(STUN_ATTR_DATA);
  data_attr->CopyBytes(data, size);
  request.AddAttribute(data_attr);

  // TODO: compute the HMAC.

  talk_base::ByteBuffer buf;
  request.Write(&buf);

  return SendPacket(buf.Data(), buf.Length());
}

void RelayEntry::ScheduleKeepAlive() {
  if (current_connection_) {
    current_connection_->SendAllocateRequest(this, kKeepAliveDelay);
  }
}

int RelayEntry::SetSocketOption(talk_base::Socket::Option opt, int value) {
  // Set the option on all available sockets.
  int socket_error = 0;
  if (current_connection_) {
    socket_error = current_connection_->SetSocketOption(opt, value);
  }
  return socket_error;
}

void RelayEntry::HandleConnectFailure(
    talk_base::AsyncPacketSocket* socket) {
  // Make sure it's the current connection that has failed, it might
  // be an old socked that has not yet been disposed.
  if (!socket || socket == current_connection_->socket()) {
    if (current_connection_)
      port()->SignalConnectFailure(current_connection_->protocol_address());

    // Try to connect to the next server address.
    server_index_ += 1;
    Connect();
  }
}

void RelayEntry::OnMessage(talk_base::Message *pmsg) {
  ASSERT(pmsg->message_id == kMessageConnectTimeout);
  if (current_connection_) {
    const ProtocolAddress* ra = current_connection_->protocol_address();
    LOG(LS_WARNING) << "Relay " << ra->proto << " connection to " <<
        ra->address << " timed out";

    // Currently we connect to each server address in sequence. If we
    // have more addresses to try, treat this is an error and move on to
    // the next address, otherwise give this connection more time and
    // await the real timeout.
    //
    // TODO: Connect to servers in parallel to speed up connect time
    // and to avoid giving up too early.
    port_->SignalSoftTimeout(ra);
    HandleConnectFailure(current_connection_->socket());
  } else {
    HandleConnectFailure(NULL);
  }
}

void RelayEntry::OnSocketConnect(talk_base::AsyncPacketSocket* socket) {
  LOG(INFO) << "relay tcp connected to " <<
      socket->GetRemoteAddress().ToString();
  if (current_connection_ != NULL) {
    current_connection_->SendAllocateRequest(this, 0);
  }
}

void RelayEntry::OnSocketClose(talk_base::AsyncPacketSocket* socket,
                               int error) {
  PLOG(LERROR, error) << "Relay connection failed: socket closed";
  HandleConnectFailure(socket);
}

void RelayEntry::OnReadPacket(talk_base::AsyncPacketSocket* socket,
                              const char* data, size_t size,
                              const talk_base::SocketAddress& remote_addr) {
  // ASSERT(remote_addr == port_->server_addr());
  // TODO: are we worried about this?

  if (current_connection_ == NULL || socket != current_connection_->socket()) {
    // This packet comes from an unknown address.
    LOG(WARNING) << "Dropping packet: unknown address";
    return;
  }

  // If the magic cookie is not present, then this is an unwrapped packet sent
  // by the server,  The actual remote address is the one we recorded.
  if (!port_->HasMagicCookie(data, size)) {
    if (locked_) {
      port_->OnReadPacket(data, size, ext_addr_);
    } else {
      LOG(WARNING) << "Dropping packet: entry not locked";
    }
    return;
  }

  talk_base::ByteBuffer buf(data, size);
  StunMessage msg;
  if (!msg.Read(&buf)) {
    LOG(INFO) << "Incoming packet was not STUN";
    return;
  }

  // The incoming packet should be a STUN ALLOCATE response, SEND response, or
  // DATA indication.
  if (current_connection_->CheckResponse(&msg)) {
    return;
  } else if (msg.type() == STUN_SEND_RESPONSE) {
    if (const StunUInt32Attribute* options_attr =
        msg.GetUInt32(STUN_ATTR_OPTIONS)) {
      if (options_attr->value() & 0x1) {
        locked_ = true;
      }
    }
    return;
  } else if (msg.type() != STUN_DATA_INDICATION) {
    LOG(INFO) << "Received BAD stun type from server: " << msg.type();
    return;
  }

  // This must be a data indication.

  const StunAddressAttribute* addr_attr =
      msg.GetAddress(STUN_ATTR_SOURCE_ADDRESS2);
  if (!addr_attr) {
    LOG(INFO) << "Data indication has no source address";
    return;
  } else if (addr_attr->family() != 1) {
    LOG(INFO) << "Source address has bad family";
    return;
  }

  talk_base::SocketAddress remote_addr2(addr_attr->ip(), addr_attr->port());

  const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
  if (!data_attr) {
    LOG(INFO) << "Data indication has no data";
    return;
  }

  // Process the actual data and remote address in the normal manner.
  port_->OnReadPacket(data_attr->bytes(), data_attr->length(), remote_addr2);
}

int RelayEntry::SendPacket(const void* data, size_t size) {
  int sent = 0;
  if (current_connection_) {
    // We are connected, no need to send packets anywere else than to
    // the current connection.
    sent = current_connection_->Send(data, size);
  }
  return sent;
}

AllocateRequest::AllocateRequest(RelayEntry* entry,
                                 RelayConnection* connection) :
    entry_(entry), connection_(connection) {
  start_time_ = talk_base::Time();
}

void AllocateRequest::Prepare(StunMessage* request) {
  request->SetType(STUN_ALLOCATE_REQUEST);

  StunByteStringAttribute* magic_cookie_attr =
      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
  magic_cookie_attr->CopyBytes(
      entry_->port()->magic_cookie().c_str(),
      entry_->port()->magic_cookie().size());
  request->AddAttribute(magic_cookie_attr);

  StunByteStringAttribute* username_attr =
      StunAttribute::CreateByteString(STUN_ATTR_USERNAME);
  username_attr->CopyBytes(
      entry_->port()->username_fragment().c_str(),
      entry_->port()->username_fragment().size());
  request->AddAttribute(username_attr);
}

int AllocateRequest::GetNextDelay() {
  int delay = 100 * talk_base::_max(1 << count_, 2);
  count_ += 1;
  if (count_ == 5)
    timeout_ = true;
  return delay;
}

void AllocateRequest::OnResponse(StunMessage* response) {
  const StunAddressAttribute* addr_attr =
      response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
  if (!addr_attr) {
    LOG(INFO) << "Allocate response missing mapped address.";
  } else if (addr_attr->family() != 1) {
    LOG(INFO) << "Mapped address has bad family";
  } else {
    talk_base::SocketAddress addr(addr_attr->ip(), addr_attr->port());
    entry_->OnConnect(addr, connection_);
  }

  // We will do a keep-alive regardless of whether this request suceeds.
  // This should have almost no impact on network usage.
  entry_->ScheduleKeepAlive();
}

void AllocateRequest::OnErrorResponse(StunMessage* response) {
  const StunErrorCodeAttribute* attr = response->GetErrorCode();
  if (!attr) {
    LOG(INFO) << "Bad allocate response error code";
  } else {
    LOG(INFO) << "Allocate error response:"
              << " code=" << static_cast<int>(attr->error_code())
              << " reason='" << attr->reason() << "'";
  }

  if (talk_base::TimeSince(start_time_) <= kRetryTimeout)
    entry_->ScheduleKeepAlive();
}

void AllocateRequest::OnTimeout() {
  LOG(INFO) << "Allocate request timed out";
  entry_->HandleConnectFailure(connection_->socket());
}

}  // namespace cricket
