1 : /*
2 : * Copyright (c) 2002, 2003 Niels Provos <provos@citi.umich.edu>
3 : * 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. The name of the author may not be used to endorse or promote products
14 : * derived from this software without specific prior written permission.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 : * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 : */
27 :
28 : #ifdef HAVE_CONFIG_H
29 : #include "config.h"
30 : #endif
31 :
32 : #ifdef WIN32
33 : #include <winsock2.h>
34 : #include <windows.h>
35 : #endif
36 :
37 : #ifdef HAVE_VASPRINTF
38 : /* If we have vasprintf, we need to define this before we include stdio.h. */
39 : #define _GNU_SOURCE
40 : #endif
41 :
42 : #include <sys/types.h>
43 :
44 : #ifdef HAVE_SYS_TIME_H
45 : #include <sys/time.h>
46 : #endif
47 :
48 : #ifdef HAVE_SYS_IOCTL_H
49 : #include <sys/ioctl.h>
50 : #endif
51 :
52 : #include <assert.h>
53 : #include <errno.h>
54 : #include <stdio.h>
55 : #include <stdlib.h>
56 : #include <string.h>
57 : #ifdef HAVE_STDARG_H
58 : #include <stdarg.h>
59 : #endif
60 : #ifdef HAVE_UNISTD_H
61 : #include <unistd.h>
62 : #endif
63 :
64 : #include "event.h"
65 : #include "config.h"
66 : #include "evutil.h"
67 :
68 : struct evbuffer *
69 0 : evbuffer_new(void)
70 : {
71 : struct evbuffer *buffer;
72 :
73 0 : buffer = calloc(1, sizeof(struct evbuffer));
74 :
75 0 : return (buffer);
76 : }
77 :
78 : void
79 0 : evbuffer_free(struct evbuffer *buffer)
80 : {
81 0 : if (buffer->orig_buffer != NULL)
82 0 : free(buffer->orig_buffer);
83 0 : free(buffer);
84 0 : }
85 :
86 : /*
87 : * This is a destructive add. The data from one buffer moves into
88 : * the other buffer.
89 : */
90 :
91 : #define SWAP(x,y) do { \
92 : (x)->buffer = (y)->buffer; \
93 : (x)->orig_buffer = (y)->orig_buffer; \
94 : (x)->misalign = (y)->misalign; \
95 : (x)->totallen = (y)->totallen; \
96 : (x)->off = (y)->off; \
97 : } while (0)
98 :
99 : int
100 0 : evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf)
101 : {
102 : int res;
103 :
104 : /* Short cut for better performance */
105 0 : if (outbuf->off == 0) {
106 : struct evbuffer tmp;
107 0 : size_t oldoff = inbuf->off;
108 :
109 : /* Swap them directly */
110 0 : SWAP(&tmp, outbuf);
111 0 : SWAP(outbuf, inbuf);
112 0 : SWAP(inbuf, &tmp);
113 :
114 : /*
115 : * Optimization comes with a price; we need to notify the
116 : * buffer if necessary of the changes. oldoff is the amount
117 : * of data that we transfered from inbuf to outbuf
118 : */
119 0 : if (inbuf->off != oldoff && inbuf->cb != NULL)
120 0 : (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg);
121 0 : if (oldoff && outbuf->cb != NULL)
122 0 : (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg);
123 :
124 0 : return (0);
125 : }
126 :
127 0 : res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off);
128 0 : if (res == 0) {
129 : /* We drain the input buffer on success */
130 0 : evbuffer_drain(inbuf, inbuf->off);
131 : }
132 :
133 0 : return (res);
134 : }
135 :
136 : int
137 0 : evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap)
138 : {
139 : char *buffer;
140 : size_t space;
141 0 : size_t oldoff = buf->off;
142 : int sz;
143 : va_list aq;
144 :
145 : /* make sure that at least some space is available */
146 0 : evbuffer_expand(buf, 64);
147 : for (;;) {
148 0 : size_t used = buf->misalign + buf->off;
149 0 : buffer = (char *)buf->buffer + buf->off;
150 0 : assert(buf->totallen >= used);
151 0 : space = buf->totallen - used;
152 :
153 : #ifndef va_copy
154 : #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list))
155 : #endif
156 0 : va_copy(aq, ap);
157 :
158 0 : sz = evutil_vsnprintf(buffer, space, fmt, aq);
159 :
160 0 : va_end(aq);
161 :
162 0 : if (sz < 0)
163 0 : return (-1);
164 0 : if (sz < space) {
165 0 : buf->off += sz;
166 0 : if (buf->cb != NULL)
167 0 : (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
168 0 : return (sz);
169 : }
170 0 : if (evbuffer_expand(buf, sz + 1) == -1)
171 0 : return (-1);
172 :
173 0 : }
174 : /* NOTREACHED */
175 : }
176 :
177 : int
178 0 : evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...)
179 : {
180 0 : int res = -1;
181 : va_list ap;
182 :
183 0 : va_start(ap, fmt);
184 0 : res = evbuffer_add_vprintf(buf, fmt, ap);
185 0 : va_end(ap);
186 :
187 0 : return (res);
188 : }
189 :
190 : /* Reads data from an event buffer and drains the bytes read */
191 :
192 : int
193 0 : evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen)
194 : {
195 0 : size_t nread = datlen;
196 0 : if (nread >= buf->off)
197 0 : nread = buf->off;
198 :
199 0 : memcpy(data, buf->buffer, nread);
200 0 : evbuffer_drain(buf, nread);
201 :
202 0 : return (nread);
203 : }
204 :
205 : /*
206 : * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'.
207 : * The returned buffer needs to be freed by the called.
208 : */
209 :
210 : char *
211 0 : evbuffer_readline(struct evbuffer *buffer)
212 : {
213 0 : u_char *data = EVBUFFER_DATA(buffer);
214 0 : size_t len = EVBUFFER_LENGTH(buffer);
215 : char *line;
216 : unsigned int i;
217 :
218 0 : for (i = 0; i < len; i++) {
219 0 : if (data[i] == '\r' || data[i] == '\n')
220 : break;
221 : }
222 :
223 0 : if (i == len)
224 0 : return (NULL);
225 :
226 0 : if ((line = malloc(i + 1)) == NULL) {
227 0 : fprintf(stderr, "%s: out of memory\n", __func__);
228 0 : evbuffer_drain(buffer, i);
229 0 : return (NULL);
230 : }
231 :
232 0 : memcpy(line, data, i);
233 0 : line[i] = '\0';
234 :
235 : /*
236 : * Some protocols terminate a line with '\r\n', so check for
237 : * that, too.
238 : */
239 0 : if ( i < len - 1 ) {
240 0 : char fch = data[i], sch = data[i+1];
241 :
242 : /* Drain one more character if needed */
243 0 : if ( (sch == '\r' || sch == '\n') && sch != fch )
244 0 : i += 1;
245 : }
246 :
247 0 : evbuffer_drain(buffer, i + 1);
248 :
249 0 : return (line);
250 : }
251 :
252 : /* Adds data to an event buffer */
253 :
254 : static void
255 0 : evbuffer_align(struct evbuffer *buf)
256 : {
257 0 : memmove(buf->orig_buffer, buf->buffer, buf->off);
258 0 : buf->buffer = buf->orig_buffer;
259 0 : buf->misalign = 0;
260 0 : }
261 :
262 : /* Expands the available space in the event buffer to at least datlen */
263 :
264 : int
265 0 : evbuffer_expand(struct evbuffer *buf, size_t datlen)
266 : {
267 0 : size_t need = buf->misalign + buf->off + datlen;
268 :
269 : /* If we can fit all the data, then we don't have to do anything */
270 0 : if (buf->totallen >= need)
271 0 : return (0);
272 :
273 : /*
274 : * If the misalignment fulfills our data needs, we just force an
275 : * alignment to happen. Afterwards, we have enough space.
276 : */
277 0 : if (buf->misalign >= datlen) {
278 0 : evbuffer_align(buf);
279 : } else {
280 : void *newbuf;
281 0 : size_t length = buf->totallen;
282 :
283 0 : if (length < 256)
284 0 : length = 256;
285 0 : while (length < need)
286 0 : length <<= 1;
287 :
288 0 : if (buf->orig_buffer != buf->buffer)
289 0 : evbuffer_align(buf);
290 0 : if ((newbuf = realloc(buf->buffer, length)) == NULL)
291 0 : return (-1);
292 :
293 0 : buf->orig_buffer = buf->buffer = newbuf;
294 0 : buf->totallen = length;
295 : }
296 :
297 0 : return (0);
298 : }
299 :
300 : int
301 0 : evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen)
302 : {
303 0 : size_t need = buf->misalign + buf->off + datlen;
304 0 : size_t oldoff = buf->off;
305 :
306 0 : if (buf->totallen < need) {
307 0 : if (evbuffer_expand(buf, datlen) == -1)
308 0 : return (-1);
309 : }
310 :
311 0 : memcpy(buf->buffer + buf->off, data, datlen);
312 0 : buf->off += datlen;
313 :
314 0 : if (datlen && buf->cb != NULL)
315 0 : (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
316 :
317 0 : return (0);
318 : }
319 :
320 : void
321 0 : evbuffer_drain(struct evbuffer *buf, size_t len)
322 : {
323 0 : size_t oldoff = buf->off;
324 :
325 0 : if (len >= buf->off) {
326 0 : buf->off = 0;
327 0 : buf->buffer = buf->orig_buffer;
328 0 : buf->misalign = 0;
329 0 : goto done;
330 : }
331 :
332 0 : buf->buffer += len;
333 0 : buf->misalign += len;
334 :
335 0 : buf->off -= len;
336 :
337 : done:
338 : /* Tell someone about changes in this buffer */
339 0 : if (buf->off != oldoff && buf->cb != NULL)
340 0 : (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
341 :
342 0 : }
343 :
344 : /*
345 : * Reads data from a file descriptor into a buffer.
346 : */
347 :
348 : #define EVBUFFER_MAX_READ 4096
349 :
350 : int
351 0 : evbuffer_read(struct evbuffer *buf, int fd, int howmuch)
352 : {
353 : u_char *p;
354 0 : size_t oldoff = buf->off;
355 0 : int n = EVBUFFER_MAX_READ;
356 :
357 : #if defined(FIONREAD)
358 : #ifdef WIN32
359 : long lng = n;
360 : if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) == 0) {
361 : #else
362 0 : if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) {
363 : #endif
364 0 : n = EVBUFFER_MAX_READ;
365 0 : } else if (n > EVBUFFER_MAX_READ && n > howmuch) {
366 : /*
367 : * It's possible that a lot of data is available for
368 : * reading. We do not want to exhaust resources
369 : * before the reader has a chance to do something
370 : * about it. If the reader does not tell us how much
371 : * data we should read, we artifically limit it.
372 : */
373 0 : if (n > buf->totallen << 2)
374 0 : n = buf->totallen << 2;
375 0 : if (n < EVBUFFER_MAX_READ)
376 0 : n = EVBUFFER_MAX_READ;
377 : }
378 : #endif
379 0 : if (howmuch < 0 || howmuch > n)
380 0 : howmuch = n;
381 :
382 : /* If we don't have FIONREAD, we might waste some space here */
383 0 : if (evbuffer_expand(buf, howmuch) == -1)
384 0 : return (-1);
385 :
386 : /* We can append new data at this point */
387 0 : p = buf->buffer + buf->off;
388 :
389 : #ifndef WIN32
390 0 : n = read(fd, p, howmuch);
391 : #else
392 : n = recv(fd, p, howmuch, 0);
393 : #endif
394 0 : if (n == -1)
395 0 : return (-1);
396 0 : if (n == 0)
397 0 : return (0);
398 :
399 0 : buf->off += n;
400 :
401 : /* Tell someone about changes in this buffer */
402 0 : if (buf->off != oldoff && buf->cb != NULL)
403 0 : (*buf->cb)(buf, oldoff, buf->off, buf->cbarg);
404 :
405 0 : return (n);
406 : }
407 :
408 : int
409 0 : evbuffer_write(struct evbuffer *buffer, int fd)
410 : {
411 : int n;
412 :
413 : #ifndef WIN32
414 0 : n = write(fd, buffer->buffer, buffer->off);
415 : #else
416 : n = send(fd, buffer->buffer, buffer->off, 0);
417 : #endif
418 0 : if (n == -1)
419 0 : return (-1);
420 0 : if (n == 0)
421 0 : return (0);
422 0 : evbuffer_drain(buffer, n);
423 :
424 0 : return (n);
425 : }
426 :
427 : u_char *
428 0 : evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len)
429 : {
430 0 : u_char *search = buffer->buffer, *end = search + buffer->off;
431 : u_char *p;
432 :
433 0 : while (search < end &&
434 0 : (p = memchr(search, *what, end - search)) != NULL) {
435 0 : if (p + len > end)
436 0 : break;
437 0 : if (memcmp(p, what, len) == 0)
438 0 : return (p);
439 0 : search = p + 1;
440 : }
441 :
442 0 : return (NULL);
443 : }
444 :
445 0 : void evbuffer_setcb(struct evbuffer *buffer,
446 : void (*cb)(struct evbuffer *, size_t, size_t, void *),
447 : void *cbarg)
448 : {
449 0 : buffer->cb = cb;
450 0 : buffer->cbarg = cbarg;
451 0 : }
|