/*
 * 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 char RELAY_PORT_TYPE[] = "relay";

RelayPort::RelayPort(
    talk_base::Thread* thread, talk_base::PacketSocketFactory* factory,
    talk_base::Network* network, const talk_base::IPAddress& 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->SetIP(addr.ipaddr());
  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->ipaddr(), 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->ipaddr(), 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
