home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / gnunet10.zip / source / telnet / ring.c < prev    next >
C/C++ Source or Header  |  1996-02-12  |  8KB  |  363 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. #include    <stdio.h>
  50. #include    <errno.h>
  51.  
  52. #ifdef    size_t
  53. #undef    size_t
  54. #endif
  55.  
  56. #include    <sys/types.h>
  57. #ifndef    FILIO_H
  58. #include    <sys/ioctl.h>
  59. #endif
  60. #include    <sys/socket.h>
  61.  
  62. #include    "ring.h"
  63. #include    "general.h"
  64.  
  65. /* Internal macros */
  66.  
  67. #if    !defined(MIN)
  68. #define    MIN(a,b)    (((a)<(b))? (a):(b))
  69. #endif    /* !defined(MIN) */
  70.  
  71. #define    ring_subtract(d,a,b)    (((a)-(b) >= 0)? \
  72.                     (a)-(b): (((a)-(b))+(d)->size))
  73.  
  74. #define    ring_increment(d,a,c)    (((a)+(c) < (d)->top)? \
  75.                     (a)+(c) : (((a)+(c))-(d)->size))
  76.  
  77. #define    ring_decrement(d,a,c)    (((a)-(c) >= (d)->bottom)? \
  78.                     (a)-(c) : (((a)-(c))-(d)->size))
  79.  
  80.  
  81. /*
  82.  * The following is a clock, used to determine full, empty, etc.
  83.  *
  84.  * There is some trickiness here.  Since the ring buffers are initialized
  85.  * to ZERO on allocation, we need to make sure, when interpreting the
  86.  * clock, that when the times are EQUAL, then the buffer is FULL.
  87.  */
  88. static u_long ring_clock = 0;
  89.  
  90.  
  91. #define    ring_empty(d) (((d)->consume == (d)->supply) && \
  92.                 ((d)->consumetime >= (d)->supplytime))
  93. #define    ring_full(d) (((d)->supply == (d)->consume) && \
  94.                 ((d)->supplytime > (d)->consumetime))
  95.  
  96.  
  97.  
  98.  
  99.  
  100. /* Buffer state transition routines */
  101.  
  102.     ring_init(ring, buffer, count)
  103. Ring *ring;
  104.     unsigned char *buffer;
  105.     int count;
  106. {
  107.     memset((char *)ring, 0, sizeof *ring);
  108.  
  109.     ring->size = count;
  110.  
  111.     ring->supply = ring->consume = ring->bottom = buffer;
  112.  
  113.     ring->top = ring->bottom+ring->size;
  114.  
  115. #ifdef    ENCRYPTION
  116.     ring->clearto = 0;
  117. #endif    /* ENCRYPTION */
  118.  
  119.     return 1;
  120. }
  121.  
  122. /* Mark routines */
  123.  
  124. /*
  125.  * Mark the most recently supplied byte.
  126.  */
  127.  
  128.     void
  129. ring_mark(ring)
  130.     Ring *ring;
  131. {
  132.     ring->mark = ring_decrement(ring, ring->supply, 1);
  133. }
  134.  
  135. /*
  136.  * Is the ring pointing to the mark?
  137.  */
  138.  
  139.     int
  140. ring_at_mark(ring)
  141.     Ring *ring;
  142. {
  143.     if (ring->mark == ring->consume) {
  144.     return 1;
  145.     } else {
  146.     return 0;
  147.     }
  148. }
  149.  
  150. /*
  151.  * Clear any mark set on the ring.
  152.  */
  153.  
  154.     void
  155. ring_clear_mark(ring)
  156.     Ring *ring;
  157. {
  158.     ring->mark = 0;
  159. }
  160.  
  161. /*
  162.  * Add characters from current segment to ring buffer.
  163.  */
  164.     void
  165. ring_supplied(ring, count)
  166.     Ring *ring;
  167.     int count;
  168. {
  169.     ring->supply = ring_increment(ring, ring->supply, count);
  170.     ring->supplytime = ++ring_clock;
  171. }
  172.  
  173. /*
  174.  * We have just consumed "c" bytes.
  175.  */
  176.     void
  177. ring_consumed(ring, count)
  178.     Ring *ring;
  179.     int count;
  180. {
  181.     if (count == 0)    /* don't update anything */
  182.     return;
  183.  
  184.     if (ring->mark &&
  185.         (ring_subtract(ring, ring->mark, ring->consume) < count)) {
  186.     ring->mark = 0;
  187.     }
  188. #ifdef    ENCRYPTION
  189.     if (ring->consume < ring->clearto &&
  190.         ring->clearto <= ring->consume + count)
  191.     ring->clearto = 0;
  192.     else if (ring->consume + count > ring->top &&
  193.         ring->bottom <= ring->clearto &&
  194.         ring->bottom + ((ring->consume + count) - ring->top))
  195.     ring->clearto = 0;
  196. #endif    /* ENCRYPTION */
  197.     ring->consume = ring_increment(ring, ring->consume, count);
  198.     ring->consumetime = ++ring_clock;
  199.     /*
  200.      * Try to encourage "ring_empty_consecutive()" to be large.
  201.      */
  202.     if (ring_empty(ring)) {
  203.     ring->consume = ring->supply = ring->bottom;
  204.     }
  205. }
  206.  
  207.  
  208.  
  209. /* Buffer state query routines */
  210.  
  211.  
  212. /* Number of bytes that may be supplied */
  213.     int
  214. ring_empty_count(ring)
  215.     Ring *ring;
  216. {
  217.     if (ring_empty(ring)) {    /* if empty */
  218.         return ring->size;
  219.     } else {
  220.     return ring_subtract(ring, ring->consume, ring->supply);
  221.     }
  222. }
  223.  
  224. /* number of CONSECUTIVE bytes that may be supplied */
  225.     int
  226. ring_empty_consecutive(ring)
  227.     Ring *ring;
  228. {
  229.     if ((ring->consume < ring->supply) || ring_empty(ring)) {
  230.                 /*
  231.                  * if consume is "below" supply, or empty, then
  232.                  * return distance to the top
  233.                  */
  234.     return ring_subtract(ring, ring->top, ring->supply);
  235.     } else {
  236.                     /*
  237.                      * else, return what we may.
  238.                      */
  239.     return ring_subtract(ring, ring->consume, ring->supply);
  240.     }
  241. }
  242.  
  243. /* Return the number of bytes that are available for consuming
  244.  * (but don't give more than enough to get to cross over set mark)
  245.  */
  246.  
  247.     int
  248. ring_full_count(ring)
  249.     Ring *ring;
  250. {
  251.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  252.     if (ring_full(ring)) {
  253.         return ring->size;    /* nothing consumed, but full */
  254.     } else {
  255.         return ring_subtract(ring, ring->supply, ring->consume);
  256.     }
  257.     } else {
  258.     return ring_subtract(ring, ring->mark, ring->consume);
  259.     }
  260. }
  261.  
  262. /*
  263.  * Return the number of CONSECUTIVE bytes available for consuming.
  264.  * However, don't return more than enough to cross over set mark.
  265.  */
  266.     int
  267. ring_full_consecutive(ring)
  268.     Ring *ring;
  269. {
  270.     if ((ring->mark == 0) || (ring->mark == ring->consume)) {
  271.     if ((ring->supply < ring->consume) || ring_full(ring)) {
  272.         return ring_subtract(ring, ring->top, ring->consume);
  273.     } else {
  274.         return ring_subtract(ring, ring->supply, ring->consume);
  275.     }
  276.     } else {
  277.     if (ring->mark < ring->consume) {
  278.         return ring_subtract(ring, ring->top, ring->consume);
  279.     } else {    /* Else, distance to mark */
  280.         return ring_subtract(ring, ring->mark, ring->consume);
  281.     }
  282.     }
  283. }
  284.  
  285. /*
  286.  * Move data into the "supply" portion of of the ring buffer.
  287.  */
  288.     void
  289. ring_supply_data(ring, buffer, count)
  290.     Ring *ring;
  291.     unsigned char *buffer;
  292.     int count;
  293. {
  294.     int i;
  295.  
  296.     while (count) {
  297.     i = MIN(count, ring_empty_consecutive(ring));
  298.     memmove(ring->supply, buffer, i);
  299.     ring_supplied(ring, i);
  300.     count -= i;
  301.     buffer += i;
  302.     }
  303. }
  304.  
  305. #ifdef notdef
  306.  
  307. /*
  308.  * Move data from the "consume" portion of the ring buffer
  309.  */
  310.     void
  311. ring_consume_data(ring, buffer, count)
  312.     Ring *ring;
  313.     unsigned char *buffer;
  314.     int count;
  315. {
  316.     int i;
  317.  
  318.     while (count) {
  319.     i = MIN(count, ring_full_consecutive(ring));
  320.     memmove(buffer, ring->consume, i);
  321.     ring_consumed(ring, i);
  322.     count -= i;
  323.     buffer += i;
  324.     }
  325. }
  326. #endif
  327.  
  328. #ifdef    ENCRYPTION
  329.     void
  330. ring_encrypt(ring, encryptor)
  331.     Ring *ring;
  332.     void (*encryptor)();
  333. {
  334.     unsigned char *s, *c;
  335.  
  336.     if (ring_empty(ring) || ring->clearto == ring->supply)
  337.     return;
  338.  
  339.     if (!(c = ring->clearto))
  340.     c = ring->consume;
  341.  
  342.     s = ring->supply;
  343.  
  344.     if (s <= c) {
  345.     (*encryptor)(c, ring->top - c);
  346.     (*encryptor)(ring->bottom, s - ring->bottom);
  347.     } else
  348.     (*encryptor)(c, s - c);
  349.  
  350.     ring->clearto = ring->supply;
  351. }
  352.  
  353.     void
  354. ring_clearto(ring)
  355.     Ring *ring;
  356. {
  357.     if (!ring_empty(ring))
  358.     ring->clearto = ring->supply;
  359.     else
  360.     ring->clearto = 0;
  361. }
  362. #endif    /* ENCRYPTION */
  363.