summaryrefslogtreecommitdiffstats
path: root/Utilities/cmcurl/lib/http.c
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmcurl/lib/http.c')
-rw-r--r--Utilities/cmcurl/lib/http.c361
1 files changed, 197 insertions, 164 deletions
diff --git a/Utilities/cmcurl/lib/http.c b/Utilities/cmcurl/lib/http.c
index 9817d72..378d8f7 100644
--- a/Utilities/cmcurl/lib/http.c
+++ b/Utilities/cmcurl/lib/http.c
@@ -5,11 +5,11 @@
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
- * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 1998 - 2016, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
- * are also available at http://curl.haxx.se/docs/copyright.html.
+ * are also available at https://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
@@ -54,9 +54,10 @@
#include "curl_base64.h"
#include "cookie.h"
#include "strequal.h"
+#include "vauth/vauth.h"
#include "vtls/vtls.h"
#include "http_digest.h"
-#include "curl_ntlm.h"
+#include "http_ntlm.h"
#include "curl_ntlm_wb.h"
#include "http_negotiate.h"
#include "url.h"
@@ -76,9 +77,9 @@
#include "pipeline.h"
#include "http2.h"
#include "connect.h"
-#include "curl_printf.h"
-/* The last #include files should be: */
+/* The last 3 #include files should be in this order */
+#include "curl_printf.h"
#include "curl_memory.h"
#include "memdebug.h"
@@ -144,14 +145,13 @@ const struct Curl_handler Curl_handler_https = {
ZERO_NULL, /* readwrite */
PORT_HTTPS, /* defport */
CURLPROTO_HTTPS, /* protocol */
- PROTOPT_SSL | PROTOPT_CREDSPERREQUEST /* flags */
+ PROTOPT_SSL | PROTOPT_CREDSPERREQUEST | PROTOPT_ALPN_NPN /* flags */
};
#endif
-
CURLcode Curl_http_setup_conn(struct connectdata *conn)
{
- /* allocate the HTTP-specific struct for the SessionHandle, only to survive
+ /* allocate the HTTP-specific struct for the Curl_easy, only to survive
during this request */
struct HTTP *http;
DEBUGASSERT(conn->data->req.protop == NULL);
@@ -179,12 +179,13 @@ char *Curl_checkheaders(const struct connectdata *conn,
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
for(head = data->set.headers;head; head=head->next) {
if(Curl_raw_nequal(head->data, thisheader, thislen))
return head->data;
}
+
return NULL;
}
@@ -193,24 +194,24 @@ char *Curl_checkheaders(const struct connectdata *conn,
* if proxy headers are not available, then it will lookup into http header
* link list
*
- * It takes a connectdata struct as input instead of the SessionHandle simply
+ * It takes a connectdata struct as input instead of the Curl_easy simply
* to know if this is a proxy request or not, as it then might check a
* different header list.
- *
*/
char *Curl_checkProxyheaders(const struct connectdata *conn,
const char *thisheader)
{
struct curl_slist *head;
size_t thislen = strlen(thisheader);
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
- for(head = (conn->bits.proxy && data->set.sep_headers)?
- data->set.proxyheaders:data->set.headers;
+ for(head = (conn->bits.proxy && data->set.sep_headers) ?
+ data->set.proxyheaders : data->set.headers;
head; head=head->next) {
if(Curl_raw_nequal(head->data, thisheader, thislen))
return head->data;
}
+
return NULL;
}
@@ -279,7 +280,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
{
size_t size = 0;
char *authorization = NULL;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
char **userp;
const char *user;
const char *pwd;
@@ -309,7 +310,7 @@ static CURLcode http_output_basic(struct connectdata *conn, bool proxy)
free(*userp);
*userp = aprintf("%sAuthorization: Basic %s\r\n",
- proxy?"Proxy-":"",
+ proxy ? "Proxy-" : "",
authorization);
free(authorization);
if(!*userp)
@@ -376,7 +377,7 @@ static bool pickoneauth(struct auth *pick)
*/
static CURLcode http_perhapsrewind(struct connectdata *conn)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
curl_off_t bytessent;
curl_off_t expectsend = -1; /* default is unknown */
@@ -484,7 +485,7 @@ static CURLcode http_perhapsrewind(struct connectdata *conn)
CURLcode Curl_http_auth_act(struct connectdata *conn)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
bool pickhost = FALSE;
bool pickproxy = FALSE;
CURLcode result = CURLE_OK;
@@ -528,7 +529,6 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
return result;
}
}
-
else if((data->req.httpcode < 300) &&
(!data->state.authhost.done) &&
conn->bits.authneg) {
@@ -553,7 +553,6 @@ CURLcode Curl_http_auth_act(struct connectdata *conn)
return result;
}
-
/*
* Output the correct authentication header depending on the auth type
* and whether or not it is to a proxy.
@@ -567,12 +566,12 @@ output_auth_headers(struct connectdata *conn,
{
const char *auth = NULL;
CURLcode result = CURLE_OK;
-#if defined(USE_SPNEGO) || !defined(CURL_DISABLE_VERBOSE_STRINGS)
- struct SessionHandle *data = conn->data;
+#if !defined(CURL_DISABLE_VERBOSE_STRINGS) || defined(USE_SPNEGO)
+ struct Curl_easy *data = conn->data;
#endif
#ifdef USE_SPNEGO
- struct negotiatedata *negdata = proxy?
- &data->state.proxyneg:&data->state.negotiate;
+ struct negotiatedata *negdata = proxy ?
+ &data->state.proxyneg : &data->state.negotiate;
#endif
#ifdef CURL_DISABLE_CRYPTO_AUTH
@@ -584,7 +583,7 @@ output_auth_headers(struct connectdata *conn,
negdata->state = GSS_AUTHNONE;
if((authstatus->picked == CURLAUTH_NEGOTIATE) &&
negdata->context && !GSS_ERROR(negdata->status)) {
- auth="Negotiate";
+ auth = "Negotiate";
result = Curl_output_negotiate(conn, proxy);
if(result)
return result;
@@ -595,7 +594,7 @@ output_auth_headers(struct connectdata *conn,
#endif
#ifdef USE_NTLM
if(authstatus->picked == CURLAUTH_NTLM) {
- auth="NTLM";
+ auth = "NTLM";
result = Curl_output_ntlm(conn, proxy);
if(result)
return result;
@@ -613,7 +612,7 @@ output_auth_headers(struct connectdata *conn,
#endif
#ifndef CURL_DISABLE_CRYPTO_AUTH
if(authstatus->picked == CURLAUTH_DIGEST) {
- auth="Digest";
+ auth = "Digest";
result = Curl_output_digest(conn,
proxy,
(const unsigned char *)request,
@@ -629,11 +628,12 @@ output_auth_headers(struct connectdata *conn,
!Curl_checkProxyheaders(conn, "Proxy-authorization:")) ||
(!proxy && conn->bits.user_passwd &&
!Curl_checkheaders(conn, "Authorization:"))) {
- auth="Basic";
+ auth = "Basic";
result = http_output_basic(conn, proxy);
if(result)
return result;
}
+
/* NOTE: this function should set 'done' TRUE, as the other auth
functions work that way */
authstatus->done = TRUE;
@@ -641,9 +641,9 @@ output_auth_headers(struct connectdata *conn,
if(auth) {
infof(data, "%s auth using %s with user '%s'\n",
- proxy?"Proxy":"Server", auth,
- proxy?(conn->proxyuser?conn->proxyuser:""):
- (conn->user?conn->user:""));
+ proxy ? "Proxy" : "Server", auth,
+ proxy ? (conn->proxyuser ? conn->proxyuser : "") :
+ (conn->user ? conn->user : ""));
authstatus->multi = (!authstatus->done) ? TRUE : FALSE;
}
else
@@ -674,7 +674,7 @@ Curl_http_output_auth(struct connectdata *conn,
up the proxy tunnel */
{
CURLcode result = CURLE_OK;
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct auth *authhost;
struct auth *authproxy;
@@ -735,7 +735,6 @@ Curl_http_output_auth(struct connectdata *conn,
return result;
}
-
/*
* Curl_http_input_auth() deals with Proxy-Authenticate: and WWW-Authenticate:
* headers. They are dealt with both in the transfer.c main loop and in the
@@ -748,7 +747,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
/*
* This resource requires authentication
*/
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
#ifdef USE_SPNEGO
struct negotiatedata *negdata = proxy?
@@ -780,7 +779,6 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
* request is sent, and then it is again set _after_ all response 401/407
* headers have been received but then only to a single preferred method
* (bit).
- *
*/
while(*auth) {
@@ -893,6 +891,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
while(*auth && ISSPACE(*auth))
auth++;
}
+
return CURLE_OK;
}
@@ -908,7 +907,7 @@ CURLcode Curl_http_input_auth(struct connectdata *conn, bool proxy,
*/
static int http_should_fail(struct connectdata *conn)
{
- struct SessionHandle *data;
+ struct Curl_easy *data;
int httpcode;
DEBUGASSERT(conn);
@@ -934,8 +933,7 @@ static int http_should_fail(struct connectdata *conn)
** Any code >= 400 that's not 401 or 407 is always
** a terminal error
*/
- if((httpcode != 401) &&
- (httpcode != 407))
+ if((httpcode != 401) && (httpcode != 407))
return 1;
/*
@@ -986,7 +984,7 @@ static size_t readmoredata(char *buffer,
struct HTTP *http = conn->data->req.protop;
size_t fullsize = size * nitems;
- if(0 == http->postsize)
+ if(!http->postsize)
/* nothing to return */
return 0;
@@ -1001,8 +999,8 @@ static size_t readmoredata(char *buffer,
/* move backup data into focus and continue on that */
http->postdata = http->backup.postdata;
http->postsize = http->backup.postsize;
- conn->data->set.fread_func = http->backup.fread_func;
- conn->data->set.in = http->backup.fread_in;
+ conn->data->state.fread_func = http->backup.fread_func;
+ conn->data->state.in = http->backup.fread_in;
http->sending++; /* move one step up */
@@ -1092,15 +1090,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
return result;
}
-
- if(conn->handler->flags & PROTOPT_SSL) {
+ if((conn->handler->flags & PROTOPT_SSL) && conn->httpversion != 20) {
/* We never send more than CURL_MAX_WRITE_SIZE bytes in one single chunk
when we speak HTTPS, as if only a fraction of it is sent now, this data
needs to fit into the normal read-callback buffer later on and that
buffer is using this size.
*/
- sendsize= (size > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:size;
+ sendsize = (size > CURL_MAX_WRITE_SIZE) ? CURL_MAX_WRITE_SIZE : size;
/* OpenSSL is very picky and we must send the SAME buffer pointer to the
library when we attempt to re-send this buffer. Sending the same data
@@ -1123,7 +1120,7 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
* only send away a part).
*/
/* how much of the header that was sent */
- size_t headlen = (size_t)amount>headersize?headersize:(size_t)amount;
+ size_t headlen = (size_t)amount>headersize ? headersize : (size_t)amount;
size_t bodylen = amount - headlen;
if(conn->data->set.verbose) {
@@ -1136,10 +1133,6 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
ptr+headlen, bodylen, conn);
}
}
- if(bodylen)
- /* since we sent a piece of the body here, up the byte counter for it
- accordingly */
- http->writebytecount += bodylen;
/* 'amount' can never be a very large value here so typecasting it so a
signed 31 bit value should not cause problems even if ssize_t is
@@ -1147,6 +1140,10 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
*bytes_written += (long)amount;
if(http) {
+ /* if we sent a piece of the body here, up the byte counter for it
+ accordingly */
+ http->writebytecount += bodylen;
+
if((size_t)amount != size) {
/* The whole request could not be sent in one system call. We must
queue it up and send it later when we get the chance. We must not
@@ -1157,14 +1154,14 @@ CURLcode Curl_add_buffer_send(Curl_send_buffer *in,
ptr = in->buffer + amount;
/* backup the currently set pointers */
- http->backup.fread_func = conn->data->set.fread_func;
- http->backup.fread_in = conn->data->set.in;
+ http->backup.fread_func = conn->data->state.fread_func;
+ http->backup.fread_in = conn->data->state.in;
http->backup.postdata = http->postdata;
http->backup.postsize = http->postsize;
/* set the new pointers for the request-sending */
- conn->data->set.fread_func = (curl_read_callback)readmoredata;
- conn->data->set.in = (void *)conn;
+ conn->data->state.fread_func = (curl_read_callback)readmoredata;
+ conn->data->state.in = (void *)conn;
http->postdata = ptr;
http->postsize = (curl_off_t)size;
@@ -1242,11 +1239,11 @@ CURLcode Curl_add_buffer(Curl_send_buffer *in, const void *inptr, size_t size)
buffer size that doubles the required size. If this new size
would wrap size_t, then just use the largest possible one */
- if((size > (size_t)-1/2) || (in->size_used > (size_t)-1/2) ||
- (~(size*2) < (in->size_used*2)))
+ if((size > (size_t)-1 / 2) || (in->size_used > (size_t)-1 / 2) ||
+ (~(size * 2) < (in->size_used * 2)))
new_size = (size_t)-1;
else
- new_size = (in->size_used+size)*2;
+ new_size = (in->size_used+size) * 2;
if(in->buffer)
/* we have a buffer, enlarge the existing one */
@@ -1394,7 +1391,8 @@ static CURLcode https_connecting(struct connectdata *conn, bool *done)
#endif
#if defined(USE_OPENSSL) || defined(USE_GNUTLS) || defined(USE_SCHANNEL) || \
- defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS)
+ defined(USE_DARWINSSL) || defined(USE_POLARSSL) || defined(USE_NSS) || \
+ defined(USE_MBEDTLS)
/* This function is for OpenSSL, GnuTLS, darwinssl, schannel and polarssl only.
It should be made to query the generic SSL layer instead. */
static int https_getsock(struct connectdata *conn,
@@ -1418,6 +1416,7 @@ static int https_getsock(struct connectdata *conn,
return GETSOCK_READSOCK(0);
}
}
+
return CURLE_OK;
}
#else
@@ -1435,14 +1434,14 @@ static int https_getsock(struct connectdata *conn,
#endif /* USE_OPENSSL || USE_GNUTLS || USE_SCHANNEL */
/*
- * Curl_http_done() gets called from Curl_done() after a single HTTP request
- * has been performed.
+ * Curl_http_done() gets called after a single HTTP request has been
+ * performed.
*/
CURLcode Curl_http_done(struct connectdata *conn,
CURLcode status, bool premature)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
struct HTTP *http = data->req.protop;
#ifdef USE_NGHTTP2
struct http_conn *httpc = &conn->proto.httpc;
@@ -1455,8 +1454,10 @@ CURLcode Curl_http_done(struct connectdata *conn,
data->state.negotiate.state == GSS_AUTHSENT) {
/* add forbid re-use if http-code != 401/407 as a WA only needed for
* 401/407 that signal auth failure (empty) otherwise state will be RECV
- * with current code */
- if((data->req.httpcode != 401) && (data->req.httpcode != 407))
+ * with current code.
+ * Do not close CONNECT_ONLY connections. */
+ if((data->req.httpcode != 401) && (data->req.httpcode != 407) &&
+ !data->set.connect_only)
connclose(conn, "Negotiate transfer completed");
Curl_cleanup_negotiate(data);
}
@@ -1466,7 +1467,7 @@ CURLcode Curl_http_done(struct connectdata *conn,
conn->seek_func = data->set.seek_func; /* restore */
conn->seek_client = data->set.seek_client; /* restore */
- if(http == NULL)
+ if(!http)
return CURLE_OK;
if(http->send_buffer) {
@@ -1479,11 +1480,16 @@ CURLcode Curl_http_done(struct connectdata *conn,
DEBUGF(infof(data, "free header_recvbuf!!\n"));
Curl_add_buffer_free(http->header_recvbuf);
http->header_recvbuf = NULL; /* clear the pointer */
- for(; http->push_headers_used > 0; --http->push_headers_used) {
- free(http->push_headers[http->push_headers_used - 1]);
+ Curl_add_buffer_free(http->trailer_recvbuf);
+ http->trailer_recvbuf = NULL; /* clear the pointer */
+ if(http->push_headers) {
+ /* if they weren't used and then freed before */
+ for(; http->push_headers_used > 0; --http->push_headers_used) {
+ free(http->push_headers[http->push_headers_used - 1]);
+ }
+ free(http->push_headers);
+ http->push_headers = NULL;
}
- free(http->push_headers);
- http->push_headers = NULL;
}
if(http->stream_id) {
nghttp2_session_set_stream_user_data(httpc->h2, http->stream_id, 0);
@@ -1511,9 +1517,9 @@ CURLcode Curl_http_done(struct connectdata *conn,
entire operation is complete */
!conn->bits.retry &&
!data->set.connect_only &&
- ((http->readbytecount +
- data->req.headerbytecount -
- data->req.deductheadercount)) <= 0) {
+ (http->readbytecount +
+ data->req.headerbytecount -
+ data->req.deductheadercount) <= 0) {
/* If this connection isn't simply closed to be retried, AND nothing was
read from the HTTP server (that counts), this can't be right so we
return an error here */
@@ -1524,7 +1530,6 @@ CURLcode Curl_http_done(struct connectdata *conn,
return CURLE_OK;
}
-
/*
* Determine if we should use HTTP 1.1 (OR BETTER) for this request. Reasons
* to avoid it include:
@@ -1534,18 +1539,20 @@ CURLcode Curl_http_done(struct connectdata *conn,
* - if any server previously contacted to handle this request only supports
* 1.0.
*/
-static bool use_http_1_1plus(const struct SessionHandle *data,
+static bool use_http_1_1plus(const struct Curl_easy *data,
const struct connectdata *conn)
{
- return ((data->set.httpversion >= CURL_HTTP_VERSION_1_1) ||
- ((data->set.httpversion != CURL_HTTP_VERSION_1_0) &&
- ((conn->httpversion == 11) ||
- ((conn->httpversion != 10) &&
- (data->state.httpversion != 10))))) ? TRUE : FALSE;
+ if((data->state.httpversion == 10) || (conn->httpversion == 10))
+ return FALSE;
+ if((data->set.httpversion == CURL_HTTP_VERSION_1_0) &&
+ (conn->httpversion <= 10))
+ return FALSE;
+ return ((data->set.httpversion == CURL_HTTP_VERSION_NONE) ||
+ (data->set.httpversion >= CURL_HTTP_VERSION_1_1));
}
/* check and possibly add an Expect: header */
-static CURLcode expect100(struct SessionHandle *data,
+static CURLcode expect100(struct Curl_easy *data,
struct connectdata *conn,
Curl_send_buffer *req_buffer)
{
@@ -1570,6 +1577,7 @@ static CURLcode expect100(struct SessionHandle *data,
data->state.expect100header = TRUE;
}
}
+
return result;
}
@@ -1587,7 +1595,7 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
struct curl_slist *h[2];
struct curl_slist *headers;
int numlists=1; /* by default */
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
int i;
enum proxy_use proxy;
@@ -1688,16 +1696,23 @@ CURLcode Curl_add_custom_headers(struct connectdata *conn,
headers = headers->next;
}
}
+
return CURLE_OK;
}
-CURLcode Curl_add_timecondition(struct SessionHandle *data,
+CURLcode Curl_add_timecondition(struct Curl_easy *data,
Curl_send_buffer *req_buffer)
{
const struct tm *tm;
char *buf = data->state.buffer;
struct tm keeptime;
- CURLcode result = Curl_gmtime(data->set.timevalue, &keeptime);
+ CURLcode result;
+
+ if(data->set.timecondition == CURL_TIMECOND_NONE)
+ /* no condition was asked for */
+ return CURLE_OK;
+
+ result = Curl_gmtime(data->set.timevalue, &keeptime);
if(result) {
failf(data, "Invalid TIMEVALUE");
return result;
@@ -1723,8 +1738,9 @@ CURLcode Curl_add_timecondition(struct SessionHandle *data,
tm->tm_sec);
switch(data->set.timecondition) {
- case CURL_TIMECOND_IFMODSINCE:
default:
+ break;
+ case CURL_TIMECOND_IFMODSINCE:
result = Curl_add_bufferf(req_buffer,
"If-Modified-Since: %s\r\n", buf);
break;
@@ -1742,13 +1758,13 @@ CURLcode Curl_add_timecondition(struct SessionHandle *data,
}
/*
- * Curl_http() gets called from the generic Curl_do() function when a HTTP
+ * Curl_http() gets called from the generic multi_do() function when a HTTP
* request is to be performed. This creates and sends a properly constructed
* HTTP request.
*/
CURLcode Curl_http(struct connectdata *conn, bool *done)
{
- struct SessionHandle *data = conn->data;
+ struct Curl_easy *data = conn->data;
CURLcode result = CURLE_OK;
struct HTTP *http;
const char *ppath = data->state.path;
@@ -1776,15 +1792,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(conn->httpversion < 20) { /* unless the connection is re-used and already
http2 */
switch(conn->negnpn) {
- case CURL_HTTP_VERSION_2_0:
+ case CURL_HTTP_VERSION_2:
conn->httpversion = 20; /* we know we're on HTTP/2 now */
- result = Curl_http2_init(conn);
- if(result)
- return result;
-
- result = Curl_http2_setup(conn);
- if(result)
- return result;
result = Curl_http2_switched(conn, NULL, 0);
if(result)
@@ -1794,7 +1803,18 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
/* continue with HTTP/1.1 when explicitly requested */
break;
default:
- /* and as fallback */
+ /* Check if user wants to use HTTP/2 with clear TCP*/
+#ifdef USE_NGHTTP2
+ if(conn->data->set.httpversion ==
+ CURL_HTTP_VERSION_2_PRIOR_KNOWLEDGE) {
+ DEBUGF(infof(data, "HTTP/2 over clean TCP\n"));
+ conn->httpversion = 20;
+
+ result = Curl_http2_switched(conn, NULL, 0);
+ if(result)
+ return result;
+ }
+#endif
break;
}
}
@@ -1814,6 +1834,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
data->state.first_host = strdup(conn->host.name);
if(!data->state.first_host)
return CURLE_OUT_OF_MEMORY;
+
+ data->state.first_remote_port = conn->remote_port;
}
http->writebytecount = http->readbytecount = 0;
@@ -1895,6 +1917,10 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!conn->allocptr.accept_encoding)
return CURLE_OUT_OF_MEMORY;
}
+ else {
+ Curl_safefree(conn->allocptr.accept_encoding);
+ conn->allocptr.accept_encoding = NULL;
+ }
#ifdef HAVE_LIBZ
/* we only consider transfer-encoding magic if libz support is built-in */
@@ -2130,7 +2156,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* file size before we continue this venture in the dark lands of HTTP.
*********************************************************************/
- if(data->state.resume_from < 0 ) {
+ if(data->state.resume_from < 0) {
/*
* This is meant to get the size of the present remote-file by itself.
* We don't support this now. Bail out!
@@ -2162,8 +2188,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
BUFSIZE : curlx_sotouz(data->state.resume_from - passed);
size_t actuallyread =
- data->set.fread_func(data->state.buffer, 1, readthisamountnow,
- data->set.in);
+ data->state.fread_func(data->state.buffer, 1, readthisamountnow,
+ data->state.in);
passed += actuallyread;
if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
@@ -2279,7 +2305,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
"%s" /* TE: */
"%s" /* accept-encoding */
"%s" /* referer */
- "%s" /* Proxy-Connection */
"%s",/* transfer-encoding */
ftp_typecode,
@@ -2302,10 +2327,6 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
conn->allocptr.accept_encoding:"",
(data->change.referer && conn->allocptr.ref)?
conn->allocptr.ref:"" /* Referer: <data> */,
- (conn->bits.httpproxy &&
- !conn->bits.tunnel_proxy &&
- !Curl_checkProxyheaders(conn, "Proxy-Connection:"))?
- "Proxy-Connection: Keep-Alive\r\n":"",
te
);
@@ -2329,7 +2350,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
if(!(conn->handler->flags&PROTOPT_SSL) &&
conn->httpversion != 20 &&
- (data->set.httpversion == CURL_HTTP_VERSION_2_0)) {
+ (data->set.httpversion == CURL_HTTP_VERSION_2)) {
/* append HTTP2 upgrade magic stuff to the HTTP request if it isn't done
over SSL */
result = Curl_http2_request_upgrade(req_buffer, conn);
@@ -2390,11 +2411,9 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
}
#endif
- if(data->set.timecondition) {
- result = Curl_add_timecondition(data, req_buffer);
- if(result)
- return result;
- }
+ result = Curl_add_timecondition(data, req_buffer);
+ if(result)
+ return result;
result = Curl_add_custom_headers(conn, FALSE, req_buffer);
if(result)
@@ -2437,11 +2456,11 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
on. The data->set.fread_func pointer itself will be changed for the
multipart case to the function that returns a multipart formatted
stream. */
- http->form.fread_func = data->set.fread_func;
+ http->form.fread_func = data->state.fread_func;
/* Set the read function to read from the generated form data */
- data->set.fread_func = (curl_read_callback)Curl_FormReader;
- data->set.in = &http->form;
+ data->state.fread_func = (curl_read_callback)Curl_FormReader;
+ data->state.in = &http->form;
http->sending = HTTPSEND_BODY;
@@ -2659,8 +2678,8 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
http->sending = HTTPSEND_BODY;
- data->set.fread_func = (curl_read_callback)readmoredata;
- data->set.in = (void *)conn;
+ data->state.fread_func = (curl_read_callback)readmoredata;
+ data->state.in = (void *)conn;
/* set the upload size to the progress meter */
Curl_pgrsSetUploadSize(data, http->postsize);
@@ -2758,7 +2777,7 @@ CURLcode Curl_http(struct connectdata *conn, bool *done)
* Returns TRUE if member of the list matches prefix of string
*/
static bool
-checkhttpprefix(struct SessionHandle *data,
+checkhttpprefix(struct Curl_easy *data,
const char *s)
{
struct curl_slist *head = data->set.http200aliases;
@@ -2797,7 +2816,7 @@ checkhttpprefix(struct SessionHandle *data,
#ifndef CURL_DISABLE_RTSP
static bool
-checkrtspprefix(struct SessionHandle *data,
+checkrtspprefix(struct Curl_easy *data,
const char *s)
{
@@ -2825,7 +2844,7 @@ checkrtspprefix(struct SessionHandle *data,
#endif /* CURL_DISABLE_RTSP */
static bool
-checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
+checkprotoprefix(struct Curl_easy *data, struct connectdata *conn,
const char *s)
{
#ifndef CURL_DISABLE_RTSP
@@ -2843,7 +2862,7 @@ checkprotoprefix(struct SessionHandle *data, struct connectdata *conn,
* header. We make sure that the full string fit in the allocated header
* buffer, or else we enlarge it.
*/
-static CURLcode header_append(struct SessionHandle *data,
+static CURLcode header_append(struct Curl_easy *data,
struct SingleRequest *k,
size_t length)
{
@@ -2881,7 +2900,7 @@ static CURLcode header_append(struct SessionHandle *data,
return CURLE_OK;
}
-static void print_http_error(struct SessionHandle *data)
+static void print_http_error(struct Curl_easy *data)
{
struct SingleRequest *k = &data->req;
char *beg = k->p;
@@ -2921,7 +2940,7 @@ static void print_http_error(struct SessionHandle *data)
/*
* Read any HTTP header lines from the server and pass them to the client app.
*/
-CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
+CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
struct connectdata *conn,
ssize_t *nread,
bool *stop_reading)
@@ -3035,7 +3054,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
switch(k->httpcode) {
case 100:
/* if we did wait for this do enable write now! */
- if(k->exp100) {
+ if(k->exp100 > EXP100_SEND_DATA) {
k->exp100 = EXP100_SEND_DATA;
k->keepon |= KEEP_SEND;
}
@@ -3119,52 +3138,50 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
data->req.deductheadercount =
(100 <= k->httpcode && 199 >= k->httpcode)?data->req.headerbytecount:0;
- if(!*stop_reading) {
- /* Curl_http_auth_act() checks what authentication methods
- * that are available and decides which one (if any) to
- * use. It will set 'newurl' if an auth method was picked. */
- result = Curl_http_auth_act(conn);
+ /* Curl_http_auth_act() checks what authentication methods
+ * that are available and decides which one (if any) to
+ * use. It will set 'newurl' if an auth method was picked. */
+ result = Curl_http_auth_act(conn);
- if(result)
- return result;
+ if(result)
+ return result;
- if(k->httpcode >= 300) {
- if((!conn->bits.authneg) && !conn->bits.close &&
- !conn->bits.rewindaftersend) {
- /*
- * General treatment of errors when about to send data. Including :
- * "417 Expectation Failed", while waiting for 100-continue.
- *
- * The check for close above is done simply because of something
- * else has already deemed the connection to get closed then
- * something else should've considered the big picture and we
- * avoid this check.
- *
- * rewindaftersend indicates that something has told libcurl to
- * continue sending even if it gets discarded
+ if(k->httpcode >= 300) {
+ if((!conn->bits.authneg) && !conn->bits.close &&
+ !conn->bits.rewindaftersend) {
+ /*
+ * General treatment of errors when about to send data. Including :
+ * "417 Expectation Failed", while waiting for 100-continue.
+ *
+ * The check for close above is done simply because of something
+ * else has already deemed the connection to get closed then
+ * something else should've considered the big picture and we
+ * avoid this check.
+ *
+ * rewindaftersend indicates that something has told libcurl to
+ * continue sending even if it gets discarded
+ */
+
+ switch(data->set.httpreq) {
+ case HTTPREQ_PUT:
+ case HTTPREQ_POST:
+ case HTTPREQ_POST_FORM:
+ /* We got an error response. If this happened before the whole
+ * request body has been sent we stop sending and mark the
+ * connection for closure after we've read the entire response.
*/
-
- switch(data->set.httpreq) {
- case HTTPREQ_PUT:
- case HTTPREQ_POST:
- case HTTPREQ_POST_FORM:
- /* We got an error response. If this happened before the whole
- * request body has been sent we stop sending and mark the
- * connection for closure after we've read the entire response.
- */
- if(!k->upload_done) {
- infof(data, "HTTP error before end of send, stop sending\n");
- connclose(conn, "Stop sending data before everything sent");
- k->upload_done = TRUE;
- k->keepon &= ~KEEP_SEND; /* don't send */
- if(data->state.expect100header)
- k->exp100 = EXP100_FAILED;
- }
- break;
-
- default: /* default label present to avoid compiler warnings */
- break;
+ if(!k->upload_done) {
+ infof(data, "HTTP error before end of send, stop sending\n");
+ connclose(conn, "Stop sending data before everything sent");
+ k->upload_done = TRUE;
+ k->keepon &= ~KEEP_SEND; /* don't send */
+ if(data->state.expect100header)
+ k->exp100 = EXP100_FAILED;
}
+ break;
+
+ default: /* default label present to avoid compiler warnings */
+ break;
}
}
@@ -3185,6 +3202,16 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
*/
if(data->set.opt_no_body)
*stop_reading = TRUE;
+#ifndef CURL_DISABLE_RTSP
+ else if((conn->handler->protocol & CURLPROTO_RTSP) &&
+ (data->set.rtspreq == RTSPREQ_DESCRIBE) &&
+ (k->size <= -1))
+ /* Respect section 4.4 of rfc2326: If the Content-Length header is
+ absent, a length 0 must be assumed. It will prevent libcurl from
+ hanging on DESCRIBE request that got refused for whatever
+ reason */
+ *stop_reading = TRUE;
+#endif
else {
/* If we know the expected size of this document, we set the
maximum download size to the size of the expected
@@ -3279,6 +3306,13 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
&httpversion_major,
&conn->httpversion,
&k->httpcode);
+
+ if(nc == 1 && httpversion_major == 2 &&
+ 1 == sscanf(HEADER1, " HTTP/2 %d", &k->httpcode)) {
+ conn->httpversion = 0;
+ nc = 3;
+ }
+
if(nc==3) {
conn->httpversion += 10 * httpversion_major;
@@ -3576,8 +3610,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
}
else if(checkprefix("Content-Encoding:", k->p) &&
- (data->set.str[STRING_ENCODING] ||
- conn->httpversion == 20)) {
+ data->set.str[STRING_ENCODING]) {
/*
* Process Content-Encoding. Look for the values: identity,
* gzip, deflate, compress, x-gzip and x-compress. x-gzip and
@@ -3726,7 +3759,7 @@ CURLcode Curl_http_readwrite_headers(struct SessionHandle *data,
k->hbufp = data->state.headerbuff;
k->hbuflen = 0;
}
- while(!*stop_reading && *k->str); /* header line within buffer */
+ while(*k->str); /* header line within buffer */
/* We might have reached the end of the header part here, but
there might be a non-header part left in the end of the read