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