// Copyright 2011 Google Inc. All Rights Reserved.


#ifndef TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
#define TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_

#include <map>
#include <string>

#include "talk/base/network.h"
#include "talk/base/basicpacketsocketfactory.h"
#include "talk/base/basictypes.h"
#include "talk/base/messagehandler.h"
#include "talk/base/proxyinfo.h"
#include "talk/base/scoped_ptr.h"
#include "talk/base/sigslot.h"
#include "talk/base/socketaddress.h"
#include "talk/p2p/client/httpportallocator.h"

namespace talk_base {
class AsyncHttpRequest;
class AutoDetectProxy;
class BasicPacketSocketFactory;
class NetworkManager;
class PacketSocketFactory;
class SignalThread;
class TestHttpPortAllocatorSession;
class Thread;
}

namespace cricket {
class HttpPortAllocator;
class Port;
class PortAllocatorSession;
struct PortConfiguration;
class RelayPort;
class StunPort;

// Contains details about a discovered firewall that are of interest
// when debugging call failures.
struct FirewallInfo {
  std::string brand;
  std::string model;

  // TODO: List of current port mappings.
};

// Contains details about a specific connect attempt.
struct ConnectInfo {
  ConnectInfo()
      : rtt(-1), error(0) {}
  // Time when the connection was initiated. Needed for calculating
  // the round trip time.
  uint32 start_time_ms;
  // Round trip time in milliseconds or -1 for failed connection.
  int32 rtt;
  // Error code representing low level errors like socket errors.
  int error;
};

// Identifier for a network interface and proxy address pair.
struct NicId {
  NicId(const talk_base::IPAddress& ip,
        const talk_base::SocketAddress& proxy_address)
      : ip(ip),
        proxy_address(proxy_address) {
  }
  talk_base::IPAddress ip;
  talk_base::SocketAddress proxy_address;
};

// Comparator implementation identifying unique network interface and
// proxy address pairs.
class NicIdComparator {
 public:
  int compare(const NicId &first, const NicId &second) const {
    if (first.ip == second.ip) {
      // Compare proxy address.
      if (first.proxy_address == second.proxy_address) {
        return 0;
      } else {
        return first.proxy_address < second.proxy_address? -1 : 1;
      }
    }
    return first.ip < second.ip ? -1 : 1;
  }

  bool operator()(const NicId &first, const NicId &second) const {
    return (compare(first, second) < 0);
  }
};

// Contains information of a network interface and proxy address pair.
struct NicInfo {
  NicInfo() {}
  talk_base::IPAddress ip;
  talk_base::ProxyInfo proxy_info;
  talk_base::SocketAddress external_address;
  talk_base::SocketAddress stun_server_address;
  talk_base::SocketAddress media_server_address;
  ConnectInfo stun;
  ConnectInfo http;
  ConnectInfo https;
  ConnectInfo udp;
  ConnectInfo tcp;
  ConnectInfo ssltcp;
  FirewallInfo firewall;
};

// Holds the result of the connectivity check.
class NicMap : public std::map<NicId, NicInfo, NicIdComparator> {
};

class TestHttpPortAllocatorSession : public HttpPortAllocatorSession {
 public:
  TestHttpPortAllocatorSession(
      HttpPortAllocator* allocator, const std::string &name,
      const std::string& session_type,
      const std::vector<talk_base::SocketAddress>& stun_hosts,
      const std::vector<std::string>& relay_hosts,
      const std::string& relay_token,
      const std::string& user_agent)
      : HttpPortAllocatorSession(allocator, name, session_type, stun_hosts,
                                 relay_hosts, relay_token, user_agent) {
  }
  void set_proxy(const talk_base::ProxyInfo& proxy) {
    proxy_ = proxy;
  }

  void ConfigReady(PortConfiguration* config);

  void OnRequestDone(talk_base::SignalThread* data);

  sigslot::signal2<const PortConfiguration*,
                   const talk_base::ProxyInfo&> SignalConfigReady;
  sigslot::signal1<talk_base::AsyncHttpRequest*> SignalRequestDone;

 private:
  talk_base::ProxyInfo proxy_;
};

// Runs a request/response check on all network interface and proxy
// address combinations. The check is considered done either when all
// checks has been successful or when the check times out.
class ConnectivityChecker
    : public talk_base::MessageHandler, public sigslot::has_slots<> {
 public:
  ConnectivityChecker(talk_base::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);
  virtual ~ConnectivityChecker();

  // Virtual for gMock.
  virtual bool Initialize();
  virtual void Start();
  virtual void Stop();

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

  const NicMap& GetResults() const {
    return nics_;
  }

  void set_timeout_ms(uint32 timeout) {
    timeout_ms_ = timeout;
  }

  void set_stun_address(const talk_base::SocketAddress& stun_address) {
    stun_address_ = stun_address;
  }

  const std::string& connection() const {
    return connection_;
  }

  talk_base::Thread* worker() {
    return worker_;
  }

  const std::string& jid() const {
    return jid_;
  }

  const std::string& session_id() const {
    return session_id_;
  }

  // Context: Main Thread. Signalled when the connectivity check is complete.
  sigslot::signal1<ConnectivityChecker*> SignalCheckDone;

 protected:
  // Can be overridden for test.
  virtual talk_base::NetworkManager* CreateNetworkManager() {
    return new talk_base::BasicNetworkManager();
  }
  virtual talk_base::BasicPacketSocketFactory* CreateSocketFactory(
      talk_base::Thread* thread) {
    return new talk_base::BasicPacketSocketFactory(thread);
  }
  virtual HttpPortAllocator* CreatePortAllocator(
      talk_base::NetworkManager* network_manager,
      const std::string& user_agent,
      const std::string& relay_token);
  virtual StunPort* CreateStunPort(const PortConfiguration* config,
                                   talk_base::Network* network);
  virtual RelayPort* CreateRelayPort(const PortConfiguration* config,
                                     talk_base::Network* network);
  virtual void InitiateProxyDetection();
  virtual void SetProxyInfo(const talk_base::ProxyInfo& info);
  virtual talk_base::ProxyInfo GetProxyInfo() const;

 private:
  bool AddNic(const talk_base::IPAddress& ip,
              const talk_base::SocketAddress& proxy_address);
  void AllocatePorts();
  void AllocateRelayPorts();
  void CheckNetworks();
  void CreateRelayPorts(const PortConfiguration* config,
                        const talk_base::ProxyInfo& proxy_info);

  // Must be called by the worker thread.
  void CleanUp();

  void OnCheckDone(bool signal_results);
  void OnRequestDone(talk_base::AsyncHttpRequest* request);
  void OnRelayAddressReady(Port* port);
  void OnStunAddressReady(Port* port);
  void OnRelayAddressError(Port* port);
  void OnStunAddressError(Port* port);
  void OnNetworksChanged();
  void OnProxyDetect(talk_base::SignalThread* thread);
  void OnConfigReady(const PortConfiguration*,
                     const talk_base::ProxyInfo& proxy);
  void OnConfigWithProxyReady(const PortConfiguration*);
  void RegisterHttpStart(int port);
  talk_base::Thread* worker_;
  std::string jid_;
  std::string session_id_;
  std::string user_agent_;
  std::string relay_token_;
  std::string connection_;
  talk_base::AutoDetectProxy* proxy_detect_;
  talk_base::scoped_ptr<talk_base::NetworkManager> network_manager_;
  talk_base::scoped_ptr<talk_base::BasicPacketSocketFactory> socket_factory_;
  talk_base::scoped_ptr<HttpPortAllocator> port_allocator_;
  NicMap nics_;
  std::vector<Port*> ports_;
  std::vector<PortAllocatorSession*> sessions_;
  uint32 timeout_ms_;
  talk_base::SocketAddress stun_address_;
  talk_base::Thread* main_;
};

}  // namespace cricket

#endif  // TALK_P2P_CLIENT_CONNECTIVITYCHECKER_H_
