<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

Reply via email to