| 554 |
554 |
| 555 #define BUF_UNNEEDED_DIFF 64 |
555 #define BUF_UNNEEDED_DIFF 64 |
| 556 /* |
556 /* |
| 557 * read from st->readbuf first, read from st->fd if perform_io is true |
557 * read from st->readbuf first, read from st->fd if perform_io is true |
| 558 */ |
558 */ |
| 559 static ssize_t http_read_buffered(HttpStream *st, char *buf, size_t nbytes, WSBool read_data, WSBool *perform_io) { |
559 static ssize_t http_read_buffered(HttpStream *httpstr, char *buf, size_t nbytes, WSBool read_data, WSBool *perform_io) { |
| 560 ssize_t r = 0; |
560 ssize_t r = 0; |
| 561 |
561 |
| 562 //memset(buf, 'x', nbytes); |
562 //memset(buf, 'x', nbytes); |
| 563 //char *orig_buf = buf; |
563 //char *orig_buf = buf; |
| 564 |
564 |
| 565 // copy available data from st->readbuf to buf |
565 // copy available data from st->readbuf to buf |
| 566 int pos = *st->bufpos; |
566 int pos = *httpstr->bufpos; |
| 567 size_t buf_available = *st->buflen - pos; |
567 int buflen = *httpstr->buflen; |
| 568 if(buf_available) { |
568 int buf_available = buflen > 0 ? buflen - pos : 0; |
| |
569 if(buf_available > 0) { |
| 569 size_t cplen = buf_available > nbytes ? nbytes : buf_available; |
570 size_t cplen = buf_available > nbytes ? nbytes : buf_available; |
| 570 if(read_data) { |
571 if(read_data) { |
| 571 // if we read data (and not a chunk header), we limit the |
572 // if we read data (and not a chunk header), we limit the |
| 572 // amount of bytes we copy |
573 // amount of bytes we copy |
| 573 size_t chunk_available = st->max_read - st->read; |
574 size_t chunk_available = httpstr->max_read - httpstr->read; |
| 574 cplen = cplen > chunk_available ? chunk_available : cplen; |
575 cplen = cplen > chunk_available ? chunk_available : cplen; |
| 575 st->read += cplen; |
576 httpstr->read += cplen; |
| 576 } |
577 } |
| 577 memcpy(buf, st->readbuf + pos, cplen); |
578 memcpy(buf, httpstr->readbuf + pos, cplen); |
| 578 *st->bufpos += cplen; |
579 *httpstr->bufpos += cplen; |
| 579 r += cplen; |
580 r += cplen; |
| 580 buf += cplen; |
581 buf += cplen; |
| 581 nbytes -= cplen; |
582 nbytes -= cplen; |
| 582 } |
583 } |
| 583 |
584 |
| 586 // when a chunk is completed |
587 // when a chunk is completed |
| 587 // |
588 // |
| 588 // if we read a chunk header (read_data == false) it is very important |
589 // if we read a chunk header (read_data == false) it is very important |
| 589 // to not perform IO, if we have previously copied data from readbuf |
590 // to not perform IO, if we have previously copied data from readbuf |
| 590 // this ensures we never override non-chunk-header data |
591 // this ensures we never override non-chunk-header data |
| 591 if(*perform_io && ((read_data && nbytes > 0 && st->max_read - st->read) || (!read_data && r == 0))) { |
592 if(*perform_io && ((read_data && nbytes > 0 && httpstr->max_read - httpstr->read) || (!read_data && r == 0))) { |
| 592 if(*st->buflen - *st->bufpos > 0) { |
593 if(*httpstr->buflen - *httpstr->bufpos > 0) { |
| 593 printf("todo: fix, should not happen, remove later\n"); |
594 printf("todo: fix, should not happen, remove later\n"); |
| 594 } |
595 } |
| 595 // fill buffer again |
596 // fill buffer again |
| 596 ssize_t rlen = st->fd->read(st->fd, st->readbuf, st->bufsize); |
597 ssize_t rlen = httpstr->fd->read(httpstr->fd, httpstr->readbuf, httpstr->bufsize); |
| 597 *st->buflen = rlen; |
598 *httpstr->buflen = rlen; |
| 598 *st->bufpos = 0; |
599 *httpstr->bufpos = 0; |
| 599 *perform_io = WS_FALSE; |
600 *perform_io = WS_FALSE; |
| 600 if(rlen < 0) { |
601 if(rlen < 0) { |
| 601 st->st.io_errno = st->fd->io_errno; |
602 httpstr->st.io_errno = httpstr->fd->io_errno; |
| 602 } |
603 } |
| 603 |
604 |
| 604 if(rlen > 0) { |
605 if(rlen > 0) { |
| 605 // call func again to get data from buffer (no IO will be performed) |
606 // call func again to get data from buffer (no IO will be performed) |
| 606 r += http_read_buffered(st, buf, nbytes, read_data, perform_io); |
607 r += http_read_buffered(httpstr, buf, nbytes, read_data, perform_io); |
| |
608 } else if(r == 0) { |
| |
609 r = rlen; |
| 607 } |
610 } |
| 608 } |
611 } |
| 609 |
612 |
| 610 return r; |
613 return r; |
| 611 } |
614 } |