summaryrefslogtreecommitdiff
path: root/appl/alphabet/auxi/endpoints.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/alphabet/auxi/endpoints.b')
-rw-r--r--appl/alphabet/auxi/endpoints.b105
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;
+}