]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/telnet/telnet/ring.c
This commit was generated by cvs2svn to compensate for changes in r53657,
[FreeBSD/FreeBSD.git] / contrib / telnet / telnet / ring.c
1 /*
2  * Copyright (c) 1988, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #ifndef lint
35 static const char sccsid[] = "@(#)ring.c        8.2 (Berkeley) 5/30/95";
36 #endif /* not lint */
37
38 /*
39  * This defines a structure for a ring buffer.
40  *
41  * The circular buffer has two parts:
42  *(((
43  *      full:   [consume, supply)
44  *      empty:  [supply, consume)
45  *]]]
46  *
47  */
48
49 #include        <stdio.h>
50 #include        <errno.h>
51 #include        <string.h>
52
53 #ifdef  size_t
54 #undef  size_t
55 #endif
56
57 #include        <sys/types.h>
58 #ifndef FILIO_H
59 #include        <sys/ioctl.h>
60 #endif
61 #include        <sys/socket.h>
62
63 #include        "ring.h"
64 #include        "general.h"
65
66 /* Internal macros */
67
68 #if     !defined(MIN)
69 #define MIN(a,b)        (((a)<(b))? (a):(b))
70 #endif  /* !defined(MIN) */
71
72 #define ring_subtract(d,a,b)    (((a)-(b) >= 0)? \
73                                         (a)-(b): (((a)-(b))+(d)->size))
74
75 #define ring_increment(d,a,c)   (((a)+(c) < (d)->top)? \
76                                         (a)+(c) : (((a)+(c))-(d)->size))
77
78 #define ring_decrement(d,a,c)   (((a)-(c) >= (d)->bottom)? \
79                                         (a)-(c) : (((a)-(c))-(d)->size))
80
81
82 /*
83  * The following is a clock, used to determine full, empty, etc.
84  *
85  * There is some trickiness here.  Since the ring buffers are initialized
86  * to ZERO on allocation, we need to make sure, when interpreting the
87  * clock, that when the times are EQUAL, then the buffer is FULL.
88  */
89 static u_long ring_clock = 0;
90
91
92 #define ring_empty(d) (((d)->consume == (d)->supply) && \
93                                 ((d)->consumetime >= (d)->supplytime))
94 #define ring_full(d) (((d)->supply == (d)->consume) && \
95                                 ((d)->supplytime > (d)->consumetime))
96
97
98
99
100
101 /* Buffer state transition routines */
102
103         int
104     ring_init(ring, buffer, count)
105 Ring *ring;
106     unsigned char *buffer;
107     int count;
108 {
109     memset((char *)ring, 0, sizeof *ring);
110
111     ring->size = count;
112
113     ring->supply = ring->consume = ring->bottom = buffer;
114
115     ring->top = ring->bottom+ring->size;
116
117 #ifdef  ENCRYPTION
118     ring->clearto = 0;
119 #endif  /* ENCRYPTION */
120
121     return 1;
122 }
123
124 /* Mark routines */
125
126 /*
127  * Mark the most recently supplied byte.
128  */
129
130     void
131 ring_mark(ring)
132     Ring *ring;
133 {
134     ring->mark = ring_decrement(ring, ring->supply, 1);
135 }
136
137 /*
138  * Is the ring pointing to the mark?
139  */
140
141     int
142 ring_at_mark(ring)
143     Ring *ring;
144 {
145     if (ring->mark == ring->consume) {
146         return 1;
147     } else {
148         return 0;
149     }
150 }
151
152 /*
153  * Clear any mark set on the ring.
154  */
155
156     void
157 ring_clear_mark(ring)
158     Ring *ring;
159 {
160     ring->mark = 0;
161 }
162
163 /*
164  * Add characters from current segment to ring buffer.
165  */
166     void
167 ring_supplied(ring, count)
168     Ring *ring;
169     int count;
170 {
171     ring->supply = ring_increment(ring, ring->supply, count);
172     ring->supplytime = ++ring_clock;
173 }
174
175 /*
176  * We have just consumed "c" bytes.
177  */
178     void
179 ring_consumed(ring, count)
180     Ring *ring;
181     int count;
182 {
183     if (count == 0)     /* don't update anything */
184         return;
185
186     if (ring->mark &&
187                 (ring_subtract(ring, ring->mark, ring->consume) < count)) {
188         ring->mark = 0;
189     }
190 #ifdef  ENCRYPTION
191     if (ring->consume < ring->clearto &&
192                 ring->clearto <= ring->consume + count)
193         ring->clearto = 0;
194     else if (ring->consume + count > ring->top &&
195                 ring->bottom <= ring->clearto &&
196                 ring->bottom + ((ring->consume + count) - ring->top))
197         ring->clearto = 0;
198 #endif  /* ENCRYPTION */
199     ring->consume = ring_increment(ring, ring->consume, count);
200     ring->consumetime = ++ring_clock;
201     /*
202      * Try to encourage "ring_empty_consecutive()" to be large.
203      */
204     if (ring_empty(ring)) {
205         ring->consume = ring->supply = ring->bottom;
206     }
207 }
208
209
210
211 /* Buffer state query routines */
212
213
214 /* Number of bytes that may be supplied */
215     int
216 ring_empty_count(ring)
217     Ring *ring;
218 {
219     if (ring_empty(ring)) {     /* if empty */
220             return ring->size;
221     } else {
222         return ring_subtract(ring, ring->consume, ring->supply);
223     }
224 }
225
226 /* number of CONSECUTIVE bytes that may be supplied */
227     int
228 ring_empty_consecutive(ring)
229     Ring *ring;
230 {
231     if ((ring->consume < ring->supply) || ring_empty(ring)) {
232                             /*
233                              * if consume is "below" supply, or empty, then
234                              * return distance to the top
235                              */
236         return ring_subtract(ring, ring->top, ring->supply);
237     } else {
238                                     /*
239                                      * else, return what we may.
240                                      */
241         return ring_subtract(ring, ring->consume, ring->supply);
242     }
243 }
244
245 /* Return the number of bytes that are available for consuming
246  * (but don't give more than enough to get to cross over set mark)
247  */
248
249     int
250 ring_full_count(ring)
251     Ring *ring;
252 {
253     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
254         if (ring_full(ring)) {
255             return ring->size;  /* nothing consumed, but full */
256         } else {
257             return ring_subtract(ring, ring->supply, ring->consume);
258         }
259     } else {
260         return ring_subtract(ring, ring->mark, ring->consume);
261     }
262 }
263
264 /*
265  * Return the number of CONSECUTIVE bytes available for consuming.
266  * However, don't return more than enough to cross over set mark.
267  */
268     int
269 ring_full_consecutive(ring)
270     Ring *ring;
271 {
272     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
273         if ((ring->supply < ring->consume) || ring_full(ring)) {
274             return ring_subtract(ring, ring->top, ring->consume);
275         } else {
276             return ring_subtract(ring, ring->supply, ring->consume);
277         }
278     } else {
279         if (ring->mark < ring->consume) {
280             return ring_subtract(ring, ring->top, ring->consume);
281         } else {        /* Else, distance to mark */
282             return ring_subtract(ring, ring->mark, ring->consume);
283         }
284     }
285 }
286
287 /*
288  * Move data into the "supply" portion of of the ring buffer.
289  */
290     void
291 ring_supply_data(ring, buffer, count)
292     Ring *ring;
293     unsigned char *buffer;
294     int count;
295 {
296     int i;
297
298     while (count) {
299         i = MIN(count, ring_empty_consecutive(ring));
300         memmove(ring->supply, buffer, i);
301         ring_supplied(ring, i);
302         count -= i;
303         buffer += i;
304     }
305 }
306
307 #ifdef notdef
308
309 /*
310  * Move data from the "consume" portion of the ring buffer
311  */
312     void
313 ring_consume_data(ring, buffer, count)
314     Ring *ring;
315     unsigned char *buffer;
316     int count;
317 {
318     int i;
319
320     while (count) {
321         i = MIN(count, ring_full_consecutive(ring));
322         memmove(buffer, ring->consume, i);
323         ring_consumed(ring, i);
324         count -= i;
325         buffer += i;
326     }
327 }
328 #endif
329
330 #ifdef  ENCRYPTION
331     void
332 ring_encrypt(ring, encryptor)
333     Ring *ring;
334     void (*encryptor)();
335 {
336     unsigned char *s, *c;
337
338     if (ring_empty(ring) || ring->clearto == ring->supply)
339         return;
340
341     if (!(c = ring->clearto))
342         c = ring->consume;
343
344     s = ring->supply;
345
346     if (s <= c) {
347         (*encryptor)(c, ring->top - c);
348         (*encryptor)(ring->bottom, s - ring->bottom);
349     } else
350         (*encryptor)(c, s - c);
351
352     ring->clearto = ring->supply;
353 }
354
355     void
356 ring_clearto(ring)
357     Ring *ring;
358 {
359     if (!ring_empty(ring))
360         ring->clearto = ring->supply;
361     else
362         ring->clearto = 0;
363 }
364 #endif  /* ENCRYPTION */