132379Sminshall /*
262311Sbostic * Copyright (c) 1988, 1993
362311Sbostic * The Regents of the University of California. All rights reserved.
433685Sbostic *
542770Sbostic * %sccs.include.redist.c%
633685Sbostic */
733685Sbostic
833685Sbostic #ifndef lint
9*69785Sdab static char sccsid[] = "@(#)ring.c 8.2 (Berkeley) 05/30/95";
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
ring_init(ring,buffer,count)7646808Sdab ring_init(ring, buffer, count)
7732381Sminshall Ring *ring;
7846808Sdab unsigned char *buffer;
7946808Sdab 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
8960149Sdab #ifdef ENCRYPTION
9046808Sdab ring->clearto = 0;
9160149Sdab #endif /* ENCRYPTION */
9246808Sdab
9332381Sminshall return 1;
9432381Sminshall }
9532381Sminshall
9633294Sminshall /* Mark routines */
9733294Sminshall
9832379Sminshall /*
9933294Sminshall * Mark the most recently supplied byte.
10033294Sminshall */
10133294Sminshall
10246808Sdab void
ring_mark(ring)10333294Sminshall ring_mark(ring)
10446808Sdab 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
11346808Sdab int
ring_at_mark(ring)11433294Sminshall ring_at_mark(ring)
11546808Sdab 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
12846808Sdab void
ring_clear_mark(ring)12933294Sminshall ring_clear_mark(ring)
13046808Sdab Ring *ring;
13133294Sminshall {
13233294Sminshall ring->mark = 0;
13333294Sminshall }
13433294Sminshall
13533294Sminshall /*
13632379Sminshall * Add characters from current segment to ring buffer.
13732379Sminshall */
13846808Sdab void
ring_supplied(ring,count)13932528Sminshall ring_supplied(ring, count)
14046808Sdab Ring *ring;
14146808Sdab 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 */
15046808Sdab void
ring_consumed(ring,count)15132528Sminshall ring_consumed(ring, count)
15246808Sdab Ring *ring;
15346808Sdab 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 }
16260149Sdab #ifdef ENCRYPTION
16346808Sdab if (ring->consume < ring->clearto &&
16446808Sdab ring->clearto <= ring->consume + count)
16546808Sdab ring->clearto = 0;
16646808Sdab else if (ring->consume + count > ring->top &&
16746808Sdab ring->bottom <= ring->clearto &&
16846808Sdab ring->bottom + ((ring->consume + count) - ring->top))
16946808Sdab ring->clearto = 0;
17060149Sdab #endif /* ENCRYPTION */
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 */
18746808Sdab int
ring_empty_count(ring)18832379Sminshall ring_empty_count(ring)
18946808Sdab 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 */
19946808Sdab int
ring_empty_consecutive(ring)20032379Sminshall ring_empty_consecutive(ring)
20146808Sdab 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
22146808Sdab int
ring_full_count(ring)22232528Sminshall ring_full_count(ring)
22346808Sdab 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 */
24046808Sdab int
ring_full_consecutive(ring)24132528Sminshall ring_full_consecutive(ring)
24246808Sdab 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 */
26246808Sdab void
ring_supply_data(ring,buffer,count)26332528Sminshall ring_supply_data(ring, buffer, count)
26446808Sdab Ring *ring;
26546808Sdab unsigned char *buffer;
26646808Sdab int count;
26732379Sminshall {
26832379Sminshall int i;
26932379Sminshall
27032379Sminshall while (count) {
27132381Sminshall i = MIN(count, ring_empty_consecutive(ring));
272*69785Sdab memmove(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 */
28446808Sdab void
ring_consume_data(ring,buffer,count)28532528Sminshall ring_consume_data(ring, buffer, count)
28646808Sdab Ring *ring;
28746808Sdab unsigned char *buffer;
28846808Sdab int count;
28932379Sminshall {
29032379Sminshall int i;
29132379Sminshall
29232379Sminshall while (count) {
29332528Sminshall i = MIN(count, ring_full_consecutive(ring));
294*69785Sdab memmove(buffer, ring->consume, i);
29532528Sminshall ring_consumed(ring, i);
29632379Sminshall count -= i;
29732379Sminshall buffer += i;
29832379Sminshall }
29932379Sminshall }
30044360Sborman #endif
30146808Sdab
30260149Sdab #ifdef ENCRYPTION
30346808Sdab void
ring_encrypt(ring,encryptor)30446808Sdab ring_encrypt(ring, encryptor)
30546808Sdab Ring *ring;
30646808Sdab void (*encryptor)();
30746808Sdab {
30846808Sdab unsigned char *s, *c;
30946808Sdab
31046808Sdab if (ring_empty(ring) || ring->clearto == ring->supply)
31146808Sdab return;
31246808Sdab
31346808Sdab if (!(c = ring->clearto))
31446808Sdab c = ring->consume;
31546808Sdab
31646808Sdab s = ring->supply;
31746808Sdab
31846808Sdab if (s <= c) {
31946808Sdab (*encryptor)(c, ring->top - c);
32046808Sdab (*encryptor)(ring->bottom, s - ring->bottom);
32146808Sdab } else
32246808Sdab (*encryptor)(c, s - c);
32346808Sdab
32446808Sdab ring->clearto = ring->supply;
32546808Sdab }
32646808Sdab
32746808Sdab void
ring_clearto(ring)32846808Sdab ring_clearto(ring)
32946808Sdab Ring *ring;
33046808Sdab {
33146808Sdab if (!ring_empty(ring))
33246808Sdab ring->clearto = ring->supply;
33346808Sdab else
33446808Sdab ring->clearto = 0;
33546808Sdab }
33660149Sdab #endif /* ENCRYPTION */
337