⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 httpd.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
#include "stdinc.h"#include "dat.h"#include "fns.h"#include "httpd.h"#include "xml.h"typedef struct HttpObj	HttpObj;enum{	ObjNameSize	= 64,	MaxObjs		= 16};struct HttpObj{	char	name[ObjNameSize];	int	(*f)(HConnect*);};static HttpObj	objs[MaxObjs];static	void		dolisten(void*);static	int		estats(HConnect *c);static	int		dindex(HConnect *c);static	int		xindex(HConnect *c);static	int		sindex(HConnect *c);static	int		notfound(HConnect *c);static	int		httpdObj(char *name, int (*f)(HConnect*));inthttpdInit(char *address){	fmtinstall('D', hdatefmt);	fmtinstall('H', httpfmt);	fmtinstall('U', hurlfmt);	if(address == nil)		address = "tcp!*!http";	httpdObj("/stats", estats);	httpdObj("/index", dindex);	httpdObj("/storage", sindex);	httpdObj("/xindex", xindex);	if(vtThread(dolisten, address) < 0)		return 0;	return 1;}static inthttpdObj(char *name, int (*f)(HConnect*)){	int i;	if(name == nil || strlen(name) >= ObjNameSize)		return 0;	for(i = 0; i < MaxObjs; i++){		if(objs[i].name[0] == '\0'){			strcpy(objs[i].name, name);			objs[i].f = f;			return 1;		}		if(strcmp(objs[i].name, name) == 0)			return 0;	}	return 0;}static HConnect*mkconnect(void){	HConnect *c;	c = mallocz(sizeof(HConnect), 1);	if(c == nil)		sysfatal("out of memory");	c->replog = nil;	c->hpos = c->header;	c->hstop = c->header;	return c;}static voiddolisten(void *vaddress){	HConnect *c;	char *address, ndir[NETPATHLEN], dir[NETPATHLEN];	int ctl, nctl, data, ok, t, i;	address = vaddress;	ctl = announce(address, dir);	if(ctl < 0){		fprint(2, "venti: httpd can't announce on %s: %r\n", address);		return;	}	for(;;){		/*		 *  wait for a call (or an error)		 */		nctl = listen(dir, ndir);		if(nctl < 0){			fprint(2, "venti: httpd can't listen on %s: %r\n", address);			return;		}		/*		 *  start a process for the service		 */		switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFNAMEG|RFMEM)){		case -1:			close(nctl);			continue;		case 0:			/*			 *  see if we know the service requested			 */			data = accept(ctl, ndir);			if(data < 0){				fprint(2, "venti: httpd can't open %s/data: %r", ndir);				exits(nil);			}			close(ctl);			close(nctl);			c = mkconnect();			hinit(&c->hin, data, Hread);			hinit(&c->hout, data, Hwrite);			for(t = 15*60*1000; ; t = 15*1000){				if(hparsereq(c, t) <= 0)					break;				ok = -1;				for(i = 0; i < MaxObjs && objs[i].name[0]; i++){					if(strcmp(c->req.uri, objs[i].name) == 0){						ok = (*objs[i].f)(c);						break;					}				}				if(i == MaxObjs)					ok = notfound(c);				if(c->head.closeit)					ok = -1;				hreqcleanup(c);				if(ok < 0)					break;			}			hreqcleanup(c);			free(c);			exits(nil);		default:			close(nctl);			break;		}	}}static intpercent(long v, long total){	if(total == 0)		total = 1;	if(v < 1000*1000)		return (v * 100) / total;	total /= 100;	if(total == 0)		total = 1;	return v / total;}static intpreq(HConnect *c){	if(hparseheaders(c, 15*60*1000) < 0)		return -1;	if(strcmp(c->req.meth, "GET") != 0	&& strcmp(c->req.meth, "HEAD") != 0)		return hunallowed(c, "GET, HEAD");	if(c->head.expectother || c->head.expectcont)		return hfail(c, HExpectFail, nil);	return 1;}static intpreqtext(HConnect *c){	Hio *hout;	int r;	r = preq(c);	if(r <= 0)		return r;	hout = &c->hout;	if(c->req.vermaj){		hokheaders(c);		hprint(hout, "Content-type: text/plain\r\n");		if(http11(c))			hprint(hout, "Transfer-Encoding: chunked\r\n");		hprint(hout, "\r\n");	}	if(http11(c))		hxferenc(hout, 1);	else		c->head.closeit = 1;	return 1;}static intnotfound(HConnect *c){	int r;	r = preq(c);	if(r <= 0)		return r;	return hfail(c, HNotFound, c->req.uri);}static intestats(HConnect *c){	Hio *hout;	int r;	r = preqtext(c);	if(r <= 0)		return r;	hout = &c->hout;	hprint(hout, "lump writes=%,ld\n", stats.lumpWrites);	hprint(hout, "lump reads=%,ld\n", stats.lumpReads);	hprint(hout, "lump cache read hits=%,ld\n", stats.lumpHit);	hprint(hout, "lump cache read misses=%,ld\n", stats.lumpMiss);	hprint(hout, "clump disk writes=%,ld\n", stats.clumpWrites);	hprint(hout, "clump disk bytes written=%,lld\n", stats.clumpBWrites);	hprint(hout, "clump disk bytes compressed=%,lld\n", stats.clumpBComp);	hprint(hout, "clump disk reads=%,ld\n", stats.clumpReads);	hprint(hout, "clump disk bytes read=%,lld\n", stats.clumpBReads);	hprint(hout, "clump disk bytes uncompressed=%,lld\n", stats.clumpBUncomp);	hprint(hout, "clump directory disk writes=%,ld\n", stats.ciWrites);	hprint(hout, "clump directory disk reads=%,ld\n", stats.ciReads);	hprint(hout, "index disk writes=%,ld\n", stats.indexWrites);	hprint(hout, "index disk reads=%,ld\n", stats.indexReads);	hprint(hout, "index disk reads for modify=%,ld\n", stats.indexWReads);	hprint(hout, "index disk reads for allocation=%,ld\n", stats.indexAReads);	hprint(hout, "index cache lookups=%,ld\n", stats.icLookups);	hprint(hout, "index cache hits=%,ld %d%%\n", stats.icHits,		percent(stats.icHits, stats.icLookups));	hprint(hout, "index cache fills=%,ld %d%%\n", stats.icFills,		percent(stats.icFills, stats.icLookups));	hprint(hout, "index cache inserts=%,ld\n", stats.icInserts);	hprint(hout, "disk cache hits=%,ld\n", stats.pcHit);	hprint(hout, "disk cache misses=%,ld\n", stats.pcMiss);	hprint(hout, "disk cache reads=%,ld\n", stats.pcReads);	hprint(hout, "disk cache bytes read=%,lld\n", stats.pcBReads);	hprint(hout, "disk writes=%,ld\n", stats.diskWrites);	hprint(hout, "disk bytes written=%,lld\n", stats.diskBWrites);	hprint(hout, "disk reads=%,ld\n", stats.diskReads);	hprint(hout, "disk bytes read=%,lld\n", stats.diskBReads);	hflush(hout);	return 1;}static intsindex(HConnect *c){	Hio *hout;	Index *ix;	Arena *arena;	vlong clumps, cclumps, uncsize, used, size;	int i, r, active;	r = preqtext(c);	if(r <= 0)		return r;	hout = &c->hout;	ix = mainIndex;	hprint(hout, "index=%s\n", ix->name);	active = 0;	clumps = 0;	cclumps = 0;	uncsize = 0;	used = 0;	size = 0;	for(i = 0; i < ix->narenas; i++){		arena = ix->arenas[i];		if(arena != nil && arena->clumps != 0){			active++;			clumps += arena->clumps;			cclumps += arena->cclumps;			uncsize += arena->uncsize;			used += arena->used;		}		size += arena->size;	}	hprint(hout, "total arenas=%d active=%d\n", ix->narenas, active);	hprint(hout, "total space=%lld used=%lld\n", size, used + clumps * ClumpInfoSize);	hprint(hout, "clumps=%lld compressed clumps=%lld data=%lld compressed data=%lld\n",		clumps, cclumps, uncsize, used - clumps * ClumpSize);	hflush(hout);	return 1;}static voiddArena(Hio *hout, Arena *arena){	hprint(hout, "arena='%s' on %s at [%lld,%lld)\n\tversion=%d created=%d modified=%d",		arena->name, arena->part->name, arena->base, arena->base + arena->size + 2 * arena->blockSize,		arena->version, arena->ctime, arena->wtime);	if(arena->sealed)		hprint(hout, " sealed\n");	else		hprint(hout, "\n");	if(!scoreEq(zeroScore, arena->score))		hprint(hout, "\tscore=%V\n", arena->score);	hprint(hout, "\tclumps=%d compressed clumps=%d data=%lld compressed data=%lld disk storage=%lld\n",		arena->clumps, arena->cclumps, arena->uncsize,		arena->used - arena->clumps * ClumpSize,		arena->used + arena->clumps * ClumpInfoSize);}static intdindex(HConnect *c){	Hio *hout;	Index *ix;	int i, r;	r = preqtext(c);	if(r <= 0)		return r;	hout = &c->hout;	ix = mainIndex;	hprint(hout, "index=%s version=%d blockSize=%d tabSize=%d\n",		ix->name, ix->version, ix->blockSize, ix->tabSize);	hprint(hout, "\tbuckets=%d div=%d\n", ix->buckets, ix->div);	for(i = 0; i < ix->nsects; i++)		hprint(hout, "\tsect=%s for buckets [%lld,%lld)\n", ix->smap[i].name, ix->smap[i].start, ix->smap[i].stop);	for(i = 0; i < ix->narenas; i++){		if(ix->arenas[i] != nil && ix->arenas[i]->clumps != 0){			hprint(hout, "arena=%s at index [%lld,%lld)\n\t", ix->amap[i].name, ix->amap[i].start, ix->amap[i].stop);			dArena(hout, ix->arenas[i]);		}	}	hflush(hout);	return 1;}static intxindex(HConnect *c){	Hio *hout;	int r;	r = preq(c);	if(r <= 0)		return r;	hout = &c->hout;	if(c->req.vermaj){		hokheaders(c);		hprint(hout, "Content-type: text/xml\r\n");		if(http11(c))			hprint(hout, "Transfer-Encoding: chunked\r\n");		hprint(hout, "\r\n");	}	if(http11(c))		hxferenc(hout, 1);	else		c->head.closeit = 1;	xmlIndex(hout, mainIndex, "index", 0);	hflush(hout);	return 1;}voidxmlIndent(Hio *hout, int indent){	int i;	for(i = 0; i < indent; i++)		hputc(hout, '\t');}voidxmlAName(Hio *hout, char *v, char *tag){	hprint(hout, " %s=\"%s\"", tag, v);}voidxmlScore(Hio *hout, u8int *v, char *tag){	if(scoreEq(zeroScore, v))		return;	hprint(hout, " %s=\"%V\"", tag, v);}voidxmlSealed(Hio *hout, int v, char *tag){	if(!v)		return;	hprint(hout, " %s=\"yes\"", tag);}voidxmlU32int(Hio *hout, u32int v, char *tag){	hprint(hout, " %s=\"%ud\"", tag, v);}voidxmlU64int(Hio *hout, u64int v, char *tag){	hprint(hout, " %s=\"%llud\"", tag, v);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -