]> git.pond.sub.org Git - empserver/blob - src/lib/w32/w32sockets.c
Use src/lib/w32/w32sockets.c for client
[empserver] / src / lib / w32 / w32sockets.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
4  *                           Ken Stevens, Steve McClure
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  *  ---
21  *
22  *  See files README, COPYING and CREDITS in the root of the source
23  *  tree for related information and legal notices.  It is expected
24  *  that future projects/authors will amend these files as needed.
25  *
26  *  ---
27  *
28  *  w32sockets.c: POSIX socket emulation layer for Windows
29  *
30  *  Known contributors to this file:
31  *     Ron Koenderink, 2007
32  *     Markus Armbruster, 2007-2009
33  */
34
35 /*
36  * POSIX sockets are file descriptors.  Windows sockets are something
37  * else, with a separate set of functions to operate on them.  To
38  * present a more POSIX-like interface to our application code, we
39  * provide a compatibility layer that wraps file descriptors around
40  * sockets.
41  */
42
43 #include <config.h>
44
45 #include <errno.h>
46 #include <fcntl.h>
47 #include <io.h>
48 /*
49  * Need to include winsock2.h before ws2tcpip.h.
50  * Use sys/socket.h to ensure the #undef NS_ALL
51  * is not missed after including winsock2.h.
52  */
53 #include "sys/socket.h"
54 #include <sys/stat.h>
55 #include <ws2tcpip.h>
56 #include "unistd.h"
57
58 #define W32_FD_TO_SOCKET(fd) ((SOCKET)_get_osfhandle((fd)))
59 #define W32_SOCKET_TO_FD(fh) (_open_osfhandle((long)(fh), O_RDWR | O_BINARY))
60
61 SOCKET
62 w32_fd2socket(int fd)
63 {
64     return W32_FD_TO_SOCKET(fd);
65 }
66
67 static int
68 fd_is_socket(int fd, SOCKET *sockp)
69 {
70     SOCKET sock;
71     WSANETWORKEVENTS ev;
72
73     sock = W32_FD_TO_SOCKET(fd);
74     if (sockp)
75         *sockp = sock;
76     return WSAEnumNetworkEvents(sock, NULL, &ev) == 0;
77 }
78
79 void
80 w32_set_winsock_errno(void)
81 {
82   int err = WSAGetLastError();
83   WSASetLastError(0);
84
85   /* Map some WSAE* errors to the runtime library's error codes.  */
86   switch (err)
87     {
88     case WSA_INVALID_HANDLE:
89       errno = EBADF;
90       break;
91     case WSA_NOT_ENOUGH_MEMORY:
92       errno = ENOMEM;
93       break;
94     case WSA_INVALID_PARAMETER:
95       errno = EINVAL;
96       break;
97     case WSAEWOULDBLOCK:
98       errno = EAGAIN;
99       break;
100     case WSAENAMETOOLONG:
101       errno = ENAMETOOLONG;
102       break;
103     case WSAENOTEMPTY:
104       errno = ENOTEMPTY;
105       break;
106     default:
107       errno = (err > 10000 && err < 10025) ? err - 10000 : err;
108       break;
109     }
110 }
111
112 #define SOCKET_FUNCTION(expr) do {              \
113         SOCKET sock = W32_FD_TO_SOCKET(fd);     \
114         int res = (expr);                       \
115         if (res == SOCKET_ERROR) {              \
116             w32_set_winsock_errno();            \
117             return -1;                          \
118         }                                       \
119         return res;                             \
120     } while (0)
121
122 /*
123  * POSIX equivalent for accept().
124  */
125 #undef accept
126 int
127 w32_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
128 {
129     SOCKET sock;
130
131     sock = accept(W32_FD_TO_SOCKET(fd), addr, addrlen);
132     if (sock == INVALID_SOCKET) {
133         w32_set_winsock_errno();
134         return -1;
135     }
136
137     return W32_SOCKET_TO_FD(sock);
138 }
139
140 /*
141  * POSIX equivalent for bind().
142  */
143 #undef bind
144 int
145 w32_bind(int fd, const struct sockaddr *name, socklen_t namelen)
146 {
147     SOCKET_FUNCTION(bind(sock, name, namelen));
148 }
149
150 /*
151  * POSIX compatible connect() replacement
152  */
153 #undef connect
154 int
155 w32_connect(int sockfd, const struct sockaddr *addr, int addrlen)
156 {
157     SOCKET sock = W32_FD_TO_SOCKET(sockfd);
158     int result;
159
160     result = connect(sock, addr, addrlen);
161     if (result == SOCKET_ERROR) {
162         /* FIXME map WSAEWOULDBLOCK to EINPROGRESS */
163         w32_set_winsock_errno();
164         return -1;
165     }
166     return result;
167 }
168
169 /*
170  * POSIX equivalent for listen().
171  */
172 #undef listen
173 int
174 w32_listen(int fd, int backlog)
175 {
176     SOCKET_FUNCTION(listen(sock, backlog));
177 }
178
179 /*
180  * POSIX equivalent for setsockopt().
181  */
182 #undef setsockopt
183 int
184 w32_setsockopt(int fd, int level, int optname,
185                const void *optval, socklen_t optlen)
186 {
187     /*
188      * SO_REUSEADDR requests to permit another bind even when the
189      * port is still in state TIME_WAIT.  Windows' SO_REUSEADDR is
190      * broken: it makes bind() succeed no matter what, even if
191      * there's another server running on the same port.  Luckily,
192      * bind() seems to be broken as well: it seems to succeed while
193      * the port is in state TIME_WAIT by default; thus we get the
194      * behavior we want by not setting SO_REUSEADDR.
195      */
196     if (level == SOL_SOCKET && optname == SO_REUSEADDR)
197         return 0;
198     {
199         SOCKET_FUNCTION(setsockopt(sock, level, optname, optval, optlen));
200     }
201 }
202
203 /*
204  * POSIX equivalent for shutdown().
205  */
206 #undef shutdown
207 int
208 w32_shutdown(int fd, int how)
209 {
210     SOCKET_FUNCTION(shutdown(sock, how));
211 }
212
213 /*
214  * POSIX equivalent for socket().
215  */
216 #undef socket
217 int
218 w32_socket(int domain, int type, int protocol)
219 {
220     SOCKET sock;
221
222     /*
223      * We have to use WSASocket() to create non-overlapped IO sockets.
224      * Overlapped IO sockets cannot be used with read/write.
225      */
226     sock = WSASocket(domain, type, protocol, NULL, 0, 0);
227     if (sock == INVALID_SOCKET) {
228         w32_set_winsock_errno();
229         return -1;
230     }
231     return W32_SOCKET_TO_FD(sock);
232 }
233
234 #ifdef HAVE_GETADDRINFO
235 const char *
236 inet_ntop(int af, const void *src, char *dst, socklen_t len)
237 {
238     struct sockaddr *sa;
239     struct sockaddr_in sin;
240     struct sockaddr_in6 sin6;
241     size_t salen;
242
243     if (af == AF_INET) {
244         memset(&sin, 0, sizeof(sin));
245         sin.sin_family = af;
246         memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
247         sa = (struct sockaddr *)&sin;
248         salen = sizeof(sin);
249     } else if (af == AF_INET6) {
250         memset(&sin6, 0, sizeof(sin6));
251         sin6.sin6_family = af;
252         memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
253         sa = (struct sockaddr *)&sin6;
254         salen = sizeof(sin6);
255     } else {
256         WSASetLastError(WSAEAFNOSUPPORT);
257         w32_set_winsock_errno();
258         return NULL;
259     }
260
261     if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
262         WSASetLastError(WSAEAFNOSUPPORT);
263         w32_set_winsock_errno();
264         return NULL;
265     }
266
267     return dst;
268 }
269 #endif
270
271 /*
272  * POSIX equivalent for fcntl().
273  * Horrible hacks, just good enough support Empire's use of fcntl().
274  * F_GETFL / F_SETFL support making a socket (non-)blocking by getting
275  * flags, adding or removing O_NONBLOCK, and setting the result.
276  */
277 int
278 fcntl(int fd, int cmd, ...)
279 {
280     va_list ap;
281     int value;
282     unsigned long nonblocking;
283     SOCKET sock;
284
285     switch (cmd)
286     {
287     case F_GETFL:
288         return 0;
289     case F_SETFL:
290         sock = W32_FD_TO_SOCKET(fd);
291         va_start(ap, cmd);
292         value = va_arg(ap, int);
293         va_end(ap);
294         nonblocking = (value & O_NONBLOCK) != 0;
295
296         if (ioctlsocket(sock, FIONBIO, &nonblocking) == SOCKET_ERROR) {
297             w32_set_winsock_errno();
298             return -1;
299         }
300         return 0;
301     }
302     errno = EINVAL;
303     return -1;
304 }
305
306 /*
307  * close() replacement that does the right thing for sockets
308  */
309 static int
310 w32_close_maybe_socket(int fd)
311 {
312     SOCKET sock;
313
314     if (fd_is_socket(fd, &sock)) {
315         if (closesocket(sock)) {
316             w32_set_winsock_errno();
317             return -1;
318         }
319         /*
320          * This always fails because the underlying handle is already
321          * gone, but it closes the fd just fine.
322          */
323         _close(fd);
324         return 0;
325     }
326     return _close(fd);
327 }
328
329 /*
330  * read() replacement that does the right thing for sockets
331  */
332 static int
333 w32_read_maybe_socket(int fd, void *buf, unsigned sz)
334 {
335     SOCKET sock;
336     ssize_t res;
337
338     if (fd_is_socket(fd, &sock)) {
339         res = recv(sock, buf, sz, 0);
340         if (res < 0)
341             w32_set_winsock_errno();
342         return res;
343     }
344     return _read(fd, buf, sz);
345 }
346
347 /*
348  * write() replacement that does the right thing for sockets
349  */
350 static int
351 w32_write_maybe_socket(int fd, const void *buf, unsigned sz)
352 {
353     SOCKET sock;
354     ssize_t res;
355
356     if (fd_is_socket(fd, &sock)) {
357         res = send(sock, buf, sz, 0);
358         if (res < 0)
359             w32_set_winsock_errno();
360         return res;
361     }
362     return _write(fd, buf, sz);
363 }
364
365 int
366 w32_socket_init(void)
367 {
368     int rc;
369     WORD wVersionRequested;
370     WSADATA wsaData;
371
372     wVersionRequested = MAKEWORD(2, 0);
373     rc = WSAStartup(wVersionRequested, &wsaData);
374     if (rc != 0)
375         return -1;
376
377     w32_close_function = w32_close_maybe_socket;
378     w32_read_function = w32_read_maybe_socket;
379     w32_write_function = w32_write_maybe_socket;
380     return 0;
381 }