ref: 3384df94db0bc2cd8cb97f5eddbdcabc9b2a2eae
parent: 6ea9b06b98aadfb089b71775deb5be03fec26e72
author: Ori Bernstein <ori@eigenstate.org>
date: Tue Jan 19 20:47:14 EST 2016
Clean up std.dial, and add support for unix socks. The code was inflexible and ugly. Let's fix that, and add support for a socket that is used frequently.
--- a/lib/std/dial+posixy.myr
+++ b/lib/std/dial+posixy.myr
@@ -11,6 +11,7 @@
use "resolve.use"
use "result.use"
use "sleq.use"
+use "slcp.use"
use "strfind.use"
use "syswrap.use"
use "utf.use"
@@ -29,33 +30,45 @@
*/
/* takes a plan 9 style dial string */
-const dial = {str
- var proto, host, port
+const dial = {ds
+ match nameseg(ds)
+ /*
+ | `Some ("net", str): -> guessdial(str)
+ */
+ | `Some ("tcp", str): -> dialsock(sys.Sockstream, str)
+ | `Some ("udp", str): -> dialsock(sys.Sockdgram, str)
+ | `Some ("unix", u): -> dialunix(u)
+ | `Some (proto, str): -> `Fail "unknown protocol"
+ | `None: -> `Fail "missing protocol"
+ ;;
+}
+
+const dialsock = {proto, str
var sa4 : sys.sockaddr_in
var sa6 : sys.sockaddr_in6
var sa : sys.sockaddr#
+ var host, portstr, port
var sock, sz
- match parsedial(str)
- | `Ok val: (proto, host, port) = val
- | `Fail m: -> `Fail m
+ match nameseg(str)
+ | `std.None: -> `Fail "required host!port for ip dial"
+ | `std.Some ("", _): -> `Fail "empty host"
+ | `std.Some (_, ""): -> `Fail "empty host"
+ | `std.Some segs: (host, portstr) = segs
;;
+ match parseport(portstr)
+ | `std.Some p: port = p
+ | `std.None: -> `Fail("invalid port")
+ ;;
+
match getaddr(host)
| `Ipv4 bits:
- sa4 = [
- .fam = sys.Afinet,
- .addr = bits,
- .port = hosttonet(port),
- ]
+ sa4=[.fam=sys.Afinet, .addr=bits, .port=hosttonet(port)]
sa = &sa4 castto(sys.sockaddr#)
sz = sizeof(sys.sockaddr_in)
| `Ipv6 bits:
- sa6 = [
- .fam = sys.Afinet6,
- .addr = bits,
- .port = hosttonet(port),
- ]
+ sa6=[.fam=sys.Afinet6, .addr=bits, .port=hosttonet(port)]
sa = &sa6 castto(sys.sockaddr#)
sz = sizeof(sys.sockaddr_in6)
;;
@@ -62,7 +75,7 @@
sock = sys.socket(sa.fam, proto, 0)
if sock < 0
- -> `Fail "failed to connect to socket"
+ -> `Fail "failed to create socket"
;;
var err
err = sys.connect(sock, sa, sz)
@@ -74,42 +87,24 @@
-> `Ok (sock castto(fd))
}
-const parsedial = {str
- var proto, host, port
- var socktype, portnum
-
- (proto, str) = nameseg(str)
- (host, str) = nameseg(str)
- (port, str) = nameseg(str)
-
- if proto.len == 0
- -> `Fail "missing proto"
- elif host.len == 0
- -> `Fail "missing host"
+const dialunix = {path
+ var sa : sys.sockaddr_un
+ var sock
+
+ sa = [.fam = sys.Afunix]
+ if path.len >= sa.path.len
+ -> `Fail "path too long"
;;
- if sleq(proto, "net")
- -> `Fail "net wildcard proto not yet supported\n"
- elif sleq(proto, "unix")
- -> `Fail "net unix proto not yet supported\n"
- elif sleq(proto, "tcp")
- if port.len == 0
- -> `Fail "missing port"
- ;;
- socktype = sys.Sockstream
- elif sleq(proto, "udp")
- if port.len == 0
- -> `Fail "missing port"
- ;;
- socktype = sys.Sockdgram
+ sock = sys.socket(sys.Afunix, sys.Sockstream, 0)
+ if sock < 0
+ -> `Fail "failed to create socket"
;;
-
- match parseport(port)
- | `Some n: portnum = n
- | `None: -> `Fail "bad port"
+ std.slcp(sa.path[:path.len], path)
+ if sys.bind(sock, &sa castto(sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
+ -> `Fail "failed to bind address"
;;
-
- -> `Ok (socktype, host, portnum)
+ -> `std.Ok (sock castto(fd))
}
const parseport = {port
@@ -150,9 +145,9 @@
const nameseg = {str
match strfind(str, "!")
| `Some idx:
- -> (str[:idx], str[idx+1:])
+ -> `Some (str[:idx], str[idx+1:])
| `None:
- -> (str, "")
+ -> `None
;;
}
--- a/lib/sys/sys+freebsd-x64.myr
+++ b/lib/sys/sys+freebsd-x64.myr
@@ -118,6 +118,12 @@
scope : uint32
;;
+ type sockaddr_un = struct
+ len : byte
+ fam : sockfam
+ path : byte[104]
+ ;;
+
type sockaddr_storage = struct
len : byte
fam : sockfam