|
|
1.1 ! root 1: /* ! 2: * This file contains routines useful to the applications developer who ! 3: * must read or write BDT data. ! 4: */ ! 5: ! 6: /* ! 7: $Log: bdt.c,v $ ! 8: * Revision 3.0 87/01/14 14:39:02 ed ! 9: * release containing Xerox (Webster Research Center) modifications ! 10: * ! 11: * Revision 2.1 86/09/07 09:36:29 jqj ! 12: * return correct number of bytes written by BDTwrite, or -1 on error. ! 13: * ! 14: * Revision 2.0 85/11/21 07:22:02 jqj ! 15: * 4.3BSD standard release ! 16: * ! 17: * Revision 1.4 85/03/11 16:36:38 jqj ! 18: * *** empty log message *** ! 19: * ! 20: * Revision 1.4 85/03/11 16:36:38 jqj ! 21: * Public alpha-test version, released 11 March 1985 ! 22: * ! 23: * Revision 1.3 85/03/11 16:34:19 jqj ! 24: * Public alpha-test version, released 11 March 1985 ! 25: * ! 26: * Revision 1.2 85/01/27 07:37:06 jqj ! 27: * finished but undebugged version ! 28: * ! 29: */ ! 30: ! 31: #ifndef lint ! 32: static char rcsid[] = "$Header: bdt.c,v 3.0 87/01/14 14:39:02 ed Exp $"; ! 33: #endif ! 34: ! 35: #include <stdio.h> ! 36: #include <sys/time.h> ! 37: #include <sys/types.h> /* for socket.h and xn.h */ ! 38: #include <sys/socket.h> ! 39: #include <sys/uio.h> /* for scatter/gather io */ ! 40: #include <netns/ns.h> /* for XNS addresses and courierconnection.h */ ! 41: #include <netns/idp.h> ! 42: #include <netns/sp.h> /* for spphdr */ ! 43: #include "courier.h" ! 44: #include "realcourierconnection.h" ! 45: ! 46: #define MAKEVEC(idx, addr, len) our_iovec[idx].iov_base = (caddr_t)addr;\ ! 47: our_iovec[idx].iov_len = len; ! 48: ! 49: ! 50: ! 51: int ! 52: BDTwrite(f,buffer,nbytes) ! 53: /* Call with CourierConnection*, not *(CourierConnection*) */ ! 54: /* Semantics are much like write(), except that it returns -1 ! 55: * if a BDT abort message arrives from receiver. ! 56: * Returns # of bytes actually written, or -1 if an error occurs (some ! 57: * data may have been transferred!). ! 58: */ ! 59: register CourierConnection *f; ! 60: char *buffer; ! 61: int nbytes; ! 62: { ! 63: register int n, w; ! 64: struct iovec our_iovec[2]; ! 65: ! 66: MAKEVEC(0, &(f->sphdrOpts), sizeof(f->sphdrOpts)); ! 67: MAKEVEC(1, buffer, SPPMAXDATA); ! 68: ! 69: if (f->bdtstate == wantdata) { ! 70: /* stream=BDT, EOM=FALSE, Attn=FALSE */ ! 71: f->sphdrOpts.sp_dt = SPPSST_BDT; ! 72: f->sphdrOpts.sp_cc &= ~SP_EM; ! 73: f->bdtstate = established; ! 74: } ! 75: if (BDTabortSeen(f)) { ! 76: BDTabort(f); /* send end (abort) */ ! 77: f->abortseen = FALSE; /* clear abort */ ! 78: f->bdtstate = bdteomseen; ! 79: return(-1); /* truncate the stream */ ! 80: } ! 81: /* ### if nbytes > SPPMAXDATA, do something intelligent? */ ! 82: for(n = nbytes; n > SPPMAXDATA; n -= SPPMAXDATA) { ! 83: w = writev(f->fd, our_iovec, 2) - sizeof(f->sphdrOpts); ! 84: if (w < 0) return(-1); ! 85: if(w < SPPMAXDATA) ! 86: return( w + nbytes - n); ! 87: our_iovec[1].iov_base += SPPMAXDATA; ! 88: } ! 89: our_iovec[1].iov_len = n; ! 90: w = writev(f->fd, our_iovec, 2) - sizeof(f->sphdrOpts); ! 91: if (w < 0) return(-1); ! 92: return( w + nbytes - n); ! 93: } ! 94: ! 95: ! 96: int ! 97: BDTclosewrite(f) ! 98: /* call with CourierConnection*, not *(CourierConnection*) */ ! 99: /* End a BDT connection. Returns 0 on success, -1 on failure. ! 100: */ ! 101: register CourierConnection *f; ! 102: { ! 103: ! 104: f->bdtstate = bdteomseen; ! 105: if (BDTabortSeen(f)) { ! 106: BDTabort(f); ! 107: f->abortseen = FALSE; ! 108: return(-1); ! 109: } ! 110: /* stream=BDT, EOM=TRUE, Attn=FALSE */ ! 111: f->sphdrOpts.sp_dt = SPPSST_BDT; ! 112: f->sphdrOpts.sp_cc |= SP_EM; ! 113: /* finally, send normal end in a packet of its own */ ! 114: write(f->fd,(char*)&f->sphdrOpts,sizeof(struct sphdr)); ! 115: return(0); ! 116: } ! 117: ! 118: ! 119: int ! 120: BDTread(f, buffer, nbytes) ! 121: /* Call with CourierConnection*, not *(CourierConnection*) */ ! 122: /* Semantics are much like read(), except that it returns -1 on ! 123: * more conditions. Returns number of characters actually read, ! 124: * or 0 on end of message. ! 125: */ ! 126: register CourierConnection *f; ! 127: char *buffer; ! 128: int nbytes; ! 129: { ! 130: register int count; ! 131: struct { ! 132: struct sphdr hdr; ! 133: char data[SPPMAXDATA]; ! 134: } packbuf; ! 135: struct iovec our_iovec[2]; ! 136: ! 137: switch (f->state) { ! 138: case closed: ! 139: case calldone: ! 140: fprintf(stderr,"BDTread() called while connection state = %s\n", ! 141: (f->state == closed) ? "closed" : "calldone"); ! 142: exit(1); ! 143: /* NOTREACHED */ ! 144: case wantversion: ! 145: count = recv(f->fd, (char*) &packbuf, sizeof(packbuf), MSG_PEEK) ! 146: - sizeof(struct sphdr); ! 147: while (count == 0 ! 148: && packbuf.hdr.sp_dt == SPPSST_RPC) { ! 149: read(f->fd, (char*) &packbuf, sizeof(packbuf)); ! 150: count = recv(f->fd, (char*) &packbuf, sizeof(packbuf), ! 151: MSG_PEEK) ! 152: - sizeof(struct sphdr); ! 153: } ! 154: if (count == 0) ! 155: /* streamtype != SPPSST_RPC, so we can't */ ! 156: /* have a version number */ ! 157: break; ! 158: /* fall out of switch, still wantversion */ ! 159: /* ### N.B. we don't handle count==2 */ ! 160: else if (count != (2*sizeof(Cardinal))) ! 161: /* must be a REJECT or ABORT message */ ! 162: /* let someone else handle it! */ ! 163: return(-1); ! 164: else { ! 165: /* must be a Courier version number */ ! 166: /* read it and throw it away */ ! 167: read(f->fd, (char*) &packbuf, sizeof(packbuf)); ! 168: f->state = inprogress; ! 169: /* fall into case inprogress */ ! 170: } ! 171: case inprogress: ! 172: switch (f->bdtstate) { ! 173: case wantdata: ! 174: count = recv(f->fd, (char*) &packbuf, sizeof(packbuf), ! 175: MSG_PEEK) ! 176: - sizeof(struct sphdr); ! 177: if (packbuf.hdr.sp_dt == SPPSST_RPC) ! 178: return(-1); ! 179: f->bdtstate = established; ! 180: /* fall through to case established */ ! 181: case established: ! 182: break; ! 183: /* fall out of inner (and outer!) switch */ ! 184: case bdteomseen: ! 185: return(0); ! 186: } ! 187: break; ! 188: } ! 189: MAKEVEC(0,&packbuf.hdr,sizeof(struct sphdr)); ! 190: MAKEVEC(1,buffer,nbytes); ! 191: count = readv(f->fd,our_iovec,2) - sizeof(struct sphdr); ! 192: /* at this point, we've read a packet that isn't SPPSST_RPC */ ! 193: while (TRUE) { ! 194: if (packbuf.hdr.sp_dt == SPPSST_END) { ! 195: (void) sppclosereply(f->fd); ! 196: f->state = closed; ! 197: fprintf(stderr,"SPP END received during BDT\n"); ! 198: exit(1); ! 199: } ! 200: if (packbuf.hdr.sp_dt != SPPSST_BDT) { ! 201: fprintf(stderr, ! 202: "wrong stream type, %d, seen during BDT\n", ! 203: packbuf.hdr.sp_dt); ! 204: exit(1); ! 205: /* NOTREACHED */ ! 206: } ! 207: if (f->abortseen || (packbuf.hdr.sp_cc & SP_OB)) { ! 208: f->abortseen = TRUE; ! 209: return(-1); ! 210: } ! 211: if (packbuf.hdr.sp_cc & SP_EM) { ! 212: f->bdtstate = bdteomseen; ! 213: /* next read will return 0 */ ! 214: return(count); ! 215: } ! 216: if (count > 0) ! 217: return(count); ! 218: count = readv(f->fd,our_iovec,2) - sizeof(struct sphdr); ! 219: } ! 220: } ! 221: ! 222: BDTabort(f) ! 223: register CourierConnection *f; ! 224: { ! 225: static struct handy { ! 226: struct sphdr hdr; ! 227: char value; ! 228: } data; ! 229: /* stream=BDT, EOM=FALSE, Attn=TRUE */ ! 230: data.hdr.sp_dt = SPPSST_BDT; ! 231: data.hdr.sp_cc = SP_EM; ! 232: data.value = 1; /* BDT abort data value */ ! 233: send(f->fd, &data, sizeof(data), MSG_OOB); ! 234: f->bdtstate = bdteomseen; ! 235: f->abortseen = TRUE; ! 236: } ! 237: ! 238: ! 239: BDTabortSeen(f) ! 240: register CourierConnection *f; ! 241: { ! 242: struct { ! 243: struct sphdr hdr; ! 244: Unspecified data[MAXWORDS]; ! 245: } packbuf; ! 246: int fdmask; ! 247: register int count; ! 248: static struct timeval timeout = {0,0}; ! 249: ! 250: fdmask = 1<<(f->fd); ! 251: /* ### code here for OOB signalling! */ ! 252: while (select(f->fd+1,&fdmask,(int*)NULL,(int*)NULL,&timeout) > 0 ! 253: && (count = recv(f->fd,(char*)&packbuf, sizeof(packbuf), ! 254: MSG_PEEK) - sizeof(struct sphdr)) > 0) { ! 255: if (packbuf.hdr.sp_dt == SPPSST_BDT ! 256: && (packbuf.hdr.sp_dt & SP_OB) ! 257: && count == 1) { ! 258: read(f->fd, (char*)&packbuf, sizeof(packbuf)); ! 259: f->abortseen = TRUE; ! 260: return(TRUE); ! 261: } ! 262: else if (count == 0) ! 263: read(f->fd, (char*)&packbuf, sizeof(packbuf)); ! 264: else return(FALSE); ! 265: } ! 266: return(FALSE); ! 267: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.