factor/basis/io/sockets/unix/unix.factor

175 lines
5.1 KiB
Factor
Raw Normal View History

2008-02-21 16:22:49 -05:00
! Copyright (C) 2004, 2008 Slava Pestov, Ivan Tikhonov.
2007-09-20 18:09:08 -04:00
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.c-types alien.strings generic kernel math
threads sequences byte-arrays io.binary io.backend.unix
io.streams.duplex io.backend io.pathnames io.sockets.private
io.files.private io.encodings.utf8 math.parser continuations
libc combinators system accessors destructors unix locals init
classes.struct alien.data ;
2008-04-20 06:15:46 -04:00
EXCLUDE: namespaces => bind ;
EXCLUDE: io => read write ;
2008-04-20 06:15:46 -04:00
EXCLUDE: io.sockets => accept ;
2007-09-20 18:09:08 -04:00
IN: io.sockets.unix
2007-09-20 18:09:08 -04:00
2008-05-14 04:55:33 -04:00
: socket-fd ( domain type -- fd )
2008-07-03 18:44:44 -04:00
0 socket dup io-error <fd> init-fd |dispose ;
2007-09-20 18:09:08 -04:00
2008-05-14 04:55:33 -04:00
: set-socket-option ( fd level opt -- )
[ handle-fd ] 2dip 1 <int> "int" heap-size setsockopt io-error ;
2007-09-20 18:09:08 -04:00
2008-04-02 21:33:36 -04:00
M: unix addrinfo-error ( n -- )
2009-08-11 19:15:53 -04:00
[ gai_strerror throw ] unless-zero ;
2007-09-20 18:09:08 -04:00
M: unix sockaddr-of-family ( alien af -- addrspec )
{
{ AF_INET [ sockaddr-in memory>struct ] }
{ AF_INET6 [ sockaddr-in6 memory>struct ] }
{ AF_UNIX [ sockaddr-un memory>struct ] }
[ 2drop f ]
} case ;
M: unix addrspec-of-family ( af -- addrspec )
{
{ AF_INET [ T{ inet4 } ] }
{ AF_INET6 [ T{ inet6 } ] }
{ AF_UNIX [ T{ local } ] }
[ drop f ]
} case ;
2007-09-20 18:09:08 -04:00
! Client sockets - TCP and Unix domain
2008-05-14 20:41:39 -04:00
M: object (get-local-address) ( handle remote -- sockaddr )
[ handle-fd ] dip empty-sockaddr/size <int>
2008-05-14 04:55:33 -04:00
[ getsockname io-error ] 2keep drop ;
2008-05-15 20:05:07 -04:00
M: object (get-remote-address) ( handle local -- sockaddr )
[ handle-fd ] dip empty-sockaddr/size <int>
2008-05-15 20:05:07 -04:00
[ getpeername io-error ] 2keep drop ;
2008-05-14 20:03:07 -04:00
: init-client-socket ( fd -- )
SOL_SOCKET SO_OOBINLINE set-socket-option ;
: wait-to-connect ( port -- )
dup handle>> handle-fd f 0 write
{
2008-05-14 20:41:39 -04:00
{ [ 0 = ] [ drop ] }
{ [ errno EAGAIN = ] [ dup +output+ wait-for-port wait-to-connect ] }
{ [ errno EINTR = ] [ wait-to-connect ] }
2008-05-14 20:03:07 -04:00
[ (io-error) ]
} cond ;
2008-05-13 21:04:57 -04:00
2008-05-14 20:03:07 -04:00
M: object establish-connection ( client-out remote -- )
2008-05-14 20:41:39 -04:00
[ drop ] [ [ handle>> handle-fd ] [ make-sockaddr/size ] bi* connect ] 2bi
2008-05-14 20:03:07 -04:00
{
2008-05-14 20:41:39 -04:00
{ [ 0 = ] [ drop ] }
{ [ errno EINPROGRESS = ] [
2008-05-14 20:41:39 -04:00
[ +output+ wait-for-port ] [ wait-to-connect ] bi
2008-05-14 20:03:07 -04:00
] }
[ (io-error) ]
} cond ;
: ?bind-client ( socket -- )
bind-local-address get [ [ fd>> ] dip make-sockaddr/size bind io-error ] [ drop ] if* ; inline
M: object ((client)) ( addrspec -- fd )
protocol-family SOCK_STREAM socket-fd
[ init-client-socket ] [ ?bind-client ] [ ] tri ;
2007-09-20 18:09:08 -04:00
! Server sockets - TCP and Unix domain
: init-server-socket ( fd -- )
2008-05-14 04:55:33 -04:00
SOL_SOCKET SO_REUSEADDR set-socket-option ;
2007-09-20 18:09:08 -04:00
: server-socket-fd ( addrspec type -- fd )
[ dup protocol-family ] dip socket-fd
[ init-server-socket ] keep
[ handle-fd swap make-sockaddr/size bind io-error ] keep ;
2007-09-20 18:09:08 -04:00
2008-05-14 20:41:39 -04:00
M: object (server) ( addrspec -- handle )
[
2008-05-14 20:41:39 -04:00
SOCK_STREAM server-socket-fd
2008-09-07 05:14:47 -04:00
dup handle-fd 128 listen io-error
] with-destructors ;
2007-09-20 18:09:08 -04:00
2008-05-16 01:57:52 -04:00
: do-accept ( server addrspec -- fd sockaddr )
[ handle>> handle-fd ] [ empty-sockaddr/size <int> ] bi*
[ accept ] 2keep drop ; inline
2008-05-13 19:24:46 -04:00
2008-05-16 01:57:52 -04:00
M: object (accept) ( server addrspec -- fd sockaddr )
2dup do-accept
2008-05-13 19:24:46 -04:00
{
{ [ over 0 >= ] [ [ 2nip <fd> init-fd ] dip ] }
{ [ errno EINTR = ] [ 2drop (accept) ] }
{ [ errno EAGAIN = ] [
2008-05-16 01:57:52 -04:00
2drop
[ drop +input+ wait-for-port ]
[ (accept) ]
2bi
2008-05-13 19:24:46 -04:00
] }
[ (io-error) ]
} cond ;
2007-09-20 18:09:08 -04:00
! Datagram sockets - UDP and Unix domain
2008-05-13 19:24:46 -04:00
M: unix (datagram)
[ SOCK_DGRAM server-socket-fd ] with-destructors ;
2007-09-20 18:09:08 -04:00
SYMBOL: receive-buffer
2009-02-22 20:13:08 -05:00
CONSTANT: packet-size 65536
2007-09-20 18:09:08 -04:00
[ packet-size malloc receive-buffer set-global ] "io.sockets.unix" add-init-hook
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
:: do-receive ( port -- packet sockaddr )
port addr>> empty-sockaddr/size :> len :> sockaddr
port handle>> handle-fd ! s
receive-buffer get-global ! buf
packet-size ! nbytes
0 ! flags
sockaddr ! from
len <int> ! fromlen
recvfrom dup 0 >=
[ receive-buffer get-global swap memory>byte-array sockaddr ]
[ drop f f ]
if ;
2008-05-13 19:24:46 -04:00
M: unix (receive) ( datagram -- packet sockaddr )
dup do-receive dup [ [ drop ] 2dip ] [
2008-05-13 19:24:46 -04:00
2drop [ +input+ wait-for-port ] [ (receive) ] bi
2007-09-20 18:09:08 -04:00
] if ;
2008-05-13 19:24:46 -04:00
:: do-send ( packet sockaddr len socket datagram -- )
2008-05-14 04:55:33 -04:00
socket handle-fd packet dup length 0 sockaddr len sendto
2008-05-13 19:24:46 -04:00
0 < [
errno EINTR = [
2008-05-13 19:24:46 -04:00
packet sockaddr len socket datagram do-send
] [
errno EAGAIN = [
2008-05-13 19:24:46 -04:00
datagram +output+ wait-for-port
packet sockaddr len socket datagram do-send
] [
(io-error)
] if
] if
] when ;
M: unix (send) ( packet addrspec datagram -- )
[ make-sockaddr/size ] [ [ handle>> ] keep ] bi* do-send ;
! Unix domain sockets
2007-09-20 18:09:08 -04:00
M: local protocol-family drop PF_UNIX ;
2009-09-03 18:08:54 -04:00
M: local sockaddr-size drop sockaddr-un heap-size ;
2008-10-02 04:38:36 -04:00
2009-09-03 18:08:54 -04:00
M: local empty-sockaddr drop sockaddr-un <struct> ;
2007-09-20 18:09:08 -04:00
M: local make-sockaddr
2008-04-20 06:15:46 -04:00
path>> (normalize-path)
2007-09-20 18:09:08 -04:00
dup length 1 + max-un-path > [ "Path too long" throw ] when
2009-09-03 18:08:54 -04:00
sockaddr-un <struct>
AF_UNIX >>family
swap utf8 string>alien >>path ;
2007-09-20 18:09:08 -04:00
M: local parse-sockaddr
drop
2009-09-03 18:08:54 -04:00
path>> utf8 alien>string <local> ;