aboutsummaryrefslogtreecommitdiff
path: root/lib/http.c
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2007-10-02 10:21:36 +0000
committerDaniel Stenberg <daniel@haxx.se>2007-10-02 10:21:36 +0000
commit119364741ef2ca0931c0ceaa6f92cb476457863c (patch)
tree32897c5dba0c6f2b2d5a298c8fb18de18617a082 /lib/http.c
parent8d1239c091ef61725e6ce3c53b92b45a71f6f927 (diff)
known bug #46: chunked-encoded CONNECT responses from a http proxy now works.
Added test case 1008 to verify. Note that #47 is still there.
Diffstat (limited to 'lib/http.c')
-rw-r--r--lib/http.c169
1 files changed, 120 insertions, 49 deletions
diff --git a/lib/http.c b/lib/http.c
index 67b2d3f55..90f56f1ba 100644
--- a/lib/http.c
+++ b/lib/http.c
@@ -1143,6 +1143,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
curl_socket_t tunnelsocket = conn->sock[sockindex];
curl_off_t cl=0;
bool closeConnection = FALSE;
+ bool chunked_encoding = FALSE;
long check;
#define SELECT_OK 0
@@ -1203,37 +1204,37 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
data->set.str[STRING_USERAGENT])
useragent = conn->allocptr.uagent;
- /* Send the connect request to the proxy */
- /* BLOCKING */
- result =
- add_bufferf(req_buffer,
- "CONNECT %s:%d HTTP/1.0\r\n"
- "%s" /* Host: */
- "%s" /* Proxy-Authorization */
- "%s" /* User-Agent */
- "%s", /* Proxy-Connection */
- hostname, remote_port,
- host,
- conn->allocptr.proxyuserpwd?
- conn->allocptr.proxyuserpwd:"",
- useragent,
- proxyconn);
-
- if(host && *host)
- free(host);
-
- if(CURLE_OK == result)
- result = add_custom_headers(conn, req_buffer);
-
- if(CURLE_OK == result)
- /* CRLF terminate the request */
- result = add_bufferf(req_buffer, "\r\n");
-
- if(CURLE_OK == result) {
- /* Now send off the request */
- result = add_buffer_send(req_buffer, conn,
- &data->info.request_size, 0, sockindex);
- }
+ /* Send the connect request to the proxy */
+ /* BLOCKING */
+ result =
+ add_bufferf(req_buffer,
+ "CONNECT %s:%d HTTP/1.0\r\n"
+ "%s" /* Host: */
+ "%s" /* Proxy-Authorization */
+ "%s" /* User-Agent */
+ "%s", /* Proxy-Connection */
+ hostname, remote_port,
+ host,
+ conn->allocptr.proxyuserpwd?
+ conn->allocptr.proxyuserpwd:"",
+ useragent,
+ proxyconn);
+
+ if(host && *host)
+ free(host);
+
+ if(CURLE_OK == result)
+ result = add_custom_headers(conn, req_buffer);
+
+ if(CURLE_OK == result)
+ /* CRLF terminate the request */
+ result = add_bufferf(req_buffer, "\r\n");
+
+ if(CURLE_OK == result) {
+ /* Now send off the request */
+ result = add_buffer_send(req_buffer, conn,
+ &data->info.request_size, 0, sockindex);
+ }
req_buffer = NULL;
if(result)
failf(data, "Failed sending CONNECT to proxy");
@@ -1340,13 +1341,33 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
nread += gotbytes;
if(keepon > TRUE) {
- /* This means we are currently ignoring a response-body, so we
- simply count down our counter and make sure to break out of
- the loop when we're done! */
- cl -= gotbytes;
- if(cl<=0) {
- keepon = FALSE;
- break;
+ /* This means we are currently ignoring a response-body */
+ if(cl) {
+ /* A Content-Length based body: simply count down the counter
+ and make sure to break out of the loop when we're done! */
+ cl -= gotbytes;
+ if(cl<=0) {
+ keepon = FALSE;
+ break;
+ }
+ }
+ else {
+ /* chunked-encoded body, so we need to do the chunked dance
+ properly to know when the end of the body is reached */
+ CHUNKcode r;
+ 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, ptr, gotbytes, &tookcareof);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ }
+ else
+ infof(data, "Read %d bytes of chunk, continue\n",
+ tookcareof);
}
}
else
@@ -1366,7 +1387,8 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(data->set.include_header)
writetype |= CLIENTWRITE_BODY;
- result = Curl_client_write(conn, writetype, line_start, perline);
+ result = Curl_client_write(conn, writetype, line_start,
+ perline);
if(result)
return result;
@@ -1377,19 +1399,60 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
if(('\r' == line_start[0]) ||
('\n' == line_start[0])) {
/* end of response-headers from the proxy */
- if(cl && (407 == k->httpcode) &&
- !data->state.authproblem) {
+ if((407 == k->httpcode) && !data->state.authproblem) {
/* If we get a 407 response code with content length
- * when we have no auth problem, we must ignore the
- * whole response-body */
+ when we have no auth problem, we must ignore the
+ whole response-body */
keepon = 2;
- infof(data, "Ignore %" FORMAT_OFF_T
- " bytes of response-body\n", cl);
- cl -= (gotbytes - i);/* remove the remaining chunk of
- what we already read */
- if(cl<=0)
- /* if the whole thing was already read, we are done! */
+
+ if(cl) {
+
+ infof(data, "Ignore %" FORMAT_OFF_T
+ " bytes of response-body\n", cl);
+ /* remove the remaining chunk of what we already
+ read */
+ cl -= (gotbytes - i);
+
+ if(cl<=0)
+ /* if the whole thing was already read, we are done!
+ */
+ keepon=FALSE;
+ }
+ else if(chunked_encoding) {
+ CHUNKcode r;
+ /* We set ignorebody true here since the chunked
+ decoder function will acknowledge that. Pay
+ attention so that this is cleared again when this
+ function returns! */
+ k->ignorebody = TRUE;
+ infof(data, "%d bytes of chunk left\n", gotbytes-i);
+
+ if(line_start[1] == '\n') {
+ /* this can only be a LF if the letter at index 0
+ was a CR */
+ line_start++;
+ i++;
+ }
+
+ /* now parse the chunked piece of data so that we can
+ properly tell when the stream ends */
+ r = Curl_httpchunk_read(conn, line_start+1,
+ gotbytes -i, &gotbytes);
+ if(r == CHUNKE_STOP) {
+ /* we're done reading chunks! */
+ infof(data, "chunk reading DONE\n");
+ keepon = FALSE;
+ }
+ else
+ infof(data, "Read %d bytes of chunk, continue\n",
+ gotbytes);
+ }
+ else {
+ /* without content-length or chunked encoding, we
+ can't keep the connection alive since the close is
+ the end signal so we bail out at once instead */
keepon=FALSE;
+ }
}
else
keepon = FALSE;
@@ -1416,6 +1479,13 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
"Connection:", "close"))
closeConnection = TRUE;
else if(Curl_compareheader(line_start,
+ "Transfer-Encoding:", "chunked")) {
+ infof(data, "CONNECT responded chunked\n");
+ chunked_encoding = TRUE;
+ /* init our chunky engine */
+ Curl_httpchunk_init(conn);
+ }
+ else if(Curl_compareheader(line_start,
"Proxy-Connection:", "close"))
closeConnection = TRUE;
else if(2 == sscanf(line_start, "HTTP/1.%d %d",
@@ -1472,6 +1542,7 @@ CURLcode Curl_proxyCONNECT(struct connectdata *conn,
data->state.authproxy.done = TRUE;
infof (data, "Proxy replied OK to CONNECT request\n");
+ k->ignorebody = FALSE; /* put it (back) to non-ignore state */
return CURLE_OK;
}