1 // Copyright 2018 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 <stddef.h>
6 #include <stdint.h>
7
8 #include <limits>
9 #include <utility>
10
11 #include "services/network/udp_socket.h"
12
13 #include "base/bind.h"
14 #include "base/logging.h"
15 #include "base/macros.h"
16 #include "base/memory/ptr_util.h"
17 #include "base/run_loop.h"
18 #include "base/test/task_environment.h"
19 #include "build/build_config.h"
20 #include "mojo/public/cpp/bindings/pending_remote.h"
21 #include "mojo/public/cpp/bindings/receiver.h"
22 #include "net/base/net_errors.h"
23 #include "net/socket/udp_socket.h"
24 #include "net/traffic_annotation/network_traffic_annotation.h"
25 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
26 #include "net/url_request/url_request_test_util.h"
27 #include "services/network/public/mojom/udp_socket.mojom.h"
28 #include "services/network/socket_factory.h"
29 #include "services/network/udp_socket_test_util.h"
30 #include "testing/gtest/include/gtest/gtest.h"
31
32 namespace network {
33
34 namespace {
35
36 const size_t kDatagramSize = 255;
37
38 class SocketWrapperTestImpl : public UDPSocket::SocketWrapper {
39 public:
SocketWrapperTestImpl()40 SocketWrapperTestImpl() {}
~SocketWrapperTestImpl()41 ~SocketWrapperTestImpl() override {}
42
Connect(const net::IPEndPoint & remote_addr,mojom::UDPSocketOptionsPtr options,net::IPEndPoint * local_addr_out)43 int Connect(const net::IPEndPoint& remote_addr,
44 mojom::UDPSocketOptionsPtr options,
45 net::IPEndPoint* local_addr_out) override {
46 NOTREACHED();
47 return net::ERR_NOT_IMPLEMENTED;
48 }
Bind(const net::IPEndPoint & local_addr,mojom::UDPSocketOptionsPtr options,net::IPEndPoint * local_addr_out)49 int Bind(const net::IPEndPoint& local_addr,
50 mojom::UDPSocketOptionsPtr options,
51 net::IPEndPoint* local_addr_out) override {
52 NOTREACHED();
53 return net::ERR_NOT_IMPLEMENTED;
54 }
SendTo(net::IOBuffer * buf,int buf_len,const net::IPEndPoint & dest_addr,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)55 int SendTo(
56 net::IOBuffer* buf,
57 int buf_len,
58 const net::IPEndPoint& dest_addr,
59 net::CompletionOnceCallback callback,
60 const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
61 NOTREACHED();
62 return net::ERR_NOT_IMPLEMENTED;
63 }
SetBroadcast(bool broadcast)64 int SetBroadcast(bool broadcast) override {
65 NOTREACHED();
66 return net::ERR_NOT_IMPLEMENTED;
67 }
SetSendBufferSize(int send_buffer_size)68 int SetSendBufferSize(int send_buffer_size) override {
69 NOTREACHED();
70 return net::ERR_NOT_IMPLEMENTED;
71 }
SetReceiveBufferSize(int receive_buffer_size)72 int SetReceiveBufferSize(int receive_buffer_size) override {
73 NOTREACHED();
74 return net::ERR_NOT_IMPLEMENTED;
75 }
JoinGroup(const net::IPAddress & group_address)76 int JoinGroup(const net::IPAddress& group_address) override {
77 NOTREACHED();
78 return net::ERR_NOT_IMPLEMENTED;
79 }
LeaveGroup(const net::IPAddress & group_address)80 int LeaveGroup(const net::IPAddress& group_address) override {
81 NOTREACHED();
82 return net::ERR_NOT_IMPLEMENTED;
83 }
Write(net::IOBuffer * buf,int buf_len,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)84 int Write(
85 net::IOBuffer* buf,
86 int buf_len,
87 net::CompletionOnceCallback callback,
88 const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
89 NOTREACHED();
90 return net::ERR_NOT_IMPLEMENTED;
91 }
RecvFrom(net::IOBuffer * buf,int buf_len,net::IPEndPoint * address,net::CompletionOnceCallback callback)92 int RecvFrom(net::IOBuffer* buf,
93 int buf_len,
94 net::IPEndPoint* address,
95 net::CompletionOnceCallback callback) override {
96 NOTREACHED();
97 return net::ERR_NOT_IMPLEMENTED;
98 }
99
100 private:
101 DISALLOW_COPY_AND_ASSIGN(SocketWrapperTestImpl);
102 };
103
GetLocalHostWithAnyPort()104 net::IPEndPoint GetLocalHostWithAnyPort() {
105 return net::IPEndPoint(net::IPAddress(127, 0, 0, 1), 0);
106 }
107
CreateTestMessage(uint8_t initial,size_t size)108 std::vector<uint8_t> CreateTestMessage(uint8_t initial, size_t size) {
109 std::vector<uint8_t> array(size);
110 for (size_t i = 0; i < size; ++i)
111 array[i] = static_cast<uint8_t>((i + initial) % 256);
112 return array;
113 }
114
115 // A Mock UDPSocket that always returns net::ERR_IO_PENDING for SendTo()s.
116 class HangingUDPSocket : public SocketWrapperTestImpl {
117 public:
HangingUDPSocket()118 HangingUDPSocket() {}
119
120 // SocketWrapperTestImpl implementation.
Bind(const net::IPEndPoint & local_addr,mojom::UDPSocketOptionsPtr options,net::IPEndPoint * local_addr_out)121 int Bind(const net::IPEndPoint& local_addr,
122 mojom::UDPSocketOptionsPtr options,
123 net::IPEndPoint* local_addr_out) override {
124 return net::OK;
125 }
SendTo(net::IOBuffer * buf,int buf_len,const net::IPEndPoint & address,net::CompletionOnceCallback callback,const net::NetworkTrafficAnnotationTag & traffic_annotation)126 int SendTo(
127 net::IOBuffer* buf,
128 int buf_len,
129 const net::IPEndPoint& address,
130 net::CompletionOnceCallback callback,
131 const net::NetworkTrafficAnnotationTag& traffic_annotation) override {
132 EXPECT_EQ(expected_data_,
133 std::vector<unsigned char>(buf->data(), buf->data() + buf_len));
134 if (should_complete_requests_)
135 return net::OK;
136 pending_io_buffers_.push_back(buf);
137 pending_io_buffer_lengths_.push_back(buf_len);
138 pending_send_requests_.push_back(std::move(callback));
139 return net::ERR_IO_PENDING;
140 }
141
set_expected_data(std::vector<uint8_t> expected_data)142 void set_expected_data(std::vector<uint8_t> expected_data) {
143 expected_data_ = expected_data;
144 }
145
pending_io_buffers() const146 const std::vector<net::IOBuffer*>& pending_io_buffers() const {
147 return pending_io_buffers_;
148 }
149
pending_io_buffer_lengths() const150 const std::vector<int>& pending_io_buffer_lengths() const {
151 return pending_io_buffer_lengths_;
152 }
153
154 // Completes all pending requests.
CompleteAllPendingRequests()155 void CompleteAllPendingRequests() {
156 should_complete_requests_ = true;
157 for (auto& request : pending_send_requests_) {
158 std::move(request).Run(net::OK);
159 }
160 pending_send_requests_.clear();
161 }
162
163 private:
164 std::vector<uint8_t> expected_data_;
165 bool should_complete_requests_ = false;
166 std::vector<net::IOBuffer*> pending_io_buffers_;
167 std::vector<int> pending_io_buffer_lengths_;
168 std::vector<net::CompletionOnceCallback> pending_send_requests_;
169 };
170
171 // A Mock UDPSocket that returns 0 byte read.
172 class ZeroByteReadUDPSocket : public SocketWrapperTestImpl {
173 public:
ZeroByteReadUDPSocket()174 ZeroByteReadUDPSocket() {}
Bind(const net::IPEndPoint & local_addr,mojom::UDPSocketOptionsPtr options,net::IPEndPoint * local_addr_out)175 int Bind(const net::IPEndPoint& local_addr,
176 mojom::UDPSocketOptionsPtr options,
177 net::IPEndPoint* local_addr_out) override {
178 return net::OK;
179 }
RecvFrom(net::IOBuffer * buf,int buf_len,net::IPEndPoint * address,net::CompletionOnceCallback callback)180 int RecvFrom(net::IOBuffer* buf,
181 int buf_len,
182 net::IPEndPoint* address,
183 net::CompletionOnceCallback callback) override {
184 *address = GetLocalHostWithAnyPort();
185 return 0;
186 }
187 };
188
189 } // namespace
190
191 class UDPSocketTest : public testing::Test {
192 public:
UDPSocketTest()193 UDPSocketTest()
194 : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
195 factory_(nullptr /*netlog*/, &url_request_context_) {}
~UDPSocketTest()196 ~UDPSocketTest() override {}
197
SetWrappedSocket(UDPSocket * socket,std::unique_ptr<UDPSocket::SocketWrapper> socket_wrapper)198 void SetWrappedSocket(
199 UDPSocket* socket,
200 std::unique_ptr<UDPSocket::SocketWrapper> socket_wrapper) {
201 socket->wrapped_socket_ = std::move(socket_wrapper);
202 }
203
GetRemainingRecvSlots(UDPSocket * socket)204 uint32_t GetRemainingRecvSlots(UDPSocket* socket) {
205 return socket->remaining_recv_slots_;
206 }
207
factory()208 SocketFactory* factory() { return &factory_; }
209
210 private:
211 base::test::TaskEnvironment task_environment_;
212 net::TestURLRequestContext url_request_context_;
213 SocketFactory factory_;
214
215 DISALLOW_COPY_AND_ASSIGN(UDPSocketTest);
216 };
217
TEST_F(UDPSocketTest,Settings)218 TEST_F(UDPSocketTest, Settings) {
219 mojo::Remote<mojom::UDPSocket> socket_remote;
220 factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
221 mojo::NullRemote());
222 net::IPEndPoint server_addr;
223 net::IPEndPoint any_port(GetLocalHostWithAnyPort());
224
225 test::UDPSocketTestHelper helper(&socket_remote);
226 net::IPEndPoint local_addr;
227 mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
228 options->send_buffer_size = 1024;
229 options->receive_buffer_size = 2048;
230 ASSERT_EQ(net::OK,
231 helper.BindSync(any_port, std::move(options), &local_addr));
232 EXPECT_NE(local_addr.ToString(), any_port.ToString());
233 }
234
235 // Tests that Send() is used after Bind() is not supported. Send() should only
236 // be used after Connect().
TEST_F(UDPSocketTest,TestSendWithBind)237 TEST_F(UDPSocketTest, TestSendWithBind) {
238 mojo::Remote<mojom::UDPSocket> socket_remote;
239 factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
240 mojo::NullRemote());
241
242 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
243
244 // Bind() the socket.
245 test::UDPSocketTestHelper helper(&socket_remote);
246 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
247
248 // Connect() has not been used, so Send() is not supported.
249 std::vector<uint8_t> test_msg{1};
250 int result = helper.SendSync(test_msg);
251 EXPECT_EQ(net::ERR_UNEXPECTED, result);
252 }
253
254 // Tests that when SendTo() is used after Connect() is not supported. SendTo()
255 // should only be used after Bind().
TEST_F(UDPSocketTest,TestSendToWithConnect)256 TEST_F(UDPSocketTest, TestSendToWithConnect) {
257 // Create a server socket to listen for incoming datagrams.
258 test::UDPSocketListenerImpl listener;
259 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
260
261 mojo::Remote<mojom::UDPSocket> server_socket;
262 factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
263 listener_receiver.BindNewPipeAndPassRemote());
264
265 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
266 test::UDPSocketTestHelper helper(&server_socket);
267 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
268
269 // Create a client socket to send datagrams.
270 mojo::Remote<mojom::UDPSocket> client_socket;
271 factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
272 mojo::NullRemote());
273 net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
274 test::UDPSocketTestHelper client_helper(&client_socket);
275 ASSERT_EQ(net::OK,
276 client_helper.ConnectSync(server_addr, nullptr, &client_addr));
277
278 std::vector<uint8_t> test_msg({1});
279 int result = client_helper.SendToSync(server_addr, test_msg);
280 EXPECT_EQ(net::ERR_UNEXPECTED, result);
281 }
282
283 // TODO(crbug.com/1014916): These two tests are very flaky on Fuchsia.
284 #if defined(OS_FUCHSIA)
285 #define MAYBE_TestReadSendTo DISABLED_TestReadSendTo
286 #define MAYBE_TestUnexpectedSequences DISABLED_TestUnexpectedSequences
287 #else
288 #define MAYBE_TestReadSendTo TestReadSendTo
289 #define MAYBE_TestUnexpectedSequences TestUnexpectedSequences
290 #endif
291
292 // Tests that the sequence of calling Bind()/Connect() and setters is
293 // important.
TEST_F(UDPSocketTest,MAYBE_TestUnexpectedSequences)294 TEST_F(UDPSocketTest, MAYBE_TestUnexpectedSequences) {
295 mojo::Remote<mojom::UDPSocket> socket_remote;
296 factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
297 mojo::NullRemote());
298 test::UDPSocketTestHelper helper(&socket_remote);
299 net::IPEndPoint local_addr(GetLocalHostWithAnyPort());
300
301 // Now these Setters should not work before Bind().
302 EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetBroadcastSync(true));
303 EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetSendBufferSizeSync(4096));
304 EXPECT_EQ(net::ERR_UNEXPECTED, helper.SetReceiveBufferSizeSync(4096));
305
306 // Now Bind() the socket.
307 ASSERT_EQ(net::OK, helper.BindSync(local_addr, nullptr, &local_addr));
308
309 // Setting the buffer size should now succeed.
310 EXPECT_EQ(net::OK, helper.SetSendBufferSizeSync(4096));
311 EXPECT_EQ(net::OK, helper.SetReceiveBufferSizeSync(4096));
312
313 // Calling Connect() after Bind() should fail because they can't be both used.
314 ASSERT_EQ(net::ERR_SOCKET_IS_CONNECTED,
315 helper.ConnectSync(local_addr, nullptr, &local_addr));
316
317 // Now Close() the socket.
318 socket_remote->Close();
319
320 // Re-Bind() is okay.
321 ASSERT_EQ(net::OK, helper.BindSync(local_addr, nullptr, &local_addr));
322 }
323
324 // Tests that if the underlying socket implementation's Send() returned
325 // ERR_IO_PENDING, udp_socket.cc doesn't free the send buffer.
TEST_F(UDPSocketTest,TestBufferValid)326 TEST_F(UDPSocketTest, TestBufferValid) {
327 mojo::Remote<mojom::UDPSocket> socket_remote;
328 UDPSocket impl(mojo::NullRemote() /*listener*/, nullptr /*net_log*/);
329 mojo::Receiver<mojom::UDPSocket> receiver(&impl);
330 receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());
331
332 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
333 test::UDPSocketTestHelper helper(&socket_remote);
334 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
335
336 HangingUDPSocket* socket_raw_ptr = new HangingUDPSocket();
337 SetWrappedSocket(&impl, base::WrapUnique(socket_raw_ptr));
338
339 std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
340 socket_raw_ptr->set_expected_data(test_msg);
341 base::RunLoop run_loop;
342 socket_remote->SendTo(
343 GetLocalHostWithAnyPort(), test_msg,
344 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
345 base::BindOnce(
346 [](base::RunLoop* run_loop, int result) {
347 EXPECT_EQ(net::OK, result);
348 run_loop->Quit();
349 },
350 base::Unretained(&run_loop)));
351
352 socket_remote.FlushForTesting();
353
354 ASSERT_EQ(1u, socket_raw_ptr->pending_io_buffers().size());
355 ASSERT_EQ(1u, socket_raw_ptr->pending_io_buffer_lengths().size());
356 // Make sure the caller of HangingUDPSocket doesn't destroy the send buffer,
357 // and that buffer still contains the exact same data.
358 net::IOBuffer* buf = socket_raw_ptr->pending_io_buffers()[0];
359 int buf_len = socket_raw_ptr->pending_io_buffer_lengths()[0];
360 EXPECT_EQ(test_msg,
361 std::vector<unsigned char>(buf->data(), buf->data() + buf_len));
362 }
363
364 // Test that exercises the queuing of send requests and makes sure
365 // ERR_INSUFFICIENT_RESOURCES is returned appropriately.
TEST_F(UDPSocketTest,TestInsufficientResources)366 TEST_F(UDPSocketTest, TestInsufficientResources) {
367 mojo::Remote<mojom::UDPSocket> socket_remote;
368 UDPSocket impl(mojo::NullRemote() /*listener*/, nullptr /*net_log*/);
369 mojo::Receiver<mojom::UDPSocket> receiver(&impl);
370 receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());
371
372 const size_t kQueueSize = UDPSocket::kMaxPendingSendRequests;
373
374 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
375 test::UDPSocketTestHelper helper(&socket_remote);
376 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
377
378 HangingUDPSocket* socket_raw_ptr = new HangingUDPSocket();
379 SetWrappedSocket(&impl, base::WrapUnique(socket_raw_ptr));
380
381 std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
382 socket_raw_ptr->set_expected_data(test_msg);
383 // Send |kQueueSize| + 1 datagrams in a row, so the queue is filled up.
384 std::vector<std::unique_ptr<base::RunLoop>> run_loops;
385 for (size_t i = 0; i < kQueueSize + 1; ++i) {
386 run_loops.push_back(std::make_unique<base::RunLoop>());
387 socket_remote->SendTo(
388 GetLocalHostWithAnyPort(), test_msg,
389 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
390 base::BindOnce(
391 [](base::RunLoop* run_loop, int result) {
392 EXPECT_EQ(net::OK, result);
393 run_loop->Quit();
394 },
395 base::Unretained(run_loops[i].get())));
396 }
397
398 // SendTo() beyond the queue size should fail.
399 EXPECT_EQ(net::ERR_INSUFFICIENT_RESOURCES,
400 helper.SendToSync(GetLocalHostWithAnyPort(), test_msg));
401
402 // Complete all pending requests. Queued SendTo() should hear back.
403 socket_raw_ptr->CompleteAllPendingRequests();
404 for (const auto& loop : run_loops) {
405 loop->Run();
406 }
407 }
408
TEST_F(UDPSocketTest,TestReceiveMoreOverflow)409 TEST_F(UDPSocketTest, TestReceiveMoreOverflow) {
410 // Create a server socket to listen for incoming datagrams.
411 test::UDPSocketListenerImpl listener;
412 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
413
414 mojo::Remote<mojom::UDPSocket> server_socket;
415 UDPSocket impl(listener_receiver.BindNewPipeAndPassRemote(),
416 nullptr /*net_log*/);
417 mojo::Receiver<mojom::UDPSocket> receiver(&impl);
418 receiver.Bind(server_socket.BindNewPipeAndPassReceiver());
419
420 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
421 test::UDPSocketTestHelper helper(&server_socket);
422 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
423
424 server_socket->ReceiveMore(std::numeric_limits<uint32_t>::max());
425 server_socket.FlushForTesting();
426 EXPECT_EQ(std::numeric_limits<uint32_t>::max(), GetRemainingRecvSlots(&impl));
427 server_socket->ReceiveMore(1);
428 server_socket.FlushForTesting();
429 EXPECT_EQ(std::numeric_limits<uint32_t>::max(), GetRemainingRecvSlots(&impl));
430 }
431
TEST_F(UDPSocketTest,TestReadSend)432 TEST_F(UDPSocketTest, TestReadSend) {
433 // Create a server socket to listen for incoming datagrams.
434 test::UDPSocketListenerImpl listener;
435 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
436
437 mojo::Remote<mojom::UDPSocket> server_socket;
438 factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
439 listener_receiver.BindNewPipeAndPassRemote());
440
441 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
442 test::UDPSocketTestHelper helper(&server_socket);
443 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
444
445 // Create a client socket to send datagrams.
446 mojo::Remote<mojom::UDPSocket> client_socket;
447 factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
448 mojo::NullRemote());
449 net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
450 test::UDPSocketTestHelper client_helper(&client_socket);
451 ASSERT_EQ(net::OK,
452 client_helper.ConnectSync(server_addr, nullptr, &client_addr));
453
454 const size_t kDatagramCount = 6;
455 server_socket->ReceiveMore(kDatagramCount);
456
457 for (size_t i = 0; i < kDatagramCount; ++i) {
458 std::vector<uint8_t> test_msg(
459 CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize));
460 int result = client_helper.SendSync(test_msg);
461 EXPECT_EQ(net::OK, result);
462 }
463
464 listener.WaitForReceivedResults(kDatagramCount);
465 EXPECT_EQ(kDatagramCount, listener.results().size());
466
467 int i = 0;
468 for (const auto& result : listener.results()) {
469 EXPECT_EQ(net::OK, result.net_error);
470 EXPECT_EQ(result.src_addr, client_addr);
471 EXPECT_EQ(CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
472 result.data.value());
473 i++;
474 }
475 // Tests that sending a message that is larger than the specified limit
476 // results in an early rejection.
477 std::vector<uint8_t> large_msg(64 * 1024, 1);
478 EXPECT_EQ(net::ERR_MSG_TOO_BIG, helper.SendToSync(client_addr, large_msg));
479
480 // Close and re-Connect client socket.
481 client_socket->Close();
482 client_socket.FlushForTesting();
483
484 // Make sure datagram can still be sent from the re-connected client socket.
485 ASSERT_EQ(net::OK,
486 client_helper.ConnectSync(server_addr, nullptr, &client_addr));
487 server_socket->ReceiveMore(1);
488 std::vector<uint8_t> msg(CreateTestMessage(0, kDatagramSize));
489 EXPECT_EQ(net::OK, client_helper.SendSync(msg));
490
491 listener.WaitForReceivedResults(kDatagramCount + 1);
492 ASSERT_EQ(kDatagramCount + 1, listener.results().size());
493
494 auto result = listener.results()[kDatagramCount];
495 EXPECT_EQ(net::OK, result.net_error);
496 EXPECT_EQ(result.src_addr, client_addr);
497 EXPECT_EQ(msg, result.data.value());
498 }
499
TEST_F(UDPSocketTest,MAYBE_TestReadSendTo)500 TEST_F(UDPSocketTest, MAYBE_TestReadSendTo) {
501 // Create a server socket to send data.
502 mojo::Remote<mojom::UDPSocket> server_socket;
503 factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
504 mojo::NullRemote());
505
506 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
507 test::UDPSocketTestHelper helper(&server_socket);
508 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
509
510 // Create a client socket to send datagrams.
511 test::UDPSocketListenerImpl listener;
512 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
513
514 mojo::Remote<mojom::UDPSocket> client_socket;
515 factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
516 listener_receiver.BindNewPipeAndPassRemote());
517 net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
518 test::UDPSocketTestHelper client_helper(&client_socket);
519 ASSERT_EQ(net::OK,
520 client_helper.ConnectSync(server_addr, nullptr, &client_addr));
521
522 const size_t kDatagramCount = 6;
523 client_socket->ReceiveMore(kDatagramCount);
524
525 for (size_t i = 0; i < kDatagramCount; ++i) {
526 std::vector<uint8_t> test_msg(
527 CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize));
528 int result = helper.SendToSync(client_addr, test_msg);
529 EXPECT_EQ(net::OK, result);
530 }
531
532 listener.WaitForReceivedResults(kDatagramCount);
533 EXPECT_EQ(kDatagramCount, listener.results().size());
534
535 int i = 0;
536 for (const auto& result : listener.results()) {
537 EXPECT_EQ(net::OK, result.net_error);
538 EXPECT_FALSE(result.src_addr);
539 EXPECT_EQ(CreateTestMessage(static_cast<uint8_t>(i), kDatagramSize),
540 result.data.value());
541 i++;
542 }
543
544 // Tests that sending a message that is larger than the specified limit
545 // results in an early rejection.
546 std::vector<uint8_t> large_msg(64 * 1024, 1);
547 EXPECT_EQ(net::ERR_MSG_TOO_BIG, helper.SendToSync(client_addr, large_msg));
548
549 // Make sure datagram can still be sent from the re-bound server socket.
550 server_socket->Close();
551 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
552 client_socket->ReceiveMore(1);
553 std::vector<uint8_t> msg(CreateTestMessage(0, kDatagramSize));
554 EXPECT_EQ(net::OK, helper.SendToSync(client_addr, msg));
555
556 listener.WaitForReceivedResults(kDatagramCount + 1);
557 ASSERT_EQ(kDatagramCount + 1, listener.results().size());
558
559 auto result = listener.results()[kDatagramCount];
560 EXPECT_EQ(net::OK, result.net_error);
561 EXPECT_FALSE(result.src_addr);
562 EXPECT_EQ(msg, result.data.value());
563 }
564
TEST_F(UDPSocketTest,TestReceiveMoreWithBufferSize)565 TEST_F(UDPSocketTest, TestReceiveMoreWithBufferSize) {
566 // Create a server socket to listen for incoming datagrams.
567 test::UDPSocketListenerImpl listener;
568 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
569
570 mojo::Remote<mojom::UDPSocket> server_socket;
571 factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
572 listener_receiver.BindNewPipeAndPassRemote());
573
574 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
575 test::UDPSocketTestHelper helper(&server_socket);
576 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
577
578 // Create a client socket to send datagrams.
579 mojo::Remote<mojom::UDPSocket> client_socket;
580 factory()->CreateUDPSocket(client_socket.BindNewPipeAndPassReceiver(),
581 mojo::NullRemote());
582 net::IPEndPoint client_addr(GetLocalHostWithAnyPort());
583 test::UDPSocketTestHelper client_helper(&client_socket);
584 ASSERT_EQ(net::OK,
585 client_helper.ConnectSync(server_addr, nullptr, &client_addr));
586
587 // Use a buffer size that is 1 byte smaller than the datagram size.
588 // This should result in net::ERR_MSG_TOO_BIG, because the transport can't
589 // complete the read with this small buffer size.
590 size_t buffer_size = kDatagramSize - 1;
591 server_socket->ReceiveMoreWithBufferSize(1, buffer_size);
592 std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
593 ASSERT_EQ(net::OK, client_helper.SendSync(test_msg));
594
595 listener.WaitForReceivedResults(1);
596 ASSERT_EQ(1u, listener.results().size());
597 auto result = listener.results()[0];
598 EXPECT_EQ(net::ERR_MSG_TOO_BIG, result.net_error);
599 EXPECT_FALSE(result.data);
600
601 // Now use a buffer size that is equal to datagram size. This should be okay.
602 server_socket->ReceiveMoreWithBufferSize(1, kDatagramSize);
603 ASSERT_EQ(net::OK, client_helper.SendSync(test_msg));
604
605 listener.WaitForReceivedResults(2);
606 ASSERT_EQ(2u, listener.results().size());
607 result = listener.results()[1];
608 EXPECT_EQ(net::OK, result.net_error);
609 EXPECT_EQ(client_addr, result.src_addr.value());
610 EXPECT_EQ(test_msg, result.data.value());
611 }
612
613 // Make sure passing an invalid net::IPEndPoint will be detected by
614 // serialization/deserialization in mojo.
TEST_F(UDPSocketTest,TestSendToInvalidAddress)615 TEST_F(UDPSocketTest, TestSendToInvalidAddress) {
616 mojo::Remote<mojom::UDPSocket> server_socket;
617 factory()->CreateUDPSocket(server_socket.BindNewPipeAndPassReceiver(),
618 mojo::NullRemote());
619
620 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
621 test::UDPSocketTestHelper helper(&server_socket);
622 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
623
624 std::vector<uint8_t> test_msg{1};
625 std::vector<uint8_t> invalid_ip_addr{127, 0, 0, 0, 1};
626 net::IPAddress ip_address(invalid_ip_addr.data(), invalid_ip_addr.size());
627 EXPECT_FALSE(ip_address.IsValid());
628 net::IPEndPoint invalid_addr(ip_address, 53);
629 server_socket->SendTo(
630 invalid_addr, test_msg,
631 net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
632 base::BindOnce([](int result) {}));
633 // Make sure that the pipe is broken upon processing |invalid_addr|.
634 base::RunLoop run_loop;
635 server_socket.set_disconnect_handler(
636 base::BindOnce([](base::RunLoop* run_loop) { run_loop->Quit(); },
637 base::Unretained(&run_loop)));
638 run_loop.Run();
639 }
640
641 // Tests that it is legal for UDPSocketListener::OnReceive() to be called with
642 // 0 byte payload.
TEST_F(UDPSocketTest,TestReadZeroByte)643 TEST_F(UDPSocketTest, TestReadZeroByte) {
644 test::UDPSocketListenerImpl listener;
645 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
646
647 mojo::Remote<mojom::UDPSocket> socket_remote;
648 UDPSocket impl(listener_receiver.BindNewPipeAndPassRemote(),
649 nullptr /*net_log*/);
650 mojo::Receiver<mojom::UDPSocket> receiver(&impl);
651 receiver.Bind(socket_remote.BindNewPipeAndPassReceiver());
652
653 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
654 test::UDPSocketTestHelper helper(&socket_remote);
655 ASSERT_EQ(net::OK, helper.BindSync(server_addr, nullptr, &server_addr));
656
657 SetWrappedSocket(&impl, std::make_unique<ZeroByteReadUDPSocket>());
658
659 socket_remote->ReceiveMore(1);
660
661 listener.WaitForReceivedResults(1);
662 ASSERT_EQ(1u, listener.results().size());
663
664 auto result = listener.results()[0];
665 EXPECT_EQ(net::OK, result.net_error);
666 EXPECT_TRUE(result.data);
667 EXPECT_EQ(std::vector<uint8_t>(), result.data.value());
668 }
669
670 #if defined(OS_ANDROID)
671 // Some Android devices do not support multicast socket.
672 // The ones supporting multicast need WifiManager.MulticastLock to enable it.
673 // https://developer.android.com/reference/android/net/wifi/WifiManager.MulticastLock.html
674 #define MAYBE_JoinMulticastGroup DISABLED_JoinMulticastGroup
675 #else
676 #define MAYBE_JoinMulticastGroup JoinMulticastGroup
677 #endif // defined(OS_ANDROID)
TEST_F(UDPSocketTest,MAYBE_JoinMulticastGroup)678 TEST_F(UDPSocketTest, MAYBE_JoinMulticastGroup) {
679 const char kGroup[] = "237.132.100.17";
680
681 net::IPAddress group_ip;
682 EXPECT_TRUE(group_ip.AssignFromIPLiteral(kGroup));
683 mojo::Remote<mojom::UDPSocket> socket_remote;
684 test::UDPSocketListenerImpl listener;
685 mojo::Receiver<mojom::UDPSocketListener> listener_receiver(&listener);
686 factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
687 listener_receiver.BindNewPipeAndPassRemote());
688
689 test::UDPSocketTestHelper helper(&socket_remote);
690
691 mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
692 #if defined(OS_FUCHSIA)
693 // Fuchsia currently doesn't support automatic interface selection for
694 // multicast, so interface index needs to be set explicitly.
695 // See https://fuchsia.atlassian.net/browse/NET-195 .
696 options->multicast_interface = 1;
697 #endif // defined(OS_FUCHSIA)
698 options->allow_address_sharing_for_multicast = true;
699
700 net::IPAddress bind_ip_address;
701 EXPECT_TRUE(bind_ip_address.AssignFromIPLiteral("0.0.0.0"));
702 net::IPEndPoint socket_address(bind_ip_address, 0);
703 ASSERT_EQ(net::OK, helper.BindSync(socket_address, std::move(options),
704 &socket_address));
705 int port = socket_address.port();
706 EXPECT_NE(0, port);
707 EXPECT_EQ(net::OK, helper.JoinGroupSync(group_ip));
708 // Joining group multiple times.
709 EXPECT_NE(net::OK, helper.JoinGroupSync(group_ip));
710
711 // Receive messages from itself.
712 std::vector<uint8_t> test_msg(CreateTestMessage(0, kDatagramSize));
713 net::IPEndPoint group_alias(group_ip, port);
714 EXPECT_EQ(net::OK, helper.SendToSync(group_alias, test_msg));
715 socket_remote->ReceiveMore(1);
716 listener.WaitForReceivedResults(1);
717 ASSERT_EQ(1u, listener.results().size());
718 auto result = listener.results()[0];
719 EXPECT_EQ(net::OK, result.net_error);
720 EXPECT_EQ(port, result.src_addr.value().port());
721 EXPECT_EQ(test_msg, result.data.value());
722
723 // Create a second socket to send a packet to multicast group.
724 mojo::Remote<mojom::UDPSocket> second_socket_remote;
725 factory()->CreateUDPSocket(second_socket_remote.BindNewPipeAndPassReceiver(),
726 mojo::NullRemote());
727 test::UDPSocketTestHelper second_socket_helper(&second_socket_remote);
728 net::IPEndPoint second_socket_address(bind_ip_address, 0);
729 ASSERT_EQ(net::OK,
730 second_socket_helper.BindSync(second_socket_address, nullptr,
731 &second_socket_address));
732 int second_port = second_socket_address.port();
733 ASSERT_EQ(net::OK, second_socket_helper.SendToSync(group_alias, test_msg));
734
735 // First socket should receive packet sent by the second socket.
736 socket_remote->ReceiveMore(1);
737 listener.WaitForReceivedResults(2);
738 ASSERT_EQ(2u, listener.results().size());
739 result = listener.results()[1];
740 EXPECT_EQ(net::OK, result.net_error);
741 EXPECT_EQ(second_port, result.src_addr.value().port());
742 EXPECT_EQ(test_msg, result.data.value());
743
744 // First socket leaves group multiple times.
745 EXPECT_EQ(net::OK, helper.LeaveGroupSync(group_ip));
746 EXPECT_NE(net::OK, helper.LeaveGroupSync(group_ip));
747
748 // No longer can receive messages from itself or from second socket.
749 EXPECT_EQ(net::OK, helper.SendToSync(group_alias, test_msg));
750 ASSERT_EQ(net::OK, second_socket_helper.SendToSync(group_alias, test_msg));
751 socket_remote->ReceiveMore(1);
752 socket_remote.FlushForTesting();
753 ASSERT_EQ(2u, listener.results().size());
754 }
755
TEST_F(UDPSocketTest,ErrorHappensDuringSocketOptionsConfiguration)756 TEST_F(UDPSocketTest, ErrorHappensDuringSocketOptionsConfiguration) {
757 mojo::Remote<mojom::UDPSocket> server_socket_remote;
758 factory()->CreateUDPSocket(server_socket_remote.BindNewPipeAndPassReceiver(),
759 mojo::NullRemote());
760 test::UDPSocketTestHelper server_helper(&server_socket_remote);
761 net::IPEndPoint server_addr(GetLocalHostWithAnyPort());
762 ASSERT_EQ(net::OK,
763 server_helper.BindSync(server_addr, nullptr, &server_addr));
764
765 mojo::Remote<mojom::UDPSocket> socket_remote;
766 factory()->CreateUDPSocket(socket_remote.BindNewPipeAndPassReceiver(),
767 mojo::NullRemote());
768 test::UDPSocketTestHelper helper(&socket_remote);
769
770 // Invalid options.
771 mojom::UDPSocketOptionsPtr options = mojom::UDPSocketOptions::New();
772 options->multicast_time_to_live = 256;
773
774 net::IPEndPoint local_addr;
775 ASSERT_EQ(net::ERR_INVALID_ARGUMENT,
776 helper.ConnectSync(server_addr, std::move(options), &local_addr));
777
778 // It's legal to retry Connect() with valid options.
779 mojom::UDPSocketOptionsPtr valid_options = mojom::UDPSocketOptions::New();
780 valid_options->multicast_time_to_live = 255;
781 ASSERT_EQ(net::OK,
782 helper.ConnectSync(server_addr, std::move(options), &local_addr));
783 EXPECT_NE(0, local_addr.port());
784 }
785
786 } // namespace network
787