/*
 *  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 "webrtc/base/gunit.h"
#include "webrtc/base/thread.h"
#include "webrtc/base/asyncpacketsocket.h"
#include "webrtc/base/ipaddress.h"
#include "webrtc/base/physicalsocketserver.h"
#include "webrtc/base/socketaddress.h"
#include "webrtc/base/socketserver.h"
#include "webrtc/base/virtualsocketserver.h"
#include "webrtc/p2p/base/basicpacketsocketfactory.h"
#include "webrtc/p2p/base/packettransportinternal.h"
#include "webrtc/p2p/base/udptransport.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()
      : physical_socket_server_(new rtc::PhysicalSocketServer),
        virtual_socket_server_(
            new rtc::VirtualSocketServer(physical_socket_server_.get())),
        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::PhysicalSocketServer> physical_socket_server_;
  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
