factor/library/io/unix/sockets.factor

115 lines
3.2 KiB
Factor
Raw Normal View History

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
USING: alien errors generic io kernel math namespaces parser
threads unix-internals ;
2005-04-26 18:49:02 -04:00
: init-sockaddr ( port -- sockaddr )
2005-12-25 17:46:21 -05:00
"sockaddr-in" <c-object>
2005-04-26 18:49:02 -04:00
[ 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 < [
2006-02-02 15:51:12 -05:00
err_no EINPROGRESS = [ dup close (io-error) ] unless
2005-04-26 18:49:02 -04:00
] 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 -- )
1 <int> "int" c-size setsockopt io-error ;
2005-04-26 18:49:02 -04:00
: server-socket ( port -- fd )
server-sockaddr [
dup SOL_SOCKET SO_REUSEADDR sockopt
2005-04-26 18:49:02 -04:00
swap dupd "sockaddr-in" c-size bind
2005-09-24 15:21:17 -04:00
dup 0 >= [ drop 1 listen ] [ ( fd n - n) nip ] if
2005-04-26 18:49:02 -04:00
] with-socket-fd ;
IN: io
C: client-stream ( host port fd -- stream )
2005-12-16 21:12:35 -05:00
[ >r dup <fd-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.
2005-12-16 21:12:35 -05:00
client-socket dup <fd-stream> ;
TUPLE: server client ;
C: server ( port -- server )
#! Starts listening for TCP connections on localhost:port.
2006-02-24 22:40:36 -05:00
[ >r server-socket f <port> r> set-delegate ] keep
2005-09-18 23:22:58 -04:00
server over set-port-type ;
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 ;
: init-socket ( fd -- ) SOL_SOCKET SO_OOBINLINE sockopt ;
2005-06-18 21:15:07 -04:00
: inet-ntoa ( n -- str )
ntohl [
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
: 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 -- ? )
2005-12-25 17:46:21 -05:00
io-task-port "sockaddr-in" <c-object>
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
2005-09-24 15:21:17 -04:00
] if ;
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-09-18 01:37:28 -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 ;
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 ;