• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/log/check.h"
21 #include "absl/log/log.h"
22 #include "absl/status/status.h"
23 #include "src/core/lib/event_engine/windows/win_socket.h"
24 #include "src/core/lib/iomgr/error.h"
25 #include "test/core/event_engine/windows/create_sockpair.h"
26 
27 namespace grpc_event_engine {
28 namespace experimental {
29 
GetSomeIpv4LoopbackAddress()30 sockaddr_in GetSomeIpv4LoopbackAddress() {
31   sockaddr_in addr;
32   memset(&addr, 0, sizeof(addr));
33   addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
34   addr.sin_family = AF_INET;
35   return addr;
36 }
37 
CreateSockpair(SOCKET sockpair[2],DWORD flags)38 void CreateSockpair(SOCKET sockpair[2], DWORD flags) {
39   SOCKET svr_sock = INVALID_SOCKET;
40   SOCKET lst_sock = INVALID_SOCKET;
41   SOCKET cli_sock = INVALID_SOCKET;
42   auto addr = GetSomeIpv4LoopbackAddress();
43   int addr_len = sizeof(addr);
44 
45   lst_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
46   CHECK(lst_sock != INVALID_SOCKET);
47 
48   CHECK(bind(lst_sock, (sockaddr*)&addr, sizeof(addr)) != SOCKET_ERROR);
49   CHECK(listen(lst_sock, SOMAXCONN) != SOCKET_ERROR);
50   CHECK(getsockname(lst_sock, (sockaddr*)&addr, &addr_len) != SOCKET_ERROR);
51 
52   cli_sock = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, flags);
53   CHECK(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     VLOG(2)
59         << GRPC_WSA_ERROR(WSAGetLastError(), "Failed in WSAConnect").ToString();
60     abort();
61   }
62   svr_sock = accept(lst_sock, (sockaddr*)&addr, &addr_len);
63   CHECK(svr_sock != INVALID_SOCKET);
64   closesocket(lst_sock);
65   // TODO(hork): see if we can migrate this to IPv6, or break up the socket prep
66   // stages.
67   // Historical note: This method creates an ipv4 sockpair, which cannot
68   // be made dual stack. This was silently preventing TCP_NODELAY from being
69   // enabled, but not causing an unrecoverable error. So this is left as a
70   // logged status. WSAEINVAL is expected.
71   auto status = PrepareSocket(cli_sock);
72   // if (!status.ok()) {
73   //   VLOG(2) << "Error preparing client socket: " << status.ToString();
74   // }
75   status = PrepareSocket(svr_sock);
76   // if (!status.ok()) {
77   //   VLOG(2) << "Error preparing server socket: " << status.ToString();
78   // }
79 
80   sockpair[0] = svr_sock;
81   sockpair[1] = cli_sock;
82 }
83 
84 }  // namespace experimental
85 }  // namespace grpc_event_engine
86 
87 #endif  // GPR_WINDOWS
88