Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc-cloned / deps / grpc / src / core / lib / iomgr / socket_windows.cc
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18
19 #include <grpc/support/port_platform.h>
20
21 #include "src/core/lib/iomgr/port.h"
22
23 #ifdef GRPC_WINSOCK_SOCKET
24
25 #include <winsock2.h>
26
27 // must be included after winsock2.h
28 #include <mswsock.h>
29
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/log_windows.h>
33 #include <grpc/support/string_util.h>
34
35 #include "src/core/lib/iomgr/iocp_windows.h"
36 #include "src/core/lib/iomgr/iomgr_internal.h"
37 #include "src/core/lib/iomgr/pollset.h"
38 #include "src/core/lib/iomgr/pollset_windows.h"
39 #include "src/core/lib/iomgr/sockaddr_windows.h"
40 #include "src/core/lib/iomgr/socket_windows.h"
41
42 static DWORD s_wsa_socket_flags;
43
44 grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name) {
45   char* final_name;
46   grpc_winsocket* r = (grpc_winsocket*)gpr_malloc(sizeof(grpc_winsocket));
47   memset(r, 0, sizeof(grpc_winsocket));
48   r->socket = socket;
49   gpr_mu_init(&r->state_mu);
50   gpr_asprintf(&final_name, "%s:socket=0x%p", name, r);
51   grpc_iomgr_register_object(&r->iomgr_object, final_name);
52   gpr_free(final_name);
53   grpc_iocp_add_socket(r);
54   return r;
55 }
56
57 SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket) {
58   return socket->socket;
59 }
60
61 /* Schedule a shutdown of the socket operations. Will call the pending
62    operations to abort them. We need to do that this way because of the
63    various callsites of that function, which happens to be in various
64    mutex hold states, and that'd be unsafe to call them directly. */
65 void grpc_winsocket_shutdown(grpc_winsocket* winsocket) {
66   /* Grab the function pointer for DisconnectEx for that specific socket.
67      It may change depending on the interface. */
68   int status;
69   GUID guid = WSAID_DISCONNECTEX;
70   LPFN_DISCONNECTEX DisconnectEx;
71   DWORD ioctl_num_bytes;
72
73   gpr_mu_lock(&winsocket->state_mu);
74   if (winsocket->shutdown_called) {
75     gpr_mu_unlock(&winsocket->state_mu);
76     return;
77   }
78   winsocket->shutdown_called = true;
79   gpr_mu_unlock(&winsocket->state_mu);
80
81   status = WSAIoctl(winsocket->socket, SIO_GET_EXTENSION_FUNCTION_POINTER,
82                     &guid, sizeof(guid), &DisconnectEx, sizeof(DisconnectEx),
83                     &ioctl_num_bytes, NULL, NULL);
84
85   if (status == 0) {
86     DisconnectEx(winsocket->socket, NULL, 0, 0);
87   } else {
88     char* utf8_message = gpr_format_message(WSAGetLastError());
89     gpr_log(GPR_INFO, "Unable to retrieve DisconnectEx pointer : %s",
90             utf8_message);
91     gpr_free(utf8_message);
92   }
93   closesocket(winsocket->socket);
94 }
95
96 static void destroy(grpc_winsocket* winsocket) {
97   grpc_iomgr_unregister_object(&winsocket->iomgr_object);
98   gpr_mu_destroy(&winsocket->state_mu);
99   gpr_free(winsocket);
100 }
101
102 static bool check_destroyable(grpc_winsocket* winsocket) {
103   return winsocket->destroy_called == true &&
104          winsocket->write_info.closure == NULL &&
105          winsocket->read_info.closure == NULL;
106 }
107
108 void grpc_winsocket_destroy(grpc_winsocket* winsocket) {
109   gpr_mu_lock(&winsocket->state_mu);
110   GPR_ASSERT(!winsocket->destroy_called);
111   winsocket->destroy_called = true;
112   bool should_destroy = check_destroyable(winsocket);
113   gpr_mu_unlock(&winsocket->state_mu);
114   if (should_destroy) destroy(winsocket);
115 }
116
117 /* Calling notify_on_read or write means either of two things:
118 -) The IOCP already completed in the background, and we need to call
119 the callback now.
120 -) The IOCP hasn't completed yet, and we're queuing it for later. */
121 static void socket_notify_on_iocp(grpc_winsocket* socket, grpc_closure* closure,
122                                   grpc_winsocket_callback_info* info) {
123   GPR_ASSERT(info->closure == NULL);
124   gpr_mu_lock(&socket->state_mu);
125   if (info->has_pending_iocp) {
126     info->has_pending_iocp = 0;
127     GRPC_CLOSURE_SCHED(closure, GRPC_ERROR_NONE);
128   } else {
129     info->closure = closure;
130   }
131   gpr_mu_unlock(&socket->state_mu);
132 }
133
134 void grpc_socket_notify_on_write(grpc_winsocket* socket,
135                                  grpc_closure* closure) {
136   socket_notify_on_iocp(socket, closure, &socket->write_info);
137 }
138
139 void grpc_socket_notify_on_read(grpc_winsocket* socket, grpc_closure* closure) {
140   socket_notify_on_iocp(socket, closure, &socket->read_info);
141 }
142
143 void grpc_socket_become_ready(grpc_winsocket* socket,
144                               grpc_winsocket_callback_info* info) {
145   GPR_ASSERT(!info->has_pending_iocp);
146   gpr_mu_lock(&socket->state_mu);
147   if (info->closure) {
148     GRPC_CLOSURE_SCHED(info->closure, GRPC_ERROR_NONE);
149     info->closure = NULL;
150   } else {
151     info->has_pending_iocp = 1;
152   }
153   bool should_destroy = check_destroyable(socket);
154   gpr_mu_unlock(&socket->state_mu);
155   if (should_destroy) destroy(socket);
156 }
157
158 static gpr_once g_probe_ipv6_once = GPR_ONCE_INIT;
159 static bool g_ipv6_loopback_available = false;
160
161 static void probe_ipv6_once(void) {
162   SOCKET s = socket(AF_INET6, SOCK_STREAM, 0);
163   g_ipv6_loopback_available = 0;
164   if (s == INVALID_SOCKET) {
165     gpr_log(GPR_INFO, "Disabling AF_INET6 sockets because socket() failed.");
166   } else {
167     grpc_sockaddr_in6 addr;
168     memset(&addr, 0, sizeof(addr));
169     addr.sin6_family = AF_INET6;
170     addr.sin6_addr.s6_addr[15] = 1; /* [::1]:0 */
171     if (bind(s, reinterpret_cast<grpc_sockaddr*>(&addr), sizeof(addr)) == 0) {
172       g_ipv6_loopback_available = 1;
173     } else {
174       gpr_log(GPR_INFO,
175               "Disabling AF_INET6 sockets because ::1 is not available.");
176     }
177     closesocket(s);
178   }
179 }
180
181 int grpc_ipv6_loopback_available(void) {
182   gpr_once_init(&g_probe_ipv6_once, probe_ipv6_once);
183   return g_ipv6_loopback_available;
184 }
185
186 DWORD grpc_get_default_wsa_socket_flags() { return s_wsa_socket_flags; }
187
188 void grpc_wsa_socket_flags_init() {
189   s_wsa_socket_flags = WSA_FLAG_OVERLAPPED;
190   /* WSA_FLAG_NO_HANDLE_INHERIT may be not supported on the older Windows
191      versions, see
192      https://msdn.microsoft.com/en-us/library/windows/desktop/ms742212(v=vs.85).aspx
193      for details. */
194   SOCKET sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
195                           s_wsa_socket_flags | WSA_FLAG_NO_HANDLE_INHERIT);
196   if (sock != INVALID_SOCKET) {
197     /* Windows 7, Windows 2008 R2 with SP1 or later */
198     s_wsa_socket_flags |= WSA_FLAG_NO_HANDLE_INHERIT;
199     closesocket(sock);
200   }
201 }
202
203 #endif /* GRPC_WINSOCK_SOCKET */