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)
;;
}