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