mirror of
https://github.com/curl/curl.git
synced 2026-07-28 11:23:12 +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
68
lib/http.c
68
lib/http.c
|
|
@ -3995,36 +3995,32 @@ CURLcode Curl_bump_headersize(struct Curl_easy *data,
|
|||
*/
|
||||
CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
||||
struct connectdata *conn,
|
||||
ssize_t *nread,
|
||||
const char *buf, size_t blen,
|
||||
size_t *pconsumed,
|
||||
bool *stop_reading)
|
||||
{
|
||||
CURLcode result;
|
||||
struct SingleRequest *k = &data->req;
|
||||
ssize_t onread = *nread;
|
||||
char *ostr = k->str;
|
||||
char *headp;
|
||||
char *str_start;
|
||||
char *end_ptr;
|
||||
|
||||
/* header line within buffer loop */
|
||||
*stop_reading = FALSE;
|
||||
*pconsumed = 0;
|
||||
do {
|
||||
size_t rest_length;
|
||||
size_t full_length;
|
||||
size_t line_length;
|
||||
int writetype;
|
||||
|
||||
/* str_start is start of line within buf */
|
||||
str_start = k->str;
|
||||
|
||||
/* data is in network encoding so use 0x0a instead of '\n' */
|
||||
end_ptr = memchr(str_start, 0x0a, *nread);
|
||||
end_ptr = memchr(buf, 0x0a, blen);
|
||||
|
||||
if(!end_ptr) {
|
||||
/* Not a complete header line within buffer, append the data to
|
||||
the end of the headerbuff. */
|
||||
result = Curl_dyn_addn(&data->state.headerb, str_start, *nread);
|
||||
result = Curl_dyn_addn(&data->state.headerb, buf, blen);
|
||||
if(result)
|
||||
return result;
|
||||
*pconsumed += blen;
|
||||
|
||||
if(!k->headerline) {
|
||||
/* check if this looks like a protocol header */
|
||||
|
|
@ -4036,31 +4032,28 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
|||
if(st == STATUS_BAD) {
|
||||
/* this is not the beginning of a protocol first header line */
|
||||
k->header = FALSE;
|
||||
k->badheader = HEADER_ALLBAD;
|
||||
k->badheader = TRUE;
|
||||
streamclose(conn, "bad HTTP: No end-of-message indicator");
|
||||
if(!data->set.http09_allowed) {
|
||||
failf(data, "Received HTTP/0.9 when not allowed");
|
||||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
break;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
*nread = 0;
|
||||
break; /* read more and try again */
|
||||
goto out; /* read more and try again */
|
||||
}
|
||||
|
||||
/* decrease the size of the remaining (supposed) header line */
|
||||
rest_length = (end_ptr - k->str) + 1;
|
||||
*nread -= (ssize_t)rest_length;
|
||||
|
||||
k->str = end_ptr + 1; /* move past new line */
|
||||
|
||||
full_length = k->str - str_start;
|
||||
|
||||
result = Curl_dyn_addn(&data->state.headerb, str_start, full_length);
|
||||
line_length = (end_ptr - buf) + 1;
|
||||
result = Curl_dyn_addn(&data->state.headerb, buf, line_length);
|
||||
if(result)
|
||||
return result;
|
||||
|
||||
blen -= line_length;
|
||||
buf += line_length;
|
||||
*pconsumed += line_length;
|
||||
|
||||
/****
|
||||
* We now have a FULL header line in 'headerb'.
|
||||
*****/
|
||||
|
|
@ -4078,14 +4071,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
|||
return CURLE_UNSUPPORTED_PROTOCOL;
|
||||
}
|
||||
k->header = FALSE;
|
||||
if(*nread)
|
||||
if(blen)
|
||||
/* since there's more, this is a partial bad header */
|
||||
k->badheader = HEADER_PARTHEADER;
|
||||
k->badheader = TRUE;
|
||||
else {
|
||||
/* this was all we read so it's all a bad header */
|
||||
k->badheader = HEADER_ALLBAD;
|
||||
*nread = onread;
|
||||
k->str = ostr;
|
||||
k->badheader = TRUE;
|
||||
return CURLE_OK;
|
||||
}
|
||||
break;
|
||||
|
|
@ -4139,22 +4130,23 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
|||
|
||||
/* switch to http2 now. The bytes after response headers
|
||||
are also processed here, otherwise they are lost. */
|
||||
result = Curl_http2_upgrade(data, conn, FIRSTSOCKET,
|
||||
k->str, *nread);
|
||||
result = Curl_http2_upgrade(data, conn, FIRSTSOCKET, buf, blen);
|
||||
if(result)
|
||||
return result;
|
||||
*nread = 0;
|
||||
*pconsumed += blen;
|
||||
blen = 0;
|
||||
}
|
||||
#ifdef USE_WEBSOCKETS
|
||||
else if(k->upgr101 == UPGR101_WS) {
|
||||
/* verify the response */
|
||||
result = Curl_ws_accept(data, k->str, *nread);
|
||||
result = Curl_ws_accept(data, buf, blen);
|
||||
if(result)
|
||||
return result;
|
||||
k->header = FALSE; /* no more header to parse! */
|
||||
if(data->set.connect_only) {
|
||||
k->keepon &= ~KEEP_RECV; /* read no more content */
|
||||
*nread = 0;
|
||||
*pconsumed += blen;
|
||||
blen = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -4393,8 +4385,10 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
|||
k->keepon &= ~KEEP_RECV;
|
||||
}
|
||||
|
||||
Curl_debug(data, CURLINFO_HEADER_IN, str_start, headerlen);
|
||||
break; /* exit header line loop */
|
||||
Curl_debug(data, CURLINFO_HEADER_IN,
|
||||
Curl_dyn_ptr(&data->state.headerb),
|
||||
Curl_dyn_len(&data->state.headerb));
|
||||
goto out; /* exit header line loop */
|
||||
}
|
||||
|
||||
/* We continue reading headers, reset the line-based header */
|
||||
|
|
@ -4583,12 +4577,12 @@ CURLcode Curl_http_readwrite_headers(struct Curl_easy *data,
|
|||
|
||||
Curl_dyn_reset(&data->state.headerb);
|
||||
}
|
||||
while(*k->str); /* header line within buffer */
|
||||
while(blen);
|
||||
|
||||
/* 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
|
||||
buffer. */
|
||||
|
||||
out:
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue