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