mirror of
https://github.com/curl/curl.git
synced 2026-05-30 04:47:29 +03:00
parent
30afc66b88
commit
17dc43ce6c
7 changed files with 97 additions and 112 deletions
103
lib/http1.c
103
lib/http1.c
|
|
@ -80,57 +80,58 @@ static CURLcode trim_line(struct h1_req_parser *parser, int options)
|
|||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static ssize_t detect_line(struct h1_req_parser *parser,
|
||||
const char *buf, const size_t buflen,
|
||||
CURLcode *err)
|
||||
static CURLcode detect_line(struct h1_req_parser *parser,
|
||||
const char *buf, const size_t buflen,
|
||||
size_t *pnread)
|
||||
{
|
||||
const char *line_end;
|
||||
|
||||
DEBUGASSERT(!parser->line);
|
||||
*pnread = 0;
|
||||
line_end = memchr(buf, '\n', buflen);
|
||||
if(!line_end) {
|
||||
*err = CURLE_AGAIN;
|
||||
return -1;
|
||||
}
|
||||
if(!line_end)
|
||||
return CURLE_AGAIN;
|
||||
parser->line = buf;
|
||||
parser->line_len = line_end - buf + 1;
|
||||
*err = CURLE_OK;
|
||||
return (ssize_t)parser->line_len;
|
||||
*pnread = parser->line_len;
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
||||
static ssize_t next_line(struct h1_req_parser *parser,
|
||||
const char *buf, const size_t buflen, int options,
|
||||
CURLcode *err)
|
||||
static CURLcode next_line(struct h1_req_parser *parser,
|
||||
const char *buf, const size_t buflen, int options,
|
||||
size_t *pnread)
|
||||
{
|
||||
ssize_t nread = 0;
|
||||
CURLcode result;
|
||||
|
||||
*pnread = 0;
|
||||
if(parser->line) {
|
||||
parser->line = NULL;
|
||||
parser->line_len = 0;
|
||||
curlx_dyn_reset(&parser->scratch);
|
||||
}
|
||||
|
||||
nread = detect_line(parser, buf, buflen, err);
|
||||
if(nread >= 0) {
|
||||
result = detect_line(parser, buf, buflen, pnread);
|
||||
if(!result) {
|
||||
if(curlx_dyn_len(&parser->scratch)) {
|
||||
/* append detected line to scratch to have the complete line */
|
||||
*err = curlx_dyn_addn(&parser->scratch, parser->line, parser->line_len);
|
||||
if(*err)
|
||||
return -1;
|
||||
result = curlx_dyn_addn(&parser->scratch, parser->line,
|
||||
parser->line_len);
|
||||
if(result)
|
||||
return result;
|
||||
parser->line = curlx_dyn_ptr(&parser->scratch);
|
||||
parser->line_len = curlx_dyn_len(&parser->scratch);
|
||||
}
|
||||
*err = trim_line(parser, options);
|
||||
if(*err)
|
||||
return -1;
|
||||
result = trim_line(parser, options);
|
||||
if(result)
|
||||
return result;
|
||||
}
|
||||
else if(*err == CURLE_AGAIN) {
|
||||
else if(result == CURLE_AGAIN) {
|
||||
/* no line end in `buf`, add it to our scratch */
|
||||
*err = curlx_dyn_addn(&parser->scratch, (const unsigned char *)buf,
|
||||
buflen);
|
||||
nread = (*err) ? -1 : (ssize_t)buflen;
|
||||
result = curlx_dyn_addn(&parser->scratch, (const unsigned char *)buf,
|
||||
buflen);
|
||||
*pnread = buflen;
|
||||
}
|
||||
return nread;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode start_req(struct h1_req_parser *parser,
|
||||
|
|
@ -264,29 +265,28 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
||||
const char *buf, size_t buflen,
|
||||
const char *scheme_default,
|
||||
const char *custom_method,
|
||||
int options, CURLcode *err)
|
||||
CURLcode Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
||||
const char *buf, size_t buflen,
|
||||
const char *scheme_default,
|
||||
const char *custom_method,
|
||||
int options, size_t *pnread)
|
||||
{
|
||||
ssize_t nread = 0, n;
|
||||
CURLcode result = CURLE_OK;
|
||||
size_t nread;
|
||||
|
||||
*err = CURLE_OK;
|
||||
*pnread = 0;
|
||||
while(!parser->done) {
|
||||
n = next_line(parser, buf, buflen, options, err);
|
||||
if(n < 0) {
|
||||
if(*err != CURLE_AGAIN) {
|
||||
nread = -1;
|
||||
}
|
||||
*err = CURLE_OK;
|
||||
result = next_line(parser, buf, buflen, options, &nread);
|
||||
if(result) {
|
||||
if(result == CURLE_AGAIN)
|
||||
result = CURLE_OK;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Consume this line */
|
||||
nread += (size_t)n;
|
||||
buf += (size_t)n;
|
||||
buflen -= (size_t)n;
|
||||
*pnread += nread;
|
||||
buf += nread;
|
||||
buflen -= nread;
|
||||
|
||||
if(!parser->line) {
|
||||
/* consumed bytes, but line not complete */
|
||||
|
|
@ -294,17 +294,14 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
|||
goto out;
|
||||
}
|
||||
else if(!parser->req) {
|
||||
*err = start_req(parser, scheme_default, custom_method, options);
|
||||
if(*err) {
|
||||
nread = -1;
|
||||
result = start_req(parser, scheme_default, custom_method, options);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
else if(parser->line_len == 0) {
|
||||
/* last, empty line, we are finished */
|
||||
if(!parser->req) {
|
||||
*err = CURLE_URL_MALFORMAT;
|
||||
nread = -1;
|
||||
result = CURLE_URL_MALFORMAT;
|
||||
goto out;
|
||||
}
|
||||
parser->done = TRUE;
|
||||
|
|
@ -312,17 +309,15 @@ ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
|||
/* last chance adjustments */
|
||||
}
|
||||
else {
|
||||
*err = Curl_dynhds_h1_add_line(&parser->req->headers,
|
||||
parser->line, parser->line_len);
|
||||
if(*err) {
|
||||
nread = -1;
|
||||
result = Curl_dynhds_h1_add_line(&parser->req->headers,
|
||||
parser->line, parser->line_len);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
return nread;
|
||||
return result;
|
||||
}
|
||||
|
||||
CURLcode Curl_h1_req_write_head(struct httpreq *req, int http_minor,
|
||||
|
|
|
|||
10
lib/http1.h
10
lib/http1.h
|
|
@ -48,11 +48,11 @@ struct h1_req_parser {
|
|||
void Curl_h1_req_parse_init(struct h1_req_parser *parser, size_t max_line_len);
|
||||
void Curl_h1_req_parse_free(struct h1_req_parser *parser);
|
||||
|
||||
ssize_t Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
||||
const char *buf, size_t buflen,
|
||||
const char *scheme_default,
|
||||
const char *custom_method,
|
||||
int options, CURLcode *err);
|
||||
CURLcode Curl_h1_req_parse_read(struct h1_req_parser *parser,
|
||||
const char *buf, size_t buflen,
|
||||
const char *scheme_default,
|
||||
const char *custom_method,
|
||||
int options, size_t *pnread);
|
||||
|
||||
CURLcode Curl_h1_req_dprint(const struct httpreq *req,
|
||||
struct dynbuf *dbuf);
|
||||
|
|
|
|||
11
lib/http2.c
11
lib/http2.c
|
|
@ -2237,7 +2237,6 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
|
|||
nghttp2_data_provider data_prd;
|
||||
int32_t stream_id;
|
||||
nghttp2_priority_spec pri_spec;
|
||||
ssize_t rc;
|
||||
size_t nwritten;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
|
|
@ -2248,11 +2247,11 @@ static CURLcode h2_submit(struct h2_stream_ctx **pstream,
|
|||
if(result)
|
||||
goto out;
|
||||
|
||||
rc = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, &result);
|
||||
if(!curlx_sztouz(rc, &nwritten))
|
||||
result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, &nwritten);
|
||||
if(result)
|
||||
goto out;
|
||||
*pnwritten = nwritten;
|
||||
if(!stream->h1.done) {
|
||||
|
|
|
|||
|
|
@ -1513,7 +1513,6 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
|
|||
nghttp3_nv *nva = NULL;
|
||||
int rc = 0;
|
||||
unsigned int i;
|
||||
ssize_t nwritten = -1;
|
||||
nghttp3_data_reader reader;
|
||||
nghttp3_data_reader *preader = NULL;
|
||||
CURLcode result;
|
||||
|
|
@ -1531,13 +1530,12 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
|
|||
goto out;
|
||||
}
|
||||
|
||||
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, &result);
|
||||
if(nwritten < 0)
|
||||
result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, pnwritten);
|
||||
if(result)
|
||||
goto out;
|
||||
*pnwritten = (size_t)nwritten;
|
||||
|
||||
if(!stream->h1.done) {
|
||||
/* need more data */
|
||||
|
|
|
|||
|
|
@ -1872,10 +1872,10 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const void *buf, size_t len,
|
||||
CURLcode *err)
|
||||
static CURLcode h3_stream_open(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
const void *buf, size_t len,
|
||||
size_t *pnwritten)
|
||||
{
|
||||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
struct h3_stream_ctx *stream = NULL;
|
||||
|
|
@ -1884,27 +1884,27 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
nghttp3_nv *nva = NULL;
|
||||
int rc = 0;
|
||||
unsigned int i;
|
||||
ssize_t nwritten = -1;
|
||||
nghttp3_data_reader reader;
|
||||
nghttp3_data_reader *preader = NULL;
|
||||
CURLcode result;
|
||||
|
||||
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
|
||||
|
||||
*err = h3_data_setup(cf, data);
|
||||
if(*err)
|
||||
result = h3_data_setup(cf, data);
|
||||
if(result)
|
||||
goto out;
|
||||
stream = H3_STREAM_CTX(ctx, data);
|
||||
DEBUGASSERT(stream);
|
||||
if(!stream) {
|
||||
*err = CURLE_FAILED_INIT;
|
||||
result = CURLE_FAILED_INIT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, err);
|
||||
if(nwritten < 0)
|
||||
result = Curl_h1_req_parse_read(&stream->h1, buf, len, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, pnwritten);
|
||||
if(result)
|
||||
goto out;
|
||||
if(!stream->h1.done) {
|
||||
/* need more data */
|
||||
|
|
@ -1912,19 +1912,16 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
}
|
||||
DEBUGASSERT(stream->h1.req);
|
||||
|
||||
*err = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
|
||||
if(*err) {
|
||||
nwritten = -1;
|
||||
result = Curl_http_req_to_h2(&h2_headers, stream->h1.req, data);
|
||||
if(result)
|
||||
goto out;
|
||||
}
|
||||
/* no longer needed */
|
||||
Curl_h1_req_parse_free(&stream->h1);
|
||||
|
||||
nheader = Curl_dynhds_count(&h2_headers);
|
||||
nva = malloc(sizeof(nghttp3_nv) * nheader);
|
||||
if(!nva) {
|
||||
*err = CURLE_OUT_OF_MEMORY;
|
||||
nwritten = -1;
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1938,11 +1935,11 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
DEBUGASSERT(stream->s.id == -1);
|
||||
*err = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0,
|
||||
&ctx->stream_bufcp, data);
|
||||
if(*err) {
|
||||
result = cf_osslq_stream_open(&stream->s, ctx->tls.ossl.ssl, 0,
|
||||
&ctx->stream_bufcp, data);
|
||||
if(result) {
|
||||
failf(data, "cannot get bidi streams");
|
||||
*err = CURLE_SEND_ERROR;
|
||||
result = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -1983,8 +1980,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
stream->s.id, rc, nghttp3_strerror(rc));
|
||||
break;
|
||||
}
|
||||
*err = CURLE_SEND_ERROR;
|
||||
nwritten = -1;
|
||||
result = CURLE_SEND_ERROR;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
|
@ -2002,7 +1998,7 @@ static ssize_t h3_stream_open(struct Curl_cfilter *cf,
|
|||
out:
|
||||
free(nva);
|
||||
Curl_dynhds_free(&h2_headers);
|
||||
return nwritten;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
|
|
@ -2012,7 +2008,6 @@ static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
struct h3_stream_ctx *stream = NULL;
|
||||
struct cf_call_data save;
|
||||
ssize_t nwritten;
|
||||
CURLcode result = CURLE_OK;
|
||||
|
||||
(void)eos; /* use to end stream */
|
||||
|
|
@ -2032,13 +2027,12 @@ static CURLcode cf_osslq_send(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
|
||||
stream = H3_STREAM_CTX(ctx, data);
|
||||
if(!stream || stream->s.id < 0) {
|
||||
nwritten = h3_stream_open(cf, data, buf, len, &result);
|
||||
if(nwritten < 0) {
|
||||
result = h3_stream_open(cf, data, buf, len, pnwritten);
|
||||
if(result) {
|
||||
CURL_TRC_CF(data, cf, "failed to open stream -> %d", result);
|
||||
goto out;
|
||||
}
|
||||
stream = H3_STREAM_CTX(ctx, data);
|
||||
*pnwritten = (size_t)nwritten;
|
||||
}
|
||||
else if(stream->closed) {
|
||||
if(stream->resp_hds_complete) {
|
||||
|
|
|
|||
|
|
@ -977,7 +977,6 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
|
|||
struct dynhds h2_headers;
|
||||
quiche_h3_header *nva = NULL;
|
||||
CURLcode result = CURLE_OK;
|
||||
ssize_t nwritten;
|
||||
|
||||
*pnwritten = 0;
|
||||
if(!stream) {
|
||||
|
|
@ -991,11 +990,12 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
|
|||
Curl_dynhds_init(&h2_headers, 0, DYN_HTTP_REQUEST);
|
||||
|
||||
DEBUGASSERT(stream);
|
||||
nwritten = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL,
|
||||
|
||||
result = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, &result);
|
||||
if(nwritten < 0)
|
||||
0, pnwritten);
|
||||
if(result)
|
||||
goto out;
|
||||
if(!stream->h1.done) {
|
||||
/* need more data */
|
||||
|
|
@ -1025,7 +1025,6 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
|
|||
nva[i].value_len = e->valuelen;
|
||||
}
|
||||
|
||||
*pnwritten = (size_t)nwritten;
|
||||
buf += *pnwritten;
|
||||
blen -= *pnwritten;
|
||||
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ static void parse_success(const struct tcase *t)
|
|||
const char *buf;
|
||||
size_t buflen, i, in_len, in_consumed;
|
||||
CURLcode err;
|
||||
ssize_t nread;
|
||||
size_t nread;
|
||||
|
||||
Curl_h1_req_parse_init(&p, 1024);
|
||||
in_len = in_consumed = 0;
|
||||
|
|
@ -74,14 +74,14 @@ static void parse_success(const struct tcase *t)
|
|||
buf = t->input[i];
|
||||
buflen = strlen(buf);
|
||||
in_len += buflen;
|
||||
nread = Curl_h1_req_parse_read(&p, buf, buflen, t->default_scheme,
|
||||
t->custom_method, 0, &err);
|
||||
if(nread < 0) {
|
||||
err = Curl_h1_req_parse_read(&p, buf, buflen, t->default_scheme,
|
||||
t->custom_method, 0, &nread);
|
||||
if(err) {
|
||||
curl_mfprintf(stderr, "got err %d parsing: '%s'\n", err, buf);
|
||||
fail("error consuming");
|
||||
}
|
||||
in_consumed += (size_t)nread;
|
||||
if((size_t)nread != buflen) {
|
||||
if(nread != buflen) {
|
||||
if(!p.done) {
|
||||
curl_mfprintf(stderr, "only %zd/%zu consumed for: '%s'\n",
|
||||
nread, buflen, buf);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue