OLD | NEW |
| (Empty) |
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 #include "./log.h" | |
68 | |
69 struct evbuffer * | |
70 evbuffer_new(void) | |
71 { | |
72 struct evbuffer *buffer; | |
73 | |
74 buffer = calloc(1, sizeof(struct evbuffer)); | |
75 | |
76 return (buffer); | |
77 } | |
78 | |
79 void | |
80 evbuffer_free(struct evbuffer *buffer) | |
81 { | |
82 if (buffer->orig_buffer != NULL) | |
83 free(buffer->orig_buffer); | |
84 free(buffer); | |
85 } | |
86 | |
87 /* | |
88 * This is a destructive add. The data from one buffer moves into | |
89 * the other buffer. | |
90 */ | |
91 | |
92 #define SWAP(x,y) do { \ | |
93 (x)->buffer = (y)->buffer; \ | |
94 (x)->orig_buffer = (y)->orig_buffer; \ | |
95 (x)->misalign = (y)->misalign; \ | |
96 (x)->totallen = (y)->totallen; \ | |
97 (x)->off = (y)->off; \ | |
98 } while (0) | |
99 | |
100 int | |
101 evbuffer_add_buffer(struct evbuffer *outbuf, struct evbuffer *inbuf) | |
102 { | |
103 int res; | |
104 | |
105 /* Short cut for better performance */ | |
106 if (outbuf->off == 0) { | |
107 struct evbuffer tmp; | |
108 size_t oldoff = inbuf->off; | |
109 | |
110 /* Swap them directly */ | |
111 SWAP(&tmp, outbuf); | |
112 SWAP(outbuf, inbuf); | |
113 SWAP(inbuf, &tmp); | |
114 | |
115 /* | |
116 * Optimization comes with a price; we need to notify the | |
117 * buffer if necessary of the changes. oldoff is the amount | |
118 * of data that we transfered from inbuf to outbuf | |
119 */ | |
120 if (inbuf->off != oldoff && inbuf->cb != NULL) | |
121 (*inbuf->cb)(inbuf, oldoff, inbuf->off, inbuf->cbarg); | |
122 if (oldoff && outbuf->cb != NULL) | |
123 (*outbuf->cb)(outbuf, 0, oldoff, outbuf->cbarg); | |
124 | |
125 return (0); | |
126 } | |
127 | |
128 res = evbuffer_add(outbuf, inbuf->buffer, inbuf->off); | |
129 if (res == 0) { | |
130 /* We drain the input buffer on success */ | |
131 evbuffer_drain(inbuf, inbuf->off); | |
132 } | |
133 | |
134 return (res); | |
135 } | |
136 | |
137 int | |
138 evbuffer_add_vprintf(struct evbuffer *buf, const char *fmt, va_list ap) | |
139 { | |
140 char *buffer; | |
141 size_t space; | |
142 size_t oldoff = buf->off; | |
143 int sz; | |
144 va_list aq; | |
145 | |
146 /* make sure that at least some space is available */ | |
147 if (evbuffer_expand(buf, 64) < 0) | |
148 return (-1); | |
149 for (;;) { | |
150 size_t used = buf->misalign + buf->off; | |
151 buffer = (char *)buf->buffer + buf->off; | |
152 assert(buf->totallen >= used); | |
153 space = buf->totallen - used; | |
154 | |
155 #ifndef va_copy | |
156 #define va_copy(dst, src) memcpy(&(dst), &(src), sizeof(va_list)) | |
157 #endif | |
158 va_copy(aq, ap); | |
159 | |
160 sz = evutil_vsnprintf(buffer, space, fmt, aq); | |
161 | |
162 va_end(aq); | |
163 | |
164 if (sz < 0) | |
165 return (-1); | |
166 if ((size_t)sz < space) { | |
167 buf->off += sz; | |
168 if (buf->cb != NULL) | |
169 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
170 return (sz); | |
171 } | |
172 if (evbuffer_expand(buf, sz + 1) == -1) | |
173 return (-1); | |
174 | |
175 } | |
176 /* NOTREACHED */ | |
177 } | |
178 | |
179 int | |
180 evbuffer_add_printf(struct evbuffer *buf, const char *fmt, ...) | |
181 { | |
182 int res = -1; | |
183 va_list ap; | |
184 | |
185 va_start(ap, fmt); | |
186 res = evbuffer_add_vprintf(buf, fmt, ap); | |
187 va_end(ap); | |
188 | |
189 return (res); | |
190 } | |
191 | |
192 /* Reads data from an event buffer and drains the bytes read */ | |
193 | |
194 int | |
195 evbuffer_remove(struct evbuffer *buf, void *data, size_t datlen) | |
196 { | |
197 size_t nread = datlen; | |
198 if (nread >= buf->off) | |
199 nread = buf->off; | |
200 | |
201 memcpy(data, buf->buffer, nread); | |
202 evbuffer_drain(buf, nread); | |
203 | |
204 return (nread); | |
205 } | |
206 | |
207 /* | |
208 * Reads a line terminated by either '\r\n', '\n\r' or '\r' or '\n'. | |
209 * The returned buffer needs to be freed by the called. | |
210 */ | |
211 | |
212 char * | |
213 evbuffer_readline(struct evbuffer *buffer) | |
214 { | |
215 u_char *data = EVBUFFER_DATA(buffer); | |
216 size_t len = EVBUFFER_LENGTH(buffer); | |
217 char *line; | |
218 unsigned int i; | |
219 | |
220 for (i = 0; i < len; i++) { | |
221 if (data[i] == '\r' || data[i] == '\n') | |
222 break; | |
223 } | |
224 | |
225 if (i == len) | |
226 return (NULL); | |
227 | |
228 if ((line = malloc(i + 1)) == NULL) { | |
229 fprintf(stderr, "%s: out of memory\n", __func__); | |
230 return (NULL); | |
231 } | |
232 | |
233 memcpy(line, data, i); | |
234 line[i] = '\0'; | |
235 | |
236 /* | |
237 * Some protocols terminate a line with '\r\n', so check for | |
238 * that, too. | |
239 */ | |
240 if ( i < len - 1 ) { | |
241 char fch = data[i], sch = data[i+1]; | |
242 | |
243 /* Drain one more character if needed */ | |
244 if ( (sch == '\r' || sch == '\n') && sch != fch ) | |
245 i += 1; | |
246 } | |
247 | |
248 evbuffer_drain(buffer, i + 1); | |
249 | |
250 return (line); | |
251 } | |
252 | |
253 | |
254 char * | |
255 evbuffer_readln(struct evbuffer *buffer, size_t *n_read_out, | |
256 enum evbuffer_eol_style eol_style) | |
257 { | |
258 u_char *data = EVBUFFER_DATA(buffer); | |
259 u_char *start_of_eol, *end_of_eol; | |
260 size_t len = EVBUFFER_LENGTH(buffer); | |
261 char *line; | |
262 unsigned int i, n_to_copy, n_to_drain; | |
263 | |
264 if (n_read_out) | |
265 *n_read_out = 0; | |
266 | |
267 /* depending on eol_style, set start_of_eol to the first character | |
268 * in the newline, and end_of_eol to one after the last character. */ | |
269 switch (eol_style) { | |
270 case EVBUFFER_EOL_ANY: | |
271 for (i = 0; i < len; i++) { | |
272 if (data[i] == '\r' || data[i] == '\n') | |
273 break; | |
274 } | |
275 if (i == len) | |
276 return (NULL); | |
277 start_of_eol = data+i; | |
278 ++i; | |
279 for ( ; i < len; i++) { | |
280 if (data[i] != '\r' && data[i] != '\n') | |
281 break; | |
282 } | |
283 end_of_eol = data+i; | |
284 break; | |
285 case EVBUFFER_EOL_CRLF: | |
286 end_of_eol = memchr(data, '\n', len); | |
287 if (!end_of_eol) | |
288 return (NULL); | |
289 if (end_of_eol > data && *(end_of_eol-1) == '\r') | |
290 start_of_eol = end_of_eol - 1; | |
291 else | |
292 start_of_eol = end_of_eol; | |
293 end_of_eol++; /*point to one after the LF. */ | |
294 break; | |
295 case EVBUFFER_EOL_CRLF_STRICT: { | |
296 u_char *cp = data; | |
297 while ((cp = memchr(cp, '\r', len-(cp-data)))) { | |
298 if (cp < data+len-1 && *(cp+1) == '\n') | |
299 break; | |
300 if (++cp >= data+len) { | |
301 cp = NULL; | |
302 break; | |
303 } | |
304 } | |
305 if (!cp) | |
306 return (NULL); | |
307 start_of_eol = cp; | |
308 end_of_eol = cp+2; | |
309 break; | |
310 } | |
311 case EVBUFFER_EOL_LF: | |
312 start_of_eol = memchr(data, '\n', len); | |
313 if (!start_of_eol) | |
314 return (NULL); | |
315 end_of_eol = start_of_eol + 1; | |
316 break; | |
317 default: | |
318 return (NULL); | |
319 } | |
320 | |
321 n_to_copy = start_of_eol - data; | |
322 n_to_drain = end_of_eol - data; | |
323 | |
324 if ((line = malloc(n_to_copy+1)) == NULL) { | |
325 event_warn("%s: out of memory\n", __func__); | |
326 return (NULL); | |
327 } | |
328 | |
329 memcpy(line, data, n_to_copy); | |
330 line[n_to_copy] = '\0'; | |
331 | |
332 evbuffer_drain(buffer, n_to_drain); | |
333 if (n_read_out) | |
334 *n_read_out = (size_t)n_to_copy; | |
335 | |
336 return (line); | |
337 } | |
338 | |
339 /* Adds data to an event buffer */ | |
340 | |
341 static void | |
342 evbuffer_align(struct evbuffer *buf) | |
343 { | |
344 memmove(buf->orig_buffer, buf->buffer, buf->off); | |
345 buf->buffer = buf->orig_buffer; | |
346 buf->misalign = 0; | |
347 } | |
348 | |
349 #ifndef SIZE_MAX | |
350 #define SIZE_MAX ((size_t)-1) | |
351 #endif | |
352 | |
353 /* Expands the available space in the event buffer to at least datlen */ | |
354 | |
355 int | |
356 evbuffer_expand(struct evbuffer *buf, size_t datlen) | |
357 { | |
358 size_t used = buf->misalign + buf->off; | |
359 | |
360 assert(buf->totallen >= used); | |
361 | |
362 /* If we can fit all the data, then we don't have to do anything */ | |
363 if (buf->totallen - used >= datlen) | |
364 return (0); | |
365 /* If we would need to overflow to fit this much data, we can't | |
366 * do anything. */ | |
367 if (datlen > SIZE_MAX - buf->off) | |
368 return (-1); | |
369 | |
370 /* | |
371 * If the misalignment fulfills our data needs, we just force an | |
372 * alignment to happen. Afterwards, we have enough space. | |
373 */ | |
374 if (buf->totallen - buf->off >= datlen) { | |
375 evbuffer_align(buf); | |
376 } else { | |
377 void *newbuf; | |
378 size_t length = buf->totallen; | |
379 size_t need = buf->off + datlen; | |
380 | |
381 if (length < 256) | |
382 length = 256; | |
383 if (need < SIZE_MAX / 2) { | |
384 while (length < need) { | |
385 length <<= 1; | |
386 } | |
387 } else { | |
388 length = need; | |
389 } | |
390 | |
391 if (buf->orig_buffer != buf->buffer) | |
392 evbuffer_align(buf); | |
393 if ((newbuf = realloc(buf->buffer, length)) == NULL) | |
394 return (-1); | |
395 | |
396 buf->orig_buffer = buf->buffer = newbuf; | |
397 buf->totallen = length; | |
398 } | |
399 | |
400 return (0); | |
401 } | |
402 | |
403 int | |
404 evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen) | |
405 { | |
406 size_t used = buf->misalign + buf->off; | |
407 size_t oldoff = buf->off; | |
408 | |
409 if (buf->totallen - used < datlen) { | |
410 if (evbuffer_expand(buf, datlen) == -1) | |
411 return (-1); | |
412 } | |
413 | |
414 memcpy(buf->buffer + buf->off, data, datlen); | |
415 buf->off += datlen; | |
416 | |
417 if (datlen && buf->cb != NULL) | |
418 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
419 | |
420 return (0); | |
421 } | |
422 | |
423 void | |
424 evbuffer_drain(struct evbuffer *buf, size_t len) | |
425 { | |
426 size_t oldoff = buf->off; | |
427 | |
428 if (len >= buf->off) { | |
429 buf->off = 0; | |
430 buf->buffer = buf->orig_buffer; | |
431 buf->misalign = 0; | |
432 goto done; | |
433 } | |
434 | |
435 buf->buffer += len; | |
436 buf->misalign += len; | |
437 | |
438 buf->off -= len; | |
439 | |
440 done: | |
441 /* Tell someone about changes in this buffer */ | |
442 if (buf->off != oldoff && buf->cb != NULL) | |
443 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
444 | |
445 } | |
446 | |
447 /* | |
448 * Reads data from a file descriptor into a buffer. | |
449 */ | |
450 | |
451 #define EVBUFFER_MAX_READ 4096 | |
452 | |
453 int | |
454 evbuffer_read(struct evbuffer *buf, int fd, int howmuch) | |
455 { | |
456 u_char *p; | |
457 size_t oldoff = buf->off; | |
458 int n = EVBUFFER_MAX_READ; | |
459 | |
460 #if defined(FIONREAD) | |
461 #ifdef WIN32 | |
462 long lng = n; | |
463 if (ioctlsocket(fd, FIONREAD, &lng) == -1 || (n=lng) <= 0) { | |
464 #else | |
465 if (ioctl(fd, FIONREAD, &n) == -1 || n <= 0) { | |
466 #endif | |
467 n = EVBUFFER_MAX_READ; | |
468 } else if (n > EVBUFFER_MAX_READ && n > howmuch) { | |
469 /* | |
470 * It's possible that a lot of data is available for | |
471 * reading. We do not want to exhaust resources | |
472 * before the reader has a chance to do something | |
473 * about it. If the reader does not tell us how much | |
474 * data we should read, we artifically limit it. | |
475 */ | |
476 if ((size_t)n > buf->totallen << 2) | |
477 n = buf->totallen << 2; | |
478 if (n < EVBUFFER_MAX_READ) | |
479 n = EVBUFFER_MAX_READ; | |
480 } | |
481 #endif | |
482 if (howmuch < 0 || howmuch > n) | |
483 howmuch = n; | |
484 | |
485 /* If we don't have FIONREAD, we might waste some space here */ | |
486 if (evbuffer_expand(buf, howmuch) == -1) | |
487 return (-1); | |
488 | |
489 /* We can append new data at this point */ | |
490 p = buf->buffer + buf->off; | |
491 | |
492 #ifndef WIN32 | |
493 n = read(fd, p, howmuch); | |
494 #else | |
495 n = recv(fd, p, howmuch, 0); | |
496 #endif | |
497 if (n == -1) | |
498 return (-1); | |
499 if (n == 0) | |
500 return (0); | |
501 | |
502 buf->off += n; | |
503 | |
504 /* Tell someone about changes in this buffer */ | |
505 if (buf->off != oldoff && buf->cb != NULL) | |
506 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); | |
507 | |
508 return (n); | |
509 } | |
510 | |
511 int | |
512 evbuffer_write(struct evbuffer *buffer, int fd) | |
513 { | |
514 int n; | |
515 | |
516 #ifndef WIN32 | |
517 n = write(fd, buffer->buffer, buffer->off); | |
518 #else | |
519 n = send(fd, buffer->buffer, buffer->off, 0); | |
520 #endif | |
521 if (n == -1) | |
522 return (-1); | |
523 if (n == 0) | |
524 return (0); | |
525 evbuffer_drain(buffer, n); | |
526 | |
527 return (n); | |
528 } | |
529 | |
530 u_char * | |
531 evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len) | |
532 { | |
533 u_char *search = buffer->buffer, *end = search + buffer->off; | |
534 u_char *p; | |
535 | |
536 while (search < end && | |
537 (p = memchr(search, *what, end - search)) != NULL) { | |
538 if (p + len > end) | |
539 break; | |
540 if (memcmp(p, what, len) == 0) | |
541 return (p); | |
542 search = p + 1; | |
543 } | |
544 | |
545 return (NULL); | |
546 } | |
547 | |
548 void evbuffer_setcb(struct evbuffer *buffer, | |
549 void (*cb)(struct evbuffer *, size_t, size_t, void *), | |
550 void *cbarg) | |
551 { | |
552 buffer->cb = cb; | |
553 buffer->cbarg = cbarg; | |
554 } | |
OLD | NEW |