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*60149Sdab static char sccsid[] = "@(#)ring.c 5.4 (Berkeley) 05/20/93"; 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 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 89*60149Sdab #ifdef ENCRYPTION 9046808Sdab ring->clearto = 0; 91*60149Sdab #endif /* ENCRYPTION */ 9246808Sdab 9332381Sminshall return 1; 9432381Sminshall } 9532381Sminshall 9633294Sminshall /* Mark routines */ 9733294Sminshall 9832379Sminshall /* 9933294Sminshall * Mark the most recently supplied byte. 10033294Sminshall */ 10133294Sminshall 10246808Sdab void 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 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 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 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 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 } 162*60149Sdab #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; 170*60149Sdab #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 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 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 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 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 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)); 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 */ 28446808Sdab void 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)); 29432528Sminshall memcpy(buffer, ring->consume, i); 29532528Sminshall ring_consumed(ring, i); 29632379Sminshall count -= i; 29732379Sminshall buffer += i; 29832379Sminshall } 29932379Sminshall } 30044360Sborman #endif 30146808Sdab 302*60149Sdab #ifdef ENCRYPTION 30346808Sdab void 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 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 } 336*60149Sdab #endif /* ENCRYPTION */ 337