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

📄 devsdp.c

📁 著名操作系统Plan 9的第三版的部分核心源代码。现在很难找到了。Plan 9是bell实验室开发的Unix后继者。
💻 C
📖 第 1 页 / 共 3 页
字号:
sdpclone(Sdp *sdp){	Conv *c, **pp, **ep;	c = nil;	ep = sdp->conv + nelem(sdp->conv);	qlock(sdp);	if(waserror()) {		qunlock(sdp);		nexterror();	}	for(pp = sdp->conv; pp < ep; pp++) {		c = *pp;		if(c == nil){			c = malloc(sizeof(Conv));			if(c == nil)				error(Enomem);			memset(c, 0, sizeof(Conv));			qlock(c);			c->sdp = sdp;			c->id = pp - sdp->conv;			*pp = c;			sdp->nconv++;			break;		}		if(c->ref == 0 && canqlock(c)){			if(c->ref == 0)				break;			qunlock(c);		}	}	poperror();	qunlock(sdp);	if(pp >= ep)		return nil;	assert(c->state == CFree);	// set ref to 2 - 1 ref for open - 1 ref for channel state	c->ref = 2;	c->state = CInit;	c->in.window = ~0;	strncpy(c->owner, up->user, sizeof(c->owner));	c->perm = 0660;	qunlock(c);	return c;}// assume c is lockedstatic voidconvretryinit(Conv *c){	c->retries = 0;	// +2 to avoid rounding effects.	c->timeout = TK2SEC(m->ticks) + 2;}// assume c is lockedstatic intconvretry(Conv *c, int reset){	c->retries++;	if(c->retries > MaxRetries) {		if(reset)			convoconnect(c, ConReset, c->dialid, c->acceptid);		convsetstate(c, CClosed);		return 0;	}	c->timeout = TK2SEC(m->ticks) + (c->retries+1);	return 1;}// assumes c is lockedstatic voidconvtimer(Conv *c, ulong sec){	Block *b;	if(c->timeout > sec)		return;	switch(c->state) {	case CInit:		break;	case CDial:		if(convretry(c, 1))			convoconnect(c, ConOpenRequest, c->dialid, 0);		break;	case CAccept:		if(convretry(c, 1))			convoconnect(c, ConOpenAck, c->dialid, c->acceptid);		break;	case COpen:		b = c->out.controlpkt;		if(b != nil) {			if(convretry(c, 1))				convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));			break;		}		c->timeout = c->lastrecv + KeepAlive;		if(c->timeout > sec)			break;		// keepalive - randomly spaced between KeepAlive and 2*KeepAlive		if(c->timeout + KeepAlive > sec && nrand(c->lastrecv + 2*KeepAlive - sec) > 0)			break;		// can not use writecontrol		b = allocb(4);		c->out.controlseq++;		hnputl(b->wp, c->out.controlseq);		b->wp += 4;		c->out.controlpkt = b;		convretryinit(c);		if(!waserror()) {			convoput(c, TControl, ControlMesg, copyblock(b, blocklen(b)));			poperror();		}		break;	case CLocalClose:		if(convretry(c, 0))			convoconnect(c, ConClose, c->dialid, c->acceptid);		break;	case CRemoteClose:	case CClosed:		break;	}}static voidsdpackproc(void *a){	Sdp *sdp = a;	ulong sec;	int i;	Conv *c;	for(;;) {		tsleep(&sdp->vous, return0, 0, 1000);		sec = TK2SEC(m->ticks);		qlock(sdp);		for(i=0; i<sdp->nconv; i++) {			c = sdp->conv[i];			if(c->ref == 0)				continue;			qunlock(sdp);			qlock(c);			if(c->ref > 0 && !waserror()) {				convtimer(c, sec);				poperror();			}			qunlock(c);			qlock(sdp);		}		qunlock(sdp);	}}Dev sdpdevtab = {	'E',	"sdp",	devreset,	sdpinit,	sdpattach,	devclone,	sdpwalk,	sdpstat,	sdpopen,	devcreate,	sdpclose,	sdpread,	devbread,	sdpwrite,	devbwrite,	devremove,	devwstat,};// assume hold lock on cstatic voidconvsetstate(Conv *c, int state){if(1)print("convsetstate %d: %s -> %s\n", c->id, convstatename[c->state], convstatename[state]);	switch(state) {	default:		panic("setstate: bad state: %d", state);	case CDial:		assert(c->state == CInit);		c->dialid = (rand()<<16) + rand();		convretryinit(c);		convoconnect(c, ConOpenRequest, c->dialid, 0);		break;	case CAccept:		assert(c->state == CInit);		c->acceptid = (rand()<<16) + rand();		convretryinit(c);		convoconnect(c, ConOpenAck, c->dialid, c->acceptid);		break;	case COpen:		assert(c->state == CDial || c->state == CAccept);		c->lastrecv = TK2SEC(m->ticks);		if(c->state == CDial) {			convretryinit(c);			convoconnect(c, ConOpenAckAck, c->dialid, c->acceptid);			hnputl(c->in.secret, c->acceptid);			hnputl(c->in.secret+4, c->dialid);			hnputl(c->out.secret, c->dialid);			hnputl(c->out.secret+4, c->acceptid);		} else {			hnputl(c->in.secret, c->dialid);			hnputl(c->in.secret+4, c->acceptid);			hnputl(c->out.secret, c->acceptid);			hnputl(c->out.secret+4, c->dialid);		}		setalg(c, "hmac_md5_96", authalg, &c->auth);		break;	case CLocalClose:		assert(c->state == CAccept || c->state == COpen);		convretryinit(c);		convoconnect(c, ConClose, c->dialid, c->acceptid);		break;	case CRemoteClose:		wakeup(&c->in.controlready);		wakeup(&c->out.controlready);		break;	case CClosed:		wakeup(&c->in.controlready);		wakeup(&c->out.controlready);		if(c->readproc)			postnote(c->readproc, 1, "interrupt", 0);		if(c->state != CClosed)			convderef(c);		break;	}	c->state = state;}//assumes c is lockedstatic voidconvderef(Conv *c){	c->ref--;	if(c->ref > 0) {		return;	}	assert(c->ref == 0);	assert(c->dataopen == 0);	assert(c->controlopen == 0);if(0)print("convderef: %d: ref == 0!\n", c->id);	c->state = CFree;	if(c->chan) {			cclose(c->chan);		c->chan = nil;	}	if(c->channame) {		free(c->channame);		c->channame = nil;	}	c->cipher = nil;	c->auth = nil;	c->comp = nil;	strcpy(c->owner, "network");	c->perm = 0660;	c->dialid = 0;	c->acceptid = 0;	c->timeout = 0;	c->retries = 0;	c->drop = 0;	onewaycleanup(&c->in);	onewaycleanup(&c->out);	memset(&c->lstats, 0, sizeof(Stats));	memset(&c->rstats, 0, sizeof(Stats));}static voidonewaycleanup(OneWay *ow){	if(ow->controlpkt)		freeb(ow->controlpkt);	if(ow->authstate)		free(ow->authstate);	if(ow->cipherstate)		free(ow->cipherstate);	if(ow->compstate)		free(ow->compstate);	memset(ow, 0, sizeof(OneWay));}// assumes conv is lockedstatic voidconvopenchan(Conv *c, char *path){	if(c->state != CInit || c->chan != nil)		error("already connected");	c->chan = namec(path, Aopen, ORDWR, 0);	c->channame = smalloc(strlen(path)+1);	strcpy(c->channame, path);	if(waserror()) {		cclose(c->chan);		c->chan = nil;		free(c->channame);		c->channame = nil;		nexterror();	}	kproc("convreader", convreader, c);	assert(c->reader == 0 && c->ref > 0);	// after kproc in case it fails	c->reader = 1;	c->ref++;	poperror();}static voidconvstats(Conv *c, int local, char *buf, int n){	Stats *stats;	char *p, *ep;	int i;	if(local) {		stats = &c->lstats;	} else {		if(!waserror()) {			writecontrol(c, 0, 0, 1);			poperror();		}		stats = &c->rstats;	}	qlock(c);	p = buf;	ep = buf + n;	p += snprint(p, ep-p, "outPackets: %lud\n", stats->outPackets);	p += snprint(p, ep-p, "outDataPackets: %lud\n", stats->outDataPackets);	p += snprint(p, ep-p, "outDataBytes: %lud\n", stats->outDataBytes);	p += snprint(p, ep-p, "outCompDataBytes: %lud\n", stats->outCompDataBytes);	for(i=0; i<NCompStats; i++) {		if(stats->outCompStats[i] == 0)			continue;		p += snprint(p, ep-p, "outCompStats[%d]: %lud\n", i, stats->outCompStats[i]);	}	p += snprint(p, ep-p, "inPackets: %lud\n", stats->inPackets);	p += snprint(p, ep-p, "inDataPackets: %lud\n", stats->inDataPackets);	p += snprint(p, ep-p, "inDataBytes: %lud\n", stats->inDataBytes);	p += snprint(p, ep-p, "inCompDataBytes: %lud\n", stats->inCompDataBytes);	p += snprint(p, ep-p, "inMissing: %lud\n", stats->inMissing);	p += snprint(p, ep-p, "inDup: %lud\n", stats->inDup);	p += snprint(p, ep-p, "inReorder: %lud\n", stats->inReorder);	p += snprint(p, ep-p, "inBadComp: %lud\n", stats->inBadComp);	p += snprint(p, ep-p, "inBadAuth: %lud\n", stats->inBadAuth);	p += snprint(p, ep-p, "inBadSeq: %lud\n", stats->inBadSeq);	p += snprint(p, ep-p, "inBadOther: %lud\n", stats->inBadOther);	USED(p);	qunlock(c);}// c is lockedstatic voidconvack(Conv *c){	Block *b;	AckPkt *ack;	Stats *s;	int i;	b = allocb(sizeof(AckPkt));	ack = (AckPkt*)b->wp;	b->wp += sizeof(AckPkt);	s = &c->lstats;	hnputl(ack->cseq, c->in.controlseq);	hnputl(ack->outPackets, s->outPackets);	hnputl(ack->outDataPackets, s->outDataPackets);	hnputl(ack->outDataBytes, s->outDataBytes);	hnputl(ack->outCompDataBytes, s->outCompDataBytes);	for(i=0; i<NCompStats; i++)		hnputl(ack->outCompStats+i*4, s->outCompStats[i]);	hnputl(ack->inPackets, s->inPackets);	hnputl(ack->inDataPackets, s->inDataPackets);	hnputl(ack->inDataBytes, s->inDataBytes);	hnputl(ack->inCompDataBytes, s->inCompDataBytes);	hnputl(ack->inMissing, s->inMissing);	hnputl(ack->inDup, s->inDup);	hnputl(ack->inReorder, s->inReorder);	hnputl(ack->inBadComp, s->inBadComp);	hnputl(ack->inBadAuth, s->inBadAuth);	hnputl(ack->inBadSeq, s->inBadSeq);	hnputl(ack->inBadOther, s->inBadOther);	convoput(c, TControl, ControlAck, b);}// assume we hold lock for cstatic Block *conviput(Conv *c, Block *b, int control){	int type, subtype;	ulong seq, seqwrap;	long seqdiff;	int pad;	c->lstats.inPackets++;	if(BLEN(b) < 4) {		c->lstats.inBadOther++;		freeb(b);		return nil;	}		type = b->rp[0] >> 4;	subtype = b->rp[0] & 0xf;	b->rp += 1;	if(type == TConnect) {		conviconnect(c, subtype, b);		return nil;	}	switch(c->state) {	case CInit:	case CDial:		c->lstats.inBadOther++;		convoconnect(c, ConReset, c->dialid, c->acceptid);		convsetstate(c, CClosed);		break;	case CAccept:	case CRemoteClose:	case CLocalClose:		c->lstats.inBadOther++;		freeb(b);		return nil;	}	seq = (b->rp[0]<<16) + (b->rp[1]<<8) + b->rp[2];	b->rp += 3;	seqwrap = c->in.seqwrap;	seqdiff = seq - c->in.seq;	if(seqdiff < -(SeqMax*3/4)) {		seqwrap++;		seqdiff += SeqMax;	} else if(seqdiff > SeqMax*3/4) {		seqwrap--;		seqdiff -= SeqMax;	}	if(seqdiff <= 0) {		if(seqdiff <= -SeqWindow) {print("old sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);			c->lstats.inBadSeq++;			freeb(b);			return nil;		}		if(c->in.window & (1<<-seqdiff)) {print("dup sequence number: %ld (%ld %ld)\n", seq, c->in.seqwrap, seqdiff);			c->lstats.inDup++;			freeb(b);			return nil;		}		c->lstats.inReorder++;	}	// ok the sequence number looks okif(0) print("coniput seq=%ulx\n", seq);	if(c->in.auth != 0) {		if(!(*c->in.auth)(&c->in, b->rp-4, BLEN(b)+4)) {print("bad auth %ld\n", BLEN(b)+4);			c->lstats.inBadAuth++;			freeb(b);			return nil;		}		b->wp -= c->in.authlen;	}	if(c->in.cipher != 0) {		if(!(*c->in.cipher)(&c->in, b->rp, BLEN(b))) {print("bad cipher\n");			c->lstats.inBadOther++;			freeb(b);			return nil;		}		b->rp += c->in.cipherivlen;		if(c->in.cipherblklen > 1) {			pad = b->wp[-1];			if(pad > BLEN(b)) {print("pad too big\n");				c->lstats.inBadOther++;				freeb(b);				return nil;			}			b->wp -= pad;		}	}	// ok the packet is good	if(seqdiff > 0) {		while(seqdiff > 0 && c->in.window != 0) {			if((c->in.window & (1<<(SeqWindow-1))) == 0) {//print("missing packet: %ld\n", seq - seqdiff);				c->lstats.inMissing++;			}			c->in.window <<= 1;			seqdiff--;		}		if(seqdiff > 0) {//print("missing packets: %ld-%ld\n", seq - SeqWindow - seqdiff+1, seq-SeqWindow);			c->lstats.inMissing += seqdiff;		}		c->in.seq = seq;		c->in.seqwrap = seqwrap;		c->in.window |= 1;	}	c->lastrecv = TK2SEC(m->ticks);	switch(type) {	case TControl:		convicontrol(c, subtype, b);		return nil;	case TData:		c->lstats.inDataPackets++;		c->lstats.inDataBytes += BLEN(b);		if(control)			break;		return b;	case TCompData:		c->lstats.inDataPackets++;		c->lstats.inCompDataBytes += BLEN(b);		b = convicomp(c, subtype, seq, b);		if(b == nil) {			c->lstats.inBadComp++;			return nil;		}		c->lstats.inDataBytes += BLEN(b);		if(control)			break;		return b;	}print("droping packet %d n=%ld\n", type, BLEN(b));	c->lstats.inBadOther++;	freeb(b);	return nil;}// assume hold conv lockstatic voidconviconnect(Conv *c, int subtype, Block *b){	ulong dialid;	ulong acceptid;	if(BLEN(b) != 8) {		freeb(b);		return;	}	dialid = nhgetl(b->rp);	acceptid = nhgetl(b->rp + 4);	freeb(b);if(0)print("conviconnect: %s: %d %uld %uld\n", convstatename[c->state], subtype, dialid, acceptid);	if(subtype == ConReset) {		convsetstate(c, CClosed);		return;	}	switch(c->state) {	default:		panic("unknown state: %d", c->state);	case CInit:		break;	case CDial:		if(dialid != c->dialid)			goto Reset;		break;	case CAccept:	case COpen:	case CLocalClose:	case CRemoteClose:		if(dialid != c->dialid		|| subtype != ConOpenRequest && acceptid != c->acceptid)			goto Reset;		break;	case CClosed:		goto Reset;	}	switch(subtype) {	case ConOpenRequest:		switch(c->state) {		case CInit:			c->dialid = dialid;			convsetstate(c, CAccept);			return;		case CAccept:		case COpen:			// duplicate ConOpenRequest that we ignore			return;		}		break;	case ConOpenAck:		switch(c->state) {		case CDial:			c->acceptid = acceptid;			convsetstate(c, COpen);			return;		case COpen:			// duplicate that we have to ack			convoconnect(c, ConOpenAckAck, acceptid, dialid);			return;		}		break;	case ConOpenAckAck:		switch(c->state) {		case CAccept:			convsetstate(c, COpen);			return;		case COpen:		case CLocalClose:		case CRemoteClose:			// duplicate that we ignore			return;		}		break;	case ConClose:		switch(c->state) {		case COpen:			convoconnect(c, ConCloseAck, dialid, acceptid);			convsetstate(c, CRemoteClose);			return;		case CRemoteClose:			// duplicate ConClose			convoconnect(c, ConCloseAck, dialid, acceptid);			return;		}		break;	case ConCloseAck:		switch(c->state) {		case CLocalClose:			convsetstate(c, CClosed);			return;		}		break;	}Reset:	// invalid connection message - reset to senderif(0)print("invalid conviconnect - sending reset\n");	convoconnect(c, ConReset, dialid, acceptid);	convsetstate(c, CClosed);}static voidconvicontrol(Conv *c, int subtype, Block *b){	ulong cseq;	AckPkt *ack;	int i;	if(BLEN(b) < 4)		return;	cseq = nhgetl(b->rp);		switch(subtype){	case ControlMesg:		if(cseq == c->in.controlseq) {print("duplicate control packet: %ulx\n", cseq);			// duplicate control packet			freeb(b);			if(c->in.controlpkt == nil)				convack(c);			return;		}		if(cseq != c->in.controlseq+1)			return;		c->in.controlseq = cseq;		b->rp += 4;		if(BLEN(b) == 0) {			// just a ping			freeb(b);			convack(c);		} else {			c->in.controlpkt = b;if(0) print("recv %ld size=%ld\n", cseq, BLEN(b));			wakeup(&c->in.controlready);		}		return;	case ControlAck:		if(cseq != c->out.controlseq)			return;		if(BLEN(b) < sizeof(AckPkt))			return;		ack = (AckPkt*)(b->rp);		c->rstats.outPackets = nhgetl(ack->outPackets);		c->rstats.outDataPackets = nhgetl(ack->outDataPackets);		c->rstats.outDataBytes = nhgetl(ack->outDataBytes);		c->rstats.outCompDataBytes = nhgetl(ack->outCompDataBytes);		for(i=0; i<NCompStats; i++)			c->rstats.outCompStats[i] = nhgetl(ack->outCompStats + 4*i);		c->rstats.inPackets = nhgetl(ack->inPackets);		c->rstats.inDataPackets = nhgetl(ack->inDataPackets);		c->rstats.inDataBytes = nhgetl(ack->inDataBytes);		c->rstats.inCompDataBytes = nhgetl(ack->inCompDataBytes);		c->rstats.inMissing = nhgetl(ack->inMissing);		c->rstats.inDup = nhgetl(ack->inDup);		c->rstats.inReorder = nhgetl(ack->inReorder);		c->rstats.inBadComp = nhgetl(ack->inBadComp);		c->rstats.inBadAuth = nhgetl(ack->inBadAuth);		c->rstats.inBadSeq = nhgetl(ack->inBadSeq);		c->rstats.inBadOther = nhgetl(ack->inBadOther);		freeb(b);		freeb(c->out.controlpkt);		c->out.controlpkt = nil;		c->timeout = c->lastrecv + KeepAlive;		wakeup(&c->out.controlready);		return;	}}static Block*convicomp(Conv *c, int subtype, ulong seq, Block *b){	if(c->in.comp == nil) {		freeb(b);		return nil;	}	if(!(*c->in.comp)(c, subtype, seq, &b))		return nil;	return b;}// c is lockedstatic voidconvwriteblock(Conv *c, Block *b){	// simulated errors	if(c->drop && nrand(c->drop) == 0)		return;	if(waserror()) {		convsetstate(c, CClosed);		nexterror();	}	devtab[c->chan->type]->bwrite(c->chan, b, 0);	poperror();}// assume hold conv lockstatic voidconvoput(Conv *c, int type, int subtype, Block *b){	int pad;		c->lstats.outPackets++;	/* Make room for sdp trailer */	if(c->out.cipherblklen > 1)		pad = c->out.cipherblklen - (BLEN(b) + c->out.cipherivlen) % c->out.cipherblklen;	else		pad = 0;	b = padblock(b, -(pad+c->out.authlen));	if(pad) {		memset(b->wp, 0, pad-1);

⌨️ 快捷键说明

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