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

📄 devip.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "u.h"#include "lib.h"#include "dat.h"#include "fns.h"#include "error.h"#include "devip.h"void		hnputl(void *p, unsigned long v);void		hnputs(void *p, unsigned short v);unsigned long	nhgetl(void *p);unsigned short	nhgets(void *p);unsigned long	parseip(char *to, char *from);void	csclose(Chan*);long	csread(Chan*, void*, long, vlong);long	cswrite(Chan*, void*, long, vlong);void osipinit(void);enum{	Qtopdir		= 1,	/* top level directory */	Qcs,	Qprotodir,		/* directory for a protocol */	Qclonus,	Qconvdir,		/* directory for a conversation */	Qdata,	Qctl,	Qstatus,	Qremote,	Qlocal,	Qlisten,	MAXPROTO	= 4};#define TYPE(x) 	((int)((x).path & 0xf))#define CONV(x) 	((int)(((x).path >> 4)&0xfff))#define PROTO(x) 	((int)(((x).path >> 16)&0xff))#define QID(p, c, y) 	(((p)<<16) | ((c)<<4) | (y))typedef struct Proto	Proto;typedef struct Conv	Conv;struct Conv{	int	x;	Ref	r;	int	sfd;	int	perm;	char	owner[KNAMELEN];	char*	state;	ulong	laddr;	ushort	lport;	ulong	raddr;	ushort	rport;	int	restricted;	char	cerr[KNAMELEN];	Proto*	p;};struct Proto{	Lock	l;	int	x;	int	stype;	char	name[KNAMELEN];	int	nc;	int	maxconv;	Conv**	conv;	Qid	qid;};static	int	np;static	Proto	proto[MAXPROTO];int	eipfmt(Fmt*);static	Conv*	protoclone(Proto*, char*, int);static	void	setladdr(Conv*);intipgen(Chan *c, char *nname, Dirtab *d, int nd, int s, Dir *dp){	Qid q;	Conv *cv;	char *p;	USED(nname);	q.vers = 0;	q.type = 0;	switch(TYPE(c->qid)) {	case Qtopdir:		if(s >= 1+np)			return -1;		if(s == 0){			q.path = QID(s, 0, Qcs);			devdir(c, q, "cs", 0, "network", 0666, dp);		}else{			s--;			q.path = QID(s, 0, Qprotodir);			q.type = QTDIR;			devdir(c, q, proto[s].name, 0, "network", DMDIR|0555, dp);		}		return 1;	case Qprotodir:		if(s < proto[PROTO(c->qid)].nc) {			cv = proto[PROTO(c->qid)].conv[s];			sprint(up->genbuf, "%d", s);			q.path = QID(PROTO(c->qid), s, Qconvdir);			q.type = QTDIR;			devdir(c, q, up->genbuf, 0, cv->owner, DMDIR|0555, dp);			return 1;		}		s -= proto[PROTO(c->qid)].nc;		switch(s) {		default:			return -1;		case 0:			p = "clone";			q.path = QID(PROTO(c->qid), 0, Qclonus);			break;		}		devdir(c, q, p, 0, "network", 0555, dp);		return 1;	case Qconvdir:		cv = proto[PROTO(c->qid)].conv[CONV(c->qid)];		switch(s) {		default:			return -1;		case 0:			q.path = QID(PROTO(c->qid), CONV(c->qid), Qdata);			devdir(c, q, "data", 0, cv->owner, cv->perm, dp);			return 1;		case 1:			q.path = QID(PROTO(c->qid), CONV(c->qid), Qctl);			devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);			return 1;		case 2:			p = "status";			q.path = QID(PROTO(c->qid), CONV(c->qid), Qstatus);			break;		case 3:			p = "remote";			q.path = QID(PROTO(c->qid), CONV(c->qid), Qremote);			break;		case 4:			p = "local";			q.path = QID(PROTO(c->qid), CONV(c->qid), Qlocal);			break;		case 5:			p = "listen";			q.path = QID(PROTO(c->qid), CONV(c->qid), Qlisten);			break;		}		devdir(c, q, p, 0, cv->owner, 0444, dp);		return 1;	}	return -1;}static voidnewproto(char *name, int type, int maxconv){	int l;	Proto *p;	if(np >= MAXPROTO) {		print("no %s: increase MAXPROTO", name);		return;	}	p = &proto[np];	strcpy(p->name, name);	p->stype = type;	p->qid.path = QID(np, 0, Qprotodir);	p->qid.type = QTDIR;	p->x = np++;	p->maxconv = maxconv;	l = sizeof(Conv*)*(p->maxconv+1);	p->conv = mallocz(l, 1);	if(p->conv == 0)		panic("no memory");}voidipinit(void){	osipinit();	newproto("udp", S_UDP, 10);	newproto("tcp", S_TCP, 30);	fmtinstall('I', eipfmt);	fmtinstall('E', eipfmt);	}Chan *ipattach(char *spec){	Chan *c;	c = devattach('I', spec);	c->qid.path = QID(0, 0, Qtopdir);	c->qid.type = QTDIR;	c->qid.vers = 0;	return c;}static Walkqid*ipwalk(Chan *c, Chan *nc, char **name, int nname){	return devwalk(c, nc, name, nname, 0, 0, ipgen);}intipstat(Chan *c, uchar *dp, int n){	return devstat(c, dp, n, 0, 0, ipgen);}Chan *ipopen(Chan *c, int omode){	Proto *p;	ulong raddr;	ushort rport;	int perm, sfd;	Conv *cv, *lcv;	omode &= 3;	perm = 0;	switch(omode) {	case OREAD:		perm = 4;		break;	case OWRITE:		perm = 2;		break;	case ORDWR:		perm = 6;		break;	}	switch(TYPE(c->qid)) {	default:		break;	case Qtopdir:	case Qprotodir:	case Qconvdir:	case Qstatus:	case Qremote:	case Qlocal:		if(omode != OREAD)			error(Eperm);		break;	case Qclonus:		p = &proto[PROTO(c->qid)];		cv = protoclone(p, up->user, -1);		if(cv == 0)			error(Enodev);		c->qid.path = QID(p->x, cv->x, Qctl);		c->qid.vers = 0;		break;	case Qdata:	case Qctl:		p = &proto[PROTO(c->qid)];		lock(&p->l);		cv = p->conv[CONV(c->qid)];		lock(&cv->r.lk);		if((perm & (cv->perm>>6)) != perm) {			if(strcmp(up->user, cv->owner) != 0 ||		 	  (perm & cv->perm) != perm) {				unlock(&cv->r.lk);				unlock(&p->l);				error(Eperm);			}		}		cv->r.ref++;		if(cv->r.ref == 1) {			memmove(cv->owner, up->user, KNAMELEN);			cv->perm = 0660;		}		unlock(&cv->r.lk);		unlock(&p->l);		break;	case Qlisten:		p = &proto[PROTO(c->qid)];		lcv = p->conv[CONV(c->qid)];		sfd = so_accept(lcv->sfd, &raddr, &rport);		cv = protoclone(p, up->user, sfd);		if(cv == 0) {			close(sfd);			error(Enodev);		}		cv->raddr = raddr;		cv->rport = rport;		setladdr(cv);		cv->state = "Established";		c->qid.path = QID(p->x, cv->x, Qctl);		break;	}	c->mode = openmode(omode);	c->flag |= COPEN;	c->offset = 0;	return c;}voidipclose(Chan *c){	Conv *cc;	switch(TYPE(c->qid)) {	case Qcs:		csclose(c);		break;	case Qdata:	case Qctl:		if((c->flag & COPEN) == 0)			break;		cc = proto[PROTO(c->qid)].conv[CONV(c->qid)];		if(decref(&cc->r) != 0)			break;		strcpy(cc->owner, "network");		cc->perm = 0666;		cc->state = "Closed";		cc->laddr = 0;		cc->raddr = 0;		cc->lport = 0;		cc->rport = 0;		close(cc->sfd);		break;	}}longipread(Chan *ch, void *a, long n, vlong offset){	int r;	Conv *c;	Proto *x;	uchar ip[4];	char buf[128], *p;/*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/	p = a;	switch(TYPE(ch->qid)) {	default:		error(Eperm);	case Qcs:		return csread(ch, a, n, offset);	case Qprotodir:	case Qtopdir:	case Qconvdir:		return devdirread(ch, a, n, 0, 0, ipgen);	case Qctl:		sprint(buf, "%d", CONV(ch->qid));		return readstr(offset, p, n, buf);	case Qremote:		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];		hnputl(ip, c->raddr);		sprint(buf, "%I!%d\n", ip, c->rport);		return readstr(offset, p, n, buf);	case Qlocal:		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];		hnputl(ip, c->laddr);		sprint(buf, "%I!%d\n", ip, c->lport);		return readstr(offset, p, n, buf);	case Qstatus:		x = &proto[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		sprint(buf, "%s/%d %d %s \n",			c->p->name, c->x, c->r.ref, c->state);		return readstr(offset, p, n, buf);	case Qdata:		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];		r = so_recv(c->sfd, a, n, 0);		if(r < 0){			oserrstr();			nexterror();		}		return r;	}}static voidsetladdr(Conv *c){	so_getsockname(c->sfd, &c->laddr, &c->lport);}static voidsetlport(Conv *c){	if(c->restricted == 0 && c->lport == 0)		return;	so_bind(c->sfd, c->restricted, c->lport);}static voidsetladdrport(Conv *c, char *str){	char *p, addr[4];	p = strchr(str, '!');	if(p == 0) {		p = str;		c->laddr = 0;	}	else {		*p++ = 0;		parseip(addr, str);		c->laddr = nhgetl((uchar*)addr);	}	if(*p == '*')		c->lport = 0;	else		c->lport = atoi(p);	setlport(c);}static char*setraddrport(Conv *c, char *str){	char *p, addr[4];	p = strchr(str, '!');	if(p == 0)		return "malformed address";	*p++ = 0;	parseip(addr, str);	c->raddr = nhgetl((uchar*)addr);	c->rport = atoi(p);	p = strchr(p, '!');	if(p) {		if(strcmp(p, "!r") == 0)			c->restricted = 1;	}	return 0;}longipwrite(Chan *ch, void *a, long n, vlong offset){	Conv *c;	Proto *x;	int r, nf;	char *p, *fields[3], buf[128];	switch(TYPE(ch->qid)) {	default:		error(Eperm);	case Qcs:		return cswrite(ch, a, n, offset);	case Qctl:		x = &proto[PROTO(ch->qid)];		c = x->conv[CONV(ch->qid)];		if(n > sizeof(buf)-1)			n = sizeof(buf)-1;		memmove(buf, a, n);		buf[n] = '\0';		nf = tokenize(buf, fields, 3);		if(strcmp(fields[0], "connect") == 0){			switch(nf) {			default:				error("bad args to connect");			case 2:

⌨️ 快捷键说明

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