]> gitweb.factorcode.org Git - factor.git/blob - basis/windows/winsock/winsock.factor
Fix comments to be ! not #!.
[factor.git] / basis / windows / winsock / winsock.factor
1 ! Copyright (C) 2006 Mackenzie Straight, Doug Coleman.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: accessors alien alien.c-types alien.data alien.strings
4 alien.syntax arrays byte-arrays classes.struct grouping init
5 io.encodings.utf16n kernel literals math math.bitwise
6 math.parser sequences system vocabs.parser windows.com.syntax
7 windows.errors windows.kernel32 windows.types ;
8 FROM: alien.c-types => short ;
9 IN: windows.winsock
10
11 <<
12 ! Some differences between Win32 and Win64
13 cpu x86.64? "windows.winsock.64" "windows.winsock.32" ? use-vocab
14 >>
15
16 TYPEDEF: int* SOCKET
17
18 : <wsadata> ( -- byte-array )
19     0x190 <byte-array> ;
20
21 CONSTANT: SOCK_STREAM    1
22 CONSTANT: SOCK_DGRAM     2
23 CONSTANT: SOCK_RAW       3
24 CONSTANT: SOCK_RDM       4
25 CONSTANT: SOCK_SEQPACKET 5
26
27 CONSTANT: SO_DEBUG       0x1
28 CONSTANT: SO_ACCEPTCONN  0x2
29 CONSTANT: SO_REUSEADDR   0x4
30 CONSTANT: SO_KEEPALIVE   0x8
31 CONSTANT: SO_DONTROUTE   0x10
32 CONSTANT: SO_BROADCAST   0x20
33 CONSTANT: SO_USELOOPBACK 0x40
34 CONSTANT: SO_LINGER      0x80
35 CONSTANT: SO_OOBINLINE   0x100
36 : SO_DONTLINGER ( -- n ) SO_LINGER bitnot ; inline
37
38 CONSTANT: SO_SNDBUF     0x1001
39 CONSTANT: SO_RCVBUF     0x1002
40 CONSTANT: SO_SNDLOWAT   0x1003
41 CONSTANT: SO_RCVLOWAT   0x1004
42 CONSTANT: SO_SNDTIMEO   0x1005
43 CONSTANT: SO_RCVTIMEO   0x1006
44 CONSTANT: SO_ERROR      0x1007
45 CONSTANT: SO_TYPE       0x1008
46
47 CONSTANT: TCP_NODELAY   0x1
48
49 CONSTANT: AF_UNSPEC      0
50 CONSTANT: AF_UNIX        1
51 CONSTANT: AF_INET        2
52 CONSTANT: AF_IMPLINK     3
53 CONSTANT: AF_PUP         4
54 CONSTANT: AF_CHAOS       5
55 CONSTANT: AF_NS          6
56 CONSTANT: AF_ISO         7
57 ALIAS: AF_OSI    AF_ISO
58 CONSTANT: AF_ECMA        8
59 CONSTANT: AF_DATAKIT     9
60 CONSTANT: AF_CCITT      10
61 CONSTANT: AF_SNA        11
62 CONSTANT: AF_DECnet     12
63 CONSTANT: AF_DLI        13
64 CONSTANT: AF_LAT        14
65 CONSTANT: AF_HYLINK     15
66 CONSTANT: AF_APPLETALK  16
67 CONSTANT: AF_NETBIOS    17
68 CONSTANT: AF_MAX        18
69 CONSTANT: AF_INET6      23
70 CONSTANT: AF_IRDA       26
71 CONSTANT: AF_BTM        32
72
73 CONSTANT: PF_UNSPEC      0
74 CONSTANT: PF_LOCAL       1
75 CONSTANT: PF_INET        2
76 CONSTANT: PF_INET6      23
77
78 CONSTANT: AI_PASSIVE     1
79 CONSTANT: AI_CANONNAME   2
80 CONSTANT: AI_NUMERICHOST 4
81
82 CONSTANT: AI_MASK flags{ AI_PASSIVE AI_CANONNAME AI_NUMERICHOST }
83
84 CONSTANT: NI_NUMERICHOST 1
85 CONSTANT: NI_NUMERICSERV 2
86
87 CONSTANT: IPPROTO_TCP    6
88 CONSTANT: IPPROTO_UDP   17
89 CONSTANT: IPPROTO_RM   113
90
91 CONSTANT: FIOASYNC      0x8004667d
92 CONSTANT: FIONBIO       0x8004667e
93 CONSTANT: FIONREAD      0x4004667f
94
95 CONSTANT: WSA_FLAG_OVERLAPPED 1
96 ALIAS: WSA_WAIT_EVENT_0 WAIT_OBJECT_0
97 ALIAS: WSA_MAXIMUM_WAIT_EVENTS MAXIMUM_WAIT_OBJECTS
98 CONSTANT: WSA_INVALID_EVENT f
99 CONSTANT: WSA_WAIT_FAILED -1
100 ALIAS: WSA_WAIT_IO_COMPLETION WAIT_IO_COMPLETION
101 ALIAS: WSA_WAIT_TIMEOUT WAIT_TIMEOUT
102 ALIAS: WSA_INFINITE INFINITE
103 ALIAS: WSA_IO_PENDING ERROR_IO_PENDING
104
105 CONSTANT: INADDR_ANY 0
106
107 : INVALID_SOCKET ( -- n ) -1 <alien> ; inline
108
109 : SOCKET_ERROR ( -- n ) -1 ; inline
110
111 CONSTANT: SD_RECV 0
112 CONSTANT: SD_SEND 1
113 CONSTANT: SD_BOTH 2
114
115 CONSTANT: SOL_SOCKET 0xffff
116
117 C-TYPE: sockaddr
118
119 STRUCT: sockaddr-in
120     { family short }
121     { port ushort }
122     { addr uint }
123     { pad char[8] } ;
124
125 STRUCT: sockaddr-in6
126     { family uchar }
127     { port ushort }
128     { flowinfo uint }
129     { addr uchar[16] }
130     { scopeid uint } ;
131
132 STRUCT: hostent
133     { name c-string }
134     { aliases void* }
135     { addrtype short }
136     { length short }
137     { addr-list void* } ;
138
139 STRUCT: protoent
140     { name c-string }
141     { aliases void* }
142     { proto short } ;
143
144 STRUCT: addrinfo
145     { flags int }
146     { family int }
147     { socktype int }
148     { protocol int }
149     { addrlen size_t }
150     { canonname c-string }
151     { addr sockaddr* }
152     { next addrinfo* } ;
153
154 STRUCT: timeval
155     { sec long }
156     { usec long } ;
157
158 GENERIC: sockaddr>ip ( sockaddr -- string )
159
160 M: sockaddr-in sockaddr>ip ( sockaddr -- string )
161     addr>> uint <ref> [ number>string ] { } map-as "." join ;
162
163 M: sockaddr-in6 sockaddr>ip ( uchar-array -- string )
164     addr>> [ >hex ] { } map-as 2 group [ concat ] map ":" join ;
165
166 STRUCT: fd_set
167     { fd_count uint }
168     { fd_array SOCKET[64] } ;
169
170 LIBRARY: winsock
171
172 FUNCTION: int setsockopt ( SOCKET s, int level, int optname, c-string optval, int optlen )
173 FUNCTION: int ioctlsocket ( SOCKET s, long cmd, ulong* *argp )
174
175 FUNCTION: ushort htons ( ushort n )
176 FUNCTION: ushort ntohs ( ushort n )
177 FUNCTION: int bind ( SOCKET socket, sockaddr-in* sockaddr, int len )
178 FUNCTION: int listen ( SOCKET socket, int backlog )
179 FUNCTION: c-string inet_ntoa ( int in-addr )
180 FUNCTION: int getaddrinfo ( c-string nodename,
181                             c-string servername,
182                             addrinfo* hints,
183                             addrinfo** res )
184
185 FUNCTION: void freeaddrinfo ( addrinfo* ai )
186
187
188 FUNCTION: hostent* gethostbyname ( c-string name )
189 FUNCTION: int gethostname ( c-string name, int len )
190 FUNCTION: SOCKET socket ( int domain, int type, int protocol )
191 FUNCTION: int connect ( SOCKET socket, sockaddr-in* sockaddr, int addrlen )
192 FUNCTION: int select ( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout )
193 FUNCTION: int closesocket ( SOCKET s )
194 FUNCTION: int shutdown ( SOCKET s, int how )
195 FUNCTION: int send ( SOCKET s, c-string buf, int len, int flags )
196 FUNCTION: int recv ( SOCKET s, c-string buf, int len, int flags )
197
198 FUNCTION: int getsockname ( SOCKET s, sockaddr-in* address, int* addrlen )
199 FUNCTION: int getpeername ( SOCKET s, sockaddr-in* address, int* addrlen )
200
201 FUNCTION: protoent* getprotobyname ( c-string name )
202
203 FUNCTION: servent* getservbyname ( c-string name, c-string prot )
204 FUNCTION: servent* getservbyport ( int port, c-string prot )
205
206 TYPEDEF: uint SERVICETYPE
207 TYPEDEF: void* LPWSADATA
208 TYPEDEF: OVERLAPPED WSAOVERLAPPED
209 TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
210 TYPEDEF: uint GROUP
211 TYPEDEF: void* LPCONDITIONPROC
212 TYPEDEF: HANDLE WSAEVENT
213 TYPEDEF: LPHANDLE LPWSAEVENT
214 TYPEDEF: sockaddr* LPSOCKADDR
215
216 STRUCT: FLOWSPEC
217     { TokenRate          uint        }
218     { TokenBucketSize    uint        }
219     { PeakBandwidth      uint        }
220     { Latency            uint        }
221     { DelayVariation     uint        }
222     { ServiceType        SERVICETYPE }
223     { MaxSduSize         uint        }
224     { MinimumPolicedSize uint        } ;
225 TYPEDEF: FLOWSPEC* PFLOWSPEC
226 TYPEDEF: FLOWSPEC* LPFLOWSPEC
227
228 STRUCT: WSABUF
229     { len ulong }
230     { buf void* } ;
231 TYPEDEF: WSABUF* LPWSABUF
232
233 STRUCT: QOS
234     { SendingFlowspec FLOWSPEC }
235     { ReceivingFlowspec FLOWSPEC }
236     { ProviderSpecific WSABUF } ;
237 TYPEDEF: QOS* LPQOS
238
239 CONSTANT: MAX_PROTOCOL_CHAIN 7
240
241 STRUCT: WSAPROTOCOLCHAIN
242     { ChainLen int }
243     { ChainEntries { DWORD 7 } } ;
244     ! { ChainEntries { DWORD MAX_PROTOCOL_CHAIN } } ;
245 TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN
246
247 CONSTANT: WSAPROTOCOL_LEN 255
248
249 STRUCT: WSAPROTOCOL_INFOW
250     { dwServiceFlags1 DWORD }
251     { dwServiceFlags2 DWORD }
252     { dwServiceFlags3 DWORD }
253     { dwServiceFlags4 DWORD }
254     { dwProviderFlags DWORD }
255     { ProviderId GUID }
256     { dwCatalogEntryId DWORD }
257     { ProtocolChain WSAPROTOCOLCHAIN }
258     { iVersion int }
259     { iAddressFamily int }
260     { iMaxSockAddr int }
261     { iMinSockAddr int }
262     { iSocketType int }
263     { iProtocol int }
264     { iProtocolMaxOffset int }
265     { iNetworkByteOrder int }
266     { iSecurityScheme int }
267     { dwMessageSize DWORD }
268     { dwProviderReserved DWORD }
269     { szProtocol { WCHAR 256 } } ;
270     ! { szProtocol[WSAPROTOCOL_LEN+1] { WCHAR 256 } } ;
271 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFOW
272 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFOW
273 TYPEDEF: WSAPROTOCOL_INFOW WSAPROTOCOL_INFO
274 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFO
275 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFO
276
277
278 STRUCT: WSANAMESPACE_INFOW
279     { NSProviderId   GUID    }
280     { dwNameSpace    DWORD   }
281     { fActive        BOOL    }
282     { dwVersion      DWORD   }
283     { lpszIdentifier LPWSTR  } ;
284 TYPEDEF: WSANAMESPACE_INFOW* PWSANAMESPACE_INFOW
285 TYPEDEF: WSANAMESPACE_INFOW* LPWSANAMESPACE_INFOW
286 TYPEDEF: WSANAMESPACE_INFOW WSANAMESPACE_INFO
287 TYPEDEF: WSANAMESPACE_INFO* PWSANAMESPACE_INFO
288 TYPEDEF: WSANAMESPACE_INFO* LPWSANAMESPACE_INFO
289
290 CONSTANT: FD_MAX_EVENTS 10
291
292 STRUCT: WSANETWORKEVENTS
293     { lNetworkEvents long }
294     { iErrorCode { int FD_MAX_EVENTS } } ;
295 TYPEDEF: WSANETWORKEVENTS* PWSANETWORKEVENTS
296 TYPEDEF: WSANETWORKEVENTS* LPWSANETWORKEVENTS
297
298 ! STRUCT: WSAOVERLAPPED
299     ! { Internal DWORD }
300     ! { InternalHigh DWORD }
301     ! { Offset DWORD }
302     ! { OffsetHigh DWORD }
303     ! { hEvent WSAEVENT }
304     ! { bytesTransferred DWORD } ;
305 ! TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
306
307 FUNCTION: SOCKET WSAAccept ( SOCKET s,
308                              sockaddr* addr,
309                              LPINT addrlen,
310                              LPCONDITIONPROC lpfnCondition,
311                              DWORD dwCallbackData )
312
313 ! FUNCTION: INT WSAAddressToString ( LPSOCKADDR lpsaAddress, DWORD dwAddressLength, LPWSAPROTOCOL_INFO lpProtocolInfo, LPTSTR lpszAddressString, LPDWORD lpdwAddressStringLength ) ;
314
315 FUNCTION: int WSACleanup ( )
316 FUNCTION: BOOL WSACloseEvent ( WSAEVENT hEvent )
317
318 FUNCTION: int WSAConnect ( SOCKET s,
319                            sockaddr* name,
320                            int namelen,
321                            LPWSABUF lpCallerData,
322                            LPWSABUF lpCalleeData,
323                            LPQOS lpSQOS,
324                            LPQOS lpGQOS )
325 FUNCTION: WSAEVENT WSACreateEvent ( )
326 ! FUNCTION: INT WSAEnumNameSpaceProviders ( LPDWORD lpdwBufferLength, LPWSANAMESPACE_INFO lpnspBuffer ) ;
327 FUNCTION: int WSAEnumNetworkEvents ( SOCKET s,
328                                      WSAEVENT hEventObject,
329                                      LPWSANETWORKEVENTS lpNetworkEvents )
330 ! FUNCTION: int WSAEnumProtocols ( LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpwdBufferLength ) ;
331
332 FUNCTION: int WSAEventSelect ( SOCKET s,
333                                WSAEVENT hEventObject,
334                                long lNetworkEvents )
335 FUNCTION: int WSAGetLastError ( )
336 FUNCTION: BOOL WSAGetOverlappedResult ( SOCKET s,
337                                         LPWSAOVERLAPPED lpOverlapped,
338                                         LPDWORD lpcbTransfer,
339                                         BOOL fWait,
340                                         LPDWORD lpdwFlags )
341
342 TYPEDEF: void* LPWSAOVERLAPPED_COMPLETION_ROUTINE
343 FUNCTION: int WSAIoctl ( SOCKET s,
344                          DWORD dwIoControlCode,
345                          LPVOID lpvInBuffer,
346                          DWORD cbInBuffer,
347                          LPVOID lpvOutBuffer,
348                          DWORD cbOutBuffer,
349                          LPDWORD lpcbBytesReturned,
350                          LPWSAOVERLAPPED lpOverlapped,
351                          LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
352
353 FUNCTION: int WSARecv ( SOCKET s,
354                         LPWSABUF lpBuffers,
355                         DWORD dwBufferCount,
356                         LPDWORD lpNumberOfBytesRecvd,
357                         LPDWORD lpFlags,
358                         LPWSAOVERLAPPED lpOverlapped,
359                         LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
360
361 FUNCTION: int WSARecvFrom ( SOCKET s,
362                             LPWSABUF lpBuffers,
363                             DWORD dwBufferCount,
364                             LPDWORD lpNumberOfBytesRecvd,
365                             LPDWORD lpFlags,
366                             sockaddr* lpFrom,
367                             LPINT lpFromlen,
368                             LPWSAOVERLAPPED lpOverlapped,
369                             LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
370
371 FUNCTION: BOOL WSAResetEvent ( WSAEVENT hEvent )
372 FUNCTION: int WSASend ( SOCKET s,
373                         LPWSABUF lpBuffers,
374                         DWORD dwBufferCount,
375                         LPDWORD lpNumberOfBytesSent,
376                         LPDWORD lpFlags,
377                         LPWSAOVERLAPPED lpOverlapped,
378                  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
379
380 FUNCTION: int WSASendTo ( SOCKET s,
381                           LPWSABUF lpBuffers,
382                           DWORD dwBufferCount,
383                           LPDWORD lpNumberOfBytesSent,
384                           DWORD dwFlags,
385                           sockaddr* lpTo,
386                           int iToLen,
387                           LPWSAOVERLAPPED lpOverlapped,
388   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine )
389
390 FUNCTION: int WSAStartup ( WORD version,  LPWSADATA out-data )
391
392 FUNCTION: SOCKET WSASocketW ( int af,
393                              int type,
394                              int protocol,
395                              LPWSAPROTOCOL_INFOW lpProtocolInfo,
396                              GROUP g,
397                              DWORD flags )
398 ALIAS: WSASocket WSASocketW
399
400 FUNCTION: DWORD WSAWaitForMultipleEvents ( DWORD cEvents,
401                                            WSAEVENT* lphEvents,
402                                            BOOL fWaitAll,
403                                            DWORD dwTimeout,
404                                            BOOL fAlertable )
405
406
407 LIBRARY: mswsock
408
409 FUNCTION: int AcceptEx ( SOCKET listen,
410                          SOCKET accept,
411                          PVOID out-buf,
412                          DWORD recv-len,
413                          DWORD addr-len,
414                          DWORD remote-len,
415                          LPDWORD out-len,
416                          LPOVERLAPPED overlapped )
417
418 FUNCTION: void GetAcceptExSockaddrs (
419   PVOID lpOutputBuffer,
420   DWORD dwReceiveDataLength,
421   DWORD dwLocalAddressLength,
422   DWORD dwRemoteAddressLength,
423   LPSOCKADDR* LocalSockaddr,
424   LPINT LocalSockaddrLength,
425   LPSOCKADDR* RemoteSockaddr,
426   LPINT RemoteSockaddrLength
427 )
428
429 CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090
430
431 CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
432
433 ERROR: winsock-exception n string ;
434
435 : winsock-expected-error? ( n -- ? )
436     ${ ERROR_IO_PENDING ERROR_SUCCESS WSA_IO_PENDING } member? ;
437
438 : (maybe-winsock-exception) ( n -- winsock-exception/f )
439     ! ! WSAStartup returns the error code 'n' directly
440     dup winsock-expected-error?
441     [ drop f ] [ [ ] [ n>win32-error-string ] bi \ winsock-exception boa ] if ;
442
443 : maybe-winsock-exception ( -- winsock-exception/f )
444     WSAGetLastError (maybe-winsock-exception) ;
445
446 : winsock-error ( -- )
447     maybe-winsock-exception [ throw ] when* ;
448
449 : (winsock-error) ( n -- * )
450     [ ] [ n>win32-error-string ] bi winsock-exception ;
451
452 : throw-winsock-error ( -- * )
453     WSAGetLastError (winsock-error) ;
454
455 : winsock-error=0/f ( n/f -- )
456     { 0 f } member? [ winsock-error ] when ;
457
458 : winsock-error!=0/f ( n/f -- )
459     { 0 f } member? [ winsock-error ] unless ;
460
461 ! WSAStartup and WSACleanup return the error code directly
462 : winsock-return-check ( n/f -- )
463     dup { 0 f } member? [
464         drop
465     ] [
466         [ ] [ n>win32-error-string ] bi winsock-exception
467     ] if ;
468
469 : socket-error* ( n -- )
470     SOCKET_ERROR = [
471         WSAGetLastError
472         dup WSA_IO_PENDING = [
473             drop
474         ] [
475             (maybe-winsock-exception) throw
476         ] if
477     ] when ;
478
479 : socket-error ( n -- )
480     SOCKET_ERROR = [ winsock-error ] when ;
481
482 : init-winsock ( -- )
483     0x0202 <wsadata> WSAStartup winsock-return-check ;
484
485 : shutdown-winsock ( -- ) WSACleanup winsock-return-check ;
486
487 [ init-winsock ] "windows.winsock" add-startup-hook
488 [ shutdown-winsock ] "windows.winsock" add-shutdown-hook