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