| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2008-12-14 21:03:00 -05:00
										 |  |  | io.binary io.backend.unix io.streams.duplex | 
					
						
							| 
									
										
										
										
											2008-12-14 22:21:44 -05:00
										 |  |  | io.backend io.ports io.pathnames io.files.private | 
					
						
							| 
									
										
										
										
											2008-05-12 23:30:18 -04:00
										 |  |  | io.encodings.utf8 math.parser continuations libc combinators | 
					
						
							| 
									
										
										
										
											2008-12-17 19:10:01 -05:00
										 |  |  | system accessors destructors unix locals init ;
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-14 21:03:00 -05: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 -- )
 | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |     [ 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 -- )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     dup zero? [ drop ] [ gai_strerror throw ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! Client sockets - TCP and Unix domain | 
					
						
							| 
									
										
										
										
											2008-05-14 20:41:39 -04:00
										 |  |  | M: object (get-local-address) ( handle remote -- sockaddr )
 | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |     [ handle-fd ] dip empty-sockaddr/size <int> | 
					
						
							| 
									
										
										
										
											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 )
 | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |     [ 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 ] } | 
					
						
							| 
									
										
										
										
											2008-05-14 20:03:07 -04:00
										 |  |  |         { [ err_no EAGAIN = ] [ dup +output+ wait-for-port wait-to-connect ] } | 
					
						
							|  |  |  |         { [ err_no EINTR = ] [ wait-to-connect ] } | 
					
						
							|  |  |  |         [ (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 ] } | 
					
						
							| 
									
										
										
										
											2008-05-14 20:03:07 -04:00
										 |  |  |         { [ err_no 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
										 |  |  | 
 | 
					
						
							|  |  |  | M: object ((client)) ( addrspec -- fd )
 | 
					
						
							| 
									
										
										
										
											2008-05-14 20:03:07 -04:00
										 |  |  |     protocol-family SOCK_STREAM socket-fd dup init-client-socket ;
 | 
					
						
							| 
									
										
										
										
											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 )
 | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |     [ dup protocol-family ] dip socket-fd | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     dup init-server-socket | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  |     dup handle-fd rot make-sockaddr/size bind io-error ;
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							| 
									
										
										
										
											2008-09-07 05:14:47 -04:00
										 |  |  |         dup handle-fd 128 listen io-error | 
					
						
							| 
									
										
										
										
											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 )
 | 
					
						
							|  |  |  |     [ 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
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2008-12-02 04:10:13 -05:00
										 |  |  |         { [ over 0 >= ] [ [ 2nip <fd> init-fd ] dip ] } | 
					
						
							| 
									
										
										
										
											2008-05-16 01:57:52 -04:00
										 |  |  |         { [ err_no EINTR = ] [ 2drop (accept) ] } | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         { [ err_no 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 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : packet-size 65536 ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-14 21:03:00 -05: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 [| sockaddr len | | 
					
						
							| 
									
										
										
										
											2008-05-14 04:55:33 -04:00
										 |  |  |         port handle>> handle-fd ! s | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         receive-buffer get-global ! buf | 
					
						
							|  |  |  |         packet-size ! nbytes | 
					
						
							|  |  |  |         0 ! flags | 
					
						
							|  |  |  |         sockaddr ! from | 
					
						
							| 
									
										
										
										
											2008-05-15 06:20:42 -04:00
										 |  |  |         len <int> ! fromlen | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         recvfrom dup 0 >= [ | 
					
						
							| 
									
										
										
										
											2008-07-03 21:50:01 -04:00
										 |  |  |             receive-buffer get-global swap memory>byte-array sockaddr | 
					
						
							| 
									
										
										
										
											2008-05-13 19:24:46 -04:00
										 |  |  |         ] [ | 
					
						
							|  |  |  |             drop f f
 | 
					
						
							|  |  |  |         ] if
 | 
					
						
							|  |  |  |     ] call ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: unix (receive) ( datagram -- packet sockaddr )
 | 
					
						
							| 
									
										
										
										
											2008-11-30 23:21:37 -05:00
										 |  |  |     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 < [ | 
					
						
							|  |  |  |         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 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-10-02 04:38:36 -04:00
										 |  |  | M: local sockaddr-size drop "sockaddr-un" heap-size ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: local empty-sockaddr drop "sockaddr-un" <c-object> ;
 | 
					
						
							| 
									
										
										
										
											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> ;
 |