Skip Menu |

This queue is for tickets about the Socket CPAN distribution.

Report information
The Basics
Id: 91524
Status: resolved
Priority: 0/
Queue: Socket

People
Owner: Nobody in particular
Requestors: carsten.dehning [...] scai.fraunhofer.de
dolmen [...] cpan.org
GTANEZA [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: 2.018
Fixed in: (no value)



Subject: MS Windows port, missing functionality
Date: Thu, 19 Dec 2013 19:17:51 +0100 (CET)
To: bug-Socket [...] rt.cpan.org
From: Carsten Dehning <carsten.dehning [...] scai.fraunhofer.de>
Dear Paul Evans, I am currently extending a multi platform software package (Unix/Linux/Windows, C/C++ and Perl) from IPv4 to IPv6 (dual stack mode). The C-world is fine since I can easily handle the differences between the Unix and Windows world. However there are some issues with the Socket module on the Perl side. As expected, with MS Windows some POSIX calls are missing in the MS winsock libraries or have at least different names, e.g.: inet_ntop() == InetNtopA() http://msdn.microsoft.com/de-de/library/windows/desktop/cc805843(v=vs.85).aspx inet_pton() == InetPtonA() http://msdn.microsoft.com/de-de/library/windows/desktop/cc805844(v=vs.85).aspx Furthermore these functions became first available under Vista. My workaround for XP (still some customers :-(() is the use of WSAStringToAddress() http://msdn.microsoft.com/de-de/library/windows/desktop/ms742214(v=vs.85).aspx WSAAddressToString() http://msdn.microsoft.com/de-de/library/windows/desktop/ms741516(v=vs.85).aspx Both are available since Window 2000. In the Perl Socket module the XS functions inet_ntop() and inet_pton() are not implemented for Windows since the Makefile.PL sub check_for() cannot find them - which is correct and not a bug. I should mention that I use Active State Perl, version 5.18, which is build with MINGW. Would it be possible for you to implement these functions also for Windows? My way in the C-world is e.g (USOCKADDR is a union to wrap IPv6 & IPv4). #ifdef _WIN32 DWORD len = countof(str); WSAAddressToStringA(&(usockaddr.saddr),sizeof(USOCKADDR),NULL,str,&len); #else inet_ntop(usockaddr.af,&usockaddr,str,sizeof(str)); #endif I believe a similar #ifdef would be possible in the Socket.xs #ifdef _WIN32 // addr must have the proper AF assigned DWORD len = countof(str); WSAAddressToStringA(&addr,sizeof(addr),NULL,str,&len); #else inet_ntop(af, &addr, str, sizeof str); #endif The major work then seems to be the modification of the checks in Makefile.PL to account for the Windows specialities. On the other hand it would be a major advantage for all Perl users to have platform independent POSIX calls also working under Windows. Another option would be to add the WSA calls to the Socket.pm (only implemented with the Windows version) and then I can easily switch between POSIX and the WSA calls inside the Perl code. Right now I cannot implement IPv6 perl under Windows since both, POSIX and WSA, are missing. With best regards Carsten Dehning
On Thu Dec 19 13:18:06 2013, carsten.dehning@scai.fraunhofer.de wrote: Show quoted text
> I believe a similar #ifdef would be possible in the Socket.xs > > #ifdef _WIN32 > // addr must have the proper AF assigned > DWORD len = countof(str); > WSAAddressToStringA(&addr,sizeof(addr),NULL,str,&len); > #else > inet_ntop(af, &addr, str, sizeof str); > #endif
Well, not having a Windows box I've no way to test it, even to know if this actually compiles, but find attached an attempt at a patch to hopefully implement it. At the very least, I know it still compiles around it on Linux. Let me know if that solves the problem, and if so I'll call it 2.013_001 and see what the smokers think. -- Paul Evans
Subject: rt91524-a1.patch
=== modified file 'Socket.xs' --- Socket.xs 2013-12-19 03:39:23 +0000 +++ Socket.xs 2013-12-30 04:14:34 +0000 @@ -51,6 +51,14 @@ # include <ws2tcpip.h> #endif +#ifdef _WIN32 +/* MSWin32 provides WSAAddressToStringA() and WSAStringToAddressA(), which do + * similar things to inet_ntop and inet_pton that we can use those + */ +# define HAS_INETNTOP +# define HAS_INETPTON +#endif + #ifdef NETWARE NETDB_DEFINE_CONTEXT NETINET_DEFINE_CONTEXT @@ -956,7 +964,32 @@ #endif "Socket::inet_ntop", af); } - +#ifdef _WIN32 + switch(af) { + case AF_INET: { + DWORD slen = sizeof str; + struct sockaddr_in sockaddr; + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + Copy(ip_address, &sockaddr.sin_addr, addrlen, char); + + WSAAddressToStringA(&sockaddr, sizeof sockaddr, NULL, &str, &slen); + } break; +#ifdef AF_INET6 + case AF_INET6: { + DWORD slen = sizeof str; + struct sockaddr_in6 sockaddr; + + sockaddr.sin6_family = AF_INET6; + sockaddr.sin6_port = 0; + Copy(ip_address, &sockaddr.sin6_addr, addrlen, char); + + WSAAddressToStringA(&sockaddr, sizeof sockaddr, NULL, &str, &slen); + } break; +#endif + } +#else if(addrlen < sizeof(addr)) { Copy(ip_address, &addr, addrlen, char); Zero(((char*)&addr) + addrlen, sizeof(addr) - addrlen, char); @@ -964,7 +997,9 @@ else { Copy(ip_address, &addr, sizeof addr, char); } + inet_ntop(af, &addr, str, sizeof str); +#endif ST(0) = sv_2mortal(newSVpvn(str, strlen(str))); #else @@ -1003,7 +1038,32 @@ #endif "Socket::inet_pton", af); } +#ifdef _WIN32 + switch(af) { + case AF_INET: { + struct sockaddr_in sockaddr; + DWORD alen = sizeof sockaddr; + + ok = !WSAStringToAddressA(host, af, NULL, &sockaddr, &alen); + if (ok) { + Copy(&sockaddr.sin_addr, &ip_address, alen, char); + } + } break; +#ifdef AF_INET6 + case AF_INET6: { + struct sockaddr_in6 sockaddr; + DWORD alen = sizeof sockaddr; + + ok = !WSAStringToAddressA(host, af, NULL, &sockaddr, &alen); + if (ok) { + Copy(&sockaddr.sin6_addr, &ip_address, alen, char); + } + } break; +#endif + } +#else ok = (*host != '\0') && inet_pton(af, host, &ip_address); +#endif ST(0) = sv_newmortal(); if (ok) {
Subject: Re: [rt.cpan.org #91524] MS Windows port, missing functionality
Date: Mon, 30 Dec 2013 17:20:47 +0100 (CET)
To: bug-Socket [...] rt.cpan.org
From: Carsten Dehning <carsten.dehning [...] scai.fraunhofer.de>
Dear Paul, thank you so much for your immediate response. I appreciate your support. Thank you for the smart idea to #define within the .xs module. Since my MINGW patch.exe crashes (I don't care :-) ), please find attached the complete Socket.xs module. I did some minor additional changes to avoid MINGW-gcc complaints and to avoid the return of a hostname filled with stack-junk. Remove the croak() calls (I just used them for testing with junk arguments). I think you know exactly what to do. It's working nice :-) ...on my Win7 laptop. I'll be back in the institute next week and then I'll do the other platforms (XP/Vista/HP-UX/SGI-IRIX/AIX4+5/Linux Intel/Itanium etc....) During the last week I found some time to find out the reasons why inet_xxx() is missing under Windows. I removed my Active State Perl and installed Strawberry Perl ... same issue :-(. By the way, Active state is far more complete compared to Strawberry Perl. Both, Active State and Strawberry are based on MINGW, and in fact the incomplete MINGW header <ws2tcpip.h> causes the trouble. I saw this quite old MINGW ticket (summer 2012) ... http://sourceforge.net/p/mingw/bugs/1641/ and got an association and may cite Larry Wall: "The three principal virtues of a programmer are Laziness, ....." Nevertheless, the implementation via the WSA stuff is the best solution, since it will also work under XP (test that next week). I wish you a happy new year Carsten
=== modified file 'Socket.xs' --- Socket.xs 2013-12-19 03:39:23 +0000 +++ Socket.xs 2013-12-30 04:14:34 +0000 @@ -51,6 +51,14 @@ # include <ws2tcpip.h> #endif +#ifdef _WIN32 +/* MSWin32 provides WSAAddressToStringA() and WSAStringToAddressA(), which do + * similar things to inet_ntop and inet_pton that we can use those + */ +# define HAS_INETNTOP +# define HAS_INETPTON +#endif + #ifdef NETWARE NETDB_DEFINE_CONTEXT NETINET_DEFINE_CONTEXT @@ -956,7 +964,32 @@ #endif "Socket::inet_ntop", af); } - +#ifdef _WIN32 + switch(af) { + case AF_INET: { + DWORD slen = sizeof str; + struct sockaddr_in sockaddr; + + sockaddr.sin_family = AF_INET; + sockaddr.sin_port = 0; + Copy(ip_address, &sockaddr.sin_addr, addrlen, char); + + WSAAddressToStringA(&sockaddr, sizeof sockaddr, NULL, &str, &slen); + } break; +#ifdef AF_INET6 + case AF_INET6: { + DWORD slen = sizeof str; + struct sockaddr_in6 sockaddr; + + sockaddr.sin6_family = AF_INET6; + sockaddr.sin6_port = 0; + Copy(ip_address, &sockaddr.sin6_addr, addrlen, char); + + WSAAddressToStringA(&sockaddr, sizeof sockaddr, NULL, &str, &slen); + } break; +#endif + } +#else if(addrlen < sizeof(addr)) { Copy(ip_address, &addr, addrlen, char); Zero(((char*)&addr) + addrlen, sizeof(addr) - addrlen, char); @@ -964,7 +997,9 @@ else { Copy(ip_address, &addr, sizeof addr, char); } + inet_ntop(af, &addr, str, sizeof str); +#endif ST(0) = sv_2mortal(newSVpvn(str, strlen(str))); #else @@ -1003,7 +1038,32 @@ #endif "Socket::inet_pton", af); } +#ifdef _WIN32 + switch(af) { + case AF_INET: { + struct sockaddr_in sockaddr; + DWORD alen = sizeof sockaddr; + + ok = !WSAStringToAddressA(host, af, NULL, &sockaddr, &alen); + if (ok) { + Copy(&sockaddr.sin_addr, &ip_address, alen, char); + } + } break; +#ifdef AF_INET6 + case AF_INET6: { + struct sockaddr_in6 sockaddr; + DWORD alen = sizeof sockaddr; + + ok = !WSAStringToAddressA(host, af, NULL, &sockaddr, &alen); + if (ok) { + Copy(&sockaddr.sin6_addr, &ip_address, alen, char); + } + } break; +#endif + } +#else ok = (*host != '\0') && inet_pton(af, host, &ip_address); +#endif ST(0) = sv_newmortal(); if (ok) {

Message body is not shown because sender requested not to inline it.

On Sun Dec 29 23:20:13 2013, PEVANS wrote: Show quoted text
> > Let me know if that solves the problem, and if so I'll call it > 2.013_001 and see what the smokers think.
I just tried the patch myself. It required defining HAS_GETADDRINFO, which seems to be undefined on Windows for historical reasons (it is only supported on Windows 2000 and later, but Perl is only supported on 2000+ anymore anyways, so that reason is no longer valid). But I also had to set the scope id to 0: sockaddr.sin6_scope_id = 0; before calling WSAAddressToStringA() with an IPv6 address. Let me know if you need a patch; the required change should be obvious in hindsight. Cheers, -Jan PS: Is there a reason the source is not on Github or some other public repo?
Subject: Re: [rt.cpan.org #91524] MS Windows port, missing functionality
Date: Tue, 1 Apr 2014 14:04:45 +0200 (CEST)
To: bug-Socket [...] rt.cpan.org
From: Carsten Dehning <carsten.dehning [...] scai.fraunhofer.de>
Dear Jan, in my last email you'll find attached a complete Socket.xs module (not just the patch), with some minor additional fixes to avoid gcc and Visual C compiler complaints. This works nice. The reason for my request is to have a Perl code without separating Unix and Windows 2000, XP, Vista, 7 .... and without doing some extra checks and find out whether inet_ntop or inet_pton are available or not. IPv6 came up first under XP (which might disappear soon), therefore a Sockets-module without inet_ntop etc. (the current situation) is OK for Windows 2000 and less. For me personally Windows XP would be the oldest platform. With best regards Carsten Dehning
Please also see comments that I just added on #84600: https://rt.cpan.org/Ticket/Display.html?id=84600#txn-1437445
Subject: IO-Socket-IP module does not compile correctly/ fails tests on Windows
I have been trying to get the IO-Socket-IP module compile correctly on the Windows platform. We need to add support for IPV6 for Perl 5.14.4. IO-Socket-IP module compiles and passes IPV6 tests on Linux x64 without any issues. Please see attached screenshots. I tried different Windows OS. Windows Server 2008 R2, Windows 7, Windows 8 with both Visual Studio 8 and Visual Studio 10. Enabled inet_ntop and inet_pton in config.VC64 config but i still get 'Vendor has not defined Socket macro' error when running IO-Socket-IP module tests. When compiling the updated Socket module; i see inet_ntop and inet_pton undefined (see attached screenshot) I see that there was a fix that was required to get this module working with Strawberry Perl : http://vinsworldcom.blogspot.com/2012/08/ipv6-in-perl-on-windows_20.html We most likely need a fix for standard Perl distribution to make this work on Windows.
Subject: Screen_Shot_2015-03-04_at_3.20.28_PM.png
Screen_Shot_2015-03-04_at_3.20.28_PM.png
Subject: Screen_Shot_2015-03-04_at_3.21.29_PM.png
Screen_Shot_2015-03-04_at_3.21.29_PM.png
On Wed Mar 11 12:31:29 2015, GTANEZA wrote: Show quoted text
> Enabled inet_ntop and inet_pton in config.VC64 config but i still get > 'Vendor has not defined Socket macro' error when running IO-Socket-IP > module tests. > > When compiling the updated Socket module; i see inet_ntop and > inet_pton undefined (see attached screenshot)
At this point it's a Socket bug, not IO-Socket-IP. -- Paul Evans
Also, seems to be a duplicate of https://rt.cpan.org/Ticket/Display.html?id=91524 Please continue there instead. -- Paul Evans
So what is the latest progress here? I don't have any way to test anything Windowsy, so I'm 100% relying on other people to supply some sort of patch to fix things. Does such a patch exist yet that I can apply? -- Paul Evans
I indepdently rewrote this patch, I didn't know this ticket exists. This patch uses WSAStringToAddress which is available in windows 95 and newer (really only 2000 and newer matter, native inet_pton is only on Vista and up, which is unacceptable since 2K and XP are supported. I thought of using RtlIpv4AddressToStringA from ntdll.dll but that supposedly XP and up. II didn't check a Win2K ntdll.dll to see if it is undocumented but implemented, but it doesn't matter since WSAStringToAddress works. The code is public domain (I guess) from SO http://stackoverflow.com/questions/13731243/what-is-the-windows-xp-equivalent-of-inet-pton-or-inetpton .
Subject: 0001-add-inet_pton-and-inet_ntop-on-Win32.patch
From fea867ad5a0d94d4f06bc3a8e2a5fbd587efdb95 Mon Sep 17 00:00:00 2001 From: bulk88 <bulk88@hotmail.com> Date: Sat, 18 Apr 2015 11:44:25 +0200 Subject: [PATCH] add inet_pton and inet_ntop on Win32 Vista and up have inet_pton and inet_ntop, exported from ws2_32.dll. XP and 2000 dont. So implement the 2 using the old fashioned way (and most portable on Win32 way). --- Socket.xs | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 52 insertions(+), 0 deletions(-) diff --git a/Socket.xs b/Socket.xs index 60f5754..f37fcc4 100644 --- a/Socket.xs +++ b/Socket.xs @@ -51,6 +51,58 @@ # include <ws2tcpip.h> #endif +#ifdef WIN32 +int inet_pton(int af, const char *src, void *dst) +{ + struct sockaddr_storage ss; + int size = sizeof(ss); + char src_copy[INET6_ADDRSTRLEN+1]; + + 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) { + switch(af) { + case AF_INET: + *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; + return 1; + case AF_INET6: + *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; + return 1; + } + } + return 0; +} + +const char *inet_ntop(int af, const void *src, char *dst, socklen_t size) +{ + struct sockaddr_storage ss; + unsigned long s = size; + + ZeroMemory(&ss, sizeof(ss)); + ss.ss_family = af; + + switch(af) { + case AF_INET: + ((struct sockaddr_in *)&ss)->sin_addr = *(struct in_addr *)src; + break; + case AF_INET6: + ((struct sockaddr_in6 *)&ss)->sin6_addr = *(struct in6_addr *)src; + break; + default: + return NULL; + } + /* cannot direclty use &size because of strict aliasing rules */ + return (WSAAddressToString((struct sockaddr *)&ss, sizeof(ss), NULL, dst, &s) == 0)? + dst : NULL; +} + +#define HAS_INETPTON +#define HAS_INETNTOP +#endif + #ifdef NETWARE NETDB_DEFINE_CONTEXT NETINET_DEFINE_CONTEXT -- 1.7.9.msysgit.0
@LeoNerd,

Bul88 and I are currently in Berlin for the QA Hackathon and are available for testing on 3 Windows platforms.

-- 
Olivier Mengué - http://perlresume.org/DOLMEN - https://gratipay.com/dolmen/
On Sat Apr 18 06:03:03 2015, DOLMEN wrote: Show quoted text
> @LeoNerd, > > Bul88 and I are currently in Berlin for the QA Hackathon and are > available for > testing on 3 Windows platforms.
Ah excellent - if you can let me know if this works on those, then I can apply it. -- Paul Evans
Le 2015-04-18 13:06:35, PEVANS a écrit :

Show quoted text
> Ah excellent - if you can let me know if this works on those, then I
> can apply it.

The patch above by BULKDD above is verified.
We are on IRC, #perl-qa

-- 
Olivier Mengué - http://perlresume.org/DOLMEN - https://gratipay.com/dolmen/
Thanks; patch applied. Uploaded to CPAN as a devel release of 2.018_001 to see if the smokers like it. Presuming all is happy, I'll call it 2.019. -- Paul Evans
On Mon Apr 27 16:24:33 2015, PEVANS wrote: Show quoted text
> Thanks; patch applied. Uploaded to CPAN as a devel release of > 2.018_001 to see if the smokers like it. Presuming all is happy, I'll > call it 2.019.
There is a bug in the above code, fix below int inet_pton(int af, const char *src, void *dst) { struct sockaddr_storage ss; int size = sizeof(ss); char src_copy[INET6_ADDRSTRLEN+1]; 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) return 0; switch(af) { case AF_INET: *(struct in_addr *)dst = ((struct sockaddr_in *)&ss)->sin_addr; return 1; case AF_INET6: *(struct in6_addr *)dst = ((struct sockaddr_in6 *)&ss)->sin6_addr; return 1; default: <<missing return 0; <<missing } } Visual C reports d:\smoke\perl\blead\build\cpan\socket\socket.xs(77) : warning C4715: 'inet_pton' : not all control paths return a value
On Wed Jul 22 07:46:08 2015, BULKDD wrote: Show quoted text
> Visual C reports > > d:\smoke\perl\blead\build\cpan\socket\socket.xs(77) : warning C4715: > 'inet_pton' : not all control paths return a value
I believe this has now been fixed by the other patch; in RT107058 -- Paul Evans