mirror of
https://github.com/curl/curl.git
synced 2026-07-27 03:57:16 +03:00
transfer: readwrite improvements
- changed header/chunk/handler->readwrite prototypes to accept `buf`, `blen` and a `pconsumed` pointer. They now get the buffer to work on and report back how many bytes they consumed - eliminated `k->str` in SingleRequest - improved excess data handling to properly calculate with any body data left in the headerb buffer - eliminated `k->badheader` enum to only be a bool Closes #12283
This commit is contained in:
parent
d9e7643ced
commit
1cd2f0072f
8 changed files with 269 additions and 246 deletions
|
|
@ -98,9 +98,9 @@ void Curl_httpchunk_init(struct Curl_easy *data)
|
|||
* For example, 0x0d and 0x0a are used instead of '\r' and '\n'.
|
||||
*/
|
||||
CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
||||
char *datap,
|
||||
ssize_t datalen,
|
||||
ssize_t *wrote,
|
||||
char *buf,
|
||||
size_t blen,
|
||||
size_t *pconsumed,
|
||||
CURLcode *extrap)
|
||||
{
|
||||
CURLcode result = CURLE_OK;
|
||||
|
|
@ -108,28 +108,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
struct Curl_chunker *ch = &conn->chunk;
|
||||
struct SingleRequest *k = &data->req;
|
||||
size_t piece;
|
||||
curl_off_t length = (curl_off_t)datalen;
|
||||
|
||||
*wrote = 0; /* nothing's written yet */
|
||||
*pconsumed = 0; /* nothing's written yet */
|
||||
|
||||
/* the original data is written to the client, but we go on with the
|
||||
chunk read process, to properly calculate the content length */
|
||||
if(data->set.http_te_skip && !k->ignorebody) {
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, datalen);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, blen);
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
return CHUNKE_PASSTHRU_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
while(length) {
|
||||
while(blen) {
|
||||
switch(ch->state) {
|
||||
case CHUNK_HEX:
|
||||
if(ISXDIGIT(*datap)) {
|
||||
if(ISXDIGIT(*buf)) {
|
||||
if(ch->hexindex < CHUNK_MAXNUM_LEN) {
|
||||
ch->hexbuffer[ch->hexindex] = *datap;
|
||||
datap++;
|
||||
length--;
|
||||
ch->hexbuffer[ch->hexindex] = *buf;
|
||||
buf++;
|
||||
blen--;
|
||||
ch->hexindex++;
|
||||
}
|
||||
else {
|
||||
|
|
@ -143,7 +142,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
a hexadecimal digit. */
|
||||
return CHUNKE_ILLEGAL_HEX;
|
||||
|
||||
/* length and datap are unmodified */
|
||||
/* blen and buf are unmodified */
|
||||
ch->hexbuffer[ch->hexindex] = 0;
|
||||
|
||||
if(curlx_strtoofft(ch->hexbuffer, &endptr, 16, &ch->datasize))
|
||||
|
|
@ -154,7 +153,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
|
||||
case CHUNK_LF:
|
||||
/* waiting for the LF after a chunk size */
|
||||
if(*datap == 0x0a) {
|
||||
if(*buf == 0x0a) {
|
||||
/* we're now expecting data to come, unless size was zero! */
|
||||
if(0 == ch->datasize) {
|
||||
ch->state = CHUNK_TRAILER; /* now check for trailers */
|
||||
|
|
@ -163,19 +162,21 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
ch->state = CHUNK_DATA;
|
||||
}
|
||||
|
||||
datap++;
|
||||
length--;
|
||||
buf++;
|
||||
blen--;
|
||||
break;
|
||||
|
||||
case CHUNK_DATA:
|
||||
/* We expect 'datasize' of data. We have 'length' right now, it can be
|
||||
/* We expect 'datasize' of data. We have 'blen' right now, it can be
|
||||
more or less than 'datasize'. Get the smallest piece.
|
||||
*/
|
||||
piece = curlx_sotouz((ch->datasize >= length)?length:ch->datasize);
|
||||
piece = blen;
|
||||
if(ch->datasize < (curl_off_t)blen)
|
||||
piece = curlx_sotouz(ch->datasize);
|
||||
|
||||
/* Write the data portion available */
|
||||
if(!data->set.http_te_skip && !k->ignorebody) {
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, datap, piece);
|
||||
result = Curl_client_write(data, CLIENTWRITE_BODY, buf, piece);
|
||||
|
||||
if(result) {
|
||||
*extrap = result;
|
||||
|
|
@ -183,10 +184,10 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
|
||||
*wrote += piece;
|
||||
*pconsumed += piece;
|
||||
ch->datasize -= piece; /* decrease amount left to expect */
|
||||
datap += piece; /* move read pointer forward */
|
||||
length -= piece; /* decrease space left in this round */
|
||||
buf += piece; /* move read pointer forward */
|
||||
blen -= piece; /* decrease space left in this round */
|
||||
|
||||
if(0 == ch->datasize)
|
||||
/* end of data this round, we now expect a trailing CRLF */
|
||||
|
|
@ -194,18 +195,18 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
break;
|
||||
|
||||
case CHUNK_POSTLF:
|
||||
if(*datap == 0x0a) {
|
||||
if(*buf == 0x0a) {
|
||||
/* The last one before we go back to hex state and start all over. */
|
||||
Curl_httpchunk_init(data); /* sets state back to CHUNK_HEX */
|
||||
}
|
||||
else if(*datap != 0x0d)
|
||||
else if(*buf != 0x0d)
|
||||
return CHUNKE_BAD_CHUNK;
|
||||
datap++;
|
||||
length--;
|
||||
buf++;
|
||||
blen--;
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER:
|
||||
if((*datap == 0x0d) || (*datap == 0x0a)) {
|
||||
if((*buf == 0x0d) || (*buf == 0x0a)) {
|
||||
char *tr = Curl_dyn_ptr(&conn->trailer);
|
||||
/* this is the end of a trailer, but if the trailer was zero bytes
|
||||
there was no trailer and we move on */
|
||||
|
|
@ -229,7 +230,7 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
}
|
||||
Curl_dyn_reset(&conn->trailer);
|
||||
ch->state = CHUNK_TRAILER_CR;
|
||||
if(*datap == 0x0a)
|
||||
if(*buf == 0x0a)
|
||||
/* already on the LF */
|
||||
break;
|
||||
}
|
||||
|
|
@ -240,19 +241,19 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
}
|
||||
}
|
||||
else {
|
||||
result = Curl_dyn_addn(&conn->trailer, datap, 1);
|
||||
result = Curl_dyn_addn(&conn->trailer, buf, 1);
|
||||
if(result)
|
||||
return CHUNKE_OUT_OF_MEMORY;
|
||||
}
|
||||
datap++;
|
||||
length--;
|
||||
buf++;
|
||||
blen--;
|
||||
break;
|
||||
|
||||
case CHUNK_TRAILER_CR:
|
||||
if(*datap == 0x0a) {
|
||||
if(*buf == 0x0a) {
|
||||
ch->state = CHUNK_TRAILER_POSTCR;
|
||||
datap++;
|
||||
length--;
|
||||
buf++;
|
||||
blen--;
|
||||
}
|
||||
else
|
||||
return CHUNKE_BAD_CHUNK;
|
||||
|
|
@ -261,27 +262,27 @@ CHUNKcode Curl_httpchunk_read(struct Curl_easy *data,
|
|||
case CHUNK_TRAILER_POSTCR:
|
||||
/* We enter this state when a CR should arrive so we expect to
|
||||
have to first pass a CR before we wait for LF */
|
||||
if((*datap != 0x0d) && (*datap != 0x0a)) {
|
||||
if((*buf != 0x0d) && (*buf != 0x0a)) {
|
||||
/* not a CR then it must be another header in the trailer */
|
||||
ch->state = CHUNK_TRAILER;
|
||||
break;
|
||||
}
|
||||
if(*datap == 0x0d) {
|
||||
if(*buf == 0x0d) {
|
||||
/* skip if CR */
|
||||
datap++;
|
||||
length--;
|
||||
buf++;
|
||||
blen--;
|
||||
}
|
||||
/* now wait for the final LF */
|
||||
ch->state = CHUNK_STOP;
|
||||
break;
|
||||
|
||||
case CHUNK_STOP:
|
||||
if(*datap == 0x0a) {
|
||||
length--;
|
||||
if(*buf == 0x0a) {
|
||||
blen--;
|
||||
|
||||
/* Record the length of any data left in the end of the buffer
|
||||
even if there's no more chunks to read */
|
||||
ch->datasize = curlx_sotouz(length);
|
||||
ch->datasize = blen;
|
||||
|
||||
return CHUNKE_STOP; /* return stop */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue