source: trunk/athena/bin/discuss/usp/internal.c @ 203

Revision 203, 5.1 KB checked in by spook, 38 years ago (diff)
Included <netinet/in.h> for machines that don't need to byte-swap.
Line 
1/* UNIX Unified Stream Protocol
2
3   Copyright 1986 by the Massachusetts Institute of Technology
4   See permission and disclaimer notice in file "notice.h"
5*/
6
7#include <sys/types.h>
8#include <errno.h>
9#include <stdio.h>
10#include "gen.h"
11#include "usp.h"
12#include <netinet/in.h>
13
14/* internal routines */
15
16get_sub_block_header(us)
17
18USPStream    *us;
19{
20    USPCardinal sbl;                        /* sub-block length */
21
22    /* get sub-block length (12 bits) + last-sub-block flag (4 bits) */
23   
24    if(get_from_net(us, (char *)&sbl, sizeof(USPCardinal)) == ERROR) {
25        return(ERROR);
26    }
27    sbl = (USPCardinal) ntohs((u_short) sbl);
28    if(sbl & EOB_FLAG) {
29        us->us_last_sub_block_p = TRUE;
30    }
31    else {
32        us->us_last_sub_block_p = FALSE;
33    }
34
35    /* mask length to 12 bits less length of sub-block length field */
36
37    us->us_nunread_sub_block_bytes =
38      (unsigned) ((sbl & 0x0FFF) - sizeof(USPCardinal));
39    return(SUCCESS);
40}
41
42/* skip to end of sub-block */
43
44skip_sub_block(us)
45
46USPStream    *us;
47{
48    Byte        buf[1024];
49
50    if(us->us_nunread_sub_block_bytes == 0) {
51        return(SUCCESS);
52    }
53    while(us->us_nunread_sub_block_bytes > 1024) {
54        if(get_from_net(us, buf, 1024) == ERROR) {
55            return(ERROR);
56        }
57        us->us_nunread_sub_block_bytes -= 1024;
58    }
59    if(get_from_net(us, buf, us->us_nunread_sub_block_bytes) == ERROR) {
60        return(ERROR);
61    }
62    us->us_nunread_sub_block_bytes = 0;
63    return(SUCCESS);
64}
65
66/* get <req> bytes from the net, putting the bytes in <buf> and returning
67   the number of bytes actually read in <bytes-actually-read>.  Assumes
68   the current sub_block has had its header read via get_sub_block_header */
69
70get_from_sub_block(us, buf, req, bytes_actually_read)
71
72USPStream       *us;
73Byte            *buf;
74unsigned        req;
75unsigned        *bytes_actually_read;
76{
77    /* read remainder of current sub-block plus whole sub-blocks until
78       we have <req> bytes */
79
80    *bytes_actually_read = 0;
81    if(req == 0) {
82        return(SUCCESS);
83    }
84    while (req > us->us_nunread_sub_block_bytes) {
85        if(get_from_net(us, buf, us->us_nunread_sub_block_bytes) == ERROR) {
86            return(ERROR);
87        }
88        req -= us->us_nunread_sub_block_bytes;
89        buf += us->us_nunread_sub_block_bytes;
90        *bytes_actually_read += us->us_nunread_sub_block_bytes;
91        if(us->us_last_sub_block_p) {
92            us->us_nunread_sub_block_bytes = 0;
93            return(SUCCESS);        /* block was shorter than we expected */
94        }
95        if(get_sub_block_header(us) == ERROR) {
96            return(ERROR);
97        }
98    }
99    if(get_from_net(us, buf, req) == ERROR) {   /* get rest of data */
100        return(ERROR);
101    }
102    us->us_nunread_sub_block_bytes -= req;
103    *bytes_actually_read += req;
104    return(SUCCESS);
105}
106
107get_from_net(us, buf, req)
108
109USPStream   *us;
110Byte        *buf;                       /* buffer */
111unsigned    req;                        /* bytes requested */
112{
113    int bytes_read;
114
115    while(req) {
116        if((bytes_read = fread((char *) buf, sizeof(Byte), (int) req,
117                               us->us_read)) == 0) {
118            if(errno != 0) {
119                return(ERROR);
120            }
121            else {
122                errno = ECONNRESET;     /* end of file -- conn reset */
123                return(ERROR);
124            }
125        }
126        req -= bytes_read;
127        buf += bytes_read;
128    }
129    return(SUCCESS);
130}
131
132/* put the <len> bytes in <buf> into the current sub-block.  If the
133   current sub-block fills up, send it and begin a new sub_block */
134
135put_into_sub_block(us, buf, len)
136
137USPStream       *us;
138Byte            *buf;
139unsigned        len;   
140{
141    unsigned avail = MAX_SUB_BLOCK_LENGTH - us->us_nsent_sub_block_bytes;
142
143    while(len > avail) {
144
145        /* copy <avail> bytes of <buf> into <us_outbuf> and send <us_outbuf>
146           as a sub-block.  Thhen flush <us_outbuf> and put more bytes of
147           <buf> into it */
148
149        bcopy(buf, us->us_outbuf + us->us_nsent_sub_block_bytes, avail);
150        len -= avail;
151        buf += avail;
152        us->us_nsent_sub_block_bytes += avail;
153        if(send_sub_block(us, FALSE) == ERROR) {
154            return(ERROR);
155        }
156        avail = MAX_SUB_BLOCK_LENGTH;
157        us->us_nsent_sub_block_bytes = 0;       
158    }
159
160    /* put rest of <buf> into <us->us_outbuf> */
161
162    bcopy(buf, us->us_outbuf + us->us_nsent_sub_block_bytes, len);
163    us->us_nsent_sub_block_bytes += len;
164    return(SUCCESS);
165}
166
167send_sub_block(us, last_p)
168
169USPStream  *us;
170Boolean    last_p;              /* last sub-block flag */
171{
172    USPCardinal len = (USPCardinal) (us->us_nsent_sub_block_bytes +
173                                     sizeof(USPCardinal));
174
175    if(last_p) {                /* is this the last sub-block? */
176        len |= EOB_FLAG;        /* then set last-sub-block flag */
177    }
178    len = (USPCardinal) htons((u_short) len);
179   
180    /* send length word */
181   
182    if(put_onto_net(us, (char *) &len, sizeof(USPCardinal), FALSE) == ERROR) {
183        return(ERROR);
184    }
185
186    /* and send outbuf */
187
188    if(put_onto_net(us, (char *) us->us_outbuf, us->us_nsent_sub_block_bytes,
189                    last_p) == ERROR) {
190        return(ERROR);
191    }
192    return(SUCCESS);
193}
194
195/* put bytes onto network */
196
197put_onto_net(us, buf, len, send_p)
198
199USPStream       *us;
200Byte            *buf;                   /* buffer */
201unsigned        len;                    /* buffer length */
202Boolean         send_p;                 /* if TRUE, force write */
203{
204    int     bytes_sent;
205
206    if((bytes_sent = fwrite((char *) buf, sizeof(Byte), (int) len,
207                            us->us_write)) != len) {
208        return(ERROR);
209    }
210    if(bytes_sent == 0 && errno != 0) {
211        return(ERROR);
212    }
213    if(send_p) {
214        fflush(us->us_write);
215    }
216    return(SUCCESS);
217}
Note: See TracBrowser for help on using the repository browser.