home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / inetutils-1.2-src.tgz / tar.out / fsf / inetutils / telnet / ring.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  367 lines

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