This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[asperl] added AS patch#2
[perl5.git] / win32 / ipsock.c
1 /*
2
3         ipsock.c
4         Interface for perl socket functions
5
6 */
7
8 #include <ipsock.h>
9 #include <fcntl.h>
10
11 #define USE_SOCKETS_AS_HANDLES
12
13 class CPerlSock : public IPerlSock
14 {
15 public:
16         CPerlSock();
17         ~CPerlSock();
18         virtual u_long Htonl(u_long hostlong);
19         virtual u_short Htons(u_short hostshort);
20         virtual u_long Ntohl(u_long netlong);
21         virtual u_short Ntohs(u_short netshort);
22         virtual SOCKET Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err);
23         virtual int Bind(SOCKET s, const struct sockaddr* name, int namelen, int &err);
24         virtual int Connect(SOCKET s, const struct sockaddr* name, int namelen, int &err);
25         virtual void Endhostent(int &err);
26         virtual void Endnetent(int &err);
27         virtual void Endprotoent(int &err);
28         virtual void Endservent(int &err);
29         virtual struct hostent* Gethostbyaddr(const char* addr, int len, int type, int &err);
30         virtual struct hostent* Gethostbyname(const char* name, int &err);
31         virtual struct hostent* Gethostent(int &err);
32         virtual int Gethostname(char* name, int namelen, int &err);
33         virtual struct netent *Getnetbyaddr(long net, int type, int &err);
34         virtual struct netent *Getnetbyname(const char *, int &err);
35         virtual struct netent *Getnetent(int &err);
36         virtual int Getpeername(SOCKET s, struct sockaddr* name, int* namelen, int &err);
37         virtual struct protoent* Getprotobyname(const char* name, int &err);
38         virtual struct protoent* Getprotobynumber(int number, int &err);
39         virtual struct protoent* Getprotoent(int &err);
40         virtual struct servent* Getservbyname(const char* name, const char* proto, int &err);
41         virtual struct servent* Getservbyport(int port, const char* proto, int &err);
42         virtual struct servent* Getservent(int &err);
43         virtual int Getsockname(SOCKET s, struct sockaddr* name, int* namelen, int &err);
44         virtual int Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err);
45         virtual unsigned long InetAddr(const char* cp, int &err);
46         virtual char* InetNtoa(struct in_addr in, int &err);
47         virtual int IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err);
48         virtual int Listen(SOCKET s, int backlog, int &err);
49         virtual int Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err);
50         virtual int Select(int nfds, char* readfds, char* writefds, char* exceptfds, const struct timeval* timeout, int &err);
51         virtual int Send(SOCKET s, const char* buffer, int len, int flags, int &err); 
52         virtual int Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err);
53         virtual void Sethostent(int stayopen, int &err);
54         virtual void Setnetent(int stayopen, int &err);
55         virtual void Setprotoent(int stayopen, int &err);
56         virtual void Setservent(int stayopen, int &err);
57         virtual int Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err);
58         virtual int Shutdown(SOCKET s, int how, int &err);
59         virtual SOCKET Socket(int af, int type, int protocol, int &err);
60         virtual int Socketpair(int domain, int type, int protocol, int* fds, int &err);
61
62         void CloseSocket(int fh, int& err);
63         void* GetAddress(HINSTANCE hInstance, char *lpFunctionName);
64         void LoadWinSock(void);
65
66         inline void SetPerlObj(CPerlObj *p) { pPerl = p; };
67         inline void SetStdObj(IPerlStdIOWin *p) { pStdIO = p; };
68 protected:
69         void Start(void);
70
71         inline int OpenOSfhandle(long osfhandle)
72         {
73                 return pStdIO->OpenOSfhandle(osfhandle, O_RDWR|O_BINARY);
74         };
75         int GetOSfhandle(int filenum)
76         {
77                 return pStdIO->GetOSfhandle(filenum);
78         };
79
80         inline void StartSockets(void)
81         {
82                 if(!bStarted)
83                         Start();
84         };
85
86         BOOL bStarted;
87         CPerlObj *pPerl;
88         IPerlStdIOWin *pStdIO;
89 };
90
91
92 #define SOCKETAPI PASCAL 
93
94 typedef SOCKET (SOCKETAPI *LPSOCKACCEPT)(SOCKET, struct sockaddr *, int *);
95 typedef int (SOCKETAPI *LPSOCKBIND)(SOCKET, const struct sockaddr *, int);
96 typedef int (SOCKETAPI *LPSOCKCLOSESOCKET)(SOCKET);
97 typedef int (SOCKETAPI *LPSOCKCONNECT)(SOCKET, const struct sockaddr *, int);
98 typedef unsigned long (SOCKETAPI *LPINETADDR)(const char *);
99 typedef char* (SOCKETAPI *LPINETNTOA)(struct in_addr);
100 typedef int (SOCKETAPI *LPSOCKIOCTLSOCKET)(SOCKET, long, u_long *);
101 typedef int (SOCKETAPI *LPSOCKGETPEERNAME)(SOCKET, struct sockaddr *, int *);
102 typedef int (SOCKETAPI *LPSOCKGETSOCKNAME)(SOCKET, struct sockaddr *, int *);
103 typedef int (SOCKETAPI *LPSOCKGETSOCKOPT)(SOCKET, int, int, char *, int *);
104 typedef u_long (SOCKETAPI *LPSOCKHTONL)(u_long);
105 typedef u_short (SOCKETAPI *LPSOCKHTONS)(u_short);
106 typedef int (SOCKETAPI *LPSOCKLISTEN)(SOCKET, int);
107 typedef u_long (SOCKETAPI *LPSOCKNTOHL)(u_long);
108 typedef u_short (SOCKETAPI *LPSOCKNTOHS)(u_short);
109 typedef int (SOCKETAPI *LPSOCKRECV)(SOCKET, char *, int, int);
110 typedef int (SOCKETAPI *LPSOCKRECVFROM)(SOCKET, char *, int, int, struct sockaddr *, int *);
111 typedef int (SOCKETAPI *LPSOCKSELECT)(int, fd_set *, fd_set *, fd_set *, const struct timeval *);
112 typedef int (SOCKETAPI *LPSOCKSEND)(SOCKET, const char *, int, int);
113 typedef int (SOCKETAPI *LPSOCKSENDTO)(SOCKET, const char *, int, int, const struct sockaddr *, int);
114 typedef int (SOCKETAPI *LPSOCKSETSOCKOPT)(SOCKET, int, int, const char *, int);
115 typedef int (SOCKETAPI *LPSOCKSHUTDOWN)(SOCKET, int);
116 typedef SOCKET (SOCKETAPI *LPSOCKSOCKET)(int, int, int);
117
118 /* Database function prototypes */
119 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYADDR)(const char *, int, int);
120 typedef struct hostent *(SOCKETAPI *LPSOCKGETHOSTBYNAME)(const char *);
121 typedef int (SOCKETAPI *LPSOCKGETHOSTNAME)(char *, int);
122 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYPORT)(int, const char *);
123 typedef struct servent *(SOCKETAPI *LPSOCKGETSERVBYNAME)(const char *, const char *);
124 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNUMBER)(int);
125 typedef struct protoent *(SOCKETAPI *LPSOCKGETPROTOBYNAME)(const char *);
126
127 /* Microsoft Windows Extension function prototypes */
128 typedef int (SOCKETAPI *LPSOCKWSASTARTUP)(unsigned short, LPWSADATA);
129 typedef int (SOCKETAPI *LPSOCKWSACLEANUP)(void);
130 typedef int (SOCKETAPI *LPSOCKWSAGETLASTERROR)(void);
131 typedef int (SOCKETAPI *LPWSAFDIsSet)(SOCKET, fd_set *);
132
133 static HINSTANCE hWinSockDll = 0;
134
135 static LPSOCKACCEPT paccept = 0;
136 static LPSOCKBIND pbind = 0;
137 static LPSOCKCLOSESOCKET pclosesocket = 0;
138 static LPSOCKCONNECT pconnect = 0;
139 static LPINETADDR pinet_addr = 0;
140 static LPINETNTOA pinet_ntoa = 0;
141 static LPSOCKIOCTLSOCKET pioctlsocket = 0;
142 static LPSOCKGETPEERNAME pgetpeername = 0;
143 static LPSOCKGETSOCKNAME pgetsockname = 0;
144 static LPSOCKGETSOCKOPT pgetsockopt = 0;
145 static LPSOCKHTONL phtonl = 0;
146 static LPSOCKHTONS phtons = 0;
147 static LPSOCKLISTEN plisten = 0;
148 static LPSOCKNTOHL pntohl = 0;
149 static LPSOCKNTOHS pntohs = 0;
150 static LPSOCKRECV precv = 0;
151 static LPSOCKRECVFROM precvfrom = 0;
152 static LPSOCKSELECT pselect = 0;
153 static LPSOCKSEND psend = 0;
154 static LPSOCKSENDTO psendto = 0;
155 static LPSOCKSETSOCKOPT psetsockopt = 0;
156 static LPSOCKSHUTDOWN pshutdown = 0;
157 static LPSOCKSOCKET psocket = 0;
158 static LPSOCKGETHOSTBYADDR pgethostbyaddr = 0;
159 static LPSOCKGETHOSTBYNAME pgethostbyname = 0;
160 static LPSOCKGETHOSTNAME pgethostname = 0;
161 static LPSOCKGETSERVBYPORT pgetservbyport = 0;
162 static LPSOCKGETSERVBYNAME pgetservbyname = 0;
163 static LPSOCKGETPROTOBYNUMBER pgetprotobynumber = 0;
164 static LPSOCKGETPROTOBYNAME pgetprotobyname = 0;
165 static LPSOCKWSASTARTUP pWSAStartup = 0;
166 static LPSOCKWSACLEANUP pWSACleanup = 0;
167 static LPSOCKWSAGETLASTERROR pWSAGetLastError = 0;
168 static LPWSAFDIsSet pWSAFDIsSet = 0;
169
170 void* CPerlSock::GetAddress(HINSTANCE hInstance, char *lpFunctionName)
171 {
172         char buffer[512];
173         FARPROC proc = GetProcAddress(hInstance, lpFunctionName);
174         if(proc == 0)
175         {
176                 sprintf(buffer, "Unable to get address of %s in WSock32.dll", lpFunctionName);
177                 croak(buffer);
178         }
179         return proc;
180 }
181
182 void CPerlSock::LoadWinSock(void)
183 {
184         if(hWinSockDll == NULL)
185         {
186                 HINSTANCE hLib = LoadLibrary("WSock32.DLL");
187                 if(hLib == NULL)
188                         croak("Could not load WSock32.dll\n");
189
190                 paccept = (LPSOCKACCEPT)GetAddress(hLib, "accept");
191                 pbind = (LPSOCKBIND)GetAddress(hLib, "bind");
192                 pclosesocket = (LPSOCKCLOSESOCKET)GetAddress(hLib, "closesocket");
193                 pconnect = (LPSOCKCONNECT)GetAddress(hLib, "connect");
194                 pinet_addr = (LPINETADDR)GetAddress(hLib, "inet_addr");
195                 pinet_ntoa = (LPINETNTOA)GetAddress(hLib, "inet_ntoa");
196                 pioctlsocket = (LPSOCKIOCTLSOCKET)GetAddress(hLib, "ioctlsocket");
197                 pgetpeername = (LPSOCKGETPEERNAME)GetAddress(hLib, "getpeername");
198                 pgetsockname = (LPSOCKGETSOCKNAME)GetAddress(hLib, "getsockname");
199                 pgetsockopt = (LPSOCKGETSOCKOPT)GetAddress(hLib, "getsockopt");
200                 phtonl = (LPSOCKHTONL)GetAddress(hLib, "htonl");
201                 phtons = (LPSOCKHTONS)GetAddress(hLib, "htons");
202                 plisten = (LPSOCKLISTEN)GetAddress(hLib, "listen");
203                 pntohl = (LPSOCKNTOHL)GetAddress(hLib, "ntohl");
204                 pntohs = (LPSOCKNTOHS)GetAddress(hLib, "ntohs");
205                 precv = (LPSOCKRECV)GetAddress(hLib, "recv");
206                 precvfrom = (LPSOCKRECVFROM)GetAddress(hLib, "recvfrom");
207                 pselect = (LPSOCKSELECT)GetAddress(hLib, "select");
208                 psend = (LPSOCKSEND)GetAddress(hLib, "send");
209                 psendto = (LPSOCKSENDTO)GetAddress(hLib, "sendto");
210                 psetsockopt = (LPSOCKSETSOCKOPT)GetAddress(hLib, "setsockopt");
211                 pshutdown = (LPSOCKSHUTDOWN)GetAddress(hLib, "shutdown");
212                 psocket = (LPSOCKSOCKET)GetAddress(hLib, "socket");
213                 pgethostbyaddr = (LPSOCKGETHOSTBYADDR)GetAddress(hLib, "gethostbyaddr");
214                 pgethostbyname = (LPSOCKGETHOSTBYNAME)GetAddress(hLib, "gethostbyname");
215                 pgethostname = (LPSOCKGETHOSTNAME)GetAddress(hLib, "gethostname");
216                 pgetservbyport = (LPSOCKGETSERVBYPORT)GetAddress(hLib, "getservbyport");
217                 pgetservbyname = (LPSOCKGETSERVBYNAME)GetAddress(hLib, "getservbyname");
218                 pgetprotobynumber = (LPSOCKGETPROTOBYNUMBER)GetAddress(hLib, "getprotobynumber");
219                 pgetprotobyname = (LPSOCKGETPROTOBYNAME)GetAddress(hLib, "getprotobyname");
220                 pWSAStartup = (LPSOCKWSASTARTUP)GetAddress(hLib, "WSAStartup");
221                 pWSACleanup = (LPSOCKWSACLEANUP)GetAddress(hLib, "WSACleanup");
222                 pWSAGetLastError = (LPSOCKWSAGETLASTERROR)GetAddress(hLib, "WSAGetLastError");
223                 pWSAFDIsSet = (LPWSAFDIsSet)GetAddress(hLib, "__WSAFDIsSet");
224                 hWinSockDll = hLib;
225         }
226 }
227
228
229 CPerlSock::CPerlSock()
230 {
231         bStarted = FALSE;
232         pPerl = NULL;
233         pStdIO = NULL;
234 }
235
236 CPerlSock::~CPerlSock()
237 {
238         if(bStarted)
239                 pWSACleanup();
240 }
241
242 void
243 CPerlSock::Start(void) 
244 {
245     unsigned short version;
246     WSADATA retdata;
247     int ret;
248     int iSockOpt = SO_SYNCHRONOUS_NONALERT;
249
250         LoadWinSock();
251     /*
252      * initalize the winsock interface and insure that it is
253      * cleaned up at exit.
254      */
255     version = 0x101;
256     if(ret = pWSAStartup(version, &retdata))
257         croak("Unable to locate winsock library!\n");
258     if(retdata.wVersion != version)
259         croak("Could not find version 1.1 of winsock dll\n");
260
261     /* atexit((void (*)(void)) EndSockets); */
262
263 #ifdef USE_SOCKETS_AS_HANDLES
264     /*
265      * Enable the use of sockets as filehandles
266      */
267     psetsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
268                 (char *)&iSockOpt, sizeof(iSockOpt));
269 #endif  /* USE_SOCKETS_AS_HANDLES */
270     bStarted = TRUE;
271 }
272
273
274 u_long 
275 CPerlSock::Htonl(u_long hostlong)
276 {
277         StartSockets();
278         return phtonl(hostlong);
279 }
280
281 u_short 
282 CPerlSock::Htons(u_short hostshort)
283 {
284         StartSockets();
285         return phtons(hostshort);
286 }
287
288 u_long 
289 CPerlSock::Ntohl(u_long netlong)
290 {
291         StartSockets();
292         return pntohl(netlong);
293 }
294
295 u_short 
296 CPerlSock::Ntohs(u_short netshort)
297 {
298         StartSockets();
299         return pntohs(netshort);
300 }
301
302
303 /* thanks to Beverly Brown      (beverly@datacube.com) */
304 #ifdef USE_SOCKETS_AS_HANDLES
305 #       define OPEN_SOCKET(x)   OpenOSfhandle(x)
306 #       define TO_SOCKET(x)     GetOSfhandle(x)
307 #else
308 #       define OPEN_SOCKET(x)   (x)
309 #       define TO_SOCKET(x)     (x)
310 #endif  /* USE_SOCKETS_AS_HANDLES */
311
312 #define SOCKET_TEST(x, y) \
313         STMT_START {                                    \
314         StartSockets();                                 \
315         if((x) == (y))                                  \
316                 err = pWSAGetLastError();       \
317         } STMT_END
318
319 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
320
321 SOCKET 
322 CPerlSock::Accept(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
323 {
324         SOCKET r;
325
326         SOCKET_TEST((r = paccept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
327         return OPEN_SOCKET(r);
328 }
329
330 int
331 CPerlSock::Bind(SOCKET s, const struct sockaddr* addr, int addrlen, int &err)
332 {
333         int r;
334
335         SOCKET_TEST_ERROR(r = pbind(TO_SOCKET(s), addr, addrlen));
336         return r;
337 }
338
339 void
340 CPerlSock::CloseSocket(int fh, int& err)
341 {
342         SOCKET_TEST_ERROR(pclosesocket(TO_SOCKET(fh)));
343 }
344
345 int 
346 CPerlSock::Connect(SOCKET s, const struct sockaddr* addr, int addrlen, int &err)
347 {
348         int r;
349
350         SOCKET_TEST_ERROR(r = pconnect(TO_SOCKET(s), addr, addrlen));
351         return r;
352 }
353
354 void CPerlSock::Endhostent(int &err)
355 {
356         croak("endhostent not implemented!\n");
357 }
358
359 void CPerlSock::Endnetent(int &err)
360 {
361         croak("endnetent not implemented!\n");
362 }
363
364 void CPerlSock::Endprotoent(int &err)
365 {
366         croak("endprotoent not implemented!\n");
367 }
368
369 void CPerlSock::Endservent(int &err)
370 {
371         croak("endservent not implemented!\n");
372 }
373
374 struct hostent* 
375 CPerlSock::Gethostbyaddr(const char* addr, int len, int type, int &err)
376 {
377     struct hostent *r;
378
379     SOCKET_TEST(r = pgethostbyaddr(addr, len, type), NULL);
380     return r;
381 }
382
383 struct hostent* 
384 CPerlSock::Gethostbyname(const char* name, int &err)
385 {
386     struct hostent *r;
387
388     SOCKET_TEST(r = pgethostbyname(name), NULL);
389     return r;
390 }
391
392 struct hostent* CPerlSock::Gethostent(int &err)
393 {
394         croak("gethostent not implemented!\n");
395         return NULL;
396 }
397
398 int 
399 CPerlSock::Gethostname(char* name, int len, int &err)
400 {
401     int r;
402
403     SOCKET_TEST_ERROR(r = pgethostname(name, len));
404     return r;
405 }
406
407 struct netent *CPerlSock::Getnetbyaddr(long net, int type, int &err)
408 {
409         croak("getnetbyaddr not implemented!\n");
410         return NULL;
411 }
412
413 struct netent *CPerlSock::Getnetbyname(const char *, int &err)
414 {
415         croak("getnetbyname not implemented!\n");
416         return NULL;
417 }
418
419 struct netent *CPerlSock::Getnetent(int &err)
420 {
421         croak("getnetent not implemented!\n");
422         return NULL;
423 }
424
425 int 
426 CPerlSock::Getpeername(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
427 {
428         int r;
429
430         SOCKET_TEST_ERROR(r = pgetpeername(TO_SOCKET(s), addr, addrlen));
431         return r;
432 }
433
434 struct protoent* 
435 CPerlSock::Getprotobyname(const char* name, int &err)
436 {
437     struct protoent *r;
438
439     SOCKET_TEST(r = pgetprotobyname(name), NULL);
440     return r;
441 }
442
443 struct protoent* 
444 CPerlSock::Getprotobynumber(int number, int &err)
445 {
446     struct protoent *r;
447
448     SOCKET_TEST(r = pgetprotobynumber(number), NULL);
449     return r;
450 }
451
452 struct protoent* CPerlSock::Getprotoent(int &err)
453 {
454         croak("getprotoent not implemented!\n");
455         return NULL;
456 }
457
458 struct servent* 
459 CPerlSock::Getservbyname(const char* name, const char* proto, int &err)
460 {
461     struct servent *r;
462     dTHR;    
463
464     SOCKET_TEST(r = pgetservbyname(name, proto), NULL);
465 //    if (r) {
466 //      r = win32_savecopyservent(&myservent, r, proto);
467 //    }
468     return r;
469 }
470
471 struct servent* 
472 CPerlSock::Getservbyport(int port, const char* proto, int &err)
473 {
474     struct servent *r;
475     dTHR; 
476
477     SOCKET_TEST(r = pgetservbyport(port, proto), NULL);
478 //    if (r) {
479 //      r = win32_savecopyservent(&myservent, r, proto);
480 //    }
481     return r;
482 }
483
484 struct servent* CPerlSock::Getservent(int &err)
485 {
486         croak("getservent not implemented!\n");
487         return NULL;
488 }
489
490 int 
491 CPerlSock::Getsockname(SOCKET s, struct sockaddr* addr, int* addrlen, int &err)
492 {
493         int r;
494
495         SOCKET_TEST_ERROR(r = pgetsockname(TO_SOCKET(s), addr, addrlen));
496         return r;
497 }
498
499 int 
500 CPerlSock::Getsockopt(SOCKET s, int level, int optname, char* optval, int* optlen, int &err)
501 {
502         int r;
503
504         SOCKET_TEST_ERROR(r = pgetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
505         return r;
506 }
507
508 unsigned long
509 CPerlSock::InetAddr(const char* cp, int &err)
510 {
511         unsigned long r;
512
513         SOCKET_TEST(r = pinet_addr(cp), INADDR_NONE);
514         return r;
515 }
516
517 char*
518 CPerlSock::InetNtoa(struct in_addr in, int &err)
519 {
520         char* r;
521
522         SOCKET_TEST(r = pinet_ntoa(in), NULL);
523         return r;
524 }
525
526 int
527 CPerlSock::IoctlSocket(SOCKET s, long cmd, u_long *argp, int& err)
528 {
529     int r;
530
531     SOCKET_TEST_ERROR(r = pioctlsocket(TO_SOCKET(s), cmd, argp));
532     return r;
533 }
534
535 int 
536 CPerlSock::Listen(SOCKET s, int backlog, int &err)
537 {
538         int r;
539
540         SOCKET_TEST_ERROR(r = plisten(TO_SOCKET(s), backlog));
541         return r;
542 }
543
544 int 
545 CPerlSock::Recvfrom(SOCKET s, char* buffer, int len, int flags, struct sockaddr* from, int* fromlen, int &err)
546 {
547         int r;
548
549         SOCKET_TEST_ERROR(r = precvfrom(TO_SOCKET(s), buffer, len, flags, from, fromlen));
550         return r;
551 }
552
553 int 
554 CPerlSock::Select(int nfds, char* rd, char* wr, char* ex, const struct timeval* timeout, int &err)
555 {
556         long r;
557         int i, fd, bit, offset;
558         FD_SET nrd, nwr, nex;
559
560         FD_ZERO(&nrd);
561         FD_ZERO(&nwr);
562         FD_ZERO(&nex);
563         for (i = 0; i < nfds; i++)
564         {
565                 fd = TO_SOCKET(i);
566                 bit = 1L<<(i % (sizeof(char)*8));
567                 offset = i / (sizeof(char)*8);
568                 if(rd != NULL && (rd[offset] & bit))
569                         FD_SET(fd, &nrd);
570                 if(wr != NULL && (wr[offset] & bit))
571                         FD_SET(fd, &nwr);
572                 if(ex != NULL && (ex[offset] & bit))
573                         FD_SET(fd, &nex);
574         }
575         SOCKET_TEST_ERROR(r = pselect(nfds, &nrd, &nwr, &nex, timeout));
576
577         for(i = 0; i < nfds; i++)
578         {
579                 fd = TO_SOCKET(i);
580                 bit = 1L<<(i % (sizeof(char)*8));
581                 offset = i / (sizeof(char)*8);
582                 if(rd != NULL && (rd[offset] & bit))
583                 {
584                         if(!pWSAFDIsSet(fd, &nrd))
585                                 rd[offset] &= ~bit;
586                 }
587                 if(wr != NULL && (wr[offset] & bit))
588                 {
589                         if(!pWSAFDIsSet(fd, &nwr))
590                                 wr[offset] &= ~bit;
591                 }
592                 if(ex != NULL && (ex[offset] & bit))
593                 {
594                         if(!pWSAFDIsSet(fd, &nex))
595                                 ex[offset] &= ~bit;
596                 }
597         }
598         return r;
599 }
600
601 int 
602 CPerlSock::Send(SOCKET s, const char* buffer, int len, int flags, int &err)
603 {
604     int r;
605
606     SOCKET_TEST_ERROR(r = psend(TO_SOCKET(s), buffer, len, flags));
607     return r;
608 }
609
610 int 
611 CPerlSock::Sendto(SOCKET s, const char* buffer, int len, int flags, const struct sockaddr* to, int tolen, int &err)
612 {
613     int r;
614
615     SOCKET_TEST_ERROR(r = psendto(TO_SOCKET(s), buffer, len, flags, to, tolen));
616     return r;
617 }
618
619 void CPerlSock::Sethostent(int stayopen, int &err)
620 {
621         croak("sethostent not implemented!\n");
622 }
623
624 void CPerlSock::Setnetent(int stayopen, int &err)
625 {
626         croak("setnetent not implemented!\n");
627 }
628
629 void CPerlSock::Setprotoent(int stayopen, int &err)
630 {
631         croak("setprotoent not implemented!\n");
632 }
633
634 void CPerlSock::Setservent(int stayopen, int &err)
635 {
636         croak("setservent not implemented!\n");
637 }
638
639 int 
640 CPerlSock::Setsockopt(SOCKET s, int level, int optname, const char* optval, int optlen, int &err)
641 {
642     int r;
643
644     SOCKET_TEST_ERROR(r = psetsockopt(TO_SOCKET(s), level, optname, optval, optlen));
645     return r;
646 }
647
648 int 
649 CPerlSock::Shutdown(SOCKET s, int how, int &err)
650 {
651     int r;
652
653     SOCKET_TEST_ERROR(r = pshutdown(TO_SOCKET(s), how));
654     return r;
655 }
656
657 SOCKET 
658 CPerlSock::Socket(int af, int type, int protocol, int &err)
659 {
660     SOCKET s;
661
662 #ifdef USE_SOCKETS_AS_HANDLES
663     StartSockets();
664     if((s = psocket(af, type, protocol)) == INVALID_SOCKET)
665         err = pWSAGetLastError();
666     else
667         s = OPEN_SOCKET(s);
668 #else
669     SOCKET_TEST(s = psocket(af, type, protocol), INVALID_SOCKET);
670 #endif  /* USE_SOCKETS_AS_HANDLES */
671
672     return s;
673 }
674
675 int CPerlSock::Socketpair(int domain, int type, int protocol, int* fds, int &err)
676 {
677         croak("socketpair not implemented!\n");
678         return 0;
679 }
680
681