http2: move HTTP/2 stream vars into local context

- remove NGHTTP2 members of `struct HTTP`
- add `void *h2_ctx` to `struct HTTP`
- add `void *h3_ctx` to `struct HTTP`
- separate h2/h3 pointers are needed for eyeballing
- manage local stream_ctx in http implementations

Closes #10877
This commit is contained in:
Stefan Eissing 2023-04-06 11:59:12 +02:00 committed by Daniel Stenberg
parent 4ae2d9f24d
commit 632e0fbe70
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
5 changed files with 375 additions and 344 deletions

View File

@ -44,7 +44,7 @@ typedef enum {
#ifndef CURL_DISABLE_HTTP
#if defined(ENABLE_QUIC) || defined(USE_NGHTTP2)
#if defined(ENABLE_QUIC)
#include <stdint.h>
#endif
@ -212,44 +212,17 @@ struct HTTP {
HTTPSEND_BODY /* sending body */
} sending;
void *impl_ctx; /* context for actual HTTP implementation */
#ifdef USE_WEBSOCKETS
struct websocket ws;
#endif
#ifndef CURL_DISABLE_HTTP
void *h2_ctx; /* HTTP/2 implementation context */
void *h3_ctx; /* HTTP/3 implementation context */
struct dynbuf send_buffer; /* used if the request couldn't be sent in one
chunk, points to an allocated send_buffer
struct */
#endif
#ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */
struct bufq h2_sendbuf; /* request body data buffere for sending */
size_t h2_send_hds_len; /* amount of bytes in first cf_send() that
are header bytes. Or 0 if not known. */
struct bufq h2_recvbuf;
size_t h2_recv_hds_len; /* how many bytes in recvbuf are headers */
struct dynhds resp_trailers;
bool close_handled; /* TRUE if stream closure is handled by libcurl */
char **push_headers; /* allocated array */
size_t push_headers_used; /* number of entries filled in */
size_t push_headers_alloc; /* number of entries allocated */
uint32_t error; /* HTTP/2 stream error code */
bool bodystarted;
int status_code; /* HTTP status code */
char *mem; /* points to a buffer in memory to store received data */
size_t len; /* size of the buffer 'mem' points to */
size_t memlen; /* size of data copied to mem */
/* fields used by both HTTP/2 and HTTP/3 */
const uint8_t *upload_mem; /* points to a buffer to read from */
size_t upload_len; /* size of the buffer 'upload_mem' points to */
curl_off_t upload_left; /* number of bytes left to upload */
bool closed; /* TRUE on stream close */
bool reset; /* TRUE on stream reset */
#endif
};
CURLcode Curl_http_size(struct Curl_easy *data);

File diff suppressed because it is too large Load Diff

View File

@ -148,9 +148,9 @@ struct stream_ctx {
};
#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
((struct HTTP *)(d)->req.p.http)->impl_ctx \
((struct HTTP *)(d)->req.p.http)->h3_ctx \
: NULL))
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->impl_ctx
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
H3_STREAM_CTX(d)->id : -2)

View File

@ -186,9 +186,9 @@ struct stream_ctx {
};
#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
((struct HTTP *)(d)->req.p.http)->impl_ctx \
((struct HTTP *)(d)->req.p.http)->h3_ctx \
: NULL))
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->impl_ctx
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
H3_STREAM_CTX(d)->id : -2)
@ -198,6 +198,11 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf,
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
if(!data || !data->req.p.http) {
failf(data, "initialization failure, transfer not http initialized");
return CURLE_FAILED_INIT;
}
if(stream)
return CURLE_OK;
@ -1517,7 +1522,7 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
size_t len)
{
struct cf_ngtcp2_ctx *ctx = cf->ctx;
struct stream_ctx *stream = H3_STREAM_CTX(data);
struct stream_ctx *stream = NULL;
size_t nheader;
CURLcode result = CURLE_OK;
nghttp3_nv *nva = NULL;
@ -1527,6 +1532,11 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
nghttp3_data_reader reader;
nghttp3_data_reader *preader = NULL;
result = h3_data_setup(cf, data);
if(result)
goto out;
stream = H3_STREAM_CTX(data);
rc = ngtcp2_conn_open_bidi_stream(ctx->qconn, &stream->id, NULL);
if(rc) {
failf(data, "can get bidi streams");
@ -1579,7 +1589,7 @@ static CURLcode h3_stream_open(struct Curl_cfilter *cf,
stream->id, data->state.url));
out:
if(!result && rc) {
if(stream && !result && rc) {
switch(rc) {
case NGHTTP3_ERR_CONN_CLOSING:
DEBUGF(LOG_CF(data, cf, "h3sid[%"PRId64"] failed to send, "
@ -1612,13 +1622,13 @@ static ssize_t cf_ngtcp2_send(struct Curl_cfilter *cf, struct Curl_easy *data,
DEBUGASSERT(ctx->h3conn);
*err = CURLE_OK;
if(stream->closed) {
if(stream && stream->closed) {
*err = CURLE_HTTP3;
sent = -1;
goto out;
}
if(stream->id < 0) {
if(!stream || stream->id < 0) {
CURLcode result = h3_stream_open(cf, data, buf, len);
if(result) {
DEBUGF(LOG_CF(data, cf, "failed to open stream -> %d", result));
@ -2070,10 +2080,8 @@ static CURLcode cf_ngtcp2_data_event(struct Curl_cfilter *cf,
(void)arg1;
(void)arg2;
switch(event) {
case CF_CTRL_DATA_SETUP: {
result = h3_data_setup(cf, data);
case CF_CTRL_DATA_SETUP:
break;
}
case CF_CTRL_DATA_DONE: {
h3_data_done(cf, data);
break;
@ -2235,10 +2243,6 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf,
if(result)
return result;
result = h3_data_setup(cf, data);
if(result)
return result;
Curl_cf_socket_peek(cf->next, data, &ctx->q.sockfd,
&sockaddr, NULL, NULL, NULL, NULL);
ctx->q.local_addrlen = sizeof(ctx->q.local_addr);

View File

@ -197,9 +197,9 @@ struct stream_ctx {
};
#define H3_STREAM_CTX(d) ((struct stream_ctx *)(((d) && (d)->req.p.http)? \
((struct HTTP *)(d)->req.p.http)->impl_ctx \
((struct HTTP *)(d)->req.p.http)->h3_ctx \
: NULL))
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->impl_ctx
#define H3_STREAM_LCTX(d) ((struct HTTP *)(d)->req.p.http)->h3_ctx
#define H3_STREAM_ID(d) (H3_STREAM_CTX(d)? \
H3_STREAM_CTX(d)->id : -2)