/*
 *  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/client/httpportallocator.h"

#include <algorithm>
#include <map>

#include "webrtc/base/basicdefs.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/httpcommon.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/nethelpers.h"
#include "webrtc/base/signalthread.h"
#include "webrtc/base/stringencode.h"

namespace {

// Helper routine to remove whitespace from the ends of a string.
void Trim(std::string& str) {
  size_t first = str.find_first_not_of(" \t\r\n");
  if (first == std::string::npos) {
    str.clear();
    return;
  }

  ASSERT(str.find_last_not_of(" \t\r\n") != std::string::npos);
}

// Parses the lines in the result of the HTTP request that are of the form
// 'a=b' and returns them in a map.
typedef std::map<std::string, std::string> StringMap;
void ParseMap(const std::string& string, StringMap& map) {
  size_t start_of_line = 0;
  size_t end_of_line = 0;

  for (;;) {  // for each line
    start_of_line = string.find_first_not_of("\r\n", end_of_line);
    if (start_of_line == std::string::npos)
      break;

    end_of_line = string.find_first_of("\r\n", start_of_line);
    if (end_of_line == std::string::npos) {
      end_of_line = string.length();
    }

    size_t equals = string.find('=', start_of_line);
    if ((equals >= end_of_line) || (equals == std::string::npos))
      continue;

    std::string key(string, start_of_line, equals - start_of_line);
    std::string value(string, equals + 1, end_of_line - equals - 1);

    Trim(key);
    Trim(value);

    if ((key.size() > 0) && (value.size() > 0))
      map[key] = value;
  }
}

}  // namespace

namespace cricket {

// HttpPortAllocatorBase

const int HttpPortAllocatorBase::kNumRetries = 5;

const char HttpPortAllocatorBase::kCreateSessionURL[] = "/create_session";

HttpPortAllocatorBase::HttpPortAllocatorBase(
    rtc::NetworkManager* network_manager,
    rtc::PacketSocketFactory* socket_factory,
    const std::string &user_agent)
    : BasicPortAllocator(network_manager, socket_factory), agent_(user_agent) {
  relay_hosts_.push_back("relay.google.com");
  stun_hosts_.push_back(
      rtc::SocketAddress("stun.l.google.com", 19302));
}

HttpPortAllocatorBase::HttpPortAllocatorBase(
    rtc::NetworkManager* network_manager,
    const std::string &user_agent)
    : BasicPortAllocator(network_manager), agent_(user_agent) {
  relay_hosts_.push_back("relay.google.com");
  stun_hosts_.push_back(
      rtc::SocketAddress("stun.l.google.com", 19302));
}

HttpPortAllocatorBase::~HttpPortAllocatorBase() {
}

// HttpPortAllocatorSessionBase

HttpPortAllocatorSessionBase::HttpPortAllocatorSessionBase(
    HttpPortAllocatorBase* allocator,
    const std::string& content_name,
    int component,
    const std::string& ice_ufrag,
    const std::string& ice_pwd,
    const std::vector<rtc::SocketAddress>& stun_hosts,
    const std::vector<std::string>& relay_hosts,
    const std::string& relay_token,
    const std::string& user_agent)
    : BasicPortAllocatorSession(allocator, content_name, component,
                                ice_ufrag, ice_pwd),
      relay_hosts_(relay_hosts), stun_hosts_(stun_hosts),
      relay_token_(relay_token), agent_(user_agent), attempts_(0) {
}

HttpPortAllocatorSessionBase::~HttpPortAllocatorSessionBase() {}

void HttpPortAllocatorSessionBase::GetPortConfigurations() {
  // Creating relay sessions can take time and is done asynchronously.
  // Creating stun sessions could also take time and could be done aysnc also,
  // but for now is done here and added to the initial config.  Note any later
  // configs will have unresolved stun ips and will be discarded by the
  // AllocationSequence.
  ServerAddresses hosts;
  for (std::vector<rtc::SocketAddress>::iterator it = stun_hosts_.begin();
      it != stun_hosts_.end(); ++it) {
    hosts.insert(*it);
  }

  PortConfiguration* config = new PortConfiguration(hosts,
                                                    username(),
                                                    password());
  ConfigReady(config);
  TryCreateRelaySession();
}

void HttpPortAllocatorSessionBase::TryCreateRelaySession() {
  if (allocator()->flags() & PORTALLOCATOR_DISABLE_RELAY) {
    LOG(LS_VERBOSE) << "HttpPortAllocator: Relay ports disabled, skipping.";
    return;
  }

  if (attempts_ == HttpPortAllocatorBase::kNumRetries) {
    LOG(LS_ERROR) << "HttpPortAllocator: maximum number of requests reached; "
                  << "giving up on relay.";
    return;
  }

  if (relay_hosts_.size() == 0) {
    LOG(LS_ERROR) << "HttpPortAllocator: no relay hosts configured.";
    return;
  }

  // Choose the next host to try.
  std::string host = relay_hosts_[attempts_ % relay_hosts_.size()];
  attempts_++;
  LOG(LS_INFO) << "HTTPPortAllocator: sending to relay host " << host;
  if (relay_token_.empty()) {
    LOG(LS_WARNING) << "No relay auth token found.";
  }

  SendSessionRequest(host, rtc::HTTP_SECURE_PORT);
}

std::string HttpPortAllocatorSessionBase::GetSessionRequestUrl() {
  std::string url = std::string(HttpPortAllocatorBase::kCreateSessionURL);
  ASSERT(!username().empty());
  ASSERT(!password().empty());
  url = url + "?username=" + rtc::s_url_encode(username()) +
      "&password=" + rtc::s_url_encode(password());
  return url;
}

void HttpPortAllocatorSessionBase::ReceiveSessionResponse(
    const std::string& response) {

  StringMap map;
  ParseMap(response, map);

  if (!username().empty() && map["username"] != username()) {
    LOG(LS_WARNING) << "Received unexpected username value from relay server.";
  }
  if (!password().empty() && map["password"] != password()) {
    LOG(LS_WARNING) << "Received unexpected password value from relay server.";
  }

  std::string relay_ip = map["relay.ip"];
  std::string relay_udp_port = map["relay.udp_port"];
  std::string relay_tcp_port = map["relay.tcp_port"];
  std::string relay_ssltcp_port = map["relay.ssltcp_port"];

  ServerAddresses hosts;
  for (std::vector<rtc::SocketAddress>::iterator it = stun_hosts_.begin();
      it != stun_hosts_.end(); ++it) {
    hosts.insert(*it);
  }

  PortConfiguration* config = new PortConfiguration(hosts,
                                                    map["username"],
                                                    map["password"]);

  RelayServerConfig relay_config(RELAY_GTURN);
  if (!relay_udp_port.empty()) {
    rtc::SocketAddress address(relay_ip, atoi(relay_udp_port.c_str()));
    relay_config.ports.push_back(ProtocolAddress(address, PROTO_UDP));
  }
  if (!relay_tcp_port.empty()) {
    rtc::SocketAddress address(relay_ip, atoi(relay_tcp_port.c_str()));
    relay_config.ports.push_back(ProtocolAddress(address, PROTO_TCP));
  }
  if (!relay_ssltcp_port.empty()) {
    rtc::SocketAddress address(relay_ip, atoi(relay_ssltcp_port.c_str()));
    relay_config.ports.push_back(ProtocolAddress(address, PROTO_SSLTCP));
  }
  config->AddRelay(relay_config);
  ConfigReady(config);
}

}  // namespace cricket
