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

185 lines
5.2 KiB
Factor
Raw Normal View History

! 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: accessors alien alien.c-types alien.data alien.strings
arrays byte-arrays classes.struct combinators destructors
io.backend.unix io.encodings.ascii io.encodings.utf8 io.files
io.pathnames io.sockets.private kernel libc locals math
namespaces sequences system unix unix.ffi vocabs ;
2008-04-20 06:15:46 -04:00
EXCLUDE: io.sockets => accept ;
IN: io.sockets.unix
2007-09-20 18:09:08 -04:00
: socket-fd ( domain type protocol -- fd )
socket dup io-error <fd> init-fd |dispose ;
2007-09-20 18:09:08 -04:00
: get-socket-option ( fd level opt -- val )
[ handle-fd ] 2dip -1 int <ref> [
dup byte-length int <ref> getsockopt io-error
] keep int deref ;
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
2014-11-20 22:46:14 -05:00
M: unix addrinfo-error-string
gai_strerror ;
2007-09-20 18:09:08 -04:00
2014-11-20 22:46:14 -05:00
M: unix sockaddr-of-family
{
{ AF_INET [ sockaddr-in memory>struct ] }
{ AF_INET6 [ sockaddr-in6 memory>struct ] }
{ AF_UNIX [ sockaddr-un memory>struct ] }
[ 2drop f ]
} case ;
2014-11-20 22:46:14 -05:00
M: unix addrspec-of-family
{
2010-09-04 17:42:05 -04:00
{ AF_INET [ T{ ipv4 } ] }
{ AF_INET6 [ T{ ipv6 } ] }
{ AF_UNIX [ T{ local } ] }
[ drop f ]
} case ;
2007-09-20 18:09:08 -04:00
! Client sockets - TCP and Unix domain
2014-11-20 22:46:14 -05:00
M: object (get-local-address)
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 ;
2014-11-20 22:46:14 -05:00
M: object (get-remote-address)
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 -- )
dup +output+ wait-for-port
dup handle>> SOL_SOCKET SO_ERROR get-socket-option
[ drop ] [ (throw-errno) ] if-zero ; inline
2014-11-20 22:46:14 -05:00
M: object establish-connection
2dup
[ handle>> handle-fd ] [ make-sockaddr/size ] bi*
connect 0 = [ 2drop ] [
errno {
{ EINTR [ establish-connection ] }
{ EINPROGRESS [ drop wait-to-connect ] }
2014-11-21 13:19:12 -05:00
[ (throw-errno) ]
2014-11-20 22:46:14 -05:00
} case
] if ;
: ?bind-client ( socket -- )
bind-local-address get [
[ fd>> ] dip make-sockaddr/size
[ bind ] unix-system-call drop
] [
drop
] if* ; inline
M: object remote>handle
[ protocol-family SOCK_STREAM ] [ protocol ] bi 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 pick protocol socket-fd
[ init-server-socket ] keep
[ handle-fd swap make-sockaddr/size [ bind ] unix-system-call drop ] keep ;
2007-09-20 18:09:08 -04:00
2014-11-20 22:46:14 -05:00
M: object (server)
[
2008-05-14 20:41:39 -04:00
SOCK_STREAM server-socket-fd
dup handle-fd 128 [ listen ] unix-system-call drop
] 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
2014-11-20 22:46:14 -05:00
M: object (accept)
2dup do-accept over 0 >= [
[ 2nip <fd> init-fd ] dip
] [
errno {
{ EINTR [ 2drop (accept) ] }
{ EAGAIN [
2drop
[ drop +input+ wait-for-port ]
[ (accept) ]
2bi
] }
2014-11-21 13:19:12 -05:00
[ (throw-errno) ]
2014-11-20 22:46:14 -05:00
} case
] if ;
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
M: unix (raw)
[ SOCK_RAW server-socket-fd ] with-destructors ;
M: unix (broadcast)
dup handle>> SOL_SOCKET SO_BROADCAST set-socket-option ;
:: do-receive ( n buf port -- count sockaddr )
port addr>> empty-sockaddr/size :> ( sockaddr len )
port handle>> handle-fd ! s
buf ! buf
n ! nbytes
0 ! flags
sockaddr ! from
2010-10-20 18:42:53 -04:00
len int <ref> ! fromlen
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
2014-11-20 22:46:14 -05:00
M: unix (receive-unsafe)
(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 < [
2014-11-20 22:46:14 -05:00
errno {
{ EINTR [
packet sockaddr len socket datagram do-send
] }
{ EAGAIN [
2008-05-13 19:24:46 -04:00
datagram +output+ wait-for-port
packet sockaddr len socket datagram do-send
2014-11-20 22:46:14 -05:00
] }
2014-11-21 13:19:12 -05:00
[ (throw-errno) ]
2014-11-20 22:46:14 -05:00
} case
] when ; inline recursive
2008-05-13 19:24:46 -04:00
2014-11-20 22:46:14 -05:00
M: unix (send)
[ make-sockaddr/size-outgoing ] [ [ handle>> ] keep ] bi* do-send ;
2008-05-13 19:24:46 -04:00
! 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
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> ;
M: unix host-name
256 [ <byte-array> dup ] keep gethostname io-error
ascii alien>string ;
os linux? [ "io.sockets.unix.linux" require ] when