2005-04-26 18:49:02 -04:00
|
|
|
! Copyright (C) 2004, 2005 Slava Pestov.
|
|
|
|
! See http://factor.sf.net/license.txt for BSD license.
|
|
|
|
|
|
|
|
! We need to fiddle with the exact search order here, since
|
|
|
|
! unix-internals::accept shadows streams::accept.
|
|
|
|
IN: io-internals
|
2005-08-21 20:50:14 -04:00
|
|
|
USING: alien errors generic io kernel math namespaces parser
|
|
|
|
threads unix-internals ;
|
2005-04-26 18:49:02 -04:00
|
|
|
|
2005-06-19 00:23:01 -04:00
|
|
|
: <socket-stream> ( fd -- stream )
|
|
|
|
dup f <fd-stream> ;
|
|
|
|
|
2005-04-26 18:49:02 -04:00
|
|
|
: init-sockaddr ( port -- sockaddr )
|
|
|
|
<sockaddr-in>
|
|
|
|
[ AF_INET swap set-sockaddr-in-family ] keep
|
|
|
|
[ >r htons r> set-sockaddr-in-port ] keep ;
|
|
|
|
|
|
|
|
: client-sockaddr ( host port -- sockaddr )
|
|
|
|
#! Error handling here
|
|
|
|
init-sockaddr [
|
2005-06-12 21:20:00 -04:00
|
|
|
>r gethostbyname dup [
|
|
|
|
"Host lookup failed" throw
|
|
|
|
] unless hostent-addr dup check-null
|
|
|
|
r> set-sockaddr-in-addr
|
2005-04-26 18:49:02 -04:00
|
|
|
] keep ;
|
|
|
|
|
|
|
|
: socket-fd ( -- socket )
|
|
|
|
PF_INET SOCK_STREAM 0 socket dup io-error dup init-handle ;
|
|
|
|
|
|
|
|
: with-socket-fd ( quot -- fd | quot: socket -- n )
|
|
|
|
socket-fd [ swap call ] keep swap 0 < [
|
2005-06-13 01:42:16 -04:00
|
|
|
err_no EINPROGRESS = [
|
2005-04-26 18:49:02 -04:00
|
|
|
dup close -1 io-error
|
|
|
|
] unless
|
|
|
|
] when ; inline
|
|
|
|
|
|
|
|
: client-socket ( host port -- fd )
|
|
|
|
client-sockaddr [
|
|
|
|
swap "sockaddr-in" c-size connect
|
|
|
|
] with-socket-fd ;
|
|
|
|
|
|
|
|
: server-sockaddr ( port -- sockaddr )
|
|
|
|
init-sockaddr INADDR_ANY htonl over set-sockaddr-in-addr ;
|
|
|
|
|
2005-05-23 19:14:29 -04:00
|
|
|
: sockopt ( fd level opt value -- )
|
2005-05-04 22:34:55 -04:00
|
|
|
1 <int> "int" c-size setsockopt io-error ;
|
2005-04-26 18:49:02 -04:00
|
|
|
|
|
|
|
: server-socket ( port -- fd )
|
|
|
|
server-sockaddr [
|
2005-05-04 22:34:55 -04:00
|
|
|
dup SOL_SOCKET SO_REUSEADDR sockopt
|
2005-04-26 18:49:02 -04:00
|
|
|
swap dupd "sockaddr-in" c-size bind
|
|
|
|
dup 0 >= [ drop 1 listen ] [ ( fd n - n) nip ] ifte
|
|
|
|
] with-socket-fd ;
|
|
|
|
|
2005-06-19 17:50:35 -04:00
|
|
|
IN: io
|
2005-06-18 16:42:49 -04:00
|
|
|
|
|
|
|
C: client-stream ( host port fd -- stream )
|
|
|
|
[ >r <socket-stream> r> set-delegate ] keep
|
|
|
|
[ set-client-stream-port ] keep
|
|
|
|
[ set-client-stream-host ] keep ;
|
|
|
|
|
|
|
|
: <client> ( host port -- stream )
|
|
|
|
#! Connect to a port number on a TCP/IP host.
|
|
|
|
client-socket <socket-stream> ;
|
|
|
|
|
|
|
|
TUPLE: server client ;
|
|
|
|
|
|
|
|
C: server ( port -- server )
|
|
|
|
#! Starts listening for TCP connections on localhost:port.
|
|
|
|
[ >r server-socket 0 <port> r> set-delegate ] keep ;
|
|
|
|
|
|
|
|
IN: io-internals
|
|
|
|
USE: unix-internals
|
|
|
|
|
2005-04-26 18:49:02 -04:00
|
|
|
TUPLE: accept-task ;
|
|
|
|
|
|
|
|
C: accept-task ( port -- task )
|
|
|
|
[ >r <io-task> r> set-delegate ] keep ;
|
|
|
|
|
2005-06-18 16:42:49 -04:00
|
|
|
: init-socket ( fd -- ) SOL_SOCKET SO_OOBINLINE sockopt ;
|
|
|
|
|
2005-06-18 21:15:07 -04:00
|
|
|
: inet-ntoa ( n -- str )
|
|
|
|
ntohl [
|
2005-08-31 21:06:13 -04:00
|
|
|
dup -24 shift HEX: ff bitand # CHAR: . ,
|
|
|
|
dup -16 shift HEX: ff bitand # CHAR: . ,
|
|
|
|
dup -8 shift HEX: ff bitand # CHAR: . ,
|
|
|
|
HEX: ff bitand #
|
2005-08-25 15:27:38 -04:00
|
|
|
] "" make ;
|
2005-06-18 21:15:07 -04:00
|
|
|
|
2005-06-18 16:42:49 -04:00
|
|
|
: do-accept ( port sockaddr fd -- )
|
|
|
|
[
|
|
|
|
init-socket
|
|
|
|
dup sockaddr-in-addr inet-ntoa
|
|
|
|
swap sockaddr-in-port ntohs
|
|
|
|
] keep <client-stream> swap set-server-client ;
|
|
|
|
|
|
|
|
M: accept-task do-io-task ( task -- ? )
|
|
|
|
io-task-port <sockaddr-in>
|
|
|
|
over port-handle over "sockaddr-in" c-size <int> accept
|
2005-06-18 21:15:07 -04:00
|
|
|
dup 0 >= [
|
|
|
|
do-accept t
|
|
|
|
] [
|
|
|
|
2drop defer-error
|
|
|
|
] ifte ;
|
2005-04-26 18:49:02 -04:00
|
|
|
|
2005-06-13 01:42:16 -04:00
|
|
|
M: accept-task task-container drop read-tasks get ;
|
2005-04-26 18:49:02 -04:00
|
|
|
|
|
|
|
: wait-to-accept ( server -- )
|
2005-04-30 00:43:39 -04:00
|
|
|
[ swap <accept-task> add-io-task stop ] callcc0 drop ;
|
2005-04-26 18:49:02 -04:00
|
|
|
|
2005-05-23 19:14:29 -04:00
|
|
|
: timeout-opt ( fd level opt value -- )
|
|
|
|
"timeval" c-size setsockopt io-error ;
|
|
|
|
|
2005-06-19 17:50:35 -04:00
|
|
|
IN: io
|
2005-04-26 18:49:02 -04:00
|
|
|
|
|
|
|
: accept ( server -- client )
|
|
|
|
#! Wait for a client connection.
|
2005-06-18 21:15:07 -04:00
|
|
|
dup wait-to-accept dup pending-error server-client ;
|