xref: /aosp_15_r20/external/grpc-grpc/test/core/event_engine/windows/create_sockpair.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include <grpc/support/port_platform.h>
15 #ifdef GPR_WINDOWS
16 
17 #include <winsock2.h>
18 #include <ws2tcpip.h>
19 
20 #include "absl/status/status.h"
21 
22 #include "src/core/lib/event_engine/windows/win_socket.h"
23 #include "src/core/lib/iomgr/error.h"
24 #include "test/core/event_engine/windows/create_sockpair.h"
25 
26 namespace grpc_event_engine {
27 namespace experimental {
28 
GetSomeIpv4LoopbackAddress()29 sockaddr_in GetSomeIpv4LoopbackAddress() {
30   sockaddr_in addr;
31   memset(&addr, 0, sizeof(addr));
32   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
33   addr.sin_family = AF_INET;
34   return addr;
35 }
36 
CreateSockpair(SOCKET sockpair[2],DWORD flags)37 void CreateSockpair(SOCKET sockpair[2], DWORD flags) {
38   SOCKET svr_sock = INVALID_SOCKET;
39   SOCKET lst_sock = INVALID_SOCKET;
40   SOCKET cli_sock = INVALID_SOCKET;
41   auto addr = GetSomeIpv4LoopbackAddress();
42   int addr_len = sizeof(addr);
43 
44   lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
45   GPR_ASSERT(lst_sock != INVALID_SOCKET);
46 
47   GPR_ASSERT(bind(lst_sock, (sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR);
48   GPR_ASSERT(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR);
49   GPR_ASSERT(getsockname(lst_sock, (sockaddr*)&addr, &addr_len) !=
50              SOCKET_ERROR);
51 
52   cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
53   GPR_ASSERT(cli_sock != INVALID_SOCKET);
54 
55   auto result =
56       WSAConnect(cli_sock, (sockaddr*)&addr, addr_len, NULL, NULL, NULL, NULL);
57   if (result != 0) {
58     gpr_log(GPR_DEBUG, "%s",
59             GRPC_WSA_ERROR(WSAGetLastError(), "Failed in WSAConnect")
60                 .ToString()
61                 .c_str());
62     abort();
63   }
64   svr_sock = accept(lst_sock, (sockaddr*)&addr, &addr_len);
65   GPR_ASSERT(svr_sock != INVALID_SOCKET);
66   closesocket(lst_sock);
67   // TODO(hork): see if we can migrate this to IPv6, or break up the socket prep
68   // stages.
69   // Historical note: This method creates an ipv4 sockpair, which cannot
70   // be made dual stack. This was silently preventing TCP_NODELAY from being
71   // enabled, but not causing an unrecoverable error. So this is left as a
72   // logged status. WSAEINVAL is expected.
73   auto status = PrepareSocket(cli_sock);
74   // if (!status.ok()) {
75   //   gpr_log(GPR_DEBUG, "Error preparing client socket: %s",
76   //           status.ToString().c_str());
77   // }
78   status = PrepareSocket(svr_sock);
79   // if (!status.ok()) {
80   //   gpr_log(GPR_DEBUG, "Error preparing server socket: %s",
81   //           status.ToString().c_str());
82   // }
83 
84   sockpair[0] = svr_sock;
85   sockpair[1] = cli_sock;
86 }
87 
88 }  // namespace experimental
89 }  // namespace grpc_event_engine
90 
91 #endif  // GPR_WINDOWS
92