|
|
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.