| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | ! Copyright (C) 2007 Doug Coleman, Slava Pestov | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: arrays byte-arrays io.backend io.binary io.sockets | 
					
						
							|  |  |  | kernel math math.parser sequences splitting system | 
					
						
							| 
									
										
										
										
											2007-12-28 21:46:06 -05:00
										 |  |  | alien.c-types combinators namespaces alien parser ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | IN: io.sockets.impl | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-12-28 21:46:06 -05:00
										 |  |  | << { | 
					
						
							|  |  |  |     { [ windows? ] [ "windows.winsock" ] } | 
					
						
							|  |  |  |     { [ unix? ] [ "unix" ] } | 
					
						
							|  |  |  | } cond use+ >> | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | GENERIC: protocol-family ( addrspec -- af )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: sockaddr-type ( addrspec -- type )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  | GENERIC: make-sockaddr ( addrspec -- sockaddr )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : make-sockaddr/size ( addrspec -- sockaddr size )
 | 
					
						
							|  |  |  |     dup make-sockaddr swap sockaddr-type heap-size ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | GENERIC: parse-sockaddr ( sockaddr addrspec -- newaddrspec )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | HOOK: addrinfo-error io-backend ( n -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ! IPV4 and IPV6 | 
					
						
							|  |  |  | GENERIC: address-size ( addrspec -- n )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: inet-ntop ( data addrspec -- str )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | GENERIC: inet-pton ( str addrspec -- data )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: inet4 inet-ntop ( data addrspec -- str )
 | 
					
						
							| 
									
										
										
										
											2008-01-26 22:38:30 -05:00
										 |  |  |     drop 4 memory>byte-array [ number>string ] { } map-as "." join ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: inet4 inet-pton ( str addrspec -- data )
 | 
					
						
							|  |  |  |     drop "." split [ string>number ] B{ } map-as ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: inet4 address-size drop 4 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: inet4 protocol-family drop PF_INET ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  | M: inet4 sockaddr-type drop "sockaddr-in" c-type ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  | M: inet4 make-sockaddr ( inet -- sockaddr )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     "sockaddr-in" <c-object> | 
					
						
							|  |  |  |     AF_INET over set-sockaddr-in-family | 
					
						
							|  |  |  |     over inet4-port htons over set-sockaddr-in-port | 
					
						
							|  |  |  |     over inet4-host | 
					
						
							|  |  |  |     "0.0.0.0" or
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  |     rot inet-pton *uint over set-sockaddr-in-addr ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  | SYMBOL: port-override | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-02-25 21:09:44 -05:00
										 |  |  | : (port) port-override get swap or ;
 | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: inet4 parse-sockaddr | 
					
						
							|  |  |  |     >r dup sockaddr-in-addr <uint> r> inet-ntop | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  |     swap sockaddr-in-port ntohs (port) <inet4> ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: inet6 inet-ntop ( data addrspec -- str )
 | 
					
						
							| 
									
										
										
										
											2008-01-26 22:38:30 -05:00
										 |  |  |     drop 16 memory>byte-array 2 <groups> [ be> >hex ] map ":" join ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: inet6 inet-pton ( str addrspec -- data )
 | 
					
						
							|  |  |  |     drop "::" split1 | 
					
						
							|  |  |  |     [ [ ":" split [ hex> dup 0 ? ] map ] [ f ] if* ] 2apply | 
					
						
							|  |  |  |     2dup [ length ] 2apply + 8 swap - 0 <array> swap 3append
 | 
					
						
							|  |  |  |     [ 2 >be ] map concat >byte-array ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: inet6 address-size drop 16 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: inet6 protocol-family drop PF_INET6 ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  | M: inet6 sockaddr-type drop "sockaddr-in6" c-type ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  | M: inet6 make-sockaddr ( inet -- sockaddr )
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  |     "sockaddr-in6" <c-object> | 
					
						
							|  |  |  |     AF_INET6 over set-sockaddr-in6-family | 
					
						
							|  |  |  |     over inet6-port htons over set-sockaddr-in6-port | 
					
						
							|  |  |  |     over inet6-host "::" or
 | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  |     rot inet-pton over set-sockaddr-in6-addr ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: inet6 parse-sockaddr | 
					
						
							|  |  |  |     >r dup sockaddr-in6-addr r> inet-ntop | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  |     swap sockaddr-in6-port ntohs (port) <inet6> ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : addrspec-of-family ( af -- addrspec )
 | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         { [ dup AF_INET = ] [ T{ inet4 } ] } | 
					
						
							|  |  |  |         { [ dup AF_INET6 = ] [ T{ inet6 } ] } | 
					
						
							|  |  |  |         { [ dup AF_UNIX = ] [ T{ local } ] } | 
					
						
							|  |  |  |         { [ t ] [ f ] } | 
					
						
							|  |  |  |     } cond nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: f parse-sockaddr nip ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : addrinfo>addrspec ( addrinfo -- addrspec )
 | 
					
						
							|  |  |  |     dup addrinfo-addr | 
					
						
							|  |  |  |     swap addrinfo-family addrspec-of-family | 
					
						
							|  |  |  |     parse-sockaddr ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : parse-addrinfo-list ( addrinfo -- seq )
 | 
					
						
							| 
									
										
										
										
											2007-10-16 04:15:16 -04:00
										 |  |  |     [ dup ] | 
					
						
							|  |  |  |     [ dup addrinfo-next swap addrinfo>addrspec ] | 
					
						
							| 
									
										
										
										
											2007-11-04 17:32:01 -05:00
										 |  |  |     [ ] unfold nip [ ] subset ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  | : prepare-resolve-host ( host serv passive? -- host' serv' flags )
 | 
					
						
							| 
									
										
										
										
											2008-01-24 18:21:10 -05:00
										 |  |  |     #! If the port is a number, we resolve for 'http' then | 
					
						
							|  |  |  |     #! change it later. This is a workaround for a FreeBSD | 
					
						
							|  |  |  |     #! getaddrinfo() limitation -- on Windows, Linux and Mac, | 
					
						
							|  |  |  |     #! we can convert a number to a string and pass that as the | 
					
						
							|  |  |  |     #! service name, but on FreeBSD this gives us an unknown | 
					
						
							|  |  |  |     #! service error. | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  |     >r | 
					
						
							| 
									
										
										
										
											2008-01-24 18:21:10 -05:00
										 |  |  |     dup integer? [ port-override set "http" ] when
 | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  |     r> AI_PASSIVE 0 ? ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | M: object resolve-host ( host serv passive? -- seq )
 | 
					
						
							| 
									
										
										
										
											2008-01-23 05:32:51 -05:00
										 |  |  |     [ | 
					
						
							|  |  |  |         prepare-resolve-host | 
					
						
							|  |  |  |         "addrinfo" <c-object> | 
					
						
							|  |  |  |         [ set-addrinfo-flags ] keep
 | 
					
						
							|  |  |  |         PF_UNSPEC over set-addrinfo-family | 
					
						
							|  |  |  |         IPPROTO_TCP over set-addrinfo-protocol | 
					
						
							|  |  |  |         f <void*> [ getaddrinfo addrinfo-error ] keep *void* | 
					
						
							|  |  |  |         [ parse-addrinfo-list ] keep
 | 
					
						
							|  |  |  |         freeaddrinfo | 
					
						
							|  |  |  |     ] with-scope ;
 | 
					
						
							| 
									
										
										
										
											2007-09-20 18:09:08 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | M: object host-name ( -- name )
 | 
					
						
							|  |  |  |     256 <byte-array> dup dup length gethostname | 
					
						
							|  |  |  |     zero? [ "gethostname failed" throw ] unless
 | 
					
						
							|  |  |  |     alien>char-string ;
 |