mirror of
https://github.com/curl/curl.git
synced 2026-08-25 10:03:37 +03:00
parent
0eed8b7330
commit
2253bc330f
64 changed files with 1218 additions and 1416 deletions
|
|
@ -72,14 +72,14 @@
|
|||
#include "../curlx/warnless.h"
|
||||
|
||||
|
||||
#define QUIC_MAX_STREAMS (256*1024)
|
||||
#define QUIC_HANDSHAKE_TIMEOUT (10*NGTCP2_SECONDS)
|
||||
#define QUIC_MAX_STREAMS (256 * 1024)
|
||||
#define QUIC_HANDSHAKE_TIMEOUT (10 * NGTCP2_SECONDS)
|
||||
|
||||
/* A stream window is the maximum amount we need to buffer for
|
||||
* each active transfer.
|
||||
* Chunk size is large enough to take a full DATA frame */
|
||||
#define H3_STREAM_WINDOW_SIZE (64 * 1024)
|
||||
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
|
||||
#define H3_STREAM_CHUNK_SIZE (16 * 1024)
|
||||
#if H3_STREAM_CHUNK_SIZE < NGTCP2_MAX_UDP_PAYLOAD_SIZE
|
||||
#error H3_STREAM_CHUNK_SIZE smaller than NGTCP2_MAX_UDP_PAYLOAD_SIZE
|
||||
#endif
|
||||
|
|
@ -150,8 +150,7 @@ struct cf_ngtcp2_ctx {
|
|||
|
||||
/* How to access `call_data` from a cf_ngtcp2 filter */
|
||||
#undef CF_CTX_CALL_DATA
|
||||
#define CF_CTX_CALL_DATA(cf) \
|
||||
((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
|
||||
#define CF_CTX_CALL_DATA(cf) ((struct cf_ngtcp2_ctx *)(cf)->ctx)->call_data
|
||||
|
||||
static void h3_stream_hash_free(unsigned int id, void *stream);
|
||||
|
||||
|
|
@ -187,14 +186,14 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
|
|||
struct cf_ngtcp2_ctx *ctx = cf->ctx;
|
||||
const ngtcp2_transport_params *rp;
|
||||
/* Peer should have sent us its transport parameters. If it
|
||||
* announces a positive `max_idle_timeout` it will close the
|
||||
* connection when it does not hear from us for that time.
|
||||
*
|
||||
* Some servers use this as a keep-alive timer at a rather low
|
||||
* value. We are doing HTTP/3 here and waiting for the response
|
||||
* to a request may take a considerable amount of time. We need
|
||||
* to prevent the peer's QUIC stack from closing in this case.
|
||||
*/
|
||||
* announces a positive `max_idle_timeout` it will close the
|
||||
* connection when it does not hear from us for that time.
|
||||
*
|
||||
* Some servers use this as a keep-alive timer at a rather low
|
||||
* value. We are doing HTTP/3 here and waiting for the response
|
||||
* to a request may take a considerable amount of time. We need
|
||||
* to prevent the peer's QUIC stack from closing in this case.
|
||||
*/
|
||||
if(!ctx->qconn)
|
||||
return;
|
||||
|
||||
|
|
@ -218,7 +217,6 @@ static void cf_ngtcp2_setup_keep_alive(struct Curl_cfilter *cf,
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
struct pkt_io_ctx;
|
||||
static CURLcode cf_progress_ingress(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
|
|
@ -231,20 +229,20 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
|
|||
* All about the H3 internals of a stream
|
||||
*/
|
||||
struct h3_stream_ctx {
|
||||
int64_t id; /* HTTP/3 protocol identifier */
|
||||
struct bufq sendbuf; /* h3 request body */
|
||||
struct h1_req_parser h1; /* h1 request parsing */
|
||||
int64_t id; /* HTTP/3 protocol identifier */
|
||||
struct bufq sendbuf; /* h3 request body */
|
||||
struct h1_req_parser h1; /* h1 request parsing */
|
||||
size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
curl_off_t upload_left; /* number of request bytes left to upload */
|
||||
uint64_t download_unacked; /* bytes not acknowledged yet */
|
||||
int status_code; /* HTTP status code */
|
||||
CURLcode xfer_result; /* result from xfer_resp_write(_hd) */
|
||||
BIT(resp_hds_complete); /* we have a complete, final response */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is local closed */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
curl_off_t upload_left; /* number of request bytes left to upload */
|
||||
uint64_t download_unacked; /* bytes not acknowledged yet */
|
||||
int status_code; /* HTTP status code */
|
||||
CURLcode xfer_result; /* result from xfer_resp_write(_hd) */
|
||||
BIT(resp_hds_complete); /* we have a complete, final response */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is local closed */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
};
|
||||
|
||||
static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
|
||||
|
|
@ -315,8 +313,8 @@ static bool cf_ngtcp2_sfind(uint32_t mid, void *value, void *user_data)
|
|||
return TRUE; /* continue */
|
||||
}
|
||||
|
||||
static struct h3_stream_ctx *
|
||||
cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx, int64_t stream_id)
|
||||
static struct h3_stream_ctx *cf_ngtcp2_get_stream(struct cf_ngtcp2_ctx *ctx,
|
||||
int64_t stream_id)
|
||||
{
|
||||
struct cf_ngtcp2_sfind_ctx fctx;
|
||||
fctx.stream_id = stream_id;
|
||||
|
|
@ -367,8 +365,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
|
||||
(void)cf;
|
||||
if(stream) {
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] easy handle is done",
|
||||
stream->id);
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] easy handle is done", stream->id);
|
||||
cf_ngtcp2_stream_close(cf, data, stream);
|
||||
Curl_uint32_hash_remove(&ctx->streams, data->mid);
|
||||
if(!Curl_uint32_hash_count(&ctx->streams))
|
||||
|
|
@ -640,10 +637,9 @@ static int cb_recv_stream_data(ngtcp2_conn *tconn, uint32_t flags,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
|
||||
uint64_t offset, uint64_t datalen, void *user_data,
|
||||
void *stream_user_data)
|
||||
static int cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
|
||||
uint64_t offset, uint64_t datalen,
|
||||
void *user_data, void *stream_user_data)
|
||||
{
|
||||
struct Curl_cfilter *cf = user_data;
|
||||
struct cf_ngtcp2_ctx *ctx = cf->ctx;
|
||||
|
|
@ -830,8 +826,8 @@ static int cb_recv_rx_key(ngtcp2_conn *tconn, ngtcp2_encryption_level level,
|
|||
}
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DLL)
|
||||
# pragma warning(push)
|
||||
# pragma warning(disable:4232) /* MSVC extension, dllimport identity */
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4232) /* MSVC extension, dllimport identity */
|
||||
#endif
|
||||
|
||||
static ngtcp2_callbacks ng_callbacks = {
|
||||
|
|
@ -881,7 +877,7 @@ static ngtcp2_callbacks ng_callbacks = {
|
|||
};
|
||||
|
||||
#if defined(_MSC_VER) && defined(_DLL)
|
||||
# pragma warning(pop)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
@ -1337,9 +1333,9 @@ static CURLcode init_ngh3_conn(struct Curl_cfilter *cf,
|
|||
}
|
||||
|
||||
static CURLcode recv_closed_stream(struct Curl_cfilter *cf,
|
||||
struct Curl_easy *data,
|
||||
struct h3_stream_ctx *stream,
|
||||
size_t *pnread)
|
||||
struct Curl_easy *data,
|
||||
struct h3_stream_ctx *stream,
|
||||
size_t *pnread)
|
||||
{
|
||||
(void)cf;
|
||||
*pnread = 0;
|
||||
|
|
@ -1452,11 +1448,10 @@ static int cb_h3_acked_req_body(nghttp3_conn *conn, int64_t stream_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static nghttp3_ssize
|
||||
cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
|
||||
nghttp3_vec *vec, size_t veccnt,
|
||||
uint32_t *pflags, void *user_data,
|
||||
void *stream_user_data)
|
||||
static nghttp3_ssize cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
|
||||
nghttp3_vec *vec, size_t veccnt,
|
||||
uint32_t *pflags, void *user_data,
|
||||
void *stream_user_data)
|
||||
{
|
||||
struct Curl_cfilter *cf = user_data;
|
||||
struct cf_ngtcp2_ctx *ctx = cf->ctx;
|
||||
|
|
@ -1504,8 +1499,7 @@ cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
|
|||
}
|
||||
else if(!nwritten) {
|
||||
/* Not EOF, and nothing to give, we signal WOULDBLOCK. */
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN",
|
||||
stream->id);
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] read req body -> AGAIN", stream->id);
|
||||
return NGHTTP3_ERR_WOULDBLOCK;
|
||||
}
|
||||
|
||||
|
|
@ -1961,7 +1955,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
|
|||
*/
|
||||
max_payload_size = ngtcp2_conn_get_max_tx_udp_payload_size(ctx->qconn);
|
||||
path_max_payload_size =
|
||||
ngtcp2_conn_get_path_max_tx_udp_payload_size(ctx->qconn);
|
||||
ngtcp2_conn_get_path_max_tx_udp_payload_size(ctx->qconn);
|
||||
send_quantum = ngtcp2_conn_get_send_quantum(ctx->qconn);
|
||||
CURL_TRC_CF(data, cf, "egress, collect and send packets, quantum=%zu",
|
||||
send_quantum);
|
||||
|
|
@ -1977,7 +1971,7 @@ static CURLcode cf_progress_egress(struct Curl_cfilter *cf,
|
|||
size_t buflen = Curl_bufq_len(&ctx->q.sendbuf);
|
||||
if((buflen >= send_quantum) ||
|
||||
((buflen + gsolen) >= ctx->q.sendbuf.chunk_size))
|
||||
break;
|
||||
break;
|
||||
DEBUGASSERT(nread > 0);
|
||||
++pktcnt;
|
||||
if(pktcnt == 1) {
|
||||
|
|
@ -2283,16 +2277,26 @@ static int quic_ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid)
|
|||
static const char *gtls_hs_msg_name(int mtype)
|
||||
{
|
||||
switch(mtype) {
|
||||
case 1: return "ClientHello";
|
||||
case 2: return "ServerHello";
|
||||
case 4: return "SessionTicket";
|
||||
case 8: return "EncryptedExtensions";
|
||||
case 11: return "Certificate";
|
||||
case 13: return "CertificateRequest";
|
||||
case 15: return "CertificateVerify";
|
||||
case 20: return "Finished";
|
||||
case 24: return "KeyUpdate";
|
||||
case 254: return "MessageHash";
|
||||
case 1:
|
||||
return "ClientHello";
|
||||
case 2:
|
||||
return "ServerHello";
|
||||
case 4:
|
||||
return "SessionTicket";
|
||||
case 8:
|
||||
return "EncryptedExtensions";
|
||||
case 11:
|
||||
return "Certificate";
|
||||
case 13:
|
||||
return "CertificateRequest";
|
||||
case 15:
|
||||
return "CertificateVerify";
|
||||
case 20:
|
||||
return "Finished";
|
||||
case 24:
|
||||
return "KeyUpdate";
|
||||
case 254:
|
||||
return "MessageHash";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
@ -2458,7 +2462,7 @@ static CURLcode cf_ngtcp2_on_session_reuse(struct Curl_cfilter *cf,
|
|||
#endif /* WOLFSSL_EARLY_DATA */
|
||||
#endif
|
||||
#if defined(USE_GNUTLS) || defined(USE_WOLFSSL) || \
|
||||
(defined(USE_OPENSSL) && defined(HAVE_OPENSSL_EARLYDATA))
|
||||
(defined(USE_OPENSSL) && defined(HAVE_OPENSSL_EARLYDATA))
|
||||
if((!ctx->earlydata_max)) {
|
||||
CURL_TRC_CF(data, cf, "SSL session does not allow earlydata");
|
||||
}
|
||||
|
|
@ -2668,7 +2672,7 @@ out:
|
|||
CURL_TRC_CF(data, cf, "connection refused by server");
|
||||
/* When a QUIC server instance is shutting down, it may send us a
|
||||
* CONNECTION_CLOSE with this code right away. We want
|
||||
* to keep on trying in this case. */
|
||||
* to keep on trying in this case. */
|
||||
result = CURLE_WEIRD_SERVER_REPLY;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -453,29 +453,29 @@ static CURLcode cf_osslq_h3conn_add_stream(struct cf_osslq_h3conn *h3,
|
|||
* BUT OpenSSL does not offer this information to us. So, we silently
|
||||
* ignore all such streams we do not expect. */
|
||||
switch(stype) {
|
||||
case SSL_STREAM_TYPE_READ: {
|
||||
struct cf_osslq_stream *nstream;
|
||||
if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) {
|
||||
/* rejected, we are full */
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote uni stream",
|
||||
stream_id);
|
||||
SSL_free(stream_ssl);
|
||||
return CURLE_OK;
|
||||
}
|
||||
nstream = &h3->remote_ctrl[h3->remote_ctrl_n++];
|
||||
nstream->id = stream_id;
|
||||
nstream->ssl = stream_ssl;
|
||||
Curl_bufq_initp(&nstream->recvbuf, &ctx->stream_bufcp, 1, BUFQ_OPT_NONE);
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] accepted remote uni stream",
|
||||
case SSL_STREAM_TYPE_READ: {
|
||||
struct cf_osslq_stream *nstream;
|
||||
if(h3->remote_ctrl_n >= CURL_ARRAYSIZE(h3->remote_ctrl)) {
|
||||
/* rejected, we are full */
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote uni stream",
|
||||
stream_id);
|
||||
return CURLE_OK;
|
||||
}
|
||||
default:
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote %s"
|
||||
" stream, type=%x", stream_id,
|
||||
(stype == SSL_STREAM_TYPE_BIDI) ? "bidi" : "write", stype);
|
||||
SSL_free(stream_ssl);
|
||||
return CURLE_OK;
|
||||
}
|
||||
nstream = &h3->remote_ctrl[h3->remote_ctrl_n++];
|
||||
nstream->id = stream_id;
|
||||
nstream->ssl = stream_ssl;
|
||||
Curl_bufq_initp(&nstream->recvbuf, &ctx->stream_bufcp, 1, BUFQ_OPT_NONE);
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] accepted remote uni stream",
|
||||
stream_id);
|
||||
return CURLE_OK;
|
||||
}
|
||||
default:
|
||||
CURL_TRC_CF(data, cf, "[%" PRId64 "] reject remote %s"
|
||||
" stream, type=%x", stream_id,
|
||||
(stype == SSL_STREAM_TYPE_BIDI) ? "bidi" : "write", stype);
|
||||
SSL_free(stream_ssl);
|
||||
return CURLE_OK;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -505,8 +505,7 @@ static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf,
|
|||
lerr = SSL_get_verify_result(ctx->tls.ossl.ssl);
|
||||
if(lerr != X509_V_OK) {
|
||||
ssl_config->certverifyresult = lerr;
|
||||
curl_msnprintf(ebuf, sizeof(ebuf),
|
||||
"SSL certificate problem: %s",
|
||||
curl_msnprintf(ebuf, sizeof(ebuf), "SSL certificate problem: %s",
|
||||
X509_verify_cert_error_string(lerr));
|
||||
}
|
||||
else
|
||||
|
|
@ -540,7 +539,7 @@ static CURLcode cf_osslq_ssl_err(struct Curl_cfilter *cf,
|
|||
* the SO_ERROR is also lost.
|
||||
*/
|
||||
if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) {
|
||||
char extramsg[80]="";
|
||||
char extramsg[80] = "";
|
||||
int sockerr = SOCKERRNO;
|
||||
struct ip_quadruple ip;
|
||||
|
||||
|
|
@ -570,20 +569,21 @@ static CURLcode cf_osslq_verify_peer(struct Curl_cfilter *cf,
|
|||
*/
|
||||
struct h3_stream_ctx {
|
||||
struct cf_osslq_stream s;
|
||||
struct bufq sendbuf; /* h3 request body */
|
||||
struct bufq recvbuf; /* h3 response body */
|
||||
struct h1_req_parser h1; /* h1 request parsing */
|
||||
struct bufq sendbuf; /* h3 request body */
|
||||
struct bufq recvbuf; /* h3 response body */
|
||||
struct h1_req_parser h1; /* h1 request parsing */
|
||||
size_t sendbuf_len_in_flight; /* sendbuf amount "in flight" */
|
||||
size_t recv_buf_nonflow; /* buffered bytes, not counting for flow control */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
curl_off_t upload_left; /* number of request bytes left to upload */
|
||||
curl_off_t download_recvd; /* number of response DATA bytes received */
|
||||
int status_code; /* HTTP status code */
|
||||
BIT(resp_hds_complete); /* we have a complete, final response */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is local closed */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
size_t recv_buf_nonflow; /* buffered bytes,
|
||||
not counting for flow control */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
curl_off_t upload_left; /* number of request bytes left to upload */
|
||||
curl_off_t download_recvd; /* number of response DATA bytes received */
|
||||
int status_code; /* HTTP status code */
|
||||
BIT(resp_hds_complete); /* we have a complete, final response */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is local closed */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
};
|
||||
|
||||
static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
|
||||
|
|
@ -645,8 +645,7 @@ static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
|
|||
|
||||
(void)cf;
|
||||
if(stream) {
|
||||
CURL_TRC_CF(data, cf, "[%" PRIu64 "] easy handle is done",
|
||||
stream->s.id);
|
||||
CURL_TRC_CF(data, cf, "[%" PRIu64 "] easy handle is done", stream->s.id);
|
||||
if(ctx->h3.conn && (stream->s.id >= 0) && !stream->closed) {
|
||||
nghttp3_conn_shutdown_stream_read(ctx->h3.conn, stream->s.id);
|
||||
nghttp3_conn_close_stream(ctx->h3.conn, stream->s.id,
|
||||
|
|
@ -965,11 +964,10 @@ static int cb_h3_reset_stream(nghttp3_conn *conn, int64_t stream_id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static nghttp3_ssize
|
||||
cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
|
||||
nghttp3_vec *vec, size_t veccnt,
|
||||
uint32_t *pflags, void *user_data,
|
||||
void *stream_user_data)
|
||||
static nghttp3_ssize cb_h3_read_req_body(nghttp3_conn *conn, int64_t stream_id,
|
||||
nghttp3_vec *vec, size_t veccnt,
|
||||
uint32_t *pflags, void *user_data,
|
||||
void *stream_user_data)
|
||||
{
|
||||
struct Curl_cfilter *cf = user_data;
|
||||
struct cf_osslq_ctx *ctx = cf->ctx;
|
||||
|
|
@ -1106,21 +1104,21 @@ static CURLcode cf_osslq_h3conn_init(struct cf_osslq_ctx *ctx, SSL *conn,
|
|||
}
|
||||
|
||||
result = cf_osslq_stream_open(&h3->s_ctrl, conn,
|
||||
SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
|
||||
SSL_STREAM_FLAG_ADVANCE | SSL_STREAM_FLAG_UNI,
|
||||
&ctx->stream_bufcp, NULL);
|
||||
if(result) {
|
||||
result = CURLE_QUIC_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
result = cf_osslq_stream_open(&h3->s_qpack_enc, conn,
|
||||
SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
|
||||
SSL_STREAM_FLAG_ADVANCE | SSL_STREAM_FLAG_UNI,
|
||||
&ctx->stream_bufcp, NULL);
|
||||
if(result) {
|
||||
result = CURLE_QUIC_CONNECT_ERROR;
|
||||
goto out;
|
||||
}
|
||||
result = cf_osslq_stream_open(&h3->s_qpack_dec, conn,
|
||||
SSL_STREAM_FLAG_ADVANCE|SSL_STREAM_FLAG_UNI,
|
||||
SSL_STREAM_FLAG_ADVANCE | SSL_STREAM_FLAG_UNI,
|
||||
&ctx->stream_bufcp, NULL);
|
||||
if(result) {
|
||||
result = CURLE_QUIC_CONNECT_ERROR;
|
||||
|
|
@ -1221,7 +1219,8 @@ static CURLcode cf_osslq_ctx_start(struct Curl_cfilter *cf,
|
|||
SSL_INCOMING_STREAM_POLICY_ACCEPT, 0);
|
||||
/* from our side, there is no idle timeout */
|
||||
SSL_set_value_uint(ctx->tls.ossl.ssl,
|
||||
SSL_VALUE_CLASS_FEATURE_REQUEST, SSL_VALUE_QUIC_IDLE_TIMEOUT, 0);
|
||||
SSL_VALUE_CLASS_FEATURE_REQUEST,
|
||||
SSL_VALUE_QUIC_IDLE_TIMEOUT, 0);
|
||||
/* setup the H3 things on top of the QUIC connection */
|
||||
result = cf_osslq_h3conn_init(ctx, ctx->tls.ossl.ssl, cf);
|
||||
|
||||
|
|
@ -1532,7 +1531,7 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
|
|||
fill_ctx.multi = data->multi;
|
||||
fill_ctx.n = 0;
|
||||
Curl_uint32_hash_visit(&ctx->streams, cf_osslq_collect_block_send,
|
||||
&fill_ctx);
|
||||
&fill_ctx);
|
||||
poll_count = fill_ctx.n;
|
||||
if(poll_count) {
|
||||
CURL_TRC_CF(data, cf, "polling %zu blocked streams", poll_count);
|
||||
|
|
@ -1541,7 +1540,7 @@ static CURLcode cf_osslq_check_and_unblock(struct Curl_cfilter *cf,
|
|||
res = CURLE_UNRECOVERABLE_POLL;
|
||||
if(!SSL_poll(ctx->poll_items, poll_count, sizeof(SSL_POLL_ITEM),
|
||||
&timeout, 0, &result_count))
|
||||
goto out;
|
||||
goto out;
|
||||
|
||||
res = CURLE_OK;
|
||||
|
||||
|
|
@ -1617,7 +1616,7 @@ static CURLcode h3_send_streams(struct Curl_cfilter *cf,
|
|||
uint64_t flags = (eos && ((i + 1) == n)) ? SSL_WRITE_FLAG_CONCLUDE : 0;
|
||||
written = vec[i].len;
|
||||
ok = !s->ssl || SSL_write_ex2(s->ssl, vec[i].base, vec[i].len, flags,
|
||||
&written);
|
||||
&written);
|
||||
if(ok && flags & SSL_WRITE_FLAG_CONCLUDE)
|
||||
eos_written = TRUE;
|
||||
if(ok) {
|
||||
|
|
|
|||
|
|
@ -167,17 +167,17 @@ static CURLcode cf_flush_egress(struct Curl_cfilter *cf,
|
|||
* All about the H3 internals of a stream
|
||||
*/
|
||||
struct h3_stream_ctx {
|
||||
uint64_t id; /* HTTP/3 protocol stream identifier */
|
||||
struct bufq recvbuf; /* h3 response */
|
||||
uint64_t id; /* HTTP/3 protocol stream identifier */
|
||||
struct bufq recvbuf; /* h3 response */
|
||||
struct h1_req_parser h1; /* h1 request parsing */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
BIT(opened); /* TRUE after stream has been opened */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is locally closed */
|
||||
uint64_t error3; /* HTTP/3 stream error code */
|
||||
BIT(opened); /* TRUE after stream has been opened */
|
||||
BIT(closed); /* TRUE on stream close */
|
||||
BIT(reset); /* TRUE on stream reset */
|
||||
BIT(send_closed); /* stream is locally closed */
|
||||
BIT(resp_hds_complete); /* final response has been received */
|
||||
BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
BIT(resp_got_header); /* TRUE when h3 stream has recvd some HEADER */
|
||||
BIT(quic_flow_blocked); /* stream is blocked by QUIC flow control */
|
||||
};
|
||||
|
||||
static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
|
||||
|
|
@ -318,7 +318,7 @@ static void cf_quiche_expire_conn_closed(struct Curl_cfilter *cf,
|
|||
|
||||
/*
|
||||
* write_resp_raw() copies response data in raw format to the `data`'s
|
||||
* receive buffer. If not enough space is available, it appends to the
|
||||
* receive buffer. If not enough space is available, it appends to the
|
||||
* `data`'s overflow buffer.
|
||||
*/
|
||||
static CURLcode write_resp_raw(struct Curl_cfilter *cf,
|
||||
|
|
@ -813,7 +813,7 @@ out:
|
|||
timeout_ns = quiche_conn_timeout_as_nanos(ctx->qconn);
|
||||
if(timeout_ns % 1000000)
|
||||
timeout_ns += 1000000;
|
||||
/* expire resolution is milliseconds */
|
||||
/* expire resolution is milliseconds */
|
||||
Curl_expire(data, (timeout_ns / 1000000), EXPIRE_QUIC);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -977,9 +977,9 @@ static CURLcode h3_open_stream(struct Curl_cfilter *cf,
|
|||
DEBUGASSERT(stream);
|
||||
|
||||
result = Curl_h1_req_parse_read(&stream->h1, buf, blen, NULL,
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, pnwritten);
|
||||
!data->state.http_ignorecustom ?
|
||||
data->set.str[STRING_CUSTOMREQUEST] : NULL,
|
||||
0, pnwritten);
|
||||
if(result)
|
||||
goto out;
|
||||
if(!stream->h1.done) {
|
||||
|
|
@ -1313,8 +1313,7 @@ static CURLcode cf_quiche_ctx_open(struct Curl_cfilter *cf,
|
|||
int qfd;
|
||||
(void)Curl_qlogdir(data, ctx->scid, sizeof(ctx->scid), &qfd);
|
||||
if(qfd != -1)
|
||||
quiche_conn_set_qlog_fd(ctx->qconn, qfd,
|
||||
"qlog title", "curl qlog");
|
||||
quiche_conn_set_qlog_fd(ctx->qconn, qfd, "qlog title", "curl qlog");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,9 @@ CURLcode Curl_vquic_tls_before_recv(struct curl_tls_ctx *ctx,
|
|||
return result;
|
||||
}
|
||||
#else
|
||||
(void)ctx; (void)cf; (void)data;
|
||||
(void)ctx;
|
||||
(void)cf;
|
||||
(void)data;
|
||||
#endif
|
||||
return CURLE_OK;
|
||||
}
|
||||
|
|
@ -172,7 +174,7 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
|
|||
#elif defined(USE_WOLFSSL)
|
||||
(void)data;
|
||||
if(conn_config->verifyhost) {
|
||||
WOLFSSL_X509* cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
|
||||
WOLFSSL_X509 *cert = wolfSSL_get_peer_certificate(ctx->wssl.ssl);
|
||||
if(!cert)
|
||||
result = CURLE_OUT_OF_MEMORY;
|
||||
else if(peer->sni &&
|
||||
|
|
@ -194,7 +196,6 @@ CURLcode Curl_vquic_tls_verify_peer(struct curl_tls_ctx *ctx,
|
|||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool Curl_vquic_tls_get_ssl_info(struct curl_tls_ctx *ctx,
|
||||
bool give_ssl_ctx,
|
||||
struct curl_tlssessioninfo *info)
|
||||
|
|
|
|||
|
|
@ -69,14 +69,14 @@ typedef CURLcode Curl_vquic_session_reuse_cb(struct Curl_cfilter *cf,
|
|||
/**
|
||||
* Initialize the QUIC TLS instances based of the SSL configurations
|
||||
* for the connection filter, transfer and peer.
|
||||
* @param ctx the TLS context to initialize
|
||||
* @param cf the connection filter involved
|
||||
* @param data the transfer involved
|
||||
* @param peer the peer that will be connected to
|
||||
* @param alpns the ALPN specifications to negotiate, may be NULL
|
||||
* @param cb_setup optional callback for early TLS config
|
||||
* @param cb_user_data user_data param for callback
|
||||
* @param ssl_user_data optional pointer to set in TLS application context
|
||||
* @param ctx the TLS context to initialize
|
||||
* @param cf the connection filter involved
|
||||
* @param data the transfer involved
|
||||
* @param peer the peer that will be connected to
|
||||
* @param alpns the ALPN specifications to negotiate, may be NULL
|
||||
* @param cb_setup optional callback for early TLS config
|
||||
* @param cb_user_data user_data param for callback
|
||||
* @param ssl_user_data optional pointer to set in TLS application context
|
||||
* @param session_reuse_cb callback to handle session reuse, signal early data
|
||||
*/
|
||||
CURLcode Curl_vquic_tls_init(struct curl_tls_ctx *ctx,
|
||||
|
|
|
|||
|
|
@ -266,7 +266,7 @@ static CURLcode vquic_send_packets(struct Curl_cfilter *cf,
|
|||
unsigned char c;
|
||||
*psent = 0;
|
||||
Curl_rand(data, &c, 1);
|
||||
if(c >= ((100-qctx->wblock_percent)*256/100)) {
|
||||
if(c >= ((100 - qctx->wblock_percent) * 256 / 100)) {
|
||||
CURL_TRC_CF(data, cf, "vquic_flush() simulate EWOULDBLOCK");
|
||||
return CURLE_AGAIN;
|
||||
}
|
||||
|
|
@ -334,8 +334,7 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
qctx->split_gsolen = gsolen;
|
||||
qctx->gsolen = tail_gsolen;
|
||||
CURL_TRC_CF(data, cf, "vquic_send_tail_split: [%zu gso=%zu][%zu gso=%zu]",
|
||||
qctx->split_len, qctx->split_gsolen,
|
||||
tail_len, qctx->gsolen);
|
||||
qctx->split_len, qctx->split_gsolen, tail_len, qctx->gsolen);
|
||||
return vquic_flush(cf, data, qctx);
|
||||
}
|
||||
|
||||
|
|
@ -476,7 +475,7 @@ static CURLcode recvmsg_packets(struct Curl_cfilter *cf,
|
|||
{
|
||||
struct iovec msg_iov;
|
||||
struct msghdr msg;
|
||||
uint8_t buf[64*1024];
|
||||
uint8_t buf[64 * 1024];
|
||||
struct sockaddr_storage remote_addr;
|
||||
size_t total_nread, pkts, calls;
|
||||
ssize_t rc;
|
||||
|
|
@ -551,7 +550,7 @@ static CURLcode recvfrom_packets(struct Curl_cfilter *cf,
|
|||
size_t max_pkts,
|
||||
vquic_recv_pkts_cb *recv_cb, void *userp)
|
||||
{
|
||||
uint8_t buf[64*1024];
|
||||
uint8_t buf[64 * 1024];
|
||||
int bufsize = (int)sizeof(buf);
|
||||
struct sockaddr_storage remote_addr;
|
||||
socklen_t remote_addrlen = sizeof(remote_addr);
|
||||
|
|
|
|||
|
|
@ -33,25 +33,25 @@
|
|||
#define MAX_UDP_PAYLOAD_SIZE 1452
|
||||
|
||||
struct cf_quic_ctx {
|
||||
curl_socket_t sockfd; /* connected UDP socket */
|
||||
curl_socket_t sockfd; /* connected UDP socket */
|
||||
struct sockaddr_storage local_addr; /* address socket is bound to */
|
||||
socklen_t local_addrlen; /* length of local address */
|
||||
socklen_t local_addrlen; /* length of local address */
|
||||
|
||||
struct bufq sendbuf; /* buffer for sending one or more packets */
|
||||
struct curltime first_byte_at; /* when first byte was recvd */
|
||||
struct curltime last_op; /* last (attempted) send/recv operation */
|
||||
struct curltime last_io; /* last successful socket IO */
|
||||
size_t gsolen; /* length of individual packets in send buf */
|
||||
size_t split_len; /* if != 0, buffer length after which GSO differs */
|
||||
struct bufq sendbuf; /* buffer for sending one or more packets */
|
||||
struct curltime first_byte_at; /* when first byte was recvd */
|
||||
struct curltime last_op; /* last (attempted) send/recv operation */
|
||||
struct curltime last_io; /* last successful socket IO */
|
||||
size_t gsolen; /* length of individual packets in send buf */
|
||||
size_t split_len; /* if != 0, buffer length after which GSO differs */
|
||||
size_t split_gsolen; /* length of individual packets after split_len */
|
||||
#ifdef DEBUGBUILD
|
||||
int wblock_percent; /* percent of writes doing EAGAIN */
|
||||
int wblock_percent; /* percent of writes doing EAGAIN */
|
||||
#endif
|
||||
BIT(got_first_byte); /* if first byte was received */
|
||||
BIT(no_gso); /* do not use gso on sending */
|
||||
BIT(no_gso); /* do not use gso on sending */
|
||||
};
|
||||
|
||||
#define H3_STREAM_CTX(ctx,data) \
|
||||
#define H3_STREAM_CTX(ctx, data) \
|
||||
(data ? Curl_uint32_hash_get(&(ctx)->streams, (data)->mid) : NULL)
|
||||
|
||||
CURLcode vquic_ctx_init(struct cf_quic_ctx *qctx);
|
||||
|
|
@ -77,7 +77,6 @@ CURLcode vquic_send_tail_split(struct Curl_cfilter *cf, struct Curl_easy *data,
|
|||
CURLcode vquic_flush(struct Curl_cfilter *cf, struct Curl_easy *data,
|
||||
struct cf_quic_ctx *qctx);
|
||||
|
||||
|
||||
typedef CURLcode vquic_recv_pkts_cb(const unsigned char *buf, size_t buflen,
|
||||
size_t gso_size,
|
||||
struct sockaddr_storage *remote_addr,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue