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

📄 bdt.c

📁 早期freebsd实现
💻 C
字号:
/* * This file contains routines useful to the applications developer who * must read or write BDT data. *//* $Log:	bdt.c,v $ * Revision 3.0  87/01/14  14:39:02  ed * release containing Xerox (Webster Research Center) modifications *  * Revision 2.1  86/09/07  09:36:29  jqj * return correct number of bytes written by BDTwrite, or -1 on error. *  * Revision 2.0  85/11/21  07:22:02  jqj * 4.3BSD standard release *  * Revision 1.4  85/03/11  16:36:38  jqj * *** empty log message *** *  * Revision 1.4  85/03/11  16:36:38  jqj * Public alpha-test version, released 11 March 1985 *  * Revision 1.3  85/03/11  16:34:19  jqj * Public alpha-test version, released 11 March 1985 *  * Revision 1.2  85/01/27  07:37:06  jqj * finished but undebugged version *  */#ifndef lintstatic char rcsid[] = "$Header: bdt.c,v 3.0 87/01/14 14:39:02 ed Exp $";#endif#include <stdio.h>#include <sys/time.h>#include <sys/types.h>		/* for socket.h and xn.h */#include <sys/socket.h>#include <sys/uio.h>		/* for scatter/gather io */#include <netns/ns.h>		/* for XNS addresses and courierconnection.h */#include <netns/idp.h>#include <netns/sp.h>		/* for spphdr */#include "courier.h"#include "realcourierconnection.h"#define MAKEVEC(idx, addr, len) our_iovec[idx].iov_base = (caddr_t)addr;\				our_iovec[idx].iov_len = len;intBDTwrite(f,buffer,nbytes)/* Call with CourierConnection*, not *(CourierConnection*) *//* Semantics are much like write(), except that it returns -1 * if a BDT abort message arrives from receiver. * Returns # of bytes actually written, or -1 if an error occurs (some * data may have been transferred!). */	register CourierConnection *f;	char *buffer;	int nbytes;{	register int n, w;	struct iovec our_iovec[2];	MAKEVEC(0, &(f->sphdrOpts), sizeof(f->sphdrOpts));	MAKEVEC(1, buffer, SPPMAXDATA);	if (f->bdtstate == wantdata) {			/* stream=BDT, EOM=FALSE, Attn=FALSE */		f->sphdrOpts.sp_dt = SPPSST_BDT;		f->sphdrOpts.sp_cc &= ~SP_EM;		f->bdtstate = established;	}	if (BDTabortSeen(f)) {		BDTabort(f);	/* send end (abort) */		f->abortseen = FALSE;	/* clear abort */		f->bdtstate = bdteomseen;		return(-1);	/* truncate the stream */	}	/* ### if nbytes > SPPMAXDATA, do something intelligent? */	for(n = nbytes; n > SPPMAXDATA; n -= SPPMAXDATA) {		w = writev(f->fd, our_iovec, 2) - sizeof(f->sphdrOpts);		if (w < 0) return(-1);		if(w < SPPMAXDATA)			return( w + nbytes - n);		our_iovec[1].iov_base += SPPMAXDATA;	}	our_iovec[1].iov_len = n;	w = writev(f->fd, our_iovec, 2) - sizeof(f->sphdrOpts);	if (w < 0) return(-1);	return( w + nbytes - n);}intBDTclosewrite(f)/* call with CourierConnection*, not *(CourierConnection*) *//* End a BDT connection.  Returns 0 on success, -1 on failure. */	register CourierConnection *f;{	f->bdtstate = bdteomseen;	if (BDTabortSeen(f)) {		BDTabort(f);		f->abortseen = FALSE;		return(-1);	}	/* stream=BDT, EOM=TRUE, Attn=FALSE */	f->sphdrOpts.sp_dt = SPPSST_BDT;	f->sphdrOpts.sp_cc |= SP_EM;	/* finally, send normal end in a packet of its own */	write(f->fd,(char*)&f->sphdrOpts,sizeof(struct sphdr));	return(0);}intBDTread(f, buffer, nbytes)/* Call with CourierConnection*, not *(CourierConnection*) *//* Semantics are much like read(), except that it returns -1 on * more conditions.  Returns number of characters actually read, * or 0 on end of message. */	register CourierConnection *f;	char *buffer;	int nbytes;{	register int count;	struct {		struct sphdr hdr;		char data[SPPMAXDATA];	} packbuf;	struct iovec our_iovec[2];	switch (f->state) {	case closed:	case calldone:		fprintf(stderr,"BDTread() called while connection state = %s\n",			(f->state == closed) ? "closed" : "calldone");		exit(1);		/* NOTREACHED */	case wantversion:		count = recv(f->fd, (char*) &packbuf, sizeof(packbuf), MSG_PEEK)				- sizeof(struct sphdr);		while (count == 0		       && packbuf.hdr.sp_dt == SPPSST_RPC) {			read(f->fd, (char*) &packbuf, sizeof(packbuf));			count = recv(f->fd, (char*) &packbuf, sizeof(packbuf),					MSG_PEEK)					- sizeof(struct sphdr);		}		if (count == 0)			/* streamtype != SPPSST_RPC, so we can't */			/* have a version number */			break;			/* fall out of switch, still wantversion */		/* ### N.B. we don't handle count==2 */		else if (count != (2*sizeof(Cardinal)))			/* must be a REJECT or ABORT message */			/* let someone else handle it! */			return(-1);		else {			/* must be a Courier version number */			/* read it and throw it away */			read(f->fd, (char*) &packbuf, sizeof(packbuf));			f->state = inprogress;			/* fall into case inprogress */		}	case inprogress:		switch (f->bdtstate) {		case wantdata:			count = recv(f->fd, (char*) &packbuf, sizeof(packbuf),					MSG_PEEK)					- sizeof(struct sphdr);			if (packbuf.hdr.sp_dt == SPPSST_RPC)				return(-1);			f->bdtstate = established;			/* fall through to case established */		case established:			break;			/* fall out of inner (and outer!) switch */		case bdteomseen:			return(0);		}		break;	}	MAKEVEC(0,&packbuf.hdr,sizeof(struct sphdr));	MAKEVEC(1,buffer,nbytes);	count = readv(f->fd,our_iovec,2) - sizeof(struct sphdr);	/* at this point, we've read a packet that isn't SPPSST_RPC */	while (TRUE) {		if (packbuf.hdr.sp_dt == SPPSST_END) {			(void) sppclosereply(f->fd);			f->state = closed;			fprintf(stderr,"SPP END received during BDT\n");			exit(1);		}		if (packbuf.hdr.sp_dt != SPPSST_BDT) {			fprintf(stderr,				"wrong stream type, %d, seen during BDT\n",				packbuf.hdr.sp_dt);			exit(1);			/* NOTREACHED */		}		if (f->abortseen || (packbuf.hdr.sp_cc & SP_OB)) {			f->abortseen = TRUE;			return(-1);		}		if (packbuf.hdr.sp_cc & SP_EM) {			f->bdtstate = bdteomseen;			/* next read will return 0 */			return(count);		}		if (count > 0)			return(count);		count = readv(f->fd,our_iovec,2) - sizeof(struct sphdr);	}}BDTabort(f)	register CourierConnection *f;{	static struct handy {		struct sphdr hdr;		char value;	} data;	/* stream=BDT, EOM=FALSE, Attn=TRUE */	data.hdr.sp_dt = SPPSST_BDT;	data.hdr.sp_cc = SP_EM;	data.value = 1;	/* BDT abort data value */	send(f->fd, &data, sizeof(data), MSG_OOB);	f->bdtstate = bdteomseen;	f->abortseen = TRUE;}BDTabortSeen(f)	register CourierConnection *f;{	struct {		struct sphdr hdr;		Unspecified data[MAXWORDS];	} packbuf;	int fdmask;	register int count;	static struct timeval timeout = {0,0};	fdmask = 1<<(f->fd);	/* ### code here for OOB signalling! */	while (select(f->fd+1,&fdmask,(int*)NULL,(int*)NULL,&timeout) > 0	    && (count = recv(f->fd,(char*)&packbuf, sizeof(packbuf),	    			MSG_PEEK) - sizeof(struct sphdr)) > 0) {		if (packbuf.hdr.sp_dt == SPPSST_BDT		    && (packbuf.hdr.sp_dt & SP_OB)		    && count == 1) {			read(f->fd, (char*)&packbuf, sizeof(packbuf));			f->abortseen = TRUE;			return(TRUE);		}		else if (count == 0)			read(f->fd, (char*)&packbuf, sizeof(packbuf));		else return(FALSE);	}	return(FALSE);}

⌨️ 快捷键说明

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