ref: 74d91a0021de012908cfdb35fb61a1473a376130
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 "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) }