This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Win32 inet_pton fallback misc fixes
authorDaniel Dragan <bulk88@hotmail.com>
Thu, 10 Sep 2015 07:36:36 +0000 (03:36 -0400)
committerSteve Hay <steve.m.hay@googlemail.com>
Sat, 17 Oct 2015 21:17:10 +0000 (22:17 +0100)
-VC complains in inet_pton
 "warning C4715: 'inet_pton' : not all control paths return a value"
 this isn't much a problem since Socket.xs doesn't allow anything but
 AF_INET and AF_INET6 on a XSUB level but fix the implementation anyway
 since the previous cargo culted off the internet version has flaws, so
 the Socket.xs version is usable elsewhere if necessery
-remove copying the string to C auto array, unix inet_ptoa requires null
 terminated strings, so does WSAStringToAddress. WSAStringToAddress's docs
 dont mention a maximum length to the input string, so no reason to
 truncate and re-null terminate it
-MSDN's docs for WSAStringToAddress mentions that filling in sin_family
 is required, even though lpAddress is an output arg, not input and a
 duplicate of arg AddressFamily, there is probably some legacy protocol
 driver out in the world that requires this
-static the functions, these fallbacks dont need to be visible in any other
 .o, and with static they might be inlined/further optimized
-provide fallbacks for Visual C 6 (circa 1998) with very old headers that
 were created before RFC 2553 was created

cpan/Socket/Socket.xs

index 5f60afa..52df483 100644 (file)
 #endif
 
 #ifdef WIN32
 #endif
 
 #ifdef WIN32
-int inet_pton(int af, const char *src, void *dst)
+
+/* VC 6 with its original headers doesn't know about sockaddr_storage, VC 2003 does*/
+#ifndef _SS_MAXSIZE
+
+#  define _SS_MAXSIZE 128
+#  define _SS_ALIGNSIZE (sizeof(__int64))
+
+#  define _SS_PAD1SIZE (_SS_ALIGNSIZE - sizeof (short))
+#  define _SS_PAD2SIZE (_SS_MAXSIZE - (sizeof (short) + _SS_PAD1SIZE \
+                                                    + _SS_ALIGNSIZE))
+
+struct sockaddr_storage {
+    short ss_family;
+    char __ss_pad1[_SS_PAD1SIZE];
+    __int64 __ss_align;
+    char __ss_pad2[_SS_PAD2SIZE];
+};
+
+typedef int socklen_t;
+
+#define in6_addr in_addr6
+
+#define INET_ADDRSTRLEN  22
+#define INET6_ADDRSTRLEN 65
+
+#endif
+
+static int inet_pton(int af, const char *src, void *dst)
 {
   struct sockaddr_storage ss;
   int size = sizeof(ss);
 {
   struct sockaddr_storage ss;
   int size = sizeof(ss);
-  char src_copy[INET6_ADDRSTRLEN+1];
+  ss.ss_family = af; /* per MSDN */
 
 
-  ZeroMemory(&ss, sizeof(ss));
-  /* stupid non-const API */
-  strncpy(src_copy, src, INET6_ADDRSTRLEN+1);
-  src_copy[INET6_ADDRSTRLEN] = 0;
-
-  if (WSAStringToAddress(src_copy, af, NULL, (struct sockaddr *)&ss, &size) != 0)
+  if (WSAStringToAddress((char*)src, af, NULL, (struct sockaddr *)&ss, &size) != 0)
     return 0;
 
   switch(af) {
     return 0;
 
   switch(af) {
@@ -73,10 +95,13 @@ int inet_pton(int af, const char *src, void *dst)
     case AF_INET6:
       *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
       return 1;
     case AF_INET6:
       *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr;
       return 1;
+    default:
+      WSASetLastError(WSAEAFNOSUPPORT);
+      return -1;
   }
 }
 
   }
 }
 
-const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
+static const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)
 {
   struct sockaddr_storage ss;
   unsigned long s = size;
 {
   struct sockaddr_storage ss;
   unsigned long s = size;