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