henesyinit from lsubb0c8bdb6 years agoHistory
285 lines · 4.7 KB · C
RawDownload
#include <u.h>#include <libc.h>#include <thread.h>#include <bio.h>#include <b.h>enum {	Nclients = 256,}; typedef struct Cli Cli; struct Cli {	ulong	epoch;	int	fd;	char*	ad;	char*	addr;	int	adfd;}; int	reportall = 1;ulong	epoch;char*	adsdir	= "/lib/ndb/vol";char*	cvols;QLock	clilk;Cli*	cli[Nclients]; #define dprint if(debug)fprint#define Dprint if(debug>1)fprint int	debug; Cli*newclient(int fd){	int	i; 	qlock(&clilk);	for (i = 0; i < nelem(cli); i++)		if (cli[i] == nil)			break;	if (i == nelem(cli)){		qunlock(&clilk);		fprint(2, "adsrv: fixme: cli table exhausted\n");		return nil;	}	cli[i] = malloc(sizeof(Cli));	assert(cli[i]);	cli[i]->addr = nil;	cli[i]->epoch = 0;	cli[i]->fd = fd;	cli[i]->adfd= -1;	cli[i]->ad = nil;	qunlock(&clilk);	return cli[i];} voiddelclient(Cli* c){	int	i; 	close(c->fd);	close(c->adfd);	// ORCLOSE	qlock(&clilk);	for (i = 0; i < nelem(cli); i++)		if (cli[i] == c){			if (cli[i]->ad != nil)				dprint(2, "gone: %s\n", cli[i]->ad);			free(cli[i]->ad);			free(cli[i]);			free(cli[i]->addr);			cli[i] = nil;			break;		}	qunlock(&clilk);} voidwriteannounces(int fd, Cli* c){	int	i; 	qlock(&clilk);	for (i = 0; i < nelem(cli); i++){		if (cli[i] != nil && cli[i]->ad != nil)			if (reportall || cli[i]->epoch > c->epoch)				fprint(fd, "%s\n", cli[i]->ad);	}	if (cvols != nil)		fprint(fd, "%s", cvols);	c->epoch = epoch;	write(fd, "\n", 1);	qunlock(&clilk);} char*readannounce(Biobuf* bin, Cli* c){	char*	a;	long	l;	char*	p;	char*	s;	char*	fname;	char*	path; 	if (c->ad != nil && c->adfd != -1)		return nil;	fname = nil;	a = Brdline(bin, '\n');	l = Blinelen(bin);	if (l < 1)		return nil;	a[--l] = 0;	if (l > 0 && a[l-1] == '\r')		a[--l] = 0;	if (strncmp(a, "tcp!", 4))		goto fail;	s = strchr(a, '\t');	if (s == nil)		goto fail;	*s++ = 0;	fname = strdup(a);	p = strchr(fname, '!');	if (p == nil)		goto fail;	p++;	p = strchr(p, '!');	if (p == nil)		goto fail;	p++;	path = smprint("%s/%s", adsdir, fname);	qlock(&clilk);	c->epoch = ++epoch;	free(c->ad);	c->ad = smprint("tcp!%s!%s\t%s", c->addr, p, s);	if (c->adfd != -1)		close(c->adfd);	c->adfd = create(path, OWRITE|ORCLOSE, 0666);	if (c->adfd == -1 || fprint(c->adfd, "%s\n", c->ad) < 0){		fprint(2, "%s: %s: %r\n", argv0, s);		free(c->ad);		c->ad = nil;		close(c->adfd);		c->adfd = -1;	}	// leave it open.	qunlock(&clilk);	free(path);	free(fname);	return c->ad;fail:	fprint(2, "bad announce: %s\n", a);	free(fname);	return nil;} voidclientproc(void* a){	Cli*	c = a;	Biobuf	bin;	char*	ln;	long	l; 	Binit(&bin, c->fd, OREAD);	while(ln = Brdline(&bin, '\n')){		l = Blinelen(&bin);		if (l < 2)			continue;		ln[--l] = 0;		if (ln[l-1] == '\r')			ln[--l] = 0;		if (!strcmp(ln, "PlanB announces")){			Dprint(2, "write announces to %d\n", c->fd);			writeannounces(c->fd, c);		} else if (!strcmp(ln, "PlanB announce:")){			if (readannounce(&bin, c))				dprint(2, "announce from %d: %s\n", c->fd, c->ad);		} else			Dprint(2, "unknown messsage: %s\n", ln);	}	Dprint(2, "gone client %d: %r\n", c->fd);	Bterm(&bin);	delclient(c);	threadexits(nil);} static char*getremotesys(char *ndir){	char buf[128], *serv, *sys;	int fd, n; 	snprint(buf, sizeof buf, "%s/remote", ndir);	sys = nil;	fd = open(buf, OREAD);	if(fd >= 0){		n = read(fd, buf, sizeof(buf)-1);		if(n>0){			buf[n-1] = 0;			serv = strchr(buf, '!');			if(serv)				*serv = 0;			sys = strdup(buf);		}		close(fd);	}	if(sys == nil)		sys = strdup("unknown");	return sys;} voidserver(char* addr){	char	adir[40], ldir[40];	int	cfd, fd;	Cli*	c; 	cfd = announce(addr, adir);	if (cfd < 0)		sysfatal("%s: announce: %r", argv0);	for (;;){		cfd = listen(adir, ldir);		if (cfd < 0)			sysfatal("%s: listen: %r", argv0);		fd = accept(cfd, ldir);		if(fd < 0){			fprint(2, "%s: accept: %r\n", argv0);			continue; 		}		fprint(cfd, "keepalive 2000\n");		close(cfd);		c = newclient(fd);		c->addr = getremotesys(ldir);		Dprint(2, "new client %d %s\n", fd, c->addr);		proccreate(clientproc, c, 16*1024);	}	sysfatal("server died");} voidusage(void){	fprint(2, "usage: %s [-d] [-n addr] [-c volcfg] [dir]\n", argv0);	sysfatal("usage");} voidthreadmain(int argc, char *argv[]){	char*	addr;	char*	cfg; 	addr= "tcp!*!11010";	cfg = "/lib/ndb/vol/vols";	ARGBEGIN{	case 'c':		cfg = EARGF(usage());		break;	case 'n':		addr = EARGF(usage());		break;	case 'd':		debug++;		break;	default:		usage();	}ARGEND;	switch(argc){	case 0:		break;	case 1:		adsdir = argv[0];		break;	default:		usage();	}	if (cfg != nil && access(cfg, AREAD) == 0)		cvols = readfstr(cfg);	dprint(2, "%s %s %s\n", argv0, adsdir, addr);	server(addr);	threadexits(nil);} 

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t