USING: alien alien.accessors alien.c-types alien.data byte-arrays continuations destructors io.ports io.timeouts io.sockets io.sockets.private io namespaces io.streams.duplex io.backend.windows io.sockets.windows io.backend.windows.nt windows.winsock kernel libc math sequences threads system combinators accessors classes.struct windows.kernel32 windows.types ; IN: io.sockets.windows.nt : malloc-int ( n -- alien ) malloc-byte-array ; inline M: winnt WSASocket-flags ( -- DWORD ) WSA_FLAG_OVERLAPPED ; : get-ConnectEx-ptr ( socket -- void* ) SIO_GET_EXTENSION_FUNCTION_POINTER WSAID_CONNECTEX GUID heap-size { void* } [ void* heap-size DWORD f f WSAIoctl SOCKET_ERROR = [ winsock-error-string throw ] when ] [ ] with-out-parameters ; TUPLE: ConnectEx-args port s name namelen lpSendBuffer dwSendDataLength lpdwBytesSent lpOverlapped ptr ; : wait-for-socket ( args -- n ) [ lpOverlapped>> ] [ port>> ] bi twiddle-thumbs ; inline : ( sockaddr size -- ConnectEx ) ConnectEx-args new swap >>namelen swap >>name f >>lpSendBuffer 0 >>dwSendDataLength f >>lpdwBytesSent (make-overlapped) >>lpOverlapped ; inline : call-ConnectEx ( ConnectEx -- ) { [ s>> ] [ name>> ] [ namelen>> ] [ lpSendBuffer>> ] [ dwSendDataLength>> ] [ lpdwBytesSent>> ] [ lpOverlapped>> ] [ ptr>> ] } cleave int { SOCKET void* int PVOID DWORD LPDWORD void* } stdcall alien-indirect drop winsock-error-string [ throw ] when* ; inline M: object establish-connection ( client-out remote -- ) make-sockaddr/size swap >>port dup port>> handle>> handle>> >>s dup s>> get-ConnectEx-ptr >>ptr dup call-ConnectEx wait-for-socket drop ; TUPLE: AcceptEx-args port sListenSocket sAcceptSocket lpOutputBuffer dwReceiveDataLength dwLocalAddressLength dwRemoteAddressLength lpdwBytesReceived lpOverlapped ; : init-accept-buffer ( addr AcceptEx -- ) swap sockaddr-size 16 + [ >>dwLocalAddressLength ] [ >>dwRemoteAddressLength ] bi dup dwLocalAddressLength>> 2 * malloc &free >>lpOutputBuffer drop ; inline : ( server addr -- AcceptEx ) AcceptEx-args new 2dup init-accept-buffer swap SOCK_STREAM open-socket |dispose handle>> >>sAcceptSocket over handle>> handle>> >>sListenSocket swap >>port 0 >>dwReceiveDataLength f >>lpdwBytesReceived (make-overlapped) >>lpOverlapped ; inline : call-AcceptEx ( AcceptEx -- ) { [ sListenSocket>> ] [ sAcceptSocket>> ] [ lpOutputBuffer>> ] [ dwReceiveDataLength>> ] [ dwLocalAddressLength>> ] [ dwRemoteAddressLength>> ] [ lpdwBytesReceived>> ] [ lpOverlapped>> ] } cleave AcceptEx drop winsock-error-string [ throw ] when* ; inline : (extract-remote-address) ( lpOutputBuffer dwReceiveDataLength dwLocalAddressLength dwRemoteAddressLength -- sockaddr ) f 0 f [ 0 GetAcceptExSockaddrs ] keep *void* ; : extract-remote-address ( AcceptEx -- sockaddr ) [ { [ lpOutputBuffer>> ] [ dwReceiveDataLength>> ] [ dwLocalAddressLength>> ] [ dwRemoteAddressLength>> ] } cleave (extract-remote-address) ] [ port>> addr>> protocol-family ] bi sockaddr-of-family ; inline M: object (accept) ( server addr -- handle sockaddr ) [ { [ call-AcceptEx ] [ wait-for-socket drop ] [ sAcceptSocket>> ] [ extract-remote-address ] } cleave ] with-destructors ; TUPLE: WSARecvFrom-args port s lpBuffers dwBufferCount lpNumberOfBytesRecvd lpFlags lpFrom lpFromLen lpOverlapped lpCompletionRoutine ; : make-receive-buffer ( -- WSABUF ) WSABUF malloc-struct &free default-buffer-size get [ >>len ] [ malloc &free >>buf ] bi ; inline : ( datagram -- WSARecvFrom ) WSARecvFrom-args new swap >>port dup port>> handle>> handle>> >>s dup port>> addr>> sockaddr-size [ malloc &free >>lpFrom ] [ malloc-int &free >>lpFromLen ] bi make-receive-buffer >>lpBuffers 1 >>dwBufferCount 0 malloc-int &free >>lpFlags 0 malloc-int &free >>lpNumberOfBytesRecvd (make-overlapped) >>lpOverlapped ; inline : call-WSARecvFrom ( WSARecvFrom -- ) { [ s>> ] [ lpBuffers>> ] [ dwBufferCount>> ] [ lpNumberOfBytesRecvd>> ] [ lpFlags>> ] [ lpFrom>> ] [ lpFromLen>> ] [ lpOverlapped>> ] [ lpCompletionRoutine>> ] } cleave WSARecvFrom socket-error* ; inline : parse-WSARecvFrom ( n WSARecvFrom -- packet sockaddr ) [ lpBuffers>> buf>> swap memory>byte-array ] [ [ port>> addr>> empty-sockaddr dup ] [ lpFrom>> ] [ lpFromLen>> *int ] tri memcpy ] bi ; inline M: winnt (receive) ( datagram -- packet addrspec ) [ [ call-WSARecvFrom ] [ wait-for-socket ] [ parse-WSARecvFrom ] tri ] with-destructors ; TUPLE: WSASendTo-args port s lpBuffers dwBufferCount lpNumberOfBytesSent dwFlags lpTo iToLen lpOverlapped lpCompletionRoutine ; : make-send-buffer ( packet -- WSABUF ) [ WSABUF malloc-struct &free ] dip [ malloc-byte-array &free >>buf ] [ length >>len ] bi ; inline : ( packet addrspec datagram -- WSASendTo ) WSASendTo-args new swap >>port dup port>> handle>> handle>> >>s swap make-sockaddr/size [ malloc-byte-array &free ] dip [ >>lpTo ] [ >>iToLen ] bi* swap make-send-buffer >>lpBuffers 1 >>dwBufferCount 0 >>dwFlags 0 >>lpNumberOfBytesSent (make-overlapped) >>lpOverlapped ; inline : call-WSASendTo ( WSASendTo -- ) { [ s>> ] [ lpBuffers>> ] [ dwBufferCount>> ] [ lpNumberOfBytesSent>> ] [ dwFlags>> ] [ lpTo>> ] [ iToLen>> ] [ lpOverlapped>> ] [ lpCompletionRoutine>> ] } cleave WSASendTo socket-error* ; inline M: winnt (send) ( packet addrspec datagram -- ) [ [ call-WSASendTo ] [ wait-for-socket drop ] bi ] with-destructors ;