1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <cstring> 6 #include <vector> 7 8 #include "ppapi/cpp/module.h" 9 #include "ppapi/cpp/private/net_address_private.h" 10 #include "ppapi/cpp/private/tcp_socket_private.h" 11 #include "ppapi/cpp/var.h" 12 #include "ppapi/tests/test_udp_socket_private.h" 13 #include "ppapi/tests/test_utils.h" 14 #include "ppapi/tests/testing_instance.h" 15 16 REGISTER_TEST_CASE(UDPSocketPrivate); 17 18 namespace { 19 20 const uint16_t kPortScanFrom = 1024; 21 const uint16_t kPortScanTo = 4096; 22 23 } // namespace 24 25 TestUDPSocketPrivate::TestUDPSocketPrivate( 26 TestingInstance* instance) 27 : TestCase(instance) { 28 } 29 30 bool TestUDPSocketPrivate::Init() { 31 bool tcp_socket_private_is_available = pp::TCPSocketPrivate::IsAvailable(); 32 if (!tcp_socket_private_is_available) 33 instance_->AppendError("PPB_TCPSocket_Private interface not available"); 34 35 bool udp_socket_private_is_available = pp::UDPSocketPrivate::IsAvailable(); 36 if (!udp_socket_private_is_available) 37 instance_->AppendError("PPB_UDPSocket_Private interface not available"); 38 39 bool net_address_private_is_available = pp::NetAddressPrivate::IsAvailable(); 40 if (!net_address_private_is_available) 41 instance_->AppendError("PPB_NetAddress_Private interface not available"); 42 43 bool init_host_port = GetLocalHostPort(instance_->pp_instance(), 44 &host_, &port_); 45 if (!init_host_port) 46 instance_->AppendError("Can't init host and port"); 47 48 return tcp_socket_private_is_available && 49 udp_socket_private_is_available && 50 net_address_private_is_available && 51 init_host_port && 52 CheckTestingInterface() && 53 EnsureRunningOverHTTP(); 54 } 55 56 void TestUDPSocketPrivate::RunTests(const std::string& filter) { 57 RUN_CALLBACK_TEST(TestUDPSocketPrivate, Connect, filter); 58 RUN_CALLBACK_TEST(TestUDPSocketPrivate, ConnectFailure, filter); 59 RUN_CALLBACK_TEST(TestUDPSocketPrivate, Broadcast, filter); 60 RUN_CALLBACK_TEST(TestUDPSocketPrivate, SetSocketFeatureErrors, filter); 61 } 62 63 std::string TestUDPSocketPrivate::GetLocalAddress( 64 PP_NetAddress_Private* address) { 65 pp::TCPSocketPrivate socket(instance_); 66 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 67 callback.WaitForResult( 68 socket.Connect(host_.c_str(), port_, callback.GetCallback())); 69 CHECK_CALLBACK_BEHAVIOR(callback); 70 ASSERT_EQ(PP_OK, callback.result()); 71 ASSERT_TRUE(socket.GetLocalAddress(address)); 72 socket.Disconnect(); 73 PASS(); 74 } 75 76 std::string TestUDPSocketPrivate::SetBroadcastOptions( 77 pp::UDPSocketPrivate* socket) { 78 int32_t rv = socket->SetSocketFeature( 79 PP_UDPSOCKETFEATURE_PRIVATE_ADDRESS_REUSE, pp::Var(true)); 80 if (rv != PP_OK) 81 return ReportError("PPB_UDPSocket_Private::SetSocketFeature", rv); 82 83 rv = socket->SetSocketFeature(PP_UDPSOCKETFEATURE_PRIVATE_BROADCAST, 84 pp::Var(true)); 85 if (rv != PP_OK) 86 return ReportError("PPB_UDPSocket_Private::SetSocketFeature", rv); 87 88 PASS(); 89 } 90 91 std::string TestUDPSocketPrivate::BindUDPSocket( 92 pp::UDPSocketPrivate* socket, 93 PP_NetAddress_Private* address) { 94 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 95 callback.WaitForResult(socket->Bind(address, callback.GetCallback())); 96 CHECK_CALLBACK_BEHAVIOR(callback); 97 ASSERT_EQ(PP_OK, callback.result()); 98 PASS(); 99 } 100 101 std::string TestUDPSocketPrivate::LookupPortAndBindUDPSocket( 102 pp::UDPSocketPrivate* socket, 103 PP_NetAddress_Private *address) { 104 PP_NetAddress_Private base_address; 105 ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address)); 106 107 bool is_free_port_found = false; 108 for (uint16_t port = kPortScanFrom; port < kPortScanTo; ++port) { 109 if (!pp::NetAddressPrivate::ReplacePort(base_address, port, address)) 110 return "PPB_NetAddress_Private::ReplacePort: Failed"; 111 if (BindUDPSocket(socket, address).empty()) { 112 is_free_port_found = true; 113 break; 114 } 115 } 116 if (!is_free_port_found) 117 return "Can't find available port"; 118 if (!socket->GetBoundAddress(address)) 119 return "PPB_UDPSocket_Private::GetBoundAddress: Failed"; 120 PASS(); 121 } 122 123 std::string TestUDPSocketPrivate::BindUDPSocketFailure( 124 pp::UDPSocketPrivate* socket, 125 PP_NetAddress_Private *address) { 126 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 127 callback.WaitForResult(socket->Bind(address, callback.GetCallback())); 128 CHECK_CALLBACK_BEHAVIOR(callback); 129 ASSERT_NE(PP_OK, callback.result()); 130 ASSERT_FALSE(socket->GetBoundAddress(address)); 131 PASS(); 132 } 133 134 std::string TestUDPSocketPrivate::ReadSocket(pp::UDPSocketPrivate* socket, 135 PP_NetAddress_Private* address, 136 size_t size, 137 std::string* message) { 138 std::vector<char> buffer(size); 139 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 140 callback.WaitForResult( 141 socket->RecvFrom(&buffer[0], size, callback.GetCallback())); 142 CHECK_CALLBACK_BEHAVIOR(callback); 143 ASSERT_FALSE(callback.result() < 0); 144 ASSERT_EQ(size, static_cast<size_t>(callback.result())); 145 message->assign(buffer.begin(), buffer.end()); 146 PASS(); 147 } 148 149 std::string TestUDPSocketPrivate::PassMessage(pp::UDPSocketPrivate* target, 150 pp::UDPSocketPrivate* source, 151 PP_NetAddress_Private* address, 152 const std::string& message) { 153 TestCompletionCallback callback(instance_->pp_instance(), callback_type()); 154 int32_t rv = source->SendTo(message.c_str(), message.size(), address, 155 callback.GetCallback()); 156 std::string str; 157 ASSERT_SUBTEST_SUCCESS(ReadSocket(target, address, message.size(), &str)); 158 159 callback.WaitForResult(rv); 160 CHECK_CALLBACK_BEHAVIOR(callback); 161 ASSERT_FALSE(callback.result() < 0); 162 ASSERT_EQ(message.size(), static_cast<size_t>(callback.result())); 163 ASSERT_EQ(message, str); 164 PASS(); 165 } 166 167 std::string TestUDPSocketPrivate::TestConnect() { 168 pp::UDPSocketPrivate server_socket(instance_), client_socket(instance_); 169 PP_NetAddress_Private server_address, client_address; 170 171 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket, 172 &server_address)); 173 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket, 174 &client_address)); 175 const std::string message = "Simple message that will be sent via UDP"; 176 ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket, &client_socket, 177 &server_address, 178 message)); 179 PP_NetAddress_Private recv_from_address; 180 ASSERT_TRUE(server_socket.GetRecvFromAddress(&recv_from_address)); 181 ASSERT_TRUE(pp::NetAddressPrivate::AreEqual(recv_from_address, 182 client_address)); 183 184 server_socket.Close(); 185 client_socket.Close(); 186 187 if (server_socket.GetBoundAddress(&server_address)) 188 return "PPB_UDPSocket_Private::GetBoundAddress: expected Failure"; 189 PASS(); 190 } 191 192 std::string TestUDPSocketPrivate::TestConnectFailure() { 193 pp::UDPSocketPrivate socket(instance_); 194 PP_NetAddress_Private invalid_address = {}; 195 196 std::string error_message = BindUDPSocketFailure(&socket, &invalid_address); 197 if (!error_message.empty()) 198 return error_message; 199 200 PASS(); 201 } 202 203 std::string TestUDPSocketPrivate::TestBroadcast() { 204 const uint8_t broadcast_ip[4] = { 0xff, 0xff, 0xff, 0xff }; 205 206 pp::UDPSocketPrivate server1(instance_), server2(instance_); 207 208 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1)); 209 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2)); 210 PP_NetAddress_Private server_address; 211 ASSERT_TRUE(pp::NetAddressPrivate::GetAnyAddress(false, &server_address)); 212 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1, &server_address)); 213 // Fill port field of |server_address|. 214 ASSERT_TRUE(server1.GetBoundAddress(&server_address)); 215 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2, &server_address)); 216 217 const uint16_t port = pp::NetAddressPrivate::GetPort(server_address); 218 PP_NetAddress_Private broadcast_address; 219 ASSERT_TRUE(pp::NetAddressPrivate::CreateFromIPv4Address( 220 broadcast_ip, port, &broadcast_address)); 221 222 std::string message; 223 const std::string first_message = "first message"; 224 const std::string second_message = "second_message"; 225 226 ASSERT_SUBTEST_SUCCESS(PassMessage(&server1, &server2, 227 &broadcast_address, 228 first_message)); 229 // |first_message| also arrived to |server2|. 230 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2, &broadcast_address, 231 first_message.size(), &message)); 232 ASSERT_EQ(first_message, message); 233 234 ASSERT_SUBTEST_SUCCESS(PassMessage(&server2, &server1, 235 &broadcast_address, 236 second_message)); 237 // |second_message| also arrived to |server1|. 238 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1, &broadcast_address, 239 second_message.size(), &message)); 240 ASSERT_EQ(second_message, message); 241 242 server1.Close(); 243 server2.Close(); 244 PASS(); 245 } 246 247 std::string TestUDPSocketPrivate::TestSetSocketFeatureErrors() { 248 pp::UDPSocketPrivate socket(instance_); 249 // Try to pass incorrect feature name. 250 int32_t rv = socket.SetSocketFeature(PP_UDPSOCKETFEATURE_PRIVATE_COUNT, 251 pp::Var(true)); 252 ASSERT_EQ(PP_ERROR_BADARGUMENT, rv); 253 254 // Try to pass incorrect feature value's type. 255 rv = socket.SetSocketFeature(PP_UDPSOCKETFEATURE_PRIVATE_ADDRESS_REUSE, 256 pp::Var(1)); 257 ASSERT_EQ(PP_ERROR_BADARGUMENT, rv); 258 PASS(); 259 } 260