aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBrent Cook <busterb@gmail.com>2014-11-20 07:32:15 -0600
committerBrent Cook <bcook@openbsd.org>2014-12-03 17:07:17 -0600
commite83c30c158d8ece1e4b0f459faccfd5e5ae67112 (patch)
tree663dc024cbc2ce527614f1d38715730bef734fbc /include
parentcccdd689e39b51af02b156229e5236a2a69dcdcb (diff)
downloadportable-e83c30c158d8ece1e4b0f459faccfd5e5ae67112.tar.gz
portable-e83c30c158d8ece1e4b0f459faccfd5e5ae67112.tar.bz2
portable-e83c30c158d8ece1e4b0f459faccfd5e5ae67112.zip
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.
Diffstat (limited to 'include')
-rw-r--r--include/stdio.h13
-rw-r--r--include/string.h16
-rw-r--r--include/win32netcompat.h155
3 files changed, 176 insertions, 8 deletions
diff --git a/include/stdio.h b/include/stdio.h
index 989b7fc..ab17883 100644
--- a/include/stdio.h
+++ b/include/stdio.h
@@ -14,4 +14,17 @@ int vasprintf(char **str, const char *fmt, va_list ap);
14int asprintf(char **str, const char *fmt, ...); 14int asprintf(char **str, const char *fmt, ...);
15#endif 15#endif
16 16
17#ifdef _WIN32
18#include <errno.h>
19#include <string.h>
20
21static inline void
22posix_perror(const char *s)
23{
24 fprintf(stderr, "%s: %s\n", s, strerror(errno));
25}
26
27#define perror(errnum) posix_perror(errnum)
28#endif
29
17#endif 30#endif
diff --git a/include/string.h b/include/string.h
index a3263e7..c558a90 100644
--- a/include/string.h
+++ b/include/string.h
@@ -50,4 +50,20 @@ void * memmem(const void *big, size_t big_len, const void *little,
50 size_t little_len); 50 size_t little_len);
51#endif 51#endif
52 52
53#ifdef _WIN32
54#include <errno.h>
55
56static inline char *
57posix_strerror(int errnum)
58{
59 if (errnum == ECONNREFUSED) {
60 return "Connection refused";
61 }
62 return strerror(errnum);
63}
64
65#define strerror(errnum) posix_strerror(errnum)
66
67#endif
68
53#endif 69#endif
diff --git a/include/win32netcompat.h b/include/win32netcompat.h
index 3c716b0..51384d0 100644
--- a/include/win32netcompat.h
+++ b/include/win32netcompat.h
@@ -1,3 +1,10 @@
1/*
2 * Public domain
3 *
4 * BSD socket emulation code for Winsock2
5 * Brent Cook <bcook@openbsd.org>
6 */
7
1#ifndef LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H 8#ifndef LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H
2#define LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H 9#define LIBCRYPTOCOMPAT_WIN32NETCOMPAT_H
3 10
@@ -5,17 +12,149 @@
5 12
6#include <ws2tcpip.h> 13#include <ws2tcpip.h>
7 14
8#ifndef SHUT_RDWR
9#define SHUT_RDWR SD_BOTH 15#define SHUT_RDWR SD_BOTH
10#endif 16#define SHUT_RD SD_RECEIVE
17#define SHUT_WR SD_SEND
11 18
12#ifndef SHUT_RD 19#include <errno.h>
13#define SHUT_RD SD_RECEIVE 20#include <unistd.h>
14#endif
15 21
16#ifndef SHUT_WR 22static int
17#define SHUT_WR SD_SEND 23wsa_errno(int err)
18#endif 24{
25 switch (err) {
26 case WSAENOBUFS:
27 errno = ENOMEM;
28 break;
29 case WSAEACCES:
30 errno = EACCES;
31 break;
32 case WSANOTINITIALISED:
33 errno = EPERM;
34 break;
35 case WSAEHOSTUNREACH:
36 case WSAENETDOWN:
37 errno = EIO;
38 break;
39 case WSAEFAULT:
40 errno = EFAULT;
41 break;
42 case WSAEINTR:
43 errno = EINTR;
44 break;
45 case WSAEINVAL:
46 errno = EINVAL;
47 break;
48 case WSAEINPROGRESS:
49 errno = EINPROGRESS;
50 break;
51 case WSAEWOULDBLOCK:
52 errno = EAGAIN;
53 break;
54 case WSAEOPNOTSUPP:
55 errno = ENOTSUP;
56 break;
57 case WSAEMSGSIZE:
58 errno = EFBIG;
59 break;
60 case WSAENOTSOCK:
61 errno = ENOTSOCK;
62 break;
63 case WSAENOPROTOOPT:
64 errno = ENOPROTOOPT;
65 break;
66 case WSAECONNREFUSED:
67 errno = ECONNREFUSED;
68 break;
69 case WSAEAFNOSUPPORT:
70 errno = EAFNOSUPPORT;
71 break;
72 case WSAENETRESET:
73 case WSAENOTCONN:
74 case WSAECONNABORTED:
75 case WSAECONNRESET:
76 case WSAESHUTDOWN:
77 case WSAETIMEDOUT:
78 errno = EPIPE;
79 break;
80 }
81 return -1;
82}
83
84static inline int
85posix_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
86{
87 int rc = connect(sockfd, addr, addrlen);
88 if (rc == SOCKET_ERROR)
89 return wsa_errno(WSAGetLastError());
90 return rc;
91}
92
93#define connect(sockfd, addr, addrlen) posix_connect(sockfd, addr, addrlen)
94
95static inline int
96posix_close(int fd)
97{
98 if (closesocket(fd) == SOCKET_ERROR) {
99 int err = WSAGetLastError();
100 return err == WSAENOTSOCK ?
101 close(fd) : wsa_errno(err);
102 }
103 return 0;
104}
105
106#define close(fd) posix_close(fd)
107
108static inline ssize_t
109posix_read(int fd, void *buf, size_t count)
110{
111 ssize_t rc = recv(fd, buf, count, 0);
112 if (rc == SOCKET_ERROR) {
113 int err = WSAGetLastError();
114 return err == WSAENOTSOCK ?
115 read(fd, buf, count) : wsa_errno(err);
116 }
117 return rc;
118}
119
120#define read(fd, buf, count) posix_read(fd, buf, count)
121
122static inline ssize_t
123posix_write(int fd, const void *buf, size_t count)
124{
125 ssize_t rc = send(fd, buf, count, 0);
126 if (rc == SOCKET_ERROR) {
127 int err = WSAGetLastError();
128 return err == WSAENOTSOCK ?
129 write(fd, buf, count) : wsa_errno(err);
130 }
131 return rc;
132}
133
134#define write(fd, buf, count) posix_write(fd, buf, count)
135
136static inline int
137posix_getsockopt(int sockfd, int level, int optname,
138 void *optval, socklen_t *optlen)
139{
140 int rc = getsockopt(sockfd, level, optname, (char *)optval, optlen);
141 return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
142
143}
144
145#define getsockopt(sockfd, level, optname, optval, optlen) \
146 posix_getsockopt(sockfd, level, optname, optval, optlen)
147
148static inline int
149posix_setsockopt(int sockfd, int level, int optname,
150 const void *optval, socklen_t optlen)
151{
152 int rc = setsockopt(sockfd, level, optname, (char *)optval, optlen);
153 return rc == 0 ? 0 : wsa_errno(WSAGetLastError());
154}
155
156#define setsockopt(sockfd, level, optname, optval, optlen) \
157 posix_setsockopt(sockfd, level, optname, optval, optlen)
19 158
20#endif 159#endif
21 160