1 /***********************************************************************\
2 *                               winsock.d                               *
3 *                                                                       *
4 *                       Windows API header module                       *
5 *                                                                       *
6 *                 Translated from MinGW Windows headers                 *
7 *                           by Stewart Gordon                           *
8 \***********************************************************************/
9 module win32.winsock;
10 
11 /*
12   Definitions for winsock 1.1
13 
14   Portions Copyright (c) 1980, 1983, 1988, 1993
15   The Regents of the University of California.  All rights reserved.
16 
17   Portions Copyright (c) 1993 by Digital Equipment Corporation.
18  */
19 
20 /*	DRK: This module should not be included if -version=Win32_Winsock2 has
21  *	been set.  If it has, assert.  I think it's better that way than letting
22  *	the user believe that it's worked.
23  *
24  *	SG: It has now been changed so that winsock2 is the default, and
25  *	-version=Win32_Winsock1 must be set to use winsock.
26  */
27 version(Win32_Winsock1) {}
28 else {
29     pragma(msg, "Cannot use win32.winsock without "
30 			~ "Win32_Winsock1 defined.");
31     static assert(false);
32 }
33 
34 import win32.windef;
35 
36 alias char u_char;
37 alias ushort u_short;
38 alias uint u_int, u_long, SOCKET;
39 
40 const size_t FD_SETSIZE = 64;
41 
42 // shutdown() how types
43 enum : int {
44 	SD_RECEIVE,
45 	SD_SEND,
46 	SD_BOTH
47 }
48 
49 struct FD_SET {
50 	u_int              fd_count;
51 	SOCKET[FD_SETSIZE] fd_array;
52 
53 	static void opCall(SOCKET fd, FD_SET* set) {
54 		if (set.fd_count < FD_SETSIZE) set.fd_array[set.fd_count++] = fd;
55 	}
56 }
57 alias FD_SET* PFD_SET, LPFD_SET;
58 
59 extern(Pascal) int __WSAFDIsSet(SOCKET, FD_SET*);
60 alias __WSAFDIsSet FD_ISSET;
61 
62 void FD_CLR(SOCKET fd, FD_SET* set) {
63 	for (u_int i = 0; i < set.fd_count; i++) {
64 		if (set.fd_array[i] == fd) {
65 			while (i < set.fd_count - 1) {
66 				set.fd_array[i] = set.fd_array[i+1];
67 				i++;
68 			}
69 			set.fd_count--;
70 			break;
71 		}
72 	}
73 }
74 
75 /+void FD_SET(SOCKET fd, FD_SET* set) {
76 	if (set.fd_count < FD_SETSIZE) set.fd_array[set.fd_count++] = fd;
77 }+/
78 
79 void FD_ZERO(FD_SET* set) {
80 	set.fd_count = 0;
81 }
82 
83 
84 struct TIMEVAL {
85 	int tv_sec;
86 	int tv_usec;
87 
88 	int opCmp(TIMEVAL tv) {
89 		if (tv_sec < tv.tv_sec)   return -1;
90 		if (tv_sec > tv.tv_sec)   return  1;
91 		if (tv_usec < tv.tv_usec) return -1;
92 		if (tv_usec > tv.tv_usec) return  1;
93 		return 0;
94 	}
95 }
96 alias TIMEVAL* PTIMEVAL, LPTIMEVAL;
97 
98 bool timerisset(TIMEVAL tvp) {
99 	return tvp.tv_sec || tvp.tv_usec;
100 }
101 
102 void timerclear(ref TIMEVAL tvp) {
103 	tvp.tv_sec = tvp.tv_usec = 0;
104 }
105 
106 struct HOSTENT {
107 	char*  h_name;
108 	char** h_aliases;
109 	short  h_addrtype;
110 	short  h_length;
111 	char** h_addr_list;
112 
113 	char* h_addr() { return h_addr_list[0]; }
114 	char* h_addr(char* h) { return h_addr_list[0] = h; }
115 }
116 alias HOSTENT* PHOSTENT, LPHOSTENT;
117 
118 struct LINGER {
119 	u_short l_onoff;
120 	u_short l_linger;
121 }
122 alias LINGER* PLINGER, LPLINGER;
123 
124 // TOTHINKABOUT: do we need these, or are they just for internal use?
125 /+
126 #define IOCPARM_MASK	0x7f
127 #define IOC_VOID	0x20000000
128 #define IOC_OUT	0x40000000
129 #define IOC_IN	0x80000000
130 #define IOC_INOUT	(IOC_IN|IOC_OUT)
131 
132 #define _IO(x,y)	(IOC_VOID|((x)<<8)|(y))
133 #define _IOR(x,y,t)	(IOC_OUT|(((int)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
134 #define _IOW(x,y,t)	(IOC_IN|(((int)sizeof(t)&IOCPARM_MASK)<<16)|((x)<<8)|(y))
135 
136 #define FIONBIO	_IOW('f', 126, u_long)
137 #define FIONREAD	_IOR('f', 127, u_long)
138 #define FIOASYNC	_IOW('f', 125, u_long)
139 #define SIOCSHIWAT	_IOW('s',  0, u_long)
140 #define SIOCGHIWAT	_IOR('s',  1, u_long)
141 #define SIOCSLOWAT	_IOW('s',  2, u_long)
142 #define SIOCGLOWAT	_IOR('s',  3, u_long)
143 #define SIOCATMARK	_IOR('s',  7, u_long)
144 +/
145 
146 enum : DWORD {
147 	FIONBIO    = 0x8004667E,
148 	FIONREAD   = 0x4004667F,
149 	FIOASYNC   = 0x8004667D,
150 	SIOCSHIWAT = 0x80047300,
151 	SIOCGHIWAT = 0x40047301,
152 	SIOCSLOWAT = 0x80047302,
153 	SIOCGLOWAT = 0x40047303,
154 	SIOCATMARK = 0x40047307
155 }
156 
157 struct netent {
158 	char*  n_name;
159 	char** n_aliases;
160 	short  n_addrtype;
161 	u_long n_net;
162 }
163 
164 struct SERVENT {
165 	char*  s_name;
166 	char** s_aliases;
167 	short  s_port;
168 	char*  s_proto;
169 }
170 alias SERVENT* PSERVENT, LPSERVENT;
171 
172 struct PROTOENT {
173 	char*  p_name;
174 	char** p_aliases;
175 	short  p_proto;
176 }
177 alias PROTOENT* PPROTOENT, LPPROTOENT;
178 
179 enum : int {
180 	IPPROTO_IP   =   0,
181 	IPPROTO_ICMP =   1,
182 	IPPROTO_IGMP =   2,
183 	IPPROTO_GGP  =   3,
184 	IPPROTO_TCP  =   6,
185 	IPPROTO_PUP  =  12,
186 	IPPROTO_UDP  =  17,
187 	IPPROTO_IDP  =  22,
188 	IPPROTO_ND   =  77,
189 	IPPROTO_RAW  = 255,
190 	IPPROTO_MAX  = 256
191 }
192 
193 // These are not documented on the MSDN site
194 enum {
195 	IPPORT_ECHO        =    7,
196 	IPPORT_DISCARD     =    9,
197 	IPPORT_SYSTAT      =   11,
198 	IPPORT_DAYTIME     =   13,
199 	IPPORT_NETSTAT     =   15,
200 	IPPORT_FTP         =   21,
201 	IPPORT_TELNET      =   23,
202 	IPPORT_SMTP        =   25,
203 	IPPORT_TIMESERVER  =   37,
204 	IPPORT_NAMESERVER  =   42,
205 	IPPORT_WHOIS       =   43,
206 	IPPORT_MTP         =   57,
207 	IPPORT_TFTP        =   69,
208 	IPPORT_RJE         =   77,
209 	IPPORT_FINGER      =   79,
210 	IPPORT_TTYLINK     =   87,
211 	IPPORT_SUPDUP      =   95,
212 	IPPORT_EXECSERVER  =  512,
213 	IPPORT_LOGINSERVER =  513,
214 	IPPORT_CMDSERVER   =  514,
215 	IPPORT_EFSSERVER   =  520,
216 	IPPORT_BIFFUDP     =  512,
217 	IPPORT_WHOSERVER   =  513,
218 	IPPORT_ROUTESERVER =  520,
219 	IPPORT_RESERVED    = 1024
220 }
221 
222 // These are not documented on the MSDN site
223 enum {
224 	IMPLINK_IP        = 155,
225 	IMPLINK_LOWEXPER  = 156,
226 	IMPLINK_HIGHEXPER = 158
227 }
228 
229 struct IN_ADDR {
230 	union {
231 		struct { u_char s_net, s_host, s_lh, s_impno; }
232 		struct { u_short s_w1, s_imp; }
233 		u_long s_addr;
234 	}
235 }
236 alias IN_ADDR* PIN_ADDR, LPIN_ADDR;
237 
238 // IN_CLASSx are not used anywhere or documented on MSDN.
239 bool IN_CLASSA(int i) {
240 	return (i & 0x80000000) == 0;
241 }
242 
243 const IN_CLASSA_NET    = 0xff000000;
244 const IN_CLASSA_NSHIFT =  24;
245 const IN_CLASSA_HOST   = 0x00ffffff;
246 const IN_CLASSA_MAX    = 128;
247 
248 bool IN_CLASSB(int i) {
249 	return (i & 0xC0000000) == 0x80000000;
250 }
251 
252 const IN_CLASSB_NET    = 0xffff0000;
253 const IN_CLASSB_NSHIFT = 16;
254 const IN_CLASSB_HOST   = 0x0000ffff;
255 const IN_CLASSB_MAX    = 65536;
256 
257 bool IN_CLASSC(int i) {
258 	return (i & 0xE0000000) == 0xC0000000;
259 }
260 
261 const IN_CLASSC_NET    = 0xffffff00;
262 const IN_CLASSC_NSHIFT = 8;
263 const IN_CLASSC_HOST   = 0x000000ff;
264 
265 const u_long
266 	INADDR_ANY       = 0,
267 	INADDR_LOOPBACK  = 0x7F000001,
268 	INADDR_BROADCAST = 0xFFFFFFFF,
269 	INADDR_NONE      = 0xFFFFFFFF;
270 
271 struct SOCKADDR_IN {
272 	short   sin_family;
273 	u_short sin_port;
274 	IN_ADDR sin_addr;
275 	char[8] sin_zero;
276 }
277 alias SOCKADDR_IN* PSOCKADDR_IN, LPSOCKADDR_IN;
278 
279 const size_t
280 	WSADESCRIPTION_LEN = 256,
281 	WSASYS_STATUS_LEN  = 128;
282 
283 struct WSADATA {
284 	WORD   wVersion;
285 	WORD   wHighVersion;
286 	char[WSADESCRIPTION_LEN+1] szDescription;
287 	char[WSASYS_STATUS_LEN+1]  szSystemStatus;
288 	ushort iMaxSockets;
289 	ushort iMaxUdpDg;
290 	char*  lpVendorInfo;
291 }
292 alias WSADATA* LPWSADATA;
293 
294 // This is not documented on the MSDN site
295 const IP_OPTIONS = 1;
296 
297 const int
298 	SO_DEBUG       =   1,
299 	SO_ACCEPTCONN  =   2,
300 	SO_REUSEADDR   =   4,
301 	SO_KEEPALIVE   =   8,
302 	SO_DONTROUTE   =  16,
303 	SO_BROADCAST   =  32,
304 	SO_USELOOPBACK =  64,
305 	SO_LINGER      = 128,
306 	SO_OOBINLINE   = 256,
307 	SO_DONTLINGER  = ~SO_LINGER;
308 
309 enum : int {
310 	SO_SNDBUF = 0x1001,
311 	SO_RCVBUF,
312 	SO_SNDLOWAT,
313 	SO_RCVLOWAT,
314 	SO_SNDTIMEO,
315 	SO_RCVTIMEO,
316 	SO_ERROR,
317 	SO_TYPE // = 0x1008
318 }
319 
320 /*
321  * Note that the next 5 IP defines are specific to WinSock 1.1 (wsock32.dll).
322  * They will cause errors or unexpected results if used with the
323  * (gs)etsockopts exported from the WinSock 2 lib, ws2_32.dll. Refer ws2tcpip.h.
324  */
325 enum : int {
326 	IP_MULTICAST_IF = 2,
327 	IP_MULTICAST_TTL,
328 	IP_MULTICAST_LOOP,
329 	IP_ADD_MEMBERSHIP,
330 	IP_DROP_MEMBERSHIP
331 }
332 
333 // These are not documented on the MSDN site
334 const IP_DEFAULT_MULTICAST_TTL  =  1;
335 const IP_DEFAULT_MULTICAST_LOOP =  1;
336 const IP_MAX_MEMBERSHIPS        = 20;
337 
338 struct ip_mreq {
339 	IN_ADDR imr_multiaddr;
340 	IN_ADDR imr_interface;
341 }
342 
343 const SOCKET INVALID_SOCKET = uint.max;
344 const int SOCKET_ERROR = -1;
345 
346 enum : int {
347 	SOCK_STREAM = 1,
348 	SOCK_DGRAM,
349 	SOCK_RAW,
350 	SOCK_RDM,
351 	SOCK_SEQPACKET
352 }
353 
354 const int TCP_NODELAY = 1;
355 
356 enum : int {
357 	AF_UNSPEC,
358 	AF_UNIX,
359 	AF_INET,
360 	AF_IMPLINK,
361 	AF_PUP,
362 	AF_CHAOS,
363 	AF_IPX,  // =  6
364 	AF_NS       =  6,
365 	AF_ISO,
366 	AF_OSI      = AF_ISO,
367 	AF_ECMA,
368 	AF_DATAKIT,
369 	AF_CCITT,
370 	AF_SNA,
371 	AF_DECnet,
372 	AF_DLI,
373 	AF_LAT,
374 	AF_HYLINK,
375 	AF_APPLETALK,
376 	AF_NETBIOS,
377 	AF_VOICEVIEW,
378 	AF_FIREFOX,
379 	AF_UNKNOWN1,
380 	AF_BAN,
381 	AF_ATM,
382 	AF_INET6,
383 	AF_MAX  // = 24
384 }
385 
386 struct SOCKADDR {
387 	u_short  sa_family;
388 	char[14] sa_data;
389 }
390 alias SOCKADDR* PSOCKADDR, LPSOCKADDR;
391 
392 struct sockproto {
393 	u_short sp_family;
394 	u_short sp_protocol;
395 }
396 
397 enum : int {
398 	PF_UNSPEC    = AF_UNSPEC,
399 	PF_UNIX      = AF_UNIX,
400 	PF_INET      = AF_INET,
401 	PF_IMPLINK   = AF_IMPLINK,
402 	PF_PUP       = AF_PUP,
403 	PF_CHAOS     = AF_CHAOS,
404 	PF_NS        = AF_NS,
405 	PF_IPX       = AF_IPX,
406 	PF_ISO       = AF_ISO,
407 	PF_OSI       = AF_OSI,
408 	PF_ECMA      = AF_ECMA,
409 	PF_DATAKIT   = AF_DATAKIT,
410 	PF_CCITT     = AF_CCITT,
411 	PF_SNA       = AF_SNA,
412 	PF_DECnet    = AF_DECnet,
413 	PF_DLI       = AF_DLI,
414 	PF_LAT       = AF_LAT,
415 	PF_HYLINK    = AF_HYLINK,
416 	PF_APPLETALK = AF_APPLETALK,
417 	PF_VOICEVIEW = AF_VOICEVIEW,
418 	PF_FIREFOX   = AF_FIREFOX,
419 	PF_UNKNOWN1  = AF_UNKNOWN1,
420 	PF_BAN       = AF_BAN,
421 	PF_ATM       = AF_ATM,
422 	PF_INET6     = AF_INET6,
423 	PF_MAX       = AF_MAX
424 }
425 
426 const int SOL_SOCKET = 0xFFFF;
427 
428 const int SOMAXCONN = 5;
429 
430 const int
431 	MSG_OOB       = 1,
432 	MSG_PEEK      = 2,
433 	MSG_DONTROUTE = 4,
434 	MSG_MAXIOVLEN = 16,
435 	MSG_PARTIAL   = 0x8000;
436 
437 const size_t MAXGETHOSTSTRUCT = 1024;
438 
439 const int
440 	FD_READ    =  1,
441 	FD_WRITE   =  2,
442 	FD_OOB     =  4,
443 	FD_ACCEPT  =  8,
444 	FD_CONNECT = 16,
445 	FD_CLOSE   = 32;
446 
447 enum : int {
448 	WSABASEERR         = 10000,
449 	WSAEINTR           = 10004,
450 	WSAEBADF           = 10009,
451 	WSAEACCES          = 10013,
452 	WSAEFAULT          = 10014,
453 	WSAEINVAL          = 10022,
454 	WSAEMFILE          = 10024,
455 	WSAEWOULDBLOCK     = 10035,
456 	WSAEINPROGRESS     = 10036,
457 	WSAEALREADY        = 10037,
458 	WSAENOTSOCK        = 10038,
459 	WSAEDESTADDRREQ    = 10039,
460 	WSAEMSGSIZE        = 10040,
461 	WSAEPROTOTYPE      = 10041,
462 	WSAENOPROTOOPT     = 10042,
463 	WSAEPROTONOSUPPORT = 10043,
464 	WSAESOCKTNOSUPPORT = 10044,
465 	WSAEOPNOTSUPP      = 10045,
466 	WSAEPFNOSUPPORT    = 10046,
467 	WSAEAFNOSUPPORT    = 10047,
468 	WSAEADDRINUSE      = 10048,
469 	WSAEADDRNOTAVAIL   = 10049,
470 	WSAENETDOWN        = 10050,
471 	WSAENETUNREACH     = 10051,
472 	WSAENETRESET       = 10052,
473 	WSAECONNABORTED    = 10053,
474 	WSAECONNRESET      = 10054,
475 	WSAENOBUFS         = 10055,
476 	WSAEISCONN         = 10056,
477 	WSAENOTCONN        = 10057,
478 	WSAESHUTDOWN       = 10058,
479 	WSAETOOMANYREFS    = 10059,
480 	WSAETIMEDOUT       = 10060,
481 	WSAECONNREFUSED    = 10061,
482 	WSAELOOP           = 10062,
483 	WSAENAMETOOLONG    = 10063,
484 	WSAEHOSTDOWN       = 10064,
485 	WSAEHOSTUNREACH    = 10065,
486 	WSAENOTEMPTY       = 10066,
487 	WSAEPROCLIM        = 10067,
488 	WSAEUSERS          = 10068,
489 	WSAEDQUOT          = 10069,
490 	WSAESTALE          = 10070,
491 	WSAEREMOTE         = 10071,
492 	WSAEDISCON         = 10101,
493 	WSASYSNOTREADY     = 10091,
494 	WSAVERNOTSUPPORTED = 10092,
495 	WSANOTINITIALISED  = 10093,
496 	WSAHOST_NOT_FOUND  = 11001,
497 	WSATRY_AGAIN       = 11002,
498 	WSANO_RECOVERY     = 11003,
499 	WSANO_DATA         = 11004,
500 	WSANO_ADDRESS      = WSANO_DATA
501 }
502 
503 alias WSAGetLastError h_errno;
504 
505 enum : int {
506 	HOST_NOT_FOUND = WSAHOST_NOT_FOUND,
507 	TRY_AGAIN      = WSATRY_AGAIN,
508 	NO_RECOVERY    = WSANO_RECOVERY,
509 	NO_DATA        = WSANO_DATA,
510 	NO_ADDRESS     = WSANO_ADDRESS
511 }
512 
513 extern (Pascal) {
514 	SOCKET accept(SOCKET, SOCKADDR*, int*);
515 	int bind(SOCKET, const(SOCKADDR)*, int);
516 	int closesocket(SOCKET);
517 	int connect(SOCKET, const(SOCKADDR)*, int);
518 	int ioctlsocket(SOCKET, int, u_long*);
519 	int getpeername(SOCKET, SOCKADDR*, int*);
520 	int getsockname(SOCKET, SOCKADDR*, int*);
521 	int getsockopt(SOCKET, int, int, char*, int*);
522 	uint inet_addr(const(char)*);
523 	int listen(SOCKET, int);
524 	int recv(SOCKET, char*, int, int);
525 	int recvfrom(SOCKET, char*, int, int, SOCKADDR*, int*);
526 	int send(SOCKET, const(char)*, int, int);
527 	int sendto(SOCKET, const(char)*, int, int, const(SOCKADDR)*, int);
528 	int setsockopt(SOCKET, int, int, const(char)*, int);
529 	int shutdown(SOCKET, int);
530 	SOCKET socket(int, int, int);
531 	int WSAStartup(WORD, LPWSADATA);
532 	int WSACleanup();
533 	void WSASetLastError(int);
534 	int WSAGetLastError();
535 	BOOL WSAIsBlocking();
536 	int WSAUnhookBlockingHook();
537 	FARPROC WSASetBlockingHook(FARPROC);
538 	int WSACancelBlockingCall();
539 	HANDLE WSAAsyncGetServByName(HWND, u_int, const(char)*, const(char)*, char*, int);
540 	HANDLE WSAAsyncGetServByPort(HWND, u_int, int, const(char)*, char*, int);
541 	HANDLE WSAAsyncGetProtoByName(HWND, u_int, const(char)*, char*, int);
542 	HANDLE WSAAsyncGetProtoByNumber(HWND, u_int, int, char*, int);
543 	HANDLE WSAAsyncGetHostByName(HWND, u_int, const(char)*, char*, int);
544 	HANDLE WSAAsyncGetHostByAddr(HWND, u_int, const(char)*, int, int, char*, int);
545 	int WSACancelAsyncRequest(HANDLE);
546 	int WSAAsyncSelect(SOCKET, HWND, u_int, int);
547 	u_long htonl(u_long);
548 	u_long ntohl(u_long);
549 	u_short htons(u_short);
550 	u_short ntohs(u_short);
551 	int select(int nfds, FD_SET*, FD_SET*, FD_SET*, const(TIMEVAL)*);
552 	int gethostname(char*, int);
553 }
554 
555 extern (Windows) {
556 	char* inet_ntoa(IN_ADDR);
557 	HOSTENT* gethostbyaddr(const(char)*, int, int);
558 	HOSTENT* gethostbyname(const(char)*);
559 	SERVENT* getservbyport(int, const(char)*);
560 	SERVENT* getservbyname(const(char)*, const(char)*);
561 	PROTOENT* getprotobynumber(int);
562 	PROTOENT* getprotobyname(const(char)*);
563 }
564 
565 alias MAKELONG WSAMAKEASYNCREPLY, WSAMAKESELECTREPLY;
566 alias LOWORD WSAGETASYNCBUFLEN, WSAGETSELECTEVENT;
567 alias HIWORD WSAGETASYNCERROR, WSAGETSELECTERROR;
568 
569 
570 /*
571  * Recent MSDN docs indicate that the MS-specific extensions exported from
572  * mswsock.dll (AcceptEx, TransmitFile. WSARecEx and GetAcceptExSockaddrs) are
573  * declared in mswsock.h. These extensions are not supported on W9x or WinCE.
574  * However, code using WinSock 1.1 API may expect the declarations and
575  * associated defines to be in this header. Thus we include mswsock.h here.
576  *
577  * When linking against the WinSock 1.1 lib, wsock32.dll, the mswsock functions
578  * are automatically routed to mswsock.dll (on platforms with support).
579  * The WinSock 2 lib, ws2_32.dll, does not contain any references to
580  * the mswsock extensions.
581  */
582 
583 import win32.mswsock;