summaryrefslogtreecommitdiff
path: root/win32/win32sck.c
diff options
context:
space:
mode:
authorSteve Hay <SteveHay@planit.com>2004-08-06 12:55:31 +0000
committerSteve Hay <SteveHay@planit.com>2004-08-06 12:55:31 +0000
commit036c1c1eb70a0dfc5a7187959eb5e39d499c9396 (patch)
tree5ec225dec9327c122e7e2efe8b22d5668441f038 /win32/win32sck.c
parent7d54d38ea123279986bac06bc420bfdc4e2395fb (diff)
downloadperl-036c1c1eb70a0dfc5a7187959eb5e39d499c9396.tar.gz
Fix [perl #24269] socket() call uses non-IFS providers
causing subsequent print/read to hang or misbehave Patch supplied by Artiom Morozov <artiom@phreaker.net> in the bug report at http://rt.perl.org/rt3/index.html?q=24269 p4raw-id: //depot/perl@23200
Diffstat (limited to 'win32/win32sck.c')
-rw-r--r--win32/win32sck.c84
1 files changed, 65 insertions, 19 deletions
diff --git a/win32/win32sck.c b/win32/win32sck.c
index 86cdc5f9ca..0e2be309bd 100644
--- a/win32/win32sck.c
+++ b/win32/win32sck.c
@@ -16,6 +16,8 @@
#define Win32_Winsock
#endif
#include <windows.h>
+#include <ws2spi.h>
+
#include "EXTERN.h"
#include "perl.h"
@@ -86,11 +88,11 @@ start_sockets(void)
* initalize the winsock interface and insure that it is
* cleaned up at exit.
*/
- version = 0x101;
+ version = 0x2;
if(ret = WSAStartup(version, &retdata))
Perl_croak_nocontext("Unable to locate winsock library!\n");
if(retdata.wVersion != version)
- Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
+ Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n");
/* atexit((void (*)(void)) EndSockets); */
wsock_started = 1;
@@ -99,22 +101,6 @@ start_sockets(void)
void
set_socktype(void)
{
-#ifdef USE_SOCKETS_AS_HANDLES
-#if defined(USE_ITHREADS)
- dTHX;
- if (!w32_init_socktype) {
-#endif
- int iSockOpt = SO_SYNCHRONOUS_NONALERT;
- /*
- * Enable the use of sockets as filehandles
- */
- setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
- (char *)&iSockOpt, sizeof(iSockOpt));
-#if defined(USE_ITHREADS)
- w32_init_socktype = 1;
- }
-#endif
-#endif /* USE_SOCKETS_AS_HANDLES */
}
@@ -399,6 +385,65 @@ win32_closesocket(SOCKET s)
return r;
}
+#ifdef USE_SOCKETS_AS_HANDLES
+#define WIN32_OPEN_SOCKET(af, type, protocol) open_ifs_socket(af, type, protocol)
+
+void
+convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out)
+{
+ Copy(in, out, 1, WSAPROTOCOL_INFOA);
+ wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol));
+}
+
+SOCKET
+open_ifs_socket(int af, int type, int protocol)
+{
+ unsigned long proto_buffers_len = 0;
+ int error_code;
+ SOCKET out = INVALID_SOCKET;
+
+ if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
+ && error_code == WSAENOBUFS)
+ {
+ WSAPROTOCOL_INFOW *proto_buffers;
+ int protocols_available = 0;
+
+ New(1, proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW),
+ WSAPROTOCOL_INFOW);
+
+ if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers,
+ &proto_buffers_len, &error_code)) != SOCKET_ERROR)
+ {
+ int i;
+ for (i = 0; i < protocols_available; i++)
+ {
+ WSAPROTOCOL_INFOA proto_info;
+
+ if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily)
+ || (type != proto_buffers[i].iSocketType)
+ || (protocol != 0 && protocol != proto_buffers[i].iProtocol))
+ continue;
+
+ if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0)
+ continue;
+
+ convert_proto_info_w2a(&(proto_buffers[i]), &proto_info);
+
+ out = WSASocket(af, type, protocol, &proto_info, 0, 0);
+ break;
+ }
+ }
+
+ Safefree(proto_buffers);
+ }
+
+ return out;
+}
+
+#else
+#define WIN32_OPEN_SOCKET(af, type, protocol) socket(af, type, protocol)
+#endif
+
SOCKET
win32_socket(int af, int type, int protocol)
{
@@ -408,7 +453,8 @@ win32_socket(int af, int type, int protocol)
SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
#else
StartSockets();
- if((s = socket(af, type, protocol)) == INVALID_SOCKET)
+
+ if((s = WIN32_OPEN_SOCKET(af, type, protocol)) == INVALID_SOCKET)
errno = WSAGetLastError();
else
s = OPEN_SOCKET(s);