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