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
30namespace folly {
31namespace portability {
32namespace sockets {
33
34namespace {
35int network_socket_to_fd(NetworkSocket sock) {
36 return socket_to_fd(sock.data);
37}
38
39NetworkSocket fd_to_network_socket(int fd) {
40 return NetworkSocket(fd_to_socket(fd));
41}
42} // namespace
43
44bool 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
53SOCKET fd_to_socket(int fd) {
54 return netops::detail::SocketFileDescriptorMap::fdToSocket(fd);
55}
56
57int socket_to_fd(SOCKET s) {
58 return netops::detail::SocketFileDescriptorMap::socketToFd(s);
59}
60
61template <class R, class F, class... Args>
62static R wrapSocketFunction(F f, int s, Args... args) {
63 NetworkSocket h = fd_to_network_socket(s);
64 return f(h, args...);
65}
66
67int 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
72int bind(int s, const struct sockaddr* name, socklen_t namelen) {
73 return wrapSocketFunction<int>(netops::bind, s, name, namelen);
74}
75
76int connect(int s, const struct sockaddr* name, socklen_t namelen) {
77 return wrapSocketFunction<int>(netops::connect, s, name, namelen);
78}
79
80int getpeername(int s, struct sockaddr* name, socklen_t* namelen) {
81 return wrapSocketFunction<int>(netops::getpeername, s, name, namelen);
82}
83
84int getsockname(int s, struct sockaddr* name, socklen_t* namelen) {
85 return wrapSocketFunction<int>(netops::getsockname, s, name, namelen);
86}
87
88int getsockopt(int s, int level, int optname, char* optval, socklen_t* optlen) {
89 return getsockopt(s, level, optname, (void*)optval, optlen);
90}
91
92int 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
97int inet_aton(const char* cp, struct in_addr* inp) {
98 return netops::inet_aton(cp, inp);
99}
100
101const 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
105int listen(int s, int backlog) {
106 return wrapSocketFunction<int>(netops::listen, s, backlog);
107}
108
109int 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
119ssize_t recv(int s, void* buf, size_t len, int flags) {
120 return wrapSocketFunction<ssize_t>(netops::recv, s, buf, len, flags);
121}
122
123ssize_t recv(int s, char* buf, int len, int flags) {
124 return recv(s, (void*)buf, (size_t)len, flags);
125}
126
127ssize_t recv(int s, void* buf, int len, int flags) {
128 return recv(s, (void*)buf, (size_t)len, flags);
129}
130
131ssize_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
142ssize_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
152ssize_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
162ssize_t recvmsg(int s, struct msghdr* message, int flags) {
163 return wrapSocketFunction<ssize_t>(netops::recvmsg, s, message, flags);
164}
165
166ssize_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
170ssize_t send(int s, const char* buf, int len, int flags) {
171 return send(s, (const void*)buf, (size_t)len, flags);
172}
173
174ssize_t send(int s, const void* buf, int len, int flags) {
175 return send(s, (const void*)buf, (size_t)len, flags);
176}
177
178ssize_t sendmsg(int s, const struct msghdr* message, int flags) {
179 return wrapSocketFunction<ssize_t>(netops::sendmsg, s, message, flags);
180}
181
182ssize_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
193ssize_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
203ssize_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
213int 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
223int 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
232int shutdown(int s, int how) {
233 return wrapSocketFunction<int>(netops::shutdown, s, how);
234}
235
236int socket(int af, int type, int protocol) {
237 return network_socket_to_fd(netops::socket(af, type, protocol));
238}
239
240int 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