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

📄 il.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
				ic->fasttimeout = 0;				ic->rexmit = 0;				goto established;			}			break;		case Ilclose:			if(ack == ic->start)				ilhangup(s, "remote close");			break;		}		freeblist(bp);		break;	case Ilestablished:	established:		switch(h->iltype) {		case Ilsync:			if(id != ic->rstart)				ilhangup(s, "remote close");			else				ilsendctl(s, nil, Ilack, ic->next, ic->rstart, 0);			freeblist(bp);				break;		case Ildata:			/*			 * avoid consuming all the mount rpc buffers in the			 * system.  if the input queue is too long, drop this			 * packet.			 */			if (s->rq && qlen(s->rq) >= Maxrq) {				priv->stats[DroppedMsgs]++;				freeblist(bp);				break;			}			ilackto(ic, ack, bp);			iloutoforder(s, h, bp);			ilpullup(s);			break;		case Ildataquery:			ilackto(ic, ack, bp);			iloutoforder(s, h, bp);			ilpullup(s);			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);			break;		case Ilack:			ilackto(ic, ack, bp);			freeblist(bp);			break;		case Ilquery:			ilackto(ic, ack, bp);			ilsendctl(s, nil, Ilstate, ic->next, ic->recvd, h->ilspec);			freeblist(bp);			break;		case Ilstate:			if(ack >= ic->rttack)				ic->rttack = 0;			ilackto(ic, ack, bp);			if(h->ilspec > Nqt)				h->ilspec = 0;			if(ic->qt[h->ilspec] > ack){				ilrexmit(ic);				ilsettimeout(ic);			}			freeblist(bp);			break;		case Ilclose:			freeblist(bp);			if(ack < ic->start || ack > ic->next) 				break;			ic->recvd = id;			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);			ic->state = Ilclosing;			ilsettimeout(ic);			ilfreeq(ic);			break;		}		break;	case Illistening:		freeblist(bp);		break;	case Ilclosing:		switch(h->iltype) {		case Ilclose:			ic->recvd = id;			ilsendctl(s, nil, Ilclose, ic->next, ic->recvd, 0);			if(ack == ic->next)				ilhangup(s, nil);			break;		default:			break;		}		freeblist(bp);		break;	}}voidilrexmit(Ilcb *ic){	Ilhdr *h;	Block *nb;	Conv *c;	ulong id;	Ilpriv *priv;	nb = nil;	qlock(&ic->ackq);	if(ic->unacked)		nb = copyblock(ic->unacked, blocklen(ic->unacked));	qunlock(&ic->ackq);	if(nb == nil)		return;	h = (Ilhdr*)nb->rp;	h->vihl = IP_VER4;	h->iltype = Ildataquery;	hnputl(h->ilack, ic->recvd);	h->ilspec = ilnextqt(ic);	h->ilsum[0] = 0;	h->ilsum[1] = 0;	hnputs(h->ilsum, ptclcsum(nb, IL_IPSIZE, nhgets(h->illen)));	c = ic->conv;	id = nhgetl(h->ilid);	netlog(c->p->f, Logil, "il: rexmit %d %ud: %d %d: %i %d/%d\n", id, ic->recvd,		ic->rexmit, ic->timeout,		c->raddr, c->lport, c->rport);	ilbackoff(ic);	ipoput4(c->p->f, nb, 0, c->ttl, c->tos, c);	/* statistics */	ic->rxtot++;	priv = c->p->priv;	priv->rexmit++;}/* DEBUG */voidilprocess(Conv *s, Ilhdr *h, Block *bp){	Ilcb *ic;	ic = (Ilcb*)s->ptcl;	USED(ic);	netlog(s->p->f, Logilmsg, "%11s rcv %d/%d snt %d/%d pkt(%s id %d ack %d %d->%d) ",		ilstates[ic->state],  ic->rstart, ic->recvd, ic->start, 		ic->next, iltype[h->iltype], nhgetl(h->ilid), 		nhgetl(h->ilack), nhgets(h->ilsrc), nhgets(h->ildst));	_ilprocess(s, h, bp);	netlog(s->p->f, Logilmsg, "%11s rcv %d snt %d\n", ilstates[ic->state], ic->recvd, ic->next);}voidilhangup(Conv *s, char *msg){	Ilcb *ic;	int callout;	netlog(s->p->f, Logil, "il: hangup! %I %d/%d: %s\n", s->raddr,		s->lport, s->rport, msg?msg:"no reason");	ic = (Ilcb*)s->ptcl;	callout = ic->state == Ilsyncer;	illocalclose(s);	qhangup(s->rq, msg);	qhangup(s->wq, msg);	if(callout)		Fsconnected(s, msg);}voidilpullup(Conv *s){	Ilcb *ic;	Ilhdr *oh;	Block *bp;	ulong oid, dlen;	Ilpriv *ipriv;	ic = (Ilcb*)s->ptcl;	if(ic->state != Ilestablished)		return;	qlock(&ic->outo);	while(ic->outoforder) {		bp = ic->outoforder;		oh = (Ilhdr*)bp->rp;		oid = nhgetl(oh->ilid);		if(oid <= ic->recvd) {			ic->outoforder = bp->list;			freeblist(bp);			continue;		}		if(oid != ic->recvd+1){			ipriv = s->p->priv;			ipriv->stats[OutOfOrder]++;			break;		}		ic->recvd = oid;		ic->outoforder = bp->list;		bp->list = nil;		dlen = nhgets(oh->illen)-IL_HDRSIZE;		bp = trimblock(bp, IL_IPSIZE+IL_HDRSIZE, dlen);		/*		 * Upper levels don't know about multiple-block		 * messages so copy all into one (yick).		 */		bp = concatblock(bp);		if(bp == 0)			panic("ilpullup");		bp = packblock(bp);		if(bp == 0)			panic("ilpullup2");		qpass(s->rq, bp);	}	qunlock(&ic->outo);}voidiloutoforder(Conv *s, Ilhdr *h, Block *bp){	Ilcb *ic;	uchar *lid;	Block *f, **l;	ulong id, newid;	Ilpriv *ipriv;	ipriv = s->p->priv;	ic = (Ilcb*)s->ptcl;	bp->list = nil;	id = nhgetl(h->ilid);	/* Window checks */	if(id <= ic->recvd || id > ic->recvd+ic->window) {		netlog(s->p->f, Logil, "il: message outside window %ud <%ud-%ud>: %i %d/%d\n",			id, ic->recvd, ic->recvd+ic->window, s->raddr, s->lport, s->rport);		freeblist(bp);		return;	}	/* Packet is acceptable so sort onto receive queue for pullup */	qlock(&ic->outo);	if(ic->outoforder == nil)		ic->outoforder = bp;	else {		l = &ic->outoforder;		for(f = *l; f; f = f->list) {			lid = ((Ilhdr*)(f->rp))->ilid;			newid = nhgetl(lid);			if(id <= newid) {				if(id == newid) {					ipriv->stats[DupMsg]++;					ipriv->stats[DupBytes] += blocklen(bp);					qunlock(&ic->outo);					freeblist(bp);					return;				}				bp->list = f;				*l = bp;				qunlock(&ic->outo);				return;			}			l = &f->list;		}		*l = bp;	}	qunlock(&ic->outo);}voidilsendctl(Conv *ipc, Ilhdr *inih, int type, ulong id, ulong ack, int ilspec){	Ilhdr *ih;	Ilcb *ic;	Block *bp;	int ttl, tos;	bp = allocb(IL_IPSIZE+IL_HDRSIZE);	bp->wp += IL_IPSIZE+IL_HDRSIZE;	ih = (Ilhdr *)(bp->rp);	ih->vihl = IP_VER4;	/* Ip fields */	ih->proto = IP_ILPROTO;	hnputs(ih->illen, IL_HDRSIZE);	ih->frag[0] = 0;	ih->frag[1] = 0;	if(inih) {		hnputl(ih->dst, nhgetl(inih->src));		hnputl(ih->src, nhgetl(inih->dst));		hnputs(ih->ilsrc, nhgets(inih->ildst));		hnputs(ih->ildst, nhgets(inih->ilsrc));		hnputl(ih->ilid, nhgetl(inih->ilack));		hnputl(ih->ilack, nhgetl(inih->ilid));		ttl = MAXTTL;		tos = DFLTTOS;	}	else {		v6tov4(ih->dst, ipc->raddr);		v6tov4(ih->src, ipc->laddr);		hnputs(ih->ilsrc, ipc->lport);		hnputs(ih->ildst, ipc->rport);		hnputl(ih->ilid, id);		hnputl(ih->ilack, ack);		ic = (Ilcb*)ipc->ptcl;		ic->acksent = ack;		ic->acktime = NOW;		ttl = ipc->ttl;		tos = ipc->tos;	}	ih->iltype = type;	ih->ilspec = ilspec;	ih->ilsum[0] = 0;	ih->ilsum[1] = 0;	if(ilcksum)		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));if(ipc==nil)	panic("ipc is nil caller is %.8lux", getcallerpc(&ipc));if(ipc->p==nil)	panic("ipc->p is nil");	netlog(ipc->p->f, Logilmsg, "ctl(%s id %d ack %d %d->%d)\n",		iltype[ih->iltype], nhgetl(ih->ilid), nhgetl(ih->ilack), 		nhgets(ih->ilsrc), nhgets(ih->ildst));	ipoput4(ipc->p->f, bp, 0, ttl, tos, ipc);}voidilreject(Fs *f, Ilhdr *inih){	Ilhdr *ih;	Block *bp;	bp = allocb(IL_IPSIZE+IL_HDRSIZE);	bp->wp += IL_IPSIZE+IL_HDRSIZE;	ih = (Ilhdr *)(bp->rp);	ih->vihl = IP_VER4;	/* Ip fields */	ih->proto = IP_ILPROTO;	hnputs(ih->illen, IL_HDRSIZE);	ih->frag[0] = 0;	ih->frag[1] = 0;	hnputl(ih->dst, nhgetl(inih->src));	hnputl(ih->src, nhgetl(inih->dst));	hnputs(ih->ilsrc, nhgets(inih->ildst));	hnputs(ih->ildst, nhgets(inih->ilsrc));	hnputl(ih->ilid, nhgetl(inih->ilack));	hnputl(ih->ilack, nhgetl(inih->ilid));	ih->iltype = Ilclose;	ih->ilspec = 0;	ih->ilsum[0] = 0;	ih->ilsum[1] = 0;	if(ilcksum)		hnputs(ih->ilsum, ptclcsum(bp, IL_IPSIZE, IL_HDRSIZE));	ipoput4(f, bp, 0, MAXTTL, DFLTTOS, nil);}voidilsettimeout(Ilcb *ic){	ulong pt;	pt = (ic->delay>>LogAGain)		+ ic->unackedbytes/(ic->rate>>LogAGain)		+ (ic->mdev>>(LogDGain-1))		+ AckDelay;	if(pt > MaxTimeout)		pt = MaxTimeout;	ic->timeout = NOW + pt;}voidilbackoff(Ilcb *ic){	ulong pt;	int i;	pt = (ic->delay>>LogAGain)		+ ic->unackedbytes/(ic->rate>>LogAGain)		+ (ic->mdev>>(LogDGain-1))		+ AckDelay;	for(i = 0; i < ic->rexmit; i++)		pt = pt + (pt>>1);	if(pt > MaxTimeout)		pt = MaxTimeout;	ic->timeout = NOW + pt;	if(ic->fasttimeout)		ic->timeout = NOW+Iltickms;	ic->rexmit++;}// complain if two numbers not within an hour of each other#define Tfuture (1000*60*60)intlater(ulong t1, ulong t2, char *x){	int dt;	dt = t1 - t2;	if(dt > 0) {		if(x != nil && dt > Tfuture)			print("%s: way future %d\n", x, dt);		return 1;	}	if(dt < -Tfuture) {		if(x != nil)			print("%s: way past %d\n", x, -dt);		return 1;	}	return 0;}voidilackproc(void *x){	Ilcb *ic;	Conv **s, *p;	Proto *il;	il = x;loop:	tsleep(&up->sleep, return0, 0, Iltickms);	for(s = il->conv; s && *s; s++) {		p = *s;		ic = (Ilcb*)p->ptcl;		switch(ic->state) {		case Ilclosed:		case Illistening:			break;		case Ilclosing:			if(later(NOW, ic->timeout, "timeout0")) {				if(ic->rexmit > MaxRexmit){					ilhangup(p, nil);					break;				}				ilsendctl(p, nil, Ilclose, ic->next, ic->recvd, 0);				ilbackoff(ic);			}			break;		case Ilsyncee:		case Ilsyncer:			if(later(NOW, ic->timeout, "timeout1")) {				if(ic->rexmit > MaxRexmit){					ilhangup(p, etime);					break;				}				ilsendctl(p, nil, Ilsync, ic->start, ic->recvd, 0);				ilbackoff(ic);			}			break;		case Ilestablished:			if(ic->recvd != ic->acksent)			if(later(NOW, ic->acktime, "acktime"))				ilsendctl(p, nil, Ilack, ic->next, ic->recvd, 0);			if(later(NOW, ic->querytime, "querytime")){				if(later(NOW, ic->lastrecv+DeathTime, "deathtime")){					netlog(il->f, Logil, "il: hangup: deathtime\n");					ilhangup(p, etime);					break;				}				ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));				ic->querytime = NOW + QueryTime;			}			if(ic->unacked != nil)			if(later(NOW, ic->timeout, "timeout2")) {				if(ic->rexmit > MaxRexmit){					netlog(il->f, Logil, "il: hangup: too many rexmits\n");					ilhangup(p, etime);					break;				}				ilsendctl(p, nil, Ilquery, ic->next, ic->recvd, ilnextqt(ic));				ic->rxquery++;				ilbackoff(ic);			}			break;		}	}	goto loop;}voidilcbinit(Ilcb *ic){	ic->start = nrand(0x1000000);	ic->next = ic->start+1;	ic->recvd = 0;	ic->window = Defaultwin;	ic->unackedbytes = 0;	ic->unacked = nil;	ic->outoforder = nil;	ic->rexmit = 0;	ic->rxtot = 0;	ic->rxquery = 0;	ic->qtx = 1;	ic->fasttimeout = 0;	/* timers */	ic->delay = DefRtt<<LogAGain;	ic->mdev = DefRtt<<LogDGain;	ic->rate = DefByteRate<<LogAGain;	ic->querytime = NOW + QueryTime;	ic->lastrecv = NOW;	/* or we'll timeout right away */	ilsettimeout(ic);}char*ilstart(Conv *c, int type, int fasttimeout){	Ilcb *ic;	Ilpriv *ipriv;	char kpname[KNAMELEN];	ipriv = c->p->priv;	if(ipriv->ackprocstarted == 0){		qlock(&ipriv->apl);		if(ipriv->ackprocstarted == 0){			sprint(kpname, "#I%dilack", c->p->f->dev);			kproc(kpname, ilackproc, c->p);			ipriv->ackprocstarted = 1;		}		qunlock(&ipriv->apl);	}	ic = (Ilcb*)c->ptcl;	ic->conv = c;	if(ic->state != Ilclosed)		return nil;	ilcbinit(ic);	if(fasttimeout){		/* timeout if we can't connect quickly */		ic->fasttimeout = 1;		ic->timeout = NOW+Iltickms;		ic->rexmit = MaxRexmit - 4;	};	switch(type) {	default:		netlog(c->p->f, Logil, "il: start: type %d\n", type);		break;	case IL_LISTEN:		ic->state = Illistening;		iphtadd(&ipriv->ht, c);		break;	case IL_CONNECT:		ic->state = Ilsyncer;		iphtadd(&ipriv->ht, c);		ilsendctl(c, nil, Ilsync, ic->start, ic->recvd, 0);		break;	}	return nil;}voidilfreeq(Ilcb *ic){	Block *bp, *next;	qlock(&ic->ackq);	for(bp = ic->unacked; bp; bp = next) {		next = bp->list;		freeblist(bp);	}	ic->unacked = nil;	qunlock(&ic->ackq);	qlock(&ic->outo);	for(bp = ic->outoforder; bp; bp = next) {		next = bp->list;		freeblist(bp);	}	ic->outoforder = nil;	qunlock(&ic->outo);}voidiladvise(Proto *il, Block *bp, char *msg){	Ilhdr *h;	Ilcb *ic;			uchar source[IPaddrlen], dest[IPaddrlen];	ushort psource;	Conv *s, **p;	h = (Ilhdr*)(bp->rp);	v4tov6(dest, h->dst);	v4tov6(source, h->src);	psource = nhgets(h->ilsrc);	/* Look for a connection, unfortunately the destination port is missing */	qlock(il);	for(p = il->conv; *p; p++) {		s = *p;		if(s->lport == psource)		if(ipcmp(s->laddr, source) == 0)		if(ipcmp(s->raddr, dest) == 0){			qunlock(il);			ic = (Ilcb*)s->ptcl;			switch(ic->state){			case Ilsyncer:				ilhangup(s, msg);				break;			}			freeblist(bp);			return;		}	}	qunlock(il);	freeblist(bp);}intilnextqt(Ilcb *ic){	int x;	qlock(&ic->ackq);	x = ic->qtx;	if(++x > Nqt)		x = 1;	ic->qtx = x;	ic->qt[x] = ic->next-1;	/* highest xmitted packet */	ic->qt[0] = ic->qt[x];	/* compatibility with old implementations */	qunlock(&ic->ackq);	return x;}/* calculate scale constants that converts fast ticks to ms (more or less) */static voidinittimescale(void){	uvlong hz;	fastticks(&hz);	if(hz > 1000){		scalediv = hz/1000;		scalemul = 1;	} else {		scalediv = 1;		scalemul = 1000/hz;	}}voidilinit(Fs *f){	Proto *il;	inittimescale();	il = smalloc(sizeof(Proto));	il->priv = smalloc(sizeof(Ilpriv));	il->name = "il";	il->connect = ilconnect;	il->announce = ilannounce;	il->state = ilstate;	il->create = ilcreate;	il->close = ilclose;	il->rcv = iliput;	il->ctl = nil;	il->advise = iladvise;	il->stats = ilxstats;	il->inuse = ilinuse;	il->gc = nil;	il->ipproto = IP_ILPROTO;	il->nc = scalednconv();	il->ptclsize = sizeof(Ilcb);	Fsproto(f, il);}

⌨️ 快捷键说明

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