]> gitweb.factorcode.org Git - factor.git/blob - basis/windows/winsock/winsock.factor
Merge:
[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: WSA_FLAG_OVERLAPPED 1
92 ALIAS: WSA_WAIT_EVENT_0 WAIT_OBJECT_0
93 ALIAS: WSA_MAXIMUM_WAIT_EVENTS MAXIMUM_WAIT_OBJECTS
94 CONSTANT: WSA_INVALID_EVENT f
95 CONSTANT: WSA_WAIT_FAILED -1
96 ALIAS: WSA_WAIT_IO_COMPLETION WAIT_IO_COMPLETION
97 ALIAS: WSA_WAIT_TIMEOUT WAIT_TIMEOUT
98 ALIAS: WSA_INFINITE INFINITE
99 ALIAS: WSA_IO_PENDING ERROR_IO_PENDING
100
101 CONSTANT: INADDR_ANY 0
102
103 : INVALID_SOCKET ( -- n ) -1 <alien> ; inline
104
105 : SOCKET_ERROR ( -- n ) -1 <alien> ; inline
106
107 CONSTANT: SD_RECV 0
108 CONSTANT: SD_SEND 1
109 CONSTANT: SD_BOTH 2
110
111 CONSTANT: SOL_SOCKET 0xffff
112
113 C-TYPE: sockaddr
114
115 STRUCT: sockaddr-in
116     { family short }
117     { port ushort }
118     { addr uint }
119     { pad char[8] } ;
120
121 STRUCT: sockaddr-in6
122     { family uchar }
123     { port ushort }
124     { flowinfo uint }
125     { addr uchar[16] }
126     { scopeid uint } ;
127
128 STRUCT: hostent
129     { name c-string }
130     { aliases void* }
131     { addrtype short }
132     { length short }
133     { addr-list void* } ;
134
135 STRUCT: protoent
136     { name c-string }
137     { aliases void* }
138     { proto short } ;
139
140 STRUCT: addrinfo
141     { flags int }
142     { family int }
143     { socktype int }
144     { protocol int }
145     { addrlen size_t }
146     { canonname c-string }
147     { addr sockaddr* }
148     { next addrinfo* } ;
149
150 STRUCT: timeval
151     { sec long }
152     { usec long } ;
153
154 GENERIC: sockaddr>ip ( sockaddr -- string )
155
156 M: sockaddr-in sockaddr>ip ( sockaddr -- string )
157     addr>> uint <ref> [ number>string ] { } map-as "." join ;
158
159 M: sockaddr-in6 sockaddr>ip ( uchar-array -- string )
160     addr>> [ >hex ] { } map-as 2 group [ concat ] map ":" join ;
161
162 STRUCT: fd_set
163     { fd_count uint }
164     { fd_array SOCKET[64] } ;
165
166 LIBRARY: winsock
167
168 FUNCTION: int setsockopt ( SOCKET s, int level, int optname, c-string optval, int optlen ) ;
169
170 FUNCTION: ushort htons ( ushort n ) ;
171 FUNCTION: ushort ntohs ( ushort n ) ;
172 FUNCTION: int bind ( void* socket, sockaddr-in* sockaddr, int len ) ;
173 FUNCTION: int listen ( void* socket, int backlog ) ;
174 FUNCTION: c-string inet_ntoa ( int in-addr ) ;
175 FUNCTION: int getaddrinfo ( c-string nodename,
176                             c-string servername,
177                             addrinfo* hints,
178                             addrinfo** res ) ;
179
180 FUNCTION: void freeaddrinfo ( addrinfo* ai ) ;
181
182
183 FUNCTION: hostent* gethostbyname ( c-string name ) ;
184 FUNCTION: int gethostname ( c-string name, int len ) ;
185 FUNCTION: void* socket ( int domain, int type, int protocol ) ;
186 FUNCTION: int connect ( void* socket, sockaddr-in* sockaddr, int addrlen ) ;
187 FUNCTION: int select ( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout ) ;
188 FUNCTION: int closesocket ( SOCKET s ) ;
189 FUNCTION: int shutdown ( SOCKET s, int how ) ;
190 FUNCTION: int send ( SOCKET s, c-string buf, int len, int flags ) ;
191 FUNCTION: int recv ( SOCKET s, c-string buf, int len, int flags ) ;
192
193 FUNCTION: int getsockname ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
194 FUNCTION: int getpeername ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
195
196 FUNCTION: protoent* getprotobyname ( c-string name ) ;
197
198 FUNCTION: servent* getservbyname ( c-string name, c-string prot ) ;
199 FUNCTION: servent* getservbyport ( int port, c-string prot ) ;
200
201 TYPEDEF: uint SERVICETYPE
202 TYPEDEF: OVERLAPPED WSAOVERLAPPED
203 TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
204 TYPEDEF: uint GROUP
205 TYPEDEF: void* LPCONDITIONPROC
206 TYPEDEF: HANDLE WSAEVENT
207 TYPEDEF: LPHANDLE LPWSAEVENT
208 TYPEDEF: sockaddr* LPSOCKADDR
209
210 STRUCT: FLOWSPEC
211     { TokenRate          uint        }
212     { TokenBucketSize    uint        }
213     { PeakBandwidth      uint        }
214     { Latency            uint        }
215     { DelayVariation     uint        }
216     { ServiceType        SERVICETYPE }
217     { MaxSduSize         uint        }
218     { MinimumPolicedSize uint        } ;
219 TYPEDEF: FLOWSPEC* PFLOWSPEC
220 TYPEDEF: FLOWSPEC* LPFLOWSPEC
221
222 STRUCT: WSABUF
223     { len ulong }
224     { buf void* } ;
225 TYPEDEF: WSABUF* LPWSABUF
226
227 STRUCT: QOS
228     { SendingFlowspec FLOWSPEC }
229     { ReceivingFlowspec FLOWSPEC }
230     { ProviderSpecific WSABUF } ;
231 TYPEDEF: QOS* LPQOS
232
233 CONSTANT: MAX_PROTOCOL_CHAIN 7
234
235 STRUCT: WSAPROTOCOLCHAIN
236     { ChainLen int }
237     { ChainEntries { DWORD 7 } } ;
238     ! { ChainEntries { DWORD MAX_PROTOCOL_CHAIN } } ;
239 TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN
240
241 CONSTANT: WSAPROTOCOL_LEN 255
242
243 STRUCT: WSAPROTOCOL_INFOW
244     { dwServiceFlags1 DWORD }
245     { dwServiceFlags2 DWORD }
246     { dwServiceFlags3 DWORD }
247     { dwServiceFlags4 DWORD }
248     { dwProviderFlags DWORD }
249     { ProviderId GUID }
250     { dwCatalogEntryId DWORD }
251     { ProtocolChain WSAPROTOCOLCHAIN }
252     { iVersion int }
253     { iAddressFamily int }
254     { iMaxSockAddr int }
255     { iMinSockAddr int }
256     { iSocketType int }
257     { iProtocol int }
258     { iProtocolMaxOffset int }
259     { iNetworkByteOrder int }
260     { iSecurityScheme int }
261     { dwMessageSize DWORD }
262     { dwProviderReserved DWORD }
263     { szProtocol { WCHAR 256 } } ;
264     ! { szProtocol[WSAPROTOCOL_LEN+1] { WCHAR 256 } } ;
265 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFOW
266 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFOW
267 TYPEDEF: WSAPROTOCOL_INFOW WSAPROTOCOL_INFO
268 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFO
269 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFO
270
271
272 STRUCT: WSANAMESPACE_INFOW
273     { NSProviderId   GUID    }
274     { dwNameSpace    DWORD   }
275     { fActive        BOOL    }
276     { dwVersion      DWORD   }
277     { lpszIdentifier LPWSTR  } ;
278 TYPEDEF: WSANAMESPACE_INFOW* PWSANAMESPACE_INFOW
279 TYPEDEF: WSANAMESPACE_INFOW* LPWSANAMESPACE_INFOW
280 TYPEDEF: WSANAMESPACE_INFOW WSANAMESPACE_INFO
281 TYPEDEF: WSANAMESPACE_INFO* PWSANAMESPACE_INFO
282 TYPEDEF: WSANAMESPACE_INFO* LPWSANAMESPACE_INFO
283
284 CONSTANT: FD_MAX_EVENTS 10
285
286 STRUCT: WSANETWORKEVENTS
287     { lNetworkEvents long }
288     { iErrorCode { int FD_MAX_EVENTS } } ;
289 TYPEDEF: WSANETWORKEVENTS* PWSANETWORKEVENTS
290 TYPEDEF: WSANETWORKEVENTS* LPWSANETWORKEVENTS
291
292 ! STRUCT: WSAOVERLAPPED
293     ! { Internal DWORD }
294     ! { InternalHigh DWORD }
295     ! { Offset DWORD }
296     ! { OffsetHigh DWORD }
297     ! { hEvent WSAEVENT }
298     ! { bytesTransferred DWORD } ;
299 ! TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
300
301 FUNCTION: SOCKET WSAAccept ( SOCKET s,
302                              sockaddr* addr,
303                              LPINT addrlen,
304                              LPCONDITIONPROC lpfnCondition,
305                              DWORD dwCallbackData ) ;
306
307 ! FUNCTION: INT WSAAddressToString ( LPSOCKADDR lpsaAddress, DWORD dwAddressLength, LPWSAPROTOCOL_INFO lpProtocolInfo, LPTSTR lpszAddressString, LPDWORD lpdwAddressStringLength ) ;
308
309 FUNCTION: int WSACleanup ( ) ;
310 FUNCTION: BOOL WSACloseEvent ( WSAEVENT hEvent ) ;
311
312 FUNCTION: int WSAConnect ( SOCKET s,
313                            sockaddr* name,
314                            int namelen,
315                            LPWSABUF lpCallerData,
316                            LPWSABUF lpCalleeData,
317                            LPQOS lpSQOS,
318                            LPQOS lpGQOS ) ;
319 FUNCTION: WSAEVENT WSACreateEvent ( ) ;
320 ! FUNCTION: INT WSAEnumNameSpaceProviders ( LPDWORD lpdwBufferLength, LPWSANAMESPACE_INFO lpnspBuffer ) ;
321 FUNCTION: int WSAEnumNetworkEvents ( SOCKET s,
322                                      WSAEVENT hEventObject,
323                                      LPWSANETWORKEVENTS lpNetworkEvents ) ;
324 ! FUNCTION: int WSAEnumProtocols ( LPINT lpiProtocols, LPWSAPROTOCOL_INFO lpProtocolBuffer, LPDWORD lpwdBufferLength ) ;
325
326 FUNCTION: int WSAEventSelect ( SOCKET s,
327                                WSAEVENT hEventObject,
328                                long lNetworkEvents ) ;
329 FUNCTION: int WSAGetLastError ( ) ;
330 FUNCTION: BOOL WSAGetOverlappedResult ( SOCKET s,
331                                         LPWSAOVERLAPPED lpOverlapped,
332                                         LPDWORD lpcbTransfer,
333                                         BOOL fWait,
334                                         LPDWORD lpdwFlags ) ;
335
336 FUNCTION: int WSAIoctl ( SOCKET s,
337                          DWORD dwIoControlCode,
338                          LPVOID lpvInBuffer,
339                          DWORD cbInBuffer,
340                          LPVOID lpvOutBuffer,
341                          DWORD cbOutBuffer,
342                          LPDWORD lpcbBytesReturned,
343                          void* lpOverlapped,
344                          void* lpCompletionRoutine ) ;
345
346 TYPEDEF: void* LPWSAOVERLAPPED_COMPLETION_ROUTINE
347 FUNCTION: int WSARecv ( SOCKET s,
348                         LPWSABUF lpBuffers,
349                         DWORD dwBufferCount,
350                         LPDWORD lpNumberOfBytesRecvd,
351                         LPDWORD lpFlags,
352                         LPWSAOVERLAPPED lpOverlapped,
353                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
354
355 FUNCTION: int WSARecvFrom ( SOCKET s,
356                     LPWSABUF lpBuffers,
357                     DWORD dwBufferCount,
358                     LPDWORD lpNumberOfBytesRecvd,
359                     LPDWORD lpFlags,
360                     sockaddr* lpFrom,
361                     LPINT lpFromlen,
362                     LPWSAOVERLAPPED lpOverlapped,
363                     LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
364
365 FUNCTION: BOOL WSAResetEvent ( WSAEVENT hEvent ) ;
366 FUNCTION: int WSASend ( SOCKET s,
367                         LPWSABUF lpBuffers,
368                         DWORD dwBufferCount,
369                         LPDWORD lpNumberOfBytesSent,
370                         LPDWORD lpFlags,
371                         LPWSAOVERLAPPED lpOverlapped,
372                  LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
373
374 FUNCTION: int WSASendTo ( SOCKET s,
375                           LPWSABUF lpBuffers,
376                           DWORD dwBufferCount,
377                           LPDWORD lpNumberOfBytesSent,
378                           DWORD dwFlags,
379                           sockaddr* lpTo,
380                           int iToLen,
381                           LPWSAOVERLAPPED lpOverlapped,
382   LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ) ;
383
384
385 FUNCTION: int WSAStartup ( short version, void* out-data ) ;
386
387
388
389 FUNCTION: SOCKET WSASocketW ( int af,
390                              int type,
391                              int protocol,
392                              LPWSAPROTOCOL_INFOW lpProtocolInfo,
393                              GROUP g,
394                              DWORD flags ) ;
395 ALIAS: WSASocket WSASocketW
396
397 FUNCTION: DWORD WSAWaitForMultipleEvents ( DWORD cEvents,
398                                            WSAEVENT* lphEvents,
399                                            BOOL fWaitAll,
400                                            DWORD dwTimeout,
401                                            BOOL fAlertable ) ;
402
403
404 LIBRARY: mswsock
405
406 FUNCTION: int AcceptEx ( void* listen, void* accept, void* out-buf, int recv-len, int addr-len, int remote-len, void* out-len, void* overlapped ) ;
407
408 FUNCTION: void GetAcceptExSockaddrs (
409   PVOID lpOutputBuffer,
410   DWORD dwReceiveDataLength,
411   DWORD dwLocalAddressLength,
412   DWORD dwRemoteAddressLength,
413   LPSOCKADDR* LocalSockaddr,
414   LPINT LocalSockaddrLength,
415   LPSOCKADDR* RemoteSockaddr,
416   LPINT RemoteSockaddrLength
417 ) ;
418
419 CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090
420
421 CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
422
423 ERROR: winsock-exception n string ;
424
425 : winsock-expected-error? ( n -- ? )
426     ${ ERROR_IO_PENDING ERROR_SUCCESS WSA_IO_PENDING } member? ;
427
428 : (maybe-winsock-exception) ( n -- winsock-exception/f )
429     ! #! WSAStartup returns the error code 'n' directly
430     dup winsock-expected-error?
431     [ drop f ] [ [ ] [ n>win32-error-string ] bi \ winsock-exception boa ] if ;
432
433 : maybe-winsock-exception ( -- winsock-exception/f )
434     WSAGetLastError (maybe-winsock-exception) ;
435
436 : winsock-error ( -- )
437     maybe-winsock-exception [ throw ] when* ;
438
439 : (throw-winsock-error) ( n -- * )
440     [ ] [ n>win32-error-string ] bi winsock-exception ;
441
442 : throw-winsock-error ( -- * )
443     WSAGetLastError (throw-winsock-error) ;
444
445 : winsock-error=0/f ( n/f -- )
446     { 0 f } member? [ throw-winsock-error ] when ;
447
448 : winsock-error!=0/f ( n/f -- )
449     { 0 f } member? [ throw-winsock-error ] unless ;
450
451 ! WSAStartup and WSACleanup return the error code directly
452 : winsock-return-check ( n/f -- )
453     dup { 0 f } member? [
454         drop
455     ] [
456         [ ] [ n>win32-error-string ] bi winsock-exception
457     ] if ;
458
459 : socket-error* ( n -- )
460     SOCKET_ERROR = [
461         WSAGetLastError
462         dup WSA_IO_PENDING = [
463             drop
464         ] [
465             (maybe-winsock-exception) throw
466         ] if
467     ] when ;
468
469 : socket-error ( n -- )
470     SOCKET_ERROR = [ winsock-error ] when ;
471
472 : init-winsock ( -- )
473     0x0202 <wsadata> WSAStartup winsock-return-check ;
474
475 : shutdown-winsock ( -- ) WSACleanup winsock-return-check ;
476
477 [ init-winsock ] "windows.winsock" add-startup-hook
478 [ shutdown-winsock ] "windows.winsock" add-shutdown-hook