/*
Copyright (C) 2018 Red Hat, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
/* Small compatibility layer for sockets, mostly to make easier portability
* for Windows but without loosing performances under Unix, the most supported
* system */
#ifndef RED_SYS_SOCKET_H_
#define RED_SYS_SOCKET_H_
#ifndef _WIN32
# include <sys/socket.h>
#define socket_read(sock, buf, len) read(sock, buf, len)
#define socket_write(sock, buf, len) write(sock, buf, len)
#define socket_writev(sock, iov, n) writev(sock, iov, n)
#define socket_close(sock) close(sock)
#else
# include <winsock2.h>
# include <windows.h>
typedef int socklen_t;
// this definition is ABI compatible with WSABUF
struct iovec {
u_long iov_len;
void FAR *iov_base;
};
void socket_win32_set_errno(void);
static inline ssize_t socket_read(int sock, void *buf, size_t count)
{
ssize_t res = recv(sock, buf, count, 0);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
static inline ssize_t socket_write(int sock, const void *buf, size_t count)
{
ssize_t res = send(sock, buf, count, 0);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
static inline ssize_t socket_writev(int sock, const struct iovec *iov, int n_iov)
{
DWORD sent;
int res = WSASend(sock, (LPWSABUF) iov, n_iov, &sent, 0, NULL, NULL);
if (res) {
socket_win32_set_errno();
return -1;
}
return sent;
}
#define socket_close(sock) closesocket(sock)
#define SHUT_RDWR SD_BOTH
static inline int
socket_getsockopt(int sock, int lvl, int type, void *value, socklen_t *len)
{
int res = getsockopt(sock, lvl, type, value, len);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
#undef getsockopt
#define getsockopt socket_getsockopt
static inline int
socket_setsockopt(int sock, int lvl, int type, const void *value, socklen_t len)
{
int res = setsockopt(sock, lvl, type, value, len);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
#undef setsockopt
#define setsockopt socket_setsockopt
static inline int
socket_listen(int sock, int backlog)
{
int res = listen(sock, backlog);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
#undef listen
#define listen socket_listen
static inline int
socket_bind(int sock, const struct sockaddr *addr, int addrlen)
{
int res = bind(sock, addr, addrlen);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
#undef bind
#define bind socket_bind
static inline int
socket_accept(int sock, struct sockaddr *addr, int *addrlen)
{
int res = accept(sock, addr, addrlen);
if (res < 0) {
socket_win32_set_errno();
}
return res;
}
#undef accept
#define accept socket_accept
int socket_newpair(int type, int protocol, int sv[2]);
#define socketpair(family, type, protocol, sv) socket_newpair(type, protocol, sv)
#endif
#endif // RED_SYS_SOCKET_H_