ref: d4fac4da419b09f014c27b0f4334f1c8f4314faf
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 ("net", str): -> dialsock(sys.Sockstream, str)
| `Some ("tcp", str): -> dialsock(sys.Sockstream, str)
| `Some ("udp", str): -> dialsock(sys.Sockdgram, str)
| `Some ("unix", u): -> dialunix(u)
| `Some (proto, str): -> `Err "unknown protocol"
| `None: -> `Err "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: -> `Err "required host!port for ip dial"
| `Some ("", _): -> `Err "empty host"
| `Some (_, ""): -> `Err "empty port"
| `Some segs: (hoststr, portstr) = segs
;;
match parseport(portstr)
| `Some p: port = p
| `None: -> `Err("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)
| `Err m:
-> `Err m
;;
sock = sys.socket(sa.fam, proto, 0)
if sock < 0
-> `Err "failed to create socket"
;;
err = sys.connect(sock, sa, sz)
if err < 0
sys.close(sock)
-> `Err "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
-> `Err "path too long"
;;
sock = sys.socket(sys.Afunix, sys.Sockstream, 0)
if sock < 0
-> `Err "failed to create socket"
;;
slcp(sa.path[:path.len], path)
if sys.connect(sock, (&sa : sys.sockaddr#), sizeof(sys.sockaddr_un)) < 0
-> `Err "failed to bind address"
;;
-> `Ok (sock : fd)
}