xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/io/socket_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2022 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 "quiche/quic/core/io/socket.h"
6 
7 #include <string>
8 
9 #include "absl/status/status.h"
10 #include "absl/status/statusor.h"
11 #include "absl/strings/string_view.h"
12 #include "absl/types/span.h"
13 #include "quiche/quic/platform/api/quic_ip_address.h"
14 #include "quiche/quic/platform/api/quic_ip_address_family.h"
15 #include "quiche/quic/platform/api/quic_socket_address.h"
16 #include "quiche/quic/test_tools/test_ip_packets.h"
17 #include "quiche/common/platform/api/quiche_logging.h"
18 #include "quiche/common/platform/api/quiche_test.h"
19 #include "quiche/common/platform/api/quiche_test_loopback.h"
20 #include "quiche/common/test_tools/quiche_test_utils.h"
21 
22 namespace quic::test {
23 namespace {
24 
25 using quiche::test::QuicheTest;
26 using quiche::test::StatusIs;
27 using testing::Lt;
28 using testing::SizeIs;
29 
CreateTestSocket(socket_api::SocketProtocol protocol,bool blocking=true)30 SocketFd CreateTestSocket(socket_api::SocketProtocol protocol,
31                           bool blocking = true) {
32   absl::StatusOr<SocketFd> socket = socket_api::CreateSocket(
33       quiche::TestLoopback().address_family(), protocol, blocking);
34 
35   if (socket.ok()) {
36     return socket.value();
37   } else {
38     QUICHE_CHECK(false);
39     return kInvalidSocketFd;
40   }
41 }
42 
CreateTestRawSocket(bool blocking=true,IpAddressFamily address_family=IpAddressFamily::IP_UNSPEC)43 SocketFd CreateTestRawSocket(
44     bool blocking = true,
45     IpAddressFamily address_family = IpAddressFamily::IP_UNSPEC) {
46   absl::StatusOr<SocketFd> socket;
47   switch (address_family) {
48     case IpAddressFamily::IP_V4:
49       socket = socket_api::CreateSocket(
50           quiche::TestLoopback4().address_family(),
51           socket_api::SocketProtocol::kRawIp, blocking);
52       break;
53     case IpAddressFamily::IP_V6:
54       socket = socket_api::CreateSocket(
55           quiche::TestLoopback6().address_family(),
56           socket_api::SocketProtocol::kRawIp, blocking);
57       break;
58     case IpAddressFamily::IP_UNSPEC:
59       socket = socket_api::CreateSocket(quiche::TestLoopback().address_family(),
60                                         socket_api::SocketProtocol::kRawIp,
61                                         blocking);
62       break;
63   }
64 
65   if (socket.ok()) {
66     return socket.value();
67   } else {
68     // This is expected if test not run with relevant admin privileges or if
69     // address family is unsupported.
70     QUICHE_CHECK(absl::IsPermissionDenied(socket.status()) ||
71                  absl::IsNotFound(socket.status()));
72     return kInvalidSocketFd;
73   }
74 }
75 
TEST(SocketTest,CreateAndCloseSocket)76 TEST(SocketTest, CreateAndCloseSocket) {
77   QuicIpAddress localhost_address = quiche::TestLoopback();
78   absl::StatusOr<SocketFd> created_socket = socket_api::CreateSocket(
79       localhost_address.address_family(), socket_api::SocketProtocol::kUdp);
80 
81   QUICHE_EXPECT_OK(created_socket.status());
82 
83   QUICHE_EXPECT_OK(socket_api::Close(created_socket.value()));
84 }
85 
TEST(SocketTest,CreateAndCloseRawSocket)86 TEST(SocketTest, CreateAndCloseRawSocket) {
87   QuicIpAddress localhost_address = quiche::TestLoopback();
88   absl::StatusOr<SocketFd> created_socket = socket_api::CreateSocket(
89       localhost_address.address_family(), socket_api::SocketProtocol::kRawIp);
90 
91   // Raw IP socket creation will typically fail if not run with relevant admin
92   // privileges.
93   if (!created_socket.ok()) {
94     EXPECT_THAT(created_socket.status(),
95                 StatusIs(absl::StatusCode::kPermissionDenied));
96     return;
97   }
98 
99   QUICHE_EXPECT_OK(socket_api::Close(created_socket.value()));
100 }
101 
TEST(SocketTest,SetSocketBlocking)102 TEST(SocketTest, SetSocketBlocking) {
103   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
104                                      /*blocking=*/true);
105 
106   QUICHE_EXPECT_OK(socket_api::SetSocketBlocking(socket, /*blocking=*/false));
107 
108   QUICHE_EXPECT_OK(socket_api::Close(socket));
109 }
110 
TEST(SocketTest,SetReceiveBufferSize)111 TEST(SocketTest, SetReceiveBufferSize) {
112   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
113                                      /*blocking=*/true);
114 
115   QUICHE_EXPECT_OK(socket_api::SetReceiveBufferSize(socket, /*size=*/100));
116 
117   QUICHE_EXPECT_OK(socket_api::Close(socket));
118 }
119 
TEST(SocketTest,SetSendBufferSize)120 TEST(SocketTest, SetSendBufferSize) {
121   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
122                                      /*blocking=*/true);
123 
124   QUICHE_EXPECT_OK(socket_api::SetSendBufferSize(socket, /*size=*/100));
125 
126   QUICHE_EXPECT_OK(socket_api::Close(socket));
127 }
128 
TEST(SocketTest,SetIpHeaderIncludedForRaw)129 TEST(SocketTest, SetIpHeaderIncludedForRaw) {
130   SocketFd socket =
131       CreateTestRawSocket(/*blocking=*/true, IpAddressFamily::IP_V4);
132   if (socket == kInvalidSocketFd) {
133     GTEST_SKIP();
134   }
135 
136   QUICHE_EXPECT_OK(socket_api::SetIpHeaderIncluded(
137       socket, IpAddressFamily::IP_V4, /*ip_header_included=*/true));
138 
139   QUICHE_EXPECT_OK(socket_api::Close(socket));
140 }
141 
TEST(SocketTest,SetIpHeaderIncludedForRawV6)142 TEST(SocketTest, SetIpHeaderIncludedForRawV6) {
143   SocketFd socket =
144       CreateTestRawSocket(/*blocking=*/true, IpAddressFamily::IP_V6);
145   if (socket == kInvalidSocketFd) {
146     GTEST_SKIP();
147   }
148 
149   QUICHE_EXPECT_OK(socket_api::SetIpHeaderIncluded(
150       socket, IpAddressFamily::IP_V6, /*ip_header_included=*/true));
151 
152   QUICHE_EXPECT_OK(socket_api::Close(socket));
153 }
154 
TEST(SocketTest,SetIpHeaderIncludedForUdp)155 TEST(SocketTest, SetIpHeaderIncludedForUdp) {
156   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
157                                      /*blocking=*/true);
158 
159   // Expect option only allowed for raw IP sockets.
160   EXPECT_THAT(socket_api::SetIpHeaderIncluded(socket, IpAddressFamily::IP_V4,
161                                               /*ip_header_included=*/true),
162               StatusIs(absl::StatusCode::kInvalidArgument));
163   EXPECT_THAT(socket_api::SetIpHeaderIncluded(socket, IpAddressFamily::IP_V6,
164                                               /*ip_header_included=*/true),
165               StatusIs(absl::StatusCode::kInvalidArgument));
166 
167   QUICHE_EXPECT_OK(socket_api::Close(socket));
168 }
169 
TEST(SocketTest,Connect)170 TEST(SocketTest, Connect) {
171   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
172 
173   // UDP, so "connecting" should succeed without any listening sockets.
174   QUICHE_EXPECT_OK(socket_api::Connect(
175       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
176 
177   QUICHE_EXPECT_OK(socket_api::Close(socket));
178 }
179 
TEST(SocketTest,GetSocketError)180 TEST(SocketTest, GetSocketError) {
181   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
182                                      /*blocking=*/true);
183 
184   absl::Status error = socket_api::GetSocketError(socket);
185   QUICHE_EXPECT_OK(error);
186 
187   QUICHE_EXPECT_OK(socket_api::Close(socket));
188 }
189 
TEST(SocketTest,Bind)190 TEST(SocketTest, Bind) {
191   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
192 
193   QUICHE_EXPECT_OK(socket_api::Bind(
194       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
195 
196   QUICHE_EXPECT_OK(socket_api::Close(socket));
197 }
198 
TEST(SocketTest,GetSocketAddress)199 TEST(SocketTest, GetSocketAddress) {
200   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
201   QUICHE_ASSERT_OK(socket_api::Bind(
202       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
203 
204   absl::StatusOr<QuicSocketAddress> address =
205       socket_api::GetSocketAddress(socket);
206   QUICHE_EXPECT_OK(address);
207   EXPECT_TRUE(address.value().IsInitialized());
208   EXPECT_EQ(address.value().host(), quiche::TestLoopback());
209 
210   QUICHE_EXPECT_OK(socket_api::Close(socket));
211 }
212 
TEST(SocketTest,Listen)213 TEST(SocketTest, Listen) {
214   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kTcp);
215   QUICHE_ASSERT_OK(socket_api::Bind(
216       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
217 
218   QUICHE_EXPECT_OK(socket_api::Listen(socket, /*backlog=*/5));
219 
220   QUICHE_EXPECT_OK(socket_api::Close(socket));
221 }
222 
TEST(SocketTest,Accept)223 TEST(SocketTest, Accept) {
224   // Need a non-blocking socket to avoid waiting when no connection comes.
225   SocketFd socket =
226       CreateTestSocket(socket_api::SocketProtocol::kTcp, /*blocking=*/false);
227   QUICHE_ASSERT_OK(socket_api::Bind(
228       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
229   QUICHE_ASSERT_OK(socket_api::Listen(socket, /*backlog=*/5));
230 
231   // Nothing set up to connect, so expect kUnavailable.
232   absl::StatusOr<socket_api::AcceptResult> result = socket_api::Accept(socket);
233   EXPECT_THAT(result, StatusIs(absl::StatusCode::kUnavailable));
234 
235   QUICHE_EXPECT_OK(socket_api::Close(socket));
236 }
237 
TEST(SocketTest,Receive)238 TEST(SocketTest, Receive) {
239   // Non-blocking to avoid waiting when no data to receive.
240   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
241                                      /*blocking=*/false);
242 
243   // On Windows, recv() fails on a socket that is connectionless and not bound.
244   QUICHE_ASSERT_OK(socket_api::Bind(
245       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
246 
247   std::string buffer(100, 0);
248   absl::StatusOr<absl::Span<char>> result =
249       socket_api::Receive(socket, absl::MakeSpan(buffer));
250   EXPECT_THAT(result, StatusIs(absl::StatusCode::kUnavailable));
251 
252   QUICHE_EXPECT_OK(socket_api::Close(socket));
253 }
254 
TEST(SocketTest,Peek)255 TEST(SocketTest, Peek) {
256   // Non-blocking to avoid waiting when no data to receive.
257   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp,
258                                      /*blocking=*/false);
259 
260   // On Windows, recv() fails on a socket that is connectionless and not bound.
261   QUICHE_ASSERT_OK(socket_api::Bind(
262       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
263 
264   std::string buffer(100, 0);
265   absl::StatusOr<absl::Span<char>> result =
266       socket_api::Receive(socket, absl::MakeSpan(buffer), /*peek=*/true);
267   EXPECT_THAT(result, StatusIs(absl::StatusCode::kUnavailable));
268 
269   QUICHE_EXPECT_OK(socket_api::Close(socket));
270 }
271 
TEST(SocketTest,Send)272 TEST(SocketTest, Send) {
273   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
274   // UDP, so "connecting" should succeed without any listening sockets.
275   QUICHE_ASSERT_OK(socket_api::Connect(
276       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
277 
278   char buffer[] = {12, 34, 56, 78};
279   // Expect at least some data to be sent successfully.
280   absl::StatusOr<absl::string_view> result =
281       socket_api::Send(socket, absl::string_view(buffer, sizeof(buffer)));
282   QUICHE_ASSERT_OK(result.status());
283   EXPECT_THAT(result.value(), SizeIs(Lt(4)));
284 
285   QUICHE_EXPECT_OK(socket_api::Close(socket));
286 }
287 
TEST(SocketTest,SendTo)288 TEST(SocketTest, SendTo) {
289   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
290 
291   // Send data to an arbitrarily-chosen ephemeral port.
292   char buffer[] = {12, 34, 56, 78};
293   absl::StatusOr<absl::string_view> result = socket_api::SendTo(
294       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/57290),
295       absl::string_view(buffer, sizeof(buffer)));
296 
297   // Expect at least some data to be sent successfully.
298   QUICHE_ASSERT_OK(result.status());
299   EXPECT_THAT(result.value(), SizeIs(Lt(4)));
300 
301   QUICHE_EXPECT_OK(socket_api::Close(socket));
302 }
303 
TEST(SocketTest,SendToWithConnection)304 TEST(SocketTest, SendToWithConnection) {
305   SocketFd socket = CreateTestSocket(socket_api::SocketProtocol::kUdp);
306   // UDP, so "connecting" should succeed without any listening sockets.
307   QUICHE_ASSERT_OK(socket_api::Connect(
308       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/0)));
309 
310   // Send data to an arbitrarily-chosen ephemeral port.
311   char buffer[] = {12, 34, 56, 78};
312   absl::StatusOr<absl::string_view> result = socket_api::SendTo(
313       socket, QuicSocketAddress(quiche::TestLoopback(), /*port=*/50495),
314       absl::string_view(buffer, sizeof(buffer)));
315   // Expect at least some data to be sent successfully.
316   QUICHE_ASSERT_OK(result.status());
317   EXPECT_THAT(result.value(), SizeIs(Lt(4)));
318 
319   QUICHE_EXPECT_OK(socket_api::Close(socket));
320 }
321 
TEST(SocketTest,SendToForRaw)322 TEST(SocketTest, SendToForRaw) {
323   SocketFd socket = CreateTestRawSocket(/*blocking=*/true);
324   if (socket == kInvalidSocketFd) {
325     GTEST_SKIP();
326   }
327 
328   QuicIpAddress localhost_address = quiche::TestLoopback();
329   QUICHE_EXPECT_OK(socket_api::SetIpHeaderIncluded(
330       socket, localhost_address.address_family(),
331       /*ip_header_included=*/false));
332 
333   // Arbitrarily-chosen ephemeral ports.
334   QuicSocketAddress client_address(localhost_address, /*port=*/53368);
335   QuicSocketAddress server_address(localhost_address, /*port=*/56362);
336   std::string packet = CreateUdpPacket(client_address, server_address, "foo");
337   absl::StatusOr<absl::string_view> result = socket_api::SendTo(
338       socket, QuicSocketAddress(localhost_address, /*port=*/56362), packet);
339 
340   // Expect at least some data to be sent successfully.
341   QUICHE_ASSERT_OK(result.status());
342   EXPECT_THAT(result.value(), SizeIs(Lt(packet.size())));
343 
344   QUICHE_EXPECT_OK(socket_api::Close(socket));
345 }
346 
TEST(SocketTest,SendToForRawWithIpHeader)347 TEST(SocketTest, SendToForRawWithIpHeader) {
348   SocketFd socket = CreateTestRawSocket(/*blocking=*/true);
349   if (socket == kInvalidSocketFd) {
350     GTEST_SKIP();
351   }
352 
353   QuicIpAddress localhost_address = quiche::TestLoopback();
354   QUICHE_EXPECT_OK(socket_api::SetIpHeaderIncluded(
355       socket, localhost_address.address_family(), /*ip_header_included=*/true));
356 
357   // Arbitrarily-chosen ephemeral ports.
358   QuicSocketAddress client_address(localhost_address, /*port=*/53368);
359   QuicSocketAddress server_address(localhost_address, /*port=*/56362);
360   std::string packet =
361       CreateIpPacket(client_address.host(), server_address.host(),
362                      CreateUdpPacket(client_address, server_address, "foo"));
363   absl::StatusOr<absl::string_view> result = socket_api::SendTo(
364       socket, QuicSocketAddress(localhost_address, /*port=*/56362), packet);
365 
366   // Expect at least some data to be sent successfully.
367   QUICHE_ASSERT_OK(result.status());
368   EXPECT_THAT(result.value(), SizeIs(Lt(packet.size())));
369 
370   QUICHE_EXPECT_OK(socket_api::Close(socket));
371 }
372 
373 }  // namespace
374 }  // namespace quic::test
375