1 /* $OpenBSD: buffer.c,v 1.15 2008/05/02 06:09:11 brad 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 evbuffer_drain(buffer, i); 229 return (NULL); 230 } 231 232 memcpy(line, data, i); 233 line[i] = '\0'; 234 235 /* 236 * Some protocols terminate a line with '\r\n', so check for 237 * that, too. 238 */ 239 if ( i < len - 1 ) { 240 char fch = data[i], sch = data[i+1]; 241 242 /* Drain one more character if needed */ 243 if ( (sch == '\r' || sch == '\n') && sch != fch ) 244 i += 1; 245 } 246 247 evbuffer_drain(buffer, i + 1); 248 249 return (line); 250 } 251 252 /* Adds data to an event buffer */ 253 254 static void 255 evbuffer_align(struct evbuffer *buf) 256 { 257 memmove(buf->orig_buffer, buf->buffer, buf->off); 258 buf->buffer = buf->orig_buffer; 259 buf->misalign = 0; 260 } 261 262 /* Expands the available space in the event buffer to at least datlen */ 263 264 int 265 evbuffer_expand(struct evbuffer *buf, size_t datlen) 266 { 267 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 if (buf->totallen >= need) 271 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 if (buf->misalign >= datlen) { 278 evbuffer_align(buf); 279 } else { 280 void *newbuf; 281 size_t length = buf->totallen; 282 283 if (length < 256) 284 length = 256; 285 while (length < need) 286 length <<= 1; 287 288 if (buf->orig_buffer != buf->buffer) 289 evbuffer_align(buf); 290 if ((newbuf = realloc(buf->buffer, length)) == NULL) 291 return (-1); 292 293 buf->orig_buffer = buf->buffer = newbuf; 294 buf->totallen = length; 295 } 296 297 return (0); 298 } 299 300 int 301 evbuffer_add(struct evbuffer *buf, const void *data, size_t datlen) 302 { 303 size_t need = buf->misalign + buf->off + datlen; 304 size_t oldoff = buf->off; 305 306 if (buf->totallen < need) { 307 if (evbuffer_expand(buf, datlen) == -1) 308 return (-1); 309 } 310 311 memcpy(buf->buffer + buf->off, data, datlen); 312 buf->off += datlen; 313 314 if (datlen && buf->cb != NULL) 315 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); 316 317 return (0); 318 } 319 320 void 321 evbuffer_drain(struct evbuffer *buf, size_t len) 322 { 323 size_t oldoff = buf->off; 324 325 if (len >= buf->off) { 326 buf->off = 0; 327 buf->buffer = buf->orig_buffer; 328 buf->misalign = 0; 329 goto done; 330 } 331 332 buf->buffer += len; 333 buf->misalign += len; 334 335 buf->off -= len; 336 337 done: 338 /* Tell someone about changes in this buffer */ 339 if (buf->off != oldoff && buf->cb != NULL) 340 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); 341 342 } 343 344 /* 345 * Reads data from a file descriptor into a buffer. 346 */ 347 348 #define EVBUFFER_MAX_READ 4096 349 350 int 351 evbuffer_read(struct evbuffer *buf, int fd, int howmuch) 352 { 353 u_char *p; 354 size_t oldoff = buf->off; 355 int n = EVBUFFER_MAX_READ; 356 #ifdef WIN32 357 DWORD dwBytesRead; 358 #endif 359 360 #ifdef FIONREAD 361 if (ioctl(fd, FIONREAD, &n) == -1 || n == 0) { 362 n = EVBUFFER_MAX_READ; 363 } else if (n > EVBUFFER_MAX_READ && n > howmuch) { 364 /* 365 * It's possible that a lot of data is available for 366 * reading. We do not want to exhaust resources 367 * before the reader has a chance to do something 368 * about it. If the reader does not tell us how much 369 * data we should read, we artifically limit it. 370 */ 371 if (n > buf->totallen << 2) 372 n = buf->totallen << 2; 373 if (n < EVBUFFER_MAX_READ) 374 n = EVBUFFER_MAX_READ; 375 } 376 #endif 377 if (howmuch < 0 || howmuch > n) 378 howmuch = n; 379 380 /* If we don't have FIONREAD, we might waste some space here */ 381 if (evbuffer_expand(buf, howmuch) == -1) 382 return (-1); 383 384 /* We can append new data at this point */ 385 p = buf->buffer + buf->off; 386 387 #ifndef WIN32 388 n = read(fd, p, howmuch); 389 if (n == -1) 390 return (-1); 391 if (n == 0) 392 return (0); 393 #else 394 n = ReadFile((HANDLE)fd, p, howmuch, &dwBytesRead, NULL); 395 if (n == 0) 396 return (-1); 397 if (dwBytesRead == 0) 398 return (0); 399 n = dwBytesRead; 400 #endif 401 402 buf->off += n; 403 404 /* Tell someone about changes in this buffer */ 405 if (buf->off != oldoff && buf->cb != NULL) 406 (*buf->cb)(buf, oldoff, buf->off, buf->cbarg); 407 408 return (n); 409 } 410 411 int 412 evbuffer_write(struct evbuffer *buffer, int fd) 413 { 414 int n; 415 #ifdef WIN32 416 DWORD dwBytesWritten; 417 #endif 418 419 #ifndef WIN32 420 n = write(fd, buffer->buffer, buffer->off); 421 if (n == -1) 422 return (-1); 423 if (n == 0) 424 return (0); 425 #else 426 n = WriteFile((HANDLE)fd, buffer->buffer, buffer->off, &dwBytesWritten, NULL); 427 if (n == 0) 428 return (-1); 429 if (dwBytesWritten == 0) 430 return (0); 431 n = dwBytesWritten; 432 #endif 433 evbuffer_drain(buffer, n); 434 435 return (n); 436 } 437 438 u_char * 439 evbuffer_find(struct evbuffer *buffer, const u_char *what, size_t len) 440 { 441 u_char *search = buffer->buffer, *end = search + buffer->off; 442 u_char *p; 443 444 while (search < end && 445 (p = memchr(search, *what, end - search)) != NULL) { 446 if (p + len > end) 447 break; 448 if (memcmp(p, what, len) == 0) 449 return (p); 450 search = p + 1; 451 } 452 453 return (NULL); 454 } 455 456 void evbuffer_setcb(struct evbuffer *buffer, 457 void (*cb)(struct evbuffer *, size_t, size_t, void *), 458 void *cbarg) 459 { 460 buffer->cb = cb; 461 buffer->cbarg = cbarg; 462 } 463