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