// Copyright 2011 Google Inc. All Rights Reserved.


#include <string>

#include "talk/p2p/base/basicpacketsocketfactory.h"
#include "talk/p2p/base/relayport.h"
#include "talk/p2p/base/stunport.h"
#include "talk/p2p/client/connectivitychecker.h"
#include "talk/p2p/client/httpportallocator.h"
#include "webrtc/base/asynchttprequest.h"
#include "webrtc/base/fakenetwork.h"
#include "webrtc/base/gunit.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/socketaddress.h"

namespace cricket {

static const rtc::SocketAddress kClientAddr1("11.11.11.11", 0);
static const rtc::SocketAddress kClientAddr2("22.22.22.22", 0);
static const rtc::SocketAddress kExternalAddr("33.33.33.33", 3333);
static const rtc::SocketAddress kStunAddr("44.44.44.44", 4444);
static const rtc::SocketAddress kRelayAddr("55.55.55.55", 5555);
static const rtc::SocketAddress kProxyAddr("66.66.66.66", 6666);
static const rtc::ProxyType kProxyType = rtc::PROXY_HTTPS;
static const char kRelayHost[] = "relay.google.com";
static const char kRelayToken[] =
    "CAESFwoOb2phQGdvb2dsZS5jb20Q043h47MmGhBTB1rbfIXkhuarDCZe+xF6";
static const char kBrowserAgent[] = "browser_test";
static const char kJid[] = "a.b@c";
static const char kUserName[] = "testuser";
static const char kPassword[] = "testpassword";
static const char kMagicCookie[] = "testcookie";
static const char kRelayUdpPort[] = "4444";
static const char kRelayTcpPort[] = "5555";
static const char kRelaySsltcpPort[] = "6666";
static const char kSessionId[] = "testsession";
static const char kConnection[] = "testconnection";
static const int kMinPort = 1000;
static const int kMaxPort = 2000;

// Fake implementation to mock away real network usage.
class FakeRelayPort : public RelayPort {
 public:
  FakeRelayPort(rtc::Thread* thread,
                rtc::PacketSocketFactory* factory,
                rtc::Network* network, const rtc::IPAddress& ip,
                int min_port, int max_port,
                const std::string& username, const std::string& password)
      : RelayPort(thread, factory, network, ip, min_port, max_port,
                  username, password) {
  }

  // Just signal that we are done.
  virtual void PrepareAddress() {
    SignalPortComplete(this);
  }
};

// Fake implementation to mock away real network usage.
class FakeStunPort : public StunPort {
 public:
  FakeStunPort(rtc::Thread* thread,
               rtc::PacketSocketFactory* factory,
               rtc::Network* network,
               const rtc::IPAddress& ip,
               int min_port, int max_port,
               const std::string& username, const std::string& password,
               const ServerAddresses& server_addr)
      : StunPort(thread, factory, network, ip, min_port, max_port,
                 username, password, server_addr) {
  }

  // Just set external address and signal that we are done.
  virtual void PrepareAddress() {
    AddAddress(kExternalAddr, kExternalAddr, rtc::SocketAddress(), "udp", "",
               STUN_PORT_TYPE, ICE_TYPE_PREFERENCE_SRFLX, 0, true);
    SignalPortComplete(this);
  }
};

// Fake implementation to mock away real network usage by responding
// to http requests immediately.
class FakeHttpPortAllocatorSession : public TestHttpPortAllocatorSession {
 public:
  FakeHttpPortAllocatorSession(
      HttpPortAllocator* 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& agent)
      : TestHttpPortAllocatorSession(allocator,
                                     content_name,
                                     component,
                                     ice_ufrag,
                                     ice_pwd,
                                     stun_hosts,
                                     relay_hosts,
                                     relay_token,
                                     agent) {
  }
  virtual void SendSessionRequest(const std::string& host, int port) {
    FakeReceiveSessionResponse(host, port);
  }

  // Pass results to the real implementation.
  void FakeReceiveSessionResponse(const std::string& host, int port) {
    rtc::AsyncHttpRequest* response = CreateAsyncHttpResponse(port);
    TestHttpPortAllocatorSession::OnRequestDone(response);
    response->Destroy(true);
  }

 private:
  // Helper method for creating a response to a relay session request.
  rtc::AsyncHttpRequest* CreateAsyncHttpResponse(int port) {
    rtc::AsyncHttpRequest* request =
        new rtc::AsyncHttpRequest(kBrowserAgent);
    std::stringstream ss;
    ss << "username=" << kUserName << std::endl
       << "password=" << kPassword << std::endl
       << "magic_cookie=" << kMagicCookie << std::endl
       << "relay.ip=" << kRelayAddr.ipaddr().ToString() << std::endl
       << "relay.udp_port=" << kRelayUdpPort << std::endl
       << "relay.tcp_port=" << kRelayTcpPort << std::endl
       << "relay.ssltcp_port=" << kRelaySsltcpPort << std::endl;
    request->response().document.reset(
        new rtc::MemoryStream(ss.str().c_str()));
    request->response().set_success();
    request->set_port(port);
    request->set_secure(port == rtc::HTTP_SECURE_PORT);
    return request;
  }
};

// Fake implementation for creating fake http sessions.
class FakeHttpPortAllocator : public HttpPortAllocator {
 public:
  FakeHttpPortAllocator(rtc::NetworkManager* network_manager,
                        const std::string& user_agent)
      : HttpPortAllocator(network_manager, user_agent) {
  }

  virtual PortAllocatorSession* CreateSessionInternal(
      const std::string& content_name, int component,
      const std::string& ice_ufrag, const std::string& ice_pwd) {
    std::vector<rtc::SocketAddress> stun_hosts;
    stun_hosts.push_back(kStunAddr);
    std::vector<std::string> relay_hosts;
    relay_hosts.push_back(kRelayHost);
    return new FakeHttpPortAllocatorSession(this,
                                            content_name,
                                            component,
                                            ice_ufrag,
                                            ice_pwd,
                                            stun_hosts,
                                            relay_hosts,
                                            kRelayToken,
                                            kBrowserAgent);
  }
};

class ConnectivityCheckerForTest : public ConnectivityChecker {
 public:
  ConnectivityCheckerForTest(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)
      : ConnectivityChecker(worker,
                            jid,
                            session_id,
                            user_agent,
                            relay_token,
                            connection),
        proxy_initiated_(false) {
  }

  rtc::FakeNetworkManager* network_manager() const {
    return network_manager_;
  }

  FakeHttpPortAllocator* port_allocator() const {
    return fake_port_allocator_;
  }

 protected:
  // Overridden methods for faking a real network.
  virtual rtc::NetworkManager* CreateNetworkManager() {
    network_manager_ = new rtc::FakeNetworkManager();
    return network_manager_;
  }
  virtual rtc::BasicPacketSocketFactory* CreateSocketFactory(
      rtc::Thread* thread) {
    // Create socket factory, for simplicity, let it run on the current thread.
    socket_factory_ =
        new rtc::BasicPacketSocketFactory(rtc::Thread::Current());
    return socket_factory_;
  }
  virtual HttpPortAllocator* CreatePortAllocator(
      rtc::NetworkManager* network_manager,
      const std::string& user_agent,
      const std::string& relay_token) {
    fake_port_allocator_ =
        new FakeHttpPortAllocator(network_manager, user_agent);
    return fake_port_allocator_;
  }
  virtual StunPort* CreateStunPort(
      const std::string& username, const std::string& password,
      const PortConfiguration* config, rtc::Network* network) {
    return new FakeStunPort(worker(), socket_factory_,
                            network, network->ip(),
                            kMinPort, kMaxPort,
                            username, password,
                            config->stun_servers);
  }
  virtual RelayPort* CreateRelayPort(
      const std::string& username, const std::string& password,
      const PortConfiguration* config, rtc::Network* network) {
    return new FakeRelayPort(worker(), socket_factory_,
                             network, network->ip(),
                             kMinPort, kMaxPort,
                             username, password);
  }
  virtual void InitiateProxyDetection() {
    if (!proxy_initiated_) {
      proxy_initiated_ = true;
      proxy_info_.address = kProxyAddr;
      proxy_info_.type = kProxyType;
      SetProxyInfo(proxy_info_);
    }
  }

  virtual rtc::ProxyInfo GetProxyInfo() const {
    return proxy_info_;
  }

 private:
  rtc::BasicPacketSocketFactory* socket_factory_;
  FakeHttpPortAllocator* fake_port_allocator_;
  rtc::FakeNetworkManager* network_manager_;
  rtc::ProxyInfo proxy_info_;
  bool proxy_initiated_;
};

class ConnectivityCheckerTest : public testing::Test {
 protected:
  void VerifyNic(const NicInfo& info,
                 const rtc::SocketAddress& local_address) {
    // Verify that the external address has been set.
    EXPECT_EQ(kExternalAddr, info.external_address);

    // Verify that the stun server address has been set.
    EXPECT_EQ(1U, info.stun_server_addresses.size());
    EXPECT_EQ(kStunAddr, *(info.stun_server_addresses.begin()));

    // Verify that the media server address has been set. Don't care
    // about port since it is different for different protocols.
    EXPECT_EQ(kRelayAddr.ipaddr(), info.media_server_address.ipaddr());

    // Verify that local ip matches.
    EXPECT_EQ(local_address.ipaddr(), info.ip);

    // Verify that we have received responses for our
    // pings. Unsuccessful ping has rtt value -1, successful >= 0.
    EXPECT_GE(info.stun.rtt, 0);
    EXPECT_GE(info.udp.rtt, 0);
    EXPECT_GE(info.tcp.rtt, 0);
    EXPECT_GE(info.ssltcp.rtt, 0);

    // If proxy has been set, verify address and type.
    if (!info.proxy_info.address.IsNil()) {
      EXPECT_EQ(kProxyAddr, info.proxy_info.address);
      EXPECT_EQ(kProxyType, info.proxy_info.type);
    }
  }
};

// Tests a configuration with two network interfaces. Verifies that 4
// combinations of ip/proxy are created and that all protocols are
// tested on each combination.
TEST_F(ConnectivityCheckerTest, TestStart) {
  ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(),
                                                  kJid,
                                                  kSessionId,
                                                  kBrowserAgent,
                                                  kRelayToken,
                                                  kConnection);
  connectivity_checker.Initialize();
  connectivity_checker.set_stun_address(kStunAddr);
  connectivity_checker.network_manager()->AddInterface(kClientAddr1);
  connectivity_checker.network_manager()->AddInterface(kClientAddr2);

  connectivity_checker.Start();
  rtc::Thread::Current()->ProcessMessages(1000);

  NicMap nics = connectivity_checker.GetResults();

  // There should be 4 nics in our map. 2 for each interface added,
  // one with proxy set and one without.
  EXPECT_EQ(4U, nics.size());

  // First verify interfaces without proxy.
  rtc::SocketAddress nilAddress;

  // First lookup the address of the first nic combined with no proxy.
  NicMap::iterator i = nics.find(NicId(kClientAddr1.ipaddr(), nilAddress));
  ASSERT(i != nics.end());
  NicInfo info = i->second;
  VerifyNic(info, kClientAddr1);

  // Then make sure the second device has been tested without proxy.
  i = nics.find(NicId(kClientAddr2.ipaddr(), nilAddress));
  ASSERT(i != nics.end());
  info = i->second;
  VerifyNic(info, kClientAddr2);

  // Now verify both interfaces with proxy.
  i = nics.find(NicId(kClientAddr1.ipaddr(), kProxyAddr));
  ASSERT(i != nics.end());
  info = i->second;
  VerifyNic(info, kClientAddr1);

  i = nics.find(NicId(kClientAddr2.ipaddr(), kProxyAddr));
  ASSERT(i != nics.end());
  info = i->second;
  VerifyNic(info, kClientAddr2);
};

// Tests that nothing bad happens if thera are no network interfaces
// available to check.
TEST_F(ConnectivityCheckerTest, TestStartNoNetwork) {
  ConnectivityCheckerForTest connectivity_checker(rtc::Thread::Current(),
                                                  kJid,
                                                  kSessionId,
                                                  kBrowserAgent,
                                                  kRelayToken,
                                                  kConnection);
  connectivity_checker.Initialize();
  connectivity_checker.Start();
  rtc::Thread::Current()->ProcessMessages(1000);

  NicMap nics = connectivity_checker.GetResults();

  // Verify that no nics where checked.
  EXPECT_EQ(0U, nics.size());
}

}  // namespace cricket
