diff options
Diffstat (limited to 'libs/libcurl/src/vquic/curl_msh3.c')
-rw-r--r-- | libs/libcurl/src/vquic/curl_msh3.c | 177 |
1 files changed, 92 insertions, 85 deletions
diff --git a/libs/libcurl/src/vquic/curl_msh3.c b/libs/libcurl/src/vquic/curl_msh3.c index 0ce9fe4cac..8f9590391f 100644 --- a/libs/libcurl/src/vquic/curl_msh3.c +++ b/libs/libcurl/src/vquic/curl_msh3.c @@ -22,30 +22,32 @@ *
***************************************************************************/
-#include "curl_setup.h"
+#include "../curl_setup.h"
#ifdef USE_MSH3
-#include "urldata.h"
-#include "hash.h"
-#include "timeval.h"
-#include "multiif.h"
-#include "sendf.h"
-#include "curl_trc.h"
-#include "cfilters.h"
-#include "cf-socket.h"
-#include "connect.h"
-#include "progress.h"
-#include "http1.h"
+#include "../urldata.h"
+#include "../hash.h"
+#include "../uint-hash.h"
+#include "../curlx/timeval.h"
+#include "../multiif.h"
+#include "../sendf.h"
+#include "../curl_trc.h"
+#include "../cfilters.h"
+#include "../cf-socket.h"
+#include "../connect.h"
+#include "../progress.h"
+#include "../http1.h"
#include "curl_msh3.h"
-#include "socketpair.h"
-#include "vtls/vtls.h"
-#include "vquic/vquic.h"
+#include "../socketpair.h"
+#include "../vtls/vtls.h"
+#include "vquic.h"
+#include "vquic_int.h"
/* The last 3 #include files should be in this order */
-#include "curl_printf.h"
-#include "curl_memory.h"
-#include "memdebug.h"
+#include "../curl_printf.h"
+#include "../curl_memory.h"
+#include "../memdebug.h"
#ifdef CURL_DISABLE_SOCKETPAIR
#error "MSH3 cannot be build with CURL_DISABLE_SOCKETPAIR set"
@@ -119,34 +121,42 @@ struct cf_msh3_ctx { struct cf_call_data call_data;
struct curltime connect_started; /* time the current attempt started */
struct curltime handshake_at; /* time connect handshake finished */
- struct Curl_hash streams; /* hash `data->mid` to `stream_ctx` */
+ struct uint_hash streams; /* hash `data->mid` to `stream_ctx` */
/* Flags written by msh3/msquic thread */
- bool handshake_complete;
- bool handshake_succeeded;
- bool connected;
+ BIT(handshake_complete);
+ BIT(handshake_succeeded);
+ BIT(connected);
BIT(initialized);
/* Flags written by curl thread */
BIT(verbose);
BIT(active);
};
-static void h3_stream_hash_free(void *stream);
+static void h3_stream_hash_free(unsigned int id, void *stream);
-static void cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
- const struct Curl_addrinfo *ai)
+static CURLcode cf_msh3_ctx_init(struct cf_msh3_ctx *ctx,
+ const struct Curl_addrinfo *ai)
{
+ CURLcode result;
+
DEBUGASSERT(!ctx->initialized);
- Curl_hash_offt_init(&ctx->streams, 63, h3_stream_hash_free);
- Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
+ Curl_uint_hash_init(&ctx->streams, 63, h3_stream_hash_free);
+
+ result = Curl_sock_assign_addr(&ctx->addr, ai, TRNSPRT_QUIC);
+ if(result)
+ return result;
+
ctx->sock[SP_LOCAL] = CURL_SOCKET_BAD;
ctx->sock[SP_REMOTE] = CURL_SOCKET_BAD;
ctx->initialized = TRUE;
+
+ return result;
}
static void cf_msh3_ctx_free(struct cf_msh3_ctx *ctx)
{
if(ctx && ctx->initialized) {
- Curl_hash_destroy(&ctx->streams);
+ Curl_uint_hash_destroy(&ctx->streams);
}
free(ctx);
}
@@ -161,7 +171,7 @@ static struct cf_msh3_ctx *h3_get_msh3_ctx(struct Curl_easy *data); /**
* All about the H3 internals of a stream
*/
-struct stream_ctx {
+struct h3_stream_ctx {
struct MSH3_REQUEST *req;
struct bufq recvbuf; /* h3 response */
#ifdef _WIN32
@@ -172,33 +182,31 @@ struct stream_ctx { uint64_t error3; /* HTTP/3 stream error code */
int status_code; /* HTTP status code */
CURLcode recv_error;
- bool closed;
- bool reset;
- bool upload_done;
- bool firstheader; /* FALSE until headers arrive */
- bool recv_header_complete;
+ BIT(closed);
+ BIT(reset);
+ BIT(upload_done);
+ BIT(firstheader); /* FALSE until headers arrive */
+ BIT(recv_header_complete);
};
-#define H3_STREAM_CTX(ctx,data) ((struct stream_ctx *)((data && ctx)? \
- Curl_hash_offt_get(&(ctx)->streams, (data)->mid) : NULL))
-
-static void h3_stream_ctx_free(struct stream_ctx *stream)
+static void h3_stream_ctx_free(struct h3_stream_ctx *stream)
{
Curl_bufq_free(&stream->recvbuf);
free(stream);
}
-static void h3_stream_hash_free(void *stream)
+static void h3_stream_hash_free(unsigned int id, void *stream)
{
+ (void)id;
DEBUGASSERT(stream);
- h3_stream_ctx_free((struct stream_ctx *)stream);
+ h3_stream_ctx_free((struct h3_stream_ctx *)stream);
}
static CURLcode h3_data_setup(struct Curl_cfilter *cf,
struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(stream)
return CURLE_OK;
@@ -213,7 +221,7 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, H3_STREAM_RECV_CHUNKS, BUFQ_OPT_SOFT_LIMIT);
CURL_TRC_CF(data, cf, "data setup");
- if(!Curl_hash_offt_set(&ctx->streams, data->mid, stream)) {
+ if(!Curl_uint_hash_set(&ctx->streams, data->mid, stream)) {
h3_stream_ctx_free(stream);
return CURLE_OUT_OF_MEMORY;
}
@@ -224,17 +232,17 @@ static CURLcode h3_data_setup(struct Curl_cfilter *cf, static void h3_data_done(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
(void)cf;
if(stream) {
CURL_TRC_CF(data, cf, "easy handle is done");
- Curl_hash_offt_remove(&ctx->streams, data->mid);
+ Curl_uint_hash_remove(&ctx->streams, data->mid);
}
}
static void drain_stream_from_other_thread(struct Curl_easy *data,
- struct stream_ctx *stream)
+ struct h3_stream_ctx *stream)
{
unsigned char bits;
@@ -252,7 +260,7 @@ static void h3_drain_stream(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
unsigned char bits;
(void)cf;
@@ -351,7 +359,7 @@ static CURLcode write_resp_raw(struct Curl_easy *data, const void *mem, size_t memlen)
{
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result = CURLE_OK;
ssize_t nwritten;
@@ -378,7 +386,7 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request, {
struct Curl_easy *data = userp;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
(void)Request;
@@ -390,7 +398,7 @@ static void MSH3_CALL msh3_header_received(MSH3_REQUEST *Request, msh3_lock_acquire(&stream->recv_lock);
if((hd->NameLength == 7) &&
- !strncmp(HTTP_PSEUDO_STATUS, (char *)hd->Name, 7)) {
+ !strncmp(HTTP_PSEUDO_STATUS, (const char *)hd->Name, 7)) {
char line[14]; /* status line is always 13 characters long */
size_t ncopy;
@@ -429,14 +437,14 @@ static bool MSH3_CALL msh3_data_received(MSH3_REQUEST *Request, {
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
CURLcode result;
bool rv = FALSE;
- /* TODO: we would like to limit the amount of data we are buffer here.
- * There seems to be no mechanism in msh3 to adjust flow control and
- * it is undocumented what happens if we return FALSE here or less
- * length (buflen is an inout parameter).
+ /* We would like to limit the amount of data we are buffer here. There seems
+ * to be no mechanism in msh3 to adjust flow control and it is undocumented
+ * what happens if we return FALSE here or less length (buflen is an inout
+ * parameter).
*/
(void)Request;
if(!stream)
@@ -469,7 +477,7 @@ static void MSH3_CALL msh3_complete(MSH3_REQUEST *Request, void *IfContext, {
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
(void)Request;
if(!stream)
@@ -489,7 +497,7 @@ static void MSH3_CALL msh3_shutdown_complete(MSH3_REQUEST *Request, {
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(!stream)
return;
@@ -502,7 +510,7 @@ static void MSH3_CALL msh3_data_sent(MSH3_REQUEST *Request, {
struct Curl_easy *data = IfContext;
struct cf_msh3_ctx *ctx = h3_get_msh3_ctx(data);
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
if(!stream)
return;
(void)Request;
@@ -515,7 +523,7 @@ static ssize_t recv_closed_stream(struct Curl_cfilter *cf, CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
if(!stream) {
@@ -549,7 +557,7 @@ out: static void set_quic_expire(struct Curl_cfilter *cf, struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
/* we have no indication from msh3 when it would be a good time
* to juggle the connection again. So, we compromise by calling
@@ -567,7 +575,7 @@ static ssize_t cf_msh3_recv(struct Curl_cfilter *cf, struct Curl_easy *data, char *buf, size_t len, CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
ssize_t nread = -1;
struct cf_call_data save;
@@ -619,7 +627,7 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, CURLcode *err)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct h1_req_parser h1;
struct dynhds h2_headers;
MSH3_HEADER *nva = NULL;
@@ -695,8 +703,8 @@ static ssize_t cf_msh3_send(struct Curl_cfilter *cf, struct Curl_easy *data, goto out;
}
- /* TODO - msh3/msquic will hold onto this memory until the send complete
- event. How do we make sure curl does not free it until then? */
+ /* msh3/msquic will hold onto this memory until the send complete event.
+ How do we make sure curl does not free it until then? */
*err = CURLE_OK;
nwritten = len;
}
@@ -715,7 +723,7 @@ static void cf_msh3_adjust_pollset(struct Curl_cfilter *cf, struct easy_pollset *ps)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
CF_DATA_SAVE(save, cf, data);
@@ -735,7 +743,7 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf, const struct Curl_easy *data)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
bool pending = FALSE;
@@ -744,12 +752,13 @@ static bool cf_msh3_data_pending(struct Curl_cfilter *cf, (void)cf;
if(stream && stream->req) {
msh3_lock_acquire(&stream->recv_lock);
- CURL_TRC_CF((struct Curl_easy *)data, cf, "data pending = %zu",
+ CURL_TRC_CF((struct Curl_easy *)CURL_UNCONST(data), cf,
+ "data pending = %zu",
Curl_bufq_len(&stream->recvbuf));
pending = !Curl_bufq_is_empty(&stream->recvbuf);
msh3_lock_release(&stream->recv_lock);
if(pending)
- h3_drain_stream(cf, (struct Curl_easy *)data);
+ h3_drain_stream(cf, (struct Curl_easy *)CURL_UNCONST(data));
}
CF_DATA_RESTORE(cf, save);
@@ -772,7 +781,7 @@ static CURLcode cf_msh3_data_event(struct Curl_cfilter *cf, int event, int arg1, void *arg2)
{
struct cf_msh3_ctx *ctx = cf->ctx;
- struct stream_ctx *stream = H3_STREAM_CTX(ctx, data);
+ struct h3_stream_ctx *stream = H3_STREAM_CTX(ctx, data);
struct cf_call_data save;
CURLcode result = CURLE_OK;
@@ -830,16 +839,10 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, MSH3_SET_PORT(&addr, (uint16_t)cf->conn->remote_port);
if(verify && (conn_config->CAfile || conn_config->CApath)) {
- /* TODO: need a way to provide trust anchors to MSH3 */
-#ifdef DEBUGBUILD
- /* we need this for our test cases to run */
- CURL_TRC_CF(data, cf, "non-standard CA not supported, "
- "switching off verifypeer in DEBUG mode");
- verify = 0;
-#else
+ /* Note there's currently no way to provide trust anchors to MSH3 and
+ that causes tests to fail. */
CURL_TRC_CF(data, cf, "non-standard CA not supported, "
"attempting with built-in verification");
-#endif
}
CURL_TRC_CF(data, cf, "connecting to %s:%d (verify=%d)",
@@ -875,13 +878,12 @@ static CURLcode cf_connect_start(struct Curl_cfilter *cf, static CURLcode cf_msh3_connect(struct Curl_cfilter *cf,
struct Curl_easy *data,
- bool blocking, bool *done)
+ bool *done)
{
struct cf_msh3_ctx *ctx = cf->ctx;
struct cf_call_data save;
CURLcode result = CURLE_OK;
- (void)blocking;
if(cf->connected) {
*done = TRUE;
return CURLE_OK;
@@ -899,18 +901,17 @@ static CURLcode cf_msh3_connect(struct Curl_cfilter *cf, *done = FALSE;
if(!ctx->qconn) {
- ctx->connect_started = Curl_now();
+ ctx->connect_started = curlx_now();
result = cf_connect_start(cf, data);
if(result)
goto out;
}
if(ctx->handshake_complete) {
- ctx->handshake_at = Curl_now();
+ ctx->handshake_at = curlx_now();
if(ctx->handshake_succeeded) {
CURL_TRC_CF(data, cf, "handshake succeeded");
cf->conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
- cf->conn->httpversion = 30;
cf->connected = TRUE;
cf->conn->alpn = CURL_HTTP_VERSION_3;
*done = TRUE;
@@ -999,7 +1000,7 @@ static CURLcode cf_msh3_query(struct Curl_cfilter *cf, switch(query) {
case CF_QUERY_MAX_CONCURRENT: {
- /* TODO: we do not have access to this so far, fake it */
+ /* We do not have access to this so far, fake it */
(void)ctx;
*pres1 = 100;
return CURLE_OK;
@@ -1017,6 +1018,9 @@ static CURLcode cf_msh3_query(struct Curl_cfilter *cf, *when = ctx->handshake_at;
return CURLE_OK;
}
+ case CF_QUERY_HTTP_VERSION:
+ *pres1 = 30;
+ return CURLE_OK;
default:
break;
}
@@ -1039,7 +1043,7 @@ static bool cf_msh3_conn_is_alive(struct Curl_cfilter *cf, struct Curl_cftype Curl_cft_http3 = {
"HTTP/3",
- CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX,
+ CF_TYPE_IP_CONNECT | CF_TYPE_SSL | CF_TYPE_MULTIPLEX | CF_TYPE_HTTP,
0,
cf_msh3_destroy,
cf_msh3_connect,
@@ -1081,13 +1085,16 @@ CURLcode Curl_cf_msh3_create(struct Curl_cfilter **pcf, (void)data;
(void)conn;
- (void)ai; /* TODO: msh3 resolves itself? */
+ (void)ai; /* msh3 resolves itself? */
ctx = calloc(1, sizeof(*ctx));
if(!ctx) {
result = CURLE_OUT_OF_MEMORY;
goto out;
}
- cf_msh3_ctx_init(ctx, ai);
+
+ result = cf_msh3_ctx_init(ctx, ai);
+ if(result)
+ goto out;
result = Curl_cf_create(&cf, &Curl_cft_http3, ctx);
|