ref: 47860ff9a4411442997c2f8166aa6b24fbfeac2e
dir: /libstd/dial.myr/
use "alloc.use" use "chartype.use" use "die.use" use "result.use" use "sys.use" use "sleq.use" use "option.use" use "ipparse.use" use "resolve.use" use "fmt.use" use "endian.use" use "intparse.use" use "hasprefix.use" use "utf.use" pkg std = const dial : (dialstr : 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 = {str var proto, host, port var socktype, portnum var sa : sockaddr_in /* we only support inet sockets right now.. ugh. */ var sock (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" elif port.len == 0 -> `Fail "missing port" ;; 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") socktype = Sockstream elif sleq(proto, "udp") socktype = Sockdgram ;; match parseport(port) | `Some n: portnum = n | `None: -> `Fail "bad port" ;; match getaddr(host) | `Ipv4 bits: sa.fam = Afinet sa.addr = bits sa.port = hosttonet(portnum) | `Ipv6 bits: -> `Fail "ipv6 not yet supported" ;; sock = socket(sa.fam, socktype, 0) if sock < 0 -> `Fail "failed to connect to socket" ;; var err err = connect(sock, (&sa) castto(sockaddr#), sizeof(sockaddr_in)) if err < 0 put("Errno %i\n", -err) close(sock) -> `Fail "Failed to bind socket" ;; -> `Ok sock } const parseport = {port match intparse(port) | `Some n: -> `Some n | `None: /* a small number of hardcoded ports */ if sleq(port, "http") -> `Some 80 elif sleq(port, "https") -> `Some 443 elif sleq(port, "ircd") -> `Some 6667 elif sleq(port, "dns") -> `Some 53 ;; ;; -> `None } const getaddr = {addr var ip match ipparse(addr) | `Some a: ip = a | `None: match resolve(addr) | `Ok hi: ip = hi[0].addr slfree(hi) | `Fail m: ;; ;; -> ip } const nameseg = {str var len for len = 0; len < str.len; len++ if str[len] == '!' castto(byte) -> (str[:len], str[len+1:]) ;; ;; -> (str[:], str[len:]) }