|
|
1.1 ! root 1: /* ! 2: * This file implements functions used by both client and servers in the ! 3: * XNS courier library ! 4: */ ! 5: ! 6: /* ! 7: $Log: readwrite.c,v $ ! 8: * Revision 2.0 85/11/21 07:22:15 jqj ! 9: * 4.3BSD standard release ! 10: * ! 11: * Revision 1.8 85/10/21 13:01:17 jqj ! 12: * Gould version. ! 13: * ! 14: * Revision 1.7 85/10/17 07:22:53 jqj ! 15: * Fix to previous edit. ! 16: * ! 17: * Revision 1.6 85/10/17 07:07:02 jqj ! 18: * ReadMessage had a typo which Gould compiler caught: bug in case of ! 19: * message with Courier header split across several SPP packets. ! 20: * ! 21: * Revision 1.5 85/09/27 16:01:23 jqj ! 22: * added error checking to read in ReadMessage to bomb on closed connections. ! 23: * ! 24: * Revision 1.4 85/03/11 16:37:24 jqj ! 25: * Public alpha-test version, released 11 March 1985 ! 26: * ! 27: * Revision 1.3 85/02/22 09:27:40 bill ! 28: * Almost working version. Am about to change ! 29: * ReadMessage to match what really shows up from the Xerox stuff. ! 30: * ! 31: * Revision 1.2 85/01/27 07:37:39 jqj ! 32: * finished but undebugged version ! 33: * ! 34: */ ! 35: ! 36: #ifndef lint ! 37: static char rcsid[] = "$Header: readwrite.c,v 2.0 85/11/21 07:22:15 jqj Exp $"; ! 38: #endif ! 39: ! 40: #include <stdio.h> ! 41: #include <sys/types.h> /* for ns.h and socket.h */ ! 42: #include <sys/socket.h> ! 43: #include <sys/time.h> ! 44: #include <sys/uio.h> /* for scatter/gather io */ ! 45: #include <netns/ns.h> /* for XNS addresses and courierconnection.h */ ! 46: #include <netns/idp.h> ! 47: #include <netns/sp.h> /* for spphdr */ ! 48: #include <errno.h> /* for EPROTOTYPE */ ! 49: #include "courier.h" ! 50: #include "realcourierconnection.h" ! 51: ! 52: #define MAKEVEC(idx, addr, len) our_iovec[idx].iov_base = (caddr_t)addr;\ ! 53: our_iovec[idx].iov_len = len; ! 54: ! 55: ! 56: CourierWrite(f, hdrlen, hdrbuf, nwords, arguments) ! 57: /* write a 2-block message possibly consisting of several packets */ ! 58: register CourierConnection *f; ! 59: int hdrlen; /* length of hdrbuf, in words */ ! 60: Unspecified *hdrbuf; ! 61: register Cardinal nwords; /* length of arguments, in words */ ! 62: register Unspecified *arguments; ! 63: { ! 64: struct iovec our_iovec[3]; ! 65: ! 66: if (f->state == closed) { ! 67: f->abortseen = FALSE; ! 68: if ((f->fd = openSPPConnection(&(f->host))) >= 0) { ! 69: f->state = wantversion; ! 70: } ! 71: else { ! 72: fprintf(stderr,"(Courier) Can't reopen SPP connection\n"); ! 73: exit(1); ! 74: /* NOTREACHED */ ! 75: } ! 76: } ! 77: MAKEVEC(0, &(f->sphdrOpts), sizeof(f->sphdrOpts)); ! 78: MAKEVEC(1, hdrbuf, (hdrlen*sizeof(Unspecified)) ); ! 79: if (nwords <= MAXWORDS-hdrlen) { ! 80: /* SetSPPoptions(f->fd, SPPSST_RPC, 1, 0); ! 81: datastream=0, EOM=TRUE, Attn=FALSE */ ! 82: f->sphdrOpts.sp_dt = SPPSST_RPC; ! 83: f->sphdrOpts.sp_cc |= SP_EM; ! 84: MAKEVEC(2, arguments, nwords*sizeof(Unspecified)); ! 85: if (writev(f->fd, our_iovec, 3) < 0) { ! 86: perror("(Courier) writev"); ! 87: exit(1); ! 88: } ! 89: ! 90: } ! 91: else { ! 92: MAKEVEC(2, arguments, (MAXWORDS-hdrlen)*sizeof(Unspecified)); ! 93: /* SetSPPoptions(f->fd, SPPSST_RPC, 0, 0); ! 94: /* datastream=0, EOM=FALSE, Attn=FALSE */ ! 95: f->sphdrOpts.sp_dt = SPPSST_RPC; ! 96: f->sphdrOpts.sp_cc &= ~SP_EM; ! 97: nwords -= MAXWORDS-hdrlen; arguments += MAXWORDS-hdrlen; ! 98: if (writev(f->fd, our_iovec, 3) < 0) { ! 99: perror("(Courier) writev"); ! 100: exit(1); ! 101: } ! 102: MAKEVEC(1, (char *)arguments, MAXWORDS*sizeof(Unspecified)); ! 103: while (nwords > MAXWORDS) { ! 104: writev(f->fd, our_iovec, 2); ! 105: nwords -= MAXWORDS; arguments += MAXWORDS; ! 106: our_iovec[1].iov_base = (char *)arguments; ! 107: } ! 108: f->sphdrOpts.sp_cc |= SP_EM; ! 109: /* SetSPPoptions(f->fd, SPPSST_RPC, 1, 0); ! 110: /* datastream=0, EOM=TRUE, Attn=FALSE */ ! 111: our_iovec[1].iov_len = nwords*sizeof(Unspecified); ! 112: writev(f->fd, our_iovec, 2); ! 113: } ! 114: ! 115: } ! 116: ! 117: ! 118: ! 119: Unspecified * ! 120: ReadMessage(f, firstbuf, firstlength) ! 121: register CourierConnection *f; /* socket descriptor */ ! 122: Unspecified *firstbuf; ! 123: Cardinal firstlength; ! 124: /* Read a complete Courier message from SPP socket f->fd, skipping packets ! 125: * with the wrong datastream type. ! 126: * If firstbuf is specified with a non-zero length (in Unspecifieds), then it ! 127: * is filled before the malloced packet. ! 128: * Return a pointer to beginning of a malloced packet (caller is responsible ! 129: * for freeing it), and a length in *retlength ! 130: * Returns NULL if connection closes prematurely. ! 131: */ ! 132: { ! 133: char *buf; /* ptr to message buffer */ ! 134: Cardinal length, /* current message length, bytes */ ! 135: bufsize, /* current buffer size, bytes */ ! 136: nextincrement; /* amt of space to try for next */ ! 137: register int count; /* data bytes read by current readv() */ ! 138: struct iovec our_iovec[3]; ! 139: struct { ! 140: struct sphdr hdr; ! 141: Cardinal version[2]; ! 142: } hdrbuf; ! 143: Cardinal versionl, /* version numbers received */ ! 144: versionh; ! 145: int verbyteswanted; ! 146: extern char *malloc(), *realloc(); ! 147: extern free(); ! 148: int cc; ! 149: ! 150: /* spp & idp header */ ! 151: MAKEVEC(0, &hdrbuf.hdr, sizeof(struct sphdr)); ! 152: /* conn id, etc... */ ! 153: if (firstbuf == NULL) ! 154: firstlength = 0; ! 155: else ! 156: firstlength *= sizeof(Unspecified); /* length in bytes */ ! 157: MAKEVEC(1, firstbuf, firstlength); ! 158: /* data */ ! 159: buf = malloc(SPPMAXDATA); ! 160: MAKEVEC(2, buf, SPPMAXDATA); ! 161: ! 162: bufsize = SPPMAXDATA; ! 163: /* ! 164: * flush Courier version number if necessary ! 165: */ ! 166: if (f->state != wantversion) { ! 167: /* we don't have to look for a version number this time! */ ! 168: count = readv(f->fd, our_iovec, 3) - sizeof(struct sphdr); ! 169: if (count < 0 || hdrbuf.hdr.sp_dt == SPPSST_END) { ! 170: if (count >= 0) (void) sppclosereply(f->fd); ! 171: f->state = closed; ! 172: free(buf); ! 173: return(NULL); ! 174: } ! 175: } else { ! 176: /* stick version range in with header */ ! 177: verbyteswanted = 2*sizeof(Cardinal); ! 178: our_iovec[0].iov_len += verbyteswanted; ! 179: while (verbyteswanted > 0) { ! 180: count = readv(f->fd, our_iovec, 3) ! 181: - sizeof(struct sphdr); ! 182: if (count < 0 || hdrbuf.hdr.sp_dt == SPPSST_END) { ! 183: if (count >= 0) (void) sppclosereply(f->fd); ! 184: f->state = closed; ! 185: free(buf); ! 186: return(NULL); ! 187: } ! 188: /* we don't bother to check for matching */ ! 189: /* Courier version */ ! 190: if (count >= verbyteswanted) { ! 191: count -= verbyteswanted; ! 192: our_iovec[0].iov_len -= verbyteswanted; ! 193: verbyteswanted = 0; ! 194: } ! 195: else { ! 196: verbyteswanted -= count; ! 197: our_iovec[0].iov_len -= count; ! 198: count = 0; ! 199: } ! 200: } ! 201: f->state = inprogress; ! 202: while (count == 0) { ! 203: /* read either RPC reply or BDT garbage */ ! 204: count = readv(f->fd, our_iovec, 3) ! 205: - sizeof(struct sphdr); ! 206: if (count < 0 || hdrbuf.hdr.sp_dt == SPPSST_END) { ! 207: if (count >= 0) (void) sppclosereply(f->fd); ! 208: f->state = closed; ! 209: free(buf); ! 210: return(NULL); ! 211: } ! 212: } ! 213: /* {version-packet, null-0-packet, bdt-packet, reply-packet}, ! 214: * is handled, but I don't think it's legal */ ! 215: } ! 216: /* ! 217: * we've flushed any version number that might be present, ! 218: * and have read the first packet -- which may be garbage. ! 219: * Throw away any further garbage (e.g. BDT data) too. ! 220: */ ! 221: while (hdrbuf.hdr.sp_dt != SPPSST_RPC) { ! 222: count = readv(f->fd, our_iovec, 3) - sizeof(struct sphdr); ! 223: if (count < 0 || hdrbuf.hdr.sp_dt == SPPSST_END) { ! 224: if (count >= 0) (void) sppclosereply(f->fd); ! 225: f->state = closed; ! 226: free(buf); ! 227: return(NULL); ! 228: } ! 229: } ! 230: /* ! 231: * Now we have a real RPC data packet, which we hope is the reply ! 232: */ ! 233: length = count; ! 234: nextincrement = SPPMAXDATA; ! 235: while ( ! (hdrbuf.hdr.sp_cc & SP_EM)) { ! 236: /* Not to end of message yet, so read another packet */ ! 237: if (length+nextincrement-firstlength > bufsize) { ! 238: /* not enough space for next packet. Make room. */ ! 239: bufsize = length+nextincrement-firstlength; ! 240: buf = realloc(buf, (unsigned) bufsize); ! 241: /* do order(log(messagelength)) reallocs */ ! 242: nextincrement += nextincrement; ! 243: } ! 244: if (length >= firstlength) { ! 245: MAKEVEC(1,NULL,0); ! 246: MAKEVEC(2,buf+length-firstlength,bufsize+firstlength-length); ! 247: } ! 248: else { ! 249: firstbuf += length/sizeof(Unspecified); ! 250: firstlength -= length; ! 251: MAKEVEC(1, firstbuf, firstlength); ! 252: } ! 253: count = readv(f->fd, our_iovec, 3) - sizeof(struct sphdr); ! 254: if (count < 0 || hdrbuf.hdr.sp_dt == SPPSST_END) { ! 255: if (count >= 0) (void) sppclosereply(f->fd); ! 256: f->state = closed; ! 257: free(buf); ! 258: return(NULL); ! 259: } ! 260: if (hdrbuf.hdr.sp_dt != SPPSST_RPC) { ! 261: fprintf(stderr,"(Courier) Stream type changed from %d to %d during message\n", ! 262: SPPSST_RPC, hdrbuf.hdr.sp_dt); ! 263: exit(1); ! 264: /* NOTREACHED */ ! 265: } ! 266: length += count; ! 267: } ! 268: return((Unspecified*) buf); ! 269: } ! 270: ! 271: ! 272: ! 273: CheckEND(f) ! 274: /* look ahead on courier connection, checking for an END packet. ! 275: * If seen, set state to closed. ! 276: */ ! 277: CourierConnection *f; ! 278: { ! 279: struct { ! 280: struct sphdr hdr; ! 281: char data[SPPMAXDATA]; ! 282: } packbuf; ! 283: int count; ! 284: int fdmask; ! 285: static struct timeval timeout = {0,0}; ! 286: ! 287: fdmask = 1<<(f->fd); ! 288: while (select(f->fd+1,&fdmask,(int*)NULL,(int*)NULL,&timeout) > 0 ! 289: && (count = recv(f->fd,(char*)&packbuf, sizeof(packbuf), ! 290: MSG_PEEK)) > 0) { ! 291: if (packbuf.hdr.sp_dt == SPPSST_END) { ! 292: read(f->fd, (char*)&packbuf, sizeof(packbuf)); ! 293: (void) sppclosereply(f->fd); ! 294: f->state = closed; ! 295: return(TRUE); ! 296: } ! 297: else if (count == sizeof(struct sphdr)) ! 298: read(f->fd, (char*)&packbuf, sizeof(packbuf)); ! 299: else return(FALSE); ! 300: } ! 301: return(FALSE); ! 302: } ! 303: ! 304: ! 305: CourierClose(conn) ! 306: CourierConnection * conn; ! 307: { ! 308: (void) sppclose(conn->fd); ! 309: free((char*) conn); ! 310: } ! 311: ! 312: ! 313: openSPPConnection(dst) ! 314: struct sockaddr_ns *dst; ! 315: { ! 316: int s; ! 317: extern int errno; ! 318: ! 319: if ((s = socket(dst->sns_family, SOCK_SEQPACKET, 0)) < 0) { ! 320: perror("(Courier) socket"); ! 321: exit(1); ! 322: /*NOTREACHED*/ ! 323: } ! 324: if (connect(s, (struct sockaddr*)dst, sizeof(struct sockaddr_ns)) < 0) { ! 325: perror("(Courier) connect"); ! 326: exit(1); ! 327: /*NOTREACHED*/ ! 328: } ! 329: return(s); ! 330: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.