1 // Copyright 2013 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.
5 #include "ppapi/tests/test_udp_socket.h"
9 #include "ppapi/cpp/pass_ref.h"
10 #include "ppapi/cpp/tcp_socket.h"
11 #include "ppapi/cpp/udp_socket.h"
12 #include "ppapi/cpp/var.h"
13 #include "ppapi/tests/test_utils.h"
14 #include "ppapi/tests/testing_instance.h"
16 REGISTER_TEST_CASE(UDPSocket
);
20 const uint16_t kPortScanFrom
= 1024;
21 const uint16_t kPortScanTo
= 4096;
23 pp::NetAddress
ReplacePort(const pp::InstanceHandle
& instance
,
24 const pp::NetAddress
& addr
,
26 switch (addr
.GetFamily()) {
27 case PP_NETADDRESS_FAMILY_IPV4
: {
28 PP_NetAddress_IPv4 ipv4_addr
;
29 if (!addr
.DescribeAsIPv4Address(&ipv4_addr
))
31 ipv4_addr
.port
= ConvertToNetEndian16(port
);
32 return pp::NetAddress(instance
, ipv4_addr
);
34 case PP_NETADDRESS_FAMILY_IPV6
: {
35 PP_NetAddress_IPv6 ipv6_addr
;
36 if (!addr
.DescribeAsIPv6Address(&ipv6_addr
))
38 ipv6_addr
.port
= ConvertToNetEndian16(port
);
39 return pp::NetAddress(instance
, ipv6_addr
);
45 return pp::NetAddress();
50 TestUDPSocket::TestUDPSocket(TestingInstance
* instance
)
52 socket_interface_1_0_(NULL
),
53 socket_interface_1_1_(NULL
) {
56 bool TestUDPSocket::Init() {
57 bool tcp_socket_is_available
= pp::TCPSocket::IsAvailable();
58 if (!tcp_socket_is_available
)
59 instance_
->AppendError("PPB_TCPSocket interface not available");
61 bool udp_socket_is_available
= pp::UDPSocket::IsAvailable();
62 if (!udp_socket_is_available
)
63 instance_
->AppendError("PPB_UDPSocket interface not available");
65 bool net_address_is_available
= pp::NetAddress::IsAvailable();
66 if (!net_address_is_available
)
67 instance_
->AppendError("PPB_NetAddress interface not available");
72 GetLocalHostPort(instance_
->pp_instance(), &host
, &port
) &&
73 ResolveHost(instance_
->pp_instance(), host
, port
, &address_
);
75 instance_
->AppendError("Can't init address");
77 socket_interface_1_0_
=
78 static_cast<const PPB_UDPSocket_1_0
*>(
79 pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_0
));
80 if (!socket_interface_1_0_
)
81 instance_
->AppendError("PPB_UDPSocket_1_0 interface not available");
83 socket_interface_1_1_
=
84 static_cast<const PPB_UDPSocket_1_1
*>(
85 pp::Module::Get()->GetBrowserInterface(PPB_UDPSOCKET_INTERFACE_1_1
));
86 if (!socket_interface_1_1_
)
87 instance_
->AppendError("PPB_UDPSocket_1_1 interface not available");
89 return tcp_socket_is_available
&&
90 udp_socket_is_available
&&
91 net_address_is_available
&&
93 CheckTestingInterface() &&
94 EnsureRunningOverHTTP() &&
95 socket_interface_1_0_
!= NULL
&&
96 socket_interface_1_1_
!= NULL
;
99 void TestUDPSocket::RunTests(const std::string
& filter
) {
100 RUN_CALLBACK_TEST(TestUDPSocket
, ReadWrite
, filter
);
101 RUN_CALLBACK_TEST(TestUDPSocket
, Broadcast
, filter
);
102 RUN_CALLBACK_TEST(TestUDPSocket
, SetOption_1_0
, filter
);
103 RUN_CALLBACK_TEST(TestUDPSocket
, SetOption_1_1
, filter
);
104 RUN_CALLBACK_TEST(TestUDPSocket
, SetOption
, filter
);
105 RUN_CALLBACK_TEST(TestUDPSocket
, ParallelSend
, filter
);
106 RUN_CALLBACK_TEST(TestUDPSocket
, Multicast
, filter
);
109 std::string
TestUDPSocket::GetLocalAddress(pp::NetAddress
* address
) {
110 pp::TCPSocket
socket(instance_
);
111 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
112 callback
.WaitForResult(socket
.Connect(address_
, callback
.GetCallback()));
113 CHECK_CALLBACK_BEHAVIOR(callback
);
114 ASSERT_EQ(PP_OK
, callback
.result());
115 *address
= socket
.GetLocalAddress();
116 ASSERT_NE(0, address
->pp_resource());
121 std::string
TestUDPSocket::SetBroadcastOptions(pp::UDPSocket
* socket
) {
122 TestCompletionCallback
callback_1(instance_
->pp_instance(), callback_type());
123 callback_1
.WaitForResult(socket
->SetOption(
124 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(true),
125 callback_1
.GetCallback()));
126 CHECK_CALLBACK_BEHAVIOR(callback_1
);
127 ASSERT_EQ(PP_OK
, callback_1
.result());
129 TestCompletionCallback
callback_2(instance_
->pp_instance(), callback_type());
130 callback_2
.WaitForResult(socket
->SetOption(
131 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(true), callback_2
.GetCallback()));
132 CHECK_CALLBACK_BEHAVIOR(callback_2
);
133 ASSERT_EQ(PP_OK
, callback_2
.result());
138 std::string
TestUDPSocket::BindUDPSocket(pp::UDPSocket
* socket
,
139 const pp::NetAddress
& address
) {
140 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
141 callback
.WaitForResult(socket
->Bind(address
, callback
.GetCallback()));
142 CHECK_CALLBACK_BEHAVIOR(callback
);
143 ASSERT_EQ(PP_OK
, callback
.result());
147 std::string
TestUDPSocket::LookupPortAndBindUDPSocket(
148 pp::UDPSocket
* socket
,
149 pp::NetAddress
* address
) {
150 pp::NetAddress base_address
;
151 ASSERT_SUBTEST_SUCCESS(GetLocalAddress(&base_address
));
153 bool is_free_port_found
= false;
155 for (uint16_t port
= kPortScanFrom
; port
< kPortScanTo
; ++port
) {
156 pp::NetAddress new_address
= ReplacePort(instance_
, base_address
, port
);
157 ASSERT_NE(0, new_address
.pp_resource());
158 ret
= BindUDPSocket(socket
, new_address
);
160 is_free_port_found
= true;
164 if (!is_free_port_found
)
165 return "Can't find available port (" + ret
+ ")";
167 *address
= socket
->GetBoundAddress();
168 ASSERT_NE(0, address
->pp_resource());
173 std::string
TestUDPSocket::ReadSocket(pp::UDPSocket
* socket
,
174 pp::NetAddress
* address
,
176 std::string
* message
) {
177 std::vector
<char> buffer(size
);
178 TestCompletionCallbackWithOutput
<pp::NetAddress
> callback(
179 instance_
->pp_instance(), callback_type());
180 callback
.WaitForResult(
181 socket
->RecvFrom(&buffer
[0], static_cast<int32_t>(size
),
182 callback
.GetCallback()));
183 CHECK_CALLBACK_BEHAVIOR(callback
);
184 ASSERT_FALSE(callback
.result() < 0);
185 ASSERT_EQ(size
, static_cast<size_t>(callback
.result()));
186 *address
= callback
.output();
187 message
->assign(buffer
.begin(), buffer
.end());
191 std::string
TestUDPSocket::PassMessage(pp::UDPSocket
* target
,
192 pp::UDPSocket
* source
,
193 const pp::NetAddress
& target_address
,
194 const std::string
& message
,
195 pp::NetAddress
* recvfrom_address
) {
196 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
197 int32_t rv
= source
->SendTo(message
.c_str(),
198 static_cast<int32_t>(message
.size()),
200 callback
.GetCallback());
202 ASSERT_SUBTEST_SUCCESS(ReadSocket(target
, recvfrom_address
, message
.size(),
205 callback
.WaitForResult(rv
);
206 CHECK_CALLBACK_BEHAVIOR(callback
);
207 ASSERT_FALSE(callback
.result() < 0);
208 ASSERT_EQ(message
.size(), static_cast<size_t>(callback
.result()));
209 ASSERT_EQ(message
, str
);
213 std::string
TestUDPSocket::SetMulticastOptions(pp::UDPSocket
* socket
) {
214 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
215 callback
.WaitForResult(socket
->SetOption(
216 PP_UDPSOCKET_OPTION_MULTICAST_LOOP
, pp::Var(true),
217 callback
.GetCallback()));
218 CHECK_CALLBACK_BEHAVIOR(callback
);
219 ASSERT_EQ(PP_OK
, callback
.result());
221 callback
.WaitForResult(socket
->SetOption(
222 PP_UDPSOCKET_OPTION_MULTICAST_TTL
, pp::Var(1), callback
.GetCallback()));
223 CHECK_CALLBACK_BEHAVIOR(callback
);
224 ASSERT_EQ(PP_OK
, callback
.result());
229 std::string
TestUDPSocket::TestReadWrite() {
230 pp::UDPSocket
server_socket(instance_
), client_socket(instance_
);
231 pp::NetAddress server_address
, client_address
;
233 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&server_socket
,
235 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&client_socket
,
237 const std::string message
= "Simple message that will be sent via UDP";
238 pp::NetAddress recvfrom_address
;
239 ASSERT_SUBTEST_SUCCESS(PassMessage(&server_socket
, &client_socket
,
240 server_address
, message
,
242 ASSERT_TRUE(EqualNetAddress(recvfrom_address
, client_address
));
244 server_socket
.Close();
245 client_socket
.Close();
247 if (server_socket
.GetBoundAddress().pp_resource() != 0)
248 return "PPB_UDPSocket::GetBoundAddress: expected failure";
253 std::string
TestUDPSocket::TestBroadcast() {
254 pp::UDPSocket
server1(instance_
), server2(instance_
);
256 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server1
));
257 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&server2
));
259 PP_NetAddress_IPv4 any_ipv4_address
= { 0, { 0, 0, 0, 0 } };
260 pp::NetAddress
any_address(instance_
, any_ipv4_address
);
261 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server1
, any_address
));
262 // Fill port field of |server_address|.
263 pp::NetAddress server_address
= server1
.GetBoundAddress();
264 ASSERT_NE(0, server_address
.pp_resource());
265 ASSERT_SUBTEST_SUCCESS(BindUDPSocket(&server2
, server_address
));
267 PP_NetAddress_IPv4 server_ipv4_address
;
268 ASSERT_TRUE(server_address
.DescribeAsIPv4Address(&server_ipv4_address
));
270 PP_NetAddress_IPv4 broadcast_ipv4_address
= {
271 server_ipv4_address
.port
, { 0xff, 0xff, 0xff, 0xff }
273 pp::NetAddress
broadcast_address(instance_
, broadcast_ipv4_address
);
276 const std::string first_message
= "first message";
277 const std::string second_message
= "second_message";
279 pp::NetAddress recvfrom_address
;
280 ASSERT_SUBTEST_SUCCESS(PassMessage(&server1
, &server2
, broadcast_address
,
281 first_message
, &recvfrom_address
));
282 // |first_message| was also received by |server2|.
283 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server2
, &recvfrom_address
,
284 first_message
.size(), &message
));
285 ASSERT_EQ(first_message
, message
);
287 ASSERT_SUBTEST_SUCCESS(PassMessage(&server2
, &server1
, broadcast_address
,
288 second_message
, &recvfrom_address
));
289 // |second_message| was also received by |server1|.
290 ASSERT_SUBTEST_SUCCESS(ReadSocket(&server1
, &recvfrom_address
,
291 second_message
.size(), &message
));
292 ASSERT_EQ(second_message
, message
);
299 int32_t TestUDPSocket::SetOptionValue(UDPSocketSetOption func
,
301 PP_UDPSocket_Option option
,
302 const PP_Var
& value
) {
303 PP_TimeTicks
start_time(NowInTimeTicks());
304 TestCompletionCallback
cb(instance_
->pp_instance(), callback_type());
305 cb
.WaitForResult(func(socket
, option
, value
,
306 cb
.GetCallback().pp_completion_callback()));
308 // Expanded from CHECK_CALLBACK_BEHAVIOR macro.
310 std::string msg
= MakeFailureMessage(__FILE__
, __LINE__
,
311 cb
.errors().c_str());
313 instance_
->LogTest("SetOptionValue", msg
, start_time
);
314 return PP_ERROR_FAILED
;
319 std::string
TestUDPSocket::TestSetOption_1_0() {
320 PP_Resource socket
= socket_interface_1_0_
->Create(instance_
->pp_instance());
321 ASSERT_NE(0, socket
);
323 // Multicast options are not supported in interface 1.0.
324 ASSERT_EQ(PP_ERROR_BADARGUMENT
,
325 SetOptionValue(socket_interface_1_0_
->SetOption
,
327 PP_UDPSOCKET_OPTION_MULTICAST_LOOP
,
328 PP_MakeBool(PP_TRUE
)));
330 ASSERT_EQ(PP_ERROR_BADARGUMENT
,
331 SetOptionValue(socket_interface_1_0_
->SetOption
,
333 PP_UDPSOCKET_OPTION_MULTICAST_TTL
,
336 socket_interface_1_0_
->Close(socket
);
337 pp::Module::Get()->core()->ReleaseResource(socket
);
342 std::string
TestUDPSocket::TestSetOption_1_1() {
343 PP_Resource socket
= socket_interface_1_1_
->Create(instance_
->pp_instance());
344 ASSERT_NE(0, socket
);
346 // Multicast options are not supported in interface 1.1.
347 ASSERT_EQ(PP_ERROR_BADARGUMENT
,
348 SetOptionValue(socket_interface_1_1_
->SetOption
,
350 PP_UDPSOCKET_OPTION_MULTICAST_LOOP
,
351 PP_MakeBool(PP_TRUE
)));
353 ASSERT_EQ(PP_ERROR_BADARGUMENT
,
354 SetOptionValue(socket_interface_1_1_
->SetOption
,
356 PP_UDPSOCKET_OPTION_MULTICAST_TTL
,
359 socket_interface_1_1_
->Close(socket
);
360 pp::Module::Get()->core()->ReleaseResource(socket
);
365 std::string
TestUDPSocket::TestSetOption() {
366 pp::UDPSocket
socket(instance_
);
368 ASSERT_SUBTEST_SUCCESS(SetBroadcastOptions(&socket
));
369 ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&socket
));
371 // Try to pass incorrect option value's type.
372 TestCompletionCallback
callback(instance_
->pp_instance(), callback_type());
373 callback
.WaitForResult(socket
.SetOption(
374 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(1), callback
.GetCallback()));
375 CHECK_CALLBACK_BEHAVIOR(callback
);
376 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
378 // Invalid multicast TTL values (less than 0 and greater than 255).
379 callback
.WaitForResult(socket
.SetOption(
380 PP_UDPSOCKET_OPTION_MULTICAST_TTL
, pp::Var(-1), callback
.GetCallback()));
381 CHECK_CALLBACK_BEHAVIOR(callback
);
382 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
384 callback
.WaitForResult(socket
.SetOption(
385 PP_UDPSOCKET_OPTION_MULTICAST_TTL
, pp::Var(256), callback
.GetCallback()));
386 CHECK_CALLBACK_BEHAVIOR(callback
);
387 ASSERT_EQ(PP_ERROR_BADARGUMENT
, callback
.result());
389 callback
.WaitForResult(socket
.SetOption(
390 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(false), callback
.GetCallback()));
391 CHECK_CALLBACK_BEHAVIOR(callback
);
392 ASSERT_EQ(PP_OK
, callback
.result());
394 callback
.WaitForResult(socket
.SetOption(
395 PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE
, pp::Var(4096),
396 callback
.GetCallback()));
397 CHECK_CALLBACK_BEHAVIOR(callback
);
398 ASSERT_EQ(PP_OK
, callback
.result());
400 callback
.WaitForResult(socket
.SetOption(
401 PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE
, pp::Var(512),
402 callback
.GetCallback()));
403 CHECK_CALLBACK_BEHAVIOR(callback
);
404 ASSERT_EQ(PP_OK
, callback
.result());
406 pp::NetAddress address
;
407 ASSERT_SUBTEST_SUCCESS(LookupPortAndBindUDPSocket(&socket
, &address
));
409 // ADDRESS_REUSE won't take effect after the socket is bound.
410 callback
.WaitForResult(socket
.SetOption(
411 PP_UDPSOCKET_OPTION_ADDRESS_REUSE
, pp::Var(true),
412 callback
.GetCallback()));
413 CHECK_CALLBACK_BEHAVIOR(callback
);
414 ASSERT_EQ(PP_ERROR_FAILED
, callback
.result());
416 // BROADCAST, SEND_BUFFER_SIZE and RECV_BUFFER_SIZE can be set after the
418 callback
.WaitForResult(socket
.SetOption(
419 PP_UDPSOCKET_OPTION_BROADCAST
, pp::Var(true), callback
.GetCallback()));
420 CHECK_CALLBACK_BEHAVIOR(callback
);
421 ASSERT_EQ(PP_OK
, callback
.result());
423 callback
.WaitForResult(socket
.SetOption(
424 PP_UDPSOCKET_OPTION_SEND_BUFFER_SIZE
, pp::Var(2048),
425 callback
.GetCallback()));
426 CHECK_CALLBACK_BEHAVIOR(callback
);
427 ASSERT_EQ(PP_OK
, callback
.result());
429 callback
.WaitForResult(socket
.SetOption(
430 PP_UDPSOCKET_OPTION_RECV_BUFFER_SIZE
, pp::Var(1024),
431 callback
.GetCallback()));
432 CHECK_CALLBACK_BEHAVIOR(callback
);
433 ASSERT_EQ(PP_OK
, callback
.result());
438 std::string
TestUDPSocket::TestParallelSend() {
439 // This test only makes sense when callbacks are optional.
440 if (callback_type() != PP_OPTIONAL
)
443 pp::UDPSocket
server_socket(instance_
), client_socket(instance_
);
444 pp::NetAddress server_address
, client_address
;
446 ASSERT_SUBTEST_SUCCESS(
447 LookupPortAndBindUDPSocket(&server_socket
, &server_address
));
448 ASSERT_SUBTEST_SUCCESS(
449 LookupPortAndBindUDPSocket(&client_socket
, &client_address
));
450 const std::string message
= "Simple message that will be sent via UDP";
451 pp::NetAddress recvfrom_address
;
453 const size_t kParallelSends
= 10;
454 std::vector
<TestCompletionCallback
*> sendto_callbacks(kParallelSends
);
455 std::vector
<int32_t> sendto_results(kParallelSends
);
457 for (size_t i
= 0; i
< kParallelSends
; i
++) {
458 sendto_callbacks
[i
] =
459 new TestCompletionCallback(instance_
->pp_instance(), callback_type());
461 client_socket
.SendTo(message
.c_str(),
462 static_cast<int32_t>(message
.size()),
464 sendto_callbacks
[i
]->GetCallback());
466 if (sendto_results
[i
] == PP_ERROR_INPROGRESS
) {
467 // Run a pending send to completion to free a slot for the current send.
468 ASSERT_GT(i
, pending
);
469 sendto_callbacks
[pending
]->WaitForResult(sendto_results
[pending
]);
470 CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks
[pending
]);
471 ASSERT_EQ(message
.size(),
472 static_cast<size_t>(sendto_callbacks
[pending
]->result()));
474 // Try to send the message again.
476 client_socket
.SendTo(message
.c_str(),
477 static_cast<int32_t>(message
.size()),
479 sendto_callbacks
[i
]->GetCallback());
480 ASSERT_NE(PP_ERROR_INPROGRESS
, sendto_results
[i
]);
484 // Finish all pending sends.
485 for (size_t i
= pending
; i
< kParallelSends
; i
++) {
486 sendto_callbacks
[i
]->WaitForResult(sendto_results
[i
]);
487 CHECK_CALLBACK_BEHAVIOR(*sendto_callbacks
[i
]);
488 ASSERT_EQ(message
.size(),
489 static_cast<size_t>(sendto_callbacks
[i
]->result()));
492 for (size_t i
= 0; i
< kParallelSends
; ++i
)
493 delete sendto_callbacks
[i
];
495 for (size_t i
= 0; i
< kParallelSends
; i
++) {
497 ASSERT_SUBTEST_SUCCESS(
498 ReadSocket(&server_socket
, &recvfrom_address
, message
.size(), &str
));
499 ASSERT_EQ(message
, str
);
502 server_socket
.Close();
503 client_socket
.Close();
508 std::string
TestUDPSocket::TestMulticast() {
509 pp::UDPSocket
server1(instance_
), server2(instance_
);
511 ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server1
));
512 ASSERT_SUBTEST_SUCCESS(SetMulticastOptions(&server2
));