1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
//
//
// Copyright 2015 gRPC authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//
#ifndef GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
#define GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
#include <grpc/support/port_platform.h>
#include "src/core/lib/iomgr/port.h"
#ifdef GRPC_WINSOCK_SOCKET
#include <winsock2.h>
#include <grpc/support/atm.h>
#include <grpc/support/sync.h>
#include "src/core/lib/iomgr/closure.h"
#include "src/core/lib/iomgr/iomgr_internal.h"
#ifndef WSA_FLAG_NO_HANDLE_INHERIT
#define WSA_FLAG_NO_HANDLE_INHERIT 0x80
#endif
// This holds the data for an outstanding read or write on a socket.
// The mutex to protect the concurrent access to that data is the one
// inside the winsocket wrapper.
typedef struct grpc_winsocket_callback_info {
// This is supposed to be a WSAOVERLAPPED, but in order to get that
// definition, we need to include ws2tcpip.h, which needs to be included
// from the top, otherwise it'll clash with a previous inclusion of
// windows.h that in turns includes winsock.h. If anyone knows a way
// to do it properly, feel free to send a patch.
OVERLAPPED overlapped;
// The callback information for the pending operation. May be empty if the
// caller hasn't registered a callback yet.
grpc_closure* closure;
// A boolean to describe if the IO Completion Port got a notification for
// that operation. This will happen if the operation completed before the
// called had time to register a callback. We could avoid that behavior
// altogether by forcing the caller to always register its callback before
// proceeding queue an operation, but it is frequent for an IO Completion
// Port to trigger quickly. This way we avoid a context switch for calling
// the callback. We also simplify the read / write operations to avoid having
// to hold a mutex for a long amount of time.
int has_pending_iocp;
// The results of the overlapped operation.
DWORD bytes_transferred;
int wsa_error;
} grpc_winsocket_callback_info;
// This is a wrapper to a Windows socket. A socket can have one outstanding
// read, and one outstanding write. Doing an asynchronous accept means waiting
// for a read operation. Doing an asynchronous connect means waiting for a
// write operation. These are completely arbitrary ties between the operation
// and the kind of event, because we can have one overlapped per pending
// operation, whichever its nature is. So we could have more dedicated pending
// operation callbacks for connect and listen. But given the scope of listen
// and accept, we don't need to go to that extent and waste memory. Also, this
// is closer to what happens in posix world.
typedef struct grpc_winsocket {
SOCKET socket;
bool destroy_called;
grpc_winsocket_callback_info write_info;
grpc_winsocket_callback_info read_info;
gpr_mu state_mu;
bool shutdown_called;
// You can't add the same socket twice to the same IO Completion Port.
// This prevents that.
int added_to_iocp;
// A label for iomgr to track outstanding objects
grpc_iomgr_object iomgr_object;
} grpc_winsocket;
// Create a wrapped windows handle. This takes ownership of it, meaning that
// it will be responsible for closing it.
grpc_winsocket* grpc_winsocket_create(SOCKET socket, const char* name);
SOCKET grpc_winsocket_wrapped_socket(grpc_winsocket* socket);
// Initiate an asynchronous shutdown of the socket. Will call off any pending
// operation to cancel them.
void grpc_winsocket_shutdown(grpc_winsocket* socket);
// Destroy a socket. Should only be called if there's no pending operation.
void grpc_winsocket_destroy(grpc_winsocket* socket);
void grpc_socket_notify_on_write(grpc_winsocket* winsocket,
grpc_closure* closure);
void grpc_socket_notify_on_read(grpc_winsocket* winsocket,
grpc_closure* closure);
void grpc_socket_become_ready(grpc_winsocket* winsocket,
grpc_winsocket_callback_info* ci);
// Returns true if this system can create AF_INET6 sockets bound to ::1.
// The value is probed once, and cached for the life of the process.
int grpc_ipv6_loopback_available(void);
void grpc_wsa_socket_flags_init();
DWORD grpc_get_default_wsa_socket_flags();
#endif
#endif // GRPC_SRC_CORE_LIB_IOMGR_SOCKET_WINDOWS_H
|