#include #include #include #include #include #include <9p.h> static Srv* clonesrv(Srv* from) { Srv* to; /* If you call leak it might seem that we leak this * srv and all its resources. * That's not true. netsrvproc process * releases to and its resources, but the parent * process reuses the variable to allocate new * servers, and that seems to confuse leak * for a while. */ to = emalloc9p(sizeof(Srv)); *to = *from; to->infd = to->outfd = to->srvfd = -1; to->fpool = nil; to->rpool = nil; to->rbuf = to->wbuf = nil; to->addr = nil; memset(&to->rlock, 0, sizeof(to->rlock)); memset(&to->wlock, 0, sizeof(to->wlock)); return to; } Srv* newclientsrv(Srv* s, char* adir, int* lfdp) { Srv* msrv; char ldir[40]; int dfd; NetConnInfo* ni; // I love these names that break indent *lfdp = listen(adir, ldir); if (*lfdp < 0) sysfatal("listen: %r"); dfd = accept(*lfdp, ldir); if (dfd < 0){ fprint(2, "%s: srvlistener: %r\n", argv0); return nil; } msrv = clonesrv(s); msrv->infd = msrv->outfd = dfd; ni = getnetconninfo(ldir, *lfdp); if (ni){ msrv->addr = estrdup9p(ni->raddr); freenetconninfo(ni); } else msrv->addr = nil; return msrv; } static void netsrvproc(Srv* s) { if (chatty9p) fprint(2, "%d %s: new srv: %s\n", getpid(), argv0, s->addr); srv(s); if (chatty9p) fprint(2, "%d %s: exiting: %s\n", getpid(), argv0, s->addr); close(s->infd); free(s->addr); free(s); _exits(0); } static void srvlistener(Srv* s) { char adir[40]; Srv* msrv; int afd,lfd; afd = announce(s->addr, adir); if (afd < 0) sysfatal("announce: %r"); rendezvous((ulong)srvlistener, 0); for(;;){ msrv = newclientsrv(s, adir, &lfd); switch(rfork(RFPROC|RFMEM|RFNOWAIT)){ case -1: sysfatal("srvlistener: %r"); case 0: netsrvproc(msrv); break; default: close(lfd); } } } int netsrv(Srv* srv, char* addr) { int pid; srv->addr = estrdup9p(addr); srv->slock = emalloc9p(sizeof(QLock)); memset(srv->slock, 0, sizeof(QLock)); switch(pid = rfork(RFPROC|RFMEM|RFNAMEG|RFNOWAIT)){ case -1: sysfatal("netsrv: %r"); case 0: srvlistener(srv); _exits(0); default: rendezvous((ulong)srvlistener, 0); } return pid; }