]> gitweb.factorcode.org Git - factor.git/blobdiff - basis/windows/winsock/winsock.factor
use radix literals
[factor.git] / basis / windows / winsock / winsock.factor
old mode 100755 (executable)
new mode 100644 (file)
index 74f67a4..3441569
@@ -1,19 +1,16 @@
 ! Copyright (C) 2006 Mackenzie Straight, Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings alien.syntax arrays
-byte-arrays kernel math sequences windows.types windows.kernel32
-windows.errors math.bitwise io.encodings.utf16n classes.struct
-literals windows.com.syntax ;
+byte-arrays kernel literals math sequences windows.types
+windows.kernel32 windows.errors math.bitwise io.encodings.utf16n
+classes.struct windows.com.syntax init ;
+FROM: alien.c-types => short ;
 IN: windows.winsock
 
-USE: libc
-: alien>byte-array ( alien str -- byte-array )
-    heap-size dup <byte-array> [ -rot memcpy ] keep ;
-
-TYPEDEF: void* SOCKET
+TYPEDEF: int* SOCKET
 
 : <wsadata> ( -- byte-array )
-    HEX: 190 <byte-array> ;
+    0x190 <byte-array> ;
 
 CONSTANT: SOCK_STREAM    1
 CONSTANT: SOCK_DGRAM     2
@@ -21,27 +18,27 @@ CONSTANT: SOCK_RAW       3
 CONSTANT: SOCK_RDM       4
 CONSTANT: SOCK_SEQPACKET 5
 
-CONSTANT: SO_DEBUG       HEX:   1
-CONSTANT: SO_ACCEPTCONN  HEX:   2
-CONSTANT: SO_REUSEADDR   HEX:   4
-CONSTANT: SO_KEEPALIVE   HEX:   8
-CONSTANT: SO_DONTROUTE   HEX:  10
-CONSTANT: SO_BROADCAST   HEX:  20
-CONSTANT: SO_USELOOPBACK HEX:  40
-CONSTANT: SO_LINGER      HEX:  80
-CONSTANT: SO_OOBINLINE   HEX: 100
+CONSTANT: SO_DEBUG       0x1
+CONSTANT: SO_ACCEPTCONN  0x2
+CONSTANT: SO_REUSEADDR   0x4
+CONSTANT: SO_KEEPALIVE   0x8
+CONSTANT: SO_DONTROUTE   0x10
+CONSTANT: SO_BROADCAST   0x20
+CONSTANT: SO_USELOOPBACK 0x40
+CONSTANT: SO_LINGER      0x80
+CONSTANT: SO_OOBINLINE   0x100
 : SO_DONTLINGER ( -- n ) SO_LINGER bitnot ; inline
 
-CONSTANT: SO_SNDBUF     HEX: 1001
-CONSTANT: SO_RCVBUF     HEX: 1002
-CONSTANT: SO_SNDLOWAT   HEX: 1003
-CONSTANT: SO_RCVLOWAT   HEX: 1004
-CONSTANT: SO_SNDTIMEO   HEX: 1005
-CONSTANT: SO_RCVTIMEO   HEX: 1006
-CONSTANT: SO_ERROR      HEX: 1007
-CONSTANT: SO_TYPE       HEX: 1008
+CONSTANT: SO_SNDBUF     0x1001
+CONSTANT: SO_RCVBUF     0x1002
+CONSTANT: SO_SNDLOWAT   0x1003
+CONSTANT: SO_RCVLOWAT   0x1004
+CONSTANT: SO_SNDTIMEO   0x1005
+CONSTANT: SO_RCVTIMEO   0x1006
+CONSTANT: SO_ERROR      0x1007
+CONSTANT: SO_TYPE       0x1008
 
-CONSTANT: TCP_NODELAY   HEX:    1
+CONSTANT: TCP_NODELAY   0x1
 
 CONSTANT: AF_UNSPEC      0
 CONSTANT: AF_UNIX        1
@@ -75,7 +72,8 @@ CONSTANT: PF_INET6      23
 CONSTANT: AI_PASSIVE     1
 CONSTANT: AI_CANONNAME   2
 CONSTANT: AI_NUMERICHOST 4
-: AI_MASK ( -- n ) { AI_PASSIVE AI_CANONNAME AI_NUMERICHOST } flags ;
+
+CONSTANT: AI_MASK flags{ AI_PASSIVE AI_CANONNAME AI_NUMERICHOST }
 
 CONSTANT: NI_NUMERICHOST 1
 CONSTANT: NI_NUMERICSERV 2
@@ -96,81 +94,89 @@ ALIAS: WSA_IO_PENDING ERROR_IO_PENDING
 
 CONSTANT: INADDR_ANY 0
 
-: INVALID_SOCKET ( -- alien ) -1 <alien> ; inline
-CONSTANT: SOCKET_ERROR -1
+: INVALID_SOCKET ( -- n ) -1 <alien> ; inline
+
+: SOCKET_ERROR ( -- n ) -1 <alien> ; inline
 
 CONSTANT: SD_RECV 0
 CONSTANT: SD_SEND 1
 CONSTANT: SD_BOTH 2
 
-CONSTANT: SOL_SOCKET HEX: ffff
+CONSTANT: SOL_SOCKET 0xffff
 
-! TYPEDEF: uint in_addr_t
-! C-STRUCT: in_addr
-    ! { "in_addr_t" "s_addr" } ;
+C-TYPE: sockaddr
 
-C-STRUCT: sockaddr-in
-    { "short" "family" }
-    { "ushort" "port" }
-    { "uint" "addr" }
-    { { "char" 8 } "pad" } ;
+STRUCT: sockaddr-in
+    { family short }
+    { port ushort }
+    { addr uint }
+    { pad char[8] } ;
 
-C-STRUCT: sockaddr-in6
-    { "uchar" "family" }
-    { "ushort" "port" }
-    { "uint" "flowinfo" }
-    { { "uchar" 16 } "addr" }
-    { "uint" "scopeid" } ;
+STRUCT: sockaddr-in6
+    { family uchar }
+    { port ushort }
+    { flowinfo uint }
+    { addr uchar[16] }
+    { scopeid uint } ;
 
 STRUCT: hostent
-    { name char* }
+    { name c-string }
     { aliases void* }
     { addrtype short }
     { length short }
     { addr-list void* } ;
 
-C-STRUCT: addrinfo
-    { "int" "flags" }
-    { "int" "family" }
-    { "int" "socktype" }
-    { "int" "protocol" }
-    { "size_t" "addrlen" }
-    { "char*" "canonname" }
-    { "sockaddr*" "addr" }
-    { "addrinfo*" "next" } ;
+STRUCT: protoent
+    { name c-string }
+    { aliases void* }
+    { proto short } ;
 
-C-STRUCT: timeval
-    { "long" "sec" }
-    { "long" "usec" } ;
+STRUCT: addrinfo
+    { flags int }
+    { family int }
+    { socktype int }
+    { protocol int }
+    { addrlen size_t }
+    { canonname c-string }
+    { addr sockaddr* }
+    { next addrinfo* } ;
+
+STRUCT: timeval
+    { sec long }
+    { usec long } ;
+
+C-TYPE: fd_set
 
 LIBRARY: winsock
 
-FUNCTION: int setsockopt ( SOCKET s, int level, int optname, char* optval, int optlen ) ;
+FUNCTION: int setsockopt ( SOCKET s, int level, int optname, c-string optval, int optlen ) ;
 
 FUNCTION: ushort htons ( ushort n ) ;
 FUNCTION: ushort ntohs ( ushort n ) ;
-FUNCTION: int bind ( void* socket, sockaddr_in* sockaddr, int len ) ;
+FUNCTION: int bind ( void* socket, sockaddr-in* sockaddr, int len ) ;
 FUNCTION: int listen ( void* socket, int backlog ) ;
-FUNCTION: char* inet_ntoa ( int in-addr ) ;
-FUNCTION: int getaddrinfo ( char* nodename,
-                            char* servername,
+FUNCTION: c-string inet_ntoa ( int in-addr ) ;
+FUNCTION: int getaddrinfo ( c-string nodename,
+                            c-string servername,
                             addrinfo* hints,
                             addrinfo** res ) ;
 
 FUNCTION: void freeaddrinfo ( addrinfo* ai ) ;
 
 
-FUNCTION: hostent* gethostbyname ( char* name ) ;
-FUNCTION: int gethostname ( char* name, int len ) ;
-FUNCTION: int connect ( void* socket, sockaddr_in* sockaddr, int addrlen ) ;
+FUNCTION: hostent* gethostbyname ( c-string name ) ;
+FUNCTION: int gethostname ( c-string name, int len ) ;
+FUNCTION: int connect ( void* socket, sockaddr-in* sockaddr, int addrlen ) ;
 FUNCTION: int select ( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, timeval* timeout ) ;
 FUNCTION: int closesocket ( SOCKET s ) ;
 FUNCTION: int shutdown ( SOCKET s, int how ) ;
-FUNCTION: int send ( SOCKET s, char* buf, int len, int flags ) ;
-FUNCTION: int recv ( SOCKET s, char* buf, int len, int flags ) ;
+FUNCTION: int send ( SOCKET s, c-string buf, int len, int flags ) ;
+FUNCTION: int recv ( SOCKET s, c-string buf, int len, int flags ) ;
+
+FUNCTION: int getsockname ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
+FUNCTION: int getpeername ( SOCKET s, sockaddr-in* address, int* addrlen ) ;
 
-FUNCTION: int getsockname ( SOCKET s, sockaddr_in* address, int* addrlen ) ;
-FUNCTION: int getpeername ( SOCKET s, sockaddr_in* address, int* addrlen ) ;
+FUNCTION: protoent* getprotobyname ( c-string name ) ;
 
 TYPEDEF: uint SERVICETYPE
 TYPEDEF: OVERLAPPED WSAOVERLAPPED
@@ -181,15 +187,15 @@ TYPEDEF: HANDLE WSAEVENT
 TYPEDEF: LPHANDLE LPWSAEVENT
 TYPEDEF: sockaddr* LPSOCKADDR
 
-C-STRUCT: FLOWSPEC
-    { "uint"        "TokenRate" }
-    { "uint"        "TokenBucketSize" }
-    { "uint"        "PeakBandwidth" }
-    { "uint"        "Latency" }
-    { "uint"        "DelayVariation" }
-    { "SERVICETYPE" "ServiceType" }
-    { "uint"        "MaxSduSize" }
-    { "uint"        "MinimumPolicedSize" } ;
+STRUCT: FLOWSPEC
+    { TokenRate          uint        }
+    { TokenBucketSize    uint        }
+    { PeakBandwidth      uint        }
+    { Latency            uint        }
+    { DelayVariation     uint        }
+    { ServiceType        SERVICETYPE }
+    { MaxSduSize         uint        }
+    { MinimumPolicedSize uint        } ;
 TYPEDEF: FLOWSPEC* PFLOWSPEC
 TYPEDEF: FLOWSPEC* LPFLOWSPEC
 
@@ -198,44 +204,44 @@ STRUCT: WSABUF
     { buf void* } ;
 TYPEDEF: WSABUF* LPWSABUF
 
-C-STRUCT: QOS
-    { "FLOWSPEC" "SendingFlowspec" }
-    { "FLOWSPEC" "ReceivingFlowspec" }
-    { "WSABUF" "ProviderSpecific" } ;
+STRUCT: QOS
+    { SendingFlowspec FLOWSPEC }
+    { ReceivingFlowspec FLOWSPEC }
+    { ProviderSpecific WSABUF } ;
 TYPEDEF: QOS* LPQOS
 
 CONSTANT: MAX_PROTOCOL_CHAIN 7
 
-C-STRUCT: WSAPROTOCOLCHAIN
-    { "int" "ChainLen" }
-    ! { { "DWORD" MAX_PROTOCOL_CHAIN } "ChainEntries" } ;
-    { { "DWORD" 7 } "ChainEntries" } ;
+STRUCT: WSAPROTOCOLCHAIN
+    { ChainLen int }
+    { ChainEntries { DWORD 7 } } ;
+    ! { ChainEntries { DWORD MAX_PROTOCOL_CHAIN } } ;
 TYPEDEF: WSAPROTOCOLCHAIN* LPWSAPROTOCOLCHAIN
 
 CONSTANT: WSAPROTOCOL_LEN 255
 
-C-STRUCT: WSAPROTOCOL_INFOW
-    { "DWORD" "dwServiceFlags1" }
-    { "DWORD" "dwServiceFlags2" }
-    { "DWORD" "dwServiceFlags3" }
-    { "DWORD" "dwServiceFlags4" }
-    { "DWORD" "dwProviderFlags" }
-    { "GUID" "ProviderId" }
-    { "DWORD" "dwCatalogEntryId" }
-    { "WSAPROTOCOLCHAIN" "ProtocolChain" }
-    { "int" "iVersion" }
-    { "int" "iAddressFamily" }
-    { "int" "iMaxSockAddr" }
-    { "int" "iMinSockAddr" }
-    { "int" "iSocketType" }
-    { "int" "iProtocol" }
-    { "int" "iProtocolMaxOffset" }
-    { "int" "iNetworkByteOrder" }
-    { "int" "iSecurityScheme" }
-    { "DWORD" "dwMessageSize" }
-    { "DWORD" "dwProviderReserved" }
-    { { "WCHAR" 256 } "szProtocol" } ;
-    ! { { "WCHAR" 256 } "szProtocol"[WSAPROTOCOL_LEN+1] } ;
+STRUCT: WSAPROTOCOL_INFOW
+    { dwServiceFlags1 DWORD }
+    { dwServiceFlags2 DWORD }
+    { dwServiceFlags3 DWORD }
+    { dwServiceFlags4 DWORD }
+    { dwProviderFlags DWORD }
+    { ProviderId GUID }
+    { dwCatalogEntryId DWORD }
+    { ProtocolChain WSAPROTOCOLCHAIN }
+    { iVersion int }
+    { iAddressFamily int }
+    { iMaxSockAddr int }
+    { iMinSockAddr int }
+    { iSocketType int }
+    { iProtocol int }
+    { iProtocolMaxOffset int }
+    { iNetworkByteOrder int }
+    { iSecurityScheme int }
+    { dwMessageSize DWORD }
+    { dwProviderReserved DWORD }
+    { szProtocol { WCHAR 256 } } ;
+    ! { szProtocol[WSAPROTOCOL_LEN+1] { WCHAR 256 } } ;
 TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFOW
 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFOW
 TYPEDEF: WSAPROTOCOL_INFOW WSAPROTOCOL_INFO
@@ -243,12 +249,12 @@ TYPEDEF: WSAPROTOCOL_INFOW* PWSAPROTOCOL_INFO
 TYPEDEF: WSAPROTOCOL_INFOW* LPWSAPROTOCOL_INFO
 
 
-C-STRUCT: WSANAMESPACE_INFOW
-    { "GUID"    "NSProviderId" }
-    { "DWORD"   "dwNameSpace" }
-    { "BOOL"    "fActive" }
-    { "DWORD"   "dwVersion" }
-    { "LPWSTR"  "lpszIdentifier" } ;
+STRUCT: WSANAMESPACE_INFOW
+    { NSProviderId   GUID    }
+    { dwNameSpace    DWORD   }
+    { fActive        BOOL    }
+    { dwVersion      DWORD   }
+    { lpszIdentifier LPWSTR  } ;
 TYPEDEF: WSANAMESPACE_INFOW* PWSANAMESPACE_INFOW
 TYPEDEF: WSANAMESPACE_INFOW* LPWSANAMESPACE_INFOW
 TYPEDEF: WSANAMESPACE_INFOW WSANAMESPACE_INFO
@@ -257,19 +263,19 @@ TYPEDEF: WSANAMESPACE_INFO* LPWSANAMESPACE_INFO
 
 CONSTANT: FD_MAX_EVENTS 10
 
-C-STRUCT: WSANETWORKEVENTS
-    { "long" "lNetworkEvents" }
-    { { "int" FD_MAX_EVENTS } "iErrorCode" } ;
+STRUCT: WSANETWORKEVENTS
+    { lNetworkEvents long }
+    { iErrorCode { int FD_MAX_EVENTS } } ;
 TYPEDEF: WSANETWORKEVENTS* PWSANETWORKEVENTS
 TYPEDEF: WSANETWORKEVENTS* LPWSANETWORKEVENTS
 
-! C-STRUCT: WSAOVERLAPPED
-    ! { "DWORD" "Internal" }
-    ! { "DWORD" "InternalHigh" }
-    ! { "DWORD" "Offset" }
-    ! { "DWORD" "OffsetHigh" }
-    ! { "WSAEVENT" "hEvent" }
-    ! { "DWORD" "bytesTransferred" } ;
+! STRUCT: WSAOVERLAPPED
+    ! { Internal DWORD }
+    ! { InternalHigh DWORD }
+    ! { Offset DWORD }
+    ! { OffsetHigh DWORD }
+    ! { hEvent WSAEVENT }
+    ! { bytesTransferred DWORD } ;
 ! TYPEDEF: WSAOVERLAPPED* LPWSAOVERLAPPED
 
 FUNCTION: SOCKET WSAAccept ( SOCKET s,
@@ -377,43 +383,57 @@ FUNCTION: DWORD WSAWaitForMultipleEvents ( DWORD cEvents,
 
 LIBRARY: mswsock
 
-! Not in Windows CE
 FUNCTION: int AcceptEx ( void* listen, void* accept, void* out-buf, int recv-len, int addr-len, int remote-len, void* out-len, void* overlapped ) ;
-FUNCTION: void GetAcceptExSockaddrs ( void* a, int b, int c, int d, void* e, void* f, void* g, void* h ) ;
+
+FUNCTION: void GetAcceptExSockaddrs (
+  PVOID lpOutputBuffer,
+  DWORD dwReceiveDataLength,
+  DWORD dwLocalAddressLength,
+  DWORD dwRemoteAddressLength,
+  LPSOCKADDR* LocalSockaddr,
+  LPINT LocalSockaddrLength,
+  LPSOCKADDR* RemoteSockaddr,
+  LPINT RemoteSockaddrLength
+) ;
 
 CONSTANT: SIO_GET_EXTENSION_FUNCTION_POINTER -939524090
 
 CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
 
+ERROR: winsock-exception n string ;
+
 : winsock-expected-error? ( n -- ? )
     ${ ERROR_IO_PENDING ERROR_SUCCESS WSA_IO_PENDING } member? ;
 
-: (winsock-error-string) ( n -- str )
+: (maybe-winsock-exception) ( n -- winsock-exception/f )
     ! #! WSAStartup returns the error code 'n' directly
     dup winsock-expected-error?
-    [ drop f ] [ n>win32-error-string ] if ;
+    [ drop f ] [ [ ] [ n>win32-error-string ] bi \ winsock-exception boa ] if ;
 
-: winsock-error-string ( -- string/f )
-    WSAGetLastError (winsock-error-string) ;
+: maybe-winsock-exception ( -- winsock-exception/f )
+    WSAGetLastError (maybe-winsock-exception) ;
 
 : winsock-error ( -- )
-    winsock-error-string [ throw ] when* ;
+    maybe-winsock-exception [ throw ] when* ;
+
+: (throw-winsock-error) ( n -- * )
+    [ ] [ n>win32-error-string ] bi winsock-exception ;
 
+: throw-winsock-error ( -- * )
+    WSAGetLastError (throw-winsock-error) ;
+    
 : winsock-error=0/f ( n/f -- )
-    { 0 f } member? [
-        winsock-error-string throw
-    ] when ;
+    { 0 f } member? [ throw-winsock-error ] when ;
 
 : winsock-error!=0/f ( n/f -- )
-    { 0 f } member? [
-        winsock-error-string throw
-    ] unless ;
+    { 0 f } member? [ throw-winsock-error ] unless ;
 
+! WSAStartup and WSACleanup return the error code directly
 : winsock-return-check ( n/f -- )
     dup { 0 f } member? [
         drop
     ] [
-        (winsock-error-string) throw
+        [ ] [ n>win32-error-string ] bi winsock-exception
     ] if ;
 
 : socket-error* ( n -- )
@@ -422,7 +442,7 @@ CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
         dup WSA_IO_PENDING = [
             drop
         ] [
-            (winsock-error-string) throw
+            (maybe-winsock-exception) throw
         ] if
     ] when ;
 
@@ -430,4 +450,9 @@ CONSTANT: WSAID_CONNECTEX GUID: {25a207b9-ddf3-4660-8ee9-76e58c74063e}
     SOCKET_ERROR = [ winsock-error ] when ;
 
 : init-winsock ( -- )
-    HEX: 0202 <wsadata> WSAStartup winsock-return-check ;
+    0x0202 <wsadata> WSAStartup winsock-return-check ;
+
+: shutdown-winsock ( -- ) WSACleanup winsock-return-check ;
+
+[ init-winsock ] "windows.winsock" add-startup-hook
+[ shutdown-winsock ] "windows.winsock" add-shutdown-hook