ref: f8e8b084dad7b4b7ea813bc4b612f64a07f27cd7
dir: /lib/std/dial+posixy.myr/
use sys
use "alloc"
use "chartype"
use "dialparse"
use "die"
use "endian"
use "option"
use "result"
use "slcp"
use "sleq"
use "strfind"
use "striter"
use "syswrap"
use "utf"
pkg std =
const dial : (ds : byte[:] -> result(fd, byte[:]))
;;
/*
a map from service name to a list of (port,proto)
pairs in order of preference
*/
/* FIXME: implement
var services : htab(byte[:], [int, byte[:]][:])#
var inited = false
*/
/* takes a plan 9 style dial string */
const dial = {ds
match nameseg(ds)
| `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 hoststr, portstr, port
var sock, sz
var err
match nameseg(str)
| `None: -> `Fail "required host!port for ip dial"
| `Some ("", _): -> `Fail "empty host"
| `Some (_, ""): -> `Fail "empty port"
| `Some segs: (hoststr, portstr) = segs
;;
match parseport(portstr)
| `Some p: port = p
| `None: -> `Fail("invalid port")
;;
match getaddr(hoststr)
| `Ok `Ipv4 bits:
sa4=[.fam=sys.Afinet, .addr=bits, .port=hosttonet(port)]
sa = (&sa4 : sys.sockaddr#)
sz = sizeof(sys.sockaddr_in)
| `Ok `Ipv6 bits:
sa6=[.fam=sys.Afinet6, .addr=bits, .port=hosttonet(port)]
sa = (&sa6 : sys.sockaddr#)
sz = sizeof(sys.sockaddr_in6)
| `Fail m:
-> `Fail m
;;
sock = sys.socket(sa.fam, proto, 0)
if sock < 0
-> `Fail "failed to create socket"
;;
err = sys.connect(sock, sa, sz)
if err < 0
sys.close(sock)
-> `Fail "Failed to bind socket"
;;
-> `Ok (sock : fd)
}
const dialunix = {path
var sa : sys.sockaddr_un
var sock
sa = [.fam = sys.Afunix]
if path.len >= sa.path.len
-> `Fail "path too long"
;;
sock = sys.socket(sys.Afunix, sys.Sockstream, 0)
if sock < 0
-> `Fail "failed to create socket"
;;
slcp(sa.path[:path.len], path)
if sys.connect(sock, (&sa : sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
-> `Fail "failed to bind address"
;;
-> `Ok (sock : fd)
}