254 lines
6.5 KiB
C++
254 lines
6.5 KiB
C++
/*
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* 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.
|
|
*/
|
|
|
|
#include <folly/portability/Sockets.h>
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <MSWSock.h> // @manual
|
|
|
|
#include <folly/ScopeGuard.h>
|
|
#include <folly/net/NetworkSocket.h>
|
|
#include <folly/net/detail/SocketFileDescriptorMap.h>
|
|
|
|
namespace folly {
|
|
namespace portability {
|
|
namespace sockets {
|
|
|
|
namespace {
|
|
int network_socket_to_fd(NetworkSocket sock) {
|
|
return socket_to_fd(sock.data);
|
|
}
|
|
|
|
NetworkSocket fd_to_network_socket(int fd) {
|
|
return NetworkSocket(fd_to_socket(fd));
|
|
}
|
|
} // namespace
|
|
|
|
bool is_fh_socket(int fh) {
|
|
SOCKET h = fd_to_socket(fh);
|
|
constexpr long kDummyEvents = 0xABCDEF12;
|
|
WSANETWORKEVENTS e;
|
|
e.lNetworkEvents = kDummyEvents;
|
|
WSAEnumNetworkEvents(h, nullptr, &e);
|
|
return e.lNetworkEvents != kDummyEvents;
|
|
}
|
|
|
|
SOCKET fd_to_socket(int fd) {
|
|
return netops::detail::SocketFileDescriptorMap::fdToSocket(fd);
|
|
}
|
|
|
|
int socket_to_fd(SOCKET s) {
|
|
return netops::detail::SocketFileDescriptorMap::socketToFd(s);
|
|
}
|
|
|
|
template <class R, class F, class... Args>
|
|
static R wrapSocketFunction(F f, int s, Args... args) {
|
|
NetworkSocket h = fd_to_network_socket(s);
|
|
return f(h, args...);
|
|
}
|
|
|
|
int accept(int s, struct sockaddr* addr, socklen_t* addrlen) {
|
|
return network_socket_to_fd(
|
|
wrapSocketFunction<NetworkSocket>(netops::accept, s, addr, addrlen));
|
|
}
|
|
|
|
int bind(int s, const struct sockaddr* name, socklen_t namelen) {
|
|
return wrapSocketFunction<int>(netops::bind, s, name, namelen);
|
|
}
|
|
|
|
int connect(int s, const struct sockaddr* name, socklen_t namelen) {
|
|
return wrapSocketFunction<int>(netops::connect, s, name, namelen);
|
|
}
|
|
|
|
int getpeername(int s, struct sockaddr* name, socklen_t* namelen) {
|
|
return wrapSocketFunction<int>(netops::getpeername, s, name, namelen);
|
|
}
|
|
|
|
int getsockname(int s, struct sockaddr* name, socklen_t* namelen) {
|
|
return wrapSocketFunction<int>(netops::getsockname, s, name, namelen);
|
|
}
|
|
|
|
int getsockopt(int s, int level, int optname, char* optval, socklen_t* optlen) {
|
|
return getsockopt(s, level, optname, (void*)optval, optlen);
|
|
}
|
|
|
|
int getsockopt(int s, int level, int optname, void* optval, socklen_t* optlen) {
|
|
return wrapSocketFunction<int>(
|
|
netops::getsockopt, s, level, optname, optval, optlen);
|
|
}
|
|
|
|
int inet_aton(const char* cp, struct in_addr* inp) {
|
|
return netops::inet_aton(cp, inp);
|
|
}
|
|
|
|
const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) {
|
|
return ::inet_ntop(af, (char*)src, dst, size_t(size));
|
|
}
|
|
|
|
int listen(int s, int backlog) {
|
|
return wrapSocketFunction<int>(netops::listen, s, backlog);
|
|
}
|
|
|
|
int poll(struct pollfd fds[], nfds_t nfds, int timeout) {
|
|
// NetOps already has the checks to ensure this is safe.
|
|
netops::PollDescriptor* desc =
|
|
reinterpret_cast<netops::PollDescriptor*>(reinterpret_cast<void*>(fds));
|
|
for (nfds_t i = 0; i < nfds; ++i) {
|
|
desc[i].fd = fd_to_network_socket((int)desc[i].fd.data);
|
|
}
|
|
return netops::poll(desc, nfds, timeout);
|
|
}
|
|
|
|
ssize_t recv(int s, void* buf, size_t len, int flags) {
|
|
return wrapSocketFunction<ssize_t>(netops::recv, s, buf, len, flags);
|
|
}
|
|
|
|
ssize_t recv(int s, char* buf, int len, int flags) {
|
|
return recv(s, (void*)buf, (size_t)len, flags);
|
|
}
|
|
|
|
ssize_t recv(int s, void* buf, int len, int flags) {
|
|
return recv(s, (void*)buf, (size_t)len, flags);
|
|
}
|
|
|
|
ssize_t recvfrom(
|
|
int s,
|
|
void* buf,
|
|
size_t len,
|
|
int flags,
|
|
struct sockaddr* from,
|
|
socklen_t* fromlen) {
|
|
return wrapSocketFunction<ssize_t>(
|
|
netops::recvfrom, s, buf, len, flags, from, fromlen);
|
|
}
|
|
|
|
ssize_t recvfrom(
|
|
int s,
|
|
char* buf,
|
|
int len,
|
|
int flags,
|
|
struct sockaddr* from,
|
|
socklen_t* fromlen) {
|
|
return recvfrom(s, (void*)buf, (size_t)len, flags, from, fromlen);
|
|
}
|
|
|
|
ssize_t recvfrom(
|
|
int s,
|
|
void* buf,
|
|
int len,
|
|
int flags,
|
|
struct sockaddr* from,
|
|
socklen_t* fromlen) {
|
|
return recvfrom(s, (void*)buf, (size_t)len, flags, from, fromlen);
|
|
}
|
|
|
|
ssize_t recvmsg(int s, struct msghdr* message, int flags) {
|
|
return wrapSocketFunction<ssize_t>(netops::recvmsg, s, message, flags);
|
|
}
|
|
|
|
ssize_t send(int s, const void* buf, size_t len, int flags) {
|
|
return wrapSocketFunction<ssize_t>(netops::send, s, buf, len, flags);
|
|
}
|
|
|
|
ssize_t send(int s, const char* buf, int len, int flags) {
|
|
return send(s, (const void*)buf, (size_t)len, flags);
|
|
}
|
|
|
|
ssize_t send(int s, const void* buf, int len, int flags) {
|
|
return send(s, (const void*)buf, (size_t)len, flags);
|
|
}
|
|
|
|
ssize_t sendmsg(int s, const struct msghdr* message, int flags) {
|
|
return wrapSocketFunction<ssize_t>(netops::sendmsg, s, message, flags);
|
|
}
|
|
|
|
ssize_t sendto(
|
|
int s,
|
|
const void* buf,
|
|
size_t len,
|
|
int flags,
|
|
const sockaddr* to,
|
|
socklen_t tolen) {
|
|
return wrapSocketFunction<ssize_t>(
|
|
netops::sendto, s, buf, len, flags, to, tolen);
|
|
}
|
|
|
|
ssize_t sendto(
|
|
int s,
|
|
const char* buf,
|
|
int len,
|
|
int flags,
|
|
const sockaddr* to,
|
|
socklen_t tolen) {
|
|
return sendto(s, (const void*)buf, (size_t)len, flags, to, tolen);
|
|
}
|
|
|
|
ssize_t sendto(
|
|
int s,
|
|
const void* buf,
|
|
int len,
|
|
int flags,
|
|
const sockaddr* to,
|
|
socklen_t tolen) {
|
|
return sendto(s, buf, (size_t)len, flags, to, tolen);
|
|
}
|
|
|
|
int setsockopt(
|
|
int s,
|
|
int level,
|
|
int optname,
|
|
const void* optval,
|
|
socklen_t optlen) {
|
|
return wrapSocketFunction<int>(
|
|
netops::setsockopt, s, level, optname, optval, optlen);
|
|
}
|
|
|
|
int setsockopt(
|
|
int s,
|
|
int level,
|
|
int optname,
|
|
const char* optval,
|
|
socklen_t optlen) {
|
|
return setsockopt(s, level, optname, (const void*)optval, optlen);
|
|
}
|
|
|
|
int shutdown(int s, int how) {
|
|
return wrapSocketFunction<int>(netops::shutdown, s, how);
|
|
}
|
|
|
|
int socket(int af, int type, int protocol) {
|
|
return network_socket_to_fd(netops::socket(af, type, protocol));
|
|
}
|
|
|
|
int socketpair(int domain, int type, int protocol, int sv[2]) {
|
|
NetworkSocket pair[2];
|
|
auto r = netops::socketpair(domain, type, protocol, pair);
|
|
if (r == -1) {
|
|
return r;
|
|
}
|
|
sv[0] = network_socket_to_fd(pair[0]);
|
|
sv[1] = network_socket_to_fd(pair[1]);
|
|
return 0;
|
|
}
|
|
} // namespace sockets
|
|
} // namespace portability
|
|
} // namespace folly
|
|
#endif
|