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

Revision 7181, 5.3 KB checked in by miki, 30 years ago (diff)
replace bzero by memset; replace bcopy with memmove if POSIX
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#ifdef POSIX
150      memmove(us->us_outbuf + us->us_nsent_sub_block_bytes, buf, avail);
151#else
152        bcopy(buf, us->us_outbuf + us->us_nsent_sub_block_bytes, avail);
153#endif
154        len -= avail;
155        buf += avail;
156        us->us_nsent_sub_block_bytes += avail;
157        if(send_sub_block(us, FALSE) == ERROR) {
158            return(ERROR);
159        }
160        avail = MAX_SUB_BLOCK_LENGTH;
161        us->us_nsent_sub_block_bytes = 0;       
162    }
163
164    /* put rest of <buf> into <us->us_outbuf> */
165
166#ifdef POSIX
167     memmove(us->us_outbuf + us->us_nsent_sub_block_bytes, buf, len);
168#else
169    bcopy(buf, us->us_outbuf + us->us_nsent_sub_block_bytes, len);
170#endif
171    us->us_nsent_sub_block_bytes += len;
172    return(SUCCESS);
173}
174
175send_sub_block(us, last_p)
176
177USPStream  *us;
178Boolean    last_p;              /* last sub-block flag */
179{
180    USPCardinal len = (USPCardinal) (us->us_nsent_sub_block_bytes +
181                                     sizeof(USPCardinal));
182
183    if(last_p) {                /* is this the last sub-block? */
184        len |= EOB_FLAG;        /* then set last-sub-block flag */
185    }
186    len = (USPCardinal) htons((u_short) len);
187   
188    /* send length word */
189   
190    if(put_onto_net(us, (char *) &len, sizeof(USPCardinal), FALSE) == ERROR) {
191        return(ERROR);
192    }
193
194    /* and send outbuf */
195
196    if(put_onto_net(us, (char *) us->us_outbuf, us->us_nsent_sub_block_bytes,
197                    last_p) == ERROR) {
198        return(ERROR);
199    }
200    return(SUCCESS);
201}
202
203/* put bytes onto network */
204
205put_onto_net(us, buf, len, send_p)
206
207USPStream       *us;
208Byte            *buf;                   /* buffer */
209unsigned        len;                    /* buffer length */
210Boolean         send_p;                 /* if TRUE, force write */
211{
212    int     bytes_sent;
213
214    if((bytes_sent = fwrite((char *) buf, sizeof(Byte), (int) len,
215                            us->us_write)) != len) {
216        return(ERROR);
217    }
218    if(bytes_sent == 0 && errno != 0) {
219        return(ERROR);
220    }
221    if(send_p) {
222        fflush(us->us_write);
223    }
224    return(SUCCESS);
225}
Note: See TracBrowser for help on using the repository browser.