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: }

Defined functions

CheckEND defined in line 273; used 1 times
CourierClose defined in line 305; never used
openSPPConnection defined in line 313; used 2 times

Defined variables

rcsid defined in line 37; never used

Defined macros

MAKEVEC defined in line 52; used 11 times
Last modified: 1986-03-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1379
Valid CSS Valid XHTML 1.0 Strict