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