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