/*
 * libjingle
 * Copyright 2011, 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 "talk/p2p/client/connectivitychecker.h"

#include "talk/p2p/base/candidate.h"
#include "talk/p2p/base/common.h"
#include "talk/p2p/base/constants.h"
#include "talk/p2p/base/port.h"
#include "talk/p2p/base/relayport.h"
#include "talk/p2p/base/stunport.h"
#include "webrtc/base/asynchttprequest.h"
#include "webrtc/base/autodetectproxy.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/httpcommon-inl.h"
#include "webrtc/base/httpcommon.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/proxydetect.h"
#include "webrtc/base/thread.h"

namespace cricket {

static const char kDefaultStunHostname[] = "stun.l.google.com";
static const int kDefaultStunPort = 19302;

// Default maximum time in milliseconds we will wait for connections.
static const uint32 kDefaultTimeoutMs = 3000;

enum {
  MSG_START = 1,
  MSG_STOP = 2,
  MSG_TIMEOUT = 3,
  MSG_SIGNAL_RESULTS = 4
};

class TestHttpPortAllocator : public HttpPortAllocator {
 public:
  TestHttpPortAllocator(rtc::NetworkManager* network_manager,
                        const std::string& user_agent,
                        const std::string& relay_token) :
      HttpPortAllocator(network_manager, user_agent) {
    SetRelayToken(relay_token);
  }
  PortAllocatorSession* CreateSessionInternal(
      const std::string& content_name,
      int component,
      const std::string& ice_ufrag,
      const std::string& ice_pwd) {
    return new TestHttpPortAllocatorSession(this, content_name, component,
                                            ice_ufrag, ice_pwd,
                                            stun_hosts(), relay_hosts(),
                                            relay_token(), user_agent());
  }
};

void TestHttpPortAllocatorSession::ConfigReady(PortConfiguration* config) {
  SignalConfigReady(username(), password(), config, proxy_);
  delete config;
}

void TestHttpPortAllocatorSession::OnRequestDone(
    rtc::SignalThread* data) {
  rtc::AsyncHttpRequest* request =
      static_cast<rtc::AsyncHttpRequest*>(data);

  // Tell the checker that the request is complete.
  SignalRequestDone(request);

  // Pass on the response to super class.
  HttpPortAllocatorSession::OnRequestDone(data);
}

ConnectivityChecker::ConnectivityChecker(
    rtc::Thread* worker,
    const std::string& jid,
    const std::string& session_id,
    const std::string& user_agent,
    const std::string& relay_token,
    const std::string& connection)
    : worker_(worker),
      jid_(jid),
      session_id_(session_id),
      user_agent_(user_agent),
      relay_token_(relay_token),
      connection_(connection),
      proxy_detect_(NULL),
      timeout_ms_(kDefaultTimeoutMs),
      stun_address_(kDefaultStunHostname, kDefaultStunPort),
      started_(false) {
}

ConnectivityChecker::~ConnectivityChecker() {
  if (started_) {
    // We try to clear the TIMEOUT below. But worker may still handle it and
    // cause SignalCheckDone to happen on main-thread. So we finally clear any
    // pending SIGNAL_RESULTS.
    worker_->Clear(this, MSG_TIMEOUT);
    worker_->Send(this, MSG_STOP);
    nics_.clear();
    main_->Clear(this, MSG_SIGNAL_RESULTS);
  }
}

bool ConnectivityChecker::Initialize() {
  network_manager_.reset(CreateNetworkManager());
  socket_factory_.reset(CreateSocketFactory(worker_));
  port_allocator_.reset(CreatePortAllocator(network_manager_.get(),
                                            user_agent_, relay_token_));
  uint32 new_allocator_flags = port_allocator_->flags();
  new_allocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_UFRAG;
  port_allocator_->set_flags(new_allocator_flags);
  return true;
}

void ConnectivityChecker::Start() {
  main_ = rtc::Thread::Current();
  worker_->Post(this, MSG_START);
  started_ = true;
}

void ConnectivityChecker::CleanUp() {
  ASSERT(worker_ == rtc::Thread::Current());
  if (proxy_detect_) {
    proxy_detect_->Release();
    proxy_detect_ = NULL;
  }

  for (uint32 i = 0; i < sessions_.size(); ++i) {
    delete sessions_[i];
  }
  sessions_.clear();
  for (uint32 i = 0; i < ports_.size(); ++i) {
    delete ports_[i];
  }
  ports_.clear();
}

bool ConnectivityChecker::AddNic(const rtc::IPAddress& ip,
                                 const rtc::SocketAddress& proxy_addr) {
  NicMap::iterator i = nics_.find(NicId(ip, proxy_addr));
  if (i != nics_.end()) {
    // Already have it.
    return false;
  }
  uint32 now = rtc::Time();
  NicInfo info;
  info.ip = ip;
  info.proxy_info = GetProxyInfo();
  info.stun.start_time_ms = now;
  nics_.insert(std::pair<NicId, NicInfo>(NicId(ip, proxy_addr), info));
  return true;
}

void ConnectivityChecker::SetProxyInfo(const rtc::ProxyInfo& proxy_info) {
  port_allocator_->set_proxy(user_agent_, proxy_info);
  AllocatePorts();
}

rtc::ProxyInfo ConnectivityChecker::GetProxyInfo() const {
  rtc::ProxyInfo proxy_info;
  if (proxy_detect_) {
    proxy_info = proxy_detect_->proxy();
  }
  return proxy_info;
}

void ConnectivityChecker::CheckNetworks() {
  network_manager_->SignalNetworksChanged.connect(
      this, &ConnectivityChecker::OnNetworksChanged);
  network_manager_->StartUpdating();
}

void ConnectivityChecker::OnMessage(rtc::Message *msg) {
  switch (msg->message_id) {
    case MSG_START:
      ASSERT(worker_ == rtc::Thread::Current());
      worker_->PostDelayed(timeout_ms_, this, MSG_TIMEOUT);
      CheckNetworks();
      break;
    case MSG_STOP:
      // We're being stopped, free resources.
      CleanUp();
      break;
    case MSG_TIMEOUT:
      // We need to signal results on the main thread.
      main_->Post(this, MSG_SIGNAL_RESULTS);
      break;
    case MSG_SIGNAL_RESULTS:
      ASSERT(main_ == rtc::Thread::Current());
      SignalCheckDone(this);
      break;
    default:
      LOG(LS_ERROR) << "Unknown message: " << msg->message_id;
  }
}

void ConnectivityChecker::OnProxyDetect(rtc::SignalThread* thread) {
  ASSERT(worker_ == rtc::Thread::Current());
  if (proxy_detect_->proxy().type != rtc::PROXY_NONE) {
    SetProxyInfo(proxy_detect_->proxy());
  }
}

void ConnectivityChecker::OnRequestDone(rtc::AsyncHttpRequest* request) {
  ASSERT(worker_ == rtc::Thread::Current());
  // Since we don't know what nic were actually used for the http request,
  // for now, just use the first one.
  std::vector<rtc::Network*> networks;
  network_manager_->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_ERROR) << "No networks while registering http start.";
    return;
  }
  rtc::ProxyInfo proxy_info = request->proxy();
  NicMap::iterator i =
#ifdef USE_WEBRTC_DEV_BRANCH
      nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address));
#else  // USE_WEBRTC_DEV_BRANCH
      nics_.find(NicId(networks[0]->ip(), proxy_info.address));
#endif  // USE_WEBRTC_DEV_BRANCH
  if (i != nics_.end()) {
    int port = request->port();
    uint32 now = rtc::Time();
    NicInfo* nic_info = &i->second;
    if (port == rtc::HTTP_DEFAULT_PORT) {
      nic_info->http.rtt = now - nic_info->http.start_time_ms;
    } else if (port == rtc::HTTP_SECURE_PORT) {
      nic_info->https.rtt = now - nic_info->https.start_time_ms;
    } else {
      LOG(LS_ERROR) << "Got response with unknown port: " << port;
    }
  } else {
    LOG(LS_ERROR) << "No nic info found while receiving response.";
  }
}

void ConnectivityChecker::OnConfigReady(
    const std::string& username, const std::string& password,
    const PortConfiguration* config, const rtc::ProxyInfo& proxy_info) {
  ASSERT(worker_ == rtc::Thread::Current());

  // Since we send requests on both HTTP and HTTPS we will get two
  // configs per nic. Results from the second will overwrite the
  // result from the first.
  // TODO: Handle multiple pings on one nic.
  CreateRelayPorts(username, password, config, proxy_info);
}

void ConnectivityChecker::OnRelayPortComplete(Port* port) {
  ASSERT(worker_ == rtc::Thread::Current());
  RelayPort* relay_port = reinterpret_cast<RelayPort*>(port);
  const ProtocolAddress* address = relay_port->ServerAddress(0);
#ifdef USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->GetBestIP();
#else  // USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->ip();
#endif  // USE_WEBRTC_DEV_BRANCH
  NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
  if (i != nics_.end()) {
    // We have it already, add the new information.
    NicInfo* nic_info = &i->second;
    ConnectInfo* connect_info = NULL;
    if (address) {
      switch (address->proto) {
        case PROTO_UDP:
          connect_info = &nic_info->udp;
          break;
        case PROTO_TCP:
          connect_info = &nic_info->tcp;
          break;
        case PROTO_SSLTCP:
          connect_info = &nic_info->ssltcp;
          break;
        default:
          LOG(LS_ERROR) << " relay address with bad protocol added";
      }
      if (connect_info) {
        connect_info->rtt =
            rtc::TimeSince(connect_info->start_time_ms);
      }
    }
  } else {
    LOG(LS_ERROR) << " got relay address for non-existing nic";
  }
}

void ConnectivityChecker::OnStunPortComplete(Port* port) {
  ASSERT(worker_ == rtc::Thread::Current());
  const std::vector<Candidate> candidates = port->Candidates();
  Candidate c = candidates[0];
#ifdef USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->GetBestIP();
#else  // USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->ip();
#endif  // USE_WEBRTC_DEV_BRANCH
  NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
  if (i != nics_.end()) {
    // We have it already, add the new information.
    uint32 now = rtc::Time();
    NicInfo* nic_info = &i->second;
    nic_info->external_address = c.address();

    nic_info->stun_server_addresses =
        static_cast<StunPort*>(port)->server_addresses();
    nic_info->stun.rtt = now - nic_info->stun.start_time_ms;
  } else {
    LOG(LS_ERROR) << "Got stun address for non-existing nic";
  }
}

void ConnectivityChecker::OnStunPortError(Port* port) {
  ASSERT(worker_ == rtc::Thread::Current());
  LOG(LS_ERROR) << "Stun address error.";
#ifdef USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->GetBestIP();
#else  // USE_WEBRTC_DEV_BRANCH
  rtc::IPAddress ip = port->Network()->ip();
#endif  // USE_WEBRTC_DEV_BRANCH
  NicMap::iterator i = nics_.find(NicId(ip, port->proxy().address));
  if (i != nics_.end()) {
    // We have it already, add the new information.
    NicInfo* nic_info = &i->second;

    nic_info->stun_server_addresses =
        static_cast<StunPort*>(port)->server_addresses();
  }
}

void ConnectivityChecker::OnRelayPortError(Port* port) {
  ASSERT(worker_ == rtc::Thread::Current());
  LOG(LS_ERROR) << "Relay address error.";
}

void ConnectivityChecker::OnNetworksChanged() {
  ASSERT(worker_ == rtc::Thread::Current());
  std::vector<rtc::Network*> networks;
  network_manager_->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_ERROR) << "Machine has no networks; nothing to do";
    return;
  }
  AllocatePorts();
}

HttpPortAllocator* ConnectivityChecker::CreatePortAllocator(
    rtc::NetworkManager* network_manager,
    const std::string& user_agent,
    const std::string& relay_token) {
  return new TestHttpPortAllocator(network_manager, user_agent, relay_token);
}

StunPort* ConnectivityChecker::CreateStunPort(
    const std::string& username, const std::string& password,
    const PortConfiguration* config, rtc::Network* network) {
  return StunPort::Create(worker_,
                          socket_factory_.get(),
                          network,
#ifdef USE_WEBRTC_DEV_BRANCH
                          network->GetBestIP(),
#else  // USE_WEBRTC_DEV_BRANCH
                          network->ip(),
#endif  // USE_WEBRTC_DEV_BRANCH
                          0,
                          0,
                          username,
                          password,
                          config->stun_servers);
}

RelayPort* ConnectivityChecker::CreateRelayPort(
    const std::string& username, const std::string& password,
    const PortConfiguration* config, rtc::Network* network) {
  return RelayPort::Create(worker_,
                           socket_factory_.get(),
                           network,
#ifdef USE_WEBRTC_DEV_BRANCH
                           network->GetBestIP(),
#else  // USE_WEBRTC_DEV_BRANCH
                           network->ip(),
#endif  // USE_WEBRTC_DEV_BRANCH
                           port_allocator_->min_port(),
                           port_allocator_->max_port(),
                           username,
                           password);
}

void ConnectivityChecker::CreateRelayPorts(
    const std::string& username, const std::string& password,
    const PortConfiguration* config, const rtc::ProxyInfo& proxy_info) {
  PortConfiguration::RelayList::const_iterator relay;
  std::vector<rtc::Network*> networks;
  network_manager_->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_ERROR) << "Machine has no networks; no relay ports created.";
    return;
  }
  for (relay = config->relays.begin();
       relay != config->relays.end(); ++relay) {
    for (uint32 i = 0; i < networks.size(); ++i) {
      NicMap::iterator iter =
#ifdef USE_WEBRTC_DEV_BRANCH
          nics_.find(NicId(networks[i]->GetBestIP(), proxy_info.address));
#else  // USE_WEBRTC_DEV_BRANCH
          nics_.find(NicId(networks[i]->ip(), proxy_info.address));
#endif  // USE_WEBRTC_DEV_BRANCH
      if (iter != nics_.end()) {
        // TODO: Now setting the same start time for all protocols.
        // This might affect accuracy, but since we are mainly looking for
        // connect failures or number that stick out, this is good enough.
        uint32 now = rtc::Time();
        NicInfo* nic_info = &iter->second;
        nic_info->udp.start_time_ms = now;
        nic_info->tcp.start_time_ms = now;
        nic_info->ssltcp.start_time_ms = now;

        // Add the addresses of this protocol.
        PortList::const_iterator relay_port;
        for (relay_port = relay->ports.begin();
             relay_port != relay->ports.end();
             ++relay_port) {
          RelayPort* port = CreateRelayPort(username, password,
                                            config, networks[i]);
          port->AddServerAddress(*relay_port);
          port->AddExternalAddress(*relay_port);

          nic_info->media_server_address = port->ServerAddress(0)->address;

          // Listen to network events.
          port->SignalPortComplete.connect(
              this, &ConnectivityChecker::OnRelayPortComplete);
          port->SignalPortError.connect(
              this, &ConnectivityChecker::OnRelayPortError);

          port->set_proxy(user_agent_, proxy_info);

          // Start fetching an address for this port.
          port->PrepareAddress();
          ports_.push_back(port);
        }
      } else {
        LOG(LS_ERROR) << "Failed to find nic info when creating relay ports.";
      }
    }
  }
}

void ConnectivityChecker::AllocatePorts() {
  const std::string username = rtc::CreateRandomString(ICE_UFRAG_LENGTH);
  const std::string password = rtc::CreateRandomString(ICE_PWD_LENGTH);
  ServerAddresses stun_servers;
  stun_servers.insert(stun_address_);
  PortConfiguration config(stun_servers, username, password);
  std::vector<rtc::Network*> networks;
  network_manager_->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_ERROR) << "Machine has no networks; no ports will be allocated";
    return;
  }
  rtc::ProxyInfo proxy_info = GetProxyInfo();
  bool allocate_relay_ports = false;
  for (uint32 i = 0; i < networks.size(); ++i) {
#ifdef USE_WEBRTC_DEV_BRANCH
    if (AddNic(networks[i]->GetBestIP(), proxy_info.address)) {
#else  // USE_WEBRTC_DEV_BRANCH
    if (AddNic(networks[i]->ip(), proxy_info.address)) {
#endif  // USE_WEBRTC_DEV_BRANCH
      Port* port = CreateStunPort(username, password, &config, networks[i]);
      if (port) {

        // Listen to network events.
        port->SignalPortComplete.connect(
            this, &ConnectivityChecker::OnStunPortComplete);
        port->SignalPortError.connect(
            this, &ConnectivityChecker::OnStunPortError);

        port->set_proxy(user_agent_, proxy_info);
        port->PrepareAddress();
        ports_.push_back(port);
        allocate_relay_ports = true;
      }
    }
  }

  // If any new ip/proxy combinations were added, send a relay allocate.
  if (allocate_relay_ports) {
    AllocateRelayPorts();
  }

  // Initiate proxy detection.
  InitiateProxyDetection();
}

void ConnectivityChecker::InitiateProxyDetection() {
  // Only start if we haven't been started before.
  if (!proxy_detect_) {
    proxy_detect_ = new rtc::AutoDetectProxy(user_agent_);
    rtc::Url<char> host_url("/", "relay.google.com",
                                  rtc::HTTP_DEFAULT_PORT);
    host_url.set_secure(true);
    proxy_detect_->set_server_url(host_url.url());
    proxy_detect_->SignalWorkDone.connect(
        this, &ConnectivityChecker::OnProxyDetect);
    proxy_detect_->Start();
  }
}

void ConnectivityChecker::AllocateRelayPorts() {
  // Currently we are using the 'default' nic for http(s) requests.
  TestHttpPortAllocatorSession* allocator_session =
      reinterpret_cast<TestHttpPortAllocatorSession*>(
          port_allocator_->CreateSessionInternal(
              "connectivity checker test content",
              ICE_CANDIDATE_COMPONENT_RTP,
              rtc::CreateRandomString(ICE_UFRAG_LENGTH),
              rtc::CreateRandomString(ICE_PWD_LENGTH)));
  allocator_session->set_proxy(port_allocator_->proxy());
  allocator_session->SignalConfigReady.connect(
      this, &ConnectivityChecker::OnConfigReady);
  allocator_session->SignalRequestDone.connect(
      this, &ConnectivityChecker::OnRequestDone);

  // Try both http and https.
  RegisterHttpStart(rtc::HTTP_SECURE_PORT);
  allocator_session->SendSessionRequest("relay.l.google.com",
                                        rtc::HTTP_SECURE_PORT);
  RegisterHttpStart(rtc::HTTP_DEFAULT_PORT);
  allocator_session->SendSessionRequest("relay.l.google.com",
                                        rtc::HTTP_DEFAULT_PORT);

  sessions_.push_back(allocator_session);
}

void ConnectivityChecker::RegisterHttpStart(int port) {
  // Since we don't know what nic were actually used for the http request,
  // for now, just use the first one.
  std::vector<rtc::Network*> networks;
  network_manager_->GetNetworks(&networks);
  if (networks.empty()) {
    LOG(LS_ERROR) << "No networks while registering http start.";
    return;
  }
  rtc::ProxyInfo proxy_info = GetProxyInfo();
  NicMap::iterator i =
#ifdef USE_WEBRTC_DEV_BRANCH
      nics_.find(NicId(networks[0]->GetBestIP(), proxy_info.address));
#else  // USE_WEBRTC_DEV_BRANCH
      nics_.find(NicId(networks[0]->ip(), proxy_info.address));
#endif  // USE_WEBRTC_DEV_BRANCH
  if (i != nics_.end()) {
    uint32 now = rtc::Time();
    NicInfo* nic_info = &i->second;
    if (port == rtc::HTTP_DEFAULT_PORT) {
      nic_info->http.start_time_ms = now;
    } else if (port == rtc::HTTP_SECURE_PORT) {
      nic_info->https.start_time_ms = now;
    } else {
      LOG(LS_ERROR) << "Registering start time for unknown port: " << port;
    }
  } else {
    LOG(LS_ERROR) << "Error, no nic info found while registering http start.";
  }
}

}  // namespace rtc
