diff options
Diffstat (limited to 'appl/alphabet/auxi/endpoints.b')
| -rw-r--r-- | appl/alphabet/auxi/endpoints.b | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/appl/alphabet/auxi/endpoints.b b/appl/alphabet/auxi/endpoints.b new file mode 100644 index 00000000..5544da8b --- /dev/null +++ b/appl/alphabet/auxi/endpoints.b @@ -0,0 +1,105 @@ +implement Endpoints; +include "sys.m"; + sys: Sys; +include "draw.m"; +include "string.m"; + str: String; +include "sh.m"; + sh: Sh; +include "alphabet/endpoints.m"; + +init() +{ + sys = load Sys Sys->PATH; + sh = load Sh Sh->PATH; + sh->initialise(); + str = load String String->PATH; +} + +DIR: con "/n/endpoint"; + +new(nil, addr: string, force: int): string # XXX don't ignore net directory +{ + if(!force && sys->stat(DIR+"/"+addr+"/clone").t0 != -1) + return nil; + if((e := sh->run(nil, "mount"::"{mntgen}"::DIR::nil)) != nil) + return "mount mntgen failed: "+e; + if((e = sh->run(nil, "endpointsrv"::addr::DIR+"/"+addr::nil)) != nil) + return "endpoint failed: "+e; + if((e = sh->run(nil, "listen"::addr::"export"::DIR+"/"+addr::nil)) != nil){ + sys->unmount(nil, DIR+"/"+addr); + return "listen failed: "+e; + } + return nil; +} + +err(e: string): Endpoint +{ + return (nil, nil, e); +} + +create(addr: string): (ref Sys->FD, Endpoint) +{ + d := DIR+"/"+addr; + fd := sys->open(d+"/clone", Sys->OREAD); + if(fd == nil) + return (nil, err(sys->sprint("cannot open %s/clone: %r", d))); + + buf := array[1024] of byte; + n := sys->read(fd, buf, len buf); + if(n <= 0) + return (nil, err("read id failed")); + s := string buf[0:n]; + (nt, toks) := sys->tokenize(s, " "); + if(nt != 2) + return (nil, err(sys->sprint("invalid id read %q", s))); + id: string; + (addr, id) = (hd toks, hd tl toks); + fd = sys->open(d+"/"+id+".in", Sys->OWRITE); + if(fd == nil) + return (nil, err(sys->sprint("cannot write to %s/%s: %r", d, id))); + return (fd, Endpoint(addr, id, nil)); +} + +open(net: string, ep: Endpoint): (ref Sys->FD, string) +{ + if(hasslash(ep.addr)) + return (nil, "bad address"); + if(hasslash(ep.id)) + return (nil, "bad id"); + d := DIR+"/"+ep.addr; + fd := sys->open(d+"/"+ep.id, Sys->OREAD); + if(fd != nil) + return (fd, nil); + e := sys->sprint("%r"); + if(sys->stat(d+"/clone").t0 != -1) + return (nil, sys->sprint("endpoint does not exist: %s", e)); + if((e = sh->run(nil, "mount"::"-A"::net+ep.addr::d::nil)) != nil) + return (nil, e); + fd = sys->open(d+"/"+ep.id, Sys->OREAD); + if(fd == nil) + return (nil, sys->sprint("endpoint does not exist: %r")); + return (fd, nil); +} + +Endpoint.text(ep: self Endpoint): string +{ + return sys->sprint("%q %q %q", ep.addr, ep.id, ep.about); +} + +Endpoint.mk(s: string): Endpoint +{ + t := str->unquoted(s); + if(len t != 3) + return err("invalid endpoint string"); + # XXX could do more validation than this. + return (hd t, hd tl t, hd tl tl t); +} + +hasslash(s: string): int +{ + for(i := 0; i < len s; i++) + if(s[i] == '/') + return 1; + return 0; +} |
