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

📄 p9any.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* * p9any - protocol negotiator. * * Protocol: *	Server->Client: list of proto@domain, tokenize separated, nul terminated *	Client->Server: proto domain, tokenize separated (not proto@domain), nul terminated * * Server protocol: * 	read list of protocols. *	write null-terminated  */#include "dat.h"static Proto *negotiable[] = {	&p9sk1,};struct State{	Fsstate subfss;	State *substate;	/* be very careful; this is not one of our States */	Proto *subproto;	int keyasked;	String *subdom;	int version;};enum{	CNeedProtos,	CHaveProto,	CNeedOK,	CRelay,	SHaveProtos,	SNeedProto,	SHaveOK,	SRelay,	Maxphase,};static char *phasenames[Maxphase] ={[CNeedProtos]	"CNeedProtos",[CHaveProto]	"CHaveProto",[CNeedOK]	"CNeedOK",[CRelay]	"CRelay",[SHaveProtos]	"SHaveProtos",[SNeedProto]	"SNeedProto",[SHaveOK]	"SHaveOK",[SRelay]	"SRelay",};static intp9anyinit(Proto*, Fsstate *fss){	int iscli;	State *s;	if((iscli = isclient(_strfindattr(fss->attr, "role"))) < 0)		return failure(fss, nil);	s = emalloc(sizeof *s);	fss = fss;	fss->phasename = phasenames;	fss->maxphase = Maxphase;	if(iscli)		fss->phase = CNeedProtos;	else		fss->phase = SHaveProtos;	s->version = 1;	fss->ps = s;	return RpcOk;}static voidp9anyclose(Fsstate *fss){	State *s;	s = fss->ps;	if(s->subproto && s->subfss.ps && s->subproto->close)		(*s->subproto->close)(&s->subfss);	s->subproto = nil;	s->substate = nil;	s_free(s->subdom);	s->subdom = nil;	s->keyasked = 0;	memset(&s->subfss, 0, sizeof s->subfss);	free(s);}static voidsetupfss(Fsstate *fss, State *s, Key *k){	fss->attr = setattr(fss->attr, "proto=%q", s->subproto->name);	fss->attr = setattr(fss->attr, "dom=%q", _strfindattr(k->attr, "dom"));	s->subfss.attr = fss->attr;	s->subfss.phase = Notstarted;	s->subfss.sysuser = fss->sysuser;	s->subfss.seqnum = fss->seqnum;	s->subfss.conf = fss->conf;	s->subfss.nconf = fss->nconf;}static intpassret(Fsstate *fss, State *s, int ret){	switch(ret){	default:		return ret;	case RpcFailure:		if(s->subfss.phase == Broken)			fss->phase = Broken;		memmove(fss->err, s->subfss.err, sizeof fss->err);		return ret;	case RpcNeedkey:		memmove(fss->keyinfo, s->subfss.keyinfo, sizeof fss->keyinfo);		return ret;	case RpcOk:		if(s->subfss.haveai){			fss->haveai = 1;			fss->ai = s->subfss.ai;			s->subfss.haveai = 0;		}		if(s->subfss.phase == Established)			fss->phase = Established;		return ret;	case RpcToosmall:		fss->rpc.nwant = s->subfss.rpc.nwant;		return ret;	case RpcConfirm:		fss->conf = s->subfss.conf;		fss->nconf = s->subfss.nconf;		return ret;	}}static intp9anyread(Fsstate *fss, void *a, uint *n){	int i, m, ophase, ret;	Attr *anew;	Key *k;	Keyinfo ki;	String *negstr;	State *s;	s = fss->ps;	switch(fss->phase){	default:		return phaseerror(fss, "read");	case SHaveProtos:		m = 0;		negstr = s_new();		mkkeyinfo(&ki, fss, nil);		ki.attr = nil;		ki.noconf = 1;		ki.user = nil;		for(i=0; i<nelem(negotiable); i++){			anew = setattr(_copyattr(fss->attr), "proto=%q dom?", negotiable[i]->name);			ki.attr = anew;			for(ki.skip=0; findkey(&k, &ki, nil)==RpcOk; ki.skip++){				if(m++)					s_append(negstr, " ");				s_append(negstr, negotiable[i]->name);				s_append(negstr, "@");				s_append(negstr, _strfindattr(k->attr, "dom"));				closekey(k);			}			_freeattr(anew);		}		if(m == 0){			s_free(negstr);			return failure(fss, Enegotiation);		}		i = s_len(negstr)+1;		if(*n < i){			s_free(negstr);			return toosmall(fss, i);		}		*n = i;		memmove(a, s_to_c(negstr), i+1);		fss->phase = SNeedProto;		s_free(negstr);		return RpcOk;	case CHaveProto:		i = strlen(s->subproto->name)+1+s_len(s->subdom)+1;		if(*n < i)			return toosmall(fss, i);		*n = i;		strcpy(a, s->subproto->name);		strcat(a, " ");		strcat(a, s_to_c(s->subdom));		if(s->version == 1)			fss->phase = CRelay;		else			fss->phase = CNeedOK;		return RpcOk;	case SHaveOK:		i = 3;		if(*n < i)			return toosmall(fss, i);		*n = i;		strcpy(a, "OK");		fss->phase = SRelay;		return RpcOk;	case CRelay:	case SRelay:		ophase = s->subfss.phase;		ret = (*s->subproto->read)(&s->subfss, a, n);		rpcrdwrlog(&s->subfss, "read", *n, ophase, ret);		return passret(fss, s, ret);	}}static char*getdom(char *p){	p = strchr(p, '@');	if(p == nil)		return "";	return p+1;}static Proto*findneg(char *name){	int i, len;	char *p;	if(p = strchr(name, '@'))		len = p-name;	else		len = strlen(name);	for(i=0; i<nelem(negotiable); i++)		if(strncmp(negotiable[i]->name, name, len) == 0 && negotiable[i]->name[len] == 0)			return negotiable[i];	return nil;}static intp9anywrite(Fsstate *fss, void *va, uint n){	char *a, *dom, *user, *token[20];	int asking, i, m, ophase, ret;	Attr *anew, *anewsf, *attr;	Key *k;	Keyinfo ki;	Proto *p;	State *s;	s = fss->ps;	a = va;	switch(fss->phase){	default:		return phaseerror(fss, "write");	case CNeedProtos:		if(n==0 || a[n-1] != '\0')			return toosmall(fss, 2048);		a = estrdup(a);		m = tokenize(a, token, nelem(token));		if(m > 0 && strncmp(token[0], "v.", 2) == 0){			s->version = atoi(token[0]+2);			if(s->version != 2){				free(a);				return failure(fss, "unknown version of p9any");			}		}			/*		 * look for a key		 */		anew = _delattr(_delattr(_copyattr(fss->attr), "proto"), "role");		anewsf = _delattr(_copyattr(anew), "user");		user = _strfindattr(anew, "user");		k = nil;		p = nil;		dom = nil;		for(i=(s->version==1?0:1); i<m; i++){			p = findneg(token[i]);			if(p == nil)				continue;			dom = getdom(token[i]);			ret = RpcFailure;			mkkeyinfo(&ki, fss, nil);			if(user==nil || strcmp(user, fss->sysuser)==0){				ki.attr = anewsf;				ki.user = nil;				ret = findkey(&k, &ki, "proto=%q dom=%q role=speakfor %s",						p->name, dom, p->keyprompt);			}			if(ret == RpcFailure){				ki.attr = anew;				ki.user = fss->sysuser;				ret = findkey(&k, &ki,					"proto=%q dom=%q role=client %s",					p->name, dom, p->keyprompt);			}			if(ret == RpcConfirm){				free(a);				return ret;			}			if(ret == RpcOk)				break;		}		_freeattr(anewsf);		/*		 * no acceptable key, go through the proto@domains one at a time.		 */		asking = 0;		if(k == nil){			while(!asking && s->keyasked < m){				p = findneg(token[s->keyasked]);				if(p == nil){					s->keyasked++;					continue;				}				dom = getdom(token[s->keyasked]);				mkkeyinfo(&ki, fss, nil);				ki.attr = anew;				ret = findkey(&k, &ki,					"proto=%q dom=%q role=client %s",					p->name, dom, p->keyprompt);				s->keyasked++;				if(ret == RpcNeedkey){					asking = 1;					break;				}			}		}		if(k == nil){			free(a);			_freeattr(anew);			if(asking)				return RpcNeedkey;			else if(s->keyasked)				return failure(fss, nil);			else				return failure(fss, Enegotiation);		}		s->subdom = s_copy(dom);		s->subproto = p;		free(a);		_freeattr(anew);		setupfss(fss, s, k);		closekey(k);		ret = (*s->subproto->init)(p, &s->subfss);		rpcstartlog(s->subfss.attr, &s->subfss, ret);		if(ret == RpcOk)			fss->phase = CHaveProto;		return passret(fss, s, ret);	case SNeedProto:		if(n==0 || a[n-1] != '\0')			return toosmall(fss, n+1);		a = estrdup(a);		m = tokenize(a, token, nelem(token));		if(m != 2){			free(a);			return failure(fss, Ebadarg);		}		p = findneg(token[0]);		if(p == nil){			free(a);			return failure(fss, Enegotiation);		}		attr = _delattr(_copyattr(fss->attr), "proto");		mkkeyinfo(&ki, fss, nil);		ki.attr = attr;		ki.user = nil;		ret = findkey(&k, &ki, "proto=%q dom=%q role=server", token[0], token[1]);		free(a);		_freeattr(attr);		if(ret == RpcConfirm)			return ret;		if(ret != RpcOk)			return failure(fss, Enegotiation);		s->subproto = p;		setupfss(fss, s, k);		closekey(k);		ret = (*s->subproto->init)(p, &s->subfss);		if(ret == RpcOk){			if(s->version == 1)				fss->phase = SRelay;			else				fss->phase = SHaveOK;		}		return passret(fss, s, ret);	case CNeedOK:		if(n < 3)			return toosmall(fss, 3);		if(strcmp("OK", a) != 0)			return failure(fss, "server gave up");		fss->phase = CRelay;		return RpcOk;	case CRelay:	case SRelay:		ophase = s->subfss.phase;		ret = (*s->subproto->write)(&s->subfss, va, n);		rpcrdwrlog(&s->subfss, "write", n, ophase, ret);		return passret(fss, s, ret);	}}Proto p9any = {.name=	"p9any",.init=		p9anyinit,.write=	p9anywrite,.read=	p9anyread,.close=	p9anyclose,};

⌨️ 快捷键说明

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