1/* Copyright 2002-2004 Justin Erenkrantz and Greg Stein 2 * 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16#include <apr_pools.h> 17 18#include "serf.h" 19#include "serf_bucket_util.h" 20#include "serf_private.h" 21 22serf_bucket_t *serf_bucket_create( 23 const serf_bucket_type_t *type, 24 serf_bucket_alloc_t *allocator, 25 void *data) 26{ 27 serf_bucket_t *bkt = serf_bucket_mem_alloc(allocator, sizeof(*bkt)); 28 29 bkt->type = type; 30 bkt->data = data; 31 bkt->allocator = allocator; 32 33 return bkt; 34} 35 36 37apr_status_t serf_default_read_iovec( 38 serf_bucket_t *bucket, 39 apr_size_t requested, 40 int vecs_size, 41 struct iovec *vecs, 42 int *vecs_used) 43{ 44 const char *data; 45 apr_size_t len; 46 47 /* Read some data from the bucket. 48 * 49 * Because we're an internal 'helper' to the bucket, we can't call the 50 * normal serf_bucket_read() call because the debug allocator tracker will 51 * end up marking the bucket as read *twice* - once for us and once for 52 * our caller - which is reading the same bucket. This leads to premature 53 * abort()s if we ever see EAGAIN. Instead, we'll go directly to the 54 * vtable and bypass the debug tracker. 55 */ 56 apr_status_t status = bucket->type->read(bucket, requested, &data, &len); 57 58 /* assert that vecs_size >= 1 ? */ 59 60 /* Return that data as a single iovec. */ 61 if (len) { 62 vecs[0].iov_base = (void *)data; /* loses the 'const' */ 63 vecs[0].iov_len = len; 64 *vecs_used = 1; 65 } 66 else { 67 *vecs_used = 0; 68 } 69 70 return status; 71} 72 73 74apr_status_t serf_default_read_for_sendfile( 75 serf_bucket_t *bucket, 76 apr_size_t requested, 77 apr_hdtr_t *hdtr, 78 apr_file_t **file, 79 apr_off_t *offset, 80 apr_size_t *len) 81{ 82 /* Read a bunch of stuff into the headers. 83 * 84 * See serf_default_read_iovec as to why we call into the vtable 85 * directly. 86 */ 87 apr_status_t status = bucket->type->read_iovec(bucket, requested, 88 hdtr->numheaders, 89 hdtr->headers, 90 &hdtr->numheaders); 91 92 /* There isn't a file, and there are no trailers. */ 93 *file = NULL; 94 hdtr->numtrailers = 0; 95 96 return status; 97} 98 99 100serf_bucket_t *serf_default_read_bucket( 101 serf_bucket_t *bucket, 102 const serf_bucket_type_t *type) 103{ 104 return NULL; 105} 106 107 108void serf_default_destroy(serf_bucket_t *bucket) 109{ 110#ifdef SERF_DEBUG_BUCKET_USE 111 serf_debug__bucket_destroy(bucket); 112#endif 113 114 serf_bucket_mem_free(bucket->allocator, bucket); 115} 116 117 118void serf_default_destroy_and_data(serf_bucket_t *bucket) 119{ 120 serf_bucket_mem_free(bucket->allocator, bucket->data); 121 serf_default_destroy(bucket); 122} 123 124 125/* ==================================================================== */ 126 127 128char *serf_bstrmemdup(serf_bucket_alloc_t *allocator, 129 const char *str, 130 apr_size_t size) 131{ 132 char *newstr = serf_bucket_mem_alloc(allocator, size + 1); 133 memcpy(newstr, str, size); 134 newstr[size] = '\0'; 135 return newstr; 136} 137 138 139void *serf_bmemdup(serf_bucket_alloc_t *allocator, 140 const void *mem, 141 apr_size_t size) 142{ 143 void *newmem = serf_bucket_mem_alloc(allocator, size); 144 memcpy(newmem, mem, size); 145 return newmem; 146} 147 148 149char *serf_bstrdup(serf_bucket_alloc_t *allocator, 150 const char *str) 151{ 152 apr_size_t size = strlen(str) + 1; 153 char *newstr = serf_bucket_mem_alloc(allocator, size); 154 memcpy(newstr, str, size); 155 return newstr; 156} 157 158char *serf_bstrcatv(serf_bucket_alloc_t *allocator, struct iovec *vec, 159 int vecs, apr_size_t *bytes_written) 160{ 161 int i; 162 apr_size_t new_len = 0; 163 char *c, *newstr; 164 165 for (i = 0; i < vecs; i++) { 166 new_len += vec[i].iov_len; 167 } 168 169 /* It's up to the caller to free this memory later. */ 170 newstr = serf_bucket_mem_alloc(allocator, new_len); 171 172 c = newstr; 173 for (i = 0; i < vecs; i++) { 174 memcpy(c, vec[i].iov_base, vec[i].iov_len); 175 c += vec[i].iov_len; 176 } 177 178 if (bytes_written) { 179 *bytes_written = c - newstr; 180 } 181 182 return newstr; 183} 184 185/* ==================================================================== */ 186 187 188static void find_crlf(const char **data, apr_size_t *len, int *found) 189{ 190 const char *start = *data; 191 const char *end = start + *len; 192 193 while (start < end) { 194 const char *cr = memchr(start, '\r', *len); 195 196 if (cr == NULL) { 197 break; 198 } 199 ++cr; 200 201 if (cr < end && cr[0] == '\n') { 202 *len -= cr + 1 - start; 203 *data = cr + 1; 204 *found = SERF_NEWLINE_CRLF; 205 return; 206 } 207 if (cr == end) { 208 *len = 0; 209 *data = end; 210 *found = SERF_NEWLINE_CRLF_SPLIT; 211 return; 212 } 213 214 /* It was a bare CR without an LF. Just move past it. */ 215 *len -= cr - start; 216 start = cr; 217 } 218 219 *data = start + *len; 220 *len -= *data - start; 221 *found = SERF_NEWLINE_NONE; 222} 223 224 225void serf_util_readline( 226 const char **data, 227 apr_size_t *len, 228 int acceptable, 229 int *found) 230{ 231 const char *start; 232 const char *cr; 233 const char *lf; 234 int want_cr; 235 int want_crlf; 236 int want_lf; 237 238 /* If _only_ CRLF is acceptable, then the scanning needs a loop to 239 * skip false hits on CR characters. Use a separate function. 240 */ 241 if (acceptable == SERF_NEWLINE_CRLF) { 242 find_crlf(data, len, found); 243 return; 244 } 245 246 start = *data; 247 cr = lf = NULL; 248 want_cr = acceptable & SERF_NEWLINE_CR; 249 want_crlf = acceptable & SERF_NEWLINE_CRLF; 250 want_lf = acceptable & SERF_NEWLINE_LF; 251 252 if (want_cr || want_crlf) { 253 cr = memchr(start, '\r', *len); 254 } 255 if (want_lf) { 256 lf = memchr(start, '\n', *len); 257 } 258 259 if (cr != NULL) { 260 if (lf != NULL) { 261 if (cr + 1 == lf) 262 *found = want_crlf ? SERF_NEWLINE_CRLF : SERF_NEWLINE_CR; 263 else if (want_cr && cr < lf) 264 *found = SERF_NEWLINE_CR; 265 else 266 *found = SERF_NEWLINE_LF; 267 } 268 else if (cr == start + *len - 1) { 269 /* the CR occurred in the last byte of the buffer. this could be 270 * a CRLF split across the data boundary. 271 * ### FIX THIS LOGIC? does caller need to detect? 272 */ 273 *found = want_crlf ? SERF_NEWLINE_CRLF_SPLIT : SERF_NEWLINE_CR; 274 } 275 else if (want_cr) 276 *found = SERF_NEWLINE_CR; 277 else /* want_crlf */ 278 *found = SERF_NEWLINE_NONE; 279 } 280 else if (lf != NULL) 281 *found = SERF_NEWLINE_LF; 282 else 283 *found = SERF_NEWLINE_NONE; 284 285 switch (*found) { 286 case SERF_NEWLINE_LF: 287 *data = lf + 1; 288 break; 289 case SERF_NEWLINE_CR: 290 case SERF_NEWLINE_CRLF: 291 case SERF_NEWLINE_CRLF_SPLIT: 292 *data = cr + 1 + (*found == SERF_NEWLINE_CRLF); 293 break; 294 case SERF_NEWLINE_NONE: 295 *data += *len; 296 break; 297 default: 298 /* Not reachable */ 299 return; 300 } 301 302 *len -= *data - start; 303} 304 305 306/* ==================================================================== */ 307 308 309void serf_databuf_init(serf_databuf_t *databuf) 310{ 311 /* nothing is sitting in the buffer */ 312 databuf->remaining = 0; 313 314 /* avoid thinking we have hit EOF */ 315 databuf->status = APR_SUCCESS; 316} 317 318/* Ensure the buffer is prepared for reading. Will return APR_SUCCESS, 319 * APR_EOF, or some failure code. *len is only set for EOF. */ 320static apr_status_t common_databuf_prep(serf_databuf_t *databuf, 321 apr_size_t *len) 322{ 323 apr_size_t readlen; 324 apr_status_t status; 325 326 /* if there is data in the buffer, then we're happy. */ 327 if (databuf->remaining > 0) 328 return APR_SUCCESS; 329 330 /* if we already hit EOF, then keep returning that. */ 331 if (APR_STATUS_IS_EOF(databuf->status)) { 332 /* *data = NULL; ?? */ 333 *len = 0; 334 return APR_EOF; 335 } 336 337 /* refill the buffer */ 338 status = (*databuf->read)(databuf->read_baton, sizeof(databuf->buf), 339 databuf->buf, &readlen); 340 if (SERF_BUCKET_READ_ERROR(status)) { 341 return status; 342 } 343 344 databuf->current = databuf->buf; 345 databuf->remaining = readlen; 346 databuf->status = status; 347 348 return APR_SUCCESS; 349} 350 351 352apr_status_t serf_databuf_read( 353 serf_databuf_t *databuf, 354 apr_size_t requested, 355 const char **data, 356 apr_size_t *len) 357{ 358 apr_status_t status = common_databuf_prep(databuf, len); 359 if (status) 360 return status; 361 362 /* peg the requested amount to what we have remaining */ 363 if (requested == SERF_READ_ALL_AVAIL || requested > databuf->remaining) 364 requested = databuf->remaining; 365 366 /* return the values */ 367 *data = databuf->current; 368 *len = requested; 369 370 /* adjust our internal state to note we've consumed some data */ 371 databuf->current += requested; 372 databuf->remaining -= requested; 373 374 /* If we read everything, then we need to return whatever the data 375 * read returned to us. This is going to be APR_EOF or APR_EGAIN. 376 * If we have NOT read everything, then return APR_SUCCESS to indicate 377 * that we're ready to return some more if asked. 378 */ 379 return databuf->remaining ? APR_SUCCESS : databuf->status; 380} 381 382 383apr_status_t serf_databuf_readline( 384 serf_databuf_t *databuf, 385 int acceptable, 386 int *found, 387 const char **data, 388 apr_size_t *len) 389{ 390 apr_status_t status = common_databuf_prep(databuf, len); 391 if (status) 392 return status; 393 394 /* the returned line will start at the current position. */ 395 *data = databuf->current; 396 397 /* read a line from the buffer, and adjust the various pointers. */ 398 serf_util_readline(&databuf->current, &databuf->remaining, acceptable, 399 found); 400 401 /* the length matches the amount consumed by the readline */ 402 *len = databuf->current - *data; 403 404 /* see serf_databuf_read's return condition */ 405 return databuf->remaining ? APR_SUCCESS : databuf->status; 406} 407 408 409apr_status_t serf_databuf_peek( 410 serf_databuf_t *databuf, 411 const char **data, 412 apr_size_t *len) 413{ 414 apr_status_t status = common_databuf_prep(databuf, len); 415 if (status) 416 return status; 417 418 /* return everything we have */ 419 *data = databuf->current; 420 *len = databuf->remaining; 421 422 /* If the last read returned EOF, then the peek should return the same. 423 * The other possibility in databuf->status is APR_EAGAIN, which we 424 * should never return. Thus, just return APR_SUCCESS for non-EOF cases. 425 */ 426 if (APR_STATUS_IS_EOF(databuf->status)) 427 return APR_EOF; 428 return APR_SUCCESS; 429} 430 431 432/* ==================================================================== */ 433 434 435void serf_linebuf_init(serf_linebuf_t *linebuf) 436{ 437 linebuf->state = SERF_LINEBUF_EMPTY; 438 linebuf->used = 0; 439} 440 441 442apr_status_t serf_linebuf_fetch( 443 serf_linebuf_t *linebuf, 444 serf_bucket_t *bucket, 445 int acceptable) 446{ 447 /* If we had a complete line, then assume the caller has used it, so 448 * we can now reset the state. 449 */ 450 if (linebuf->state == SERF_LINEBUF_READY) { 451 linebuf->state = SERF_LINEBUF_EMPTY; 452 453 /* Reset the line_used, too, so we don't have to test the state 454 * before using this value. 455 */ 456 linebuf->used = 0; 457 } 458 459 while (1) { 460 apr_status_t status; 461 const char *data; 462 apr_size_t len; 463 464 if (linebuf->state == SERF_LINEBUF_CRLF_SPLIT) { 465 /* On the previous read, we received just a CR. The LF might 466 * be present, but the bucket couldn't see it. We need to 467 * examine a single character to determine how to handle the 468 * split CRLF. 469 */ 470 471 status = serf_bucket_peek(bucket, &data, &len); 472 if (SERF_BUCKET_READ_ERROR(status)) 473 return status; 474 475 if (len > 0) { 476 if (*data == '\n') { 477 /* We saw the second part of CRLF. We don't need to 478 * save that character, so do an actual read to suck 479 * up that character. 480 */ 481 /* ### check status */ 482 (void) serf_bucket_read(bucket, 1, &data, &len); 483 } 484 /* else: 485 * We saw the first character of the next line. Thus, 486 * the current line is terminated by the CR. Just 487 * ignore whatever we peeked at. The next reader will 488 * see it and handle it as appropriate. 489 */ 490 491 /* Whatever was read, the line is now ready for use. */ 492 linebuf->state = SERF_LINEBUF_READY; 493 } else { 494 /* no data available, try again later. */ 495 return APR_EAGAIN; 496 } 497 } 498 else { 499 int found; 500 501 status = serf_bucket_readline(bucket, acceptable, &found, 502 &data, &len); 503 if (SERF_BUCKET_READ_ERROR(status)) { 504 return status; 505 } 506 /* Some bucket types (socket) might need an extra read to find 507 out EOF state, so they'll return no data in that read. This 508 means we're done reading, return what we got. */ 509 if (APR_STATUS_IS_EOF(status) && len == 0) { 510 return status; 511 } 512 if (linebuf->used + len > sizeof(linebuf->line)) { 513 /* ### need a "line too long" error */ 514 return APR_EGENERAL; 515 } 516 517 /* Note: our logic doesn't change for SERF_LINEBUF_PARTIAL. That 518 * only affects how we fill the buffer. It is a communication to 519 * our caller on whether the line is ready or not. 520 */ 521 522 /* If we didn't see a newline, then we should mark the line 523 * buffer as partially complete. 524 */ 525 if (found == SERF_NEWLINE_NONE) { 526 linebuf->state = SERF_LINEBUF_PARTIAL; 527 } 528 else if (found == SERF_NEWLINE_CRLF_SPLIT) { 529 linebuf->state = SERF_LINEBUF_CRLF_SPLIT; 530 531 /* Toss the partial CR. We won't ever need it. */ 532 --len; 533 } 534 else { 535 /* We got a newline (of some form). We don't need it 536 * in the line buffer, so back up the length. Then 537 * mark the line as ready. 538 */ 539 len -= 1 + (found == SERF_NEWLINE_CRLF); 540 541 linebuf->state = SERF_LINEBUF_READY; 542 } 543 544 /* ### it would be nice to avoid this copy if at all possible, 545 ### and just return the a data/len pair to the caller. we're 546 ### keeping it simple for now. */ 547 memcpy(&linebuf->line[linebuf->used], data, len); 548 linebuf->used += len; 549 } 550 551 /* If we saw anything besides "success. please read again", then 552 * we should return that status. If the line was completed, then 553 * we should also return. 554 */ 555 if (status || linebuf->state == SERF_LINEBUF_READY) 556 return status; 557 558 /* We got APR_SUCCESS and the line buffer is not complete. Let's 559 * loop to read some more data. 560 */ 561 } 562 /* NOTREACHED */ 563} 564 565/* Logging functions. 566 Use with one of the [COMP]_VERBOSE defines so that the compiler knows to 567 optimize this code out when no logging is needed. */ 568static void log_time() 569{ 570 apr_time_exp_t tm; 571 572 apr_time_exp_lt(&tm, apr_time_now()); 573 fprintf(stderr, "[%d-%02d-%02dT%02d:%02d:%02d.%06d%+03d] ", 574 1900 + tm.tm_year, 1 + tm.tm_mon, tm.tm_mday, 575 tm.tm_hour, tm.tm_min, tm.tm_sec, tm.tm_usec, 576 tm.tm_gmtoff/3600); 577} 578 579void serf__log(int verbose_flag, const char *filename, const char *fmt, ...) 580{ 581 va_list argp; 582 583 if (verbose_flag) { 584 log_time(); 585 586 if (filename) 587 fprintf(stderr, "%s: ", filename); 588 589 va_start(argp, fmt); 590 vfprintf(stderr, fmt, argp); 591 va_end(argp); 592 } 593} 594 595void serf__log_nopref(int verbose_flag, const char *fmt, ...) 596{ 597 va_list argp; 598 599 if (verbose_flag) { 600 va_start(argp, fmt); 601 vfprintf(stderr, fmt, argp); 602 va_end(argp); 603 } 604} 605 606void serf__log_skt(int verbose_flag, const char *filename, apr_socket_t *skt, 607 const char *fmt, ...) 608{ 609 va_list argp; 610 611 if (verbose_flag) { 612 apr_sockaddr_t *sa; 613 log_time(); 614 615 if (skt) { 616 /* Log local and remote ip address:port */ 617 fprintf(stderr, "[l:"); 618 if (apr_socket_addr_get(&sa, APR_LOCAL, skt) == APR_SUCCESS) { 619 char buf[32]; 620 apr_sockaddr_ip_getbuf(buf, 32, sa); 621 fprintf(stderr, "%s:%d", buf, sa->port); 622 } 623 fprintf(stderr, " r:"); 624 if (apr_socket_addr_get(&sa, APR_REMOTE, skt) == APR_SUCCESS) { 625 char buf[32]; 626 apr_sockaddr_ip_getbuf(buf, 32, sa); 627 fprintf(stderr, "%s:%d", buf, sa->port); 628 } 629 fprintf(stderr, "] "); 630 } 631 632 if (filename) 633 fprintf(stderr, "%s: ", filename); 634 635 va_start(argp, fmt); 636 vfprintf(stderr, fmt, argp); 637 va_end(argp); 638 } 639} 640 641