17d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
27d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
37d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// found in the LICENSE file.
47d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/tests/test_udp_socket.h"
67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
77d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include <vector>
87d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
97d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/cpp/pass_ref.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/cpp/tcp_socket.h"
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "ppapi/cpp/udp_socket.h"
127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/cpp/var.h"
137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/tests/test_utils.h"
147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ppapi/tests/testing_instance.h"
157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)REGISTER_TEST_CASE(UDPSocket);
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)namespace {
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const uint16_t kPortScanFrom = 1024;
217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const uint16_t kPortScanTo = 4096;
227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
23eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochpp::NetAddress ReplacePort(const pp::InstanceHandle& instance,
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           const pp::NetAddress& addr,
25eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                           uint16_t port) {
267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  switch (addr.GetFamily()) {
277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case PP_NETADDRESS_FAMILY_IPV4: {
28eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_NetAddress_IPv4 ipv4_addr;
297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!addr.DescribeAsIPv4Address(&ipv4_addr))
307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        break;
317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ipv4_addr.port = ConvertToNetEndian16(port);
32eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return pp::NetAddress(instance, ipv4_addr);
337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case PP_NETADDRESS_FAMILY_IPV6: {
35eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_NetAddress_IPv6 ipv6_addr;
367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!addr.DescribeAsIPv6Address(&ipv6_addr))
377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        break;
387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ipv6_addr.port = ConvertToNetEndian16(port);
39eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      return pp::NetAddress(instance, ipv6_addr);
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    default: {
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      PP_NOTREACHED();
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
45eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  return pp::NetAddress();
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}  // namespace
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)TestUDPSocket::TestUDPSocket(TestingInstance* instance) : TestCase(instance) {
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool TestUDPSocket::Init() {
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool tcp_socket_is_available = pp::TCPSocket::IsAvailable();
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!tcp_socket_is_available)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    instance_->AppendError("PPB_TCPSocket interface not available");
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool udp_socket_is_available = pp::UDPSocket::IsAvailable();
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!udp_socket_is_available)
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    instance_->AppendError("PPB_UDPSocket interface not available");
617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  bool net_address_is_available = pp::NetAddress::IsAvailable();
637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!net_address_is_available)
647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    instance_->AppendError("PPB_NetAddress interface not available");
657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string host;
677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  uint16_t port = 0;
687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool init_address =
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GetLocalHostPort(instance_->pp_instance(), &host, &port) &&
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      ResolveHost(instance_->pp_instance(), host, port, &address_);
717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!init_address)
727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    instance_->AppendError("Can't init address");
737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return tcp_socket_is_available &&
757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      udp_socket_is_available &&
767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      net_address_is_available &&
777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      init_address &&
787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      CheckTestingInterface() &&
797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      EnsureRunningOverHTTP();
807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void TestUDPSocket::RunTests(const std::string& filter) {
837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RUN_CALLBACK_TEST(TestUDPSocket, ReadWrite, filter);
847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RUN_CALLBACK_TEST(TestUDPSocket, Broadcast, filter);
857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RUN_CALLBACK_TEST(TestUDPSocket, SetOption, filter);
867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TestUDPSocket::GetLocalAddress(pp::NetAddress* address) {
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::TCPSocket socket(instance_);
907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(socket.Connect(address_, callback.GetCallback()));
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *address = socket.GetLocalAddress();
957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_NE(0, address->pp_resource());
967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  socket.Close();
977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TestUDPSocket::SetBroadcastOptions(pp::UDPSocket* socket) {
1017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback_1(instance_->pp_instance(), callback_type());
1027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback_1.WaitForResult(socket->SetOption(
1037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
1047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      callback_1.GetCallback()));
1057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_1);
1067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback_1.result());
1077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback_2(instance_->pp_instance(), callback_type());
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback_2.WaitForResult(socket->SetOption(
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback_2.GetCallback()));
1117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback_2);
1127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback_2.result());
1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
1157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TestUDPSocket::BindUDPSocket(pp::UDPSocket* socket,
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                         const pp::NetAddress& address) {
1197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(socket->Bind(address, callback.GetCallback()));
1217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_OK, callback.result());
1237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
1247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string TestUDPSocket::LookupPortAndBindUDPSocket(
127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::UDPSocket* socket,
128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::NetAddress* address) {
129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress base_address;
1307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address));
1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  bool is_free_port_found = false;
1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (uint16_t port = kPortScanFrom; port < kPortScanTo; ++port) {
134eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    pp::NetAddress new_address = ReplacePort(instance_, base_address, port);
1357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    ASSERT_NE(0, new_address.pp_resource());
1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (BindUDPSocket(socket, new_address).empty()) {
1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      is_free_port_found = true;
1387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      break;
1397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
1407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
1417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (!is_free_port_found)
1427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return "Can't find available port";
1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *address = socket->GetBoundAddress();
1457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_NE(0, address->pp_resource());
1467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
1487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TestUDPSocket::ReadSocket(pp::UDPSocket* socket,
151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                      pp::NetAddress* address,
1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      size_t size,
1537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                      std::string* message) {
1547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::vector<char> buffer(size);
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  TestCompletionCallbackWithOutput<pp::NetAddress> callback(
1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      instance_->pp_instance(), callback_type());
1577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(
1587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      socket->RecvFrom(&buffer[0], size, callback.GetCallback()));
1597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_FALSE(callback.result() < 0);
1617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(size, static_cast<size_t>(callback.result()));
1627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  *address = callback.output();
1637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  message->assign(buffer.begin(), buffer.end());
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
1657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
167eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstd::string TestUDPSocket::PassMessage(pp::UDPSocket* target,
168eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       pp::UDPSocket* source,
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       const pp::NetAddress& target_address,
1707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       const std::string& message,
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                                       pp::NetAddress* recvfrom_address) {
1727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  int32_t rv = source->SendTo(message.c_str(), message.size(),
1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                              target_address,
1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                              callback.GetCallback());
1767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string str;
1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(ReadSocket(target, recvfrom_address, message.size(),
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    &str));
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(rv);
1817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
1827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_FALSE(callback.result() < 0);
1837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(message.size(), static_cast<size_t>(callback.result()));
1847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(message, str);
1857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
1867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
1877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string TestUDPSocket::TestReadWrite() {
189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::UDPSocket server_socket(instance_), client_socket(instance_);
190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress server_address, client_address;
1917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket,
1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                    &server_address));
1947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket,
1957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                                    &client_address));
1967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const std::string message = "Simple message that will be sent via UDP";
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress recvfrom_address;
1987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, &client_socket,
1997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     server_address, message,
2007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     &recvfrom_address));
2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(EqualNetAddress(recvfrom_address, client_address));
2027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  server_socket.Close();
2047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  client_socket.Close();
2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (server_socket.GetBoundAddress().pp_resource() != 0)
2077d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return "PPB_UDPSocket::GetBoundAddress: expected failure";
2087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string TestUDPSocket::TestBroadcast() {
213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::UDPSocket server1(instance_), server2(instance_);
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1));
2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2));
2177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
218eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PP_NetAddress_IPv4 any_ipv4_address = { 0, { 0, 0, 0, 0 } };
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress any_address(instance_, any_ipv4_address);
2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1, any_address));
2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Fill port field of |server_address|.
222eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress server_address = server1.GetBoundAddress();
2237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_NE(0, server_address.pp_resource());
2247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2, server_address));
2257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PP_NetAddress_IPv4 server_ipv4_address;
2277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_TRUE(server_address.DescribeAsIPv4Address(&server_ipv4_address));
2287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
229eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  PP_NetAddress_IPv4 broadcast_ipv4_address = {
2307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    server_ipv4_address.port, { 0xff, 0xff, 0xff, 0xff }
2317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  };
232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress broadcast_address(instance_, broadcast_ipv4_address);
2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  std::string message;
2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const std::string first_message = "first message";
2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const std::string second_message = "second_message";
2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress recvfrom_address;
2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(PassMessage(&server1, &server2, broadcast_address,
2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     first_message, &recvfrom_address));
2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |first_message| was also received by |server2|.
2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2, &recvfrom_address,
2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    first_message.size(), &message));
2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(first_message, message);
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(PassMessage(&server2, &server1, broadcast_address,
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                     second_message, &recvfrom_address));
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // |second_message| was also received by |server1|.
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1, &recvfrom_address,
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                    second_message.size(), &message));
2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(second_message, message);
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  server1.Close();
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  server2.Close();
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)std::string TestUDPSocket::TestSetOption() {
259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::UDPSocket socket(instance_);
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket));
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Try to pass incorrect option value's type.
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  TestCompletionCallback callback(instance_->pp_instance(), callback_type());
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  callback.WaitForResult(socket.SetOption(
2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(1), callback.GetCallback()));
2677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK_CALLBACK_BEHAVIOR(callback);
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  ASSERT_EQ(PP_ERROR_BADARGUMENT, callback.result());
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(false), callback.GetCallback()));
272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_OK, callback.result());
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // SEND_BUFFER_SIZE and RECV_BUFFER_SIZE shouldn't be set before the socket is
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // bound.
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(4096),
279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.GetCallback()));
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(512),
285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.GetCallback()));
286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  pp::NetAddress address;
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&socket, &address));
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // ADDRESS_REUSE and BROADCAST won't take effect after the socket is bound.
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_ADDRESS_REUSE, pp::Var(true),
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.GetCallback()));
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_BROADCAST, pp::Var(true), callback.GetCallback()));
301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_ERROR_FAILED, callback.result());
303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  // SEND_BUFFER_SIZE and RECV_BUFFER_SIZE can be set after the socket is bound.
305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE, pp::Var(2048),
307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.GetCallback()));
308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_OK, callback.result());
310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  callback.WaitForResult(socket.SetOption(
312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE, pp::Var(1024),
313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      callback.GetCallback()));
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  CHECK_CALLBACK_BEHAVIOR(callback);
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ASSERT_EQ(PP_OK, callback.result());
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
3177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  PASS();
3187d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
319