diff --git a/lib/http.h b/lib/http.h index f0ddec759..a3a275702 100644 --- a/lib/http.h +++ b/lib/http.h @@ -83,11 +83,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done); CURLcode Curl_http_done(struct connectdata *, CURLcode, bool premature); CURLcode Curl_http_connect(struct connectdata *conn, bool *done); -/* The following functions are defined in http_chunks.c */ -void Curl_httpchunk_init(struct connectdata *conn); -CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, - ssize_t length, ssize_t *wrote); - /* These functions are in http.c */ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy, const char *auth); diff --git a/lib/http_chunks.c b/lib/http_chunks.c index 18dfcb282..b6ffa4185 100644 --- a/lib/http_chunks.c +++ b/lib/http_chunks.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2018, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -109,7 +109,8 @@ void Curl_httpchunk_init(struct connectdata *conn) CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, ssize_t datalen, - ssize_t *wrotep) + ssize_t *wrotep, + CURLcode *extrap) { CURLcode result = CURLE_OK; struct Curl_easy *data = conn->data; @@ -125,8 +126,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, chunk read process, to properly calculate the content length*/ if(data->set.http_te_skip && !k->ignorebody) { result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, datalen); - if(result) - return CHUNKE_WRITE_ERROR; + if(result) { + *extrap = result; + return CHUNKE_PASSTHRU_ERROR; + } } while(length) { @@ -197,8 +200,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, else result = Curl_client_write(conn, CLIENTWRITE_BODY, datap, piece); - if(result) - return CHUNKE_WRITE_ERROR; + if(result) { + *extrap = result; + return CHUNKE_PASSTHRU_ERROR; + } } *wrote += piece; @@ -244,8 +249,10 @@ CHUNKcode Curl_httpchunk_read(struct connectdata *conn, if(!data->set.http_te_skip) { result = Curl_client_write(conn, CLIENTWRITE_HEADER, conn->trailer, conn->trlPos); - if(result) - return CHUNKE_WRITE_ERROR; + if(result) { + *extrap = result; + return CHUNKE_PASSTHRU_ERROR; + } } conn->trlPos = 0; ch->state = CHUNK_TRAILER_CR; @@ -339,8 +346,9 @@ const char *Curl_chunked_strerror(CHUNKcode code) return "Illegal or missing hexadecimal sequence"; case CHUNKE_BAD_CHUNK: return "Malformed encoding found"; - case CHUNKE_WRITE_ERROR: - return "Write error"; + case CHUNKE_PASSTHRU_ERROR: + DEBUGASSERT(0); /* never used */ + return ""; case CHUNKE_BAD_ENCODING: return "Bad content-encoding found"; case CHUNKE_OUT_OF_MEMORY: diff --git a/lib/http_chunks.h b/lib/http_chunks.h index b969c5590..8f4a33c8e 100644 --- a/lib/http_chunks.h +++ b/lib/http_chunks.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2014, Daniel Stenberg, , et al. + * Copyright (C) 1998 - 2019, Daniel Stenberg, , et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -21,6 +21,9 @@ * KIND, either express or implied. * ***************************************************************************/ + +struct connectdata; + /* * The longest possible hexadecimal number we support in a chunked transfer. * Weird enough, RFC2616 doesn't set a maximum size! Since we use strtoul() @@ -71,9 +74,9 @@ typedef enum { CHUNKE_TOO_LONG_HEX = 1, CHUNKE_ILLEGAL_HEX, CHUNKE_BAD_CHUNK, - CHUNKE_WRITE_ERROR, CHUNKE_BAD_ENCODING, CHUNKE_OUT_OF_MEMORY, + CHUNKE_PASSTHRU_ERROR, /* Curl_httpchunk_read() returns a CURLcode to use */ CHUNKE_LAST } CHUNKcode; @@ -87,4 +90,10 @@ struct Curl_chunker { size_t dataleft; /* untouched data amount at the end of the last buffer */ }; +/* The following functions are defined in http_chunks.c */ +void Curl_httpchunk_init(struct connectdata *conn); +CHUNKcode Curl_httpchunk_read(struct connectdata *conn, char *datap, + ssize_t length, ssize_t *wrote, + CURLcode *passthru); + #endif /* HEADER_CURL_HTTP_CHUNKS_H */ diff --git a/lib/http_proxy.c b/lib/http_proxy.c index 710101774..f095455a5 100644 --- a/lib/http_proxy.c +++ b/lib/http_proxy.c @@ -384,11 +384,12 @@ static CURLcode CONNECT(struct connectdata *conn, /* chunked-encoded body, so we need to do the chunked dance properly to know when the end of the body is reached */ CHUNKcode r; + CURLcode extra; ssize_t tookcareof = 0; /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof); + r = Curl_httpchunk_read(conn, s->ptr, 1, &tookcareof, &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE\n"); @@ -455,6 +456,7 @@ static CURLcode CONNECT(struct connectdata *conn, } else if(s->chunked_encoding) { CHUNKcode r; + CURLcode extra; infof(data, "Ignore chunked response-body\n"); @@ -472,7 +474,8 @@ static CURLcode CONNECT(struct connectdata *conn, /* now parse the chunked piece of data so that we can properly tell when the stream ends */ - r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes); + r = Curl_httpchunk_read(conn, s->line_start + 1, 1, &gotbytes, + &extra); if(r == CHUNKE_STOP) { /* we're done reading chunks! */ infof(data, "chunk reading DONE\n"); diff --git a/lib/transfer.c b/lib/transfer.c index ef0d80638..44aa10971 100644 --- a/lib/transfer.c +++ b/lib/transfer.c @@ -776,14 +776,14 @@ static CURLcode readwrite_data(struct Curl_easy *data, * and writes away the data. The returned 'nread' holds the number * of actual data it wrote to the client. */ - + CURLcode extra; CHUNKcode res = - Curl_httpchunk_read(conn, k->str, nread, &nread); + Curl_httpchunk_read(conn, k->str, nread, &nread, &extra); if(CHUNKE_OK < res) { - if(CHUNKE_WRITE_ERROR == res) { - failf(data, "Failed writing data"); - return CURLE_WRITE_ERROR; + if(CHUNKE_PASSTHRU_ERROR == res) { + failf(data, "Failed reading the chunked-encoded stream"); + return extra; } failf(data, "%s in chunked-encoding", Curl_chunked_strerror(res)); return CURLE_RECV_ERROR;