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