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