/*
 *  Copyright 2004 The WebRTC Project Authors. All rights reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */
#include <errno.h>
#include <string.h>
#include <algorithm>

#include "p2p/base/relay_port.h"
#include "p2p/base/stun.h"
#include "p2p/base/stun_request.h"
#include "rtc_base/async_packet_socket.h"
#include "rtc_base/byte_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/dscp.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
#include "rtc_base/message_handler.h"
#include "rtc_base/message_queue.h"
#include "rtc_base/net_helper.h"
#include "rtc_base/proxy_info.h"
#include "rtc_base/time_utils.h"

namespace cricket {

static const int 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,
                  rtc::AsyncPacketSocket* socket,
                  rtc::Thread* thread);
  ~RelayConnection() override;
  rtc::AsyncPacketSocket* socket() const { return socket_; }

  const ProtocolAddress* protocol_address() { return protocol_address_; }

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

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

  int SetSocketOption(rtc::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, const rtc::PacketOptions& options);

  // 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:
  rtc::AsyncPacketSocket* socket_;
  const ProtocolAddress* protocol_address_;
  StunRequestManager* request_manager_;
  rtc::DiffServCodePoint dscp_;
};

// 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 rtc::MessageHandler, public sigslot::has_slots<> {
 public:
  RelayEntry(RelayPort* port, const rtc::SocketAddress& ext_addr);
  ~RelayEntry() override;

  RelayPort* port() { return port_; }

  const rtc::SocketAddress& address() const { return ext_addr_; }
  void set_address(const rtc::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 rtc::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 rtc::SocketAddress& addr,
             const rtc::PacketOptions& options);

  // 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(rtc::Socket::Option opt, int value);

  size_t ServerIndex() const { return server_index_; }

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

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

 private:
  RelayPort* port_;
  rtc::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(rtc::AsyncPacketSocket* socket);
  void OnSocketClose(rtc::AsyncPacketSocket* socket, int error);

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

  void OnSentPacket(rtc::AsyncPacketSocket* socket,
                    const rtc::SentPacket& sent_packet);

  // Called when the socket is currently able to send.
  void OnReadyToSend(rtc::AsyncPacketSocket* socket);

  // 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,
                 const rtc::PacketOptions& options);
};

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

  void Prepare(StunMessage* request) override;

  void OnSent() override;
  int resend_delay() override;

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

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

RelayPort::RelayPort(rtc::Thread* thread,
                     rtc::PacketSocketFactory* factory,
                     rtc::Network* network,
                     uint16_t min_port,
                     uint16_t max_port,
                     const std::string& username,
                     const std::string& password)
    : Port(thread,
           RELAY_PORT_TYPE,
           factory,
           network,
           min_port,
           max_port,
           username,
           password),
      ready_(false),
      error_(0) {
  entries_.push_back(new RelayEntry(this, rtc::SocketAddress()));
  // TODO(?): set local preference value for TCP based candidates.
}

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 == rtc::PROXY_HTTPS ||
                                     proxy().type == rtc::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<ProtocolAddress>::iterator it = external_addr_.begin();
       it != external_addr_.end(); ++it) {
    if ((it->address == addr.address) && (it->proto == addr.proto)) {
      RTC_LOG(INFO) << "Redundant relay address: " << proto_name << " @ "
                    << addr.address.ToSensitiveString();
      return;
    }
  }
  external_addr_.push_back(addr);
}

void RelayPort::SetReady() {
  if (!ready_) {
    std::vector<ProtocolAddress>::iterator iter;
    for (iter = external_addr_.begin(); iter != external_addr_.end(); ++iter) {
      std::string proto_name = ProtoToString(iter->proto);
      // In case of Gturn, related address is set to null socket address.
      // This is due to as mapped address stun attribute is used for allocated
      // address.
      AddAddress(iter->address, iter->address, rtc::SocketAddress(), proto_name,
                 proto_name, "", RELAY_PORT_TYPE, ICE_TYPE_PREFERENCE_RELAY_UDP,
                 0, "", false);
    }
    ready_ = true;
    SignalPortComplete(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 + sizeof(TURN_MAGIC_COOKIE_VALUE)) {
    return false;
  } else {
    return memcmp(data + 24, TURN_MAGIC_COOKIE_VALUE,
                  sizeof(TURN_MAGIC_COOKIE_VALUE)) == 0;
  }
}

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.
  RTC_DCHECK(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_PROTOCOL_NAME) &&
      (origin != ORIGIN_THIS_PORT)) {
    return 0;
  }

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

  if (!IsCompatibleAddress(address.address())) {
    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);
  AddOrReplaceConnection(conn);
  return conn;
}

int RelayPort::SendTo(const void* data,
                      size_t size,
                      const rtc::SocketAddress& addr,
                      const rtc::PacketOptions& options,
                      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().IsNil() && 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()) {
    RTC_DCHECK(!entries_.empty());
    entry = entries_[0];
    if (!entry->connected()) {
      error_ = ENOTCONN;
      return SOCKET_ERROR;
    }
  }

  // Send the actual contents to the server using the usual mechanism.
  rtc::PacketOptions modified_options(options);
  CopyPortInformationToPacketInfo(&modified_options.info_signaled_after_sent);
  int sent = entry->SendTo(data, size, addr, modified_options);
  if (sent <= 0) {
    RTC_DCHECK(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 static_cast<int>(size);
}

int RelayPort::SetOption(rtc::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::GetOption(rtc::Socket::Option opt, int* value) {
  std::vector<OptionValue>::iterator it;
  for (it = options_.begin(); it < options_.end(); ++it) {
    if (it->first == opt) {
      *value = it->second;
      return 0;
    }
  }
  return SOCKET_ERROR;
}

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

bool RelayPort::SupportsProtocol(const std::string& protocol) const {
  // Relay port may create both TCP and UDP connections.
  return true;
}

ProtocolType RelayPort::GetProtocol() const {
  // We shouldn't be using RelayPort, but we need to provide an implementation
  // here.
  return PROTO_UDP;
}

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

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

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

int RelayConnection::SetSocketOption(rtc::Socket::Option opt, int value) {
  if (opt == rtc::Socket::OPT_DSCP) {
    dscp_ = static_cast<rtc::DiffServCodePoint>(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) {
  rtc::PacketOptions options(dscp_);
  int sent = socket_->SendTo(data, size, GetAddress(), options);
  if (sent <= 0) {
    RTC_LOG(LS_VERBOSE) << "OnSendPacket: failed sending to "
                        << GetAddress().ToString()
                        << strerror(socket_->GetError());
    RTC_DCHECK(sent < 0);
  }
}

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

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

RelayEntry::RelayEntry(RelayPort* port, const rtc::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) {
    RTC_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.
  RTC_LOG(LS_INFO) << "Connecting to relay via " << ProtoToString(ra->proto)
                   << " @ " << ra->address.ToSensitiveString();

  rtc::AsyncPacketSocket* socket = NULL;

  if (ra->proto == PROTO_UDP) {
    // UDP sockets are simple.
    socket = port_->socket_factory()->CreateUdpSocket(
        rtc::SocketAddress(port_->Network()->GetBestIP(), 0), port_->min_port(),
        port_->max_port());
  } else if (ra->proto == PROTO_TCP || ra->proto == PROTO_SSLTCP) {
    int opts = (ra->proto == PROTO_SSLTCP)
                   ? rtc::PacketSocketFactory::OPT_TLS_FAKE
                   : 0;
    socket = port_->socket_factory()->CreateClientTcpSocket(
        rtc::SocketAddress(port_->Network()->GetBestIP(), 0), ra->address,
        port_->proxy(), port_->user_agent(), opts);
  } else {
    RTC_LOG(LS_WARNING) << "Unknown protocol: " << ra->proto;
  }

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

  // Otherwise, create the new connection and configure any socket options.
  socket->SignalReadPacket.connect(this, &RelayEntry::OnReadPacket);
  socket->SignalSentPacket.connect(this, &RelayEntry::OnSentPacket);
  socket->SignalReadyToSend.connect(this, &RelayEntry::OnReadyToSend);
  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(RTC_FROM_HERE, 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 rtc::SocketAddress& mapped_addr,
                           RelayConnection* connection) {
  // We are connected, notify our parent.
  ProtocolType proto = PROTO_UDP;
  RTC_LOG(INFO) << "Relay allocate succeeded: " << ProtoToString(proto) << " @ "
                << mapped_addr.ToSensitiveString();
  connected_ = true;

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

int RelayEntry::SendTo(const void* data,
                       size_t size,
                       const rtc::SocketAddress& addr,
                       const rtc::PacketOptions& options) {
  // 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, options);

  // 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.

  RelayMessage request;
  request.SetType(STUN_SEND_REQUEST);

  auto magic_cookie_attr =
      StunAttribute::CreateByteString(STUN_ATTR_MAGIC_COOKIE);
  magic_cookie_attr->CopyBytes(TURN_MAGIC_COOKIE_VALUE,
                               sizeof(TURN_MAGIC_COOKIE_VALUE));
  request.AddAttribute(std::move(magic_cookie_attr));

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

  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_DESTINATION_ADDRESS);
  addr_attr->SetIP(addr.ipaddr());
  addr_attr->SetPort(addr.port());
  request.AddAttribute(std::move(addr_attr));

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

  auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA);
  data_attr->CopyBytes(data, size);
  request.AddAttribute(std::move(data_attr));

  // TODO(?): compute the HMAC.

  rtc::ByteBufferWriter buf;
  request.Write(&buf);

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

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

int RelayEntry::SetSocketOption(rtc::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(rtc::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 ||
      (current_connection_ && 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(rtc::Message* pmsg) {
  RTC_DCHECK(pmsg->message_id == kMessageConnectTimeout);
  if (current_connection_) {
    const ProtocolAddress* ra = current_connection_->protocol_address();
    RTC_LOG(LS_WARNING) << "Relay " << ra->proto << " connection to "
                        << ra->address.ToString() << " 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(rtc::AsyncPacketSocket* socket) {
  RTC_LOG(INFO) << "relay tcp connected to "
                << socket->GetRemoteAddress().ToSensitiveString();
  if (current_connection_ != NULL) {
    current_connection_->SendAllocateRequest(this, 0);
  }
}

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

void RelayEntry::OnReadPacket(rtc::AsyncPacketSocket* socket,
                              const char* data,
                              size_t size,
                              const rtc::SocketAddress& remote_addr,
                              const int64_t& packet_time_us) {
  // RTC_DCHECK(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.
    RTC_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_, PROTO_UDP, packet_time_us);
    } else {
      RTC_LOG(WARNING) << "Dropping packet: entry not locked";
    }
    return;
  }

  rtc::ByteBufferReader buf(data, size);
  RelayMessage msg;
  if (!msg.Read(&buf)) {
    RTC_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) {
    RTC_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) {
    RTC_LOG(INFO) << "Data indication has no source address";
    return;
  } else if (addr_attr->family() != 1) {
    RTC_LOG(INFO) << "Source address has bad family";
    return;
  }

  rtc::SocketAddress remote_addr2(addr_attr->ipaddr(), addr_attr->port());

  const StunByteStringAttribute* data_attr = msg.GetByteString(STUN_ATTR_DATA);
  if (!data_attr) {
    RTC_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,
                      PROTO_UDP, packet_time_us);
}

void RelayEntry::OnSentPacket(rtc::AsyncPacketSocket* socket,
                              const rtc::SentPacket& sent_packet) {
  port_->OnSentPacket(socket, sent_packet);
}

void RelayEntry::OnReadyToSend(rtc::AsyncPacketSocket* socket) {
  if (connected()) {
    port_->OnReadyToSend();
  }
}

int RelayEntry::SendPacket(const void* data,
                           size_t size,
                           const rtc::PacketOptions& options) {
  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, options);
  }
  return sent;
}

AllocateRequest::AllocateRequest(RelayEntry* entry, RelayConnection* connection)
    : StunRequest(new RelayMessage()), entry_(entry), connection_(connection) {
  start_time_ = rtc::TimeMillis();
}

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

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

void AllocateRequest::OnSent() {
  count_ += 1;
  if (count_ == 5)
    timeout_ = true;
}

int AllocateRequest::resend_delay() {
  if (count_ == 0) {
    return 0;
  }
  return 100 * std::max(1 << (count_ - 1), 2);
}

void AllocateRequest::OnResponse(StunMessage* response) {
  const StunAddressAttribute* addr_attr =
      response->GetAddress(STUN_ATTR_MAPPED_ADDRESS);
  if (!addr_attr) {
    RTC_LOG(INFO) << "Allocate response missing mapped address.";
  } else if (addr_attr->family() != 1) {
    RTC_LOG(INFO) << "Mapped address has bad family";
  } else {
    rtc::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) {
    RTC_LOG(LS_ERROR) << "Missing allocate response error code.";
  } else {
    RTC_LOG(INFO) << "Allocate error response: code=" << attr->code()
                  << " reason=" << attr->reason();
  }

  if (rtc::TimeMillis() - start_time_ <= kRetryTimeout)
    entry_->ScheduleKeepAlive();
}

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

}  // namespace cricket
