ref: bd25454011010946b91c21e8af737d86505c4041
dir: /lib/std/listen+plan9.myr/
use sys use "alloc" use "die" use "dirname" use "fmt" use "option" use "result" use "strfind" use "syswrap" use "cstrconv" use "utf" pkg std = const announce : (ds : byte[:] -> result(fd, byte[:])) const accept : (lfd : fd -> result(fd, byte[:])) ;; const Maxpath = 256 const announce = {ds var a, abuf : byte[Maxpath] var f, fbuf : byte[Maxpath] var l, lbuf : byte[Maxpath] var nbuf : byte[32] var dir, ctl, lfd, n /* announce */ match translate(ds, abuf[:], fbuf[:]) | `Err _: -> `Err "invalid dial string" | `Ok (addr, file): put("addr: {}, file: {}\n", addr, file) a = addr f = file match strrfind(f, "/") | `Some i: dir = i | `None: -> `Err "invalid net dir" ;; ;; match open(f, Ordwr) | `Ok fd: ctl = fd | `Err e: -> `Err "could not open ctl fd" ;; match read(ctl, nbuf[:]) | `Err e: ->`Err "unable to read ctl fd" | `Ok nn: l = bfmt(lbuf[:], "{}/{}/listen", f[:dir], nbuf[:nn]) ;; put("announce {}\n", a) n = fput(ctl, "announce {}", a) if n <= 0 close(ctl) -> `Err "writing announce" ;; /* listen */ match open(l, Ordwr) | `Err e: close(ctl) -> `Err "could not open ctl" | `Ok fd: lfd = fd ;; close(ctl) -> `Ok lfd } const accept = {lfd -> result(fd, byte[:]) var dir, dirbuf : byte[40] var num, numbuf : byte[40] var dat, datbuf : byte[Maxpath] match read(lfd, numbuf[:]) | `Ok n: num = numbuf[:n] | `Err e: -> `Err "could not accept" ;; fput(lfd, "accept {}", num) sys.fd2path((lfd : sys.fd), dirbuf[:]) dir = dirname(cstrconv(dirbuf[:])) match strrfind(dir, "/") | `None: dat = bfmt(datbuf[:], "{}/{}/data", dir, num) | `Some i: dat = bfmt(datbuf[:], "{}/{}/data", dir[:i], num) ;; put("data fd: {}\n", dat) match open(dat, Ordwr) | `Ok fd: -> `Ok fd | `Err e: -> `Err "could not open data fd" ;; } const translate = {ds, addrbuf, filebuf var cs, csbuf : byte[Maxpath] var r, rbuf : byte[Maxpath] var netdir, rest var addr, file match strfind(ds, "!") | `None: -> `Err void | `Some sep: if decode(ds[:sep]) == '#' || decode(ds[:sep]) == '/' match strrfind(ds[:sep], "/") | `None: -> `Err void | `Some idx: netdir = ds[:idx] rest = ds[idx+1:] ;; else netdir = "/net" addr = ds ;; ;; cs = bfmt(csbuf[:], "{}/cs", netdir) match open(cs, Ordwr) | `Err e: -> identtrans(rest, netdir, addrbuf, filebuf) | `Ok fd: match write(fd, addr) | `Err e: close(fd) -> `Err void | `Ok _: ;; seek(fd, 0, Seekset) match read(fd, rbuf[:]) | `Err e: close(fd) -> `Err void | `Ok n: r = rbuf[:n] ;; close(fd) ;; put("cs returned: {}\n", r) match strfind(r, " ") | `None: -> `Err void | `Some i: addr = bfmt(addrbuf, "{}", r[i+1:]) if decode(r) == '/' match strfind(r[:i], "/") | `None: -> `Err void | `Some 0: file = bfmt(filebuf, "{}{}", netdir, r[:i]) | `Some n: file = bfmt(filebuf, "{}{}", netdir, r[n+1:]) ;; else file = bfmt(filebuf, "{}/{}", netdir, r[:i]) ;; ;; -> `Ok (addr, file) } const identtrans = {ds, netdir, addrbuf, filebuf var a, f match strfind(ds, "!") | `None: -> `Err void | `Some sep: a = bfmt(addrbuf, "{}", ds[sep + 1:]) f = bfmt(filebuf, "{}/{}/clone", netdir, ds[:sep]) -> `Ok (a, f) ;; }