chiark / gitweb /
Build: Overhaul build system.
[mLib] / pkbuf.c
CommitLineData
436fddaa 1/* -*-c-*-
2 *
8656dc50 3 * $Id: pkbuf.c,v 1.7 2004/04/08 01:36:13 mdw Exp $
436fddaa 4 *
5 * Simple packet buffering
6 *
7 * (c) 2000 Straylight/Edgeware
8 */
9
d4efbcd9 10/*----- Licensing notice --------------------------------------------------*
436fddaa 11 *
12 * This file is part of the mLib utilities library.
13 *
14 * mLib is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
d4efbcd9 18 *
436fddaa 19 * mLib is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
d4efbcd9 23 *
436fddaa 24 * You should have received a copy of the GNU Library General Public
25 * License along with mLib; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
27 * MA 02111-1307, USA.
28 */
29
436fddaa 30/*----- Header files ------------------------------------------------------*/
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35
36#include "alloc.h"
37#include "arena.h"
38#include "pkbuf.h"
39
40/*----- Main code ---------------------------------------------------------*/
41
42/* --- @pkbuf_flush@ --- *
43 *
44 * Arguments: @pkbuf *pk@ = pointer to buffer block
45 * @octet *p@ = pointer to where to start searching
46 * @size_t len@ = length of new material added
47 *
48 * Returns: ---
49 *
50 * Use: Flushes any complete packets in a packet buffer. New
51 * material is assumed to have been added starting at @p@. If
52 * @p@ is null, then the scan starts at the beginning of the
53 * buffer, and the size of data already in the buffer is used in
54 * place of @len@.
55 *
56 * It is assumed that the buffer is initially enabled. You
57 * shouldn't be contributing data to a disabled buffer anyway.
58 * However, the buffer handler may at some point disable itself,
59 * and @pkbuf_flush@ can cope with this eventuality. Any
60 * pending data is left at the start of the buffer and can be
61 * flushed out by calling @pkbuf_flush(b, 0, 0)@ if the buffer
62 * is ever re-enabled.
63 */
64
65void pkbuf_flush(pkbuf *pk, octet *p, size_t len)
66{
67 size_t l;
f88f8d87 68 size_t o, keep;
436fddaa 69
3fd896a4 70 if (pk->f & PKBUF_CLOSE) {
71 pk->func(0, 0, pk, 0, pk->p);
72 return;
73 }
74
436fddaa 75 /* --- Initialize variables as necessary --- */
76
77 if (!p) {
78 p = pk->buf;
79 len = pk->len;
80 }
81 l = p + len - pk->buf;
f88f8d87 82 o = 0;
436fddaa 83
84 /* --- Now grind through any packets which have accumulated --- */
85
f88f8d87 86 pk->len = l;
87 while (l >= pk->want) {
436fddaa 88 size_t sz = pk->want;
89
90 /* --- Pass a packet to the user handler --- */
91
92 keep = 0;
f88f8d87 93 pk->func(pk->buf + o, sz, pk, &keep, pk->p);
436fddaa 94
95 /* --- Adjust all the pointers for the next packet --- */
96
97 sz -= keep;
f88f8d87 98 o += sz;
436fddaa 99 l -= sz;
100
101 /* --- Abort here if disabled --- */
102
103 if (!(pk->f & PKBUF_ENABLE))
104 break;
105 }
106
107 /* --- Shunt data around in the buffer --- */
108
f88f8d87 109 if (o > 0 && l != 0)
110 memmove(pk->buf, pk->buf + o, l);
436fddaa 111 pk->len = l;
112}
113
114/* --- @pkbuf_close@ --- *
115 *
116 * Arguments: @pkbuf *pk@ = pointer to buffer block
117 *
118 * Returns: ---
119 *
120 * Use: Informs the client that no more data is likely to arrive. If
121 * there is a partial packet in the buffer, it is discarded.
122 */
123
124void pkbuf_close(pkbuf *pk)
125{
126 if (pk->buf) {
436fddaa 127 x_free(pk->a, pk->buf);
128 pk->buf = 0;
129 }
3fd896a4 130 pk->f |= PKBUF_CLOSE;
436fddaa 131 if (pk->f & PKBUF_ENABLE)
132 pk->func(0, 0, pk, 0, pk->p);
133}
134
135/* --- @pkbuf_free@ --- *
136 *
137 * Arguments: @pkbuf *pk@ = pointer to buffer block
138 * @octet **p@ = output pointer to free space
139 *
140 * Returns: Free buffer size.
141 *
142 * Use: Returns the free portion of a packet buffer. Data can then
143 * be written to this portion, and split out into packets by
144 * calling @pkbuf_flush@. A buffer is allocated if none
145 * currently exists.
146 */
147
148size_t pkbuf_free(pkbuf *pk, octet **p)
149{
f88f8d87 150 if (!pk->buf)
436fddaa 151 pk->buf = x_alloc(pk->a, pk->sz);
436fddaa 152 *p = pk->buf + pk->len;
153 return (pk->sz - pk->len);
154}
155
156/* --- @pkbuf_snarf@ --- *
157 *
158 * Arguments: @pkbuf *pk@ = pointer to buffer block
159 * @const void *p@ = pointer to input data buffer
160 * @size_t sz@ = size of data in input buffer
161 *
162 * Returns: ---
163 *
164 * Use: Snarfs the data from the input buffer and spits it out as
165 * packets. This interface ignores the complexities of dealing
166 * with disablement: you should be using @pkbuf_free@ to
167 * contribute data if you want to cope with that.
168 */
169
170void pkbuf_snarf(pkbuf *pk, const void *p, size_t sz)
171{
172 const octet *pp = p;
173 while (sz && (pk->f & PKBUF_ENABLE)) {
174 size_t bsz;
175 octet *bp;
176
177 bsz = pkbuf_free(pk, &bp);
178 if (bsz > sz)
179 bsz = sz;
180 memcpy(bp, pp, bsz);
181 pkbuf_flush(pk, bp, bsz);
182 pp += bsz;
183 sz -= bsz;
184 }
185}
186
187/* --- @pkbuf_want@ --- *
188 *
189 * Arguments: @pkbuf *pk@ = pointer to buffer block
190 * @size_t want@ = how many octets wanted for next packet
191 *
192 * Returns: ---
193 *
194 * Use: Sets the desired size for the next packet to be read. If
195 * it's larger than the current buffer, the buffer is extended.
196 */
197
198void pkbuf_want(pkbuf *pk, size_t want)
199{
200 pk->want = want;
201 if (want > pk->sz) {
f88f8d87 202 do pk->sz <<= 1; while (want > pk->sz);
436fddaa 203 if (pk->buf) {
204 if (pk->len)
b5ea4de3 205 pk->buf = x_realloc(pk->a, pk->buf, pk->sz, pk->len);
436fddaa 206 else {
207 x_free(pk->a, pk->buf);
208 pk->buf = 0;
209 }
210 }
211 }
212}
213
214/* --- @pkbuf_init@ --- *
215 *
216 * Arguments: @pkbuf *pk@ = pointer to buffer block
0daaeb18 217 * @pkbuf *func@ = handler function
436fddaa 218 * @void *p@ = argument pointer for @func@
219 *
220 * Returns: ---
221 *
222 * Use: Initializes a packet buffer block. Any packets are passed to
223 * the provided function for handling.
224 */
225
0daaeb18 226void pkbuf_init(pkbuf *pk, pkbuf_func *func, void *p)
436fddaa 227{
228 pk->func = func;
229 pk->p = p;
230 pk->len = 0;
231 pk->f = PKBUF_ENABLE;
232 pk->buf = 0;
233 pk->sz = 256;
234 pk->want = 1;
235 pk->a = arena_global;
236}
237
238/* --- @pkbuf_destroy@ --- *
239 *
240 * Arguments: @pkbuf *pk@ = pointer to buffer block
241 *
242 * Returns: ---
243 *
244 * Use: Deallocates a line buffer and frees any resources it owned.
245 */
246
247void pkbuf_destroy(pkbuf *pk)
248{
249 if (pk->buf) {
250 x_free(pk->a, pk->buf);
251 pk->buf = 0;
252 }
253}
254
255/*----- That's all, folks -------------------------------------------------*/