Hash :
e83c30c1
Author :
Date :
2014-11-20T07:32:15
monkey patch more POSIX-like behavior out of winsock 2 Windows sockets functions look on the outside like they behave similarly to POSIX functions, but there are many subtle and glaring differences, including errors reported via WSAGetLastError, read, write, and close do not work on sockets, setsockopt takes a (char *) rather than (void *), etc. This header implements wrappers that coerce more POSIX-like behavior from these functions, making portable code easier to develop. BENEFITS: One does not necessarily need to sprinkle #ifdefs around code to handle the Windows and non-Windows behavior when porting code. CAVEATS: There may be performance implications with the 'mother-may-I' approach to determining if a descriptor is a socket or a file. The errno mappings are not 100% what one might expect compared to POSIX since there were not always good 1:1 equivalents from the WSA errors.
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 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
/*
* Public domain
*
* BSD socket emulation code for Winsock2
* Brent Cook <bcook@openbsd.org>
*/
#ifndef LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H
#define LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H
#ifdef _WIN32
#include <ws2tcpip.h>
#define SHUT_RDWR SD_BOTH
#define SHUT_RD SD_RECEIVE
#define SHUT_WR SD_SEND
#include <errno.h>
#include <unistd.h>
static int
wsa_errno(int err)
{
switch (err) {
case WSAENOBUFS:
errno = ENOMEM;
break;
case WSAEACCES:
errno = EACCES;
break;
case WSANOTINITIALISED:
errno = EPERM;
break;
case WSAEHOSTUNREACH:
case WSAENETDOWN:
errno = EIO;
break;
case WSAEFAULT:
errno = EFAULT;
break;
case WSAEINTR:
errno = EINTR;
break;
case WSAEINVAL:
errno = EINVAL;
break;
case WSAEINPROGRESS:
errno = EINPROGRESS;
break;
case WSAEWOULDBLOCK:
errno = EAGAIN;
break;
case WSAEOPNOTSUPP:
errno = ENOTSUP;
break;
case WSAEMSGSIZE:
errno = EFBIG;
break;
case WSAENOTSOCK:
errno = ENOTSOCK;
break;
case WSAENOPROTOOPT:
errno = ENOPROTOOPT;
break;
case WSAECONNREFUSED:
errno = ECONNREFUSED;
break;
case WSAEAFNOSUPPORT:
errno = EAFNOSUPPORT;
break;
case WSAENETRESET:
case WSAENOTCONN:
case WSAECONNABORTED:
case WSAECONNRESET:
case WSAESHUTDOWN:
case WSAETIMEDOUT:
errno = EPIPE;
break;
}
return -1;
}
static inline int
posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
{
int rc = connect(sockfd, addr, addrlen);
if (rc == SOCKET_ERROR)
return wsa_errno(WSAGetLastError());
return rc;
}
#define connect(sockfd, addr, addrlen) posix_connect(sockfd, addr, addrlen)
static inline int
posix_close(int fd)
{
if (closesocket(fd) == SOCKET_ERROR) {
int err = WSAGetLastError();
return err == WSAENOTSOCK ?
close(fd) : wsa_errno(err);
}
return 0;
}
#define close(fd) posix_close(fd)
static inline ssize_t
posix_read(int fd, void *buf, size_t count)
{
ssize_t rc = recv(fd, buf, count, 0);
if (rc == SOCKET_ERROR) {
int err = WSAGetLastError();
return err == WSAENOTSOCK ?
read(fd, buf, count) : wsa_errno(err);
}
return rc;
}
#define read(fd, buf, count) posix_read(fd, buf, count)
static inline ssize_t
posix_write(int fd, const void *buf, size_t count)
{
ssize_t rc = send(fd, buf, count, 0);
if (rc == SOCKET_ERROR) {
int err = WSAGetLastError();
return err == WSAENOTSOCK ?
write(fd, buf, count) : wsa_errno(err);
}
return rc;
}
#define write(fd, buf, count) posix_write(fd, buf, count)
static inline int
posix_getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
}
#define getsockopt(sockfd, level, optname, optval, optlen) \
posix_getsockopt(sockfd, level, optname, optval, optlen)
static inline int
posix_setsockopt(int sockfd, int level, int optname,
const void *optval, socklen_t optlen)
{
int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
}
#define setsockopt(sockfd, level, optname, optval, optlen) \
posix_setsockopt(sockfd, level, optname, optval, optlen)
#endif
#endif