// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ppapi/tests/test_udp_socket.h"

#include <vector>

#include "ppapi/cpp/pass_ref.h"
#include "ppapi/cpp/tcp_socket.h"
#include "ppapi/cpp/udp_socket.h"
#include "ppapi/cpp/var.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(UDPSocket);

namespace {

const uint16_t kPortScanFrom = 1024;
const uint16_t kPortScanTo = 4096;

pp::NetAddress ReplacePort(const pp::InstanceHandle& instance,
                           const pp::NetAddress& addr,
                           uint16_t port) {
  switch (addr.GetFamily()) {
    case PP_NETADDRESS_FAMILY_IPV4: {
      PP_NetAddress_IPv4 ipv4_addr;
      if (!addr.DescribeAsIPv4Address(&ipv4_addr))
        break;
      ipv4_addr.port = ConvertToNetEndian16(port);
      return pp::NetAddress(instance, ipv4_addr);
    }
    case PP_NETADDRESS_FAMILY_IPV6: {
      PP_NetAddress_IPv6 ipv6_addr;
      if (!addr.DescribeAsIPv6Address(&ipv6_addr))
        break;
      ipv6_addr.port = ConvertToNetEndian16(port);
      return pp::NetAddress(instance, ipv6_addr);
    }
    default: {
      PP_NOTREACHED();
    }
  }
  return pp::NetAddress();
}

}  // namespace

TestUDPSocket::TestUDPSocket(TestingInstance* instance)
    : TestCase(instance),
      socket_interface_1_0_(NULL),
      socket_interface_1_1_(NULL) {
}

bool TestUDPSocket::Init() {
  bool tcp_socket_is_available = pp::TCPSocket::IsAvailable();
  if (!tcp_socket_is_available)
    instance_->AppendError("PPB_TCPSocket interface not available");

  bool udp_socket_is_available = pp::UDPSocket::IsAvailable();
  if (!udp_socket_is_available)
    instance_->AppendError("PPB_UDPSocket interface not available");

  bool net_address_is_available = pp::NetAddress::IsAvailable();
  if (!net_address_is_available)
    instance_->AppendError("PPB_NetAddress interface not available");

  std::string host;
  uint16_t port = 0;
  bool init_address =
      GetLocalHostPort(instance_->pp_instance(), &host, &port) &&
      ResolveHost(instance_->pp_instance(), host, port, &address_);
  if (!init_address)
    instance_->AppendError("Can't init address");

  socket_interface_1_0_ =
      static_cast<const PPB_UDPSocket_1_0*>(
          pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_0));
  if (!socket_interface_1_0_)
    instance_->AppendError("PPB_UDPSocket_1_0 interface not available");

  socket_interface_1_1_ =
      static_cast<const PPB_UDPSocket_1_1*>(
          pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_1));
  if (!socket_interface_1_1_)
    instance_->AppendError("PPB_UDPSocket_1_1 interface not available");

  return tcp_socket_is_available &&
      udp_socket_is_available &&
      net_address_is_available &&
      init_address &&
      CheckTestingInterface() &&
      EnsureRunningOverHTTP() &&
      socket_interface_1_0_ != NULL &&
      socket_interface_1_1_ != NULL;
}

void TestUDPSocket::RunTests(const std::string& filter) {
  RUN_CALLBACK_TEST(TestUDPSocket, ReadWrite, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, Broadcast, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption_1_0, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption_1_1, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, SetOption, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, ParallelSend, filter);
  RUN_CALLBACK_TEST(TestUDPSocket, Multicast, filter);
}

std::string TestUDPSocket::GetLocalAddress(pp::NetAddress* address) {
  pp::TCPSocket socket(instance_);
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.Connect(address_, callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());
  *address = socket.GetLocalAddress();
  ASSERT_NE(0, address->pp_resource());
  socket.Close();
  PASS();
}

std::string TestUDPSocket::SetBroadcastOptions(pp::UDPSocket* socket) {
  TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
  callback_1.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
      callback_1.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback_1);
  ASSERT_EQ(PP_OK, callback_1.result());

  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
  callback_2.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback_2);
  ASSERT_EQ(PP_OK, callback_2.result());

  PASS();
}

std::string TestUDPSocket::BindUDPSocket(pp::UDPSocket* socket,
                                         const pp::NetAddress& address) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket->Bind(address, callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());
  PASS();
}

std::string TestUDPSocket::LookupPortAndBindUDPSocket(
    pp::UDPSocket* socket,
    pp::NetAddress* address) {
  pp::NetAddress base_address;
  ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address));

  bool is_free_port_found = false;
  std::string ret;
  for (uint16_t port = kPortScanFrom; port < kPortScanTo; ++port) {
    pp::NetAddress new_address = ReplacePort(instance_, base_address, port);
    ASSERT_NE(0, new_address.pp_resource());
    ret = BindUDPSocket(socket, new_address);
    if (ret.empty()) {
      is_free_port_found = true;
      break;
    }
  }
  if (!is_free_port_found)
    return "Can't find available port (" + ret + ")";

  *address = socket->GetBoundAddress();
  ASSERT_NE(0, address->pp_resource());

  PASS();
}

std::string TestUDPSocket::ReadSocket(pp::UDPSocket* socket,
                                      pp::NetAddress* address,
                                      size_t size,
                                      std::string* message) {
  std::vector<char> buffer(size);
  TestCompletionCallbackWithOutput<pp::NetAddress> callback(
      instance_->pp_instance(), callback_type());
  callback.WaitForResult(
      socket->RecvFrom(&buffer[0], static_cast<int32_t>(size),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_FALSE(callback.result() < 0);
  ASSERT_EQ(size, static_cast<size_t>(callback.result()));
  *address = callback.output();
  message->assign(buffer.begin(), buffer.end());
  PASS();
}

std::string TestUDPSocket::PassMessage(pp::UDPSocket* target,
                                       pp::UDPSocket* source,
                                       const pp::NetAddress& target_address,
                                       const std::string& message,
                                       pp::NetAddress* recvfrom_address) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  int32_t rv = source->SendTo(message.c_str(),
                              static_cast<int32_t>(message.size()),
                              target_address,
                              callback.GetCallback());
  std::string str;
  ASSERT_SUBTEST_SUCCESS(ReadSocket(target, recvfrom_address, message.size(),
                                    &str));

  callback.WaitForResult(rv);
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_FALSE(callback.result() < 0);
  ASSERT_EQ(message.size(), static_cast<size_t>(callback.result()));
  ASSERT_EQ(message, str);
  PASS();
}

std::string TestUDPSocket::SetMulticastOptions(pp::UDPSocket* socket) {
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_LOOP, pp::Var(true),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket->SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  PASS();
}

std::string TestUDPSocket::TestReadWrite() {
  pp::UDPSocket server_socket(instance_), client_socket(instance_);
  pp::NetAddress server_address, client_address;

  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket,
                                                    &server_address));
  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket,
                                                    &client_address));
  const std::string message = "Simple message that will be sent via UDP";
  pp::NetAddress recvfrom_address;
  ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, &client_socket,
                                     server_address, message,
                                     &recvfrom_address));
  ASSERT_TRUE(EqualNetAddress(recvfrom_address, client_address));

  server_socket.Close();
  client_socket.Close();

  if (server_socket.GetBoundAddress().pp_resource() != 0)
    return "PPB_UDPSocket::GetBoundAddress: expected failure";

  PASS();
}

std::string TestUDPSocket::TestBroadcast() {
  pp::UDPSocket server1(instance_), server2(instance_);

  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1));
  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2));

  PP_NetAddress_IPv4 any_ipv4_address = { 0, { 0, 0, 0, 0 } };
  pp::NetAddress any_address(instance_, any_ipv4_address);
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1, any_address));
  // Fill port field of |server_address|.
  pp::NetAddress server_address = server1.GetBoundAddress();
  ASSERT_NE(0, server_address.pp_resource());
  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2, server_address));

  PP_NetAddress_IPv4 server_ipv4_address;
  ASSERT_TRUE(server_address.DescribeAsIPv4Address(&server_ipv4_address));

  PP_NetAddress_IPv4 broadcast_ipv4_address = {
    server_ipv4_address.port, { 0xff, 0xff, 0xff, 0xff }
  };
  pp::NetAddress broadcast_address(instance_, broadcast_ipv4_address);

  std::string message;
  const std::string first_message = "first message";
  const std::string second_message = "second_message";

  pp::NetAddress recvfrom_address;
  ASSERT_SUBTEST_SUCCESS(PassMessage(&server1, &server2, broadcast_address,
                                     first_message, &recvfrom_address));
  // |first_message| was also received by |server2|.
  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2, &recvfrom_address,
                                    first_message.size(), &message));
  ASSERT_EQ(first_message, message);

  ASSERT_SUBTEST_SUCCESS(PassMessage(&server2, &server1, broadcast_address,
                                     second_message, &recvfrom_address));
  // |second_message| was also received by |server1|.
  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1, &recvfrom_address,
                                    second_message.size(), &message));
  ASSERT_EQ(second_message, message);

  server1.Close();
  server2.Close();
  PASS();
}

int32_t TestUDPSocket::SetOptionValue(UDPSocketSetOption func,
                                      PP_Resource socket,
                                      PP_UDPSocket_Option option,
                                      const PP_Var& value) {
  PP_TimeTicks start_time(NowInTimeTicks());
  TestCompletionCallback cb(instance_->pp_instance(), callback_type());
  cb.WaitForResult(func(socket, option, value,
                        cb.GetCallback().pp_completion_callback()));

  // Expanded from CHECK_CALLBACK_BEHAVIOR macro.
  if (cb.failed()) {
    std::string msg = MakeFailureMessage(__FILE__, __LINE__,
                                         cb.errors().c_str());

    instance_->LogTest("SetOptionValue", msg, start_time);
    return PP_ERROR_FAILED;
  }
  return cb.result();
}

std::string TestUDPSocket::TestSetOption_1_0() {
  PP_Resource socket = socket_interface_1_0_->Create(instance_->pp_instance());
  ASSERT_NE(0, socket);

  // Multicast options are not supported in interface 1.0.
  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_0_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_LOOP,
                           PP_MakeBool(PP_TRUE)));

  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_0_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_TTL,
                           PP_MakeInt32(1)));

  socket_interface_1_0_->Close(socket);
  pp::Module::Get()->core()->ReleaseResource(socket);

  PASS();
}

std::string TestUDPSocket::TestSetOption_1_1() {
  PP_Resource socket = socket_interface_1_1_->Create(instance_->pp_instance());
  ASSERT_NE(0, socket);

  // Multicast options are not supported in interface 1.1.
  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_1_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_LOOP,
                           PP_MakeBool(PP_TRUE)));

  ASSERT_EQ(PP_ERROR_BADARGUMENT,
            SetOptionValue(socket_interface_1_1_->SetOption,
                           socket,
                           PP_UDPSOCKET_OPTION_MULTICAST_TTL,
                           PP_MakeInt32(1)));

  socket_interface_1_1_->Close(socket);
  pp::Module::Get()->core()->ReleaseResource(socket);

  PASS();
}

std::string TestUDPSocket::TestSetOption() {
  pp::UDPSocket socket(instance_);

  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket));
  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&socket));

  // Try to pass incorrect option value's type.
  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  // Invalid multicast TTL values (less than 0 and greater than 255).
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(-1), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_MULTICAST_TTL, pp::Var(256), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(false), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(4096),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(512),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  pp::NetAddress address;
  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&socket, &address));

  // ADDRESS_REUSE won't take effect after the socket is bound.
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_ERROR_FAILED, callback.result());

  // BROADCAST, SEND_BUFFER_SIZE and RECV_BUFFER_SIZE can be set after the
  // socket is bound.
  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(2048),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  callback.WaitForResult(socket.SetOption(
      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(1024),
      callback.GetCallback()));
  CHECK_CALLBACK_BEHAVIOR(callback);
  ASSERT_EQ(PP_OK, callback.result());

  PASS();
}

std::string TestUDPSocket::TestParallelSend() {
  // This test only makes sense when callbacks are optional.
  if (callback_type() != PP_OPTIONAL)
    PASS();

  pp::UDPSocket server_socket(instance_), client_socket(instance_);
  pp::NetAddress server_address, client_address;

  ASSERT_SUBTEST_SUCCESS(
      LookupPortAndBindUDPSocket(&server_socket, &server_address));
  ASSERT_SUBTEST_SUCCESS(
      LookupPortAndBindUDPSocket(&client_socket, &client_address));
  const std::string message = "Simple message that will be sent via UDP";
  pp::NetAddress recvfrom_address;

  const size_t kParallelSends = 10;
  std::vector<TestCompletionCallback*> sendto_callbacks(kParallelSends);
  std::vector<int32_t> sendto_results(kParallelSends);
  size_t pending = 0;
  for (size_t i = 0; i < kParallelSends; i++) {
    sendto_callbacks[i] =
        new TestCompletionCallback(instance_->pp_instance(), callback_type());
    sendto_results[i] =
        client_socket.SendTo(message.c_str(),
                             static_cast<int32_t>(message.size()),
                             server_address,
                             sendto_callbacks[i]->GetCallback());

    if (sendto_results[i] == PP_ERROR_INPROGRESS) {
      // Run a pending send to completion to free a slot for the current send.
      ASSERT_GT(i, pending);
      sendto_callbacks[pending]->WaitForResult(sendto_results[pending]);
      CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks[pending]);
      ASSERT_EQ(message.size(),
                static_cast<size_t>(sendto_callbacks[pending]->result()));
      pending++;
      // Try to send the message again.
      sendto_results[i] =
          client_socket.SendTo(message.c_str(),
                               static_cast<int32_t>(message.size()),
                               server_address,
                               sendto_callbacks[i]->GetCallback());
      ASSERT_NE(PP_ERROR_INPROGRESS, sendto_results[i]);
    }
  }

  // Finish all pending sends.
  for (size_t i = pending; i < kParallelSends; i++) {
    sendto_callbacks[i]->WaitForResult(sendto_results[i]);
    CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks[i]);
    ASSERT_EQ(message.size(),
              static_cast<size_t>(sendto_callbacks[i]->result()));
  }

  for (size_t i = 0; i < kParallelSends; ++i)
    delete sendto_callbacks[i];

  for (size_t i = 0; i < kParallelSends; i++) {
    std::string str;
    ASSERT_SUBTEST_SUCCESS(
        ReadSocket(&server_socket, &recvfrom_address, message.size(), &str));
    ASSERT_EQ(message, str);
  }

  server_socket.Close();
  client_socket.Close();

  PASS();
}

std::string TestUDPSocket::TestMulticast() {
  pp::UDPSocket server1(instance_), server2(instance_);

  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server1));
  ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server2));

  server1.Close();
  server2.Close();

  PASS();
}
