/*
 *  Copyright 2011 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 <string>

#include "webrtc/p2p/base/basicpacketsocketfactory.h"
#include "webrtc/p2p/base/relayport.h"
#include "webrtc/p2p/base/stunport.h"
#include "webrtc/p2p/client/connectivitychecker.h"
#include "webrtc/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, std::string()) {
  }

  // 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,
#ifdef USE_WEBRTC_DEV_BRANCH
                            network->GetBestIP(),
#else  // USE_WEBRTC_DEV_BRANCH
                            network->ip(),
#endif  // USE_WEBRTC_DEV_BRANCH
                            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,
#ifdef USE_WEBRTC_DEV_BRANCH
                             network->GetBestIP(),
#else  // USE_WEBRTC_DEV_BRANCH
                             network->ip(),
#endif  // USE_WEBRTC_DEV_BRANCH
                             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
