OLD | NEW |
| (Empty) |
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 "net/udp/udp_socket.h" | |
6 | |
7 #include "net/udp/udp_client_socket.h" | |
8 #include "net/udp/udp_server_socket.h" | |
9 | |
10 #include "base/basictypes.h" | |
11 #include "base/bind.h" | |
12 #include "base/memory/weak_ptr.h" | |
13 #include "base/message_loop/message_loop.h" | |
14 #include "base/metrics/histogram.h" | |
15 #include "base/run_loop.h" | |
16 #include "base/stl_util.h" | |
17 #include "net/base/io_buffer.h" | |
18 #include "net/base/ip_endpoint.h" | |
19 #include "net/base/net_errors.h" | |
20 #include "net/base/net_log_unittest.h" | |
21 #include "net/base/net_util.h" | |
22 #include "net/base/test_completion_callback.h" | |
23 #include "net/test/net_test_suite.h" | |
24 #include "testing/gtest/include/gtest/gtest.h" | |
25 #include "testing/platform_test.h" | |
26 | |
27 namespace net { | |
28 | |
29 namespace { | |
30 | |
31 class UDPSocketTest : public PlatformTest { | |
32 public: | |
33 UDPSocketTest() : buffer_(new IOBufferWithSize(kMaxRead)) {} | |
34 | |
35 // Blocks until data is read from the socket. | |
36 std::string RecvFromSocket(UDPServerSocket* socket) { | |
37 TestCompletionCallback callback; | |
38 | |
39 int rv = socket->RecvFrom( | |
40 buffer_.get(), kMaxRead, &recv_from_address_, callback.callback()); | |
41 if (rv == ERR_IO_PENDING) | |
42 rv = callback.WaitForResult(); | |
43 if (rv < 0) | |
44 return std::string(); // error! | |
45 return std::string(buffer_->data(), rv); | |
46 } | |
47 | |
48 // Loop until |msg| has been written to the socket or until an | |
49 // error occurs. | |
50 // If |address| is specified, then it is used for the destination | |
51 // to send to. Otherwise, will send to the last socket this server | |
52 // received from. | |
53 int SendToSocket(UDPServerSocket* socket, std::string msg) { | |
54 return SendToSocket(socket, msg, recv_from_address_); | |
55 } | |
56 | |
57 int SendToSocket(UDPServerSocket* socket, | |
58 std::string msg, | |
59 const IPEndPoint& address) { | |
60 TestCompletionCallback callback; | |
61 | |
62 int length = msg.length(); | |
63 scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(msg)); | |
64 scoped_refptr<DrainableIOBuffer> buffer( | |
65 new DrainableIOBuffer(io_buffer.get(), length)); | |
66 | |
67 int bytes_sent = 0; | |
68 while (buffer->BytesRemaining()) { | |
69 int rv = socket->SendTo( | |
70 buffer.get(), buffer->BytesRemaining(), address, callback.callback()); | |
71 if (rv == ERR_IO_PENDING) | |
72 rv = callback.WaitForResult(); | |
73 if (rv <= 0) | |
74 return bytes_sent > 0 ? bytes_sent : rv; | |
75 bytes_sent += rv; | |
76 buffer->DidConsume(rv); | |
77 } | |
78 return bytes_sent; | |
79 } | |
80 | |
81 std::string ReadSocket(UDPClientSocket* socket) { | |
82 TestCompletionCallback callback; | |
83 | |
84 int rv = socket->Read(buffer_.get(), kMaxRead, callback.callback()); | |
85 if (rv == ERR_IO_PENDING) | |
86 rv = callback.WaitForResult(); | |
87 if (rv < 0) | |
88 return std::string(); // error! | |
89 return std::string(buffer_->data(), rv); | |
90 } | |
91 | |
92 // Loop until |msg| has been written to the socket or until an | |
93 // error occurs. | |
94 int WriteSocket(UDPClientSocket* socket, std::string msg) { | |
95 TestCompletionCallback callback; | |
96 | |
97 int length = msg.length(); | |
98 scoped_refptr<StringIOBuffer> io_buffer(new StringIOBuffer(msg)); | |
99 scoped_refptr<DrainableIOBuffer> buffer( | |
100 new DrainableIOBuffer(io_buffer.get(), length)); | |
101 | |
102 int bytes_sent = 0; | |
103 while (buffer->BytesRemaining()) { | |
104 int rv = socket->Write( | |
105 buffer.get(), buffer->BytesRemaining(), callback.callback()); | |
106 if (rv == ERR_IO_PENDING) | |
107 rv = callback.WaitForResult(); | |
108 if (rv <= 0) | |
109 return bytes_sent > 0 ? bytes_sent : rv; | |
110 bytes_sent += rv; | |
111 buffer->DidConsume(rv); | |
112 } | |
113 return bytes_sent; | |
114 } | |
115 | |
116 void WriteSocketIgnoreResult(UDPClientSocket* socket, std::string msg) { | |
117 WriteSocket(socket, msg); | |
118 } | |
119 | |
120 // Creates an address from ip address and port and writes it to |*address|. | |
121 void CreateUDPAddress(std::string ip_str, uint16 port, IPEndPoint* address) { | |
122 IPAddressNumber ip_number; | |
123 bool rv = ParseIPLiteralToNumber(ip_str, &ip_number); | |
124 if (!rv) | |
125 return; | |
126 *address = IPEndPoint(ip_number, port); | |
127 } | |
128 | |
129 // Run unit test for a connection test. | |
130 // |use_nonblocking_io| is used to switch between overlapped and non-blocking | |
131 // IO on Windows. It has no effect in other ports. | |
132 void ConnectTest(bool use_nonblocking_io); | |
133 | |
134 protected: | |
135 static const int kMaxRead = 1024; | |
136 scoped_refptr<IOBufferWithSize> buffer_; | |
137 IPEndPoint recv_from_address_; | |
138 }; | |
139 | |
140 void ReadCompleteCallback(int* result_out, base::Closure callback, int result) { | |
141 *result_out = result; | |
142 callback.Run(); | |
143 } | |
144 | |
145 void UDPSocketTest::ConnectTest(bool use_nonblocking_io) { | |
146 const uint16 kPort = 9999; | |
147 std::string simple_message("hello world!"); | |
148 | |
149 // Setup the server to listen. | |
150 IPEndPoint bind_address; | |
151 CreateUDPAddress("127.0.0.1", kPort, &bind_address); | |
152 CapturingNetLog server_log; | |
153 scoped_ptr<UDPServerSocket> server( | |
154 new UDPServerSocket(&server_log, NetLog::Source())); | |
155 #if defined(OS_WIN) | |
156 if (use_nonblocking_io) | |
157 server->UseNonBlockingIO(); | |
158 #endif | |
159 server->AllowAddressReuse(); | |
160 int rv = server->Listen(bind_address); | |
161 ASSERT_EQ(OK, rv); | |
162 | |
163 // Setup the client. | |
164 IPEndPoint server_address; | |
165 CreateUDPAddress("127.0.0.1", kPort, &server_address); | |
166 CapturingNetLog client_log; | |
167 scoped_ptr<UDPClientSocket> client( | |
168 new UDPClientSocket(DatagramSocket::DEFAULT_BIND, RandIntCallback(), | |
169 &client_log, NetLog::Source())); | |
170 #if defined(OS_WIN) | |
171 if (use_nonblocking_io) | |
172 client->UseNonBlockingIO(); | |
173 #endif | |
174 | |
175 rv = client->Connect(server_address); | |
176 EXPECT_EQ(OK, rv); | |
177 | |
178 // Client sends to the server. | |
179 rv = WriteSocket(client.get(), simple_message); | |
180 EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); | |
181 | |
182 // Server waits for message. | |
183 std::string str = RecvFromSocket(server.get()); | |
184 DCHECK(simple_message == str); | |
185 | |
186 // Server echoes reply. | |
187 rv = SendToSocket(server.get(), simple_message); | |
188 EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); | |
189 | |
190 // Client waits for response. | |
191 str = ReadSocket(client.get()); | |
192 DCHECK(simple_message == str); | |
193 | |
194 // Test asynchronous read. Server waits for message. | |
195 base::RunLoop run_loop; | |
196 int read_result = 0; | |
197 rv = server->RecvFrom( | |
198 buffer_.get(), kMaxRead, &recv_from_address_, | |
199 base::Bind(&ReadCompleteCallback, &read_result, run_loop.QuitClosure())); | |
200 EXPECT_EQ(ERR_IO_PENDING, rv); | |
201 | |
202 // Client sends to the server. | |
203 base::MessageLoop::current()->PostTask( | |
204 FROM_HERE, | |
205 base::Bind(&UDPSocketTest::WriteSocketIgnoreResult, | |
206 base::Unretained(this), client.get(), simple_message)); | |
207 run_loop.Run(); | |
208 EXPECT_EQ(simple_message.length(), static_cast<size_t>(read_result)); | |
209 EXPECT_EQ(simple_message, std::string(buffer_->data(), read_result)); | |
210 | |
211 // Delete sockets so they log their final events. | |
212 server.reset(); | |
213 client.reset(); | |
214 | |
215 // Check the server's log. | |
216 CapturingNetLog::CapturedEntryList server_entries; | |
217 server_log.GetEntries(&server_entries); | |
218 EXPECT_EQ(5u, server_entries.size()); | |
219 EXPECT_TRUE( | |
220 LogContainsBeginEvent(server_entries, 0, NetLog::TYPE_SOCKET_ALIVE)); | |
221 EXPECT_TRUE(LogContainsEvent( | |
222 server_entries, 1, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE)); | |
223 EXPECT_TRUE(LogContainsEvent(server_entries, 2, NetLog::TYPE_UDP_BYTES_SENT, | |
224 NetLog::PHASE_NONE)); | |
225 EXPECT_TRUE(LogContainsEvent( | |
226 server_entries, 3, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE)); | |
227 EXPECT_TRUE( | |
228 LogContainsEndEvent(server_entries, 4, NetLog::TYPE_SOCKET_ALIVE)); | |
229 | |
230 // Check the client's log. | |
231 CapturingNetLog::CapturedEntryList client_entries; | |
232 client_log.GetEntries(&client_entries); | |
233 EXPECT_EQ(7u, client_entries.size()); | |
234 EXPECT_TRUE( | |
235 LogContainsBeginEvent(client_entries, 0, NetLog::TYPE_SOCKET_ALIVE)); | |
236 EXPECT_TRUE( | |
237 LogContainsBeginEvent(client_entries, 1, NetLog::TYPE_UDP_CONNECT)); | |
238 EXPECT_TRUE(LogContainsEndEvent(client_entries, 2, NetLog::TYPE_UDP_CONNECT)); | |
239 EXPECT_TRUE(LogContainsEvent(client_entries, 3, NetLog::TYPE_UDP_BYTES_SENT, | |
240 NetLog::PHASE_NONE)); | |
241 EXPECT_TRUE(LogContainsEvent( | |
242 client_entries, 4, NetLog::TYPE_UDP_BYTES_RECEIVED, NetLog::PHASE_NONE)); | |
243 EXPECT_TRUE(LogContainsEvent(client_entries, 5, NetLog::TYPE_UDP_BYTES_SENT, | |
244 NetLog::PHASE_NONE)); | |
245 EXPECT_TRUE( | |
246 LogContainsEndEvent(client_entries, 6, NetLog::TYPE_SOCKET_ALIVE)); | |
247 } | |
248 | |
249 TEST_F(UDPSocketTest, Connect) { | |
250 // The variable |use_nonblocking_io| has no effect in non-Windows ports. | |
251 ConnectTest(false); | |
252 } | |
253 | |
254 #if defined(OS_WIN) | |
255 TEST_F(UDPSocketTest, ConnectNonBlocking) { | |
256 ConnectTest(true); | |
257 } | |
258 #endif | |
259 | |
260 #if defined(OS_MACOSX) | |
261 // UDPSocketPrivate_Broadcast is disabled for OSX because it requires | |
262 // root permissions on OSX 10.7+. | |
263 TEST_F(UDPSocketTest, DISABLED_Broadcast) { | |
264 #elif defined(OS_ANDROID) | |
265 // It is also disabled for Android because it is extremely flaky. | |
266 // The first call to SendToSocket returns -109 (Address not reachable) | |
267 // in some unpredictable cases. crbug.com/139144. | |
268 TEST_F(UDPSocketTest, DISABLED_Broadcast) { | |
269 #else | |
270 TEST_F(UDPSocketTest, Broadcast) { | |
271 #endif | |
272 const uint16 kPort = 9999; | |
273 std::string first_message("first message"), second_message("second message"); | |
274 | |
275 IPEndPoint broadcast_address; | |
276 CreateUDPAddress("255.255.255.255", kPort, &broadcast_address); | |
277 IPEndPoint listen_address; | |
278 CreateUDPAddress("0.0.0.0", kPort, &listen_address); | |
279 | |
280 CapturingNetLog server1_log, server2_log; | |
281 scoped_ptr<UDPServerSocket> server1( | |
282 new UDPServerSocket(&server1_log, NetLog::Source())); | |
283 scoped_ptr<UDPServerSocket> server2( | |
284 new UDPServerSocket(&server2_log, NetLog::Source())); | |
285 server1->AllowAddressReuse(); | |
286 server1->AllowBroadcast(); | |
287 server2->AllowAddressReuse(); | |
288 server2->AllowBroadcast(); | |
289 | |
290 int rv = server1->Listen(listen_address); | |
291 EXPECT_EQ(OK, rv); | |
292 rv = server2->Listen(listen_address); | |
293 EXPECT_EQ(OK, rv); | |
294 | |
295 rv = SendToSocket(server1.get(), first_message, broadcast_address); | |
296 ASSERT_EQ(static_cast<int>(first_message.size()), rv); | |
297 std::string str = RecvFromSocket(server1.get()); | |
298 ASSERT_EQ(first_message, str); | |
299 str = RecvFromSocket(server2.get()); | |
300 ASSERT_EQ(first_message, str); | |
301 | |
302 rv = SendToSocket(server2.get(), second_message, broadcast_address); | |
303 ASSERT_EQ(static_cast<int>(second_message.size()), rv); | |
304 str = RecvFromSocket(server1.get()); | |
305 ASSERT_EQ(second_message, str); | |
306 str = RecvFromSocket(server2.get()); | |
307 ASSERT_EQ(second_message, str); | |
308 } | |
309 | |
310 // In this test, we verify that random binding logic works, which attempts | |
311 // to bind to a random port and returns if succeeds, otherwise retries for | |
312 // |kBindRetries| number of times. | |
313 | |
314 // To generate the scenario, we first create |kBindRetries| number of | |
315 // UDPClientSockets with default binding policy and connect to the same | |
316 // peer and save the used port numbers. Then we get rid of the last | |
317 // socket, making sure that the local port it was bound to is available. | |
318 // Finally, we create a socket with random binding policy, passing it a | |
319 // test PRNG that would serve used port numbers in the array, one after | |
320 // another. At the end, we make sure that the test socket was bound to the | |
321 // port that became available after deleting the last socket with default | |
322 // binding policy. | |
323 | |
324 // We do not test the randomness of bound ports, but that we are using | |
325 // passed in PRNG correctly, thus, it's the duty of PRNG to produce strong | |
326 // random numbers. | |
327 static const int kBindRetries = 10; | |
328 | |
329 class TestPrng { | |
330 public: | |
331 explicit TestPrng(const std::deque<int>& numbers) : numbers_(numbers) {} | |
332 int GetNext(int /* min */, int /* max */) { | |
333 DCHECK(!numbers_.empty()); | |
334 int rv = numbers_.front(); | |
335 numbers_.pop_front(); | |
336 return rv; | |
337 } | |
338 private: | |
339 std::deque<int> numbers_; | |
340 | |
341 DISALLOW_COPY_AND_ASSIGN(TestPrng); | |
342 }; | |
343 | |
344 #if defined(OS_ANDROID) | |
345 // Disabled on Android for lack of 192.168.1.13. crbug.com/161245 | |
346 TEST_F(UDPSocketTest, DISABLED_ConnectRandomBind) { | |
347 #else | |
348 TEST_F(UDPSocketTest, ConnectRandomBind) { | |
349 #endif | |
350 std::vector<UDPClientSocket*> sockets; | |
351 IPEndPoint peer_address; | |
352 CreateUDPAddress("192.168.1.13", 53, &peer_address); | |
353 | |
354 // Create and connect sockets and save port numbers. | |
355 std::deque<int> used_ports; | |
356 for (int i = 0; i < kBindRetries; ++i) { | |
357 UDPClientSocket* socket = | |
358 new UDPClientSocket(DatagramSocket::DEFAULT_BIND, | |
359 RandIntCallback(), | |
360 NULL, | |
361 NetLog::Source()); | |
362 sockets.push_back(socket); | |
363 EXPECT_EQ(OK, socket->Connect(peer_address)); | |
364 | |
365 IPEndPoint client_address; | |
366 EXPECT_EQ(OK, socket->GetLocalAddress(&client_address)); | |
367 used_ports.push_back(client_address.port()); | |
368 } | |
369 | |
370 // Free the last socket, its local port is still in |used_ports|. | |
371 delete sockets.back(); | |
372 sockets.pop_back(); | |
373 | |
374 TestPrng test_prng(used_ports); | |
375 RandIntCallback rand_int_cb = | |
376 base::Bind(&TestPrng::GetNext, base::Unretained(&test_prng)); | |
377 | |
378 // Create a socket with random binding policy and connect. | |
379 scoped_ptr<UDPClientSocket> test_socket( | |
380 new UDPClientSocket(DatagramSocket::RANDOM_BIND, | |
381 rand_int_cb, | |
382 NULL, | |
383 NetLog::Source())); | |
384 EXPECT_EQ(OK, test_socket->Connect(peer_address)); | |
385 | |
386 // Make sure that the last port number in the |used_ports| was used. | |
387 IPEndPoint client_address; | |
388 EXPECT_EQ(OK, test_socket->GetLocalAddress(&client_address)); | |
389 EXPECT_EQ(used_ports.back(), client_address.port()); | |
390 | |
391 STLDeleteElements(&sockets); | |
392 } | |
393 | |
394 // Return a privileged port (under 1024) so binding will fail. | |
395 int PrivilegedRand(int min, int max) { | |
396 // Chosen by fair dice roll. Guaranteed to be random. | |
397 return 4; | |
398 } | |
399 | |
400 TEST_F(UDPSocketTest, ConnectFail) { | |
401 IPEndPoint peer_address; | |
402 CreateUDPAddress("0.0.0.0", 53, &peer_address); | |
403 | |
404 scoped_ptr<UDPSocket> socket( | |
405 new UDPSocket(DatagramSocket::RANDOM_BIND, | |
406 base::Bind(&PrivilegedRand), | |
407 NULL, | |
408 NetLog::Source())); | |
409 int rv = socket->Open(peer_address.GetFamily()); | |
410 EXPECT_EQ(OK, rv); | |
411 rv = socket->Connect(peer_address); | |
412 // Connect should have failed since we couldn't bind to that port, | |
413 EXPECT_NE(OK, rv); | |
414 // Make sure that UDPSocket actually closed the socket. | |
415 EXPECT_FALSE(socket->is_connected()); | |
416 } | |
417 | |
418 // In this test, we verify that connect() on a socket will have the effect | |
419 // of filtering reads on this socket only to data read from the destination | |
420 // we connected to. | |
421 // | |
422 // The purpose of this test is that some documentation indicates that connect | |
423 // binds the client's sends to send to a particular server endpoint, but does | |
424 // not bind the client's reads to only be from that endpoint, and that we need | |
425 // to always use recvfrom() to disambiguate. | |
426 TEST_F(UDPSocketTest, VerifyConnectBindsAddr) { | |
427 const uint16 kPort1 = 9999; | |
428 const uint16 kPort2 = 10000; | |
429 std::string simple_message("hello world!"); | |
430 std::string foreign_message("BAD MESSAGE TO GET!!"); | |
431 | |
432 // Setup the first server to listen. | |
433 IPEndPoint bind_address; | |
434 CreateUDPAddress("127.0.0.1", kPort1, &bind_address); | |
435 UDPServerSocket server1(NULL, NetLog::Source()); | |
436 server1.AllowAddressReuse(); | |
437 int rv = server1.Listen(bind_address); | |
438 ASSERT_EQ(OK, rv); | |
439 | |
440 // Setup the second server to listen. | |
441 CreateUDPAddress("127.0.0.1", kPort2, &bind_address); | |
442 UDPServerSocket server2(NULL, NetLog::Source()); | |
443 server2.AllowAddressReuse(); | |
444 rv = server2.Listen(bind_address); | |
445 ASSERT_EQ(OK, rv); | |
446 | |
447 // Setup the client, connected to server 1. | |
448 IPEndPoint server_address; | |
449 CreateUDPAddress("127.0.0.1", kPort1, &server_address); | |
450 UDPClientSocket client(DatagramSocket::DEFAULT_BIND, | |
451 RandIntCallback(), | |
452 NULL, | |
453 NetLog::Source()); | |
454 rv = client.Connect(server_address); | |
455 EXPECT_EQ(OK, rv); | |
456 | |
457 // Client sends to server1. | |
458 rv = WriteSocket(&client, simple_message); | |
459 EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); | |
460 | |
461 // Server1 waits for message. | |
462 std::string str = RecvFromSocket(&server1); | |
463 DCHECK(simple_message == str); | |
464 | |
465 // Get the client's address. | |
466 IPEndPoint client_address; | |
467 rv = client.GetLocalAddress(&client_address); | |
468 EXPECT_EQ(OK, rv); | |
469 | |
470 // Server2 sends reply. | |
471 rv = SendToSocket(&server2, foreign_message, | |
472 client_address); | |
473 EXPECT_EQ(foreign_message.length(), static_cast<size_t>(rv)); | |
474 | |
475 // Server1 sends reply. | |
476 rv = SendToSocket(&server1, simple_message, | |
477 client_address); | |
478 EXPECT_EQ(simple_message.length(), static_cast<size_t>(rv)); | |
479 | |
480 // Client waits for response. | |
481 str = ReadSocket(&client); | |
482 DCHECK(simple_message == str); | |
483 } | |
484 | |
485 TEST_F(UDPSocketTest, ClientGetLocalPeerAddresses) { | |
486 struct TestData { | |
487 std::string remote_address; | |
488 std::string local_address; | |
489 bool may_fail; | |
490 } tests[] = { | |
491 { "127.0.00.1", "127.0.0.1", false }, | |
492 { "::1", "::1", true }, | |
493 #if !defined(OS_ANDROID) | |
494 // Addresses below are disabled on Android. See crbug.com/161248 | |
495 { "192.168.1.1", "127.0.0.1", false }, | |
496 { "2001:db8:0::42", "::1", true }, | |
497 #endif | |
498 }; | |
499 for (size_t i = 0; i < arraysize(tests); i++) { | |
500 SCOPED_TRACE(std::string("Connecting from ") + tests[i].local_address + | |
501 std::string(" to ") + tests[i].remote_address); | |
502 | |
503 IPAddressNumber ip_number; | |
504 ParseIPLiteralToNumber(tests[i].remote_address, &ip_number); | |
505 IPEndPoint remote_address(ip_number, 80); | |
506 ParseIPLiteralToNumber(tests[i].local_address, &ip_number); | |
507 IPEndPoint local_address(ip_number, 80); | |
508 | |
509 UDPClientSocket client(DatagramSocket::DEFAULT_BIND, | |
510 RandIntCallback(), | |
511 NULL, | |
512 NetLog::Source()); | |
513 int rv = client.Connect(remote_address); | |
514 if (tests[i].may_fail && rv == ERR_ADDRESS_UNREACHABLE) { | |
515 // Connect() may return ERR_ADDRESS_UNREACHABLE for IPv6 | |
516 // addresses if IPv6 is not configured. | |
517 continue; | |
518 } | |
519 | |
520 EXPECT_LE(ERR_IO_PENDING, rv); | |
521 | |
522 IPEndPoint fetched_local_address; | |
523 rv = client.GetLocalAddress(&fetched_local_address); | |
524 EXPECT_EQ(OK, rv); | |
525 | |
526 // TODO(mbelshe): figure out how to verify the IP and port. | |
527 // The port is dynamically generated by the udp stack. | |
528 // The IP is the real IP of the client, not necessarily | |
529 // loopback. | |
530 //EXPECT_EQ(local_address.address(), fetched_local_address.address()); | |
531 | |
532 IPEndPoint fetched_remote_address; | |
533 rv = client.GetPeerAddress(&fetched_remote_address); | |
534 EXPECT_EQ(OK, rv); | |
535 | |
536 EXPECT_EQ(remote_address, fetched_remote_address); | |
537 } | |
538 } | |
539 | |
540 TEST_F(UDPSocketTest, ServerGetLocalAddress) { | |
541 IPEndPoint bind_address; | |
542 CreateUDPAddress("127.0.0.1", 0, &bind_address); | |
543 UDPServerSocket server(NULL, NetLog::Source()); | |
544 int rv = server.Listen(bind_address); | |
545 EXPECT_EQ(OK, rv); | |
546 | |
547 IPEndPoint local_address; | |
548 rv = server.GetLocalAddress(&local_address); | |
549 EXPECT_EQ(rv, 0); | |
550 | |
551 // Verify that port was allocated. | |
552 EXPECT_GT(local_address.port(), 0); | |
553 EXPECT_EQ(local_address.address(), bind_address.address()); | |
554 } | |
555 | |
556 TEST_F(UDPSocketTest, ServerGetPeerAddress) { | |
557 IPEndPoint bind_address; | |
558 CreateUDPAddress("127.0.0.1", 0, &bind_address); | |
559 UDPServerSocket server(NULL, NetLog::Source()); | |
560 int rv = server.Listen(bind_address); | |
561 EXPECT_EQ(OK, rv); | |
562 | |
563 IPEndPoint peer_address; | |
564 rv = server.GetPeerAddress(&peer_address); | |
565 EXPECT_EQ(rv, ERR_SOCKET_NOT_CONNECTED); | |
566 } | |
567 | |
568 // Close the socket while read is pending. | |
569 TEST_F(UDPSocketTest, CloseWithPendingRead) { | |
570 IPEndPoint bind_address; | |
571 CreateUDPAddress("127.0.0.1", 0, &bind_address); | |
572 UDPServerSocket server(NULL, NetLog::Source()); | |
573 int rv = server.Listen(bind_address); | |
574 EXPECT_EQ(OK, rv); | |
575 | |
576 TestCompletionCallback callback; | |
577 IPEndPoint from; | |
578 rv = server.RecvFrom(buffer_.get(), kMaxRead, &from, callback.callback()); | |
579 EXPECT_EQ(rv, ERR_IO_PENDING); | |
580 | |
581 server.Close(); | |
582 | |
583 EXPECT_FALSE(callback.have_result()); | |
584 } | |
585 | |
586 #if defined(OS_ANDROID) | |
587 // Some Android devices do not support multicast socket. | |
588 // The ones supporting multicast need WifiManager.MulitcastLock to enable it. | |
589 // http://goo.gl/jjAk9 | |
590 #define MAYBE_JoinMulticastGroup DISABLED_JoinMulticastGroup | |
591 #else | |
592 #define MAYBE_JoinMulticastGroup JoinMulticastGroup | |
593 #endif // defined(OS_ANDROID) | |
594 | |
595 TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) { | |
596 const uint16 kPort = 9999; | |
597 const char kGroup[] = "237.132.100.17"; | |
598 | |
599 IPEndPoint bind_address; | |
600 CreateUDPAddress("0.0.0.0", kPort, &bind_address); | |
601 IPAddressNumber group_ip; | |
602 EXPECT_TRUE(ParseIPLiteralToNumber(kGroup, &group_ip)); | |
603 | |
604 UDPSocket socket(DatagramSocket::DEFAULT_BIND, | |
605 RandIntCallback(), | |
606 NULL, | |
607 NetLog::Source()); | |
608 EXPECT_EQ(OK, socket.Open(bind_address.GetFamily())); | |
609 EXPECT_EQ(OK, socket.Bind(bind_address)); | |
610 EXPECT_EQ(OK, socket.JoinGroup(group_ip)); | |
611 // Joining group multiple times. | |
612 EXPECT_NE(OK, socket.JoinGroup(group_ip)); | |
613 EXPECT_EQ(OK, socket.LeaveGroup(group_ip)); | |
614 // Leaving group multiple times. | |
615 EXPECT_NE(OK, socket.LeaveGroup(group_ip)); | |
616 | |
617 socket.Close(); | |
618 } | |
619 | |
620 TEST_F(UDPSocketTest, MulticastOptions) { | |
621 const uint16 kPort = 9999; | |
622 IPEndPoint bind_address; | |
623 CreateUDPAddress("0.0.0.0", kPort, &bind_address); | |
624 | |
625 UDPSocket socket(DatagramSocket::DEFAULT_BIND, | |
626 RandIntCallback(), | |
627 NULL, | |
628 NetLog::Source()); | |
629 // Before binding. | |
630 EXPECT_EQ(OK, socket.SetMulticastLoopbackMode(false)); | |
631 EXPECT_EQ(OK, socket.SetMulticastLoopbackMode(true)); | |
632 EXPECT_EQ(OK, socket.SetMulticastTimeToLive(0)); | |
633 EXPECT_EQ(OK, socket.SetMulticastTimeToLive(3)); | |
634 EXPECT_NE(OK, socket.SetMulticastTimeToLive(-1)); | |
635 EXPECT_EQ(OK, socket.SetMulticastInterface(0)); | |
636 | |
637 EXPECT_EQ(OK, socket.Open(bind_address.GetFamily())); | |
638 EXPECT_EQ(OK, socket.Bind(bind_address)); | |
639 | |
640 EXPECT_NE(OK, socket.SetMulticastLoopbackMode(false)); | |
641 EXPECT_NE(OK, socket.SetMulticastTimeToLive(0)); | |
642 EXPECT_NE(OK, socket.SetMulticastInterface(0)); | |
643 | |
644 socket.Close(); | |
645 } | |
646 | |
647 // Checking that DSCP bits are set correctly is difficult, | |
648 // but let's check that the code doesn't crash at least. | |
649 TEST_F(UDPSocketTest, SetDSCP) { | |
650 // Setup the server to listen. | |
651 IPEndPoint bind_address; | |
652 UDPSocket client(DatagramSocket::DEFAULT_BIND, | |
653 RandIntCallback(), | |
654 NULL, | |
655 NetLog::Source()); | |
656 // We need a real IP, but we won't actually send anything to it. | |
657 CreateUDPAddress("8.8.8.8", 9999, &bind_address); | |
658 int rv = client.Open(bind_address.GetFamily()); | |
659 EXPECT_EQ(OK, rv); | |
660 | |
661 rv = client.Connect(bind_address); | |
662 if (rv != OK) { | |
663 // Let's try localhost then.. | |
664 CreateUDPAddress("127.0.0.1", 9999, &bind_address); | |
665 rv = client.Connect(bind_address); | |
666 } | |
667 EXPECT_EQ(OK, rv); | |
668 | |
669 client.SetDiffServCodePoint(DSCP_NO_CHANGE); | |
670 client.SetDiffServCodePoint(DSCP_AF41); | |
671 client.SetDiffServCodePoint(DSCP_DEFAULT); | |
672 client.SetDiffServCodePoint(DSCP_CS2); | |
673 client.SetDiffServCodePoint(DSCP_NO_CHANGE); | |
674 client.SetDiffServCodePoint(DSCP_DEFAULT); | |
675 client.Close(); | |
676 } | |
677 | |
678 } // namespace | |
679 | |
680 #if defined(OS_WIN) | |
681 | |
682 namespace { | |
683 | |
684 const HANDLE kFakeHandle = (HANDLE)19; | |
685 const QOS_FLOWID kFakeFlowId = (QOS_FLOWID)27; | |
686 | |
687 BOOL WINAPI FakeQOSCreateHandleFAIL(PQOS_VERSION version, PHANDLE handle) { | |
688 EXPECT_EQ(0, version->MinorVersion); | |
689 EXPECT_EQ(1, version->MajorVersion); | |
690 SetLastError(ERROR_OPEN_FAILED); | |
691 return false; | |
692 } | |
693 | |
694 BOOL WINAPI FakeQOSCreateHandle(PQOS_VERSION version, PHANDLE handle) { | |
695 EXPECT_EQ(0, version->MinorVersion); | |
696 EXPECT_EQ(1, version->MajorVersion); | |
697 *handle = kFakeHandle; | |
698 return true; | |
699 } | |
700 | |
701 BOOL WINAPI FakeQOSCloseHandle(HANDLE handle) { | |
702 EXPECT_EQ(kFakeHandle, handle); | |
703 return true; | |
704 } | |
705 | |
706 QOS_TRAFFIC_TYPE g_expected_traffic_type; | |
707 | |
708 BOOL WINAPI FakeQOSAddSocketToFlow(HANDLE handle, | |
709 SOCKET socket, | |
710 PSOCKADDR addr, | |
711 QOS_TRAFFIC_TYPE traffic_type, | |
712 DWORD flags, | |
713 PQOS_FLOWID flow_id) { | |
714 EXPECT_EQ(kFakeHandle, handle); | |
715 EXPECT_EQ(NULL, addr); | |
716 EXPECT_EQ(QOS_NON_ADAPTIVE_FLOW, flags); | |
717 EXPECT_EQ(0, *flow_id); | |
718 *flow_id = kFakeFlowId; | |
719 return true; | |
720 } | |
721 | |
722 BOOL WINAPI FakeQOSRemoveSocketFromFlow(HANDLE handle, | |
723 SOCKET socket, | |
724 QOS_FLOWID flowid, | |
725 DWORD reserved) { | |
726 EXPECT_EQ(kFakeHandle, handle); | |
727 EXPECT_EQ(NULL, socket); | |
728 EXPECT_EQ(kFakeFlowId, flowid); | |
729 EXPECT_EQ(0, reserved); | |
730 return true; | |
731 } | |
732 | |
733 DWORD g_expected_dscp; | |
734 | |
735 BOOL WINAPI FakeQOSSetFlow(HANDLE handle, | |
736 QOS_FLOWID flow_id, | |
737 QOS_SET_FLOW op, | |
738 ULONG size, | |
739 PVOID data, | |
740 DWORD reserved, | |
741 LPOVERLAPPED overlapped) { | |
742 EXPECT_EQ(kFakeHandle, handle); | |
743 EXPECT_EQ(QOSSetOutgoingDSCPValue, op); | |
744 EXPECT_EQ(sizeof(DWORD), size); | |
745 EXPECT_EQ(g_expected_dscp, *reinterpret_cast<DWORD*>(data)); | |
746 EXPECT_EQ(kFakeFlowId, flow_id); | |
747 EXPECT_EQ(0, reserved); | |
748 EXPECT_EQ(NULL, overlapped); | |
749 return true; | |
750 } | |
751 | |
752 } // namespace | |
753 | |
754 // Mock out the Qwave functions and make sure they are | |
755 // called correctly. Must be in net namespace for friendship | |
756 // reasons. | |
757 TEST_F(UDPSocketTest, SetDSCPFake) { | |
758 // Setup the server to listen. | |
759 IPEndPoint bind_address; | |
760 // We need a real IP, but we won't actually send anything to it. | |
761 CreateUDPAddress("8.8.8.8", 9999, &bind_address); | |
762 UDPSocket client(DatagramSocket::DEFAULT_BIND, | |
763 RandIntCallback(), | |
764 NULL, | |
765 NetLog::Source()); | |
766 int rv = client.SetDiffServCodePoint(DSCP_AF41); | |
767 EXPECT_EQ(ERR_SOCKET_NOT_CONNECTED, rv); | |
768 | |
769 rv = client.Open(bind_address.GetFamily()); | |
770 EXPECT_EQ(OK, rv); | |
771 | |
772 rv = client.Connect(bind_address); | |
773 EXPECT_EQ(OK, rv); | |
774 | |
775 QwaveAPI& qos(QwaveAPI::Get()); | |
776 qos.create_handle_func_ = FakeQOSCreateHandleFAIL; | |
777 qos.close_handle_func_ = FakeQOSCloseHandle; | |
778 qos.add_socket_to_flow_func_ = FakeQOSAddSocketToFlow; | |
779 qos.remove_socket_from_flow_func_ = FakeQOSRemoveSocketFromFlow; | |
780 qos.set_flow_func_ = FakeQOSSetFlow; | |
781 qos.qwave_supported_ = true; | |
782 | |
783 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_NO_CHANGE)); | |
784 EXPECT_EQ(ERROR_NOT_SUPPORTED, client.SetDiffServCodePoint(DSCP_AF41)); | |
785 qos.create_handle_func_ = FakeQOSCreateHandle; | |
786 g_expected_dscp = DSCP_AF41; | |
787 g_expected_traffic_type = QOSTrafficTypeAudioVideo; | |
788 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_AF41)); | |
789 g_expected_dscp = DSCP_DEFAULT; | |
790 g_expected_traffic_type = QOSTrafficTypeBestEffort; | |
791 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_DEFAULT)); | |
792 g_expected_dscp = DSCP_CS2; | |
793 g_expected_traffic_type = QOSTrafficTypeExcellentEffort; | |
794 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_CS2)); | |
795 g_expected_dscp = DSCP_CS3; | |
796 g_expected_traffic_type = QOSTrafficTypeExcellentEffort; | |
797 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_NO_CHANGE)); | |
798 g_expected_dscp = DSCP_DEFAULT; | |
799 g_expected_traffic_type = QOSTrafficTypeBestEffort; | |
800 EXPECT_EQ(OK, client.SetDiffServCodePoint(DSCP_DEFAULT)); | |
801 client.Close(); | |
802 } | |
803 #endif | |
804 | |
805 } // namespace net | |
OLD | NEW |