diff options
| author | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
|---|---|---|
| committer | Charles.Forsyth <devnull@localhost> | 2006-12-22 17:07:39 +0000 |
| commit | 37da2899f40661e3e9631e497da8dc59b971cbd0 (patch) | |
| tree | cbc6d4680e347d906f5fa7fca73214418741df72 /appl/collab/proxy.b | |
| parent | 54bc8ff236ac10b3eaa928fd6bcfc0cdb2ba46ae (diff) | |
20060303a
Diffstat (limited to 'appl/collab/proxy.b')
| -rw-r--r-- | appl/collab/proxy.b | 177 |
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); +} |
