summaryrefslogtreecommitdiff
path: root/Utilities/cmcurl/lib/vquic/ngtcp2.c
diff options
context:
space:
mode:
authorBrad King <brad.king@kitware.com>2021-09-15 15:28:38 -0400
committerBrad King <brad.king@kitware.com>2021-09-15 15:28:38 -0400
commit8ecd95845cf0254259cd19a0550beafe83131708 (patch)
tree6983d7d95f0c7be15b33cf7953c3a9ebc9f815b8 /Utilities/cmcurl/lib/vquic/ngtcp2.c
parenta8ae9c7055fc5d7175a3082640733745248b4274 (diff)
parent386467c9dc939cd20711c451dd7d60341fd0e802 (diff)
downloadcmake-8ecd95845cf0254259cd19a0550beafe83131708.tar.gz
Merge branch 'upstream-curl' into update-curl
* upstream-curl: curl 2021-09-14 (8e82f2a0)
Diffstat (limited to 'Utilities/cmcurl/lib/vquic/ngtcp2.c')
-rw-r--r--Utilities/cmcurl/lib/vquic/ngtcp2.c205
1 files changed, 79 insertions, 126 deletions
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c
index 7f076759b8..9fcfe81a8c 100644
--- a/Utilities/cmcurl/lib/vquic/ngtcp2.c
+++ b/Utilities/cmcurl/lib/vquic/ngtcp2.c
@@ -28,6 +28,9 @@
#include <nghttp3/nghttp3.h>
#ifdef USE_OPENSSL
#include <openssl/err.h>
+#include <ngtcp2/ngtcp2_crypto_openssl.h>
+#elif defined(USE_GNUTLS)
+#include <ngtcp2/ngtcp2_crypto_gnutls.h>
#endif
#include "urldata.h"
#include "sendf.h"
@@ -86,7 +89,8 @@ struct h3out {
#define QUIC_PRIORITY \
"NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
"+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
- "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
+ "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1:" \
+ "%DISABLE_TLS13_COMPAT_MODE"
#endif
static CURLcode ng_process_ingress(struct Curl_easy *data,
@@ -116,42 +120,6 @@ static void quic_printf(void *user_data, const char *fmt, ...)
}
#endif
-#ifdef USE_OPENSSL
-static ngtcp2_crypto_level
-quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level)
-{
- switch(ossl_level) {
- case ssl_encryption_initial:
- return NGTCP2_CRYPTO_LEVEL_INITIAL;
- case ssl_encryption_early_data:
- return NGTCP2_CRYPTO_LEVEL_EARLY;
- case ssl_encryption_handshake:
- return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- case ssl_encryption_application:
- return NGTCP2_CRYPTO_LEVEL_APPLICATION;
- default:
- assert(0);
- }
-}
-#elif defined(USE_GNUTLS)
-static ngtcp2_crypto_level
-quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
-{
- switch(gtls_level) {
- case GNUTLS_ENCRYPTION_LEVEL_INITIAL:
- return NGTCP2_CRYPTO_LEVEL_INITIAL;
- case GNUTLS_ENCRYPTION_LEVEL_EARLY:
- return NGTCP2_CRYPTO_LEVEL_EARLY;
- case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
- return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
- case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
- return NGTCP2_CRYPTO_LEVEL_APPLICATION;
- default:
- assert(0);
- }
-}
-#endif
-
static void qlog_callback(void *user_data, uint32_t flags,
const void *data, size_t datalen)
{
@@ -222,27 +190,9 @@ static int write_client_handshake(struct quicsocket *qs,
ngtcp2_crypto_level level,
const uint8_t *data, size_t len)
{
- struct quic_handshake *crypto_data;
int rv;
- crypto_data = &qs->crypto_data[level];
- if(!crypto_data->buf) {
- crypto_data->buf = malloc(4096);
- if(!crypto_data->buf)
- return 0;
- crypto_data->alloclen = 4096;
- }
-
- /* TODO Just pretend that handshake does not grow more than 4KiB for
- now */
- assert(crypto_data->len + len <= crypto_data->alloclen);
-
- memcpy(&crypto_data->buf[crypto_data->len], data, len);
- crypto_data->len += len;
-
- rv = ngtcp2_conn_submit_crypto_data(
- qs->qconn, level, (uint8_t *)(&crypto_data->buf[crypto_data->len] - len),
- len);
+ rv = ngtcp2_conn_submit_crypto_data(qs->qconn, level, data, len);
if(rv) {
H3BUGF(fprintf(stderr, "write_client_handshake failed\n"));
}
@@ -259,7 +209,7 @@ static int quic_set_encryption_secrets(SSL *ssl,
size_t secretlen)
{
struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- int level = quic_from_ossl_level(ossl_level);
+ int level = ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
if(ngtcp2_crypto_derive_and_install_rx_key(
qs->qconn, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
@@ -281,7 +231,8 @@ static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
const uint8_t *data, size_t len)
{
struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
- ngtcp2_crypto_level level = quic_from_ossl_level(ossl_level);
+ ngtcp2_crypto_level level =
+ ngtcp2_crypto_openssl_from_ossl_encryption_level(ossl_level);
return write_client_handshake(qs, level, data, len);
}
@@ -369,7 +320,8 @@ static int secret_func(gnutls_session_t ssl,
const void *tx_secret, size_t secretlen)
{
struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- int level = quic_from_gtls_level(gtls_level);
+ int level =
+ ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
ngtcp2_crypto_derive_and_install_rx_key(
@@ -394,7 +346,8 @@ static int read_func(gnutls_session_t ssl,
size_t len)
{
struct quicsocket *qs = gnutls_session_get_ptr(ssl);
- ngtcp2_crypto_level level = quic_from_gtls_level(gtls_level);
+ ngtcp2_crypto_level level =
+ ngtcp2_crypto_gnutls_from_gnutls_record_encryption_level(gtls_level);
int rv;
if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
@@ -542,22 +495,6 @@ static int quic_init_ssl(struct quicsocket *qs)
}
#endif
-static int
-cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
- uint64_t offset,
- const uint8_t *data, size_t datalen,
- void *user_data)
-{
- (void)offset;
- (void)user_data;
-
- if(ngtcp2_crypto_read_write_crypto_data(tconn, crypto_level, data,
- datalen) != 0)
- return NGTCP2_ERR_CRYPTO;
-
- return 0;
-}
-
static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
{
(void)user_data;
@@ -622,8 +559,8 @@ cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
return 0;
}
-static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
- uint64_t app_error_code,
+static int cb_stream_close(ngtcp2_conn *tconn, uint32_t flags,
+ int64_t stream_id, uint64_t app_error_code,
void *user_data, void *stream_user_data)
{
struct quicsocket *qs = (struct quicsocket *)user_data;
@@ -632,6 +569,10 @@ static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
(void)stream_user_data;
/* stream is closed... */
+ if(!(flags & NGTCP2_STREAM_CLOSE_FLAG_APP_ERROR_CODE_SET)) {
+ app_error_code = NGHTTP3_H3_NO_ERROR;
+ }
+
rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
app_error_code);
if(rv) {
@@ -652,7 +593,25 @@ static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
(void)app_error_code;
(void)stream_user_data;
- rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
+ rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
+ if(rv) {
+ return NGTCP2_ERR_CALLBACK_FAILURE;
+ }
+
+ return 0;
+}
+
+static int cb_stream_stop_sending(ngtcp2_conn *tconn, int64_t stream_id,
+ uint64_t app_error_code, void *user_data,
+ void *stream_user_data)
+{
+ struct quicsocket *qs = (struct quicsocket *)user_data;
+ int rv;
+ (void)tconn;
+ (void)app_error_code;
+ (void)stream_user_data;
+
+ rv = nghttp3_conn_shutdown_stream_read(qs->h3conn, stream_id);
if(rv) {
return NGTCP2_ERR_CALLBACK_FAILURE;
}
@@ -712,14 +671,13 @@ static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_client_initial_cb,
NULL, /* recv_client_initial */
- cb_recv_crypto_data,
+ ngtcp2_crypto_recv_crypto_data_cb,
cb_handshake_completed,
NULL, /* recv_version_negotiation */
ngtcp2_crypto_encrypt_cb,
ngtcp2_crypto_decrypt_cb,
ngtcp2_crypto_hp_mask_cb,
cb_recv_stream_data,
- NULL, /* acked_crypto_offset */
cb_acked_stream_data_offset,
NULL, /* stream_open */
cb_stream_close,
@@ -744,7 +702,9 @@ static ngtcp2_callbacks ng_callbacks = {
ngtcp2_crypto_delete_crypto_cipher_ctx_cb,
NULL, /* recv_datagram */
NULL, /* ack_datagram */
- NULL /* lost_datagram */
+ NULL, /* lost_datagram */
+ NULL, /* get_path_challenge_data */
+ cb_stream_stop_sending
};
/*
@@ -778,7 +738,7 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
return CURLE_BAD_FUNCTION_ARGUMENT;
}
- infof(data, "Connect socket %d over QUIC to %s:%d\n",
+ infof(data, "Connect socket %d over QUIC to %s:%d",
sockfd, ipbuf, port);
qs->version = NGTCP2_PROTO_VER_MAX;
@@ -827,15 +787,14 @@ CURLcode Curl_quic_connect(struct Curl_easy *data,
}
/*
- * Store ngtp2 version info in this buffer, Prefix with a space. Return total
- * length written.
+ * Store ngtcp2 version info in this buffer.
*/
-int Curl_quic_ver(char *p, size_t len)
+void Curl_quic_ver(char *p, size_t len)
{
const ngtcp2_info *ng2 = ngtcp2_version(0);
nghttp3_info *ht3 = nghttp3_version(0);
- return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
- ng2->version_str, ht3->version_str);
+ (void)msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
+ ng2->version_str, ht3->version_str);
}
static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
@@ -859,7 +818,6 @@ static int ng_getsock(struct Curl_easy *data, struct connectdata *conn,
static void qs_disconnect(struct quicsocket *qs)
{
- int i;
if(!qs->conn) /* already closed */
return;
qs->conn = NULL;
@@ -880,8 +838,6 @@ static void qs_disconnect(struct quicsocket *qs)
qs->cred = NULL;
}
#endif
- for(i = 0; i < 3; i++)
- Curl_safefree(qs->crypto_data[i].buf);
nghttp3_conn_del(qs->h3conn);
ngtcp2_conn_del(qs->qconn);
#ifdef USE_OPENSSL
@@ -951,7 +907,7 @@ static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
(void)stream_id;
(void)app_error_code;
(void)user_data;
- H3BUGF(infof(data, "cb_h3_stream_close CALLED\n"));
+ H3BUGF(infof(data, "cb_h3_stream_close CALLED"));
stream->closed = TRUE;
Curl_expire(data, 0, EXPIRE_QUIC);
@@ -1143,14 +1099,10 @@ static nghttp3_callbacks ngh3_callbacks = {
NULL, /* begin_trailers */
cb_h3_recv_header,
NULL, /* end_trailers */
- NULL, /* http_begin_push_promise */
- NULL, /* http_recv_push_promise */
- NULL, /* http_end_push_promise */
- NULL, /* http_cancel_push */
cb_h3_send_stop_sending,
- NULL, /* push_stream */
NULL, /* end_stream */
NULL, /* reset_stream */
+ NULL /* shutdown */
};
static int init_ngh3_conn(struct quicsocket *qs)
@@ -1287,7 +1239,7 @@ static ssize_t ngh3_stream_recv(struct Curl_easy *data,
return 0;
}
- infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
+ infof(data, "ngh3_stream_recv returns 0 bytes and EAGAIN");
*curlcode = CURLE_AGAIN;
return -1;
}
@@ -1304,7 +1256,7 @@ static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
if(!data->set.postfields) {
stream->h3out->used -= datalen;
H3BUGF(infof(data,
- "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
+ "cb_h3_acked_stream_data, %zd bytes, %zd left unacked",
datalen, stream->h3out->used));
DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
@@ -1366,13 +1318,13 @@ static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
if(!stream->upload_left)
*pflags = NGHTTP3_DATA_FLAG_EOF;
}
- H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n",
+ H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)",
nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
out->used));
}
if(stream->upload_done && !stream->upload_len &&
(stream->upload_left <= 0)) {
- H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
+ H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF"));
*pflags = NGHTTP3_DATA_FLAG_EOF;
return nread ? 1 : 0;
}
@@ -1565,7 +1517,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
if(acc > MAX_ACC) {
infof(data, "http_request: Warning: The cumulative length of all "
"headers exceeds %d bytes and that could cause the "
- "stream to be rejected.\n", MAX_ACC);
+ "stream to be rejected.", MAX_ACC);
}
}
@@ -1611,7 +1563,7 @@ static CURLcode http_request(struct Curl_easy *data, const void *mem,
Curl_safefree(nva);
- infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
+ infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)",
stream3_id, (void *)data);
return CURLE_OK;
@@ -1641,7 +1593,7 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data,
sent = len;
}
else {
- H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes\n",
+ H3BUGF(infof(data, "ngh3_stream_send() wants to send %zd bytes",
len));
if(!stream->upload_len) {
stream->upload_mem = mem;
@@ -1660,6 +1612,12 @@ static ssize_t ngh3_stream_send(struct Curl_easy *data,
return -1;
}
+ /* Reset post upload buffer after resumed. */
+ if(stream->upload_mem) {
+ stream->upload_mem = NULL;
+ stream->upload_len = 0;
+ }
+
*curlcode = CURLE_OK;
return sent;
}
@@ -1758,8 +1716,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
int rv;
ssize_t sent;
ssize_t outlen;
- uint8_t out[NGTCP2_MAX_PKTLEN_IPV4];
- size_t pktlen;
+ uint8_t out[NGTCP2_MAX_UDP_PAYLOAD_SIZE];
ngtcp2_path_storage ps;
ngtcp2_tstamp ts = timestamp();
struct sockaddr_storage remote_addr;
@@ -1772,19 +1729,6 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
ssize_t ndatalen;
uint32_t flags;
- switch(qs->local_addr.ss_family) {
- case AF_INET:
- pktlen = NGTCP2_MAX_PKTLEN_IPV4;
- break;
-#ifdef ENABLE_IPV6
- case AF_INET6:
- pktlen = NGTCP2_MAX_PKTLEN_IPV6;
- break;
-#endif
- default:
- assert(0);
- }
-
rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
if(rv) {
failf(data, "ngtcp2_conn_handle_expiry returned error: %s",
@@ -1811,15 +1755,16 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
flags = NGTCP2_WRITE_STREAM_FLAG_MORE |
(fin ? NGTCP2_WRITE_STREAM_FLAG_FIN : 0);
- outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out, pktlen,
+ outlen = ngtcp2_conn_writev_stream(qs->qconn, &ps.path, NULL, out,
+ sizeof(out),
&ndatalen, flags, stream_id,
(const ngtcp2_vec *)vec, veccnt, ts);
if(outlen == 0) {
break;
}
if(outlen < 0) {
- if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
- outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
+ switch(outlen) {
+ case NGTCP2_ERR_STREAM_DATA_BLOCKED:
assert(ndatalen == -1);
rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
if(rv) {
@@ -1828,8 +1773,17 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
return CURLE_SEND_ERROR;
}
continue;
- }
- else if(outlen == NGTCP2_ERR_WRITE_MORE) {
+ case NGTCP2_ERR_STREAM_SHUT_WR:
+ assert(ndatalen == -1);
+ rv = nghttp3_conn_shutdown_stream_write(qs->h3conn, stream_id);
+ if(rv) {
+ failf(data,
+ "nghttp3_conn_shutdown_stream_write returned error: %s\n",
+ nghttp3_strerror(rv));
+ return CURLE_SEND_ERROR;
+ }
+ continue;
+ case NGTCP2_ERR_WRITE_MORE:
assert(ndatalen >= 0);
rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
if(rv) {
@@ -1838,8 +1792,7 @@ static CURLcode ng_flush_egress(struct Curl_easy *data,
return CURLE_SEND_ERROR;
}
continue;
- }
- else {
+ default:
assert(ndatalen == -1);
failf(data, "ngtcp2_conn_writev_stream returned error: %s",
ngtcp2_strerror((int)outlen));