#define Win32_Winsock
#endif
#include <windows.h>
+#include <ws2spi.h>
+
#include "EXTERN.h"
#include "perl.h"
# define TO_SOCKET(x) (x)
#endif /* USE_SOCKETS_AS_HANDLES */
-#if defined(USE_5005THREADS) || defined(USE_ITHREADS)
#define StartSockets() \
STMT_START { \
if (!wsock_started) \
start_sockets(); \
- set_socktype(); \
} STMT_END
-#else
-#define StartSockets() \
- STMT_START { \
- if (!wsock_started) { \
- start_sockets(); \
- set_socktype(); \
- } \
- } STMT_END
-#endif
#define SOCKET_TEST(x, y) \
STMT_START { \
* 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;
}
-void
-set_socktype(void)
-{
-#ifdef USE_SOCKETS_AS_HANDLES
-#if defined(USE_5005THREADS) || 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_5005THREADS) || defined(USE_ITHREADS)
- w32_init_socktype = 1;
- }
-#endif
-#endif /* USE_SOCKETS_AS_HANDLES */
-}
-
-
#ifndef USE_SOCKETS_AS_HANDLES
#undef fdopen
FILE *
/*
* If we get here, then fd is actually a socket.
*/
- Newz(1310, fp, 1, FILE); /* XXX leak, good thing this code isn't used */
+ Newxz(fp, 1, FILE); /* XXX leak, good thing this code isn't used */
if(fp == NULL) {
errno = ENOMEM;
return NULL;
{
int r;
#ifdef USE_SOCKETS_AS_HANDLES
- Perl_fd_set dummy;
- int i, fd, bit, offset;
- FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
+ int i, fd, save_errno = errno;
+ FD_SET nrd, nwr, nex;
/* winsock seems incapable of dealing with all three null fd_sets,
* so do the (millisecond) sleep as a special case
return 0;
}
StartSockets();
- PERL_FD_ZERO(&dummy);
- if (!rd)
- rd = &dummy, prd = NULL;
- else
- prd = &nrd;
- if (!wr)
- wr = &dummy, pwr = NULL;
- else
- pwr = &nwr;
- if (!ex)
- ex = &dummy, pex = NULL;
- else
- pex = &nex;
FD_ZERO(&nrd);
FD_ZERO(&nwr);
FD_ZERO(&nex);
for (i = 0; i < nfds; i++) {
fd = TO_SOCKET(i);
- if (PERL_FD_ISSET(i,rd))
- FD_SET(fd, &nrd);
- if (PERL_FD_ISSET(i,wr))
- FD_SET(fd, &nwr);
- if (PERL_FD_ISSET(i,ex))
- FD_SET(fd, &nex);
+ if (rd && PERL_FD_ISSET(i,rd))
+ FD_SET((unsigned)fd, &nrd);
+ if (wr && PERL_FD_ISSET(i,wr))
+ FD_SET((unsigned)fd, &nwr);
+ if (ex && PERL_FD_ISSET(i,ex))
+ FD_SET((unsigned)fd, &nex);
}
- SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout));
+ errno = save_errno;
+ SOCKET_TEST_ERROR(r = select(nfds, &nrd, &nwr, &nex, timeout));
+ save_errno = errno;
for (i = 0; i < nfds; i++) {
fd = TO_SOCKET(i);
- if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
+ if (rd && PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
PERL_FD_CLR(i,rd);
- if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
+ if (wr && PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
PERL_FD_CLR(i,wr);
- if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
+ if (ex && PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
PERL_FD_CLR(i,ex);
}
+ errno = save_errno;
#else
SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
#endif
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)
+{
+ dTHX;
+ char *s;
+ unsigned long proto_buffers_len = 0;
+ int error_code;
+ SOCKET out = INVALID_SOCKET;
+
+ if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s))
+ return WSASocket(af, type, protocol, NULL, 0, 0);
+
+ if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR
+ && error_code == WSAENOBUFS)
+ {
+ WSAPROTOCOL_INFOW *proto_buffers;
+ int protocols_available = 0;
+
+ Newx(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 && proto_buffers[i].iProtocol != 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)
{
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);
#undef fstat
int
-my_fstat(int fd, struct stat *sbufptr)
+my_fstat(int fd, Stat_t *sbufptr)
{
/* This fixes a bug in fstat() on Windows 9x. fstat() uses the
* GetFileType() win32 syscall, which will fail on Windows 9x.
* sbufptr->st_mode.
*/
int osf;
- if (!wsock_started || IsWinNT())
+ if (!wsock_started || IsWinNT()) {
+#if defined(WIN64) || defined(USE_LARGE_FILES)
+#if defined(__BORLANDC__) /* buk */
+ return win32_fstat(fd, sbufptr );
+#else
+ return _fstati64(fd, sbufptr);
+#endif
+#else
return fstat(fd, sbufptr);
+#endif
+ }
osf = TO_SOCKET(fd);
if (osf != -1) {
sbufptr->st_nlink = 1;
sbufptr->st_uid = sbufptr->st_gid = sbufptr->st_ino = 0;
sbufptr->st_atime = sbufptr->st_mtime = sbufptr->st_ctime = 0;
- sbufptr->st_size = (off_t)0;
+ sbufptr->st_size = (Off_t)0;
return 0;
}
}
+#if defined(WIN64) || defined(USE_LARGE_FILES)
+#if defined(__BORLANDC__) /* buk */
+ return win32_fstat(fd, sbufptr );
+#else
+ return _fstati64(fd, sbufptr);
+#endif
+#else
return fstat(fd, sbufptr);
+#endif
}
struct hostent *
win32_ioctl(int i, unsigned int u, char *data)
{
dTHX;
- u_long argp = (u_long)data;
+ u_long u_long_arg;
int retval;
-
+
if (!wsock_started) {
Perl_croak_nocontext("ioctl implemented only on sockets");
/* NOTREACHED */
}
- retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
+ /* mauke says using memcpy avoids alignment issues */
+ memcpy(&u_long_arg, data, sizeof u_long_arg);
+ retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg);
+ memcpy(data, &u_long_arg, sizeof u_long_arg);
+
if (retval == SOCKET_ERROR) {
if (WSAGetLastError() == WSAENOTSOCK) {
Perl_croak_nocontext("ioctl implemented only on sockets");