diff options
Diffstat (limited to 'libs/libcurl/src/c-hyper.c')
-rw-r--r-- | libs/libcurl/src/c-hyper.c | 104 |
1 files changed, 90 insertions, 14 deletions
diff --git a/libs/libcurl/src/c-hyper.c b/libs/libcurl/src/c-hyper.c index 81f589eb9e..2cc5d496e1 100644 --- a/libs/libcurl/src/c-hyper.c +++ b/libs/libcurl/src/c-hyper.c @@ -124,6 +124,17 @@ static int hyper_each_header(void *userdata, size_t len; char *headp; CURLcode result; + int writetype; + + if(name_len + value_len + 2 > CURL_MAX_HTTP_HEADER) { + failf(data, "Too long response header"); + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_ITER_BREAK; + } + + if(!data->req.bytecount) + Curl_pgrsTime(data, TIMER_STARTTRANSFER); + Curl_dyn_reset(&data->state.headerb); if(name_len) { if(Curl_dyn_addf(&data->state.headerb, "%.*s: %.*s\r\n", @@ -145,7 +156,10 @@ static int hyper_each_header(void *userdata, Curl_debug(data, CURLINFO_HEADER_IN, headp, len); - result = Curl_client_write(data, CLIENTWRITE_HEADER, headp, len); + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, headp, len); if(result) { data->state.hresult = CURLE_ABORTED_BY_CALLBACK; return HYPER_ITER_BREAK; @@ -166,9 +180,27 @@ static int hyper_body_chunk(void *userdata, const hyper_buf *chunk) if(0 == k->bodywrites++) { bool done = FALSE; - result = Curl_http_firstwrite(data, data->conn, &done); +#if defined(USE_NTLM) + struct connectdata *conn = data->conn; + if(conn->bits.close && + (((data->req.httpcode == 401) && + (conn->http_ntlm_state == NTLMSTATE_TYPE2)) || + ((data->req.httpcode == 407) && + (conn->proxy_ntlm_state == NTLMSTATE_TYPE2)))) { + infof(data, "Connection closed while negotiating NTLM"); + data->state.authproblem = TRUE; + Curl_safefree(data->req.newurl); + } +#endif + if(data->state.hconnect && + (data->req.httpcode/100 != 2)) { + done = TRUE; + result = CURLE_OK; + } + else + result = Curl_http_firstwrite(data, data->conn, &done); if(result || done) { - infof(data, "Return early from hyper_body_chunk\n"); + infof(data, "Return early from hyper_body_chunk"); data->state.hresult = result; return HYPER_ITER_BREAK; } @@ -207,6 +239,7 @@ static CURLcode status_line(struct Curl_easy *data, CURLcode result; size_t len; const char *vstr; + int writetype; vstr = http_version == HYPER_HTTP_VERSION_1_1 ? "1.1" : (http_version == HYPER_HTTP_VERSION_2 ? "2" : "1.0"); conn->httpversion = @@ -229,7 +262,10 @@ static CURLcode status_line(struct Curl_easy *data, len = Curl_dyn_len(&data->state.headerb); Curl_debug(data, CURLINFO_HEADER_IN, Curl_dyn_ptr(&data->state.headerb), len); - result = Curl_client_write(data, CLIENTWRITE_HEADER, + writetype = CLIENTWRITE_HEADER; + if(data->set.include_header) + writetype |= CLIENTWRITE_BODY; + result = Curl_client_write(data, writetype, Curl_dyn_ptr(&data->state.headerb), len); if(result) { data->state.hresult = CURLE_ABORTED_BY_CALLBACK; @@ -309,7 +345,7 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, if(errnum == HYPERE_ABORTED_BY_CALLBACK) { /* override Hyper's view, might not even be an error */ result = data->state.hresult; - infof(data, "hyperstream is done (by early callback)\n"); + infof(data, "hyperstream is done (by early callback)"); } else { uint8_t errbuf[256]; @@ -318,6 +354,8 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); if((code == HYPERE_UNEXPECTED_EOF) && !data->req.bytecount) result = CURLE_GOT_NOTHING; + else if(code == HYPERE_INVALID_PEER_MESSAGE) + result = CURLE_UNSUPPORTED_PROTOCOL; /* maybe */ else result = CURLE_RECV_ERROR; } @@ -328,10 +366,10 @@ CURLcode Curl_hyper_stream(struct Curl_easy *data, else if(h->endtask == task) { /* end of transfer */ *done = TRUE; - infof(data, "hyperstream is done!\n"); + infof(data, "hyperstream is done!"); break; } - else if(t != HYPER_TASK_RESPONSE && t != HYPER_TASK_EMPTY) { + else if(t != HYPER_TASK_RESPONSE) { *didwhat = KEEP_RECV; break; } @@ -472,7 +510,7 @@ CURLcode Curl_hyper_header(struct Curl_easy *data, hyper_headers *headers, if(HYPERE_OK != hyper_headers_add(headers, (uint8_t *)n, nlen, (uint8_t *)v, vlen)) { - failf(data, "hyper_headers_add host"); + failf(data, "hyper refused to add header '%s'", line); return CURLE_OUT_OF_MEMORY; } if(data->set.verbose) { @@ -530,8 +568,18 @@ static int uploadpostfields(void *userdata, hyper_context *ctx, *chunk = NULL; /* nothing more to deliver */ else { /* send everything off in a single go */ - *chunk = hyper_buf_copy(data->set.postfields, - (size_t)data->req.p.http->postsize); + hyper_buf *copy = hyper_buf_copy(data->set.postfields, + (size_t)data->req.p.http->postsize); + if(copy) + *chunk = copy; + else { + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_POLL_ERROR; + } + /* increasing the writebytecount here is a little premature but we + don't know exactly when the body is sent*/ + data->req.writebytecount += (size_t)data->req.p.http->postsize; + Curl_pgrsSetUploadCounter(data, data->req.writebytecount); data->req.upload_done = TRUE; } return HYPER_POLL_READY; @@ -545,13 +593,26 @@ static int uploadstreamed(void *userdata, hyper_context *ctx, CURLcode result = Curl_fillreadbuffer(data, data->set.upload_buffer_size, &fillcount); (void)ctx; - if(result) + if(result) { + data->state.hresult = result; return HYPER_POLL_ERROR; + } if(!fillcount) /* done! */ *chunk = NULL; - else - *chunk = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); + else { + hyper_buf *copy = hyper_buf_copy((uint8_t *)data->state.ulbuf, fillcount); + if(copy) + *chunk = copy; + else { + data->state.hresult = CURLE_OUT_OF_MEMORY; + return HYPER_POLL_ERROR; + } + /* increasing the writebytecount here is a little premature but we + don't know exactly when the body is sent*/ + data->req.writebytecount += fillcount; + Curl_pgrsSetUploadCounter(data, fillcount); + } return HYPER_POLL_READY; } @@ -646,7 +707,7 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) the rest of the request in the PERFORM phase. */ *done = TRUE; - infof(data, "Time for the Hyper dance\n"); + infof(data, "Time for the Hyper dance"); memset(h, 0, sizeof(struct hyptransfer)); result = Curl_http_host(data, conn); @@ -830,6 +891,15 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) else Curl_safefree(data->state.aptr.accept_encoding); +#ifdef HAVE_LIBZ + /* we only consider transfer-encoding magic if libz support is built-in */ + result = Curl_transferencode(data); + if(result) + return result; + if(Curl_hyper_header(data, headers, data->state.aptr.te)) + goto error; +#endif + result = cookies(data, conn, headers); if(result) return result; @@ -881,6 +951,10 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) } conn->datastream = Curl_hyper_stream; + /* clear userpwd and proxyuserpwd to avoid re-using old credentials + * from re-used connections */ + Curl_safefree(data->state.aptr.userpwd); + Curl_safefree(data->state.aptr.proxyuserpwd); return CURLE_OK; error: @@ -899,6 +973,8 @@ CURLcode Curl_http(struct Curl_easy *data, bool *done) hyper_code code = hyper_error_code(hypererr); failf(data, "Hyper: [%d] %.*s", (int)code, (int)errlen, errbuf); hyper_error_free(hypererr); + if(data->state.hresult) + return data->state.hresult; } return CURLE_OUT_OF_MEMORY; } |