diff options
-rw-r--r-- | socket.c | 1 | ||||
-rw-r--r-- | stdlib/doc-syms.tl | 1 | ||||
-rw-r--r-- | stdlib/socket.tl | 9 | ||||
-rw-r--r-- | tests/014/sockaddr-str.tl | 49 | ||||
-rw-r--r-- | txr.1 | 86 |
5 files changed, 146 insertions, 0 deletions
@@ -1253,6 +1253,7 @@ static val sock_set_entries(val fun) lit("sock-accept"), lit("sock-shutdown"), lit("open-socket"), lit("open-socket-pair"), lit("sock-send-timeout"), lit("sock-recv-timeout"), lit("sock-opt"), lit("sock-set-opt"), + lit("sockaddr-str"), nil }; val name_noload[] = { diff --git a/stdlib/doc-syms.tl b/stdlib/doc-syms.tl index e9685e70..7d8c30b9 100644 --- a/stdlib/doc-syms.tl +++ b/stdlib/doc-syms.tl @@ -1829,6 +1829,7 @@ ("sockaddr" "N-02C48759") ("sockaddr-in" "N-01DD05D9") ("sockaddr-in6" "N-013DD169") + ("sockaddr-str" "N-0370C05F") ("sockaddr-un" "N-01DD05D2") ("socklen-t" "N-01153D9E") ("sol-socket" "N-031C01CB") diff --git a/stdlib/socket.tl b/stdlib/socket.tl index 80a60ec5..af4aca4e 100644 --- a/stdlib/socket.tl +++ b/stdlib/socket.tl @@ -279,3 +279,12 @@ (,setter (val) ^(sock-set-opt ,',sock ,',level ,',option ,val ,',type))) ,body))) + +(defun sockaddr-str (str) + (cond + ((starts-with "[" str) (in6addr-str str)) + ((starts-with "/" str) (new sockaddr-un path str)) + ((contains "::" str) (in6addr-str str)) + ((contains "." str) (inaddr-str str)) + (t (or (ignerr (in6addr-str str)) + (inaddr-str str))))) diff --git a/tests/014/sockaddr-str.tl b/tests/014/sockaddr-str.tl new file mode 100644 index 00000000..183c1a02 --- /dev/null +++ b/tests/014/sockaddr-str.tl @@ -0,0 +1,49 @@ +(load "../common.tl") + +(mtest + (sockaddr-str "") :error + (sockaddr-str "1") :error + (sockaddr-str "x") :error + (sockaddr-str "1:2") :error + (sockaddr-str "[]:") :error) + +(mtest + (sockaddr-str "[::1]:-1") :error + (sockaddr-str "[::1]:65536") :error + (sockaddr-str "1.2.3.4:-1") :error + (sockaddr-str "1.2.3.4:65536") :error + (sockaddr-str "1:2/8") :error) + +(mtest + (sockaddr-str "/") #S(sockaddr-un canonname nil path "/") + (sockaddr-str "/abc") #S(sockaddr-un canonname nil path "/abc")) + +(mtest + (sockaddr-str "[::1]:2") #S(sockaddr-in6 addr 1 port 2) + (sockaddr-str "[::1/1]:2") #S(sockaddr-in6 addr 0 port 2 prefix 1)) + +(mtest + (sockaddr-str "::1") #S(sockaddr-in6 addr 1) + (sockaddr-str "::1/1") #S(sockaddr-in6 addr 0 prefix 1)) + +(mtest + (sockaddr-str "::ffff:1.2.3.4") #S(sockaddr-in6 addr 281470698652420) + (sockaddr-str "::ffff:1.2.3.4/96") #S(sockaddr-in6 addr 281470681743360 prefix 96)) + +(mtest + (sockaddr-str "1.2.3.4") #S(sockaddr-in addr 16909060) + (sockaddr-str "1.2.3.4/8") #S(sockaddr-in addr 16777216 prefix 8) + (sockaddr-str "1.2.3.4:16") #S(sockaddr-in addr 16909060 port 16) + (sockaddr-str "1.2.3.4/8:16") #S(sockaddr-in addr 16777216 prefix 8 port 16)) + +(mtest + (sockaddr-str "1/8") #S(sockaddr-in addr 16777216 prefix 8) + (sockaddr-str "1.2/8") #S(sockaddr-in addr 16777216 prefix 8) + (sockaddr-str "1/8:5") #S(sockaddr-in addr 16777216 prefix 8 port 5) + (sockaddr-str "1.2/8:5") #S(sockaddr-in addr 16777216 prefix 8 port 5)) + +(mtest + (sockaddr-str "1:2:3:4:5:6:7:8/127") + #S(sockaddr-in6 addr 5192455318486707404433266433261576 prefix 127) + (sockaddr-str "[1:2:3:4:5:6:7:8/127]:5") + #S(sockaddr-in6 addr 5192455318486707404433266433261576 prefix 127 port 5)) @@ -75409,6 +75409,92 @@ brackets. The closing square bracket must be followed by a colon and one or more digits denoting a decimal number in the range 0 to 65535. For instance .strn "[1:2:3::4/64]:1234". +.coNP Function @ sockaddr-str +.synb +.mets (sockaddr-str << string ) +.syne +.desc +The function +.code sockaddr-str +analyzes the +.meta string +argument to determine whether it represents a valid IPv4, IPv6 or Unix domain +address. If so, it constructs an object, representing that address, of type +.codn sockaddr-in , +.code sockaddr-in +or +.codn sockaddr-un . + +The slash prefix notation, and port numbers are handled, and represented +in the returned structures accordingly. + +The +.code sockaddr-str +function works by applying simple tests to the input, and then invoking +the functions +.code inaddr-str +or +.codn in6addr-str , +or constructing a +.code sockaddr-un +structure whose +.code path +slot is +.metn string . + +The precise procedure followed is: +.RS +.IP 1. +If +.meta string +starts with +.str [ +then it is handled via +.codn in6addr-str . +.IP 2. +If +.meta string +starts with +.str / +then it is assumed to be the path of a Unix socket. +A +.code sockaddr-un +structure is constructed whose +.code path +slot is +.metn string . +This is the only case in which a structure of type +.code sockaddr-un +is returned. +.IP 3. +If +.meta string +contains +.str "::" +as a substring, it is handled via +.codn in6addr-str . +.IP 4. +If +.meta string +contains +.str . +then it is handled via +.codn inaddr-str . +.IP 5. +If the above tests fail, +.meta string +is passed to +.codn in6addr-str , +and if that call returns normally, +.code sockaddr-str +returns that value. +.IP 6. +Otherwise, +.code string +is passed to +.codn inaddr-str . +.RE + .SS* Unix Terminal Control \*(TX provides access to the terminal control "termios" interfaces defined by |