<URL: http://bugs.freeciv.org/Ticket/Display.html?id=19481 >
Updated patches for S2_1 and trunk attached. To get rid of the various #ifdefs from the previous patches I introduced wrapper functions my_connect() and my_select() and made those my_* functions check the result of the wrapped call and set errno manually in case of an Winsock error.
Index: client/clinet.c =================================================================== --- client/clinet.c (revision 13342) +++ client/clinet.c (working copy) @@ -216,12 +216,12 @@ return -1; } - if (connect(aconnection.sock, &server_addr.sockaddr, + if (my_connect(aconnection.sock, &server_addr.sockaddr, sizeof(server_addr)) == -1) { (void) mystrlcpy(errbuf, mystrerror(), errbufsize); my_closesocket(aconnection.sock); aconnection.sock = -1; -#ifdef WIN32_NATIVE +#ifdef HAVE_WINSOCK return -1; #else return errno; @@ -320,12 +320,12 @@ MY_FD_ZERO(&writefs); FD_SET(socket_fd, &writefs); n = - select(socket_fd + 1, &readfs, &writefs, &exceptfs, - block ? NULL : &tv); + my_select(socket_fd + 1, &readfs, &writefs, &exceptfs, + block ? NULL : &tv); } else { n = - select(socket_fd + 1, &readfs, NULL, &exceptfs, - block ? NULL : &tv); + my_select(socket_fd + 1, &readfs, NULL, &exceptfs, + block ? NULL : &tv); } /* the socket is neither readable, writeable nor got an Index: client/gui-sdl/gui_main.c =================================================================== --- client/gui-sdl/gui_main.c (revision 13342) +++ client/gui-sdl/gui_main.c (working copy) @@ -557,7 +557,7 @@ tv.tv_sec = 0; tv.tv_usec = 10000;/* 10ms*/ - result = select(MAX(net_socket, ggz_socket) + 1, &civfdset, NULL, NULL, &tv); + result = my_select(MAX(net_socket, ggz_socket) + 1, &civfdset, NULL, NULL, &tv); if (result < 0) { if (errno != EINTR) { break; Index: client/gui-win32/gui_main.c =================================================================== --- client/gui-win32/gui_main.c (revision 13342) +++ client/gui-win32/gui_main.c (working copy) @@ -565,7 +565,7 @@ FD_SET(net_input, &civfdset); tv.tv_sec = 0; tv.tv_usec = 0; - if (select(1, &civfdset, NULL, NULL, &tv)) { + if (my_select(1, &civfdset, NULL, NULL, &tv)) { if (FD_ISSET(net_input, &civfdset)) { input_from_server(net_input); processed = TRUE; Index: client/servers.c =================================================================== --- client/servers.c (revision 13342) +++ client/servers.c (working copy) @@ -421,14 +421,8 @@ my_nonblock(s); - if (connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) { - if ( -#ifdef HAVE_WINSOCK - errno == WSAEINPROGRESS -#else - errno == EINPROGRESS -#endif - ) { + if (my_connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) { + if (errno == EINPROGRESS) { /* With non-blocking sockets this is the expected result. */ scan->meta.state = META_CONNECTING; scan->sock = s; @@ -466,7 +460,7 @@ switch (scan->meta.state) { case META_CONNECTING: - if (select(scan->sock + 1, NULL, &sockset, NULL, &tv) < 0) { + if (my_select(scan->sock + 1, NULL, &sockset, NULL, &tv) < 0) { (scan->error_func)(scan, mystrerror()); } else if (FD_ISSET(scan->sock, &sockset)) { meta_send_request(scan); @@ -475,7 +469,7 @@ } return NULL; case META_WAITING: - if (select(scan->sock + 1, &sockset, NULL, NULL, &tv) < 0) { + if (my_select(scan->sock + 1, &sockset, NULL, NULL, &tv) < 0) { (scan->error_func)(scan, mystrerror()); } else if (FD_ISSET(scan->sock, &sockset)) { meta_read_response(scan); @@ -542,8 +536,10 @@ unsigned char buffer[MAX_LEN_PACKET]; struct ip_mreq mreq; const char *group; - unsigned char ttl; size_t size; +#ifndef HAVE_WINSOCK + unsigned char ttl; +#endif /* Create a socket for broadcasting to servers. */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { @@ -563,6 +559,9 @@ addr.sockaddr_in.sin_addr.s_addr = inet_addr(get_multicast_group()); addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT); +/* this setsockopt call fails on Windows 98, so we stick with the default + * value of 1 on Windows, which should be fine in most cases */ +#ifndef HAVE_WINSOCK /* Set the Time-to-Live field for the packet */ ttl = SERVER_LAN_TTL; if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, @@ -570,6 +569,7 @@ freelog(LOG_ERROR, "setsockopt failed: %s", mystrerror()); return FALSE; } +#endif if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt))) { @@ -636,11 +636,7 @@ **************************************************************************/ static struct server_list *get_lan_server_list(struct server_scan *scan) { -#ifdef HAVE_SOCKLEN_T socklen_t fromlen; -# else - int fromlen; -# endif union my_sockaddr fromend; struct hostent *from; char msgbuf[128]; Index: common/connection.c =================================================================== --- common/connection.c (revision 13342) +++ common/connection.c (working copy) @@ -212,7 +212,7 @@ tv.tv_sec = 0; tv.tv_usec = 0; - if (select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { + if (my_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { if (errno != EINTR) { break; } else { Index: configure.ac =================================================================== --- configure.ac (revision 13342) +++ configure.ac (working copy) @@ -366,6 +366,7 @@ AC_DEFINE(ALWAYS_ROOT, 1, [Mingw32-specific setting - root]) AC_DEFINE(WIN32_NATIVE, 1, [Mingw32-specific setting - native]) AC_DEFINE(HAVE_WINSOCK, 1, [Mingw32-specific setting - winsock]) + AC_DEFINE(NONBLOCKING_SOCKETS, 1, [nonblocking sockets support]) LIBS="$LIBS -lwsock32" fi Index: server/meta.c =================================================================== --- server/meta.c (revision 13342) +++ server/meta.c (working copy) @@ -218,7 +218,7 @@ return FALSE; } - if (connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) { + if (my_connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) { freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror()); metaserver_failed(); my_closesocket(sock); Index: server/sernet.c =================================================================== --- server/sernet.c (revision 13342) +++ server/sernet.c (working copy) @@ -323,7 +323,7 @@ return; } - if(select(max_desc+1, NULL, &writefs, &exceptfs, &tv)<=0) { + if(my_select(max_desc+1, NULL, &writefs, &exceptfs, &tv)<=0) { return; } @@ -612,7 +612,7 @@ } con_prompt_off(); /* output doesn't generate a new prompt */ - if (select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv) == 0) { + if (my_select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv) == 0) { /* timeout */ (void) send_server_info_to_metaserver(META_REFRESH); if (game.info.timeout > 0 @@ -804,11 +804,7 @@ { /* This used to have size_t for some platforms. If this is necessary * it should be done with a configure check not a platform check. */ -#ifdef HAVE_SOCKLEN_T socklen_t fromlen; -#else /* HAVE_SOCKLEN_T */ - int fromlen; -#endif /* HAVE_SOCKLEN_T */ int new_sock; union my_sockaddr fromend; @@ -1093,7 +1089,7 @@ tv.tv_sec = 0; tv.tv_usec = 0; - while (select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) { + while (my_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) { if (errno != EINTR) { freelog(LOG_ERROR, "select failed: %s", mystrerror()); return; @@ -1134,7 +1130,9 @@ int socksend, setting = 1; const char *group; size_t size; +#ifndef HAVE_WINSOCK unsigned char ttl; +#endif /* Create a socket to broadcast to client. */ if ((socksend = socket(AF_INET,SOCK_DGRAM, 0)) < 0) { @@ -1149,6 +1147,9 @@ addr.sockaddr_in.sin_addr.s_addr = inet_addr(group); addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1); +/* this setsockopt call fails on Windows 98, so we stick with the default + * value of 1 on Windows, which should be fine in most cases */ +#ifndef HAVE_WINSOCK /* Set the Time-to-Live field for the packet. */ ttl = SERVER_LAN_TTL; if (setsockopt(socksend, IPPROTO_IP, IP_MULTICAST_TTL, @@ -1156,6 +1157,7 @@ freelog(LOG_ERROR, "setsockopt failed: %s", mystrerror()); return; } +#endif if (setsockopt(socksend, SOL_SOCKET, SO_BROADCAST, (const char*)&setting, sizeof(setting))) { Index: utility/ftwl/be_sdl.c =================================================================== --- utility/ftwl/be_sdl.c (revision 13342) +++ utility/ftwl/be_sdl.c (working copy) @@ -192,7 +192,7 @@ zero_timeout.tv_sec = 0; zero_timeout.tv_usec = 0; - ret = select(other_fd + 1, &readfds, NULL, &exceptfds, &zero_timeout); + ret = my_select(other_fd + 1, &readfds, NULL, &exceptfds, &zero_timeout); if (ret > 0 && (FD_ISSET(other_fd, &readfds) || FD_ISSET(other_fd, &exceptfds))) { event->type = BE_DATA_OTHER_FD; Index: utility/ftwl/be_x11_cairo_32.c =================================================================== --- utility/ftwl/be_x11_cairo_32.c (revision 13342) +++ utility/ftwl/be_x11_cairo_32.c (working copy) @@ -251,7 +251,7 @@ } } - ret = select(highest + 1, &readfds, NULL, &exceptfds, timeout); + ret = my_select(highest + 1, &readfds, NULL, &exceptfds, timeout); if (ret == 0) { // timed out event->type = BE_TIMEOUT; Index: utility/ftwl/be_x11_ximage_32.c =================================================================== --- utility/ftwl/be_x11_ximage_32.c (revision 13342) +++ utility/ftwl/be_x11_ximage_32.c (working copy) @@ -262,7 +262,7 @@ } } - ret = select(highest + 1, &readfds, NULL, &exceptfds, timeout); + ret = my_select(highest + 1, &readfds, NULL, &exceptfds, timeout); if (ret == 0) { // timed out event->type = BE_TIMEOUT; Index: utility/netintf.c =================================================================== --- utility/netintf.c (revision 13342) +++ utility/netintf.c (working copy) @@ -60,17 +60,81 @@ #define INADDR_NONE 0xffffffff #endif +#ifdef HAVE_WINSOCK +/*************************************************************** + Set errno variable on Winsock error +***************************************************************/ +static void set_socket_errno(void) +{ + switch(WSAGetLastError()) { + /* these have mappings to symbolic errno names in netintf.h */ + case WSAEINTR: + case WSAEWOULDBLOCK: + case WSAECONNRESET: + errno = WSAGetLastError(); + return; + default: + freelog(LOG_ERROR, "Missing errno mapping for Winsock error #%d. " + "Please report this message at %s.", + WSAGetLastError(), BUG_URL); + } +} +#endif /*************************************************************** + Connect a socket to an address +***************************************************************/ +int my_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int result; + + result = connect(sockfd, serv_addr, addrlen); + +#ifdef HAVE_WINSOCK + if (result == -1) { + set_socket_errno(); + } +#endif + + return result; +} + +/*************************************************************** + Wait for a number of sockets to change status +**************************************************************/ +int my_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + int result; + + result = select(n, readfds, writefds, exceptfds, timeout); + +#ifdef HAVE_WINSOCK + if (result == -1) { + set_socket_errno(); + } +#endif + + return result; +} + +/*************************************************************** Read from a socket. ***************************************************************/ int my_readsocket(int sock, void *buf, size_t size) { + int result; + #ifdef HAVE_WINSOCK - return recv(sock, buf, size, 0); + result = recv(sock, buf, size, 0); + if (result == -1) { + set_socket_errno(); + } #else - return read(sock, buf, size); + result = read(sock, buf, size); #endif + + return result; } /*************************************************************** @@ -78,11 +142,18 @@ ***************************************************************/ int my_writesocket(int sock, const void *buf, size_t size) { + int result; + #ifdef HAVE_WINSOCK - return send(sock, buf, size, 0); + result = send(sock, buf, size, 0); + if (result == -1) { + set_socket_errno(); + } #else - return write(sock, buf, size); + result = write(sock, buf, size); #endif + + return result; } /*************************************************************** @@ -132,6 +203,10 @@ void my_nonblock(int sockfd) { #ifdef NONBLOCKING_SOCKETS +#ifdef HAVE_WINSOCK + unsigned long b = 1; + ioctlsocket(sockfd, FIONBIO, &b); +#else #ifdef HAVE_FCNTL int f_set; @@ -153,6 +228,7 @@ } #endif #endif +#endif #else freelog(LOG_DEBUG, "NONBLOCKING_SOCKETS not available"); #endif Index: utility/netintf.h =================================================================== --- utility/netintf.h (revision 13342) +++ utility/netintf.h (working copy) @@ -37,23 +37,41 @@ #include <unistd.h> #endif #ifdef HAVE_WINSOCK -# include <winsock.h> +#include <winsock.h> #endif #include "ioz.h" #include "shared.h" /* bool type */ +/* map symbolic Winsock error names to symbolic errno names */ +#ifdef HAVE_WINSOCK +#undef EINTR +#undef EINPROGRESS +#undef EWOULDBLOCK +#define EINTR WSAEINTR +#define EINPROGRESS WSAEWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ECONNRESET WSAECONNRESET +#endif + #ifdef FD_ZERO #define MY_FD_ZERO FD_ZERO #else #define MY_FD_ZERO(p) memset((void *)(p), 0, sizeof(*(p))) #endif +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + union my_sockaddr { struct sockaddr sockaddr; struct sockaddr_in sockaddr_in; }; +int my_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int my_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout); int my_readsocket(int sock, void *buf, size_t size); int my_writesocket(int sock, const void *buf, size_t size); void my_closesocket(int sock); Index: utility/support.c =================================================================== --- utility/support.c (revision 13342) +++ utility/support.c (working copy) @@ -211,7 +211,7 @@ tv.tv_usec=usec; /* FIXME: an interrupt can cause an EINTR return here. In that case we * need to have another select call. */ - select(0, NULL, NULL, NULL, &tv); + my_select(0, NULL, NULL, NULL, &tv); #endif #endif #endif
Index: client/clinet.c =================================================================== --- client/clinet.c (revision 13349) +++ client/clinet.c (working copy) @@ -216,12 +216,12 @@ return -1; } - if (connect(aconnection.sock, &server_addr.sockaddr, + if (my_connect(aconnection.sock, &server_addr.sockaddr, sizeof(server_addr)) == -1) { (void) mystrlcpy(errbuf, mystrerror(), errbufsize); my_closesocket(aconnection.sock); aconnection.sock = -1; -#ifdef WIN32_NATIVE +#ifdef HAVE_WINSOCK return -1; #else return errno; @@ -320,12 +320,12 @@ MY_FD_ZERO(&writefs); FD_SET(socket_fd, &writefs); n = - select(socket_fd + 1, &readfs, &writefs, &exceptfs, - block ? NULL : &tv); + my_select(socket_fd + 1, &readfs, &writefs, &exceptfs, + block ? NULL : &tv); } else { n = - select(socket_fd + 1, &readfs, NULL, &exceptfs, - block ? NULL : &tv); + my_select(socket_fd + 1, &readfs, NULL, &exceptfs, + block ? NULL : &tv); } /* the socket is neither readable, writeable nor got an Index: client/gui-sdl/gui_main.c =================================================================== --- client/gui-sdl/gui_main.c (revision 13349) +++ client/gui-sdl/gui_main.c (working copy) @@ -557,7 +557,7 @@ tv.tv_sec = 0; tv.tv_usec = 10000;/* 10ms*/ - result = select(MAX(net_socket, ggz_socket) + 1, &civfdset, NULL, NULL, &tv); + result = my_select(MAX(net_socket, ggz_socket) + 1, &civfdset, NULL, NULL, &tv); if (result < 0) { if (errno != EINTR) { break; Index: client/gui-win32/gui_main.c =================================================================== --- client/gui-win32/gui_main.c (revision 13349) +++ client/gui-win32/gui_main.c (working copy) @@ -565,7 +565,7 @@ FD_SET(net_input, &civfdset); tv.tv_sec = 0; tv.tv_usec = 0; - if (select(1, &civfdset, NULL, NULL, &tv)) { + if (my_select(1, &civfdset, NULL, NULL, &tv)) { if (FD_ISSET(net_input, &civfdset)) { input_from_server(net_input); processed = TRUE; Index: client/servers.c =================================================================== --- client/servers.c (revision 13349) +++ client/servers.c (working copy) @@ -421,14 +421,8 @@ my_nonblock(s); - if (connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) { - if ( -#ifdef HAVE_WINSOCK - errno == WSAEINPROGRESS -#else - errno == EINPROGRESS -#endif - ) { + if (my_connect(s, (struct sockaddr *) &addr.sockaddr, sizeof(addr)) == -1) { + if (errno == EINPROGRESS) { /* With non-blocking sockets this is the expected result. */ scan->meta.state = META_CONNECTING; scan->sock = s; @@ -466,7 +460,7 @@ switch (scan->meta.state) { case META_CONNECTING: - if (select(scan->sock + 1, NULL, &sockset, NULL, &tv) < 0) { + if (my_select(scan->sock + 1, NULL, &sockset, NULL, &tv) < 0) { (scan->error_func)(scan, mystrerror()); } else if (FD_ISSET(scan->sock, &sockset)) { meta_send_request(scan); @@ -475,7 +469,7 @@ } return NULL; case META_WAITING: - if (select(scan->sock + 1, &sockset, NULL, NULL, &tv) < 0) { + if (my_select(scan->sock + 1, &sockset, NULL, NULL, &tv) < 0) { (scan->error_func)(scan, mystrerror()); } else if (FD_ISSET(scan->sock, &sockset)) { meta_read_response(scan); @@ -542,8 +536,10 @@ unsigned char buffer[MAX_LEN_PACKET]; struct ip_mreq mreq; const char *group; - unsigned char ttl; size_t size; +#ifndef HAVE_WINSOCK + unsigned char ttl; +#endif /* Create a socket for broadcasting to servers. */ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { @@ -563,6 +559,9 @@ addr.sockaddr_in.sin_addr.s_addr = inet_addr(get_multicast_group()); addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT); +/* this setsockopt call fails on Windows 98, so we stick with the default + * value of 1 on Windows, which should be fine in most cases */ +#ifndef HAVE_WINSOCK /* Set the Time-to-Live field for the packet */ ttl = SERVER_LAN_TTL; if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, @@ -570,6 +569,7 @@ freelog(LOG_ERROR, "setsockopt failed: %s", mystrerror()); return FALSE; } +#endif if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt))) { @@ -636,11 +636,7 @@ **************************************************************************/ static struct server_list *get_lan_server_list(struct server_scan *scan) { -#ifdef HAVE_SOCKLEN_T socklen_t fromlen; -# else - int fromlen; -# endif union my_sockaddr fromend; struct hostent *from; char msgbuf[128]; Index: common/connection.c =================================================================== --- common/connection.c (revision 13349) +++ common/connection.c (working copy) @@ -212,7 +212,7 @@ tv.tv_sec = 0; tv.tv_usec = 0; - if (select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { + if (my_select(pc->sock+1, NULL, &writefs, &exceptfs, &tv) <= 0) { if (errno != EINTR) { break; } else { Index: configure.ac =================================================================== --- configure.ac (revision 13349) +++ configure.ac (working copy) @@ -354,6 +354,7 @@ AC_DEFINE(ALWAYS_ROOT, 1, [Mingw32-specific setting - root]) AC_DEFINE(WIN32_NATIVE, 1, [Mingw32-specific setting - native]) AC_DEFINE(HAVE_WINSOCK, 1, [Mingw32-specific setting - winsock]) + AC_DEFINE(NONBLOCKING_SOCKETS, 1, [nonblocking sockets support]) LIBS="$LIBS -lwsock32" fi Index: server/meta.c =================================================================== --- server/meta.c (revision 13349) +++ server/meta.c (working copy) @@ -218,7 +218,7 @@ return FALSE; } - if (connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) { + if (my_connect(sock, (struct sockaddr *) &meta_addr, sizeof(meta_addr)) == -1) { freelog(LOG_ERROR, "Metaserver: connect failed: %s", mystrerror()); metaserver_failed(); my_closesocket(sock); Index: server/sernet.c =================================================================== --- server/sernet.c (revision 13349) +++ server/sernet.c (working copy) @@ -323,7 +323,7 @@ return; } - if(select(max_desc+1, NULL, &writefs, &exceptfs, &tv)<=0) { + if(my_select(max_desc+1, NULL, &writefs, &exceptfs, &tv)<=0) { return; } @@ -612,7 +612,7 @@ } con_prompt_off(); /* output doesn't generate a new prompt */ - if (select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv) == 0) { + if (my_select(max_desc + 1, &readfs, &writefs, &exceptfs, &tv) == 0) { /* timeout */ (void) send_server_info_to_metaserver(META_REFRESH); if (game.info.timeout > 0 @@ -804,11 +804,7 @@ { /* This used to have size_t for some platforms. If this is necessary * it should be done with a configure check not a platform check. */ -#ifdef HAVE_SOCKLEN_T socklen_t fromlen; -#else /* HAVE_SOCKLEN_T */ - int fromlen; -#endif /* HAVE_SOCKLEN_T */ int new_sock; union my_sockaddr fromend; @@ -1093,7 +1089,7 @@ tv.tv_sec = 0; tv.tv_usec = 0; - while (select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) { + while (my_select(socklan + 1, &readfs, NULL, &exceptfs, &tv) == -1) { if (errno != EINTR) { freelog(LOG_ERROR, "select failed: %s", mystrerror()); return; @@ -1134,7 +1130,9 @@ int socksend, setting = 1; const char *group; size_t size; +#ifndef HAVE_WINSOCK unsigned char ttl; +#endif /* Create a socket to broadcast to client. */ if ((socksend = socket(AF_INET,SOCK_DGRAM, 0)) < 0) { @@ -1149,6 +1147,9 @@ addr.sockaddr_in.sin_addr.s_addr = inet_addr(group); addr.sockaddr_in.sin_port = htons(SERVER_LAN_PORT + 1); +/* this setsockopt call fails on Windows 98, so we stick with the default + * value of 1 on Windows, which should be fine in most cases */ +#ifndef HAVE_WINSOCK /* Set the Time-to-Live field for the packet. */ ttl = SERVER_LAN_TTL; if (setsockopt(socksend, IPPROTO_IP, IP_MULTICAST_TTL, @@ -1156,6 +1157,7 @@ freelog(LOG_ERROR, "setsockopt failed: %s", mystrerror()); return; } +#endif if (setsockopt(socksend, SOL_SOCKET, SO_BROADCAST, (const char*)&setting, sizeof(setting))) { Index: utility/ftwl/be_sdl.c =================================================================== --- utility/ftwl/be_sdl.c (revision 13349) +++ utility/ftwl/be_sdl.c (working copy) @@ -172,7 +172,7 @@ zero_timeout.tv_sec = 0; zero_timeout.tv_usec = 0; - ret = select(other_fd + 1, &readfds, NULL, &exceptfds, &zero_timeout); + ret = my_select(other_fd + 1, &readfds, NULL, &exceptfds, &zero_timeout); if (ret > 0 && (FD_ISSET(other_fd, &readfds) || FD_ISSET(other_fd, &exceptfds))) { event->type = BE_DATA_OTHER_FD; Index: utility/ftwl/be_x11_ximage.c =================================================================== --- utility/ftwl/be_x11_ximage.c (revision 13349) +++ utility/ftwl/be_x11_ximage.c (working copy) @@ -262,7 +262,7 @@ } } - ret = select(highest + 1, &readfds, NULL, &exceptfds, timeout); + ret = my_select(highest + 1, &readfds, NULL, &exceptfds, timeout); if (ret == 0) { // timed out event->type = BE_TIMEOUT; Index: utility/netintf.c =================================================================== --- utility/netintf.c (revision 13349) +++ utility/netintf.c (working copy) @@ -60,17 +60,81 @@ #define INADDR_NONE 0xffffffff #endif +#ifdef HAVE_WINSOCK +/*************************************************************** + Set errno variable on Winsock error +***************************************************************/ +static void set_socket_errno(void) +{ + switch(WSAGetLastError()) { + /* these have mappings to symbolic errno names in netintf.h */ + case WSAEINTR: + case WSAEWOULDBLOCK: + case WSAECONNRESET: + errno = WSAGetLastError(); + return; + default: + freelog(LOG_ERROR, "Missing errno mapping for Winsock error #%d. " + "Please report this message at %s.", + WSAGetLastError(), BUG_URL); + } +} +#endif /*************************************************************** + Connect a socket to an address +***************************************************************/ +int my_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen) +{ + int result; + + result = connect(sockfd, serv_addr, addrlen); + +#ifdef HAVE_WINSOCK + if (result == -1) { + set_socket_errno(); + } +#endif + + return result; +} + +/*************************************************************** + Wait for a number of sockets to change status +**************************************************************/ +int my_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout) +{ + int result; + + result = select(n, readfds, writefds, exceptfds, timeout); + +#ifdef HAVE_WINSOCK + if (result == -1) { + set_socket_errno(); + } +#endif + + return result; +} + +/*************************************************************** Read from a socket. ***************************************************************/ int my_readsocket(int sock, void *buf, size_t size) { + int result; + #ifdef HAVE_WINSOCK - return recv(sock, buf, size, 0); + result = recv(sock, buf, size, 0); + if (result == -1) { + set_socket_errno(); + } #else - return read(sock, buf, size); + result = read(sock, buf, size); #endif + + return result; } /*************************************************************** @@ -78,11 +142,18 @@ ***************************************************************/ int my_writesocket(int sock, const void *buf, size_t size) { + int result; + #ifdef HAVE_WINSOCK - return send(sock, buf, size, 0); + result = send(sock, buf, size, 0); + if (result == -1) { + set_socket_errno(); + } #else - return write(sock, buf, size); + result = write(sock, buf, size); #endif + + return result; } /*************************************************************** @@ -132,6 +203,10 @@ void my_nonblock(int sockfd) { #ifdef NONBLOCKING_SOCKETS +#ifdef HAVE_WINSOCK + unsigned long b = 1; + ioctlsocket(sockfd, FIONBIO, &b); +#else #ifdef HAVE_FCNTL int f_set; @@ -153,6 +228,7 @@ } #endif #endif +#endif #else freelog(LOG_DEBUG, "NONBLOCKING_SOCKETS not available"); #endif Index: utility/netintf.h =================================================================== --- utility/netintf.h (revision 13349) +++ utility/netintf.h (working copy) @@ -37,23 +37,41 @@ #include <unistd.h> #endif #ifdef HAVE_WINSOCK -# include <winsock.h> +#include <winsock.h> #endif #include "ioz.h" #include "shared.h" /* bool type */ +/* map symbolic Winsock error names to symbolic errno names */ +#ifdef HAVE_WINSOCK +#undef EINTR +#undef EINPROGRESS +#undef EWOULDBLOCK +#define EINTR WSAEINTR +#define EINPROGRESS WSAEWOULDBLOCK +#define EWOULDBLOCK WSAEWOULDBLOCK +#define ECONNRESET WSAECONNRESET +#endif + #ifdef FD_ZERO #define MY_FD_ZERO FD_ZERO #else #define MY_FD_ZERO(p) memset((void *)(p), 0, sizeof(*(p))) #endif +#ifndef HAVE_SOCKLEN_T +typedef int socklen_t; +#endif + union my_sockaddr { struct sockaddr sockaddr; struct sockaddr_in sockaddr_in; }; +int my_connect(int sockfd, const struct sockaddr *serv_addr, socklen_t addrlen); +int my_select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + struct timeval *timeout); int my_readsocket(int sock, void *buf, size_t size); int my_writesocket(int sock, const void *buf, size_t size); void my_closesocket(int sock); Index: utility/support.c =================================================================== --- utility/support.c (revision 13349) +++ utility/support.c (working copy) @@ -211,7 +211,7 @@ tv.tv_usec=usec; /* FIXME: an interrupt can cause an EINTR return here. In that case we * need to have another select call. */ - select(0, NULL, NULL, NULL, &tv); + my_select(0, NULL, NULL, NULL, &tv); #endif #endif #endif
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev