1 ! Copyright (C) 2004, 2008 Slava Pestov, Ivan Tikhonov.
2 ! See http://factorcode.org/license.txt for BSD license.
3 USING: alien alien.c-types alien.strings generic kernel math
4 threads sequences byte-arrays io.binary io.backend.unix
5 io.streams.duplex io.backend io.pathnames io.sockets.private
6 io.files.private io.encodings.utf8 math.parser continuations
7 libc combinators system accessors destructors unix locals init
8 classes.struct alien.data ;
10 EXCLUDE: namespaces => bind ;
11 EXCLUDE: io => read write ;
12 EXCLUDE: io.sockets => accept ;
16 : socket-fd ( domain type -- fd )
17 0 socket dup io-error <fd> init-fd |dispose ;
19 : set-socket-option ( fd level opt -- )
20 [ handle-fd ] 2dip 1 <int> "int" heap-size setsockopt io-error ;
22 M: unix addrinfo-error ( n -- )
23 [ gai_strerror throw ] unless-zero ;
25 M: unix sockaddr-of-family ( alien af -- addrspec )
27 { AF_INET [ sockaddr-in memory>struct ] }
28 { AF_INET6 [ sockaddr-in6 memory>struct ] }
29 { AF_UNIX [ sockaddr-un memory>struct ] }
33 M: unix addrspec-of-family ( af -- addrspec )
35 { AF_INET [ T{ inet4 } ] }
36 { AF_INET6 [ T{ inet6 } ] }
37 { AF_UNIX [ T{ local } ] }
41 ! Client sockets - TCP and Unix domain
42 M: object (get-local-address) ( handle remote -- sockaddr )
43 [ handle-fd ] dip empty-sockaddr/size <int>
44 [ getsockname io-error ] 2keep drop ;
46 M: object (get-remote-address) ( handle local -- sockaddr )
47 [ handle-fd ] dip empty-sockaddr/size <int>
48 [ getpeername io-error ] 2keep drop ;
50 : init-client-socket ( fd -- )
51 SOL_SOCKET SO_OOBINLINE set-socket-option ;
53 : wait-to-connect ( port -- )
54 dup handle>> handle-fd f 0 write
57 { [ errno EAGAIN = ] [ dup +output+ wait-for-port wait-to-connect ] }
58 { [ errno EINTR = ] [ wait-to-connect ] }
62 M: object establish-connection ( client-out remote -- )
63 [ drop ] [ [ handle>> handle-fd ] [ make-sockaddr/size ] bi* connect ] 2bi
66 { [ errno EINPROGRESS = ] [
67 [ +output+ wait-for-port ] [ wait-to-connect ] bi
72 : ?bind-client ( socket -- )
73 bind-local-address get [ [ fd>> ] dip make-sockaddr/size bind io-error ] [ drop ] if* ; inline
75 M: object ((client)) ( addrspec -- fd )
76 protocol-family SOCK_STREAM socket-fd
77 [ init-client-socket ] [ ?bind-client ] [ ] tri ;
79 ! Server sockets - TCP and Unix domain
80 : init-server-socket ( fd -- )
81 SOL_SOCKET SO_REUSEADDR set-socket-option ;
83 : server-socket-fd ( addrspec type -- fd )
84 [ dup protocol-family ] dip socket-fd
85 [ init-server-socket ] keep
86 [ handle-fd swap make-sockaddr/size bind io-error ] keep ;
88 M: object (server) ( addrspec -- handle )
90 SOCK_STREAM server-socket-fd
91 dup handle-fd 128 listen io-error
94 : do-accept ( server addrspec -- fd sockaddr )
95 [ handle>> handle-fd ] [ empty-sockaddr/size <int> ] bi*
96 [ accept ] 2keep drop ; inline
98 M: object (accept) ( server addrspec -- fd sockaddr )
101 { [ over 0 >= ] [ [ 2nip <fd> init-fd ] dip ] }
102 { [ errno EINTR = ] [ 2drop (accept) ] }
103 { [ errno EAGAIN = ] [
105 [ drop +input+ wait-for-port ]
112 ! Datagram sockets - UDP and Unix domain
114 [ SOCK_DGRAM server-socket-fd ] with-destructors ;
116 SYMBOL: receive-buffer
118 CONSTANT: packet-size 65536
120 [ packet-size malloc receive-buffer set-global ] "io.sockets.unix" add-init-hook
122 :: do-receive ( port -- packet sockaddr )
123 port addr>> empty-sockaddr/size :> ( sockaddr len )
124 port handle>> handle-fd ! s
125 receive-buffer get-global ! buf
131 [ receive-buffer get-global swap memory>byte-array sockaddr ]
135 M: unix (receive) ( datagram -- packet sockaddr )
136 dup do-receive dup [ [ drop ] 2dip ] [
137 2drop [ +input+ wait-for-port ] [ (receive) ] bi
140 :: do-send ( packet sockaddr len socket datagram -- )
141 socket handle-fd packet dup length 0 sockaddr len sendto
144 packet sockaddr len socket datagram do-send
147 datagram +output+ wait-for-port
148 packet sockaddr len socket datagram do-send
155 M: unix (send) ( packet addrspec datagram -- )
156 [ make-sockaddr/size ] [ [ handle>> ] keep ] bi* do-send ;
158 ! Unix domain sockets
159 M: local protocol-family drop PF_UNIX ;
161 M: local sockaddr-size drop sockaddr-un heap-size ;
163 M: local empty-sockaddr drop sockaddr-un <struct> ;
165 M: local make-sockaddr
167 dup length 1 + max-un-path > [ "Path too long" throw ] when
170 swap utf8 string>alien >>path ;
172 M: local parse-sockaddr
174 path>> utf8 alien>string <local> ;