/*
 *  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 "webrtc/p2p/base/relayserver.h"

#ifdef WEBRTC_POSIX
#include <errno.h>
#endif  // WEBRTC_POSIX

#include <algorithm>

#include "webrtc/base/asynctcpsocket.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/socketadapters.h"

namespace cricket {

// By default, we require a ping every 90 seconds.
const int MAX_LIFETIME = 15 * 60 * 1000;

// The number of bytes in each of the usernames we use.
const uint32_t USERNAME_LENGTH = 16;

// Calls SendTo on the given socket and logs any bad results.
void Send(rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
          const rtc::SocketAddress& addr) {
  rtc::PacketOptions options;
  int result = socket->SendTo(bytes, size, addr, options);
  if (result < static_cast<int>(size)) {
    LOG(LS_ERROR) << "SendTo wrote only " << result << " of " << size
                  << " bytes";
  } else if (result < 0) {
    LOG_ERR(LS_ERROR) << "SendTo";
  }
}

// Sends the given STUN message on the given socket.
void SendStun(const StunMessage& msg,
              rtc::AsyncPacketSocket* socket,
              const rtc::SocketAddress& addr) {
  rtc::ByteBufferWriter buf;
  msg.Write(&buf);
  Send(socket, buf.Data(), buf.Length(), addr);
}

// Constructs a STUN error response and sends it on the given socket.
void SendStunError(const StunMessage& msg, rtc::AsyncPacketSocket* socket,
                   const rtc::SocketAddress& remote_addr, int error_code,
                   const char* error_desc, const std::string& magic_cookie) {
  RelayMessage err_msg;
  err_msg.SetType(GetStunErrorResponseType(msg.type()));
  err_msg.SetTransactionID(msg.transaction_id());

  auto magic_cookie_attr =
      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
  if (magic_cookie.size() == 0) {
    magic_cookie_attr->CopyBytes(cricket::TURN_MAGIC_COOKIE_VALUE,
                                 sizeof(cricket::TURN_MAGIC_COOKIE_VALUE));
  } else {
    magic_cookie_attr->CopyBytes(magic_cookie.c_str(), magic_cookie.size());
  }
  err_msg.AddAttribute(std::move(magic_cookie_attr));

  auto err_code = StunAttribute::CreateErrorCode();
  err_code->SetClass(error_code / 100);
  err_code->SetNumber(error_code % 100);
  err_code->SetReason(error_desc);
  err_msg.AddAttribute(std::move(err_code));

  SendStun(err_msg, socket, remote_addr);
}

RelayServer::RelayServer(rtc::Thread* thread)
  : thread_(thread), log_bindings_(true) {
}

RelayServer::~RelayServer() {
  // Deleting the binding will cause it to be removed from the map.
  while (!bindings_.empty())
    delete bindings_.begin()->second;
  for (size_t i = 0; i < internal_sockets_.size(); ++i)
    delete internal_sockets_[i];
  for (size_t i = 0; i < external_sockets_.size(); ++i)
    delete external_sockets_[i];
  for (size_t i = 0; i < removed_sockets_.size(); ++i)
    delete removed_sockets_[i];
  while (!server_sockets_.empty()) {
    rtc::AsyncSocket* socket = server_sockets_.begin()->first;
    server_sockets_.erase(server_sockets_.begin()->first);
    delete socket;
  }
}

void RelayServer::AddInternalSocket(rtc::AsyncPacketSocket* socket) {
  RTC_DCHECK(internal_sockets_.end() == std::find(internal_sockets_.begin(),
                                                  internal_sockets_.end(),
                                                  socket));
  internal_sockets_.push_back(socket);
  socket->SignalReadPacket.connect(this, &RelayServer::OnInternalPacket);
}

void RelayServer::RemoveInternalSocket(rtc::AsyncPacketSocket* socket) {
  SocketList::iterator iter =
      std::find(internal_sockets_.begin(), internal_sockets_.end(), socket);
  RTC_DCHECK(iter != internal_sockets_.end());
  internal_sockets_.erase(iter);
  removed_sockets_.push_back(socket);
  socket->SignalReadPacket.disconnect(this);
}

void RelayServer::AddExternalSocket(rtc::AsyncPacketSocket* socket) {
  RTC_DCHECK(external_sockets_.end() == std::find(external_sockets_.begin(),
                                                  external_sockets_.end(),
                                                  socket));
  external_sockets_.push_back(socket);
  socket->SignalReadPacket.connect(this, &RelayServer::OnExternalPacket);
}

void RelayServer::RemoveExternalSocket(rtc::AsyncPacketSocket* socket) {
  SocketList::iterator iter =
      std::find(external_sockets_.begin(), external_sockets_.end(), socket);
  RTC_DCHECK(iter != external_sockets_.end());
  external_sockets_.erase(iter);
  removed_sockets_.push_back(socket);
  socket->SignalReadPacket.disconnect(this);
}

void RelayServer::AddInternalServerSocket(rtc::AsyncSocket* socket,
                                          cricket::ProtocolType proto) {
  RTC_DCHECK(server_sockets_.end() == server_sockets_.find(socket));
  server_sockets_[socket] = proto;
  socket->SignalReadEvent.connect(this, &RelayServer::OnReadEvent);
}

void RelayServer::RemoveInternalServerSocket(
    rtc::AsyncSocket* socket) {
  ServerSocketMap::iterator iter = server_sockets_.find(socket);
  RTC_DCHECK(iter != server_sockets_.end());
  server_sockets_.erase(iter);
  socket->SignalReadEvent.disconnect(this);
}

int RelayServer::GetConnectionCount() const {
  return static_cast<int>(connections_.size());
}

rtc::SocketAddressPair RelayServer::GetConnection(int connection) const {
  int i = 0;
  for (ConnectionMap::const_iterator it = connections_.begin();
       it != connections_.end(); ++it) {
    if (i == connection) {
      return it->second->addr_pair();
    }
    ++i;
  }
  return rtc::SocketAddressPair();
}

bool RelayServer::HasConnection(const rtc::SocketAddress& address) const {
  for (ConnectionMap::const_iterator it = connections_.begin();
       it != connections_.end(); ++it) {
    if (it->second->addr_pair().destination() == address) {
      return true;
    }
  }
  return false;
}

void RelayServer::OnReadEvent(rtc::AsyncSocket* socket) {
  RTC_DCHECK(server_sockets_.find(socket) != server_sockets_.end());
  AcceptConnection(socket);
}

void RelayServer::OnInternalPacket(
    rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
    const rtc::SocketAddress& remote_addr,
    const rtc::PacketTime& packet_time) {

  // Get the address of the connection we just received on.
  rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
  RTC_DCHECK(!ap.destination().IsNil());

  // If this did not come from an existing connection, it should be a STUN
  // allocate request.
  ConnectionMap::iterator piter = connections_.find(ap);
  if (piter == connections_.end()) {
    HandleStunAllocate(bytes, size, ap, socket);
    return;
  }

  RelayServerConnection* int_conn = piter->second;

  // Handle STUN requests to the server itself.
  if (int_conn->binding()->HasMagicCookie(bytes, size)) {
    HandleStun(int_conn, bytes, size);
    return;
  }

  // Otherwise, this is a non-wrapped packet that we are to forward.  Make sure
  // that this connection has been locked.  (Otherwise, we would not know what
  // address to forward to.)
  if (!int_conn->locked()) {
    LOG(LS_WARNING) << "Dropping packet: connection not locked";
    return;
  }

  // Forward this to the destination address into the connection.
  RelayServerConnection* ext_conn = int_conn->binding()->GetExternalConnection(
      int_conn->default_destination());
  if (ext_conn && ext_conn->locked()) {
    // TODO: Check the HMAC.
    ext_conn->Send(bytes, size);
  } else {
    // This happens very often and is not an error.
    LOG(LS_INFO) << "Dropping packet: no external connection";
  }
}

void RelayServer::OnExternalPacket(
    rtc::AsyncPacketSocket* socket, const char* bytes, size_t size,
    const rtc::SocketAddress& remote_addr,
    const rtc::PacketTime& packet_time) {

  // Get the address of the connection we just received on.
  rtc::SocketAddressPair ap(remote_addr, socket->GetLocalAddress());
  RTC_DCHECK(!ap.destination().IsNil());

  // If this connection already exists, then forward the traffic.
  ConnectionMap::iterator piter = connections_.find(ap);
  if (piter != connections_.end()) {
    // TODO: Check the HMAC.
    RelayServerConnection* ext_conn = piter->second;
    RelayServerConnection* int_conn =
        ext_conn->binding()->GetInternalConnection(
            ext_conn->addr_pair().source());
    RTC_DCHECK(int_conn != NULL);
    int_conn->Send(bytes, size, ext_conn->addr_pair().source());
    ext_conn->Lock();  // allow outgoing packets
    return;
  }

  // The first packet should always be a STUN / TURN packet.  If it isn't, then
  // we should just ignore this packet.
  RelayMessage msg;
  rtc::ByteBufferReader buf(bytes, size);
  if (!msg.Read(&buf)) {
    LOG(LS_WARNING) << "Dropping packet: first packet not STUN";
    return;
  }

  // The initial packet should have a username (which identifies the binding).
  const StunByteStringAttribute* username_attr =
      msg.GetByteString(STUN_ATTR_USERNAME);
  if (!username_attr) {
    LOG(LS_WARNING) << "Dropping packet: no username";
    return;
  }

  uint32_t length =
      std::min(static_cast<uint32_t>(username_attr->length()), USERNAME_LENGTH);
  std::string username(username_attr->bytes(), length);
  // TODO: Check the HMAC.

  // The binding should already be present.
  BindingMap::iterator biter = bindings_.find(username);
  if (biter == bindings_.end()) {
    LOG(LS_WARNING) << "Dropping packet: no binding with username";
    return;
  }

  // Add this authenticted connection to the binding.
  RelayServerConnection* ext_conn =
      new RelayServerConnection(biter->second, ap, socket);
  ext_conn->binding()->AddExternalConnection(ext_conn);
  AddConnection(ext_conn);

  // We always know where external packets should be forwarded, so we can lock
  // them from the beginning.
  ext_conn->Lock();

  // Send this message on the appropriate internal connection.
  RelayServerConnection* int_conn = ext_conn->binding()->GetInternalConnection(
      ext_conn->addr_pair().source());
  RTC_DCHECK(int_conn != NULL);
  int_conn->Send(bytes, size, ext_conn->addr_pair().source());
}

bool RelayServer::HandleStun(
    const char* bytes, size_t size, const rtc::SocketAddress& remote_addr,
    rtc::AsyncPacketSocket* socket, std::string* username,
    StunMessage* msg) {

  // Parse this into a stun message. Eat the message if this fails.
  rtc::ByteBufferReader buf(bytes, size);
  if (!msg->Read(&buf)) {
    return false;
  }

  // The initial packet should have a username (which identifies the binding).
  const StunByteStringAttribute* username_attr =
      msg->GetByteString(STUN_ATTR_USERNAME);
  if (!username_attr) {
    SendStunError(*msg, socket, remote_addr, 432, "Missing Username", "");
    return false;
  }

  // Record the username if requested.
  if (username)
    username->append(username_attr->bytes(), username_attr->length());

  // TODO: Check for unknown attributes (<= 0x7fff)

  return true;
}

void RelayServer::HandleStunAllocate(
    const char* bytes, size_t size, const rtc::SocketAddressPair& ap,
    rtc::AsyncPacketSocket* socket) {

  // Make sure this is a valid STUN request.
  RelayMessage request;
  std::string username;
  if (!HandleStun(bytes, size, ap.source(), socket, &username, &request))
    return;

  // Make sure this is a an allocate request.
  if (request.type() != STUN_ALLOCATE_REQUEST) {
    SendStunError(request,
                  socket,
                  ap.source(),
                  600,
                  "Operation Not Supported",
                  "");
    return;
  }

  // TODO: Check the HMAC.

  // Find or create the binding for this username.

  RelayServerBinding* binding;

  BindingMap::iterator biter = bindings_.find(username);
  if (biter != bindings_.end()) {
    binding = biter->second;
  } else {
    // NOTE: In the future, bindings will be created by the bot only.  This
    //       else-branch will then disappear.

    // Compute the appropriate lifetime for this binding.
    int lifetime = MAX_LIFETIME;
    const StunUInt32Attribute* lifetime_attr =
        request.GetUInt32(STUN_ATTR_LIFETIME);
    if (lifetime_attr)
      lifetime =
          std::min(lifetime, static_cast<int>(lifetime_attr->value() * 1000));

    binding = new RelayServerBinding(this, username, "0", lifetime);
    binding->SignalTimeout.connect(this, &RelayServer::OnTimeout);
    bindings_[username] = binding;

    if (log_bindings_) {
      LOG(LS_INFO) << "Added new binding " << username << ", "
                   << bindings_.size() << " total";
    }
  }

  // Add this connection to the binding.  It starts out unlocked.
  RelayServerConnection* int_conn =
      new RelayServerConnection(binding, ap, socket);
  binding->AddInternalConnection(int_conn);
  AddConnection(int_conn);

  // Now that we have a connection, this other method takes over.
  HandleStunAllocate(int_conn, request);
}

void RelayServer::HandleStun(
    RelayServerConnection* int_conn, const char* bytes, size_t size) {

  // Make sure this is a valid STUN request.
  RelayMessage request;
  std::string username;
  if (!HandleStun(bytes, size, int_conn->addr_pair().source(),
                  int_conn->socket(), &username, &request))
    return;

  // Make sure the username is the one were were expecting.
  if (username != int_conn->binding()->username()) {
    int_conn->SendStunError(request, 430, "Stale Credentials");
    return;
  }

  // TODO: Check the HMAC.

  // Send this request to the appropriate handler.
  if (request.type() == STUN_SEND_REQUEST)
    HandleStunSend(int_conn, request);
  else if (request.type() == STUN_ALLOCATE_REQUEST)
    HandleStunAllocate(int_conn, request);
  else
    int_conn->SendStunError(request, 600, "Operation Not Supported");
}

void RelayServer::HandleStunAllocate(
    RelayServerConnection* int_conn, const StunMessage& request) {

  // Create a response message that includes an address with which external
  // clients can communicate.

  RelayMessage response;
  response.SetType(STUN_ALLOCATE_RESPONSE);
  response.SetTransactionID(request.transaction_id());

  auto magic_cookie_attr =
      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
  magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
                               int_conn->binding()->magic_cookie().size());
  response.AddAttribute(std::move(magic_cookie_attr));

  size_t index = rand() % external_sockets_.size();
  rtc::SocketAddress ext_addr =
      external_sockets_[index]->GetLocalAddress();

  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_MAPPED_ADDRESS);
  addr_attr->SetIP(ext_addr.ipaddr());
  addr_attr->SetPort(ext_addr.port());
  response.AddAttribute(std::move(addr_attr));

  auto res_lifetime_attr = StunAttribute::CreateUInt32(STUN_ATTR_LIFETIME);
  res_lifetime_attr->SetValue(int_conn->binding()->lifetime() / 1000);
  response.AddAttribute(std::move(res_lifetime_attr));

  // TODO: Support transport-prefs (preallocate RTCP port).
  // TODO: Support bandwidth restrictions.
  // TODO: Add message integrity check.

  // Send a response to the caller.
  int_conn->SendStun(response);
}

void RelayServer::HandleStunSend(
    RelayServerConnection* int_conn, const StunMessage& request) {

  const StunAddressAttribute* addr_attr =
      request.GetAddress(STUN_ATTR_DESTINATION_ADDRESS);
  if (!addr_attr) {
    int_conn->SendStunError(request, 400, "Bad Request");
    return;
  }

  const StunByteStringAttribute* data_attr =
      request.GetByteString(STUN_ATTR_DATA);
  if (!data_attr) {
    int_conn->SendStunError(request, 400, "Bad Request");
    return;
  }

  rtc::SocketAddress ext_addr(addr_attr->ipaddr(), addr_attr->port());
  RelayServerConnection* ext_conn =
      int_conn->binding()->GetExternalConnection(ext_addr);
  if (!ext_conn) {
    // Create a new connection to establish the relationship with this binding.
    RTC_DCHECK(external_sockets_.size() == 1);
    rtc::AsyncPacketSocket* socket = external_sockets_[0];
    rtc::SocketAddressPair ap(ext_addr, socket->GetLocalAddress());
    ext_conn = new RelayServerConnection(int_conn->binding(), ap, socket);
    ext_conn->binding()->AddExternalConnection(ext_conn);
    AddConnection(ext_conn);
  }

  // If this connection has pinged us, then allow outgoing traffic.
  if (ext_conn->locked())
    ext_conn->Send(data_attr->bytes(), data_attr->length());

  const StunUInt32Attribute* options_attr =
      request.GetUInt32(STUN_ATTR_OPTIONS);
  if (options_attr && (options_attr->value() & 0x01)) {
    int_conn->set_default_destination(ext_addr);
    int_conn->Lock();

    RelayMessage response;
    response.SetType(STUN_SEND_RESPONSE);
    response.SetTransactionID(request.transaction_id());

    auto magic_cookie_attr =
        StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
    magic_cookie_attr->CopyBytes(int_conn->binding()->magic_cookie().c_str(),
                                 int_conn->binding()->magic_cookie().size());
    response.AddAttribute(std::move(magic_cookie_attr));

    auto options2_attr =
        StunAttribute::CreateUInt32(cricket::STUN_ATTR_OPTIONS);
    options2_attr->SetValue(0x01);
    response.AddAttribute(std::move(options2_attr));

    int_conn->SendStun(response);
  }
}

void RelayServer::AddConnection(RelayServerConnection* conn) {
  RTC_DCHECK(connections_.find(conn->addr_pair()) == connections_.end());
  connections_[conn->addr_pair()] = conn;
}

void RelayServer::RemoveConnection(RelayServerConnection* conn) {
  ConnectionMap::iterator iter = connections_.find(conn->addr_pair());
  RTC_DCHECK(iter != connections_.end());
  connections_.erase(iter);
}

void RelayServer::RemoveBinding(RelayServerBinding* binding) {
  BindingMap::iterator iter = bindings_.find(binding->username());
  RTC_DCHECK(iter != bindings_.end());
  bindings_.erase(iter);

  if (log_bindings_) {
    LOG(LS_INFO) << "Removed binding " << binding->username() << ", "
                 << bindings_.size() << " remaining";
  }
}

void RelayServer::OnMessage(rtc::Message *pmsg) {
  static const uint32_t kMessageAcceptConnection = 1;
  RTC_DCHECK(pmsg->message_id == kMessageAcceptConnection);

  rtc::MessageData* data = pmsg->pdata;
  rtc::AsyncSocket* socket =
      static_cast <rtc::TypedMessageData<rtc::AsyncSocket*>*>
      (data)->data();
  AcceptConnection(socket);
  delete data;
}

void RelayServer::OnTimeout(RelayServerBinding* binding) {
  // This call will result in all of the necessary clean-up. We can't call
  // delete here, because you can't delete an object that is signaling you.
  thread_->Dispose(binding);
}

void RelayServer::AcceptConnection(rtc::AsyncSocket* server_socket) {
  // Check if someone is trying to connect to us.
  rtc::SocketAddress accept_addr;
  rtc::AsyncSocket* accepted_socket =
      server_socket->Accept(&accept_addr);
  if (accepted_socket != NULL) {
    // We had someone trying to connect, now check which protocol to
    // use and create a packet socket.
    RTC_DCHECK(server_sockets_[server_socket] == cricket::PROTO_TCP ||
               server_sockets_[server_socket] == cricket::PROTO_SSLTCP);
    if (server_sockets_[server_socket] == cricket::PROTO_SSLTCP) {
      accepted_socket = new rtc::AsyncSSLServerSocket(accepted_socket);
    }
    rtc::AsyncTCPSocket* tcp_socket =
        new rtc::AsyncTCPSocket(accepted_socket, false);

    // Finally add the socket so it can start communicating with the client.
    AddInternalSocket(tcp_socket);
  }
}

RelayServerConnection::RelayServerConnection(
    RelayServerBinding* binding, const rtc::SocketAddressPair& addrs,
    rtc::AsyncPacketSocket* socket)
  : binding_(binding), addr_pair_(addrs), socket_(socket), locked_(false) {
  // The creation of a new connection constitutes a use of the binding.
  binding_->NoteUsed();
}

RelayServerConnection::~RelayServerConnection() {
  // Remove this connection from the server's map (if it exists there).
  binding_->server()->RemoveConnection(this);
}

void RelayServerConnection::Send(const char* data, size_t size) {
  // Note that the binding has been used again.
  binding_->NoteUsed();

  cricket::Send(socket_, data, size, addr_pair_.source());
}

void RelayServerConnection::Send(
    const char* data, size_t size, const rtc::SocketAddress& from_addr) {
  // If the from address is known to the client, we don't need to send it.
  if (locked() && (from_addr == default_dest_)) {
    Send(data, size);
    return;
  }

  // Wrap the given data in a data-indication packet.

  RelayMessage msg;
  msg.SetType(STUN_DATA_INDICATION);

  auto magic_cookie_attr =
      StunAttribute::CreateByteString(cricket::STUN_ATTR_MAGIC_COOKIE);
  magic_cookie_attr->CopyBytes(binding_->magic_cookie().c_str(),
                               binding_->magic_cookie().size());
  msg.AddAttribute(std::move(magic_cookie_attr));

  auto addr_attr = StunAttribute::CreateAddress(STUN_ATTR_SOURCE_ADDRESS2);
  addr_attr->SetIP(from_addr.ipaddr());
  addr_attr->SetPort(from_addr.port());
  msg.AddAttribute(std::move(addr_attr));

  auto data_attr = StunAttribute::CreateByteString(STUN_ATTR_DATA);
  RTC_DCHECK(size <= 65536);
  data_attr->CopyBytes(data, uint16_t(size));
  msg.AddAttribute(std::move(data_attr));

  SendStun(msg);
}

void RelayServerConnection::SendStun(const StunMessage& msg) {
  // Note that the binding has been used again.
  binding_->NoteUsed();

  cricket::SendStun(msg, socket_, addr_pair_.source());
}

void RelayServerConnection::SendStunError(
      const StunMessage& request, int error_code, const char* error_desc) {
  // An error does not indicate use.  If no legitimate use off the binding
  // occurs, we want it to be cleaned up even if errors are still occuring.

  cricket::SendStunError(
      request, socket_, addr_pair_.source(), error_code, error_desc,
      binding_->magic_cookie());
}

void RelayServerConnection::Lock() {
  locked_ = true;
}

void RelayServerConnection::Unlock() {
  locked_ = false;
}

// IDs used for posted messages:
const uint32_t MSG_LIFETIME_TIMER = 1;

RelayServerBinding::RelayServerBinding(RelayServer* server,
                                       const std::string& username,
                                       const std::string& password,
                                       int lifetime)
    : server_(server),
      username_(username),
      password_(password),
      lifetime_(lifetime) {
  // For now, every connection uses the standard magic cookie value.
  magic_cookie_.append(
      reinterpret_cast<const char*>(TURN_MAGIC_COOKIE_VALUE),
      sizeof(TURN_MAGIC_COOKIE_VALUE));

  // Initialize the last-used time to now.
  NoteUsed();

  // Set the first timeout check.
  server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this,
                                 MSG_LIFETIME_TIMER);
}

RelayServerBinding::~RelayServerBinding() {
  // Clear the outstanding timeout check.
  server_->thread()->Clear(this);

  // Clean up all of the connections.
  for (size_t i = 0; i < internal_connections_.size(); ++i)
    delete internal_connections_[i];
  for (size_t i = 0; i < external_connections_.size(); ++i)
    delete external_connections_[i];

  // Remove this binding from the server's map.
  server_->RemoveBinding(this);
}

void RelayServerBinding::AddInternalConnection(RelayServerConnection* conn) {
  internal_connections_.push_back(conn);
}

void RelayServerBinding::AddExternalConnection(RelayServerConnection* conn) {
  external_connections_.push_back(conn);
}

void RelayServerBinding::NoteUsed() {
  last_used_ = rtc::TimeMillis();
}

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

RelayServerConnection* RelayServerBinding::GetInternalConnection(
    const rtc::SocketAddress& ext_addr) {

  // Look for an internal connection that is locked to this address.
  for (size_t i = 0; i < internal_connections_.size(); ++i) {
    if (internal_connections_[i]->locked() &&
        (ext_addr == internal_connections_[i]->default_destination()))
      return internal_connections_[i];
  }

  // If one was not found, we send to the first connection.
  RTC_DCHECK(internal_connections_.size() > 0);
  return internal_connections_[0];
}

RelayServerConnection* RelayServerBinding::GetExternalConnection(
    const rtc::SocketAddress& ext_addr) {
  for (size_t i = 0; i < external_connections_.size(); ++i) {
    if (ext_addr == external_connections_[i]->addr_pair().source())
      return external_connections_[i];
  }
  return 0;
}

void RelayServerBinding::OnMessage(rtc::Message *pmsg) {
  if (pmsg->message_id == MSG_LIFETIME_TIMER) {
    RTC_DCHECK(!pmsg->pdata);

    // If the lifetime timeout has been exceeded, then send a signal.
    // Otherwise, just keep waiting.
    if (rtc::TimeMillis() >= last_used_ + lifetime_) {
      LOG(LS_INFO) << "Expiring binding " << username_;
      SignalTimeout(this);
    } else {
      server_->thread()->PostDelayed(RTC_FROM_HERE, lifetime_, this,
                                     MSG_LIFETIME_TIMER);
    }

  } else {
    RTC_NOTREACHED();
  }
}

}  // namespace cricket
