summaryrefslogtreecommitdiff
path: root/appl/collab/proxy.b
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 17:07:39 +0000
commit37da2899f40661e3e9631e497da8dc59b971cbd0 (patch)
treecbc6d4680e347d906f5fa7fca73214418741df72 /appl/collab/proxy.b
parent54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff)
20060303a
Diffstat (limited to 'appl/collab/proxy.b')
-rw-r--r--appl/collab/proxy.b177
1 files changed, 177 insertions, 0 deletions
diff --git a/appl/collab/proxy.b b/appl/collab/proxy.b
new file mode 100644
index 00000000..83999495
--- /dev/null
+++ b/appl/collab/proxy.b
@@ -0,0 +1,177 @@
+implement Proxy;
+
+include "sys.m";
+ sys: Sys;
+
+include "srvmgr.m";
+include "proxy.m";
+
+Srvreq, Srvreply: import Srvmgr;
+
+init(root: string, fd: ref Sys->FD, rc: chan of ref Srvreq, user: string)
+{
+ sys = load Sys Sys->PATH;
+
+ sys->chdir(root);
+ sys->bind("export/services", "export/services", Sys->MCREATE);
+ sys->bind("#s", "export/services", Sys->MBEFORE);
+
+ ctlio := sys->file2chan("export/services", "ctl");
+
+ hangup := chan of int;
+ spawn export(fd, "export", hangup);
+ fd = nil;
+
+ for (;;) alt {
+ <- hangup =>
+ # closedown all clients
+ sys->print("client exit [%s]\n", user);
+ rmclients(rc);
+ return;
+ (offset, count, fid, r) := <- ctlio.read =>
+ client := fid2client(fid);
+ if (r == nil) {
+ if (client != nil)
+ rmclient(rc, client);
+ continue;
+ }
+ if (client == nil) {
+ rreply(r, (nil, "service not set"));
+ continue;
+ }
+ rreply(r, reads(client.path, offset, count));
+
+ (offset, data, fid, w) := <- ctlio.write =>
+ client := fid2client(fid);
+ if (w == nil) {
+ if (client != nil)
+ rmclient(rc, client);
+ continue;
+ }
+ if (client != nil) {
+ wreply(w, (0, "service set"));
+ continue;
+ }
+ err := newclient(rc, user, fid, string data);
+ if (err != nil)
+ wreply(w, (0, err));
+ else
+ wreply(w, (len data, nil));
+ }
+
+}
+
+rreply(rc: chan of (array of byte, string), reply: (array of byte, string))
+{
+ alt {
+ rc <-= reply =>;
+ * =>;
+ }
+}
+
+wreply(wc: chan of (int, string), reply: (int, string))
+{
+ alt {
+ wc <-= reply=>;
+ * =>;
+ }
+}
+
+reads(str: string, off, nbytes: int): (array of byte, string)
+{
+ bstr := array of byte str;
+ slen := len bstr;
+ if(off < 0 || off >= slen)
+ return (nil, nil);
+ if(off + nbytes > slen)
+ nbytes = slen - off;
+ if(nbytes <= 0)
+ return (nil, nil);
+ return (bstr[off:off+nbytes], nil);
+}
+
+export(exportfd: ref Sys->FD, dir: string, done: chan of int)
+{
+ sys->export(exportfd, dir, Sys->EXPWAIT);
+ done <-= 1;
+}
+
+Client: adt {
+ fid: int;
+ path: string;
+ sname: string;
+ id: string;
+};
+
+clients: list of ref Client;
+freepaths: list of string;
+nextpath := 0;
+
+fid2client(fid: int): ref Client
+{
+ for(cl := clients; cl != nil; cl = tl cl)
+ if ((c := hd cl).fid == fid)
+ return c;
+ return nil;
+}
+
+newclient(rc: chan of ref Srvreq, user: string, fid: int, cmd: string): string
+{
+sys->print("new Client %s [%s]\n", user, cmd);
+ for (i := 0; i < len cmd; i++)
+ if (cmd[i] == ' ')
+ break;
+ if (i == 0 || i == len cmd)
+ return "bad command";
+
+ sname := cmd[:i];
+ id := cmd[i:];
+ reply := chan of Srvreply;
+ rc <-= ref Srvreq.Acquire(sname, id, user, reply);
+ (err, root, fd) := <- reply;
+ if (err != nil)
+ return err;
+
+ path := "";
+ if (freepaths != nil)
+ (path, freepaths) = (hd freepaths, tl freepaths);
+ else
+ path = string nextpath++;
+
+ sys->mount(fd, nil, "mnt", Sys->MREPL, nil); # connection to the active service fs
+ mkdir("export/services/"+path);
+ sys->bind("mnt/"+root, "export/services/"+path, Sys->MREPL|Sys->MCREATE);
+ sys->unmount("mnt", nil);
+ clients = ref Client(fid, path, sname, id) :: clients;
+ return nil;
+}
+
+rmclient(rc: chan of ref Srvreq, client: ref Client)
+{
+sys->print("rmclient [%s %s]\n", client.sname, client.id);
+ nl: list of ref Client;
+ for(cl := clients; cl != nil; cl = tl cl)
+ if((c := hd cl) == client){
+ sys->unmount("export/services/" + client.path, nil);
+ freepaths = client.path :: freepaths;
+ rc <-= ref Srvreq.Release(client.sname, client.id);
+ } else
+ nl = c :: nl;
+ clients = nl;
+}
+
+rmclients(rc: chan of ref Srvreq)
+{
+ for(cl := clients; cl != nil; cl = tl cl){
+ c := hd cl;
+sys->print("rmclients [%s %s]\n", c.sname, c.id);
+ rc <-= ref Srvreq.Release(c.sname, c.id);
+ }
+ clients = nil;
+}
+
+mkdir(path: string)
+{
+ sys->print("mkdir [%s]\n", path);
+ sys->create(path, Sys->OREAD, 8r777 | Sys->DMDIR);
+}