plan 9 kernel history: overview | file list | diff list

1999/0910/port/devsdp.c (diff list | history)

1999/0909/sys/src/9/port/devsdp.c:74,801999/0910/sys/src/9/port/devsdp.c:74,81 (short | long | prev | next)
1999/0909    
	CDial, 
	CAccept, 
1999/0902    
	COpen, 
	CClosing, 
1999/0910    
	CLocalClose, 
	CRemoteClose, 
1999/0906    
	CClosed, 
1999/0902    
}; 
 
1999/0909/sys/src/9/port/devsdp.c:86,931999/0910/sys/src/9/port/devsdp.c:87,94
1999/0901    
 
1999/0902    
	int state; 
1999/0906    
	int dataopen; 
1999/0910    
	int reader;		// reader proc has been started 
1999/0901    
 
1999/0906    
                 
	ulong	timeout; 
	int		retries; 
 
1999/0909/sys/src/9/port/devsdp.c:95,1031999/0910/sys/src/9/port/devsdp.c:96,106
1999/0906    
	ulong dialid; 
	ulong acceptid; 
 
1999/0910    
	QLock readlk;		// protects readproc 
1999/0907    
	Proc *readproc; 
	QLock readlk; 
1999/0910    
 
1999/0902    
	Chan *chan;	// packet channel 
1999/0910    
	char *channame; 
1999/0902    
 
1999/0907    
	char owner[NAMELEN];		/* protections */ 
1999/0901    
	int	perm; 
1999/0909/sys/src/9/port/devsdp.c:131,1381999/0910/sys/src/9/port/devsdp.c:134,141
1999/0906    
enum { 
1999/0909    
	ConOpenRequest, 
1999/0906    
	ConOpenAck, 
1999/0910    
	ConOpenAckAck, 
1999/0906    
	ConClose, 
	ConCloseAck, 
1999/0909    
	ConReset, 
1999/0906    
}; 
 
1999/0909/sys/src/9/port/devsdp.c:186,1921999/0910/sys/src/9/port/devsdp.c:189,196
1999/0909    
	[CDial] "Dial", 
	[CAccept] "Accept", 
1999/0908    
	[COpen] "Open", 
	[CClosing] "Closing", 
1999/0910    
	[CLocalClose] "LocalClose", 
	[CRemoteClose] "RemoteClose", 
1999/0908    
	[CClosed] "Closed", 
}; 
1999/0824    
 
1999/0909/sys/src/9/port/devsdp.c:203,2081999/0910/sys/src/9/port/devsdp.c:207,213
1999/0907    
static Block *readdata(Conv *c, int n); 
static void convoput(Conv *c, int type, Block *b); 
static void convoput2(Conv *c, int op, ulong dialid, ulong acceptid); 
1999/0910    
static void convreader(void *a); 
1999/0824    
 
1999/0907    
 
1999/0824    
static void 
1999/0909/sys/src/9/port/devsdp.c:328,3351999/0910/sys/src/9/port/devsdp.c:333,344
1999/0907    
		if(strcmp(up->user, c->owner) != 0 || (perm & c->perm) != perm) 
1999/0902    
				error(Eperm); 
		c->ref++; 
1999/0907    
		if(TYPE(ch->qid) == Qdata) 
1999/0910    
		if(TYPE(ch->qid) == Qdata) { 
			if(c->dataopen == 0) 
			if(c->readproc != nil) 
				postnote(c->readproc, 1, "interrupt", 0); 
1999/0907    
			c->dataopen++; 
1999/0910    
		} 
1999/0902    
		qunlock(c); 
		poperror(); 
		break; 
1999/0909/sys/src/9/port/devsdp.c:377,3861999/0910/sys/src/9/port/devsdp.c:386,395
1999/0907    
				break; 
1999/0909    
			case CAccept: 
1999/0907    
			case COpen: 
				convsetstate(c, CClosing); 
1999/0910    
				convsetstate(c, CLocalClose); 
1999/0907    
				break; 
			case CClosing: 
				break; 
1999/0910    
			case CLocalClose: 
				panic("local close already happened"); 
1999/0907    
			} 
		} 
		qunlock(c); 
1999/0909/sys/src/9/port/devsdp.c:474,4931999/0910/sys/src/9/port/devsdp.c:483,504
1999/0824    
			error("short write"); 
		arg0 = cb->f[0]; 
1999/0901    
print("cmd = %s\n", arg0); 
1999/0906    
		if(strcmp(arg0, "chan") == 0) { 
1999/0910    
		if(strcmp(arg0, "accept") == 0) { 
1999/0906    
			if(cb->nf != 2) 
				error("usage: chan file"); 
1999/0910    
				error("usage: accect file"); 
1999/0906    
			if(c->chan != nil) 
				error("chan already set"); 
1999/0910    
				error("already connected"); 
1999/0906    
			c->chan = namec(cb->f[1], Aopen, ORDWR, 0); 
		} else if(strcmp(arg0, "accept") == 0) { 
			if(cb->nf != 2) 
				error("usage: accect id"); 
			c->dialid = atoi(cb->f[1]); 
1999/0909    
			convsetstate(c, CAccept); 
1999/0910    
			c->channame = malloc(strlen(cb->f[1])+1); 
			strcpy(c->channame, cb->f[1]); 
1999/0906    
		} else if(strcmp(arg0, "dial") == 0) { 
			if(cb->nf != 1) 
				error("usage: dial"); 
1999/0910    
			if(cb->nf != 2) 
				error("usage: accect file"); 
			if(c->chan != nil) 
				error("already connected"); 
			c->chan = namec(cb->f[1], Aopen, ORDWR, 0); 
			c->channame = malloc(strlen(cb->f[1])+1); 
			strcpy(c->channame, cb->f[1]); 
1999/0909    
			convsetstate(c, CDial); 
1999/0906    
		} else if(strcmp(arg0, "drop") == 0) { 
			if(cb->nf != 2) 
1999/0909/sys/src/9/port/devsdp.c:584,5901999/0910/sys/src/9/port/devsdp.c:595,601
1999/0901    
			break; 
		} 
		if(canqlock(c)){ 
1999/0902    
			if(c->state == CClosed) 
1999/0910    
			if(c->state == CClosed && c->reader == 0) 
1999/0901    
				break; 
			qunlock(c); 
		} 
1999/0909/sys/src/9/port/devsdp.c:597,6031999/0910/sys/src/9/port/devsdp.c:608,617
1999/0901    
 
1999/0902    
	c->ref++; 
1999/0906    
	c->state = CInit; 
1999/0902    
                 
1999/0910    
	if(!waserror()) { 
		kproc("convreader", convreader, c); 
		c->reader = 1; 
	} 
1999/0907    
	strncpy(c->owner, up->user, sizeof(c->owner)); 
1999/0901    
	c->perm = 0660; 
	qunlock(c); 
1999/0909/sys/src/9/port/devsdp.c:647,6571999/0910/sys/src/9/port/devsdp.c:661,673
1999/0909    
	case CAccept: 
		if(convretry(c)) 
			convoput2(c, ConOpenAck, c->dialid, c->acceptid); 
1999/0910    
		else 
			convoput2(c, ConReset, c->dialid, c->acceptid); 
1999/0909    
		break; 
1999/0906    
	case COpen: 
1999/0909    
		// check for control packet and keepalive 
1999/0906    
		break; 
	case CClosing: 
1999/0910    
	case CLocalClose: 
1999/0906    
		if(convretry(c)) 
1999/0907    
			convoput2(c, ConClose, c->dialid, c->acceptid); 
1999/0906    
		break; 
1999/0909/sys/src/9/port/devsdp.c:730,7441999/0910/sys/src/9/port/devsdp.c:746,763
1999/0909    
		assert(c->state == CDial || c->state == CAccept); 
		if(c->state == CDial) { 
			convretryinit(c); 
1999/0907    
			convoput2(c, ConOpenAck, c->dialid, c->acceptid); 
1999/0910    
			convoput2(c, ConOpenAckAck, c->dialid, c->acceptid); 
1999/0906    
		} 
		// setup initial key and auth method 
		break; 
	case CClosing: 
1999/0909    
		assert(c->state == COpen); 
1999/0910    
	case CLocalClose: 
		assert(c->state == CAccept || c->state == COpen); 
1999/0909    
		convretryinit(c); 
1999/0907    
		convoput2(c, ConClose, c->dialid, c->acceptid); 
1999/0906    
		break; 
1999/0910    
	case CRemoteClose: 
		convoput2(c, ConReset, c->dialid, c->acceptid); 
		break; 
1999/0906    
	case CClosed: 
1999/0907    
		if(c->readproc) 
			postnote(c->readproc, 1, "interrupt", 0); 
1999/0909/sys/src/9/port/devsdp.c:748,7531999/0910/sys/src/9/port/devsdp.c:767,776
1999/0907    
			cclose(c->chan); 
			c->chan = nil; 
		} 
1999/0910    
		if(c->channame) { 
			free(c->channame); 
			c->channame = nil; 
		} 
1999/0907    
		strcpy(c->owner, "network"); 
		c->perm = 0660; 
		c->dialid = 0; 
1999/0909/sys/src/9/port/devsdp.c:778,8131999/0910/sys/src/9/port/devsdp.c:801,808
1999/0907    
} 
1999/0906    
 
1999/0907    
 
static Block * 
convreadblock(Conv *c, int n) 
{ 
	Block *b; 
 
	qlock(&c->readlk); 
	if(waserror()) { 
		c->readproc = nil; 
		qunlock(&c->readlk); 
		nexterror(); 
	} 
	qlock(c); 
	if(c->state == CClosed) { 
		qunlock(c); 
		poperror(); 
		qunlock(&c->readlk); 
		return 0; 
	} 
	c->readproc = up; 
	qunlock(c); 
 
	b = devtab[c->chan->type]->bread(c->chan, n, 0); 
	c->readproc = nil; 
	poperror(); 
	qunlock(&c->readlk); 
                 
	return b; 
} 
                 
                 
// assume we hold lock for c 
static Block * 
conviput(Conv *c, Block *b, int control) 
1999/0909/sys/src/9/port/devsdp.c:853,8601999/0910/sys/src/9/port/devsdp.c:848,853
1999/0907    
	 
		c->in.controlseq = cseq; 
		b->rp += 4; 
		if(control) 
			return b; 
		c->in.controlpkt = b; 
		wakeup(&c->in.controlready); 
		return nil; 
1999/0909/sys/src/9/port/devsdp.c:895,9571999/0910/sys/src/9/port/devsdp.c:888,983
1999/0907    
	dialid = nhgetl(con->dialid); 
	acceptid = nhgetl(con->acceptid); 
 
print("conviput2: %d %uld %uld\n", con->op, dialid, acceptid); 
1999/0910    
	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 || acceptid != c->acceptid) 
			goto Reset; 
		break; 
	case CClosed: 
		goto Reset; 
	} 
 
 
print("conviput2: %s: %d %uld %uld\n", convstatename[c->state], con->op, dialid, acceptid); 
1999/0907    
	switch(con->op) { 
1999/0909    
	case ConOpenRequest: 
		switch(c->state) { 
		default: 
			convoput2(c, ConReset, dialid, acceptid); 
			break; 
		case CInit: 
			c->dialid = dialid; 
			convsetstate(c, CAccept); 
			break; 
1999/0910    
			return; 
1999/0909    
		case CAccept: 
		case COpen: 
			if(dialid != c->dialid || acceptid != c->acceptid) 
				convoput2(c, ConReset, dialid, acceptid); 
			break; 
1999/0910    
			// duplicate ConOpenRequest that we ignore 
			return; 
1999/0909    
		} 
1999/0907    
		break; 
	case ConOpenAck: 
1999/0909    
		switch(c->state) { 
		case CDial: 
			if(dialid != c->dialid) { 
				convoput2(c, ConReset, dialid, acceptid); 
				break; 
			} 
			c->acceptid = acceptid; 
			convsetstate(c, COpen); 
1999/0907    
			break; 
1999/0910    
			return; 
		case COpen: 
			// duplicate that we have to ack 
			convoput2(c, ConOpenAckAck, acceptid, dialid); 
			return; 
		} 
		break; 
	case ConOpenAckAck: 
		switch(c->state) { 
1999/0909    
		case CAccept: 
			if(dialid != c->dialid || acceptid != c->acceptid) { 
				convoput2(c, ConReset, dialid, acceptid); 
				break; 
			} 
			convsetstate(c, COpen); 
1999/0910    
			return; 
		case COpen: 
			// duplicate that we ignore 
			return; 
1999/0909    
		} 
1999/0907    
		break; 
	case ConClose: 
1999/0909    
		convoput2(c, ConCloseAck, dialid, acceptid); 
		// fall though 
	case ConReset: 
1999/0910    
		convoput2(c, ConReset, dialid, acceptid); 
1999/0909    
		switch(c->state) { 
1999/0910    
		case CInit: 
1999/0909    
		case CDial: 
			if(dialid == c->dialid) 
				convsetstate(c, CClosed); 
1999/0907    
			break; 
1999/0909    
		case CAccept: 
1999/0910    
		case CLocalClose: 
			convsetstate(c, CClosed); 
			return; 
1999/0909    
		case COpen: 
		case CClosing: 
			if(dialid == c->dialid && acceptid == c->acceptid) 
				convsetstate(c, CClosed); 
1999/0907    
			break; 
1999/0910    
			convsetstate(c, CRemoteClose); 
			return; 
		case CRemoteClose: 
			return; 
1999/0909    
		} 
	case ConCloseAck: 
		if(c->state == CClosing && dialid == c->dialid && acceptid == c->acceptid) 
1999/0910    
		return; 
	case ConReset: 
		switch(c->state) { 
		case CInit: 
		case CDial: 
		case CAccept: 
		case COpen: 
		case CLocalClose: 
1999/0909    
			convsetstate(c, CClosed); 
1999/0907    
		break; 
1999/0910    
			return; 
		case CRemoteClose: 
			return; 
		} 
		return; 
1999/0907    
	} 
1999/0910    
Reset: 
	// invalid connection message - reset to sender 
	convoput2(c, ConReset, dialid, acceptid); 
1999/0907    
} 
 
// assume hold conv lock 
1999/0909/sys/src/9/port/devsdp.c:1003,10141999/0910/sys/src/9/port/devsdp.c:1029,1073
1999/0906    
	devtab[c->chan->type]->write(c->chan, &con, sizeof(con), 0); 
1999/0907    
} 
 
1999/0910    
static Block * 
convreadblock(Conv *c, int n) 
{ 
	Block *b; 
	Chan *ch = nil; 
 
	qlock(&c->readlk); 
	if(waserror()) { 
		c->readproc = nil; 
		if(ch) 
			cclose(ch); 
		qunlock(&c->readlk); 
		nexterror(); 
	} 
	qlock(c); 
	if(c->state == CClosed) { 
		qunlock(c); 
		error("closed"); 
	} 
	c->readproc = up; 
	ch = c->chan; 
	incref(ch); 
	qunlock(c); 
 
	b = devtab[ch->type]->bread(ch, n, 0); 
	c->readproc = nil; 
	cclose(ch); 
	poperror(); 
	qunlock(&c->readlk); 
 
	return b; 
} 
 
1999/0907    
static int 
readready(void *a) 
{ 
	Conv *c = a; 
 
	return (c->state == CClosed) || c->in.controlpkt != nil || c->dataopen == 0; 
1999/0910    
	return (c->state == CClosed) || c->in.controlpkt != nil; 
1999/0907    
} 
 
static Block * 
1999/0909/sys/src/9/port/devsdp.c:1016,10241999/0910/sys/src/9/port/devsdp.c:1075,1084
1999/0907    
{ 
	Block *b; 
 
1999/0910    
	USED(n); 
1999/0907    
	for(;;) { 
		qlock(c); 
		if(c->state == CClosed || c->state == CInit) { 
1999/0910    
		if(c->state == CInit || c->state == CClosed) { 
1999/0907    
			qunlock(c); 
			return nil; 
		} 
1999/0909/sys/src/9/port/devsdp.c:1031,10641999/0910/sys/src/9/port/devsdp.c:1091,1099
1999/0907    
		} 
		qunlock(c); 
 
		// hack - this is to avoid gating onto the 
		// read which will in general result in excessive 
		// context switches. 
		// The assumed behavior is that the client will read 
		// from the control channel until the session is authenticated 
		// at which point it will open the data channel and 
		// start reading on that.  After the data channel is opened, 
		// read on the channel are required for packets to 
		// be delivered to the control channel 
                 
		if(c->dataopen) { 
			sleep(&c->in.controlready, readready, c); 
		} else { 
			b = convreadblock(c, n); 
			if(b == nil) 
				return nil; 
			qlock(c); 
			if(waserror()) { 
				qunlock(c); 
				return nil; 
			} 
			b = conviput(c, b, 1); 
			poperror(); 
			qunlock(c); 
			if(b != nil) 
				return b; 
		} 
1999/0910    
		sleep(&c->in.controlready, readready, c); 
1999/0907    
	} 
1999/0910    
	return 0; 
1999/0907    
} 
 
static Block * 
1999/0909/sys/src/9/port/devsdp.c:1068,10751999/0910/sys/src/9/port/devsdp.c:1103,1108
1999/0907    
 
	for(;;) { 
		b = convreadblock(c, n); 
		if(b == nil) 
			return nil; 
		qlock(c); 
		if(waserror()) { 
			qunlock(c); 
1999/0909/sys/src/9/port/devsdp.c:1081,10841999/0910/sys/src/9/port/devsdp.c:1114,1147
1999/0907    
		if(b != nil) 
			return b; 
	} 
1999/0910    
} 
 
static void 
convreader(void *a) 
{ 
	Conv *c = a; 
	Block *b; 
 
	qlock(c); 
	assert(c->reader == 1); 
	while(c->dataopen == 0) { 
		qunlock(c); 
		b = nil; 
		if(!waserror()) { 
			b = convreadblock(c, 2000); 
			poperror(); 
		} 
		qlock(c); 
		if(b == nil) { 
			convsetstate(c, CClosed); 
			break; 
		} 
		if(!waserror()) { 
			conviput(c, b, 1); 
			poperror(); 
		} 
	} 
	c->reader = 0; 
	qunlock(c); 
	pexit("hangup", 1); 
1999/0906    
} 


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)