summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--socket.c1
-rw-r--r--stdlib/doc-syms.tl1
-rw-r--r--stdlib/socket.tl9
-rw-r--r--tests/014/sockaddr-str.tl49
-rw-r--r--txr.186
5 files changed, 146 insertions, 0 deletions
diff --git a/socket.c b/socket.c
index e7695c1e..f49c4005 100644
--- a/socket.c
+++ b/socket.c
@@ -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))
diff --git a/txr.1 b/txr.1
index 95c71ac9..11ffebd6 100644
--- a/txr.1
+++ b/txr.1
@@ -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