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