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

Defined functions

BDTabort defined in line 213; used 2 times
BDTabortSeen defined in line 230; used 2 times
BDTclosewrite defined in line 87; used 1 times
BDTread defined in line 110; used 1 times
BDTwrite defined in line 45; used 1 times

Defined variables

rcsid defined in line 26; never used

Defined struct's

handy defined in line 216; never used

Defined macros

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