xref: /csrg-svn/usr.bin/telnet/ring.c (revision 46808)
132379Sminshall /*
233685Sbostic  * Copyright (c) 1988 Regents of the University of California.
333685Sbostic  * All rights reserved.
433685Sbostic  *
542770Sbostic  * %sccs.include.redist.c%
633685Sbostic  */
733685Sbostic 
833685Sbostic #ifndef lint
9*46808Sdab static char sccsid[] = "@(#)ring.c	5.2 (Berkeley) 03/01/91";
1033685Sbostic #endif /* not lint */
1133685Sbostic 
1233685Sbostic /*
1332528Sminshall  * This defines a structure for a ring buffer.
1432379Sminshall  *
1532528Sminshall  * The circular buffer has two parts:
1632379Sminshall  *(((
1732528Sminshall  *	full:	[consume, supply)
1832528Sminshall  *	empty:	[supply, consume)
1932379Sminshall  *]]]
2032379Sminshall  *
2132379Sminshall  */
2232379Sminshall 
2332379Sminshall #include	<stdio.h>
2432379Sminshall #include	<errno.h>
2532379Sminshall 
2632379Sminshall #ifdef	size_t
2732379Sminshall #undef	size_t
2832379Sminshall #endif
2932379Sminshall 
3032379Sminshall #include	<sys/types.h>
3144360Sborman #ifndef	FILIO_H
3232379Sminshall #include	<sys/ioctl.h>
3344360Sborman #endif
3432379Sminshall #include	<sys/socket.h>
3532379Sminshall 
3632379Sminshall #include	"ring.h"
3732379Sminshall #include	"general.h"
3832379Sminshall 
3932379Sminshall /* Internal macros */
4032379Sminshall 
4132381Sminshall #if	!defined(MIN)
4232381Sminshall #define	MIN(a,b)	(((a)<(b))? (a):(b))
4332381Sminshall #endif	/* !defined(MIN) */
4432379Sminshall 
4538689Sborman #define	ring_subtract(d,a,b)	(((a)-(b) >= 0)? \
4632381Sminshall 					(a)-(b): (((a)-(b))+(d)->size))
4732379Sminshall 
4832379Sminshall #define	ring_increment(d,a,c)	(((a)+(c) < (d)->top)? \
4932379Sminshall 					(a)+(c) : (((a)+(c))-(d)->size))
5032379Sminshall 
5133294Sminshall #define	ring_decrement(d,a,c)	(((a)-(c) >= (d)->bottom)? \
5233294Sminshall 					(a)-(c) : (((a)-(c))-(d)->size))
5332379Sminshall 
5433294Sminshall 
5532379Sminshall /*
5632379Sminshall  * The following is a clock, used to determine full, empty, etc.
5732379Sminshall  *
5832379Sminshall  * There is some trickiness here.  Since the ring buffers are initialized
5932379Sminshall  * to ZERO on allocation, we need to make sure, when interpreting the
6032528Sminshall  * clock, that when the times are EQUAL, then the buffer is FULL.
6132379Sminshall  */
6232379Sminshall static u_long ring_clock = 0;
6332379Sminshall 
6432379Sminshall 
6532528Sminshall #define	ring_empty(d) (((d)->consume == (d)->supply) && \
6632528Sminshall 				((d)->consumetime >= (d)->supplytime))
6732528Sminshall #define	ring_full(d) (((d)->supply == (d)->consume) && \
6832528Sminshall 				((d)->supplytime > (d)->consumetime))
6932379Sminshall 
7032379Sminshall 
7132379Sminshall 
7232379Sminshall 
7332379Sminshall 
7432379Sminshall /* Buffer state transition routines */
7532379Sminshall 
76*46808Sdab     ring_init(ring, buffer, count)
7732381Sminshall Ring *ring;
78*46808Sdab     unsigned char *buffer;
79*46808Sdab     int count;
8032381Sminshall {
8132381Sminshall     memset((char *)ring, 0, sizeof *ring);
8232379Sminshall 
8332381Sminshall     ring->size = count;
8432381Sminshall 
8532528Sminshall     ring->supply = ring->consume = ring->bottom = buffer;
8632381Sminshall 
8732381Sminshall     ring->top = ring->bottom+ring->size;
8832381Sminshall 
89*46808Sdab #if	defined(ENCRYPT)
90*46808Sdab     ring->clearto = 0;
91*46808Sdab #endif
92*46808Sdab 
9332381Sminshall     return 1;
9432381Sminshall }
9532381Sminshall 
9633294Sminshall /* Mark routines */
9733294Sminshall 
9832379Sminshall /*
9933294Sminshall  * Mark the most recently supplied byte.
10033294Sminshall  */
10133294Sminshall 
102*46808Sdab     void
10333294Sminshall ring_mark(ring)
104*46808Sdab     Ring *ring;
10533294Sminshall {
10633294Sminshall     ring->mark = ring_decrement(ring, ring->supply, 1);
10733294Sminshall }
10833294Sminshall 
10933294Sminshall /*
11033294Sminshall  * Is the ring pointing to the mark?
11133294Sminshall  */
11233294Sminshall 
113*46808Sdab     int
11433294Sminshall ring_at_mark(ring)
115*46808Sdab     Ring *ring;
11633294Sminshall {
11733294Sminshall     if (ring->mark == ring->consume) {
11833294Sminshall 	return 1;
11933294Sminshall     } else {
12033294Sminshall 	return 0;
12133294Sminshall     }
12233294Sminshall }
12333294Sminshall 
12433294Sminshall /*
12533294Sminshall  * Clear any mark set on the ring.
12633294Sminshall  */
12733294Sminshall 
128*46808Sdab     void
12933294Sminshall ring_clear_mark(ring)
130*46808Sdab     Ring *ring;
13133294Sminshall {
13233294Sminshall     ring->mark = 0;
13333294Sminshall }
13433294Sminshall 
13533294Sminshall /*
13632379Sminshall  * Add characters from current segment to ring buffer.
13732379Sminshall  */
138*46808Sdab     void
13932528Sminshall ring_supplied(ring, count)
140*46808Sdab     Ring *ring;
141*46808Sdab     int count;
14232379Sminshall {
14332528Sminshall     ring->supply = ring_increment(ring, ring->supply, count);
14432528Sminshall     ring->supplytime = ++ring_clock;
14532379Sminshall }
14632379Sminshall 
14732379Sminshall /*
14832528Sminshall  * We have just consumed "c" bytes.
14932379Sminshall  */
150*46808Sdab     void
15132528Sminshall ring_consumed(ring, count)
152*46808Sdab     Ring *ring;
153*46808Sdab     int count;
15432379Sminshall {
15532667Sminshall     if (count == 0)	/* don't update anything */
15632667Sminshall 	return;
15732667Sminshall 
15833294Sminshall     if (ring->mark &&
15933294Sminshall 		(ring_subtract(ring, ring->mark, ring->consume) < count)) {
16033294Sminshall 	ring->mark = 0;
16133294Sminshall     }
162*46808Sdab #if	defined(ENCRYPT)
163*46808Sdab     if (ring->consume < ring->clearto &&
164*46808Sdab 		ring->clearto <= ring->consume + count)
165*46808Sdab 	ring->clearto = 0;
166*46808Sdab     else if (ring->consume + count > ring->top &&
167*46808Sdab 		ring->bottom <= ring->clearto &&
168*46808Sdab 		ring->bottom + ((ring->consume + count) - ring->top))
169*46808Sdab 	ring->clearto = 0;
170*46808Sdab #endif
17132528Sminshall     ring->consume = ring_increment(ring, ring->consume, count);
17232528Sminshall     ring->consumetime = ++ring_clock;
17332547Sminshall     /*
17432547Sminshall      * Try to encourage "ring_empty_consecutive()" to be large.
17532547Sminshall      */
17632547Sminshall     if (ring_empty(ring)) {
17732547Sminshall 	ring->consume = ring->supply = ring->bottom;
17832547Sminshall     }
17932379Sminshall }
18032379Sminshall 
18132379Sminshall 
18232379Sminshall 
18332379Sminshall /* Buffer state query routines */
18432379Sminshall 
18532379Sminshall 
18632528Sminshall /* Number of bytes that may be supplied */
187*46808Sdab     int
18832379Sminshall ring_empty_count(ring)
189*46808Sdab     Ring *ring;
19032379Sminshall {
19132528Sminshall     if (ring_empty(ring)) {	/* if empty */
19232379Sminshall 	    return ring->size;
19332379Sminshall     } else {
19432528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
19532379Sminshall     }
19632379Sminshall }
19732379Sminshall 
19832528Sminshall /* number of CONSECUTIVE bytes that may be supplied */
199*46808Sdab     int
20032379Sminshall ring_empty_consecutive(ring)
201*46808Sdab     Ring *ring;
20232379Sminshall {
20332528Sminshall     if ((ring->consume < ring->supply) || ring_empty(ring)) {
20432528Sminshall 			    /*
20532528Sminshall 			     * if consume is "below" supply, or empty, then
20632528Sminshall 			     * return distance to the top
20732528Sminshall 			     */
20832528Sminshall 	return ring_subtract(ring, ring->top, ring->supply);
20932379Sminshall     } else {
21032379Sminshall 				    /*
21132379Sminshall 				     * else, return what we may.
21232379Sminshall 				     */
21332528Sminshall 	return ring_subtract(ring, ring->consume, ring->supply);
21432379Sminshall     }
21532379Sminshall }
21632379Sminshall 
21733294Sminshall /* Return the number of bytes that are available for consuming
21833294Sminshall  * (but don't give more than enough to get to cross over set mark)
21933294Sminshall  */
22033294Sminshall 
221*46808Sdab     int
22232528Sminshall ring_full_count(ring)
223*46808Sdab     Ring *ring;
22432379Sminshall {
22533294Sminshall     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
22633294Sminshall 	if (ring_full(ring)) {
22733294Sminshall 	    return ring->size;	/* nothing consumed, but full */
22833294Sminshall 	} else {
22933294Sminshall 	    return ring_subtract(ring, ring->supply, ring->consume);
23033294Sminshall 	}
23132379Sminshall     } else {
23233294Sminshall 	return ring_subtract(ring, ring->mark, ring->consume);
23332379Sminshall     }
23432379Sminshall }
23532379Sminshall 
23633294Sminshall /*
23733294Sminshall  * Return the number of CONSECUTIVE bytes available for consuming.
23833294Sminshall  * However, don't return more than enough to cross over set mark.
23933294Sminshall  */
240*46808Sdab     int
24132528Sminshall ring_full_consecutive(ring)
242*46808Sdab     Ring *ring;
24332379Sminshall {
24433294Sminshall     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
24533294Sminshall 	if ((ring->supply < ring->consume) || ring_full(ring)) {
24633294Sminshall 	    return ring_subtract(ring, ring->top, ring->consume);
24733294Sminshall 	} else {
24833294Sminshall 	    return ring_subtract(ring, ring->supply, ring->consume);
24933294Sminshall 	}
25032379Sminshall     } else {
25133294Sminshall 	if (ring->mark < ring->consume) {
25233294Sminshall 	    return ring_subtract(ring, ring->top, ring->consume);
25333294Sminshall 	} else {	/* Else, distance to mark */
25433294Sminshall 	    return ring_subtract(ring, ring->mark, ring->consume);
25533294Sminshall 	}
25632379Sminshall     }
25732379Sminshall }
25832379Sminshall 
25932379Sminshall /*
26032528Sminshall  * Move data into the "supply" portion of of the ring buffer.
26132379Sminshall  */
262*46808Sdab     void
26332528Sminshall ring_supply_data(ring, buffer, count)
264*46808Sdab     Ring *ring;
265*46808Sdab     unsigned char *buffer;
266*46808Sdab     int count;
26732379Sminshall {
26832379Sminshall     int i;
26932379Sminshall 
27032379Sminshall     while (count) {
27132381Sminshall 	i = MIN(count, ring_empty_consecutive(ring));
27232528Sminshall 	memcpy(ring->supply, buffer, i);
27332528Sminshall 	ring_supplied(ring, i);
27432379Sminshall 	count -= i;
27532379Sminshall 	buffer += i;
27632379Sminshall     }
27732379Sminshall }
27832379Sminshall 
27944360Sborman #ifdef notdef
28032379Sminshall 
28132379Sminshall /*
28232528Sminshall  * Move data from the "consume" portion of the ring buffer
28332379Sminshall  */
284*46808Sdab     void
28532528Sminshall ring_consume_data(ring, buffer, count)
286*46808Sdab     Ring *ring;
287*46808Sdab     unsigned char *buffer;
288*46808Sdab     int count;
28932379Sminshall {
29032379Sminshall     int i;
29132379Sminshall 
29232379Sminshall     while (count) {
29332528Sminshall 	i = MIN(count, ring_full_consecutive(ring));
29432528Sminshall 	memcpy(buffer, ring->consume, i);
29532528Sminshall 	ring_consumed(ring, i);
29632379Sminshall 	count -= i;
29732379Sminshall 	buffer += i;
29832379Sminshall     }
29932379Sminshall }
30044360Sborman #endif
301*46808Sdab 
302*46808Sdab #if	defined(ENCRYPT)
303*46808Sdab     void
304*46808Sdab ring_encrypt(ring, encryptor)
305*46808Sdab     Ring *ring;
306*46808Sdab     void (*encryptor)();
307*46808Sdab {
308*46808Sdab     unsigned char *s, *c;
309*46808Sdab 
310*46808Sdab     if (ring_empty(ring) || ring->clearto == ring->supply)
311*46808Sdab 	return;
312*46808Sdab 
313*46808Sdab     if (!(c = ring->clearto))
314*46808Sdab 	c = ring->consume;
315*46808Sdab 
316*46808Sdab     s = ring->supply;
317*46808Sdab 
318*46808Sdab     if (s <= c) {
319*46808Sdab 	(*encryptor)(c, ring->top - c);
320*46808Sdab 	(*encryptor)(ring->bottom, s - ring->bottom);
321*46808Sdab     } else
322*46808Sdab 	(*encryptor)(c, s - c);
323*46808Sdab 
324*46808Sdab     ring->clearto = ring->supply;
325*46808Sdab }
326*46808Sdab 
327*46808Sdab     void
328*46808Sdab ring_clearto(ring)
329*46808Sdab     Ring *ring;
330*46808Sdab {
331*46808Sdab     if (!ring_empty(ring))
332*46808Sdab 	ring->clearto = ring->supply;
333*46808Sdab     else
334*46808Sdab 	ring->clearto = 0;
335*46808Sdab }
336*46808Sdab #endif
337