-Wstrict-prototypes -Wmissing-prototypes -Wnested-externs \
-Wredundant-decls
endif
-ifeq ($(empthread),Windows) # really: W32, regardless of thread package
-# FIXME split src/lib/w32/posixio.c
-LDLIBS := $(LIBS_server)
-endif
$(client): LDLIBS := $(LIBS_client)
$(server): LDLIBS := $(LIBS_server)
*
* ---
*
- * posixio.c: POSIX I/O emulation layer for WIN32
+ * posixio.c: POSIX I/O emulation layer for Windows
*
* Known contributors to this file:
* Ron Koenderink, 2007
#include <config.h>
#include <errno.h>
-#include <fcntl.h>
#include <io.h>
-#include <stdarg.h>
#include <stdlib.h>
-/*
- * Need to include winsock2.h before ws2tcpip.h.
- * Use sys/socket.h to ensure the #undef NS_ALL
- * is not missed after including winsock2.h.
- */
-#include "sys/socket.h"
-#include <sys/stat.h>
-#include <ws2tcpip.h>
-
+#include <string.h>
#include "misc.h"
#include "sys/uio.h"
-#include "unistd.h"
-
-#define W32_FD_TO_SOCKET(fd) ((SOCKET)_get_osfhandle((fd)))
-#define W32_SOCKET_TO_FD(fh) (_open_osfhandle((long)(fh), O_RDWR | O_BINARY))
-
-SOCKET
-posix_fd2socket(int fd)
-{
- return W32_FD_TO_SOCKET(fd);
-}
-
-static int
-fd_is_socket(int fd, SOCKET *sockp)
-{
- SOCKET sock;
- WSANETWORKEVENTS ev;
-
- sock = W32_FD_TO_SOCKET(fd);
- if (sockp)
- *sockp = sock;
- return WSAEnumNetworkEvents(sock, NULL, &ev) == 0;
-}
-
-void
-w32_set_winsock_errno(void)
-{
- int err = WSAGetLastError();
- WSASetLastError(0);
-
- /* Map some WSAE* errors to the runtime library's error codes. */
- switch (err)
- {
- case WSA_INVALID_HANDLE:
- errno = EBADF;
- break;
- case WSA_NOT_ENOUGH_MEMORY:
- errno = ENOMEM;
- break;
- case WSA_INVALID_PARAMETER:
- errno = EINVAL;
- break;
- case WSAEWOULDBLOCK:
- errno = EAGAIN;
- break;
- case WSAENAMETOOLONG:
- errno = ENAMETOOLONG;
- break;
- case WSAENOTEMPTY:
- errno = ENOTEMPTY;
- break;
- default:
- errno = (err > 10000 && err < 10025) ? err - 10000 : err;
- break;
- }
-}
-#define SOCKET_FUNCTION(expr) do { \
- SOCKET sock = W32_FD_TO_SOCKET(fd); \
- int res = (expr); \
- if (res == SOCKET_ERROR) { \
- w32_set_winsock_errno(); \
- return -1; \
- } \
- return res; \
- } while (0)
-
-/*
- * POSIX equivalent for accept().
- */
-#undef accept
-int
-posix_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
-{
- SOCKET sock;
-
- sock = accept(W32_FD_TO_SOCKET(fd), addr, addrlen);
- if (sock == INVALID_SOCKET) {
- w32_set_winsock_errno();
- return -1;
- }
-
- return W32_SOCKET_TO_FD(sock);
-}
-
-/*
- * POSIX equivalent for bind().
- */
-#undef bind
-int
-posix_bind(int fd, const struct sockaddr *name, socklen_t namelen)
-{
- SOCKET_FUNCTION(bind(sock, name, namelen));
-}
-
-/*
- * POSIX equivalent for listen().
- */
-#undef listen
-int
-posix_listen(int fd, int backlog)
-{
- SOCKET_FUNCTION(listen(sock, backlog));
-}
-
-/*
- * POSIX equivalent for setsockopt().
- */
-#undef setsockopt
-int
-posix_setsockopt(int fd, int level, int optname,
- const void *optval, socklen_t optlen)
-{
- /*
- * SO_REUSEADDR requests to permit another bind even when the
- * port is still in state TIME_WAIT. Windows' SO_REUSEADDR is
- * broken: it makes bind() succeed no matter what, even if
- * there's another server running on the same port. Luckily,
- * bind() seems to be broken as well: it seems to succeed while
- * the port is in state TIME_WAIT by default; thus we get the
- * behavior we want by not setting SO_REUSEADDR.
- */
- if (level == SOL_SOCKET && optname == SO_REUSEADDR)
- return 0;
- {
- SOCKET_FUNCTION(setsockopt(sock, level, optname, optval, optlen));
- }
-}
-
-/*
- * POSIX equivalent for shutdown().
- */
-#undef shutdown
-int
-posix_shutdown(int fd, int how)
-{
- SOCKET_FUNCTION(shutdown(sock, how));
-}
-
-/*
- * POSIX equivalent for socket().
- */
-#undef socket
-int
-posix_socket(int domain, int type, int protocol)
-{
- SOCKET sock;
-
- /*
- * We have to use WSASocket() to create non-overlapped IO sockets.
- * Overlapped IO sockets cannot be used with read/write.
- */
- sock = WSASocket(domain, type, protocol, NULL, 0, 0);
- if (sock == INVALID_SOCKET) {
- w32_set_winsock_errno();
- return -1;
- }
- return W32_SOCKET_TO_FD(sock);
-}
-
-#ifdef HAVE_GETADDRINFO
-const char *
-inet_ntop(int af, const void *src, char *dst, socklen_t len)
-{
- struct sockaddr *sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- size_t salen;
-
- if (af == AF_INET) {
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = af;
- memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
- sa = (struct sockaddr *)&sin;
- salen = sizeof(sin);
- } else if (af == AF_INET6) {
- memset(&sin6, 0, sizeof(sin6));
- sin6.sin6_family = af;
- memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
- sa = (struct sockaddr *)&sin6;
- salen = sizeof(sin6);
- } else {
- WSASetLastError(WSAEAFNOSUPPORT);
- w32_set_winsock_errno();
- return NULL;
- }
-
- if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
- WSASetLastError(WSAEAFNOSUPPORT);
- w32_set_winsock_errno();
- return NULL;
- }
-
- return dst;
-}
-#endif
-
-/*
- * POSIX equivalent for close().
- */
-int
-posix_close(int fd)
-{
- SOCKET sock;
-
- if (fd_is_socket(fd, &sock)) {
- if (closesocket(sock)) {
- w32_set_winsock_errno();
- return -1;
- }
- /*
- * This always fails because the underlying handle is already
- * gone, but it closes the fd just fine.
- */
- _close(fd);
- return 0;
- }
- return _close(fd);
-}
-
-/*
- * POSIX equivalent for read().
- */
-ssize_t
-posix_read(int fd, void *buf, size_t sz)
-{
- SOCKET sock;
- ssize_t res;
-
- if (fd_is_socket(fd, &sock)) {
- res = recv(sock, buf, sz, 0);
- if (res < 0)
- w32_set_winsock_errno();
- return res;
- }
- return _read(fd, buf, sz);
-}
+int (*w32_close_function)(int) = _close;
+int (*w32_read_function)(int, void *, unsigned) = _read;
+int (*w32_write_function)(int, const void *, unsigned) = _write;
/*
* POSIX equivalent for readv
return -1;
}
- bytes_read = posix_read(fd, buffer, total_bytes);
+ bytes_read = read(fd, buffer, total_bytes);
if (bytes_read <= 0) {
free(buffer);
return -1;
return bytes_read;
}
-/*
- * POSIX equivalent for write().
- */
-ssize_t
-posix_write(int fd, const void *buf, size_t sz)
-{
- SOCKET sock;
- ssize_t res;
-
- if (fd_is_socket(fd, &sock)) {
- res = send(sock, buf, sz, 0);
- if (res < 0)
- w32_set_winsock_errno();
- return res;
- }
- return _write(fd, buf, sz);
-}
-
/*
* POSIX equivalent for writev
* Modelled after the GNU's libc/sysdeps/posix/writev.c
buffer_location += iov[i].iov_len;
}
- bytes_written = posix_write(fd, buffer, total_bytes);
+ bytes_written = write(fd, buffer, total_bytes);
free(buffer);
return -1;
return bytes_written;
}
-
-/*
- * POSIX equivalent for fcntl().
- * Horrible hacks, just good enough support Empire's use of fcntl().
- * F_GETFL / F_SETFL support making a socket (non-)blocking by getting
- * flags, adding or removing O_NONBLOCK, and setting the result.
- */
-int
-fcntl(int fd, int cmd, ...)
-{
- va_list ap;
- int value;
- unsigned long nonblocking;
- SOCKET sock;
-
- switch (cmd)
- {
- case F_GETFL:
- return 0;
- case F_SETFL:
- sock = W32_FD_TO_SOCKET(fd);
- va_start(ap, cmd);
- value = va_arg(ap, int);
- va_end(ap);
- nonblocking = (value & O_NONBLOCK) != 0;
-
- if (ioctlsocket(sock, FIONBIO, &nonblocking) == SOCKET_ERROR) {
- w32_set_winsock_errno();
- return -1;
- }
- return 0;
- }
- errno = EINVAL;
- return -1;
-}
/* Low-level stuff specific to the emulation */
extern SOCKET posix_fd2socket(int fd);
extern void w32_set_winsock_errno(void);
+extern int w32_socket_init(void);
#endif /* SYS_SOCKET_H */
extern int fcntl(int fd, int cmd, ...);
/* Stuff that actually belongs here */
-#define close(fd) \
- posix_close((fd))
-#define read posix_read
-extern ssize_t posix_read(int, void *, size_t);
-#define write(fd, buffer, count) \
- posix_write((fd), (buffer), (count))
-extern ssize_t posix_write(int, const void *, size_t);
-extern int posix_close(int fd);
+#define close(fd) w32_close_function((fd))
+extern int (*w32_close_function)(int);
#define ftruncate(fd, length) _chsize((fd), (length))
+#define read(fd, buf, sz) w32_read_function((fd), (buf), (sz))
+extern int (*w32_read_function)(int, void *, unsigned);
+#define write(fd, buf, sz) w32_write_function((fd), (buf), (sz))
+extern int (*w32_write_function)(int, const void *, unsigned);
#endif /* UNISTD_H */
--- /dev/null
+/*
+ * Empire - A multi-player, client/server Internet based war game.
+ * Copyright (C) 1986-2009, Dave Pare, Jeff Bailey, Thomas Ruschak,
+ * Ken Stevens, Steve McClure
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * ---
+ *
+ * See files README, COPYING and CREDITS in the root of the source
+ * tree for related information and legal notices. It is expected
+ * that future projects/authors will amend these files as needed.
+ *
+ * ---
+ *
+ * w32sockets.c: POSIX socket emulation layer for Windows
+ *
+ * Known contributors to this file:
+ * Ron Koenderink, 2007
+ * Markus Armbruster, 2007-2009
+ */
+
+/*
+ * POSIX sockets are file descriptors. Windows sockets are something
+ * else, with a separate set of functions to operate on them. To
+ * present a more POSIX-like interface to our application code, we
+ * provide a compatibility layer that wraps file descriptors around
+ * sockets.
+ */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+/*
+ * Need to include winsock2.h before ws2tcpip.h.
+ * Use sys/socket.h to ensure the #undef NS_ALL
+ * is not missed after including winsock2.h.
+ */
+#include "sys/socket.h"
+#include <sys/stat.h>
+#include <ws2tcpip.h>
+#include "unistd.h"
+
+#define W32_FD_TO_SOCKET(fd) ((SOCKET)_get_osfhandle((fd)))
+#define W32_SOCKET_TO_FD(fh) (_open_osfhandle((long)(fh), O_RDWR | O_BINARY))
+
+SOCKET
+posix_fd2socket(int fd)
+{
+ return W32_FD_TO_SOCKET(fd);
+}
+
+static int
+fd_is_socket(int fd, SOCKET *sockp)
+{
+ SOCKET sock;
+ WSANETWORKEVENTS ev;
+
+ sock = W32_FD_TO_SOCKET(fd);
+ if (sockp)
+ *sockp = sock;
+ return WSAEnumNetworkEvents(sock, NULL, &ev) == 0;
+}
+
+void
+w32_set_winsock_errno(void)
+{
+ int err = WSAGetLastError();
+ WSASetLastError(0);
+
+ /* Map some WSAE* errors to the runtime library's error codes. */
+ switch (err)
+ {
+ case WSA_INVALID_HANDLE:
+ errno = EBADF;
+ break;
+ case WSA_NOT_ENOUGH_MEMORY:
+ errno = ENOMEM;
+ break;
+ case WSA_INVALID_PARAMETER:
+ errno = EINVAL;
+ break;
+ case WSAEWOULDBLOCK:
+ errno = EAGAIN;
+ break;
+ case WSAENAMETOOLONG:
+ errno = ENAMETOOLONG;
+ break;
+ case WSAENOTEMPTY:
+ errno = ENOTEMPTY;
+ break;
+ default:
+ errno = (err > 10000 && err < 10025) ? err - 10000 : err;
+ break;
+ }
+}
+
+#define SOCKET_FUNCTION(expr) do { \
+ SOCKET sock = W32_FD_TO_SOCKET(fd); \
+ int res = (expr); \
+ if (res == SOCKET_ERROR) { \
+ w32_set_winsock_errno(); \
+ return -1; \
+ } \
+ return res; \
+ } while (0)
+
+/*
+ * POSIX equivalent for accept().
+ */
+#undef accept
+int
+posix_accept(int fd, struct sockaddr *addr, socklen_t *addrlen)
+{
+ SOCKET sock;
+
+ sock = accept(W32_FD_TO_SOCKET(fd), addr, addrlen);
+ if (sock == INVALID_SOCKET) {
+ w32_set_winsock_errno();
+ return -1;
+ }
+
+ return W32_SOCKET_TO_FD(sock);
+}
+
+/*
+ * POSIX equivalent for bind().
+ */
+#undef bind
+int
+posix_bind(int fd, const struct sockaddr *name, socklen_t namelen)
+{
+ SOCKET_FUNCTION(bind(sock, name, namelen));
+}
+
+/*
+ * POSIX equivalent for listen().
+ */
+#undef listen
+int
+posix_listen(int fd, int backlog)
+{
+ SOCKET_FUNCTION(listen(sock, backlog));
+}
+
+/*
+ * POSIX equivalent for setsockopt().
+ */
+#undef setsockopt
+int
+posix_setsockopt(int fd, int level, int optname,
+ const void *optval, socklen_t optlen)
+{
+ /*
+ * SO_REUSEADDR requests to permit another bind even when the
+ * port is still in state TIME_WAIT. Windows' SO_REUSEADDR is
+ * broken: it makes bind() succeed no matter what, even if
+ * there's another server running on the same port. Luckily,
+ * bind() seems to be broken as well: it seems to succeed while
+ * the port is in state TIME_WAIT by default; thus we get the
+ * behavior we want by not setting SO_REUSEADDR.
+ */
+ if (level == SOL_SOCKET && optname == SO_REUSEADDR)
+ return 0;
+ {
+ SOCKET_FUNCTION(setsockopt(sock, level, optname, optval, optlen));
+ }
+}
+
+/*
+ * POSIX equivalent for shutdown().
+ */
+#undef shutdown
+int
+posix_shutdown(int fd, int how)
+{
+ SOCKET_FUNCTION(shutdown(sock, how));
+}
+
+/*
+ * POSIX equivalent for socket().
+ */
+#undef socket
+int
+posix_socket(int domain, int type, int protocol)
+{
+ SOCKET sock;
+
+ /*
+ * We have to use WSASocket() to create non-overlapped IO sockets.
+ * Overlapped IO sockets cannot be used with read/write.
+ */
+ sock = WSASocket(domain, type, protocol, NULL, 0, 0);
+ if (sock == INVALID_SOCKET) {
+ w32_set_winsock_errno();
+ return -1;
+ }
+ return W32_SOCKET_TO_FD(sock);
+}
+
+#ifdef HAVE_GETADDRINFO
+const char *
+inet_ntop(int af, const void *src, char *dst, socklen_t len)
+{
+ struct sockaddr *sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ size_t salen;
+
+ if (af == AF_INET) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = af;
+ memcpy(&sin.sin_addr, src, sizeof(sin.sin_addr));
+ sa = (struct sockaddr *)&sin;
+ salen = sizeof(sin);
+ } else if (af == AF_INET6) {
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = af;
+ memcpy(&sin6.sin6_addr, src, sizeof(sin6.sin6_addr));
+ sa = (struct sockaddr *)&sin6;
+ salen = sizeof(sin6);
+ } else {
+ WSASetLastError(WSAEAFNOSUPPORT);
+ w32_set_winsock_errno();
+ return NULL;
+ }
+
+ if (getnameinfo(sa, salen, dst, len, NULL, 0, NI_NUMERICHOST)) {
+ WSASetLastError(WSAEAFNOSUPPORT);
+ w32_set_winsock_errno();
+ return NULL;
+ }
+
+ return dst;
+}
+#endif
+
+/*
+ * POSIX equivalent for fcntl().
+ * Horrible hacks, just good enough support Empire's use of fcntl().
+ * F_GETFL / F_SETFL support making a socket (non-)blocking by getting
+ * flags, adding or removing O_NONBLOCK, and setting the result.
+ */
+int
+fcntl(int fd, int cmd, ...)
+{
+ va_list ap;
+ int value;
+ unsigned long nonblocking;
+ SOCKET sock;
+
+ switch (cmd)
+ {
+ case F_GETFL:
+ return 0;
+ case F_SETFL:
+ sock = W32_FD_TO_SOCKET(fd);
+ va_start(ap, cmd);
+ value = va_arg(ap, int);
+ va_end(ap);
+ nonblocking = (value & O_NONBLOCK) != 0;
+
+ if (ioctlsocket(sock, FIONBIO, &nonblocking) == SOCKET_ERROR) {
+ w32_set_winsock_errno();
+ return -1;
+ }
+ return 0;
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+/*
+ * close() replacement that does the right thing for sockets
+ */
+static int
+w32_close_maybe_socket(int fd)
+{
+ SOCKET sock;
+
+ if (fd_is_socket(fd, &sock)) {
+ if (closesocket(sock)) {
+ w32_set_winsock_errno();
+ return -1;
+ }
+ /*
+ * This always fails because the underlying handle is already
+ * gone, but it closes the fd just fine.
+ */
+ _close(fd);
+ return 0;
+ }
+ return _close(fd);
+}
+
+/*
+ * read() replacement that does the right thing for sockets
+ */
+static int
+w32_read_maybe_socket(int fd, void *buf, unsigned sz)
+{
+ SOCKET sock;
+ ssize_t res;
+
+ if (fd_is_socket(fd, &sock)) {
+ res = recv(sock, buf, sz, 0);
+ if (res < 0)
+ w32_set_winsock_errno();
+ return res;
+ }
+ return _read(fd, buf, sz);
+}
+
+/*
+ * write() replacement that does the right thing for sockets
+ */
+static int
+w32_write_maybe_socket(int fd, const void *buf, unsigned sz)
+{
+ SOCKET sock;
+ ssize_t res;
+
+ if (fd_is_socket(fd, &sock)) {
+ res = send(sock, buf, sz, 0);
+ if (res < 0)
+ w32_set_winsock_errno();
+ return res;
+ }
+ return _write(fd, buf, sz);
+}
+
+int
+w32_socket_init(void)
+{
+ int rc;
+ WORD wVersionRequested;
+ WSADATA wsaData;
+
+ wVersionRequested = MAKEWORD(2, 0);
+ rc = WSAStartup(wVersionRequested, &wsaData);
+ if (rc != 0)
+ return -1;
+
+ w32_close_function = w32_close_maybe_socket;
+ w32_read_function = w32_read_maybe_socket;
+ w32_write_function = w32_write_maybe_socket;
+ return 0;
+}
* Steve McClure, 1996, 1998
* Doug Hay, 1998
* Ron Koenderink, 2004-2009
- * Markus Armbruster, 2005-2008
+ * Markus Armbruster, 2005-2009
*/
#include <config.h>
#if defined(_WIN32)
#include <process.h>
#include "service.h"
+#include "sys/socket.h"
#endif
#include "empio.h"
#if defined(_WIN32)
static void loc_NTInit(void);
-static void loc_NTTerm(void);
#endif
/*
finish_server(void)
{
ef_fin_srv();
-#if defined(_WIN32)
- loc_NTTerm();
-#endif
journal_shutdown();
remove(pidfname);
}
loc_NTInit(void)
{
int rc;
- WORD wVersionRequested;
- WSADATA wsaData;
- wVersionRequested = MAKEWORD(2, 0);
- rc = WSAStartup(wVersionRequested, &wsaData);
+ rc = w32_socket_init();
if (rc != 0) {
- logerror("WSAStartup failed. %d", rc);
+ logerror("WSAStartup Failed, error code %d\n", rc);
exit(1);
}
}
-
-static void
-loc_NTTerm(void)
-{
- WSACleanup();
-}
#endif