factor/extra/io/unix/sockets/sockets.factor

142 lines
3.9 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.
2008-04-20 06:15:46 -04:00
USING: alien alien.c-types alien.strings generic kernel math
2008-05-13 19:24:46 -04:00
namespaces threads sequences byte-arrays io.ports
io.binary io.unix.backend io.streams.duplex
io.backend io.ports io.files io.files.private
2008-05-12 23:30:18 -04:00
io.encodings.utf8 math.parser continuations libc combinators
2008-05-13 19:24:46 -04:00
system accessors qualified destructors unix locals ;
2008-04-20 06:15:46 -04:00
EXCLUDE: io => read write close ;
EXCLUDE: io.sockets => accept ;
2007-09-20 18:09:08 -04:00
IN: io.unix.sockets
2007-09-20 18:09:08 -04:00
: socket-fd ( domain type -- socket )
0 socket
dup io-error
dup close-later
dup init-handle ;
2007-09-20 18:09:08 -04:00
: sockopt ( fd level opt -- )
1 <int> "int" heap-size setsockopt io-error ;
2008-04-02 21:33:36 -04:00
M: unix addrinfo-error ( n -- )
2007-09-20 18:09:08 -04:00
dup zero? [ drop ] [ gai_strerror throw ] if ;
! Client sockets - TCP and Unix domain
: init-client-socket ( fd -- )
SOL_SOCKET SO_OOBINLINE sockopt ;
2008-05-13 19:24:46 -04:00
: get-socket-name ( fd addrspec -- sockaddr )
empty-sockaddr/size [ getsockname io-error ] 2keep drop ;
M: integer (wait-to-connect)
2008-05-13 19:24:46 -04:00
>r >r +output+ wait-for-port r> r> get-socket-name ;
M: object ((client)) ( addrspec -- fd )
[ protocol-family SOCK_STREAM socket-fd ] [ make-sockaddr/size ] bi
[ 2drop ] [ connect ] 3bi
zero? err_no EINPROGRESS = or
[ dup init-client-socket ] [ (io-error) ] if ;
2007-09-20 18:09:08 -04:00
! Server sockets - TCP and Unix domain
: init-server-socket ( fd -- )
SOL_SOCKET SO_REUSEADDR sockopt ;
: server-socket-fd ( addrspec type -- fd )
>r dup protocol-family r> socket-fd
2007-09-20 18:09:08 -04:00
dup init-server-socket
2008-05-13 19:24:46 -04:00
dup rot make-sockaddr/size bind io-error ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
M: object (server) ( addrspec -- handle sockaddr )
[
2008-05-13 19:24:46 -04:00
[
SOCK_STREAM server-socket-fd
dup 10 listen io-error
dup
] keep
get-socket-name
] with-destructors ;
2007-09-20 18:09:08 -04:00
2008-05-13 19:24:46 -04:00
: do-accept ( server -- fd sockaddr )
[ handle>> ] [ addr>> empty-sockaddr/size ] bi
[ accept ] 2keep drop ; inline
M: unix (accept) ( server -- fd sockaddr )
dup do-accept
{
{ [ over 0 >= ] [ rot drop ] }
{ [ err_no EINTR = ] [ 2drop do-accept ] }
{ [ err_no EAGAIN = ] [
2drop
[ +input+ wait-for-port ]
[ do-accept ] bi
] }
[ (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
: packet-size 65536 ; inline
packet-size <byte-array> receive-buffer set-global
2008-05-13 19:24:46 -04:00
:: do-receive ( port -- packet sockaddr )
port addr>> empty-sockaddr/size [| sockaddr len |
port handle>> ! s
receive-buffer get-global ! buf
packet-size ! nbytes
0 ! flags
sockaddr ! from
len ! fromlen
recvfrom dup 0 >= [
receive-buffer get-global swap head sockaddr
] [
drop f f
] if
] call ;
M: unix (receive) ( datagram -- packet sockaddr )
dup do-receive dup [ rot drop ] [
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 -- )
socket packet dup length 0 sockaddr len sendto
0 < [
err_no EINTR = [
packet sockaddr len socket datagram do-send
] [
err_no EAGAIN = [
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 ;
M: local sockaddr-type drop "sockaddr-un" c-type ;
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
"sockaddr-un" <c-object>
AF_UNIX over set-sockaddr-un-family
2008-04-20 06:15:46 -04:00
dup sockaddr-un-path rot utf8 string>alien dup length memcpy ;
2007-09-20 18:09:08 -04:00
M: local parse-sockaddr
drop
2008-04-20 06:15:46 -04:00
sockaddr-un-path utf8 alien>string <local> ;