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