diff options
author | Brad King <brad.king@kitware.com> | 2021-09-15 19:28:38 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2021-09-15 19:28:38 (GMT) |
commit | 8ecd95845cf0254259cd19a0550beafe83131708 (patch) | |
tree | 6983d7d95f0c7be15b33cf7953c3a9ebc9f815b8 /Utilities/cmcurl/lib/vquic/ngtcp2.c | |
parent | a8ae9c7055fc5d7175a3082640733745248b4274 (diff) | |
parent | 386467c9dc939cd20711c451dd7d60341fd0e802 (diff) | |
download | CMake-8ecd95845cf0254259cd19a0550beafe83131708.zip CMake-8ecd95845cf0254259cd19a0550beafe83131708.tar.gz CMake-8ecd95845cf0254259cd19a0550beafe83131708.tar.bz2 |
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.c | 205 |
1 files changed, 79 insertions, 126 deletions
diff --git a/Utilities/cmcurl/lib/vquic/ngtcp2.c b/Utilities/cmcurl/lib/vquic/ngtcp2.c index 7f07675..9fcfe81 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)); |