/*
 * 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 <string>
#include <vector>

#include "talk/base/basicpacketsocketfactory.h"
#include "talk/base/common.h"
#include "talk/base/helpers.h"
#include "talk/base/host.h"
#include "talk/base/logging.h"
#include "talk/p2p/client/basicportallocator.h"
#include "talk/p2p/base/common.h"
#include "talk/p2p/base/port.h"
#include "talk/p2p/base/relayport.h"
#include "talk/p2p/base/stunport.h"
#include "talk/p2p/base/tcpport.h"
#include "talk/p2p/base/udpport.h"

using talk_base::CreateRandomId;
using talk_base::CreateRandomString;

namespace {

const uint32 MSG_CONFIG_START = 1;
const uint32 MSG_CONFIG_READY = 2;
const uint32 MSG_ALLOCATE = 3;
const uint32 MSG_ALLOCATION_PHASE = 4;
const uint32 MSG_SHAKE = 5;

const uint32 ALLOCATE_DELAY = 250;
const uint32 ALLOCATION_STEP_DELAY = 1 * 1000;

const int PHASE_UDP = 0;
const int PHASE_RELAY = 1;
const int PHASE_TCP = 2;
const int PHASE_SSLTCP = 3;
const int kNumPhases = 4;

const float PREF_LOCAL_UDP = 1.0f;
const float PREF_LOCAL_STUN = 0.9f;
const float PREF_LOCAL_TCP = 0.8f;
const float PREF_RELAY = 0.5f;

// Modifiers of the above constants
const float RELAY_PRIMARY_PREF_MODIFIER = 0.0f;
const float RELAY_BACKUP_PREF_MODIFIER = -0.2f;

// Returns the phase in which a given local candidate (or rather, the port that
// gave rise to that local candidate) would have been created.
int LocalCandidateToPhase(const cricket::Candidate& candidate) {
  cricket::ProtocolType proto;
  bool result = cricket::StringToProto(candidate.protocol().c_str(), &proto);
  if (result) {
    if (candidate.type() == cricket::LOCAL_PORT_TYPE) {
      switch (proto) {
      case cricket::PROTO_UDP: return PHASE_UDP;
      case cricket::PROTO_TCP: return PHASE_TCP;
      default: ASSERT(false);
      }
    } else if (candidate.type() == cricket::STUN_PORT_TYPE) {
      return PHASE_UDP;
    } else if (candidate.type() == cricket::RELAY_PORT_TYPE) {
      switch (proto) {
      case cricket::PROTO_UDP: return PHASE_RELAY;
      case cricket::PROTO_TCP: return PHASE_TCP;
      case cricket::PROTO_SSLTCP: return PHASE_SSLTCP;
      default: ASSERT(false);
      }
    } else {
      ASSERT(false);
    }
  } else {
    ASSERT(false);
  }
  return PHASE_UDP;  // reached only with assert failure
}

const int SHAKE_MIN_DELAY = 45 * 1000;  // 45 seconds
const int SHAKE_MAX_DELAY = 90 * 1000;  // 90 seconds

int ShakeDelay() {
  int range = SHAKE_MAX_DELAY - SHAKE_MIN_DELAY + 1;
  return SHAKE_MIN_DELAY + CreateRandomId() % range;
}

}  // namespace

namespace cricket {

const uint32 DISABLE_ALL_PHASES =
  PORTALLOCATOR_DISABLE_UDP
  | PORTALLOCATOR_DISABLE_TCP
  | PORTALLOCATOR_DISABLE_STUN
  | PORTALLOCATOR_DISABLE_RELAY;

// Performs the allocation of ports, in a sequenced (timed) manner, for a given
// network and IP address.
class AllocationSequence : public talk_base::MessageHandler {
 public:
  AllocationSequence(BasicPortAllocatorSession* session,
                     talk_base::Network* network,
                     PortConfiguration* config,
                     uint32 flags);
  ~AllocationSequence();

  // Disables the phases for a new sequence that this one already covers for an
  // equivalent network setup.
  void DisableEquivalentPhases(talk_base::Network* network,
      PortConfiguration* config, uint32* flags);

  // Starts and stops the sequence.  When started, it will continue allocating
  // new ports on its own timed schedule.
  void Start();
  void Stop();

  // MessageHandler
  void OnMessage(talk_base::Message* msg);

  void EnableProtocol(ProtocolType proto);
  bool ProtocolEnabled(ProtocolType proto) const;

 private:
  typedef std::vector<ProtocolType> ProtocolList;

  void CreateUDPPorts();
  void CreateTCPPorts();
  void CreateStunPorts();
  void CreateRelayPorts();

  BasicPortAllocatorSession* session_;
  talk_base::Network* network_;
  talk_base::IPAddress ip_;
  PortConfiguration* config_;
  bool running_;
  int step_;
  int step_of_phase_[kNumPhases];
  uint32 flags_;
  ProtocolList protocols_;
};


// BasicPortAllocator
BasicPortAllocator::BasicPortAllocator(
    talk_base::NetworkManager* network_manager,
    talk_base::PacketSocketFactory* socket_factory)
    : network_manager_(network_manager),
      socket_factory_(socket_factory) {
  ASSERT(socket_factory_ != NULL);
  Construct();
}

BasicPortAllocator::BasicPortAllocator(
    talk_base::NetworkManager* network_manager)
    : network_manager_(network_manager),
      socket_factory_(NULL) {
  Construct();
}

BasicPortAllocator::BasicPortAllocator(
    talk_base::NetworkManager* network_manager,
    const talk_base::SocketAddress& stun_address,
    const talk_base::SocketAddress& relay_address_udp,
    const talk_base::SocketAddress& relay_address_tcp,
    const talk_base::SocketAddress& relay_address_ssl)
    : network_manager_(network_manager),
      socket_factory_(NULL),
      stun_address_(stun_address),
      relay_address_udp_(relay_address_udp),
      relay_address_tcp_(relay_address_tcp),
      relay_address_ssl_(relay_address_ssl) {
  Construct();
}

void BasicPortAllocator::Construct() {
  best_writable_phase_ = -1;
  allow_tcp_listen_ = true;
}

BasicPortAllocator::~BasicPortAllocator() {
}

int BasicPortAllocator::best_writable_phase() const {
  // If we are configured with an HTTP proxy, the best bet is to use the relay
  if ((best_writable_phase_ == -1)
      && ((proxy().type == talk_base::PROXY_HTTPS)
          || (proxy().type == talk_base::PROXY_UNKNOWN))) {
    return PHASE_RELAY;
  }
  return best_writable_phase_;
}

PortAllocatorSession *BasicPortAllocator::CreateSession(
    const std::string &name, const std::string &session_type) {
  return new BasicPortAllocatorSession(this, name, session_type);
}

void BasicPortAllocator::AddWritablePhase(int phase) {
  if ((best_writable_phase_ == -1) || (phase < best_writable_phase_))
    best_writable_phase_ = phase;
}

// BasicPortAllocatorSession
BasicPortAllocatorSession::BasicPortAllocatorSession(
    BasicPortAllocator *allocator,
    const std::string &name,
    const std::string &session_type)
    : PortAllocatorSession(name, session_type, allocator->flags()),
      allocator_(allocator), network_thread_(NULL),
      socket_factory_(allocator->socket_factory()), allocation_started_(false),
      network_manager_started_(false),
      running_(false) {
  allocator_->network_manager()->SignalNetworksChanged.connect(
      this, &BasicPortAllocatorSession::OnNetworksChanged);
  allocator_->network_manager()->StartUpdating();
}

BasicPortAllocatorSession::~BasicPortAllocatorSession() {
  if (network_thread_ != NULL)
    network_thread_->Clear(this);

  std::vector<PortData>::iterator it;
  for (it = ports_.begin(); it != ports_.end(); it++)
    delete it->port;

  for (uint32 i = 0; i < configs_.size(); ++i)
    delete configs_[i];

  for (uint32 i = 0; i < sequences_.size(); ++i)
    delete sequences_[i];
}

void BasicPortAllocatorSession::GetInitialPorts() {
  network_thread_ = talk_base::Thread::Current();
  if (!socket_factory_) {
    owned_socket_factory_.reset(
        new talk_base::BasicPacketSocketFactory(network_thread_));
    socket_factory_ = owned_socket_factory_.get();
  }

  network_thread_->Post(this, MSG_CONFIG_START);

  if (flags() & PORTALLOCATOR_ENABLE_SHAKER)
    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
}

void BasicPortAllocatorSession::StartGetAllPorts() {
  ASSERT(talk_base::Thread::Current() == network_thread_);
  running_ = true;
  if (allocation_started_)
    network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
  for (uint32 i = 0; i < sequences_.size(); ++i)
    sequences_[i]->Start();
  for (size_t i = 0; i < ports_.size(); ++i)
    ports_[i].port->Start();
}

void BasicPortAllocatorSession::StopGetAllPorts() {
  ASSERT(talk_base::Thread::Current() == network_thread_);
  running_ = false;
  network_thread_->Clear(this, MSG_ALLOCATE);
  for (uint32 i = 0; i < sequences_.size(); ++i)
    sequences_[i]->Stop();
}

void BasicPortAllocatorSession::OnMessage(talk_base::Message *message) {
  switch (message->message_id) {
  case MSG_CONFIG_START:
    ASSERT(talk_base::Thread::Current() == network_thread_);
    GetPortConfigurations();
    break;

  case MSG_CONFIG_READY:
    ASSERT(talk_base::Thread::Current() == network_thread_);
    OnConfigReady(static_cast<PortConfiguration*>(message->pdata));
    break;

  case MSG_ALLOCATE:
    ASSERT(talk_base::Thread::Current() == network_thread_);
    OnAllocate();
    break;

  case MSG_SHAKE:
    ASSERT(talk_base::Thread::Current() == network_thread_);
    OnShake();
    break;

  default:
    ASSERT(false);
  }
}

void BasicPortAllocatorSession::GetPortConfigurations() {
  PortConfiguration* config = new PortConfiguration(allocator_->stun_address(),
                                                    CreateRandomString(16),
                                                    CreateRandomString(16),
                                                    "");
  PortConfiguration::PortList ports;
  if (!allocator_->relay_address_udp().IsAny())
    ports.push_back(ProtocolAddress(
        allocator_->relay_address_udp(), PROTO_UDP));
  if (!allocator_->relay_address_tcp().IsAny())
    ports.push_back(ProtocolAddress(
        allocator_->relay_address_tcp(), PROTO_TCP));
  if (!allocator_->relay_address_ssl().IsAny())
    ports.push_back(ProtocolAddress(
        allocator_->relay_address_ssl(), PROTO_SSLTCP));
  config->AddRelay(ports, RELAY_PRIMARY_PREF_MODIFIER);

  ConfigReady(config);
}

void BasicPortAllocatorSession::ConfigReady(PortConfiguration* config) {
  network_thread_->Post(this, MSG_CONFIG_READY, config);
}

// Adds a configuration to the list.
void BasicPortAllocatorSession::OnConfigReady(PortConfiguration* config) {
  if (config)
    configs_.push_back(config);

  AllocatePorts();
}

void BasicPortAllocatorSession::AllocatePorts() {
  ASSERT(talk_base::Thread::Current() == network_thread_);
  network_thread_->Post(this, MSG_ALLOCATE);
}

void BasicPortAllocatorSession::OnAllocate() {
  if (network_manager_started_)
    DoAllocate();

  allocation_started_ = true;
  if (running_)
    network_thread_->PostDelayed(ALLOCATE_DELAY, this, MSG_ALLOCATE);
}

// For each network, see if we have a sequence that covers it already.  If not,
// create a new sequence to create the appropriate ports.
void BasicPortAllocatorSession::DoAllocate() {
  std::vector<talk_base::Network*> networks;
  allocator_->network_manager()->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_WARNING) << "Machine has no networks; no ports will be allocated";
  } else {
    for (uint32 i = 0; i < networks.size(); ++i) {
      PortConfiguration* config = NULL;
      if (configs_.size() > 0)
        config = configs_.back();

      uint32 sequence_flags = flags();

      // Disables phases that are not specified in this config.
      if (!config || config->stun_address.IsNil()) {
        // No STUN ports specified in this config.
        sequence_flags |= PORTALLOCATOR_DISABLE_STUN;
      }
      if (!config || config->relays.empty()) {
        // No relay ports specified in this config.
        sequence_flags |= PORTALLOCATOR_DISABLE_RELAY;
      }

      // Disable phases that would only create ports equivalent to
      // ones that we have already made.
      DisableEquivalentPhases(networks[i], config, &sequence_flags);

      if ((sequence_flags & DISABLE_ALL_PHASES) == DISABLE_ALL_PHASES) {
        // New AllocationSequence would have nothing to do, so don't make it.
        continue;
      }

      AllocationSequence* sequence =
          new AllocationSequence(this, networks[i], config, sequence_flags);
      if (running_)
        sequence->Start();

      sequences_.push_back(sequence);
    }
  }
}

void BasicPortAllocatorSession::OnNetworksChanged() {
  network_manager_started_ = true;
  if (allocation_started_)
    DoAllocate();
}

void BasicPortAllocatorSession::DisableEquivalentPhases(
    talk_base::Network* network, PortConfiguration* config, uint32* flags) {
  for (uint32 i = 0; i < sequences_.size() &&
      (*flags & DISABLE_ALL_PHASES) != DISABLE_ALL_PHASES; ++i) {
    sequences_[i]->DisableEquivalentPhases(network, config, flags);
  }
}

void BasicPortAllocatorSession::AddAllocatedPort(Port* port,
                                                 AllocationSequence * seq,
                                                 float pref,
                                                 bool prepare_address) {
  if (!port)
    return;

  port->set_name(name_);
  port->set_preference(pref);
  port->set_generation(generation());
  if (allocator_->proxy().type != talk_base::PROXY_NONE)
    port->set_proxy(allocator_->user_agent(), allocator_->proxy());

  PortData data;
  data.port = port;
  data.sequence = seq;
  data.ready = false;
  ports_.push_back(data);

  port->SignalAddressReady.connect(this,
      &BasicPortAllocatorSession::OnAddressReady);
  port->SignalConnectionCreated.connect(this,
      &BasicPortAllocatorSession::OnConnectionCreated);
  port->SignalDestroyed.connect(this,
      &BasicPortAllocatorSession::OnPortDestroyed);
  LOG_J(LS_INFO, port) << "Added port to allocator";

  if (prepare_address)
    port->PrepareAddress();
  if (running_)
    port->Start();
}

void BasicPortAllocatorSession::OnAddressReady(Port *port) {
  ASSERT(talk_base::Thread::Current() == network_thread_);
  std::vector<PortData>::iterator it
    = std::find(ports_.begin(), ports_.end(), port);
  ASSERT(it != ports_.end());
  if (it->ready)
    return;
  it->ready = true;
  SignalPortReady(this, port);

  // Only accumulate the candidates whose protocol has been enabled
  std::vector<Candidate> candidates;
  const std::vector<Candidate>& potentials = port->candidates();
  for (size_t i = 0; i < potentials.size(); ++i) {
    ProtocolType pvalue;
    if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
      continue;
    if (it->sequence->ProtocolEnabled(pvalue)) {
      candidates.push_back(potentials[i]);
    }
  }
  if (!candidates.empty()) {
    SignalCandidatesReady(this, candidates);
  }
}

void BasicPortAllocatorSession::OnProtocolEnabled(AllocationSequence * seq,
                                                  ProtocolType proto) {
  std::vector<Candidate> candidates;
  for (std::vector<PortData>::iterator it = ports_.begin();
       it != ports_.end(); ++it) {
    if (!it->ready || (it->sequence != seq))
      continue;

    const std::vector<Candidate>& potentials = it->port->candidates();
    for (size_t i = 0; i < potentials.size(); ++i) {
      ProtocolType pvalue;
      if (!StringToProto(potentials[i].protocol().c_str(), &pvalue))
        continue;
      if (pvalue == proto) {
        candidates.push_back(potentials[i]);
      }
    }
  }
  if (!candidates.empty()) {
    SignalCandidatesReady(this, candidates);
  }
}

void BasicPortAllocatorSession::OnPortDestroyed(Port* port) {
  ASSERT(talk_base::Thread::Current() == network_thread_);
  std::vector<PortData>::iterator iter =
      std::find(ports_.begin(), ports_.end(), port);
  ASSERT(iter != ports_.end());
  ports_.erase(iter);

  LOG_J(LS_INFO, port) << "Removed port from allocator ("
                       << static_cast<int>(ports_.size()) << " remaining)";
}

void BasicPortAllocatorSession::OnConnectionCreated(Port* port,
                                                    Connection* conn) {
  conn->SignalStateChange.connect(this,
    &BasicPortAllocatorSession::OnConnectionStateChange);
}

void BasicPortAllocatorSession::OnConnectionStateChange(Connection* conn) {
  if (conn->write_state() == Connection::STATE_WRITABLE)
    allocator_->AddWritablePhase(
      LocalCandidateToPhase(conn->local_candidate()));
}

void BasicPortAllocatorSession::OnShake() {
  LOG(INFO) << ">>>>> SHAKE <<<<< >>>>> SHAKE <<<<< >>>>> SHAKE <<<<<";

  std::vector<Port*> ports;
  std::vector<Connection*> connections;

  for (size_t i = 0; i < ports_.size(); ++i) {
    if (ports_[i].ready)
      ports.push_back(ports_[i].port);
  }

  for (size_t i = 0; i < ports.size(); ++i) {
    Port::AddressMap::const_iterator iter;
    for (iter = ports[i]->connections().begin();
         iter != ports[i]->connections().end();
         ++iter) {
      connections.push_back(iter->second);
    }
  }

  LOG(INFO) << ">>>>> Destroying " << ports.size() << " ports and "
            << connections.size() << " connections";

  for (size_t i = 0; i < connections.size(); ++i)
    connections[i]->Destroy();

  if (running_ || (ports.size() > 0) || (connections.size() > 0))
    network_thread_->PostDelayed(ShakeDelay(), this, MSG_SHAKE);
}

// AllocationSequence

AllocationSequence::AllocationSequence(BasicPortAllocatorSession* session,
                                       talk_base::Network* network,
                                       PortConfiguration* config,
                                       uint32 flags)
  : session_(session), network_(network), ip_(network->ip()), config_(config),
    running_(false), step_(0), flags_(flags) {
  // All of the phases up until the best-writable phase so far run in step 0.
  // The other phases follow sequentially in the steps after that.  If there is
  // no best-writable so far, then only phase 0 occurs in step 0.
  int last_phase_in_step_zero =
      talk_base::_max(0, session->allocator()->best_writable_phase());
  for (int phase = 0; phase < kNumPhases; ++phase)
    step_of_phase_[phase] = talk_base::_max(0, phase - last_phase_in_step_zero);

  // Immediately perform phase 0.
  OnMessage(NULL);
}

AllocationSequence::~AllocationSequence() {
  session_->network_thread()->Clear(this);
}

void AllocationSequence::DisableEquivalentPhases(talk_base::Network* network,
    PortConfiguration* config, uint32* flags) {
  if (!((network == network_) && (ip_ == network->ip()))) {
    // Different network setup; nothing is equivalent.
    return;
  }

  // Else turn off the stuff that we've already got covered.

  // Every config implicitly specifies local, so turn that off right away.
  *flags |= PORTALLOCATOR_DISABLE_UDP;
  *flags |= PORTALLOCATOR_DISABLE_TCP;

  if (config_ && config) {
    if (config_->stun_address == config->stun_address) {
      // Already got this STUN server covered.
      *flags |= PORTALLOCATOR_DISABLE_STUN;
    }
    if (!config_->relays.empty()) {
      // Already got relays covered.
      // NOTE: This will even skip a _different_ set of relay servers if we
      // were to be given one, but that never happens in our codebase. Should
      // probably get rid of the list in PortConfiguration and just keep a
      // single relay server in each one.
      *flags |= PORTALLOCATOR_DISABLE_RELAY;
    }
  }
}

void AllocationSequence::Start() {
  running_ = true;
  session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY,
                                          this,
                                          MSG_ALLOCATION_PHASE);
}

void AllocationSequence::Stop() {
  running_ = false;
  session_->network_thread()->Clear(this, MSG_ALLOCATION_PHASE);
}

void AllocationSequence::OnMessage(talk_base::Message* msg) {
  ASSERT(talk_base::Thread::Current() == session_->network_thread());
  if (msg)
    ASSERT(msg->message_id == MSG_ALLOCATION_PHASE);

  const char* const PHASE_NAMES[kNumPhases] = {
    "Udp", "Relay", "Tcp", "SslTcp"
  };

  // Perform all of the phases in the current step.
  for (int phase = 0; phase < kNumPhases; phase++) {
    if (step_of_phase_[phase] != step_)
      continue;

    LOG_J(LS_INFO, network_) << "Allocation Phase=" << PHASE_NAMES[phase]
                             << " (Step=" << step_ << ")";

    switch (phase) {
    case PHASE_UDP:
      CreateUDPPorts();
      CreateStunPorts();
      EnableProtocol(PROTO_UDP);
      break;

    case PHASE_RELAY:
      CreateRelayPorts();
      break;

    case PHASE_TCP:
      CreateTCPPorts();
      EnableProtocol(PROTO_TCP);
      break;

    case PHASE_SSLTCP:
      EnableProtocol(PROTO_SSLTCP);
      break;

    default:
      ASSERT(false);
    }
  }

  // TODO: use different delays for each stage
  step_ += 1;
  if (running_) {
    session_->network_thread()->PostDelayed(ALLOCATION_STEP_DELAY,
                                            this,
                                            MSG_ALLOCATION_PHASE);
  }
}

void AllocationSequence::EnableProtocol(ProtocolType proto) {
  if (!ProtocolEnabled(proto)) {
    protocols_.push_back(proto);
    session_->OnProtocolEnabled(this, proto);
  }
}

bool AllocationSequence::ProtocolEnabled(ProtocolType proto) const {
  for (ProtocolList::const_iterator it = protocols_.begin();
       it != protocols_.end(); ++it) {
    if (*it == proto)
      return true;
  }
  return false;
}

void AllocationSequence::CreateUDPPorts() {
  if (flags_ & PORTALLOCATOR_DISABLE_UDP) {
    LOG(LS_VERBOSE) << "AllocationSequence: UDP ports disabled, skipping.";
    return;
  }

  Port* port = UDPPort::Create(session_->network_thread(),
                               session_->socket_factory(),
                               network_, ip_,
                               session_->allocator()->min_port(),
                               session_->allocator()->max_port());
  if (port)
    session_->AddAllocatedPort(port, this, PREF_LOCAL_UDP);
}

void AllocationSequence::CreateTCPPorts() {
  if (flags_ & PORTALLOCATOR_DISABLE_TCP) {
    LOG(LS_VERBOSE) << "AllocationSequence: TCP ports disabled, skipping.";
    return;
  }

  Port* port = TCPPort::Create(session_->network_thread(),
                               session_->socket_factory(),
                               network_, ip_,
                               session_->allocator()->min_port(),
                               session_->allocator()->max_port(),
                               session_->allocator()->allow_tcp_listen());
  if (port)
    session_->AddAllocatedPort(port, this, PREF_LOCAL_TCP);
}

void AllocationSequence::CreateStunPorts() {
  if (flags_ & PORTALLOCATOR_DISABLE_STUN) {
    LOG(LS_VERBOSE) << "AllocationSequence: STUN ports disabled, skipping.";
    return;
  }

  // If BasicPortAllocatorSession::OnAllocate left STUN ports enabled then we
  // ought to have an address for them here.
  ASSERT(config_ && !config_->stun_address.IsNil());
  if (!(config_ && !config_->stun_address.IsNil())) {
    LOG(LS_WARNING)
        << "AllocationSequence: No STUN server configured, skipping.";
    return;
  }

  Port* port = StunPort::Create(session_->network_thread(),
                                session_->socket_factory(),
                                network_, ip_,
                                session_->allocator()->min_port(),
                                session_->allocator()->max_port(),
                                config_->stun_address);
  if (port)
    session_->AddAllocatedPort(port, this, PREF_LOCAL_STUN);
}

void AllocationSequence::CreateRelayPorts() {
  if (flags_ & PORTALLOCATOR_DISABLE_RELAY) {
     LOG(LS_VERBOSE) << "AllocationSequence: Relay ports disabled, skipping.";
     return;
  }

  // If BasicPortAllocatorSession::OnAllocate left relay ports enabled then we
  // ought to have a relay list for them here.
  ASSERT(config_ && !config_->relays.empty());
  if (!(config_ && !config_->relays.empty())) {
    LOG(LS_WARNING)
        << "AllocationSequence: No relay server configured, skipping.";
    return;
  }

  PortConfiguration::RelayList::const_iterator relay;
  for (relay = config_->relays.begin();
       relay != config_->relays.end(); ++relay) {
    RelayPort* port = RelayPort::Create(session_->network_thread(),
                                        session_->socket_factory(),
                                        network_, ip_,
                                        session_->allocator()->min_port(),
                                        session_->allocator()->max_port(),
                                        config_->username, config_->password,
                                        config_->magic_cookie);
    if (port) {
      // Note: We must add the allocated port before we add addresses because
      //       the latter will create candidates that need name and preference
      //       settings.  However, we also can't prepare the address (normally
      //       done by AddAllocatedPort) until we have these addresses.  So we
      //       wait to do that until below.
      session_->AddAllocatedPort(port, this, PREF_RELAY + relay->pref_modifier,
                                 false);

      // Add the addresses of this protocol.
      PortConfiguration::PortList::const_iterator relay_port;
      for (relay_port = relay->ports.begin();
            relay_port != relay->ports.end();
            ++relay_port) {
        port->AddServerAddress(*relay_port);
        port->AddExternalAddress(*relay_port);
      }

      // Start fetching an address for this port.
      port->PrepareAddress();
    }
  }
}

// PortConfiguration
PortConfiguration::PortConfiguration(const talk_base::SocketAddress& sa,
                                     const std::string& un,
                                     const std::string& pw,
                                     const std::string& mc)
    : stun_address(sa), username(un), password(pw), magic_cookie(mc) {
}

void PortConfiguration::AddRelay(const PortList& ports, float pref_modifier) {
  RelayServer relay;
  relay.ports = ports;
  relay.pref_modifier = pref_modifier;
  relays.push_back(relay);
}

bool PortConfiguration::ResolveStunAddress() {
  int err = 0;
  if (!stun_address.ResolveIP(true, &err)) {
    LOG(LS_ERROR) << "Unable to resolve STUN host "
                  << stun_address.hostname() << ".  Error " << err;
    return false;
  }
  return true;
}

bool PortConfiguration::SupportsProtocol(
    const PortConfiguration::RelayServer& relay, ProtocolType type) {
  PortConfiguration::PortList::const_iterator relay_port;
  for (relay_port = relay.ports.begin();
        relay_port != relay.ports.end();
        ++relay_port) {
    if (relay_port->proto == type)
      return true;
  }
  return false;
}

}  // namespace cricket
