diff options
author | Brent Cook <busterb@gmail.com> | 2014-11-20 07:32:15 -0600 |
---|---|---|
committer | Brent Cook <bcook@openbsd.org> | 2014-12-03 17:07:17 -0600 |
commit | e83c30c158d8ece1e4b0f459faccfd5e5ae67112 (patch) | |
tree | 663dc024cbc2ce527614f1d38715730bef734fbc /include | |
parent | cccdd689e39b51af02b156229e5236a2a69dcdcb (diff) | |
download | portable-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.h | 13 | ||||
-rw-r--r-- | include/string.h | 16 | ||||
-rw-r--r-- | include/win32netcompat.h | 155 |
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); | |||
14 | int asprintf(char **str, const char *fmt, ...); | 14 | int asprintf(char **str, const char *fmt, ...); |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | #ifdef _WIN32 | ||
18 | #include <errno.h> | ||
19 | #include <string.h> | ||
20 | |||
21 | static inline void | ||
22 | posix_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 | |||
56 | static inline char * | ||
57 | posix_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 | 22 | static int |
17 | #define SHUT_WR SD_SEND | 23 | wsa_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 | |||
84 | static inline int | ||
85 | posix_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 | |||
95 | static inline int | ||
96 | posix_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 | |||
108 | static inline ssize_t | ||
109 | posix_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 | |||
122 | static inline ssize_t | ||
123 | posix_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 | |||
136 | static inline int | ||
137 | posix_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 | |||
148 | static inline int | ||
149 | posix_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 | ||