1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #include <folly/portability/Sockets.h> |
18 | |
19 | #ifdef _MSC_VER |
20 | |
21 | #include <errno.h> |
22 | #include <fcntl.h> |
23 | |
24 | #include <MSWSock.h> // @manual |
25 | |
26 | #include <folly/ScopeGuard.h> |
27 | #include <folly/net/NetworkSocket.h> |
28 | #include <folly/net/detail/SocketFileDescriptorMap.h> |
29 | |
30 | namespace folly { |
31 | namespace portability { |
32 | namespace sockets { |
33 | |
34 | namespace { |
35 | int network_socket_to_fd(NetworkSocket sock) { |
36 | return socket_to_fd(sock.data); |
37 | } |
38 | |
39 | NetworkSocket fd_to_network_socket(int fd) { |
40 | return NetworkSocket(fd_to_socket(fd)); |
41 | } |
42 | } // namespace |
43 | |
44 | bool is_fh_socket(int fh) { |
45 | SOCKET h = fd_to_socket(fh); |
46 | constexpr long kDummyEvents = 0xABCDEF12; |
47 | WSANETWORKEVENTS e; |
48 | e.lNetworkEvents = kDummyEvents; |
49 | WSAEnumNetworkEvents(h, nullptr, &e); |
50 | return e.lNetworkEvents != kDummyEvents; |
51 | } |
52 | |
53 | SOCKET fd_to_socket(int fd) { |
54 | return netops::detail::SocketFileDescriptorMap::fdToSocket(fd); |
55 | } |
56 | |
57 | int socket_to_fd(SOCKET s) { |
58 | return netops::detail::SocketFileDescriptorMap::socketToFd(s); |
59 | } |
60 | |
61 | template <class R, class F, class... Args> |
62 | static R wrapSocketFunction(F f, int s, Args... args) { |
63 | NetworkSocket h = fd_to_network_socket(s); |
64 | return f(h, args...); |
65 | } |
66 | |
67 | int accept(int s, struct sockaddr* addr, socklen_t* addrlen) { |
68 | return network_socket_to_fd( |
69 | wrapSocketFunction<NetworkSocket>(netops::accept, s, addr, addrlen)); |
70 | } |
71 | |
72 | int bind(int s, const struct sockaddr* name, socklen_t namelen) { |
73 | return wrapSocketFunction<int>(netops::bind, s, name, namelen); |
74 | } |
75 | |
76 | int connect(int s, const struct sockaddr* name, socklen_t namelen) { |
77 | return wrapSocketFunction<int>(netops::connect, s, name, namelen); |
78 | } |
79 | |
80 | int getpeername(int s, struct sockaddr* name, socklen_t* namelen) { |
81 | return wrapSocketFunction<int>(netops::getpeername, s, name, namelen); |
82 | } |
83 | |
84 | int getsockname(int s, struct sockaddr* name, socklen_t* namelen) { |
85 | return wrapSocketFunction<int>(netops::getsockname, s, name, namelen); |
86 | } |
87 | |
88 | int getsockopt(int s, int level, int optname, char* optval, socklen_t* optlen) { |
89 | return getsockopt(s, level, optname, (void*)optval, optlen); |
90 | } |
91 | |
92 | int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen) { |
93 | return wrapSocketFunction<int>( |
94 | netops::getsockopt, s, level, optname, optval, optlen); |
95 | } |
96 | |
97 | int inet_aton(const char* cp, struct in_addr* inp) { |
98 | return netops::inet_aton(cp, inp); |
99 | } |
100 | |
101 | const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { |
102 | return ::inet_ntop(af, (char*)src, dst, size_t(size)); |
103 | } |
104 | |
105 | int listen(int s, int backlog) { |
106 | return wrapSocketFunction<int>(netops::listen, s, backlog); |
107 | } |
108 | |
109 | int poll(struct pollfd fds[], nfds_t nfds, int timeout) { |
110 | // NetOps already has the checks to ensure this is safe. |
111 | netops::PollDescriptor* desc = |
112 | reinterpret_cast<netops::PollDescriptor*>(reinterpret_cast<void*>(fds)); |
113 | for (nfds_t i = 0; i < nfds; ++i) { |
114 | desc[i].fd = fd_to_network_socket((int)desc[i].fd.data); |
115 | } |
116 | return netops::poll(desc, nfds, timeout); |
117 | } |
118 | |
119 | ssize_t recv(int s, void* buf, size_t len, int flags) { |
120 | return wrapSocketFunction<ssize_t>(netops::recv, s, buf, len, flags); |
121 | } |
122 | |
123 | ssize_t recv(int s, char* buf, int len, int flags) { |
124 | return recv(s, (void*)buf, (size_t)len, flags); |
125 | } |
126 | |
127 | ssize_t recv(int s, void* buf, int len, int flags) { |
128 | return recv(s, (void*)buf, (size_t)len, flags); |
129 | } |
130 | |
131 | ssize_t recvfrom( |
132 | int s, |
133 | void* buf, |
134 | size_t len, |
135 | int flags, |
136 | struct sockaddr* from, |
137 | socklen_t* fromlen) { |
138 | return wrapSocketFunction<ssize_t>( |
139 | netops::recvfrom, s, buf, len, flags, from, fromlen); |
140 | } |
141 | |
142 | ssize_t recvfrom( |
143 | int s, |
144 | char* buf, |
145 | int len, |
146 | int flags, |
147 | struct sockaddr* from, |
148 | socklen_t* fromlen) { |
149 | return recvfrom(s, (void*)buf, (size_t)len, flags, from, fromlen); |
150 | } |
151 | |
152 | ssize_t recvfrom( |
153 | int s, |
154 | void* buf, |
155 | int len, |
156 | int flags, |
157 | struct sockaddr* from, |
158 | socklen_t* fromlen) { |
159 | return recvfrom(s, (void*)buf, (size_t)len, flags, from, fromlen); |
160 | } |
161 | |
162 | ssize_t recvmsg(int s, struct msghdr* message, int flags) { |
163 | return wrapSocketFunction<ssize_t>(netops::recvmsg, s, message, flags); |
164 | } |
165 | |
166 | ssize_t send(int s, const void* buf, size_t len, int flags) { |
167 | return wrapSocketFunction<ssize_t>(netops::send, s, buf, len, flags); |
168 | } |
169 | |
170 | ssize_t send(int s, const char* buf, int len, int flags) { |
171 | return send(s, (const void*)buf, (size_t)len, flags); |
172 | } |
173 | |
174 | ssize_t send(int s, const void* buf, int len, int flags) { |
175 | return send(s, (const void*)buf, (size_t)len, flags); |
176 | } |
177 | |
178 | ssize_t sendmsg(int s, const struct msghdr* message, int flags) { |
179 | return wrapSocketFunction<ssize_t>(netops::sendmsg, s, message, flags); |
180 | } |
181 | |
182 | ssize_t sendto( |
183 | int s, |
184 | const void* buf, |
185 | size_t len, |
186 | int flags, |
187 | const sockaddr* to, |
188 | socklen_t tolen) { |
189 | return wrapSocketFunction<ssize_t>( |
190 | netops::sendto, s, buf, len, flags, to, tolen); |
191 | } |
192 | |
193 | ssize_t sendto( |
194 | int s, |
195 | const char* buf, |
196 | int len, |
197 | int flags, |
198 | const sockaddr* to, |
199 | socklen_t tolen) { |
200 | return sendto(s, (const void*)buf, (size_t)len, flags, to, tolen); |
201 | } |
202 | |
203 | ssize_t sendto( |
204 | int s, |
205 | const void* buf, |
206 | int len, |
207 | int flags, |
208 | const sockaddr* to, |
209 | socklen_t tolen) { |
210 | return sendto(s, buf, (size_t)len, flags, to, tolen); |
211 | } |
212 | |
213 | int setsockopt( |
214 | int s, |
215 | int level, |
216 | int optname, |
217 | const void* optval, |
218 | socklen_t optlen) { |
219 | return wrapSocketFunction<int>( |
220 | netops::setsockopt, s, level, optname, optval, optlen); |
221 | } |
222 | |
223 | int setsockopt( |
224 | int s, |
225 | int level, |
226 | int optname, |
227 | const char* optval, |
228 | socklen_t optlen) { |
229 | return setsockopt(s, level, optname, (const void*)optval, optlen); |
230 | } |
231 | |
232 | int shutdown(int s, int how) { |
233 | return wrapSocketFunction<int>(netops::shutdown, s, how); |
234 | } |
235 | |
236 | int socket(int af, int type, int protocol) { |
237 | return network_socket_to_fd(netops::socket(af, type, protocol)); |
238 | } |
239 | |
240 | int socketpair(int domain, int type, int protocol, int sv[2]) { |
241 | NetworkSocket pair[2]; |
242 | auto r = netops::socketpair(domain, type, protocol, pair); |
243 | if (r == -1) { |
244 | return r; |
245 | } |
246 | sv[0] = |
247 | _open_osfhandle(static_cast<intptr_t>(pair[0].data), O_RDWR | O_BINARY); |
248 | sv[1] = |
249 | _open_osfhandle(static_cast<intptr_t>(pair[1].data), O_RDWR | O_BINARY); |
250 | return 0; |
251 | } |
252 | } // namespace sockets |
253 | } // namespace portability |
254 | } // namespace folly |
255 | #endif |
256 | |