/*
 *  Copyright 2016 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 <algorithm>
#include <list>
#include <memory>
#include <utility>
#include <vector>

#include "p2p/base/basicpacketsocketfactory.h"
#include "p2p/base/packettransportinternal.h"
#include "p2p/base/udptransport.h"
#include "rtc_base/asyncpacketsocket.h"
#include "rtc_base/gunit.h"
#include "rtc_base/ipaddress.h"
#include "rtc_base/socketaddress.h"
#include "rtc_base/socketserver.h"
#include "rtc_base/thread.h"
#include "rtc_base/virtualsocketserver.h"

namespace cricket {

constexpr int kTimeoutMs = 10000;
static const rtc::IPAddress kIPv4LocalHostAddress =
    rtc::IPAddress(0x7F000001);  // 127.0.0.1

class UdpTransportTest : public testing::Test, public sigslot::has_slots<> {
 public:
  UdpTransportTest()
      : virtual_socket_server_(new rtc::VirtualSocketServer()),
        network_thread_(virtual_socket_server_.get()),
        ep1_("Name1",
             std::unique_ptr<rtc::AsyncPacketSocket>(
                 socket_factory_.CreateUdpSocket(
                     rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
                     0,
                     0))),
        ep2_("Name2",
             std::unique_ptr<rtc::AsyncPacketSocket>(
                 socket_factory_.CreateUdpSocket(
                     rtc::SocketAddress(rtc::GetAnyIP(AF_INET), 0),
                     0,
                     0))) {
    // Setup IP Address for outgoing packets from sockets bound to IPV4
    // INADDR_ANY ("0.0.0.0."), as used above when creating the virtual
    // sockets. The virtual socket server sends these packets only if the
    // default address is explicit set. With a physical socket, the actual
    // network stack / operating system would set the IP address for outgoing
    // packets.
    virtual_socket_server_->SetDefaultRoute(kIPv4LocalHostAddress);
  }

  struct Endpoint : public sigslot::has_slots<> {
    explicit Endpoint(std::string tch_name,
                      std::unique_ptr<rtc::AsyncPacketSocket> socket) {
      ch_.reset(new UdpTransport(std::move(tch_name), std::move(socket)));
      ch_->SignalReadPacket.connect(this, &Endpoint::OnReadPacket);
      ch_->SignalSentPacket.connect(this, &Endpoint::OnSentPacket);
      ch_->SignalReadyToSend.connect(this, &Endpoint::OnReadyToSend);
      ch_->SignalWritableState.connect(this, &Endpoint::OnWritableState);
    }

    bool CheckData(const char* data, int len) {
      bool ret = false;
      if (!ch_packets_.empty()) {
        std::string packet = ch_packets_.front();
        ret = (packet == std::string(data, len));
        ch_packets_.pop_front();
      }
      return ret;
    }

    void OnWritableState(rtc::PacketTransportInternal* transport) {
      num_sig_writable_++;
    }

    void OnReadyToSend(rtc::PacketTransportInternal* transport) {
      num_sig_ready_to_send_++;
    }

    void OnReadPacket(rtc::PacketTransportInternal* transport,
                      const char* data,
                      size_t len,
                      const rtc::PacketTime& packet_time,
                      int flags) {
      num_received_packets_++;
      LOG(LS_VERBOSE) << "OnReadPacket (unittest)";
      ch_packets_.push_front(std::string(data, len));
    }

    void OnSentPacket(rtc::PacketTransportInternal* transport,
                      const rtc::SentPacket&) {
      num_sig_sent_packets_++;
    }

    int SendData(const char* data, size_t len) {
      rtc::PacketOptions options;
      return ch_->SendPacket(data, len, options, 0);
    }

    void GetLocalPort(uint16_t* local_port) {
      *local_port = ch_->GetLocalAddress().port();
    }

    std::list<std::string> ch_packets_;
    std::unique_ptr<UdpTransport> ch_;
    uint32_t num_received_packets_ = 0;   // Increases on SignalReadPacket.
    uint32_t num_sig_sent_packets_ = 0;   // Increases on SignalSentPacket.
    uint32_t num_sig_writable_ = 0;       // Increases on SignalWritable.
    uint32_t num_sig_ready_to_send_ = 0;  // Increases on SignalReadyToSend.
  };

  std::unique_ptr<rtc::VirtualSocketServer> virtual_socket_server_;
  rtc::AutoSocketServerThread network_thread_;
  // Uses current thread's socket server, which will be set by ss_scope_.
  rtc::BasicPacketSocketFactory socket_factory_;

  Endpoint ep1_;
  Endpoint ep2_;

  void TestSendRecv() {
    for (uint32_t i = 0; i < 5; ++i) {
      static const char* data = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
      int len = static_cast<int>(strlen(data));
      // local_channel <==> remote_channel
      EXPECT_EQ_WAIT(len, ep1_.SendData(data, len), kTimeoutMs);
      EXPECT_TRUE_WAIT(ep2_.CheckData(data, len), kTimeoutMs);
      EXPECT_EQ_WAIT(i + 1u, ep2_.num_received_packets_, kTimeoutMs);
      EXPECT_EQ_WAIT(len, ep2_.SendData(data, len), kTimeoutMs);
      EXPECT_TRUE_WAIT(ep1_.CheckData(data, len), kTimeoutMs);
      EXPECT_EQ_WAIT(i + 1u, ep1_.num_received_packets_, kTimeoutMs);
    }
  }
};

TEST_F(UdpTransportTest, AddressGetters) {
  // Initially, remote address should be nil but local address shouldn't be.
  EXPECT_FALSE(ep1_.ch_->GetLocalAddress().IsNil());
  EXPECT_TRUE(ep1_.ch_->GetRemoteAddress().IsNil());
  rtc::SocketAddress destination("127.0.0.1", 1337);
  ASSERT_TRUE(ep1_.ch_->SetRemoteAddress(destination));
  EXPECT_EQ(destination, ep1_.ch_->GetRemoteAddress());
}

// Setting an invalid address should fail and have no effect.
TEST_F(UdpTransportTest, SettingIncompleteRemoteAddressFails) {
  EXPECT_FALSE(ep1_.ch_->SetRemoteAddress(rtc::SocketAddress("127.0.0.1", 0)));
  EXPECT_TRUE(ep1_.ch_->GetRemoteAddress().IsNil());
}

TEST_F(UdpTransportTest, SendRecvBasic) {
  uint16_t port;
  ep2_.GetLocalPort(&port);
  rtc::SocketAddress addr2 = rtc::SocketAddress("127.0.0.1", port);
  EXPECT_TRUE(ep1_.ch_->SetRemoteAddress(addr2));
  ep1_.GetLocalPort(&port);
  rtc::SocketAddress addr1 = rtc::SocketAddress("127.0.0.1", port);
  EXPECT_TRUE(ep2_.ch_->SetRemoteAddress(addr1));
  TestSendRecv();
}

// Test the signals and state methods used internally by causing a UdpTransport
// to send a packet to itself.
TEST_F(UdpTransportTest, StatusAndSignals) {
  EXPECT_EQ(0u, ep1_.num_sig_writable_);
  EXPECT_EQ(0u, ep1_.num_sig_ready_to_send_);
  // Loopback
  EXPECT_TRUE(!ep1_.ch_->writable());
  rtc::SocketAddress addr = ep1_.ch_->GetLocalAddress();
  // Keep port, but explicitly set IP.
  addr.SetIP("127.0.0.1");
  ep1_.ch_->SetRemoteAddress(addr);
  EXPECT_TRUE(ep1_.ch_->writable());
  EXPECT_EQ(1u, ep1_.num_sig_writable_);
  EXPECT_EQ(1u, ep1_.num_sig_ready_to_send_);
  const char data[] = "abc";
  ep1_.SendData(data, sizeof(data));
  EXPECT_EQ_WAIT(1u, ep1_.ch_packets_.size(), kTimeoutMs);
  EXPECT_EQ_WAIT(1u, ep1_.num_sig_sent_packets_, kTimeoutMs);
}

}  // namespace cricket
