Plan 9 from Bell Labs’s /usr/web/sources/patch/applied/9p-auth-and-listen/netsrv.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


#include <u.h>
#include <libc.h>
#include <auth.h>
#include <fcall.h>
#include <thread.h>
#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;
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].