1 /*
2     Written by Christopher E. Miller
3     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
4 */
5 
6 
7 module core.sys.windows.winsock2;
8 version (Windows):
9 
10 pragma(lib, "ws2_32");
11 
12 extern(Windows):
13 nothrow:
14 
15 alias SOCKET = size_t;
16 alias socklen_t = int;
17 
18 enum SOCKET INVALID_SOCKET = cast(SOCKET)~0;
19 enum int SOCKET_ERROR = -1;
20 
21 enum WSADESCRIPTION_LEN = 256;
22 enum WSASYS_STATUS_LEN = 128;
23 
24 struct WSADATA
25 {
26     ushort wVersion;
27     ushort wHighVersion;
28     char[WSADESCRIPTION_LEN + 1] szDescription = 0;
29     char[WSASYS_STATUS_LEN + 1] szSystemStatus = 0;
30     ushort iMaxSockets;
31     ushort iMaxUdpDg;
32     char* lpVendorInfo;
33 }
34 alias LPWSADATA = WSADATA*;
35 
36 
37 enum int IOCPARM_MASK =  0x7F;
38 enum int IOC_IN =        cast(int)0x80000000;
39 enum int FIONBIO =       cast(int)(IOC_IN | ((uint.sizeof & IOCPARM_MASK) << 16) | (102 << 8) | 126);
40 
41 enum NI_MAXHOST = 1025;
42 enum NI_MAXSERV = 32;
43 
44 @nogc
45 {
46 int WSAStartup(ushort wVersionRequested, LPWSADATA lpWSAData);
47 @trusted int WSACleanup();
48 @trusted SOCKET socket(int af, int type, int protocol);
49 int ioctlsocket(SOCKET s, int cmd, uint* argp);
50 int bind(SOCKET s, const(sockaddr)* name, socklen_t namelen);
51 int connect(SOCKET s, const(sockaddr)* name, socklen_t namelen);
52 @trusted int listen(SOCKET s, int backlog);
53 SOCKET accept(SOCKET s, sockaddr* addr, socklen_t* addrlen);
54 @trusted int closesocket(SOCKET s);
55 @trusted int shutdown(SOCKET s, int how);
56 int getpeername(SOCKET s, sockaddr* name, socklen_t* namelen);
57 int getsockname(SOCKET s, sockaddr* name, socklen_t* namelen);
58 int send(SOCKET s, const(void)* buf, int len, int flags);
59 int sendto(SOCKET s, const(void)* buf, int len, int flags, const(sockaddr)* to, socklen_t tolen);
60 int recv(SOCKET s, void* buf, int len, int flags);
61 int recvfrom(SOCKET s, void* buf, int len, int flags, sockaddr* from, socklen_t* fromlen);
62 int getsockopt(SOCKET s, int level, int optname, void* optval, socklen_t* optlen);
63 int setsockopt(SOCKET s, int level, int optname, const(void)* optval, socklen_t optlen);
64 uint inet_addr(const char* cp);
65 int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* errorfds, const(timeval)* timeout);
66 char* inet_ntoa(in_addr ina);
67 hostent* gethostbyname(const char* name);
68 hostent* gethostbyaddr(const(void)* addr, int len, int type);
69 protoent* getprotobyname(const char* name);
70 protoent* getprotobynumber(int number);
71 servent* getservbyname(const char* name, const char* proto);
72 servent* getservbyport(int port, const char* proto);
73 }
74 
75 enum: int
76 {
77     NI_NOFQDN =          0x01,
78     NI_NUMERICHOST =     0x02,
79     NI_NAMEREQD =        0x04,
80     NI_NUMERICSERV =     0x08,
81     NI_DGRAM  =          0x10,
82 }
83 
84 @nogc
85 {
86 int gethostname(const char* name, int namelen);
87 int getaddrinfo(const(char)* nodename, const(char)* servname, const(addrinfo)* hints, addrinfo** res);
88 void freeaddrinfo(addrinfo* ai);
89 int getnameinfo(const(sockaddr)* sa, socklen_t salen, char* host, uint hostlen, char* serv, uint servlen, int flags);
90 }
91 
92 enum WSABASEERR = 10000;
93 
94 enum: int
95 {
96     /*
97      * Windows Sockets definitions of regular Microsoft C error constants
98      */
99     WSAEINTR = (WSABASEERR+4),
100     WSAEBADF = (WSABASEERR+9),
101     WSAEACCES = (WSABASEERR+13),
102     WSAEFAULT = (WSABASEERR+14),
103     WSAEINVAL = (WSABASEERR+22),
104     WSAEMFILE = (WSABASEERR+24),
105 
106     /*
107      * Windows Sockets definitions of regular Berkeley error constants
108      */
109     WSAEWOULDBLOCK = (WSABASEERR+35),
110     WSAEINPROGRESS = (WSABASEERR+36),
111     WSAEALREADY = (WSABASEERR+37),
112     WSAENOTSOCK = (WSABASEERR+38),
113     WSAEDESTADDRREQ = (WSABASEERR+39),
114     WSAEMSGSIZE = (WSABASEERR+40),
115     WSAEPROTOTYPE = (WSABASEERR+41),
116     WSAENOPROTOOPT = (WSABASEERR+42),
117     WSAEPROTONOSUPPORT = (WSABASEERR+43),
118     WSAESOCKTNOSUPPORT = (WSABASEERR+44),
119     WSAEOPNOTSUPP = (WSABASEERR+45),
120     WSAEPFNOSUPPORT = (WSABASEERR+46),
121     WSAEAFNOSUPPORT = (WSABASEERR+47),
122     WSAEADDRINUSE = (WSABASEERR+48),
123     WSAEADDRNOTAVAIL = (WSABASEERR+49),
124     WSAENETDOWN = (WSABASEERR+50),
125     WSAENETUNREACH = (WSABASEERR+51),
126     WSAENETRESET = (WSABASEERR+52),
127     WSAECONNABORTED = (WSABASEERR+53),
128     WSAECONNRESET = (WSABASEERR+54),
129     WSAENOBUFS = (WSABASEERR+55),
130     WSAEISCONN = (WSABASEERR+56),
131     WSAENOTCONN = (WSABASEERR+57),
132     WSAESHUTDOWN = (WSABASEERR+58),
133     WSAETOOMANYREFS = (WSABASEERR+59),
134     WSAETIMEDOUT = (WSABASEERR+60),
135     WSAECONNREFUSED = (WSABASEERR+61),
136     WSAELOOP = (WSABASEERR+62),
137     WSAENAMETOOLONG = (WSABASEERR+63),
138     WSAEHOSTDOWN = (WSABASEERR+64),
139     WSAEHOSTUNREACH = (WSABASEERR+65),
140     WSAENOTEMPTY = (WSABASEERR+66),
141     WSAEPROCLIM = (WSABASEERR+67),
142     WSAEUSERS = (WSABASEERR+68),
143     WSAEDQUOT = (WSABASEERR+69),
144     WSAESTALE = (WSABASEERR+70),
145     WSAEREMOTE = (WSABASEERR+71),
146 
147     /*
148      * Extended Windows Sockets error constant definitions
149      */
150     WSASYSNOTREADY = (WSABASEERR+91),
151     WSAVERNOTSUPPORTED = (WSABASEERR+92),
152     WSANOTINITIALISED = (WSABASEERR+93),
153 
154     /* Authoritative Answer: Host not found */
155     WSAHOST_NOT_FOUND = (WSABASEERR+1001),
156     HOST_NOT_FOUND = WSAHOST_NOT_FOUND,
157 
158     /* Non-Authoritative: Host not found, or SERVERFAIL */
159     WSATRY_AGAIN = (WSABASEERR+1002),
160     TRY_AGAIN = WSATRY_AGAIN,
161 
162     /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
163     WSANO_RECOVERY = (WSABASEERR+1003),
164     NO_RECOVERY = WSANO_RECOVERY,
165 
166     /* Valid name, no data record of requested type */
167     WSANO_DATA = (WSABASEERR+1004),
168     NO_DATA = WSANO_DATA,
169 
170     /* no address, look for MX record */
171     WSANO_ADDRESS = WSANO_DATA,
172     NO_ADDRESS = WSANO_ADDRESS
173 }
174 
175 /*
176  * Windows Sockets errors redefined as regular Berkeley error constants
177  */
178 enum: int
179 {
180     EWOULDBLOCK = WSAEWOULDBLOCK,
181     EINPROGRESS = WSAEINPROGRESS,
182     EALREADY = WSAEALREADY,
183     ENOTSOCK = WSAENOTSOCK,
184     EDESTADDRREQ = WSAEDESTADDRREQ,
185     EMSGSIZE = WSAEMSGSIZE,
186     EPROTOTYPE = WSAEPROTOTYPE,
187     ENOPROTOOPT = WSAENOPROTOOPT,
188     EPROTONOSUPPORT = WSAEPROTONOSUPPORT,
189     ESOCKTNOSUPPORT = WSAESOCKTNOSUPPORT,
190     EOPNOTSUPP = WSAEOPNOTSUPP,
191     EPFNOSUPPORT = WSAEPFNOSUPPORT,
192     EAFNOSUPPORT = WSAEAFNOSUPPORT,
193     EADDRINUSE = WSAEADDRINUSE,
194     EADDRNOTAVAIL = WSAEADDRNOTAVAIL,
195     ENETDOWN = WSAENETDOWN,
196     ENETUNREACH = WSAENETUNREACH,
197     ENETRESET = WSAENETRESET,
198     ECONNABORTED = WSAECONNABORTED,
199     ECONNRESET = WSAECONNRESET,
200     ENOBUFS = WSAENOBUFS,
201     EISCONN = WSAEISCONN,
202     ENOTCONN = WSAENOTCONN,
203     ESHUTDOWN = WSAESHUTDOWN,
204     ETOOMANYREFS = WSAETOOMANYREFS,
205     ETIMEDOUT = WSAETIMEDOUT,
206     ECONNREFUSED = WSAECONNREFUSED,
207     ELOOP = WSAELOOP,
208     ENAMETOOLONG = WSAENAMETOOLONG,
209     EHOSTDOWN = WSAEHOSTDOWN,
210     EHOSTUNREACH = WSAEHOSTUNREACH,
211     ENOTEMPTY = WSAENOTEMPTY,
212     EPROCLIM = WSAEPROCLIM,
213     EUSERS = WSAEUSERS,
214     EDQUOT = WSAEDQUOT,
215     ESTALE = WSAESTALE,
216     EREMOTE = WSAEREMOTE
217 }
218 
219 enum: int
220 {
221     EAI_NONAME    = WSAHOST_NOT_FOUND,
222 }
223 
224 int WSAGetLastError() @trusted @nogc;
225 
226 
227 enum: int
228 {
229     AF_UNSPEC =     0,
230 
231     AF_UNIX =       1,
232     AF_INET =       2,
233     AF_IMPLINK =    3,
234     AF_PUP =        4,
235     AF_CHAOS =      5,
236     AF_NS =         6,
237     AF_IPX =        AF_NS,
238     AF_ISO =        7,
239     AF_OSI =        AF_ISO,
240     AF_ECMA =       8,
241     AF_DATAKIT =    9,
242     AF_CCITT =      10,
243     AF_SNA =        11,
244     AF_DECnet =     12,
245     AF_DLI =        13,
246     AF_LAT =        14,
247     AF_HYLINK =     15,
248     AF_APPLETALK =  16,
249     AF_NETBIOS =    17,
250     AF_VOICEVIEW =  18,
251     AF_FIREFOX =    19,
252     AF_UNKNOWN1 =   20,
253     AF_BAN =        21,
254     AF_ATM =        22,
255     AF_INET6 =      23,
256     AF_CLUSTER =    24,
257     AF_12844 =      25,
258     AF_IRDA =       26,
259     AF_NETDES =     28,
260 
261     AF_MAX =        29,
262 
263 
264     PF_UNSPEC     = AF_UNSPEC,
265 
266     PF_UNIX =       AF_UNIX,
267     PF_INET =       AF_INET,
268     PF_IMPLINK =    AF_IMPLINK,
269     PF_PUP =        AF_PUP,
270     PF_CHAOS =      AF_CHAOS,
271     PF_NS =         AF_NS,
272     PF_IPX =        AF_IPX,
273     PF_ISO =        AF_ISO,
274     PF_OSI =        AF_OSI,
275     PF_ECMA =       AF_ECMA,
276     PF_DATAKIT =    AF_DATAKIT,
277     PF_CCITT =      AF_CCITT,
278     PF_SNA =        AF_SNA,
279     PF_DECnet =     AF_DECnet,
280     PF_DLI =        AF_DLI,
281     PF_LAT =        AF_LAT,
282     PF_HYLINK =     AF_HYLINK,
283     PF_APPLETALK =  AF_APPLETALK,
284     PF_VOICEVIEW =  AF_VOICEVIEW,
285     PF_FIREFOX =    AF_FIREFOX,
286     PF_UNKNOWN1 =   AF_UNKNOWN1,
287     PF_BAN =        AF_BAN,
288     PF_INET6 =      AF_INET6,
289 
290     PF_MAX        = AF_MAX,
291 }
292 
293 
294 enum: int
295 {
296     SOL_SOCKET = 0xFFFF,
297 }
298 
299 
300 enum: int
301 {
302     SO_DEBUG =        0x0001,
303     SO_ACCEPTCONN =   0x0002,
304     SO_REUSEADDR =    0x0004,
305     SO_KEEPALIVE =    0x0008,
306     SO_DONTROUTE =    0x0010,
307     SO_BROADCAST =    0x0020,
308     SO_USELOOPBACK =  0x0040,
309     SO_LINGER =       0x0080,
310     SO_DONTLINGER =   ~SO_LINGER,
311     SO_OOBINLINE =    0x0100,
312     SO_SNDBUF =       0x1001,
313     SO_RCVBUF =       0x1002,
314     SO_SNDLOWAT =     0x1003,
315     SO_RCVLOWAT =     0x1004,
316     SO_SNDTIMEO =     0x1005,
317     SO_RCVTIMEO =     0x1006,
318     SO_ERROR =        0x1007,
319     SO_TYPE =         0x1008,
320     SO_EXCLUSIVEADDRUSE = ~SO_REUSEADDR,
321 
322     TCP_NODELAY =    1,
323 
324     IP_OPTIONS                  = 1,
325 
326     IP_HDRINCL                  = 2,
327     IP_TOS                      = 3,
328     IP_TTL                      = 4,
329     IP_MULTICAST_IF             = 9,
330     IP_MULTICAST_TTL            = 10,
331     IP_MULTICAST_LOOP           = 11,
332     IP_ADD_MEMBERSHIP           = 12,
333     IP_DROP_MEMBERSHIP          = 13,
334     IP_DONTFRAGMENT             = 14,
335     IP_ADD_SOURCE_MEMBERSHIP    = 15,
336     IP_DROP_SOURCE_MEMBERSHIP   = 16,
337     IP_BLOCK_SOURCE             = 17,
338     IP_UNBLOCK_SOURCE           = 18,
339     IP_PKTINFO                  = 19,
340 
341     IPV6_UNICAST_HOPS =    4,
342     IPV6_MULTICAST_IF =    9,
343     IPV6_MULTICAST_HOPS =  10,
344     IPV6_MULTICAST_LOOP =  11,
345     IPV6_ADD_MEMBERSHIP =  12,
346     IPV6_DROP_MEMBERSHIP = 13,
347     IPV6_JOIN_GROUP =      IPV6_ADD_MEMBERSHIP,
348     IPV6_LEAVE_GROUP =     IPV6_DROP_MEMBERSHIP,
349     IPV6_V6ONLY = 27,
350 }
351 
352 
353 /// Default FD_SETSIZE value.
354 /// In C/C++, it is redefinable by #define-ing the macro before #include-ing
355 /// winsock.h. In D, use the $(D FD_CREATE) function to allocate a $(D fd_set)
356 /// of an arbitrary size.
357 enum int FD_SETSIZE = 64;
358 
359 
360 struct fd_set_custom(uint SETSIZE)
361 {
362     uint fd_count;
363     SOCKET[SETSIZE] fd_array;
364 }
365 
366 alias fd_set = fd_set_custom!FD_SETSIZE;
367 
368 // Removes.
369 void FD_CLR(SOCKET fd, fd_set* set) pure @nogc
370 {
371     uint c = set.fd_count;
372     SOCKET* start = set.fd_array.ptr;
373     SOCKET* stop = start + c;
374 
375     for (; start != stop; start++)
376     {
377         if (*start == fd)
378             goto found;
379     }
380     return; //not found
381 
382     found:
383     for (++start; start != stop; start++)
384     {
385         *(start - 1) = *start;
386     }
387 
388     set.fd_count = c - 1;
389 }
390 
391 
392 // Tests.
393 int FD_ISSET(SOCKET fd, const(fd_set)* set) pure @nogc
394 {
395 const(SOCKET)* start = set.fd_array.ptr;
396 const(SOCKET)* stop = start + set.fd_count;
397 
398     for (; start != stop; start++)
399     {
400         if (*start == fd)
401             return true;
402     }
403     return false;
404 }
405 
406 
407 // Adds.
408 void FD_SET(SOCKET fd, fd_set* set)     pure @nogc
409 {
410     uint c = set.fd_count;
411     set.fd_array.ptr[c] = fd;
412     set.fd_count = c + 1;
413 }
414 
415 
416 // Resets to zero.
417 void FD_ZERO(fd_set* set) pure @nogc
418 {
419     set.fd_count = 0;
420 }
421 
422 
423 /// Creates a new $(D fd_set) with the specified capacity.
424 fd_set* FD_CREATE(uint capacity) pure
425 {
426     // Take into account alignment (SOCKET may be 64-bit and require 64-bit alignment on 64-bit systems)
427     size_t size = (fd_set_custom!1).sizeof - SOCKET.sizeof + (SOCKET.sizeof * capacity);
428     auto data = new ubyte[size];
429     auto set = cast(fd_set*)data.ptr;
430     FD_ZERO(set);
431     return set;
432 }
433 
434 struct linger
435 {
436     ushort l_onoff;
437     ushort l_linger;
438 }
439 
440 
441 struct protoent
442 {
443     char* p_name;
444     char** p_aliases;
445     short p_proto;
446 }
447 
448 
449 struct servent
450 {
451     char* s_name;
452     char** s_aliases;
453 
454     version (Win64)
455     {
456         char* s_proto;
457         short s_port;
458     }
459     else version (Win32)
460     {
461         short s_port;
462         char* s_proto;
463     }
464 }
465 
466 
467 /+
468 union in6_addr
469 {
470     private union _u_t
471     {
472         ubyte[16] Byte;
473         ushort[8] Word;
474     }
475     _u_t u;
476 }
477 
478 
479 struct in_addr6
480 {
481     ubyte[16] s6_addr;
482 }
483 +/
484 
485 @safe pure @nogc
486 {
487     ushort htons(ushort x);
488     uint htonl(uint x);
489     ushort ntohs(ushort x);
490     uint ntohl(uint x);
491 }
492 
493 
494 enum: int
495 {
496     SOCK_STREAM =     1,
497     SOCK_DGRAM =      2,
498     SOCK_RAW =        3,
499     SOCK_RDM =        4,
500     SOCK_SEQPACKET =  5,
501 }
502 
503 
504 enum: int
505 {
506     IPPROTO_IP =    0,
507     IPPROTO_ICMP =  1,
508     IPPROTO_IGMP =  2,
509     IPPROTO_GGP =   3,
510     IPPROTO_TCP =   6,
511     IPPROTO_PUP =   12,
512     IPPROTO_UDP =   17,
513     IPPROTO_IDP =   22,
514     IPPROTO_IPV6 =  41,
515     IPPROTO_ND =    77,
516     IPPROTO_RAW =   255,
517 
518     IPPROTO_MAX =   256,
519 }
520 
521 
522 enum: int
523 {
524     MSG_OOB =        0x1,
525     MSG_PEEK =       0x2,
526     MSG_DONTROUTE =  0x4
527 }
528 
529 
530 enum: int
531 {
532     SD_RECEIVE =  0,
533     SD_SEND =     1,
534     SD_BOTH =     2,
535 }
536 
537 
538 enum: uint
539 {
540     INADDR_ANY =        0,
541     INADDR_LOOPBACK =   0x7F000001,
542     INADDR_BROADCAST =  0xFFFFFFFF,
543     INADDR_NONE =       0xFFFFFFFF,
544     ADDR_ANY =          INADDR_ANY,
545 }
546 
547 
548 enum: int
549 {
550     AI_PASSIVE = 0x1,
551     AI_CANONNAME = 0x2,
552     AI_NUMERICHOST = 0x4,
553     AI_ADDRCONFIG = 0x0400,
554     AI_NON_AUTHORITATIVE = 0x04000,
555     AI_SECURE = 0x08000,
556     AI_RETURN_PREFERRED_NAMES = 0x010000,
557 }
558 
559 
560 struct timeval
561 {
562     int tv_sec;
563     int tv_usec;
564 }
565 
566 
567 union in_addr
568 {
569     private union _S_un_t
570     {
571         private struct _S_un_b_t
572         {
573             ubyte s_b1, s_b2, s_b3, s_b4;
574         }
575         _S_un_b_t S_un_b;
576 
577         private struct _S_un_w_t
578         {
579             ushort s_w1, s_w2;
580         }
581         _S_un_w_t S_un_w;
582 
583         uint S_addr;
584     }
585     _S_un_t S_un;
586 
587     uint s_addr;
588 
589     struct
590     {
591         ubyte s_net, s_host;
592 
593         union
594         {
595             ushort s_imp;
596 
597             struct
598             {
599                 ubyte s_lh, s_impno;
600             }
601         }
602     }
603 }
604 
605 
606 union in6_addr
607 {
608     private union _in6_u_t
609     {
610         ubyte[16] u6_addr8;
611         ushort[8] u6_addr16;
612         uint[4] u6_addr32;
613     }
614     _in6_u_t in6_u;
615 
616     ubyte[16] s6_addr8;
617     ushort[8] s6_addr16;
618     uint[4] s6_addr32;
619 
620     alias s6_addr = s6_addr8;
621 }
622 
623 
624 enum in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
625 enum in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
626 //alias IN6ADDR_ANY_INIT = IN6ADDR_ANY;
627 //alias IN6ADDR_LOOPBACK_INIT = IN6ADDR_LOOPBACK;
628 
629 enum int INET_ADDRSTRLEN = 16;
630 enum int INET6_ADDRSTRLEN = 46;
631 
632 
633 
634 
635 struct sockaddr
636 {
637     short sa_family;
638     ubyte[14] sa_data;
639 }
640 alias sockaddr SOCKADDR;
641 alias SOCKADDR* PSOCKADDR, LPSOCKADDR;
642 
643 struct sockaddr_storage
644 {
645     short     ss_family;
646     char[6]   __ss_pad1 = void;
647     long      __ss_align;
648     char[112] __ss_pad2 = void;
649 }
650 alias sockaddr_storage SOCKADDR_STORAGE;
651 alias SOCKADDR_STORAGE* PSOCKADDR_STORAGE;
652 
653 struct sockaddr_in
654 {
655     short sin_family = AF_INET;
656     ushort sin_port;
657     in_addr sin_addr;
658     ubyte[8] sin_zero;
659 }
660 alias sockaddr_in SOCKADDR_IN;
661 alias SOCKADDR_IN* PSOCKADDR_IN, LPSOCKADDR_IN;
662 
663 
664 struct sockaddr_in6
665 {
666     short sin6_family = AF_INET6;
667     ushort sin6_port;
668     uint sin6_flowinfo;
669     in6_addr sin6_addr;
670     uint sin6_scope_id;
671 }
672 
673 
674 struct addrinfo
675 {
676     int ai_flags;
677     int ai_family;
678     int ai_socktype;
679     int ai_protocol;
680     size_t ai_addrlen;
681     char* ai_canonname;
682     sockaddr* ai_addr;
683     addrinfo* ai_next;
684 }
685 
686 
687 struct hostent
688 {
689     char* h_name;
690     char** h_aliases;
691     short h_addrtype;
692     short h_length;
693     char** h_addr_list;
694 
695 
696     char* h_addr() @safe pure nothrow @nogc
697     {
698         return h_addr_list[0];
699     }
700 }
701 
702 // Note: These are Winsock2!!
703 struct WSAOVERLAPPED;
704 alias LPWSAOVERLAPPED = WSAOVERLAPPED*;
705 alias LPWSAOVERLAPPED_COMPLETION_ROUTINE = void function(uint, uint, LPWSAOVERLAPPED, uint);
706 int WSAIoctl(SOCKET s, uint dwIoControlCode,
707     void* lpvInBuffer, uint cbInBuffer,
708     void* lpvOutBuffer, uint cbOutBuffer,
709     uint* lpcbBytesReturned,
710     LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
711 
712 
713 enum IOC_VENDOR = 0x18000000;
714 enum SIO_KEEPALIVE_VALS = IOC_IN | IOC_VENDOR | 4;
715 
716 /* Argument structure for SIO_KEEPALIVE_VALS */
717 struct tcp_keepalive
718 {
719     uint onoff;
720     uint keepalivetime;
721     uint keepaliveinterval;
722 }