• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
20 #define GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
21 
22 #include <grpc/support/port_platform.h>
23 
24 #include "src/core/lib/iomgr/port.h"
25 
26 #ifdef GRPC_WINSOCK_SOCKET
27 #include <grpc/support/atm.h>
28 #include <grpc/support/sync.h>
29 #include <winsock2.h>
30 
31 #include "src/core/lib/iomgr/closure.h"
32 #include "src/core/lib/iomgr/iomgr_internal.h"
33 
34 #ifndef WSA_FLAG_NO_HANDLE_INHERIT
35 #define WSA_FLAG_NO_HANDLE_INHERIT 0x80
36 #endif
37 
38 // This holds the data for an outstanding read or write on a socket.
39 // The mutex to protect the concurrent access to that data is the one
40 // inside the winsocket wrapper.
41 typedef struct grpc_winsocket_callback_info {
42   // This is supposed to be a WSAOVERLAPPED, but in order to get that
43   // definition, we need to include ws2tcpip.h, which needs to be included
44   // from the top, otherwise it'll clash with a previous inclusion of
45   // windows.h that in turns includes winsock.h. If anyone knows a way
46   // to do it properly, feel free to send a patch.
47   OVERLAPPED overlapped;
48   // The callback information for the pending operation. May be empty if the
49   // caller hasn't registered a callback yet.
50   grpc_closure* closure;
51   // A boolean to describe if the IO Completion Port got a notification for
52   // that operation. This will happen if the operation completed before the
53   // called had time to register a callback. We could avoid that behavior
54   // altogether by forcing the caller to always register its callback before
55   // proceeding queue an operation, but it is frequent for an IO Completion
56   // Port to trigger quickly. This way we avoid a context switch for calling
57   // the callback. We also simplify the read / write operations to avoid having
58   // to hold a mutex for a long amount of time.
59   int has_pending_iocp;
60   // The results of the overlapped operation.
61   DWORD bytes_transferred;
62   int wsa_error;
63   // Tracks whether the final closure has already been run when the socket is
64   // shut down. This allows closures to be run immediately upon socket shutdown.
65   bool closure_already_executed_at_shutdown = false;
66 } grpc_winsocket_callback_info;
67 
68 // This is a wrapper to a Windows socket. A socket can have one outstanding
69 // read, and one outstanding write. Doing an asynchronous accept means waiting
70 // for a read operation. Doing an asynchronous connect means waiting for a
71 // write operation. These are completely arbitrary ties between the operation
72 // and the kind of event, because we can have one overlapped per pending
73 // operation, whichever its nature is. So we could have more dedicated pending
74 // operation callbacks for connect and listen. But given the scope of listen
75 // and accept, we don't need to go to that extent and waste memory. Also, this
76 // is closer to what happens in posix world.
77 typedef struct grpc_winsocket {
78   SOCKET socket;
79   bool destroy_called;
80 
81   grpc_winsocket_callback_info write_info;
82   grpc_winsocket_callback_info read_info;
83 
84   gpr_mu state_mu;
85   bool shutdown_called;
86   bool shutdown_registered;
87 
88   // You can't add the same socket twice to the same IO Completion Port.
89   // This prevents that.
90   int added_to_iocp;
91 
92   // A label for iomgr to track outstanding objects
93   grpc_iomgr_object iomgr_object;
94 } grpc_winsocket;
95 
96 // Create a wrapped windows handle. This takes ownership of it, meaning that
97 // it will be responsible for closing it.
98 grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name);
99 
100 SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket);
101 
102 // Initiate an asynchronous shutdown of the socket. Will call off any pending
103 // operation to cancel them.
104 void grpc_winsocket_shutdown(grpc_winsocket* socket);
105 
106 // Destroy a socket. Should only be called if there's no pending operation.
107 void grpc_winsocket_destroy(grpc_winsocket* socket);
108 
109 void grpc_socket_notify_on_write(grpc_winsocket* winsocket,
110                                  grpc_closure* closure);
111 
112 void grpc_socket_notify_on_read(grpc_winsocket* winsocket,
113                                 grpc_closure* closure);
114 
115 bool grpc_socket_become_ready(grpc_winsocket* socket,
116                               grpc_winsocket_callback_info* info);
117 
118 // Returns true if this system can create AF_INET6 sockets bound to ::1.
119 // The value is probed once, and cached for the life of the process.
120 int grpc_ipv6_loopback_available(void);
121 
122 void grpc_wsa_socket_flags_init();
123 
124 DWORD grpc_get_default_wsa_socket_flags();
125 
126 // Final cleanup operations on the socket prior to deletion.
127 void grpc_winsocket_finish(grpc_winsocket*);
128 
129 #endif
130 
131 #endif  // GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
132