]> git.pond.sub.org Git - empserver/blob - src/lib/w32/w32sockets.c
Clean up commented out code left behind by commit eea24fb0
[empserver] / src / lib / w32 / w32sockets.c
1 /*
2  *  Empire - A multi-player, client/server Internet based war game.
3  *  Copyright (C) 1986-2010, 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     BOOL val;
72     int size = sizeof(val);
73
74     sock = W32_FD_TO_SOCKET(fd);
75     if (sockp)
76         *sockp = sock;
77     return getsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&val, &size)
78         == 0;
79 }
80
81 void
82 w32_set_winsock_errno(void)
83 {
84   int err = WSAGetLastError();
85   WSASetLastError(0);
86
87   /* Map some WSAE* errors to the runtime library's error codes.  */
88   switch (err)
89     {
90     case WSA_INVALID_HANDLE:
91       errno = EBADF;
92       break;
93     case WSA_NOT_ENOUGH_MEMORY:
94       errno = ENOMEM;
95       break;
96     case WSA_INVALID_PARAMETER:
97       errno = EINVAL;
98       break;
99     case WSAEWOULDBLOCK:
100       errno = EAGAIN;
101       break;
102     case WSAENAMETOOLONG:
103       errno = ENAMETOOLONG;
104       break;
105     case WSAENOTEMPTY:
106       errno = ENOTEMPTY;
107       break;
108     default:
109       errno = (err > 10000 && err < 10025) ? err - 10000 : err;
110       break;
111     }
112 }
113
114 #define SOCKET_FUNCTION(expr) do {              \
115         SOCKET sock = W32_FD_TO_SOCKET(fd);     \
116         int res = (expr);                       \
117         if (res == SOCKET_ERROR) {              \
118             w32_set_winsock_errno();            \
119             return -1;                          \
120         }                                       \
121         return res;                             \
122     } while (0)
123
124 /*
125  * POSIX equivalent for accept().
126  */
127 #undef accept
128 int
129 w32_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
130 {
131     SOCKET sock;
132
133     sock = accept(W32_FD_TO_SOCKET(fd), addr, addrlen);
134     if (sock == INVALID_SOCKET) {
135         w32_set_winsock_errno();
136         return -1;
137     }
138
139     return W32_SOCKET_TO_FD(sock);
140 }
141
142 /*
143  * POSIX equivalent for bind().
144  */
145 #undef bind
146 int
147 w32_bind(int fd, const struct sockaddr *name, socklen_t namelen)
148 {
149     SOCKET_FUNCTION(bind(sock, name, namelen));
150 }
151
152 /*
153  * POSIX compatible connect() replacement
154  */
155 #undef connect
156 int
157 w32_connect(int sockfd, const struct sockaddr *addr, int addrlen)
158 {
159     SOCKET sock = W32_FD_TO_SOCKET(sockfd);
160     int result;
161
162     result = connect(sock, addr, addrlen);
163     if (result == SOCKET_ERROR) {
164         /* FIXME map WSAEWOULDBLOCK to EINPROGRESS */
165         w32_set_winsock_errno();
166         return -1;
167     }
168     return result;
169 }
170
171 /*
172  * POSIX equivalent for listen().
173  */
174 #undef listen
175 int
176 w32_listen(int fd, int backlog)
177 {
178     SOCKET_FUNCTION(listen(sock, backlog));
179 }
180
181 /*
182  * POSIX equivalent for setsockopt().
183  */
184 #undef setsockopt
185 int
186 w32_setsockopt(int fd, int level, int optname,
187                const void *optval, socklen_t optlen)
188 {
189     /*
190      * SO_REUSEADDR requests to permit another bind even when the
191      * port is still in state TIME_WAIT.  Windows' SO_REUSEADDR is
192      * broken: it makes bind() succeed no matter what, even if
193      * there's another server running on the same port.  Luckily,
194      * bind() seems to be broken as well: it seems to succeed while
195      * the port is in state TIME_WAIT by default; thus we get the
196      * behavior we want by not setting SO_REUSEADDR.
197      */
198     if (level == SOL_SOCKET && optname == SO_REUSEADDR)
199         return 0;
200     {
201         SOCKET_FUNCTION(setsockopt(sock, level, optname, optval, optlen));
202     }
203 }
204
205 /*
206  * POSIX equivalent for shutdown().
207  */
208 #undef shutdown
209 int
210 w32_shutdown(int fd, int how)
211 {
212     SOCKET_FUNCTION(shutdown(sock, how));
213 }
214
215 /*
216  * POSIX equivalent for socket().
217  */
218 #undef socket
219 int
220 w32_socket(int domain, int type, int protocol)
221 {
222     SOCKET sock;
223
224     /*
225      * We have to use WSASocket() to create non-overlapped IO sockets.
226      * Overlapped IO sockets cannot be used with read/write.
227      */
228     sock = WSASocket(domain, type, protocol, NULL, 0, 0);
229     if (sock == INVALID_SOCKET) {
230         w32_set_winsock_errno();
231         return -1;
232     }
233     return W32_SOCKET_TO_FD(sock);
234 }
235
236 #ifdef HAVE_GETADDRINFO
237 const char *
238 inet_ntop(int af, const void *src, char *dst, socklen_t len)
239 {
240     struct sockaddr *sa;
241     struct sockaddr_in sin;
242     struct sockaddr_in6 sin6;
243     size_t salen;
244
245     if (af == AF_INET) {
246         memset(&sin, 0, sizeof(sin));
247         sin.sin_family = af;
248         memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
249         sa = (struct sockaddr *)&sin;
250         salen = sizeof(sin);
251     } else if (af == AF_INET6) {
252         memset(&sin6, 0, sizeof(sin6));
253         sin6.sin6_family = af;
254         memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
255         sa = (struct sockaddr *)&sin6;
256         salen = sizeof(sin6);
257     } else {
258         WSASetLastError(WSAEAFNOSUPPORT);
259         w32_set_winsock_errno();
260         return NULL;
261     }
262
263     if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
264         WSASetLastError(WSAEAFNOSUPPORT);
265         w32_set_winsock_errno();
266         return NULL;
267     }
268
269     return dst;
270 }
271 #endif
272
273 /*
274  * POSIX equivalent for fcntl().
275  * Horrible hacks, just good enough support Empire's use of fcntl().
276  * F_GETFL / F_SETFL support making a socket (non-)blocking by getting
277  * flags, adding or removing O_NONBLOCK, and setting the result.
278  */
279 int
280 fcntl(int fd, int cmd, ...)
281 {
282     va_list ap;
283     int value;
284     unsigned long nonblocking;
285     SOCKET sock;
286
287     switch (cmd)
288     {
289     case F_GETFL:
290         return 0;
291     case F_SETFL:
292         sock = W32_FD_TO_SOCKET(fd);
293         va_start(ap, cmd);
294         value = va_arg(ap, int);
295         va_end(ap);
296         nonblocking = (value & O_NONBLOCK) != 0;
297
298         if (ioctlsocket(sock, FIONBIO, &nonblocking) == SOCKET_ERROR) {
299             w32_set_winsock_errno();
300             return -1;
301         }
302         return 0;
303     }
304     errno = EINVAL;
305     return -1;
306 }
307
308 /*
309  * close() replacement that does the right thing for sockets
310  */
311 static int
312 w32_close_maybe_socket(int fd)
313 {
314     SOCKET sock;
315
316     if (fd_is_socket(fd, &sock)) {
317         if (closesocket(sock)) {
318             w32_set_winsock_errno();
319             return -1;
320         }
321         /*
322          * This always fails because the underlying handle is already
323          * gone, but it closes the fd just fine.
324          */
325         _close(fd);
326         return 0;
327     }
328     return _close(fd);
329 }
330
331 /*
332  * read() replacement that does the right thing for sockets
333  */
334 static int
335 w32_read_maybe_socket(int fd, void *buf, unsigned sz)
336 {
337     SOCKET sock;
338     ssize_t res;
339
340     if (fd_is_socket(fd, &sock)) {
341         res = recv(sock, buf, sz, 0);
342         if (res < 0)
343             w32_set_winsock_errno();
344         return res;
345     }
346     return _read(fd, buf, sz);
347 }
348
349 /*
350  * write() replacement that does the right thing for sockets
351  */
352 static int
353 w32_write_maybe_socket(int fd, const void *buf, unsigned sz)
354 {
355     SOCKET sock;
356     ssize_t res;
357
358     if (fd_is_socket(fd, &sock)) {
359         res = send(sock, buf, sz, 0);
360         if (res < 0)
361             w32_set_winsock_errno();
362         return res;
363     }
364     return _write(fd, buf, sz);
365 }
366
367 int
368 w32_socket_init(void)
369 {
370     int rc;
371     WORD wVersionRequested;
372     WSADATA wsaData;
373
374     wVersionRequested = MAKEWORD(2, 0);
375     rc = WSAStartup(wVersionRequested, &wsaData);
376     if (rc != 0)
377         return -1;
378
379     w32_close_function = w32_close_maybe_socket;
380     w32_read_function = w32_read_maybe_socket;
381     w32_write_function = w32_write_maybe_socket;
382     return 0;
383 }