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.
|
2010-09-23 14:19:15 -04:00
|
|
|
USING: accessors alien alien.c-types alien.data alien.strings
|
2012-07-19 03:53:09 -04:00
|
|
|
classes.struct combinators destructors io.backend.unix
|
|
|
|
io.encodings.utf8 io.pathnames io.sockets.private kernel libc
|
|
|
|
locals math namespaces sequences system unix unix.ffi vocabs ;
|
2009-05-13 23:15:48 -04:00
|
|
|
EXCLUDE: io => read write ;
|
2008-04-20 06:15:46 -04:00
|
|
|
EXCLUDE: io.sockets => accept ;
|
2008-12-14 21:03:00 -05:00
|
|
|
IN: io.sockets.unix
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2010-09-21 12:15:33 -04:00
|
|
|
: socket-fd ( domain type protocol -- fd )
|
|
|
|
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 -- )
|
2010-10-20 18:42:53 -04:00
|
|
|
[ handle-fd ] 2dip 1 int <ref> dup byte-length 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
|
|
|
|
2009-09-04 06:02:33 -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 )
|
|
|
|
{
|
2010-09-04 17:42:05 -04:00
|
|
|
{ AF_INET [ T{ ipv4 } ] }
|
|
|
|
{ AF_INET6 [ T{ ipv6 } ] }
|
2009-09-04 06:02:33 -04:00
|
|
|
{ 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 )
|
2010-10-20 18:42:53 -04:00
|
|
|
[ handle-fd ] dip empty-sockaddr/size int <ref>
|
2008-05-14 04:55:33 -04:00
|
|
|
[ getsockname io-error ] 2keep drop ;
|
2008-05-12 19:53:22 -04:00
|
|
|
|
2008-05-15 20:05:07 -04:00
|
|
|
M: object (get-remote-address) ( handle local -- sockaddr )
|
2010-10-20 18:42:53 -04:00
|
|
|
[ handle-fd ] dip empty-sockaddr/size int <ref>
|
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 -- )
|
2011-08-26 14:55:52 -04:00
|
|
|
dup handle>> handle-fd f 0 write
|
2008-05-14 20:03:07 -04:00
|
|
|
{
|
2008-05-14 20:41:39 -04:00
|
|
|
{ [ 0 = ] [ drop ] }
|
2009-02-06 19:22:28 -05:00
|
|
|
{ [ 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
|
|
|
|
2010-01-19 17:53:15 -05:00
|
|
|
M:: object establish-connection ( client-out remote -- )
|
|
|
|
client-out remote
|
|
|
|
[ 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 ] }
|
2010-01-19 17:53:15 -05:00
|
|
|
{ [ errno EINTR = ] [ drop client-out remote establish-connection ] }
|
2009-02-06 19:22:28 -05:00
|
|
|
{ [ 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 ;
|
2008-05-12 19:53:22 -04:00
|
|
|
|
2009-09-27 11:31:02 -04:00
|
|
|
: ?bind-client ( socket -- )
|
2010-01-19 17:53:15 -05:00
|
|
|
bind-local-address get [
|
|
|
|
[ fd>> ] dip make-sockaddr/size
|
2010-01-23 10:07:35 -05:00
|
|
|
[ bind ] unix-system-call drop
|
2010-01-19 17:53:15 -05:00
|
|
|
] [
|
|
|
|
drop
|
|
|
|
] if* ; inline
|
2009-09-27 11:31:02 -04:00
|
|
|
|
2008-05-12 19:53:22 -04:00
|
|
|
M: object ((client)) ( addrspec -- fd )
|
2010-09-21 12:15:33 -04:00
|
|
|
[ protocol-family SOCK_STREAM ] [ protocol ] bi socket-fd
|
2009-09-27 11:31:02 -04:00
|
|
|
[ 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
|
|
|
|
2008-05-12 19:53:22 -04:00
|
|
|
: server-socket-fd ( addrspec type -- fd )
|
2010-09-21 12:15:33 -04:00
|
|
|
[ dup protocol-family ] dip pick protocol socket-fd
|
2009-08-30 23:21:14 -04:00
|
|
|
[ init-server-socket ] keep
|
2010-01-23 10:07:35 -05:00
|
|
|
[ handle-fd swap make-sockaddr/size [ bind ] unix-system-call drop ] keep ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-05-14 20:41:39 -04:00
|
|
|
M: object (server) ( addrspec -- handle )
|
2008-05-12 19:53:22 -04:00
|
|
|
[
|
2008-05-14 20:41:39 -04:00
|
|
|
SOCK_STREAM server-socket-fd
|
2010-01-23 10:07:35 -05:00
|
|
|
dup handle-fd 128 [ listen ] unix-system-call drop
|
2008-05-12 19:53:22 -04:00
|
|
|
] with-destructors ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
2008-05-16 01:57:52 -04:00
|
|
|
: do-accept ( server addrspec -- fd sockaddr )
|
2010-10-20 18:42:53 -04:00
|
|
|
[ handle>> handle-fd ] [ empty-sockaddr/size int <ref> ] bi*
|
2008-05-16 01:57:52 -04:00
|
|
|
[ 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
|
|
|
{
|
2008-12-02 04:10:13 -05:00
|
|
|
{ [ over 0 >= ] [ [ 2nip <fd> init-fd ] dip ] }
|
2009-02-06 19:22:28 -05:00
|
|
|
{ [ 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
|
|
|
|
2010-09-21 23:00:18 -04:00
|
|
|
M: unix (raw)
|
|
|
|
[ SOCK_RAW server-socket-fd ] with-destructors ;
|
|
|
|
|
2012-05-29 13:46:19 -04:00
|
|
|
M: unix (broadcast)
|
|
|
|
dup handle>> SOL_SOCKET SO_BROADCAST set-socket-option ;
|
|
|
|
|
2011-10-16 22:37:21 -04:00
|
|
|
:: do-receive ( n buf port -- count sockaddr )
|
2009-10-28 17:11:33 -04:00
|
|
|
port addr>> empty-sockaddr/size :> ( sockaddr len )
|
2009-09-04 06:02:33 -04:00
|
|
|
port handle>> handle-fd ! s
|
2011-10-16 22:37:21 -04:00
|
|
|
buf ! buf
|
|
|
|
n ! nbytes
|
2009-09-04 06:02:33 -04:00
|
|
|
0 ! flags
|
|
|
|
sockaddr ! from
|
2010-10-20 18:42:53 -04:00
|
|
|
len int <ref> ! fromlen
|
2011-10-16 22:37:21 -04:00
|
|
|
recvfrom sockaddr ; inline
|
|
|
|
|
|
|
|
: (receive-loop) ( n buf datagram -- count sockaddr )
|
|
|
|
3dup do-receive over 0 > [ [ 3drop ] 2dip ] [
|
|
|
|
2drop [ +input+ wait-for-port ] [ (receive-loop) ] bi
|
|
|
|
] if ; inline recursive
|
2008-05-13 19:24:46 -04:00
|
|
|
|
2011-10-18 00:18:16 -04:00
|
|
|
M: unix (receive-unsafe) ( n buf datagram -- count sockaddr )
|
2011-10-16 22:37:21 -04:00
|
|
|
(receive-loop) ;
|
2007-09-20 18:09:08 -04:00
|
|
|
|
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 < [
|
2009-02-06 19:22:28 -05:00
|
|
|
errno EINTR = [
|
2008-05-13 19:24:46 -04:00
|
|
|
packet sockaddr len socket datagram do-send
|
|
|
|
] [
|
2009-02-06 19:22:28 -05:00
|
|
|
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
|
2011-10-16 22:37:21 -04:00
|
|
|
] when ; inline recursive
|
2008-05-13 19:24:46 -04:00
|
|
|
|
|
|
|
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
|
2009-10-28 18:25:50 -04:00
|
|
|
path>> absolute-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> ;
|
2010-09-23 14:19:15 -04:00
|
|
|
|
|
|
|
os linux? [ "io.sockets.unix.linux" require ] when
|