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 windows.com.syntax windows.errors
7 windows.kernel32 windows.types ;
8 FROM: alien.c-types => short ;
13 : <wsadata> ( -- byte-array )
16 CONSTANT: SOCK_STREAM 1
17 CONSTANT: SOCK_DGRAM 2
20 CONSTANT: SOCK_SEQPACKET 5
22 CONSTANT: SO_DEBUG 0x1
23 CONSTANT: SO_ACCEPTCONN 0x2
24 CONSTANT: SO_REUSEADDR 0x4
25 CONSTANT: SO_KEEPALIVE 0x8
26 CONSTANT: SO_DONTROUTE 0x10
27 CONSTANT: SO_BROADCAST 0x20
28 CONSTANT: SO_USELOOPBACK 0x40
29 CONSTANT: SO_LINGER 0x80
30 CONSTANT: SO_OOBINLINE 0x100
31 : SO_DONTLINGER ( -- n ) SO_LINGER bitnot ; inline
33 CONSTANT: SO_SNDBUF 0x1001
34 CONSTANT: SO_RCVBUF 0x1002
35 CONSTANT: SO_SNDLOWAT 0x1003
36 CONSTANT: SO_RCVLOWAT 0x1004
37 CONSTANT: SO_SNDTIMEO 0x1005
38 CONSTANT: SO_RCVTIMEO 0x1006
39 CONSTANT: SO_ERROR 0x1007
40 CONSTANT: SO_TYPE 0x1008
42 CONSTANT: TCP_NODELAY 0x1
47 CONSTANT: AF_IMPLINK 3
54 CONSTANT: AF_DATAKIT 9
57 CONSTANT: AF_DECnet 12
60 CONSTANT: AF_HYLINK 15
61 CONSTANT: AF_APPLETALK 16
62 CONSTANT: AF_NETBIOS 17
73 CONSTANT: AI_PASSIVE 1
74 CONSTANT: AI_CANONNAME 2
75 CONSTANT: AI_NUMERICHOST 4
77 CONSTANT: AI_MASK flags{ AI_PASSIVE AI_CANONNAME AI_NUMERICHOST }
79 CONSTANT: NI_NUMERICHOST 1
80 CONSTANT: NI_NUMERICSERV 2
82 CONSTANT: IPPROTO_TCP 6
83 CONSTANT: IPPROTO_UDP 17
84 CONSTANT: IPPROTO_RM 113
86 CONSTANT: WSA_FLAG_OVERLAPPED 1
87 ALIAS: WSA_WAIT_EVENT_0 WAIT_OBJECT_0
88 ALIAS: WSA_MAXIMUM_WAIT_EVENTS MAXIMUM_WAIT_OBJECTS
89 CONSTANT: WSA_INVALID_EVENT f
90 CONSTANT: WSA_WAIT_FAILED -1
91 ALIAS: WSA_WAIT_IO_COMPLETION WAIT_IO_COMPLETION
92 ALIAS: WSA_WAIT_TIMEOUT WAIT_TIMEOUT
93 ALIAS: WSA_INFINITE INFINITE
94 ALIAS: WSA_IO_PENDING ERROR_IO_PENDING
96 CONSTANT: INADDR_ANY 0
98 : INVALID_SOCKET ( -- n ) -1 <alien> ; inline
100 : SOCKET_ERROR ( -- n ) -1 <alien> ; inline
106 CONSTANT: SOL_SOCKET 0xffff
128 { addr-list void* } ;
141 { canonname c-string }
153 GENERIC: sockaddr>ip ( sockaddr -- string )
155 M: sockaddr-in sockaddr>ip ( sockaddr -- string )
156 addr>> uint <ref> [ number>string ] { } map-as "." join ;
158 M: sockaddr-in6 sockaddr>ip ( uchar-array -- string )
159 addr>> [ >hex ] { } map-as 2 group [ concat ] map ":" join ;
165 FUNCTION: int setsockopt ( SOCKET s, int level, int optname, c-string optval, int optlen ) ;
167 FUNCTION: ushort htons ( ushort n ) ;
168 FUNCTION: ushort ntohs ( ushort n ) ;
169 FUNCTION: int bind ( void* socket, sockaddr-in* sockaddr, int len ) ;
170 FUNCTION: int listen ( void* socket, int backlog ) ;
171 FUNCTION: c-string inet_ntoa ( int in-addr ) ;
172 FUNCTION: int getaddrinfo ( c-string nodename,
177 FUNCTION: void freeaddrinfo ( addrinfo* ai ) ;
180 FUNCTION: hostent* gethostbyname ( c-string name ) ;
181 FUNCTION: int gethostname ( c-string name, int len ) ;
182 FUNCTION: int connect ( void* socket, sockaddr-in* sockaddr, int addrlen ) ;
183 FUNCTION: int select ( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout ) ;
184 FUNCTION: int closesocket ( SOCKET s ) ;
185 FUNCTION: int shutdown ( SOCKET s, int how ) ;
186 FUNCTION: int send ( SOCKET s, c-string buf, int len, int flags ) ;
187 FUNCTION: int recv ( SOCKET s, c-string buf, int len, int flags ) ;
189 FUNCTION: int getsockname ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
190 FUNCTION: int getpeername ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
192 FUNCTION: protoent* getprotobyname ( c-string name ) ;
194 FUNCTION: servent* getservbyname ( c-string name, c-string prot ) ;
195 FUNCTION: servent* getservbyport ( c-string name, c-string prot ) ;
197 TYPEDEF: uint SERVICETYPE
198 TYPEDEF: OVERLAPPED WSAOVERLAPPED
199 TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
201 TYPEDEF: void* LPCONDITIONPROC
202 TYPEDEF: HANDLE WSAEVENT
203 TYPEDEF: LPHANDLE LPWSAEVENT
204 TYPEDEF: sockaddr* LPSOCKADDR
208 { TokenBucketSize uint }
209 { PeakBandwidth uint }
211 { DelayVariation uint }
212 { ServiceType SERVICETYPE }
214 { MinimumPolicedSize uint } ;
215 TYPEDEF: FLOWSPEC* PFLOWSPEC
216 TYPEDEF: FLOWSPEC* LPFLOWSPEC
221 TYPEDEF: WSABUF* LPWSABUF
224 { SendingFlowspec FLOWSPEC }
225 { ReceivingFlowspec FLOWSPEC }
226 { ProviderSpecific WSABUF } ;
229 CONSTANT: MAX_PROTOCOL_CHAIN 7
231 STRUCT: WSAPROTOCOLCHAIN
233 { ChainEntries { DWORD 7 } } ;
234 ! { ChainEntries { DWORD MAX_PROTOCOL_CHAIN } } ;
235 TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN
237 CONSTANT: WSAPROTOCOL_LEN 255
239 STRUCT: WSAPROTOCOL_INFOW
240 { dwServiceFlags1 DWORD }
241 { dwServiceFlags2 DWORD }
242 { dwServiceFlags3 DWORD }
243 { dwServiceFlags4 DWORD }
244 { dwProviderFlags DWORD }
246 { dwCatalogEntryId DWORD }
247 { ProtocolChain WSAPROTOCOLCHAIN }
249 { iAddressFamily int }
254 { iProtocolMaxOffset int }
255 { iNetworkByteOrder int }
256 { iSecurityScheme int }
257 { dwMessageSize DWORD }
258 { dwProviderReserved DWORD }
259 { szProtocol { WCHAR 256 } } ;
260 ! { szProtocol[WSAPROTOCOL_LEN+1] { WCHAR 256 } } ;
261 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFOW
262 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFOW
263 TYPEDEF: WSAPROTOCOL_INFOW WSAPROTOCOL_INFO
264 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFO
265 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFO
268 STRUCT: WSANAMESPACE_INFOW
269 { NSProviderId GUID }
270 { dwNameSpace DWORD }
273 { lpszIdentifier LPWSTR } ;
274 TYPEDEF: WSANAMESPACE_INFOW* PWSANAMESPACE_INFOW
275 TYPEDEF: WSANAMESPACE_INFOW* LPWSANAMESPACE_INFOW
276 TYPEDEF: WSANAMESPACE_INFOW WSANAMESPACE_INFO
277 TYPEDEF: WSANAMESPACE_INFO* PWSANAMESPACE_INFO
278 TYPEDEF: WSANAMESPACE_INFO* LPWSANAMESPACE_INFO
280 CONSTANT: FD_MAX_EVENTS 10
282 STRUCT: WSANETWORKEVENTS
283 { lNetworkEvents long }
284 { iErrorCode { int FD_MAX_EVENTS } } ;
285 TYPEDEF: WSANETWORKEVENTS* PWSANETWORKEVENTS
286 TYPEDEF: WSANETWORKEVENTS* LPWSANETWORKEVENTS
288 ! STRUCT: WSAOVERLAPPED
290 ! { InternalHigh DWORD }
292 ! { OffsetHigh DWORD }
293 ! { hEvent WSAEVENT }
294 ! { bytesTransferred DWORD } ;
295 ! TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
297 FUNCTION: SOCKET WSAAccept ( SOCKET s,
300 LPCONDITIONPROC lpfnCondition,
301 DWORD dwCallbackData ) ;
303 ! FUNCTION: INT WSAAddressToString ( LPSOCKADDR lpsaAddress, DWORD dwAddressLength, LPWSAPROTOCOL_INFO lpProtocolInfo, LPTSTR lpszAddressString, LPDWORD lpdwAddressStringLength ) ;
305 FUNCTION: int WSACleanup ( ) ;
306 FUNCTION: BOOL WSACloseEvent ( WSAEVENT hEvent ) ;
308 FUNCTION: int WSAConnect ( SOCKET s,
311 LPWSABUF lpCallerData,
312 LPWSABUF lpCalleeData,
315 FUNCTION: WSAEVENT WSACreateEvent ( ) ;
316 ! FUNCTION: INT WSAEnumNameSpaceProviders ( LPDWORD lpdwBufferLength, LPWSANAMESPACE_INFO lpnspBuffer ) ;
317 FUNCTION: int WSAEnumNetworkEvents ( SOCKET s,
318 WSAEVENT hEventObject,
319 LPWSANETWORKEVENTS lpNetworkEvents ) ;
320 ! FUNCTION: int WSAEnumProtocols ( LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpwdBufferLength ) ;
322 FUNCTION: int WSAEventSelect ( SOCKET s,
323 WSAEVENT hEventObject,
324 long lNetworkEvents ) ;
325 FUNCTION: int WSAGetLastError ( ) ;
326 FUNCTION: BOOL WSAGetOverlappedResult ( SOCKET s,
327 LPWSAOVERLAPPED lpOverlapped,
328 LPDWORD lpcbTransfer,
330 LPDWORD lpdwFlags ) ;
332 FUNCTION: int WSAIoctl ( SOCKET s,
333 DWORD dwIoControlCode,
338 LPDWORD lpcbBytesReturned,
340 void* lpCompletionRoutine ) ;
342 TYPEDEF: void* LPWSAOVERLAPPED_COMPLETION_ROUTINE
343 FUNCTION: int WSARecv ( SOCKET s,
346 LPDWORD lpNumberOfBytesRecvd,
348 LPWSAOVERLAPPED lpOverlapped,
349 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
351 FUNCTION: int WSARecvFrom ( SOCKET s,
354 LPDWORD lpNumberOfBytesRecvd,
358 LPWSAOVERLAPPED lpOverlapped,
359 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
361 FUNCTION: BOOL WSAResetEvent ( WSAEVENT hEvent ) ;
362 FUNCTION: int WSASend ( SOCKET s,
365 LPDWORD lpNumberOfBytesSent,
367 LPWSAOVERLAPPED lpOverlapped,
368 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
370 FUNCTION: int WSASendTo ( SOCKET s,
373 LPDWORD lpNumberOfBytesSent,
377 LPWSAOVERLAPPED lpOverlapped,
378 LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
381 FUNCTION: int WSAStartup ( short version, void* out-data ) ;
385 FUNCTION: SOCKET WSASocketW ( int af,
388 LPWSAPROTOCOL_INFOW lpProtocolInfo,
391 ALIAS: WSASocket WSASocketW
393 FUNCTION: DWORD WSAWaitForMultipleEvents ( DWORD cEvents,
402 FUNCTION: int AcceptEx ( void* listen, void* accept, void* out-buf, int recv-len, int addr-len, int remote-len, void* out-len, void* overlapped ) ;
404 FUNCTION: void GetAcceptExSockaddrs (
405 PVOID lpOutputBuffer,
406 DWORD dwReceiveDataLength,
407 DWORD dwLocalAddressLength,
408 DWORD dwRemoteAddressLength,
409 LPSOCKADDR* LocalSockaddr,
410 LPINT LocalSockaddrLength,
411 LPSOCKADDR* RemoteSockaddr,
412 LPINT RemoteSockaddrLength
415 CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090
417 CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
419 ERROR: winsock-exception n string ;
421 : winsock-expected-error? ( n -- ? )
422 ${ ERROR_IO_PENDING ERROR_SUCCESS WSA_IO_PENDING } member? ;
424 : (maybe-winsock-exception) ( n -- winsock-exception/f )
425 ! #! WSAStartup returns the error code 'n' directly
426 dup winsock-expected-error?
427 [ drop f ] [ [ ] [ n>win32-error-string ] bi \ winsock-exception boa ] if ;
429 : maybe-winsock-exception ( -- winsock-exception/f )
430 WSAGetLastError (maybe-winsock-exception) ;
432 : winsock-error ( -- )
433 maybe-winsock-exception [ throw ] when* ;
435 : (throw-winsock-error) ( n -- * )
436 [ ] [ n>win32-error-string ] bi winsock-exception ;
438 : throw-winsock-error ( -- * )
439 WSAGetLastError (throw-winsock-error) ;
441 : winsock-error=0/f ( n/f -- )
442 { 0 f } member? [ throw-winsock-error ] when ;
444 : winsock-error!=0/f ( n/f -- )
445 { 0 f } member? [ throw-winsock-error ] unless ;
447 ! WSAStartup and WSACleanup return the error code directly
448 : winsock-return-check ( n/f -- )
449 dup { 0 f } member? [
452 [ ] [ n>win32-error-string ] bi winsock-exception
455 : socket-error* ( n -- )
458 dup WSA_IO_PENDING = [
461 (maybe-winsock-exception) throw
465 : socket-error ( n -- )
466 SOCKET_ERROR = [ winsock-error ] when ;
468 : init-winsock ( -- )
469 0x0202 <wsadata> WSAStartup winsock-return-check ;
471 : shutdown-winsock ( -- ) WSACleanup winsock-return-check ;
473 [ init-winsock ] "windows.winsock" add-startup-hook
474 [ shutdown-winsock ] "windows.winsock" add-shutdown-hook