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