/*
 * 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, 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->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
