Annotation of embedaddon/curl/lib/vquic/ngtcp2.c, revision 1.1.1.1

1.1       misho       1: /***************************************************************************
                      2:  *                                  _   _ ____  _
                      3:  *  Project                     ___| | | |  _ \| |
                      4:  *                             / __| | | | |_) | |
                      5:  *                            | (__| |_| |  _ <| |___
                      6:  *                             \___|\___/|_| \_\_____|
                      7:  *
                      8:  * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al.
                      9:  *
                     10:  * This software is licensed as described in the file COPYING, which
                     11:  * you should have received as part of this distribution. The terms
                     12:  * are also available at https://curl.haxx.se/docs/copyright.html.
                     13:  *
                     14:  * You may opt to use, copy, modify, merge, publish, distribute and/or sell
                     15:  * copies of the Software, and permit persons to whom the Software is
                     16:  * furnished to do so, under the terms of the COPYING file.
                     17:  *
                     18:  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
                     19:  * KIND, either express or implied.
                     20:  *
                     21:  ***************************************************************************/
                     22: 
                     23: #include "curl_setup.h"
                     24: 
                     25: #ifdef USE_NGTCP2
                     26: #include <ngtcp2/ngtcp2.h>
                     27: #include <ngtcp2/ngtcp2_crypto.h>
                     28: #include <nghttp3/nghttp3.h>
                     29: #ifdef USE_OPENSSL
                     30: #include <openssl/err.h>
                     31: #endif
                     32: #include "urldata.h"
                     33: #include "sendf.h"
                     34: #include "strdup.h"
                     35: #include "rand.h"
                     36: #include "ngtcp2.h"
                     37: #include "multiif.h"
                     38: #include "strcase.h"
                     39: #include "connect.h"
                     40: #include "strerror.h"
                     41: 
                     42: /* The last 3 #include files should be in this order */
                     43: #include "curl_printf.h"
                     44: #include "curl_memory.h"
                     45: #include "memdebug.h"
                     46: 
                     47: /* #define DEBUG_NGTCP2 */
                     48: #ifdef CURLDEBUG
                     49: #define DEBUG_HTTP3
                     50: #endif
                     51: #ifdef DEBUG_HTTP3
                     52: #define H3BUGF(x) x
                     53: #else
                     54: #define H3BUGF(x) do { } while(0)
                     55: #endif
                     56: 
                     57: /*
                     58:  * This holds outgoing HTTP/3 stream data that is used by nghttp3 until acked.
                     59:  * It is used as a circular buffer. Add new bytes at the end until it reaches
                     60:  * the far end, then start over at index 0 again.
                     61:  */
                     62: 
                     63: #define H3_SEND_SIZE (20*1024)
                     64: struct h3out {
                     65:   uint8_t buf[H3_SEND_SIZE];
                     66:   size_t used;   /* number of bytes used in the buffer */
                     67:   size_t windex; /* index in the buffer where to start writing the next
                     68:                     data block */
                     69: };
                     70: 
                     71: #define QUIC_MAX_STREAMS (256*1024)
                     72: #define QUIC_MAX_DATA (1*1024*1024)
                     73: #define QUIC_IDLE_TIMEOUT 60000 /* milliseconds */
                     74: 
                     75: #ifdef USE_OPENSSL
                     76: #define QUIC_CIPHERS                                                          \
                     77:   "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_"               \
                     78:   "POLY1305_SHA256:TLS_AES_128_CCM_SHA256"
                     79: #define QUIC_GROUPS "P-256:X25519:P-384:P-521"
                     80: #elif defined(USE_GNUTLS)
                     81: #define QUIC_PRIORITY \
                     82:   "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+AES-256-GCM:" \
                     83:   "+CHACHA20-POLY1305:+AES-128-CCM:-GROUP-ALL:+GROUP-SECP256R1:" \
                     84:   "+GROUP-X25519:+GROUP-SECP384R1:+GROUP-SECP521R1"
                     85: #endif
                     86: 
                     87: static CURLcode ng_process_ingress(struct connectdata *conn,
                     88:                                    curl_socket_t sockfd,
                     89:                                    struct quicsocket *qs);
                     90: static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
                     91:                                 struct quicsocket *qs);
                     92: static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                     93:                                    size_t datalen, void *user_data,
                     94:                                    void *stream_user_data);
                     95: 
                     96: static ngtcp2_tstamp timestamp(void)
                     97: {
                     98:   struct curltime ct = Curl_now();
                     99:   return ct.tv_sec * NGTCP2_SECONDS + ct.tv_usec * NGTCP2_MICROSECONDS;
                    100: }
                    101: 
                    102: #ifdef DEBUG_NGTCP2
                    103: static void quic_printf(void *user_data, const char *fmt, ...)
                    104: {
                    105:   va_list ap;
                    106:   (void)user_data; /* TODO, use this to do infof() instead long-term */
                    107:   va_start(ap, fmt);
                    108:   vfprintf(stderr, fmt, ap);
                    109:   va_end(ap);
                    110:   fprintf(stderr, "\n");
                    111: }
                    112: #endif
                    113: 
                    114: #ifdef USE_OPENSSL
                    115: static ngtcp2_crypto_level
                    116: quic_from_ossl_level(OSSL_ENCRYPTION_LEVEL ossl_level)
                    117: {
                    118:   switch(ossl_level) {
                    119:   case ssl_encryption_initial:
                    120:     return NGTCP2_CRYPTO_LEVEL_INITIAL;
                    121:   case ssl_encryption_early_data:
                    122:     return NGTCP2_CRYPTO_LEVEL_EARLY;
                    123:   case ssl_encryption_handshake:
                    124:     return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
                    125:   case ssl_encryption_application:
                    126:     return NGTCP2_CRYPTO_LEVEL_APP;
                    127:   default:
                    128:     assert(0);
                    129:   }
                    130: }
                    131: #elif defined(USE_GNUTLS)
                    132: static ngtcp2_crypto_level
                    133: quic_from_gtls_level(gnutls_record_encryption_level_t gtls_level)
                    134: {
                    135:   switch(gtls_level) {
                    136:   case GNUTLS_ENCRYPTION_LEVEL_INITIAL:
                    137:     return NGTCP2_CRYPTO_LEVEL_INITIAL;
                    138:   case GNUTLS_ENCRYPTION_LEVEL_EARLY:
                    139:     return NGTCP2_CRYPTO_LEVEL_EARLY;
                    140:   case GNUTLS_ENCRYPTION_LEVEL_HANDSHAKE:
                    141:     return NGTCP2_CRYPTO_LEVEL_HANDSHAKE;
                    142:   case GNUTLS_ENCRYPTION_LEVEL_APPLICATION:
                    143:     return NGTCP2_CRYPTO_LEVEL_APP;
                    144:   default:
                    145:     assert(0);
                    146:   }
                    147: }
                    148: #endif
                    149: 
                    150: static int setup_initial_crypto_context(struct quicsocket *qs)
                    151: {
                    152:   const ngtcp2_cid *dcid = ngtcp2_conn_get_dcid(qs->qconn);
                    153: 
                    154:   if(ngtcp2_crypto_derive_and_install_initial_key(
                    155:          qs->qconn, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
                    156:          dcid) != 0)
                    157:     return -1;
                    158: 
                    159:   return 0;
                    160: }
                    161: 
                    162: static void quic_settings(ngtcp2_settings *s,
                    163:                           uint64_t stream_buffer_size)
                    164: {
                    165:   ngtcp2_settings_default(s);
                    166: #ifdef DEBUG_NGTCP2
                    167:   s->log_printf = quic_printf;
                    168: #else
                    169:   s->log_printf = NULL;
                    170: #endif
                    171:   s->initial_ts = timestamp();
                    172:   s->transport_params.initial_max_stream_data_bidi_local = stream_buffer_size;
                    173:   s->transport_params.initial_max_stream_data_bidi_remote = QUIC_MAX_STREAMS;
                    174:   s->transport_params.initial_max_stream_data_uni = QUIC_MAX_STREAMS;
                    175:   s->transport_params.initial_max_data = QUIC_MAX_DATA;
                    176:   s->transport_params.initial_max_streams_bidi = 1;
                    177:   s->transport_params.initial_max_streams_uni = 3;
                    178:   s->transport_params.max_idle_timeout = QUIC_IDLE_TIMEOUT;
                    179: }
                    180: 
                    181: static FILE *keylog_file; /* not thread-safe */
                    182: #ifdef USE_OPENSSL
                    183: static void keylog_callback(const SSL *ssl, const char *line)
                    184: {
                    185:   (void)ssl;
                    186:   fputs(line, keylog_file);
                    187:   fputc('\n', keylog_file);
                    188:   fflush(keylog_file);
                    189: }
                    190: #elif defined(USE_GNUTLS)
                    191: static int keylog_callback(gnutls_session_t session, const char *label,
                    192:                     const gnutls_datum_t *secret)
                    193: {
                    194:   gnutls_datum_t crandom;
                    195:   gnutls_datum_t srandom;
                    196:   gnutls_datum_t crandom_hex = { NULL, 0 };
                    197:   gnutls_datum_t secret_hex = { NULL, 0 };
                    198:   int rc = 0;
                    199: 
                    200:   gnutls_session_get_random(session, &crandom, &srandom);
                    201:   if(crandom.size != 32) {
                    202:     return -1;
                    203:   }
                    204: 
                    205:   rc = gnutls_hex_encode2(&crandom, &crandom_hex);
                    206:   if(rc < 0) {
                    207:     fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
                    208:             gnutls_strerror(rc));
                    209:     goto out;
                    210:   }
                    211: 
                    212:   rc = gnutls_hex_encode2(secret, &secret_hex);
                    213:   if(rc < 0) {
                    214:     fprintf(stderr, "gnutls_hex_encode2 failed: %s\n",
                    215:             gnutls_strerror(rc));
                    216:     goto out;
                    217:   }
                    218: 
                    219:   fprintf(keylog_file, "%s %s %s\n", label, crandom_hex.data, secret_hex.data);
                    220:   fflush(keylog_file);
                    221: 
                    222:  out:
                    223:   gnutls_free(crandom_hex.data);
                    224:   gnutls_free(secret_hex.data);
                    225:   return rc;
                    226: }
                    227: #endif
                    228: 
                    229: static int init_ngh3_conn(struct quicsocket *qs);
                    230: 
                    231: static int write_client_handshake(struct quicsocket *qs,
                    232:                                   ngtcp2_crypto_level level,
                    233:                                   const uint8_t *data, size_t len)
                    234: {
                    235:   struct quic_handshake *crypto_data;
                    236:   int rv;
                    237: 
                    238:   crypto_data = &qs->crypto_data[level];
                    239:   if(crypto_data->buf == NULL) {
                    240:     crypto_data->buf = malloc(4096);
                    241:     if(!crypto_data->buf)
                    242:       return 0;
                    243:     crypto_data->alloclen = 4096;
                    244:   }
                    245: 
                    246:   /* TODO Just pretend that handshake does not grow more than 4KiB for
                    247:      now */
                    248:   assert(crypto_data->len + len <= crypto_data->alloclen);
                    249: 
                    250:   memcpy(&crypto_data->buf[crypto_data->len], data, len);
                    251:   crypto_data->len += len;
                    252: 
                    253:   rv = ngtcp2_conn_submit_crypto_data(
                    254:     qs->qconn, level, (uint8_t *)(&crypto_data->buf[crypto_data->len] - len),
                    255:     len);
                    256:   if(rv) {
                    257:     H3BUGF(fprintf(stderr, "write_client_handshake failed\n"));
                    258:   }
                    259:   assert(0 == rv);
                    260: 
                    261:   return 1;
                    262: }
                    263: 
                    264: #ifdef USE_OPENSSL
                    265: static int quic_set_encryption_secrets(SSL *ssl,
                    266:                                        OSSL_ENCRYPTION_LEVEL ossl_level,
                    267:                                        const uint8_t *rx_secret,
                    268:                                        const uint8_t *tx_secret,
                    269:                                        size_t secretlen)
                    270: {
                    271:   struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
                    272:   int level = quic_from_ossl_level(ossl_level);
                    273: 
                    274:   if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
                    275:      ngtcp2_crypto_derive_and_install_rx_key(
                    276:          qs->qconn, ssl, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
                    277:     return 0;
                    278: 
                    279:   if(ngtcp2_crypto_derive_and_install_tx_key(
                    280:          qs->qconn, ssl, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
                    281:     return 0;
                    282: 
                    283:   if(level == NGTCP2_CRYPTO_LEVEL_APP) {
                    284:     if(init_ngh3_conn(qs) != CURLE_OK)
                    285:       return 0;
                    286:   }
                    287: 
                    288:   return 1;
                    289: }
                    290: 
                    291: static int quic_add_handshake_data(SSL *ssl, OSSL_ENCRYPTION_LEVEL ossl_level,
                    292:                                    const uint8_t *data, size_t len)
                    293: {
                    294:   struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
                    295:   ngtcp2_crypto_level level = quic_from_ossl_level(ossl_level);
                    296: 
                    297:   return write_client_handshake(qs, level, data, len);
                    298: }
                    299: 
                    300: static int quic_flush_flight(SSL *ssl)
                    301: {
                    302:   (void)ssl;
                    303:   return 1;
                    304: }
                    305: 
                    306: static int quic_send_alert(SSL *ssl, enum ssl_encryption_level_t level,
                    307:                            uint8_t alert)
                    308: {
                    309:   struct quicsocket *qs = (struct quicsocket *)SSL_get_app_data(ssl);
                    310:   (void)level;
                    311: 
                    312:   qs->tls_alert = alert;
                    313:   return 1;
                    314: }
                    315: 
                    316: static SSL_QUIC_METHOD quic_method = {quic_set_encryption_secrets,
                    317:                                       quic_add_handshake_data,
                    318:                                       quic_flush_flight, quic_send_alert};
                    319: 
                    320: static SSL_CTX *quic_ssl_ctx(struct Curl_easy *data)
                    321: {
                    322:   SSL_CTX *ssl_ctx = SSL_CTX_new(TLS_method());
                    323:   const char *keylog_filename;
                    324: 
                    325:   SSL_CTX_set_min_proto_version(ssl_ctx, TLS1_3_VERSION);
                    326:   SSL_CTX_set_max_proto_version(ssl_ctx, TLS1_3_VERSION);
                    327: 
                    328:   SSL_CTX_set_default_verify_paths(ssl_ctx);
                    329: 
                    330:   if(SSL_CTX_set_ciphersuites(ssl_ctx, QUIC_CIPHERS) != 1) {
                    331:     char error_buffer[256];
                    332:     ERR_error_string_n(ERR_get_error(), error_buffer, sizeof(error_buffer));
                    333:     failf(data, "SSL_CTX_set_ciphersuites: %s", error_buffer);
                    334:     return NULL;
                    335:   }
                    336: 
                    337:   if(SSL_CTX_set1_groups_list(ssl_ctx, QUIC_GROUPS) != 1) {
                    338:     failf(data, "SSL_CTX_set1_groups_list failed");
                    339:     return NULL;
                    340:   }
                    341: 
                    342:   SSL_CTX_set_quic_method(ssl_ctx, &quic_method);
                    343: 
                    344:   keylog_filename = getenv("SSLKEYLOGFILE");
                    345:   if(keylog_filename) {
                    346:     keylog_file = fopen(keylog_filename, "wb");
                    347:     if(keylog_file) {
                    348:       SSL_CTX_set_keylog_callback(ssl_ctx, keylog_callback);
                    349:     }
                    350:   }
                    351: 
                    352:   return ssl_ctx;
                    353: }
                    354: 
                    355: /** SSL callbacks ***/
                    356: 
                    357: static int quic_init_ssl(struct quicsocket *qs)
                    358: {
                    359:   const uint8_t *alpn = NULL;
                    360:   size_t alpnlen = 0;
                    361:   /* this will need some attention when HTTPS proxy over QUIC get fixed */
                    362:   const char * const hostname = qs->conn->host.name;
                    363: 
                    364:   if(qs->ssl)
                    365:     SSL_free(qs->ssl);
                    366: 
                    367:   qs->ssl = SSL_new(qs->sslctx);
                    368: 
                    369:   SSL_set_app_data(qs->ssl, qs);
                    370:   SSL_set_connect_state(qs->ssl);
                    371: 
                    372:   switch(qs->version) {
                    373: #ifdef NGTCP2_PROTO_VER
                    374:   case NGTCP2_PROTO_VER:
                    375:     alpn = (const uint8_t *)NGTCP2_ALPN_H3;
                    376:     alpnlen = sizeof(NGTCP2_ALPN_H3) - 1;
                    377:     break;
                    378: #endif
                    379:   }
                    380:   if(alpn)
                    381:     SSL_set_alpn_protos(qs->ssl, alpn, (int)alpnlen);
                    382: 
                    383:   /* set SNI */
                    384:   SSL_set_tlsext_host_name(qs->ssl, hostname);
                    385:   return 0;
                    386: }
                    387: #elif defined(USE_GNUTLS)
                    388: static int secret_func(gnutls_session_t ssl,
                    389:                        gnutls_record_encryption_level_t gtls_level,
                    390:                        const void *rx_secret,
                    391:                        const void *tx_secret, size_t secretlen)
                    392: {
                    393:   struct quicsocket *qs = gnutls_session_get_ptr(ssl);
                    394:   int level = quic_from_gtls_level(gtls_level);
                    395: 
                    396:   if(level != NGTCP2_CRYPTO_LEVEL_EARLY &&
                    397:      ngtcp2_crypto_derive_and_install_rx_key(
                    398:          qs->qconn, ssl, NULL, NULL, NULL, level, rx_secret, secretlen) != 0)
                    399:     return 0;
                    400: 
                    401:   if(ngtcp2_crypto_derive_and_install_tx_key(
                    402:          qs->qconn, ssl, NULL, NULL, NULL, level, tx_secret, secretlen) != 0)
                    403:     return 0;
                    404: 
                    405:   if(level == NGTCP2_CRYPTO_LEVEL_APP) {
                    406:     if(init_ngh3_conn(qs) != CURLE_OK)
                    407:       return -1;
                    408:   }
                    409: 
                    410:   return 0;
                    411: }
                    412: 
                    413: static int read_func(gnutls_session_t ssl,
                    414:                      gnutls_record_encryption_level_t gtls_level,
                    415:                      gnutls_handshake_description_t htype, const void *data,
                    416:                      size_t len)
                    417: {
                    418:   struct quicsocket *qs = gnutls_session_get_ptr(ssl);
                    419:   ngtcp2_crypto_level level = quic_from_gtls_level(gtls_level);
                    420:   int rv;
                    421: 
                    422:   if(htype == GNUTLS_HANDSHAKE_CHANGE_CIPHER_SPEC)
                    423:     return 0;
                    424: 
                    425:   rv = write_client_handshake(qs, level, data, len);
                    426:   if(rv == 0)
                    427:     return -1;
                    428: 
                    429:   return 0;
                    430: }
                    431: 
                    432: static int alert_read_func(gnutls_session_t ssl,
                    433:                            gnutls_record_encryption_level_t gtls_level,
                    434:                            gnutls_alert_level_t alert_level,
                    435:                            gnutls_alert_description_t alert_desc)
                    436: {
                    437:   struct quicsocket *qs = gnutls_session_get_ptr(ssl);
                    438:   (void)gtls_level;
                    439:   (void)alert_level;
                    440: 
                    441:   qs->tls_alert = alert_desc;
                    442:   return 1;
                    443: }
                    444: 
                    445: static int tp_recv_func(gnutls_session_t ssl, const uint8_t *data,
                    446:                         size_t data_size)
                    447: {
                    448:   struct quicsocket *qs = gnutls_session_get_ptr(ssl);
                    449:   ngtcp2_transport_params params;
                    450: 
                    451:   if(ngtcp2_decode_transport_params(
                    452:          &params, NGTCP2_TRANSPORT_PARAMS_TYPE_ENCRYPTED_EXTENSIONS,
                    453:          data, data_size) != 0)
                    454:     return -1;
                    455: 
                    456:   if(ngtcp2_conn_set_remote_transport_params(qs->qconn, &params) != 0)
                    457:     return -1;
                    458: 
                    459:   return 0;
                    460: }
                    461: 
                    462: static int tp_send_func(gnutls_session_t ssl, gnutls_buffer_t extdata)
                    463: {
                    464:   struct quicsocket *qs = gnutls_session_get_ptr(ssl);
                    465:   uint8_t paramsbuf[64];
                    466:   ngtcp2_transport_params params;
                    467:   ssize_t nwrite;
                    468:   int rc;
                    469: 
                    470:   ngtcp2_conn_get_local_transport_params(qs->qconn, &params);
                    471:   nwrite = ngtcp2_encode_transport_params(
                    472:     paramsbuf, sizeof(paramsbuf), NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
                    473:     &params);
                    474:   if(nwrite < 0) {
                    475:     fprintf(stderr, "ngtcp2_encode_transport_params: %s\n",
                    476:           ngtcp2_strerror((int)nwrite));
                    477:     return -1;
                    478:   }
                    479: 
                    480:   rc = gnutls_buffer_append_data(extdata, paramsbuf, nwrite);
                    481:   if(rc < 0)
                    482:     return rc;
                    483: 
                    484:   return (int)nwrite;
                    485: }
                    486: 
                    487: static int quic_init_ssl(struct quicsocket *qs)
                    488: {
                    489:   gnutls_datum_t alpn = {NULL, 0};
                    490:   /* this will need some attention when HTTPS proxy over QUIC get fixed */
                    491:   const char * const hostname = qs->conn->host.name;
                    492:   const char *keylog_filename;
                    493:   int rc;
                    494: 
                    495:   if(qs->ssl)
                    496:     gnutls_deinit(qs->ssl);
                    497: 
                    498:   gnutls_init(&qs->ssl, GNUTLS_CLIENT);
                    499:   gnutls_session_set_ptr(qs->ssl, qs);
                    500: 
                    501:   rc = gnutls_priority_set_direct(qs->ssl, QUIC_PRIORITY, NULL);
                    502:   if(rc < 0) {
                    503:     fprintf(stderr, "gnutls_priority_set_direct failed: %s\n",
                    504:             gnutls_strerror(rc));
                    505:     return 1;
                    506:   }
                    507: 
                    508:   gnutls_handshake_set_secret_function(qs->ssl, secret_func);
                    509:   gnutls_handshake_set_read_function(qs->ssl, read_func);
                    510:   gnutls_alert_set_read_function(qs->ssl, alert_read_func);
                    511: 
                    512:   rc = gnutls_session_ext_register(qs->ssl, "QUIC Transport Parameters",
                    513:                                    0xffa5, GNUTLS_EXT_TLS,
                    514:                                    tp_recv_func, tp_send_func,
                    515:                                    NULL, NULL, NULL,
                    516:                                    GNUTLS_EXT_FLAG_TLS |
                    517:                                    GNUTLS_EXT_FLAG_CLIENT_HELLO |
                    518:                                    GNUTLS_EXT_FLAG_EE);
                    519:   if(rc < 0) {
                    520:     fprintf(stderr, "gnutls_session_ext_register failed: %s\n",
                    521:             gnutls_strerror(rc));
                    522:     return 1;
                    523:   }
                    524: 
                    525:   keylog_filename = getenv("SSLKEYLOGFILE");
                    526:   if(keylog_filename) {
                    527:     keylog_file = fopen(keylog_filename, "wb");
                    528:     if(keylog_file) {
                    529:       gnutls_session_set_keylog_function(qs->ssl, keylog_callback);
                    530:     }
                    531:   }
                    532: 
                    533:   if(qs->cred)
                    534:     gnutls_certificate_free_credentials(qs->cred);
                    535: 
                    536:   rc = gnutls_certificate_allocate_credentials(&qs->cred);
                    537:   if(rc < 0) {
                    538:     fprintf(stderr, "gnutls_certificate_allocate_credentials failed: %s\n",
                    539:             gnutls_strerror(rc));
                    540:     return 1;
                    541:   }
                    542: 
                    543:   rc = gnutls_certificate_set_x509_system_trust(qs->cred);
                    544:   if(rc < 0) {
                    545:     fprintf(stderr, "gnutls_certificate_set_x509_system_trust failed: %s\n",
                    546:             gnutls_strerror(rc));
                    547:     return 1;
                    548:   }
                    549: 
                    550:   rc = gnutls_credentials_set(qs->ssl, GNUTLS_CRD_CERTIFICATE, qs->cred);
                    551:   if(rc < 0) {
                    552:     fprintf(stderr, "gnutls_credentials_set failed: %s\n",
                    553:             gnutls_strerror(rc));
                    554:     return 1;
                    555:   }
                    556: 
                    557:   switch(qs->version) {
                    558: #ifdef NGTCP2_PROTO_VER
                    559:   case NGTCP2_PROTO_VER:
                    560:     /* strip the first byte from NGTCP2_ALPN_H3 */
                    561:     alpn.data = (unsigned char *)NGTCP2_ALPN_H3 + 1;
                    562:     alpn.size = sizeof(NGTCP2_ALPN_H3) - 2;
                    563:     break;
                    564: #endif
                    565:   }
                    566:   if(alpn.data)
                    567:     gnutls_alpn_set_protocols(qs->ssl, &alpn, 1, 0);
                    568: 
                    569:   /* set SNI */
                    570:   gnutls_server_name_set(qs->ssl, GNUTLS_NAME_DNS, hostname, strlen(hostname));
                    571:   return 0;
                    572: }
                    573: #endif
                    574: 
                    575: static int cb_initial(ngtcp2_conn *quic, void *user_data)
                    576: {
                    577:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    578: 
                    579:   if(ngtcp2_crypto_read_write_crypto_data(
                    580:        quic, qs->ssl, NGTCP2_CRYPTO_LEVEL_INITIAL, NULL, 0) != 0)
                    581:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    582: 
                    583:   return 0;
                    584: }
                    585: 
                    586: static int
                    587: cb_recv_crypto_data(ngtcp2_conn *tconn, ngtcp2_crypto_level crypto_level,
                    588:                     uint64_t offset,
                    589:                     const uint8_t *data, size_t datalen,
                    590:                     void *user_data)
                    591: {
                    592:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    593:   (void)offset;
                    594: 
                    595:   if(ngtcp2_crypto_read_write_crypto_data(tconn, qs->ssl, crypto_level, data,
                    596:                                           datalen) != 0)
                    597:     return NGTCP2_ERR_CRYPTO;
                    598: 
                    599:   return 0;
                    600: }
                    601: 
                    602: static int cb_handshake_completed(ngtcp2_conn *tconn, void *user_data)
                    603: {
                    604:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    605:   (void)tconn;
                    606:   infof(qs->conn->data, "QUIC handshake is completed\n");
                    607: 
                    608:   return 0;
                    609: }
                    610: 
                    611: static void extend_stream_window(ngtcp2_conn *tconn,
                    612:                                  struct HTTP *stream)
                    613: {
                    614:   size_t thismuch = stream->unacked_window;
                    615:   ngtcp2_conn_extend_max_stream_offset(tconn, stream->stream3_id, thismuch);
                    616:   ngtcp2_conn_extend_max_offset(tconn, thismuch);
                    617:   stream->unacked_window = 0;
                    618: }
                    619: 
                    620: 
                    621: static int cb_recv_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
                    622:                                int fin, uint64_t offset,
                    623:                                const uint8_t *buf, size_t buflen,
                    624:                                void *user_data, void *stream_user_data)
                    625: {
                    626:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    627:   ssize_t nconsumed;
                    628:   (void)offset;
                    629:   (void)stream_user_data;
                    630: 
                    631:   nconsumed =
                    632:     nghttp3_conn_read_stream(qs->h3conn, stream_id, buf, buflen, fin);
                    633:   if(nconsumed < 0) {
                    634:     failf(qs->conn->data, "nghttp3_conn_read_stream returned error: %s\n",
                    635:           nghttp3_strerror((int)nconsumed));
                    636:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    637:   }
                    638: 
                    639:   /* number of bytes inside buflen which consists of framing overhead
                    640:    * including QPACK HEADERS. In other words, it does not consume payload of
                    641:    * DATA frame. */
                    642:   ngtcp2_conn_extend_max_stream_offset(tconn, stream_id, nconsumed);
                    643:   ngtcp2_conn_extend_max_offset(tconn, nconsumed);
                    644: 
                    645:   return 0;
                    646: }
                    647: 
                    648: static int
                    649: cb_acked_stream_data_offset(ngtcp2_conn *tconn, int64_t stream_id,
                    650:                             uint64_t offset, size_t datalen, void *user_data,
                    651:                             void *stream_user_data)
                    652: {
                    653:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    654:   int rv;
                    655:   (void)stream_id;
                    656:   (void)tconn;
                    657:   (void)offset;
                    658:   (void)datalen;
                    659:   (void)stream_user_data;
                    660: 
                    661:   rv = nghttp3_conn_add_ack_offset(qs->h3conn, stream_id, datalen);
                    662:   if(rv != 0) {
                    663:     failf(qs->conn->data, "nghttp3_conn_add_ack_offset returned error: %s\n",
                    664:           nghttp3_strerror(rv));
                    665:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    666:   }
                    667: 
                    668:   return 0;
                    669: }
                    670: 
                    671: static int cb_stream_close(ngtcp2_conn *tconn, int64_t stream_id,
                    672:                            uint64_t app_error_code,
                    673:                            void *user_data, void *stream_user_data)
                    674: {
                    675:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    676:   int rv;
                    677:   (void)tconn;
                    678:   (void)stream_user_data;
                    679:   /* stream is closed... */
                    680: 
                    681:   rv = nghttp3_conn_close_stream(qs->h3conn, stream_id,
                    682:                                  app_error_code);
                    683:   if(rv != 0) {
                    684:     failf(qs->conn->data, "nghttp3_conn_close_stream returned error: %s\n",
                    685:           nghttp3_strerror(rv));
                    686:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    687:   }
                    688: 
                    689:   return 0;
                    690: }
                    691: 
                    692: static int cb_stream_reset(ngtcp2_conn *tconn, int64_t stream_id,
                    693:                            uint64_t final_size, uint64_t app_error_code,
                    694:                            void *user_data, void *stream_user_data)
                    695: {
                    696:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    697:   int rv;
                    698:   (void)tconn;
                    699:   (void)final_size;
                    700:   (void)app_error_code;
                    701:   (void)stream_user_data;
                    702: 
                    703:   rv = nghttp3_conn_reset_stream(qs->h3conn, stream_id);
                    704:   if(rv != 0) {
                    705:     failf(qs->conn->data, "nghttp3_conn_reset_stream returned error: %s\n",
                    706:           nghttp3_strerror(rv));
                    707:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    708:   }
                    709: 
                    710:   return 0;
                    711: }
                    712: 
                    713: static int cb_recv_retry(ngtcp2_conn *tconn, const ngtcp2_pkt_hd *hd,
                    714:                          const ngtcp2_pkt_retry *retry, void *user_data)
                    715: {
                    716:   /* Re-generate handshake secrets here because connection ID might change. */
                    717:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    718:   (void)tconn;
                    719:   (void)hd;
                    720:   (void)retry;
                    721: 
                    722:   setup_initial_crypto_context(qs);
                    723: 
                    724:   return 0;
                    725: }
                    726: 
                    727: static int cb_extend_max_local_streams_bidi(ngtcp2_conn *tconn,
                    728:                                             uint64_t max_streams,
                    729:                                             void *user_data)
                    730: {
                    731:   (void)tconn;
                    732:   (void)max_streams;
                    733:   (void)user_data;
                    734: 
                    735:   return 0;
                    736: }
                    737: 
                    738: static int cb_extend_max_stream_data(ngtcp2_conn *tconn, int64_t stream_id,
                    739:                                      uint64_t max_data, void *user_data,
                    740:                                      void *stream_user_data)
                    741: {
                    742:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    743:   int rv;
                    744:   (void)tconn;
                    745:   (void)max_data;
                    746:   (void)stream_user_data;
                    747: 
                    748:   rv = nghttp3_conn_unblock_stream(qs->h3conn, stream_id);
                    749:   if(rv != 0) {
                    750:     failf(qs->conn->data, "nghttp3_conn_unblock_stream returned error: %s\n",
                    751:           nghttp3_strerror(rv));
                    752:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    753:   }
                    754: 
                    755:   return 0;
                    756: }
                    757: 
                    758: static int cb_get_new_connection_id(ngtcp2_conn *tconn, ngtcp2_cid *cid,
                    759:                                     uint8_t *token, size_t cidlen,
                    760:                                     void *user_data)
                    761: {
                    762:   struct quicsocket *qs = (struct quicsocket *)user_data;
                    763:   CURLcode result;
                    764:   (void)tconn;
                    765: 
                    766:   result = Curl_rand(qs->conn->data, cid->data, cidlen);
                    767:   if(result)
                    768:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    769:   cid->datalen = cidlen;
                    770: 
                    771:   result = Curl_rand(qs->conn->data, token, NGTCP2_STATELESS_RESET_TOKENLEN);
                    772:   if(result)
                    773:     return NGTCP2_ERR_CALLBACK_FAILURE;
                    774: 
                    775:   return 0;
                    776: }
                    777: 
                    778: static ngtcp2_conn_callbacks ng_callbacks = {
                    779:   cb_initial,
                    780:   NULL, /* recv_client_initial */
                    781:   cb_recv_crypto_data,
                    782:   cb_handshake_completed,
                    783:   NULL, /* recv_version_negotiation */
                    784:   ngtcp2_crypto_encrypt_cb,
                    785:   ngtcp2_crypto_decrypt_cb,
                    786:   ngtcp2_crypto_hp_mask_cb,
                    787:   cb_recv_stream_data,
                    788:   NULL, /* acked_crypto_offset */
                    789:   cb_acked_stream_data_offset,
                    790:   NULL, /* stream_open */
                    791:   cb_stream_close,
                    792:   NULL, /* recv_stateless_reset */
                    793:   cb_recv_retry,
                    794:   cb_extend_max_local_streams_bidi,
                    795:   NULL, /* extend_max_local_streams_uni */
                    796:   NULL, /* rand  */
                    797:   cb_get_new_connection_id,
                    798:   NULL, /* remove_connection_id */
                    799:   ngtcp2_crypto_update_key_cb, /* update_key */
                    800:   NULL, /* path_validation */
                    801:   NULL, /* select_preferred_addr */
                    802:   cb_stream_reset,
                    803:   NULL, /* extend_max_remote_streams_bidi */
                    804:   NULL, /* extend_max_remote_streams_uni */
                    805:   cb_extend_max_stream_data,
                    806:   NULL, /* dcid_status */
                    807:   NULL  /* handshake_confirmed */
                    808: };
                    809: 
                    810: /*
                    811:  * Might be called twice for happy eyeballs.
                    812:  */
                    813: CURLcode Curl_quic_connect(struct connectdata *conn,
                    814:                            curl_socket_t sockfd,
                    815:                            int sockindex,
                    816:                            const struct sockaddr *addr,
                    817:                            socklen_t addrlen)
                    818: {
                    819:   int rc;
                    820:   int rv;
                    821:   CURLcode result;
                    822:   ngtcp2_path path; /* TODO: this must be initialized properly */
                    823:   struct Curl_easy *data = conn->data;
                    824:   struct quicsocket *qs = &conn->hequic[sockindex];
                    825:   char ipbuf[40];
                    826:   long port;
                    827: #ifdef USE_OPENSSL
                    828:   uint8_t paramsbuf[64];
                    829:   ngtcp2_transport_params params;
                    830:   ssize_t nwrite;
                    831: #endif
                    832: 
                    833:   qs->conn = conn;
                    834: 
                    835:   /* extract the used address as a string */
                    836:   if(!Curl_addr2string((struct sockaddr*)addr, addrlen, ipbuf, &port)) {
                    837:     char buffer[STRERROR_LEN];
                    838:     failf(data, "ssrem inet_ntop() failed with errno %d: %s",
                    839:           SOCKERRNO, Curl_strerror(SOCKERRNO, buffer, sizeof(buffer)));
                    840:     return CURLE_BAD_FUNCTION_ARGUMENT;
                    841:   }
                    842: 
                    843:   infof(data, "Connect socket %d over QUIC to %s:%ld\n",
                    844:         sockfd, ipbuf, port);
                    845: 
                    846:   qs->version = NGTCP2_PROTO_VER;
                    847: #ifdef USE_OPENSSL
                    848:   qs->sslctx = quic_ssl_ctx(data);
                    849:   if(!qs->sslctx)
                    850:     return CURLE_QUIC_CONNECT_ERROR;
                    851: #endif
                    852: 
                    853:   if(quic_init_ssl(qs))
                    854:     return CURLE_QUIC_CONNECT_ERROR;
                    855: 
                    856:   qs->dcid.datalen = NGTCP2_MAX_CIDLEN;
                    857:   result = Curl_rand(data, qs->dcid.data, NGTCP2_MAX_CIDLEN);
                    858:   if(result)
                    859:     return result;
                    860: 
                    861:   qs->scid.datalen = NGTCP2_MAX_CIDLEN;
                    862:   result = Curl_rand(data, qs->scid.data, NGTCP2_MAX_CIDLEN);
                    863:   if(result)
                    864:     return result;
                    865: 
                    866:   quic_settings(&qs->settings, data->set.buffer_size);
                    867: 
                    868:   qs->local_addrlen = sizeof(qs->local_addr);
                    869:   rv = getsockname(sockfd, (struct sockaddr *)&qs->local_addr,
                    870:                    &qs->local_addrlen);
                    871:   if(rv == -1)
                    872:     return CURLE_QUIC_CONNECT_ERROR;
                    873: 
                    874:   ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr, qs->local_addrlen,
                    875:                    NULL);
                    876:   ngtcp2_addr_init(&path.remote, (uint8_t*)addr, addrlen, NULL);
                    877: 
                    878: #ifdef NGTCP2_PROTO_VER
                    879: #define QUICVER NGTCP2_PROTO_VER
                    880: #else
                    881: #error "unsupported ngtcp2 version"
                    882: #endif
                    883:   rc = ngtcp2_conn_client_new(&qs->qconn, &qs->dcid, &qs->scid, &path, QUICVER,
                    884:                               &ng_callbacks, &qs->settings, NULL, qs);
                    885:   if(rc)
                    886:     return CURLE_QUIC_CONNECT_ERROR;
                    887: 
                    888: #ifdef USE_OPENSSL
                    889:   ngtcp2_conn_get_local_transport_params(qs->qconn, &params);
                    890:   nwrite = ngtcp2_encode_transport_params(
                    891:     paramsbuf, sizeof(paramsbuf), NGTCP2_TRANSPORT_PARAMS_TYPE_CLIENT_HELLO,
                    892:     &params);
                    893:   if(nwrite < 0) {
                    894:     failf(data, "ngtcp2_encode_transport_params: %s\n",
                    895:           ngtcp2_strerror((int)nwrite));
                    896:     return CURLE_QUIC_CONNECT_ERROR;
                    897:   }
                    898: 
                    899:   if(!SSL_set_quic_transport_params(qs->ssl, paramsbuf, nwrite))
                    900:     return CURLE_QUIC_CONNECT_ERROR;
                    901: #endif
                    902: 
                    903:   rc = setup_initial_crypto_context(qs);
                    904:   if(rc)
                    905:     return CURLE_QUIC_CONNECT_ERROR;
                    906: 
                    907:   return CURLE_OK;
                    908: }
                    909: 
                    910: /*
                    911:  * Store ngtp2 version info in this buffer, Prefix with a space.  Return total
                    912:  * length written.
                    913:  */
                    914: int Curl_quic_ver(char *p, size_t len)
                    915: {
                    916:   ngtcp2_info *ng2 = ngtcp2_version(0);
                    917:   nghttp3_info *ht3 = nghttp3_version(0);
                    918:   return msnprintf(p, len, "ngtcp2/%s nghttp3/%s",
                    919:                    ng2->version_str, ht3->version_str);
                    920: }
                    921: 
                    922: static int ng_getsock(struct connectdata *conn, curl_socket_t *socks)
                    923: {
                    924:   struct SingleRequest *k = &conn->data->req;
                    925:   int bitmap = GETSOCK_BLANK;
                    926: 
                    927:   socks[0] = conn->sock[FIRSTSOCKET];
                    928: 
                    929:   /* in a HTTP/2 connection we can basically always get a frame so we should
                    930:      always be ready for one */
                    931:   bitmap |= GETSOCK_READSOCK(FIRSTSOCKET);
                    932: 
                    933:   /* we're still uploading or the HTTP/2 layer wants to send data */
                    934:   if((k->keepon & (KEEP_SEND|KEEP_SEND_PAUSE)) == KEEP_SEND)
                    935:     bitmap |= GETSOCK_WRITESOCK(FIRSTSOCKET);
                    936: 
                    937:   return bitmap;
                    938: }
                    939: 
                    940: static int ng_perform_getsock(const struct connectdata *conn,
                    941:                               curl_socket_t *socks)
                    942: {
                    943:   return ng_getsock((struct connectdata *)conn, socks);
                    944: }
                    945: 
                    946: static CURLcode ng_disconnect(struct connectdata *conn,
                    947:                               bool dead_connection)
                    948: {
                    949:   int i;
                    950:   struct quicsocket *qs = &conn->hequic[0];
                    951:   (void)dead_connection;
                    952:   if(qs->ssl)
                    953: #ifdef USE_OPENSSL
                    954:     SSL_free(qs->ssl);
                    955: #elif defined(USE_GNUTLS)
                    956:     gnutls_deinit(qs->ssl);
                    957: #endif
                    958: #ifdef USE_GNUTLS
                    959:   if(qs->cred)
                    960:     gnutls_certificate_free_credentials(qs->cred);
                    961: #endif
                    962:   for(i = 0; i < 3; i++)
                    963:     free(qs->crypto_data[i].buf);
                    964:   nghttp3_conn_del(qs->h3conn);
                    965:   ngtcp2_conn_del(qs->qconn);
                    966: #ifdef USE_OPENSSL
                    967:   SSL_CTX_free(qs->sslctx);
                    968: #endif
                    969:   return CURLE_OK;
                    970: }
                    971: 
                    972: static unsigned int ng_conncheck(struct connectdata *conn,
                    973:                                  unsigned int checks_to_perform)
                    974: {
                    975:   (void)conn;
                    976:   (void)checks_to_perform;
                    977:   return CONNRESULT_NONE;
                    978: }
                    979: 
                    980: static const struct Curl_handler Curl_handler_http3 = {
                    981:   "HTTPS",                              /* scheme */
                    982:   ZERO_NULL,                            /* setup_connection */
                    983:   Curl_http,                            /* do_it */
                    984:   Curl_http_done,                       /* done */
                    985:   ZERO_NULL,                            /* do_more */
                    986:   ZERO_NULL,                            /* connect_it */
                    987:   ZERO_NULL,                            /* connecting */
                    988:   ZERO_NULL,                            /* doing */
                    989:   ng_getsock,                           /* proto_getsock */
                    990:   ng_getsock,                           /* doing_getsock */
                    991:   ZERO_NULL,                            /* domore_getsock */
                    992:   ng_perform_getsock,                   /* perform_getsock */
                    993:   ng_disconnect,                        /* disconnect */
                    994:   ZERO_NULL,                            /* readwrite */
                    995:   ng_conncheck,                         /* connection_check */
                    996:   PORT_HTTP,                            /* defport */
                    997:   CURLPROTO_HTTPS,                      /* protocol */
                    998:   PROTOPT_SSL | PROTOPT_STREAM          /* flags */
                    999: };
                   1000: 
                   1001: static int cb_h3_stream_close(nghttp3_conn *conn, int64_t stream_id,
                   1002:                               uint64_t app_error_code, void *user_data,
                   1003:                               void *stream_user_data)
                   1004: {
                   1005:   struct Curl_easy *data = stream_user_data;
                   1006:   struct HTTP *stream = data->req.protop;
                   1007:   (void)conn;
                   1008:   (void)stream_id;
                   1009:   (void)app_error_code;
                   1010:   (void)user_data;
                   1011:   H3BUGF(infof(data, "cb_h3_stream_close CALLED\n"));
                   1012: 
                   1013:   stream->closed = TRUE;
                   1014:   Curl_expire(data, 0, EXPIRE_QUIC);
                   1015:   /* make sure that ngh3_stream_recv is called again to complete the transfer
                   1016:      even if there are no more packets to be received from the server. */
                   1017:   data->state.drain = 1;
                   1018:   return 0;
                   1019: }
                   1020: 
                   1021: /* Minimum size of the overflow buffer */
                   1022: #define OVERFLOWSIZE 1024
                   1023: 
                   1024: /*
                   1025:  * allocate_overflow() ensures that there is room for incoming data in the
                   1026:  * overflow buffer, growing it to accommodate the new data if necessary. We
                   1027:  * may need to use the overflow buffer because we can't precisely limit the
                   1028:  * amount of HTTP/3 header data we receive using QUIC flow control mechanisms.
                   1029:  */
                   1030: static CURLcode allocate_overflow(struct Curl_easy *data,
                   1031:                                   struct HTTP *stream,
                   1032:                                   size_t length)
                   1033: {
                   1034:   size_t maxleft;
                   1035:   size_t newsize;
                   1036:   /* length can be arbitrarily large, so take care not to overflow newsize */
                   1037:   maxleft = CURL_MAX_READ_SIZE - stream->overflow_buflen;
                   1038:   if(length > maxleft) {
                   1039:     /* The reason to have a max limit for this is to avoid the risk of a bad
                   1040:        server feeding libcurl with a highly compressed list of headers that
                   1041:        will cause our overflow buffer to grow too large */
                   1042:     failf(data, "Rejected %zu bytes of overflow data (max is %d)!",
                   1043:           stream->overflow_buflen + length, CURL_MAX_READ_SIZE);
                   1044:     return CURLE_OUT_OF_MEMORY;
                   1045:   }
                   1046:   newsize = stream->overflow_buflen + length;
                   1047:   if(newsize > stream->overflow_bufsize) {
                   1048:     /* We enlarge the overflow buffer as it is too small */
                   1049:     char *newbuff;
                   1050:     newsize = CURLMAX(newsize * 3 / 2, stream->overflow_bufsize*2);
                   1051:     newsize = CURLMIN(CURLMAX(OVERFLOWSIZE, newsize), CURL_MAX_READ_SIZE);
                   1052:     newbuff = realloc(stream->overflow_buf, newsize);
                   1053:     if(!newbuff) {
                   1054:       failf(data, "Failed to alloc memory for overflow buffer!");
                   1055:       return CURLE_OUT_OF_MEMORY;
                   1056:     }
                   1057:     stream->overflow_buf = newbuff;
                   1058:     stream->overflow_bufsize = newsize;
                   1059:     infof(data, "Grew HTTP/3 overflow buffer to %zu bytes\n", newsize);
                   1060:   }
                   1061:   return CURLE_OK;
                   1062: }
                   1063: 
                   1064: /*
                   1065:  * write_data() copies data to the stream's receive buffer. If not enough
                   1066:  * space is available in the receive buffer, it copies the rest to the
                   1067:  * stream's overflow buffer.
                   1068:  */
                   1069: static CURLcode write_data(struct Curl_easy *data,
                   1070:                            struct HTTP *stream,
                   1071:                            const void *mem, size_t memlen)
                   1072: {
                   1073:   CURLcode result = CURLE_OK;
                   1074:   const char *buf = mem;
                   1075:   size_t ncopy = memlen;
                   1076:   /* copy as much as possible to the receive buffer */
                   1077:   if(stream->len) {
                   1078:     size_t len = CURLMIN(ncopy, stream->len);
                   1079: #if 0 /* extra debugging of incoming h3 data */
                   1080:     fprintf(stderr, "!! Copies %zd bytes to %p (total %zd)\n",
                   1081:             len, stream->mem, stream->memlen);
                   1082: #endif
                   1083:     memcpy(stream->mem, buf, len);
                   1084:     stream->len -= len;
                   1085:     stream->memlen += len;
                   1086:     stream->mem += len;
                   1087:     buf += len;
                   1088:     ncopy -= len;
                   1089:   }
                   1090:   /* copy the rest to the overflow buffer */
                   1091:   if(ncopy) {
                   1092:     result = allocate_overflow(data, stream, ncopy);
                   1093:     if(result) {
                   1094:       return result;
                   1095:     }
                   1096: #if 0 /* extra debugging of incoming h3 data */
                   1097:     fprintf(stderr, "!! Copies %zd overflow bytes to %p (total %zd)\n",
                   1098:             ncopy, stream->overflow_buf, stream->overflow_buflen);
                   1099: #endif
                   1100:     memcpy(stream->overflow_buf + stream->overflow_buflen, buf, ncopy);
                   1101:     stream->overflow_buflen += ncopy;
                   1102:   }
                   1103: #if 0 /* extra debugging of incoming h3 data */
                   1104:   {
                   1105:     size_t i;
                   1106:     for(i = 0; i < memlen; i++) {
                   1107:       fprintf(stderr, "!! data[%d]: %02x '%c'\n", i, buf[i], buf[i]);
                   1108:     }
                   1109:   }
                   1110: #endif
                   1111:   return result;
                   1112: }
                   1113: 
                   1114: static int cb_h3_recv_data(nghttp3_conn *conn, int64_t stream_id,
                   1115:                            const uint8_t *buf, size_t buflen,
                   1116:                            void *user_data, void *stream_user_data)
                   1117: {
                   1118:   struct Curl_easy *data = stream_user_data;
                   1119:   struct HTTP *stream = data->req.protop;
                   1120:   CURLcode result = CURLE_OK;
                   1121:   (void)conn;
                   1122: 
                   1123:   result = write_data(data, stream, buf, buflen);
                   1124:   if(result) {
                   1125:     return -1;
                   1126:   }
                   1127:   stream->unacked_window += buflen;
                   1128:   (void)stream_id;
                   1129:   (void)user_data;
                   1130:   return 0;
                   1131: }
                   1132: 
                   1133: static int cb_h3_deferred_consume(nghttp3_conn *conn, int64_t stream_id,
                   1134:                                   size_t consumed, void *user_data,
                   1135:                                   void *stream_user_data)
                   1136: {
                   1137:   struct quicsocket *qs = user_data;
                   1138:   (void)conn;
                   1139:   (void)stream_user_data;
                   1140:   (void)stream_id;
                   1141: 
                   1142:   ngtcp2_conn_extend_max_stream_offset(qs->qconn, stream_id, consumed);
                   1143:   ngtcp2_conn_extend_max_offset(qs->qconn, consumed);
                   1144:   return 0;
                   1145: }
                   1146: 
                   1147: /* Decode HTTP status code.  Returns -1 if no valid status code was
                   1148:    decoded. (duplicate from http2.c) */
                   1149: static int decode_status_code(const uint8_t *value, size_t len)
                   1150: {
                   1151:   int i;
                   1152:   int res;
                   1153: 
                   1154:   if(len != 3) {
                   1155:     return -1;
                   1156:   }
                   1157: 
                   1158:   res = 0;
                   1159: 
                   1160:   for(i = 0; i < 3; ++i) {
                   1161:     char c = value[i];
                   1162: 
                   1163:     if(c < '0' || c > '9') {
                   1164:       return -1;
                   1165:     }
                   1166: 
                   1167:     res *= 10;
                   1168:     res += c - '0';
                   1169:   }
                   1170: 
                   1171:   return res;
                   1172: }
                   1173: 
                   1174: static int cb_h3_end_headers(nghttp3_conn *conn, int64_t stream_id,
                   1175:                              void *user_data, void *stream_user_data)
                   1176: {
                   1177:   struct Curl_easy *data = stream_user_data;
                   1178:   struct HTTP *stream = data->req.protop;
                   1179:   CURLcode result = CURLE_OK;
                   1180:   (void)conn;
                   1181:   (void)stream_id;
                   1182:   (void)user_data;
                   1183: 
                   1184:   /* add a CRLF only if we've received some headers */
                   1185:   if(stream->firstheader) {
                   1186:     result = write_data(data, stream, "\r\n", 2);
                   1187:     if(result) {
                   1188:       return -1;
                   1189:     }
                   1190:   }
                   1191:   return 0;
                   1192: }
                   1193: 
                   1194: static int cb_h3_recv_header(nghttp3_conn *conn, int64_t stream_id,
                   1195:                              int32_t token, nghttp3_rcbuf *name,
                   1196:                              nghttp3_rcbuf *value, uint8_t flags,
                   1197:                              void *user_data, void *stream_user_data)
                   1198: {
                   1199:   nghttp3_vec h3name = nghttp3_rcbuf_get_buf(name);
                   1200:   nghttp3_vec h3val = nghttp3_rcbuf_get_buf(value);
                   1201:   struct Curl_easy *data = stream_user_data;
                   1202:   struct HTTP *stream = data->req.protop;
                   1203:   CURLcode result = CURLE_OK;
                   1204:   (void)conn;
                   1205:   (void)stream_id;
                   1206:   (void)token;
                   1207:   (void)flags;
                   1208:   (void)user_data;
                   1209: 
                   1210:   if(h3name.len == sizeof(":status") - 1 &&
                   1211:      !memcmp(":status", h3name.base, h3name.len)) {
                   1212:     char line[14]; /* status line is always 13 characters long */
                   1213:     size_t ncopy;
                   1214:     int status = decode_status_code(h3val.base, h3val.len);
                   1215:     DEBUGASSERT(status != -1);
                   1216:     ncopy = msnprintf(line, sizeof(line), "HTTP/3 %03d \r\n", status);
                   1217:     result = write_data(data, stream, line, ncopy);
                   1218:     if(result) {
                   1219:       return -1;
                   1220:     }
                   1221:   }
                   1222:   else {
                   1223:     /* store as a HTTP1-style header */
                   1224:     result = write_data(data, stream, h3name.base, h3name.len);
                   1225:     if(result) {
                   1226:       return -1;
                   1227:     }
                   1228:     result = write_data(data, stream, ": ", 2);
                   1229:     if(result) {
                   1230:       return -1;
                   1231:     }
                   1232:     result = write_data(data, stream, h3val.base, h3val.len);
                   1233:     if(result) {
                   1234:       return -1;
                   1235:     }
                   1236:     result = write_data(data, stream, "\r\n", 2);
                   1237:     if(result) {
                   1238:       return -1;
                   1239:     }
                   1240:   }
                   1241: 
                   1242:   stream->firstheader = TRUE;
                   1243:   return 0;
                   1244: }
                   1245: 
                   1246: static int cb_h3_send_stop_sending(nghttp3_conn *conn, int64_t stream_id,
                   1247:                                    uint64_t app_error_code,
                   1248:                                    void *user_data,
                   1249:                                    void *stream_user_data)
                   1250: {
                   1251:   (void)conn;
                   1252:   (void)stream_id;
                   1253:   (void)app_error_code;
                   1254:   (void)user_data;
                   1255:   (void)stream_user_data;
                   1256:   return 0;
                   1257: }
                   1258: 
                   1259: static nghttp3_conn_callbacks ngh3_callbacks = {
                   1260:   cb_h3_acked_stream_data, /* acked_stream_data */
                   1261:   cb_h3_stream_close,
                   1262:   cb_h3_recv_data,
                   1263:   cb_h3_deferred_consume,
                   1264:   NULL, /* begin_headers */
                   1265:   cb_h3_recv_header,
                   1266:   cb_h3_end_headers,
                   1267:   NULL, /* begin_trailers */
                   1268:   cb_h3_recv_header,
                   1269:   NULL, /* end_trailers */
                   1270:   NULL, /* http_begin_push_promise */
                   1271:   NULL, /* http_recv_push_promise */
                   1272:   NULL, /* http_end_push_promise */
                   1273:   NULL, /* http_cancel_push */
                   1274:   cb_h3_send_stop_sending,
                   1275:   NULL, /* push_stream */
                   1276:   NULL, /* end_stream */
                   1277: };
                   1278: 
                   1279: static int init_ngh3_conn(struct quicsocket *qs)
                   1280: {
                   1281:   CURLcode result;
                   1282:   int rc;
                   1283:   int64_t ctrl_stream_id, qpack_enc_stream_id, qpack_dec_stream_id;
                   1284: 
                   1285:   if(ngtcp2_conn_get_max_local_streams_uni(qs->qconn) < 3) {
                   1286:     failf(qs->conn->data, "too few available QUIC streams");
                   1287:     return CURLE_QUIC_CONNECT_ERROR;
                   1288:   }
                   1289: 
                   1290:   nghttp3_conn_settings_default(&qs->h3settings);
                   1291: 
                   1292:   rc = nghttp3_conn_client_new(&qs->h3conn,
                   1293:                                &ngh3_callbacks,
                   1294:                                &qs->h3settings,
                   1295:                                nghttp3_mem_default(),
                   1296:                                qs);
                   1297:   if(rc) {
                   1298:     result = CURLE_OUT_OF_MEMORY;
                   1299:     goto fail;
                   1300:   }
                   1301: 
                   1302:   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &ctrl_stream_id, NULL);
                   1303:   if(rc) {
                   1304:     result = CURLE_QUIC_CONNECT_ERROR;
                   1305:     goto fail;
                   1306:   }
                   1307: 
                   1308:   rc = nghttp3_conn_bind_control_stream(qs->h3conn, ctrl_stream_id);
                   1309:   if(rc) {
                   1310:     result = CURLE_QUIC_CONNECT_ERROR;
                   1311:     goto fail;
                   1312:   }
                   1313: 
                   1314:   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_enc_stream_id, NULL);
                   1315:   if(rc) {
                   1316:     result = CURLE_QUIC_CONNECT_ERROR;
                   1317:     goto fail;
                   1318:   }
                   1319: 
                   1320:   rc = ngtcp2_conn_open_uni_stream(qs->qconn, &qpack_dec_stream_id, NULL);
                   1321:   if(rc) {
                   1322:     result = CURLE_QUIC_CONNECT_ERROR;
                   1323:     goto fail;
                   1324:   }
                   1325: 
                   1326:   rc = nghttp3_conn_bind_qpack_streams(qs->h3conn, qpack_enc_stream_id,
                   1327:                                        qpack_dec_stream_id);
                   1328:   if(rc) {
                   1329:     result = CURLE_QUIC_CONNECT_ERROR;
                   1330:     goto fail;
                   1331:   }
                   1332: 
                   1333:   return CURLE_OK;
                   1334:   fail:
                   1335: 
                   1336:   return result;
                   1337: }
                   1338: 
                   1339: static Curl_recv ngh3_stream_recv;
                   1340: static Curl_send ngh3_stream_send;
                   1341: 
                   1342: static size_t drain_overflow_buffer(struct HTTP *stream)
                   1343: {
                   1344:   size_t ncopy = CURLMIN(stream->overflow_buflen, stream->len);
                   1345:   if(ncopy > 0) {
                   1346:     memcpy(stream->mem, stream->overflow_buf, ncopy);
                   1347:     stream->len -= ncopy;
                   1348:     stream->mem += ncopy;
                   1349:     stream->memlen += ncopy;
                   1350:     stream->overflow_buflen -= ncopy;
                   1351:     memmove(stream->overflow_buf, stream->overflow_buf + ncopy,
                   1352:             stream->overflow_buflen);
                   1353:   }
                   1354:   return ncopy;
                   1355: }
                   1356: 
                   1357: /* incoming data frames on the h3 stream */
                   1358: static ssize_t ngh3_stream_recv(struct connectdata *conn,
                   1359:                                 int sockindex,
                   1360:                                 char *buf,
                   1361:                                 size_t buffersize,
                   1362:                                 CURLcode *curlcode)
                   1363: {
                   1364:   curl_socket_t sockfd = conn->sock[sockindex];
                   1365:   struct HTTP *stream = conn->data->req.protop;
                   1366:   struct quicsocket *qs = conn->quic;
                   1367: 
                   1368:   if(!stream->memlen) {
                   1369:     /* remember where to store incoming data for this stream and how big the
                   1370:        buffer is */
                   1371:     stream->mem = buf;
                   1372:     stream->len = buffersize;
                   1373:   }
                   1374:   /* else, there's data in the buffer already */
                   1375: 
                   1376:   /* if there's data in the overflow buffer from a previous call, copy as much
                   1377:      as possible to the receive buffer before receiving more */
                   1378:   drain_overflow_buffer(stream);
                   1379: 
                   1380:   if(ng_process_ingress(conn, sockfd, qs)) {
                   1381:     *curlcode = CURLE_RECV_ERROR;
                   1382:     return -1;
                   1383:   }
                   1384:   if(ng_flush_egress(conn, sockfd, qs)) {
                   1385:     *curlcode = CURLE_SEND_ERROR;
                   1386:     return -1;
                   1387:   }
                   1388: 
                   1389:   if(stream->memlen) {
                   1390:     ssize_t memlen = stream->memlen;
                   1391:     /* data arrived */
                   1392:     *curlcode = CURLE_OK;
                   1393:     /* reset to allow more data to come */
                   1394:     stream->memlen = 0;
                   1395:     stream->mem = buf;
                   1396:     stream->len = buffersize;
                   1397:     /* extend the stream window with the data we're consuming and send out
                   1398:        any additional packets to tell the server that we can receive more */
                   1399:     extend_stream_window(qs->qconn, stream);
                   1400:     if(ng_flush_egress(conn, sockfd, qs)) {
                   1401:       *curlcode = CURLE_SEND_ERROR;
                   1402:       return -1;
                   1403:     }
                   1404:     return memlen;
                   1405:   }
                   1406: 
                   1407:   if(stream->closed) {
                   1408:     *curlcode = CURLE_OK;
                   1409:     return 0;
                   1410:   }
                   1411: 
                   1412:   infof(conn->data, "ngh3_stream_recv returns 0 bytes and EAGAIN\n");
                   1413:   *curlcode = CURLE_AGAIN;
                   1414:   return -1;
                   1415: }
                   1416: 
                   1417: /* this amount of data has now been acked on this stream */
                   1418: static int cb_h3_acked_stream_data(nghttp3_conn *conn, int64_t stream_id,
                   1419:                                    size_t datalen, void *user_data,
                   1420:                                    void *stream_user_data)
                   1421: {
                   1422:   struct Curl_easy *data = stream_user_data;
                   1423:   struct HTTP *stream = data->req.protop;
                   1424:   (void)conn;
                   1425:   (void)stream_id;
                   1426:   (void)user_data;
                   1427: 
                   1428:   if(!data->set.postfields) {
                   1429:     stream->h3out->used -= datalen;
                   1430:     H3BUGF(infof(data,
                   1431:                  "cb_h3_acked_stream_data, %zd bytes, %zd left unacked\n",
                   1432:                  datalen, stream->h3out->used));
                   1433:     DEBUGASSERT(stream->h3out->used < H3_SEND_SIZE);
                   1434:   }
                   1435:   return 0;
                   1436: }
                   1437: 
                   1438: static ssize_t cb_h3_readfunction(nghttp3_conn *conn, int64_t stream_id,
                   1439:                                   nghttp3_vec *vec, size_t veccnt,
                   1440:                                   uint32_t *pflags, void *user_data,
                   1441:                                   void *stream_user_data)
                   1442: {
                   1443:   struct Curl_easy *data = stream_user_data;
                   1444:   size_t nread;
                   1445:   struct HTTP *stream = data->req.protop;
                   1446:   (void)conn;
                   1447:   (void)stream_id;
                   1448:   (void)user_data;
                   1449:   (void)veccnt;
                   1450: 
                   1451:   if(data->set.postfields) {
                   1452:     vec[0].base = data->set.postfields;
                   1453:     vec[0].len = data->state.infilesize;
                   1454:     *pflags = NGHTTP3_DATA_FLAG_EOF;
                   1455:     return 1;
                   1456:   }
                   1457: 
                   1458:   nread = CURLMIN(stream->upload_len, H3_SEND_SIZE - stream->h3out->used);
                   1459:   if(nread > 0) {
                   1460:     /* nghttp3 wants us to hold on to the data until it tells us it is okay to
                   1461:        delete it. Append the data at the end of the h3out buffer. Since we can
                   1462:        only return consecutive data, copy the amount that fits and the next
                   1463:        part comes in next invoke. */
                   1464:     struct h3out *out = stream->h3out;
                   1465:     if(nread + out->windex > H3_SEND_SIZE)
                   1466:       nread = H3_SEND_SIZE - out->windex;
                   1467: 
                   1468:     memcpy(&out->buf[out->windex], stream->upload_mem, nread);
                   1469:     out->windex += nread;
                   1470:     out->used += nread;
                   1471: 
                   1472:     /* that's the chunk we return to nghttp3 */
                   1473:     vec[0].base = &out->buf[out->windex];
                   1474:     vec[0].len = nread;
                   1475: 
                   1476:     if(out->windex == H3_SEND_SIZE)
                   1477:       out->windex = 0; /* wrap */
                   1478:     stream->upload_mem += nread;
                   1479:     stream->upload_len -= nread;
                   1480:     if(data->state.infilesize != -1) {
                   1481:       stream->upload_left -= nread;
                   1482:       if(!stream->upload_left)
                   1483:         *pflags = NGHTTP3_DATA_FLAG_EOF;
                   1484:     }
                   1485:     H3BUGF(infof(data, "cb_h3_readfunction %zd bytes%s (at %zd unacked)\n",
                   1486:                  nread, *pflags == NGHTTP3_DATA_FLAG_EOF?" EOF":"",
                   1487:                  out->used));
                   1488:   }
                   1489:   if(stream->upload_done && !stream->upload_len &&
                   1490:      (stream->upload_left <= 0)) {
                   1491:     H3BUGF(infof(data, "!!!!!!!!! cb_h3_readfunction sets EOF\n"));
                   1492:     *pflags = NGHTTP3_DATA_FLAG_EOF;
                   1493:     return 0;
                   1494:   }
                   1495:   else if(!nread) {
                   1496:     return NGHTTP3_ERR_WOULDBLOCK;
                   1497:   }
                   1498:   return 1;
                   1499: }
                   1500: 
                   1501: /* Index where :authority header field will appear in request header
                   1502:    field list. */
                   1503: #define AUTHORITY_DST_IDX 3
                   1504: 
                   1505: static CURLcode http_request(struct connectdata *conn, const void *mem,
                   1506:                              size_t len)
                   1507: {
                   1508:   struct HTTP *stream = conn->data->req.protop;
                   1509:   size_t nheader;
                   1510:   size_t i;
                   1511:   size_t authority_idx;
                   1512:   char *hdbuf = (char *)mem;
                   1513:   char *end, *line_end;
                   1514:   struct quicsocket *qs = conn->quic;
                   1515:   CURLcode result = CURLE_OK;
                   1516:   struct Curl_easy *data = conn->data;
                   1517:   nghttp3_nv *nva = NULL;
                   1518:   int64_t stream3_id;
                   1519:   int rc;
                   1520:   struct h3out *h3out = NULL;
                   1521: 
                   1522:   rc = ngtcp2_conn_open_bidi_stream(qs->qconn, &stream3_id, NULL);
                   1523:   if(rc) {
                   1524:     failf(conn->data, "can get bidi streams");
                   1525:     result = CURLE_SEND_ERROR;
                   1526:     goto fail;
                   1527:   }
                   1528: 
                   1529:   stream->stream3_id = stream3_id;
                   1530:   stream->h3req = TRUE; /* senf off! */
                   1531: 
                   1532:   /* Calculate number of headers contained in [mem, mem + len). Assumes a
                   1533:      correctly generated HTTP header field block. */
                   1534:   nheader = 0;
                   1535:   for(i = 1; i < len; ++i) {
                   1536:     if(hdbuf[i] == '\n' && hdbuf[i - 1] == '\r') {
                   1537:       ++nheader;
                   1538:       ++i;
                   1539:     }
                   1540:   }
                   1541:   if(nheader < 2)
                   1542:     goto fail;
                   1543: 
                   1544:   /* We counted additional 2 \r\n in the first and last line. We need 3
                   1545:      new headers: :method, :path and :scheme. Therefore we need one
                   1546:      more space. */
                   1547:   nheader += 1;
                   1548:   nva = malloc(sizeof(nghttp3_nv) * nheader);
                   1549:   if(!nva) {
                   1550:     result = CURLE_OUT_OF_MEMORY;
                   1551:     goto fail;
                   1552:   }
                   1553: 
                   1554:   /* Extract :method, :path from request line
                   1555:      We do line endings with CRLF so checking for CR is enough */
                   1556:   line_end = memchr(hdbuf, '\r', len);
                   1557:   if(!line_end) {
                   1558:     result = CURLE_BAD_FUNCTION_ARGUMENT; /* internal error */
                   1559:     goto fail;
                   1560:   }
                   1561: 
                   1562:   /* Method does not contain spaces */
                   1563:   end = memchr(hdbuf, ' ', line_end - hdbuf);
                   1564:   if(!end || end == hdbuf)
                   1565:     goto fail;
                   1566:   nva[0].name = (unsigned char *)":method";
                   1567:   nva[0].namelen = strlen((char *)nva[0].name);
                   1568:   nva[0].value = (unsigned char *)hdbuf;
                   1569:   nva[0].valuelen = (size_t)(end - hdbuf);
                   1570:   nva[0].flags = NGHTTP3_NV_FLAG_NONE;
                   1571: 
                   1572:   hdbuf = end + 1;
                   1573: 
                   1574:   /* Path may contain spaces so scan backwards */
                   1575:   end = NULL;
                   1576:   for(i = (size_t)(line_end - hdbuf); i; --i) {
                   1577:     if(hdbuf[i - 1] == ' ') {
                   1578:       end = &hdbuf[i - 1];
                   1579:       break;
                   1580:     }
                   1581:   }
                   1582:   if(!end || end == hdbuf)
                   1583:     goto fail;
                   1584:   nva[1].name = (unsigned char *)":path";
                   1585:   nva[1].namelen = strlen((char *)nva[1].name);
                   1586:   nva[1].value = (unsigned char *)hdbuf;
                   1587:   nva[1].valuelen = (size_t)(end - hdbuf);
                   1588:   nva[1].flags = NGHTTP3_NV_FLAG_NONE;
                   1589: 
                   1590:   nva[2].name = (unsigned char *)":scheme";
                   1591:   nva[2].namelen = strlen((char *)nva[2].name);
                   1592:   if(conn->handler->flags & PROTOPT_SSL)
                   1593:     nva[2].value = (unsigned char *)"https";
                   1594:   else
                   1595:     nva[2].value = (unsigned char *)"http";
                   1596:   nva[2].valuelen = strlen((char *)nva[2].value);
                   1597:   nva[2].flags = NGHTTP3_NV_FLAG_NONE;
                   1598: 
                   1599: 
                   1600:   authority_idx = 0;
                   1601:   i = 3;
                   1602:   while(i < nheader) {
                   1603:     size_t hlen;
                   1604: 
                   1605:     hdbuf = line_end + 2;
                   1606: 
                   1607:     /* check for next CR, but only within the piece of data left in the given
                   1608:        buffer */
                   1609:     line_end = memchr(hdbuf, '\r', len - (hdbuf - (char *)mem));
                   1610:     if(!line_end || (line_end == hdbuf))
                   1611:       goto fail;
                   1612: 
                   1613:     /* header continuation lines are not supported */
                   1614:     if(*hdbuf == ' ' || *hdbuf == '\t')
                   1615:       goto fail;
                   1616: 
                   1617:     for(end = hdbuf; end < line_end && *end != ':'; ++end)
                   1618:       ;
                   1619:     if(end == hdbuf || end == line_end)
                   1620:       goto fail;
                   1621:     hlen = end - hdbuf;
                   1622: 
                   1623:     if(hlen == 4 && strncasecompare("host", hdbuf, 4)) {
                   1624:       authority_idx = i;
                   1625:       nva[i].name = (unsigned char *)":authority";
                   1626:       nva[i].namelen = strlen((char *)nva[i].name);
                   1627:     }
                   1628:     else {
                   1629:       nva[i].namelen = (size_t)(end - hdbuf);
                   1630:       /* Lower case the header name for HTTP/3 */
                   1631:       Curl_strntolower((char *)hdbuf, hdbuf, nva[i].namelen);
                   1632:       nva[i].name = (unsigned char *)hdbuf;
                   1633:     }
                   1634:     nva[i].flags = NGHTTP3_NV_FLAG_NONE;
                   1635:     hdbuf = end + 1;
                   1636:     while(*hdbuf == ' ' || *hdbuf == '\t')
                   1637:       ++hdbuf;
                   1638:     end = line_end;
                   1639: 
                   1640: #if 0 /* This should probably go in more or less like this */
                   1641:     switch(inspect_header((const char *)nva[i].name, nva[i].namelen, hdbuf,
                   1642:                           end - hdbuf)) {
                   1643:     case HEADERINST_IGNORE:
                   1644:       /* skip header fields prohibited by HTTP/2 specification. */
                   1645:       --nheader;
                   1646:       continue;
                   1647:     case HEADERINST_TE_TRAILERS:
                   1648:       nva[i].value = (uint8_t*)"trailers";
                   1649:       nva[i].value_len = sizeof("trailers") - 1;
                   1650:       break;
                   1651:     default:
                   1652:       nva[i].value = (unsigned char *)hdbuf;
                   1653:       nva[i].value_len = (size_t)(end - hdbuf);
                   1654:     }
                   1655: #endif
                   1656:     nva[i].value = (unsigned char *)hdbuf;
                   1657:     nva[i].valuelen = (size_t)(end - hdbuf);
                   1658:     nva[i].flags = NGHTTP3_NV_FLAG_NONE;
                   1659: 
                   1660:     ++i;
                   1661:   }
                   1662: 
                   1663:   /* :authority must come before non-pseudo header fields */
                   1664:   if(authority_idx != 0 && authority_idx != AUTHORITY_DST_IDX) {
                   1665:     nghttp3_nv authority = nva[authority_idx];
                   1666:     for(i = authority_idx; i > AUTHORITY_DST_IDX; --i) {
                   1667:       nva[i] = nva[i - 1];
                   1668:     }
                   1669:     nva[i] = authority;
                   1670:   }
                   1671: 
                   1672:   /* Warn stream may be rejected if cumulative length of headers is too
                   1673:      large. */
                   1674: #define MAX_ACC 60000  /* <64KB to account for some overhead */
                   1675:   {
                   1676:     size_t acc = 0;
                   1677:     for(i = 0; i < nheader; ++i)
                   1678:       acc += nva[i].namelen + nva[i].valuelen;
                   1679: 
                   1680:     if(acc > MAX_ACC) {
                   1681:       infof(data, "http_request: Warning: The cumulative length of all "
                   1682:             "headers exceeds %zu bytes and that could cause the "
                   1683:             "stream to be rejected.\n", MAX_ACC);
                   1684:     }
                   1685:   }
                   1686: 
                   1687:   switch(data->set.httpreq) {
                   1688:   case HTTPREQ_POST:
                   1689:   case HTTPREQ_POST_FORM:
                   1690:   case HTTPREQ_POST_MIME:
                   1691:   case HTTPREQ_PUT: {
                   1692:     nghttp3_data_reader data_reader;
                   1693:     if(data->state.infilesize != -1)
                   1694:       stream->upload_left = data->state.infilesize;
                   1695:     else
                   1696:       /* data sending without specifying the data amount up front */
                   1697:       stream->upload_left = -1; /* unknown, but not zero */
                   1698: 
                   1699:     data_reader.read_data = cb_h3_readfunction;
                   1700: 
                   1701:     h3out = calloc(sizeof(struct h3out), 1);
                   1702:     if(!h3out) {
                   1703:       result = CURLE_OUT_OF_MEMORY;
                   1704:       goto fail;
                   1705:     }
                   1706:     stream->h3out = h3out;
                   1707: 
                   1708:     rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                   1709:                                      nva, nheader, &data_reader,
                   1710:                                      conn->data);
                   1711:     if(rc) {
                   1712:       result = CURLE_SEND_ERROR;
                   1713:       goto fail;
                   1714:     }
                   1715:     break;
                   1716:   }
                   1717:   default:
                   1718:     stream->upload_left = 0; /* nothing left to send */
                   1719:     rc = nghttp3_conn_submit_request(qs->h3conn, stream->stream3_id,
                   1720:                                      nva, nheader,
                   1721:                                      NULL, /* no body! */
                   1722:                                      conn->data);
                   1723:     if(rc) {
                   1724:       result = CURLE_SEND_ERROR;
                   1725:       goto fail;
                   1726:     }
                   1727:     break;
                   1728:   }
                   1729: 
                   1730:   Curl_safefree(nva);
                   1731: 
                   1732:   infof(data, "Using HTTP/3 Stream ID: %x (easy handle %p)\n",
                   1733:         stream3_id, (void *)data);
                   1734: 
                   1735:   return CURLE_OK;
                   1736: 
                   1737: fail:
                   1738:   free(nva);
                   1739:   return result;
                   1740: }
                   1741: static ssize_t ngh3_stream_send(struct connectdata *conn,
                   1742:                                 int sockindex,
                   1743:                                 const void *mem,
                   1744:                                 size_t len,
                   1745:                                 CURLcode *curlcode)
                   1746: {
                   1747:   ssize_t sent;
                   1748:   struct quicsocket *qs = conn->quic;
                   1749:   curl_socket_t sockfd = conn->sock[sockindex];
                   1750:   struct HTTP *stream = conn->data->req.protop;
                   1751: 
                   1752:   if(!stream->h3req) {
                   1753:     CURLcode result = http_request(conn, mem, len);
                   1754:     if(result) {
                   1755:       *curlcode = CURLE_SEND_ERROR;
                   1756:       return -1;
                   1757:     }
                   1758:     sent = len;
                   1759:   }
                   1760:   else {
                   1761:     H3BUGF(infof(conn->data, "ngh3_stream_send() wants to send %zd bytes\n",
                   1762:                  len));
                   1763:     if(!stream->upload_len) {
                   1764:       stream->upload_mem = mem;
                   1765:       stream->upload_len = len;
                   1766:       (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
                   1767:       sent = len;
                   1768:     }
                   1769:     else {
                   1770:       *curlcode = CURLE_AGAIN;
                   1771:       return -1;
                   1772:     }
                   1773:   }
                   1774: 
                   1775:   if(ng_flush_egress(conn, sockfd, qs)) {
                   1776:     *curlcode = CURLE_SEND_ERROR;
                   1777:     return -1;
                   1778:   }
                   1779: 
                   1780:   *curlcode = CURLE_OK;
                   1781:   return sent;
                   1782: }
                   1783: 
                   1784: static void ng_has_connected(struct connectdata *conn, int tempindex)
                   1785: {
                   1786:   conn->recv[FIRSTSOCKET] = ngh3_stream_recv;
                   1787:   conn->send[FIRSTSOCKET] = ngh3_stream_send;
                   1788:   conn->handler = &Curl_handler_http3;
                   1789:   conn->bits.multiplex = TRUE; /* at least potentially multiplexed */
                   1790:   conn->httpversion = 30;
                   1791:   conn->bundle->multiuse = BUNDLE_MULTIPLEX;
                   1792:   conn->quic = &conn->hequic[tempindex];
                   1793:   DEBUGF(infof(conn->data, "ngtcp2 established connection!\n"));
                   1794: }
                   1795: 
                   1796: /*
                   1797:  * There can be multiple connection attempts going on in parallel.
                   1798:  */
                   1799: CURLcode Curl_quic_is_connected(struct connectdata *conn,
                   1800:                                 int sockindex,
                   1801:                                 bool *done)
                   1802: {
                   1803:   CURLcode result;
                   1804:   struct quicsocket *qs = &conn->hequic[sockindex];
                   1805:   curl_socket_t sockfd = conn->tempsock[sockindex];
                   1806: 
                   1807:   result = ng_process_ingress(conn, sockfd, qs);
                   1808:   if(result)
                   1809:     return result;
                   1810: 
                   1811:   result = ng_flush_egress(conn, sockfd, qs);
                   1812:   if(result)
                   1813:     return result;
                   1814: 
                   1815:   if(ngtcp2_conn_get_handshake_completed(qs->qconn)) {
                   1816:     *done = TRUE;
                   1817:     ng_has_connected(conn, sockindex);
                   1818:   }
                   1819: 
                   1820:   return result;
                   1821: }
                   1822: 
                   1823: static CURLcode ng_process_ingress(struct connectdata *conn, int sockfd,
                   1824:                                    struct quicsocket *qs)
                   1825: {
                   1826:   ssize_t recvd;
                   1827:   int rv;
                   1828:   uint8_t buf[65536];
                   1829:   size_t bufsize = sizeof(buf);
                   1830:   struct sockaddr_storage remote_addr;
                   1831:   socklen_t remote_addrlen;
                   1832:   ngtcp2_path path;
                   1833:   ngtcp2_tstamp ts = timestamp();
                   1834: 
                   1835:   for(;;) {
                   1836:     remote_addrlen = sizeof(remote_addr);
                   1837:     while((recvd = recvfrom(sockfd, buf, bufsize, 0,
                   1838:                             (struct sockaddr *)&remote_addr,
                   1839:                             &remote_addrlen)) == -1 &&
                   1840:           SOCKERRNO == EINTR)
                   1841:       ;
                   1842:     if(recvd == -1) {
                   1843:       if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK)
                   1844:         break;
                   1845: 
                   1846:       failf(conn->data, "ngtcp2: recvfrom() unexpectedly returned %d", recvd);
                   1847:       return CURLE_RECV_ERROR;
                   1848:     }
                   1849: 
                   1850:     ngtcp2_addr_init(&path.local, (uint8_t *)&qs->local_addr,
                   1851:                      qs->local_addrlen, NULL);
                   1852:     ngtcp2_addr_init(&path.remote, (uint8_t *)&remote_addr, remote_addrlen,
                   1853:                      NULL);
                   1854: 
                   1855:     rv = ngtcp2_conn_read_pkt(qs->qconn, &path, buf, recvd, ts);
                   1856:     if(rv != 0) {
                   1857:       /* TODO Send CONNECTION_CLOSE if possible */
                   1858:       return CURLE_RECV_ERROR;
                   1859:     }
                   1860:   }
                   1861: 
                   1862:   return CURLE_OK;
                   1863: }
                   1864: 
                   1865: static CURLcode ng_flush_egress(struct connectdata *conn, int sockfd,
                   1866:                                 struct quicsocket *qs)
                   1867: {
                   1868:   int rv;
                   1869:   ssize_t sent;
                   1870:   ssize_t outlen;
                   1871:   uint8_t out[NGTCP2_MAX_PKTLEN_IPV4];
                   1872:   size_t pktlen;
                   1873:   ngtcp2_path_storage ps;
                   1874:   ngtcp2_tstamp ts = timestamp();
                   1875:   struct sockaddr_storage remote_addr;
                   1876:   ngtcp2_tstamp expiry;
                   1877:   ngtcp2_duration timeout;
                   1878:   int64_t stream_id;
                   1879:   ssize_t veccnt;
                   1880:   int fin;
                   1881:   nghttp3_vec vec[16];
                   1882:   ssize_t ndatalen;
                   1883: 
                   1884:   switch(qs->local_addr.ss_family) {
                   1885:   case AF_INET:
                   1886:     pktlen = NGTCP2_MAX_PKTLEN_IPV4;
                   1887:     break;
                   1888: #ifdef ENABLE_IPV6
                   1889:   case AF_INET6:
                   1890:     pktlen = NGTCP2_MAX_PKTLEN_IPV6;
                   1891:     break;
                   1892: #endif
                   1893:   default:
                   1894:     assert(0);
                   1895:   }
                   1896: 
                   1897:   rv = ngtcp2_conn_handle_expiry(qs->qconn, ts);
                   1898:   if(rv != 0) {
                   1899:     failf(conn->data, "ngtcp2_conn_handle_expiry returned error: %s\n",
                   1900:           ngtcp2_strerror(rv));
                   1901:     return CURLE_SEND_ERROR;
                   1902:   }
                   1903: 
                   1904:   ngtcp2_path_storage_zero(&ps);
                   1905: 
                   1906:   for(;;) {
                   1907:     outlen = -1;
                   1908:     if(qs->h3conn && ngtcp2_conn_get_max_data_left(qs->qconn)) {
                   1909:       veccnt = nghttp3_conn_writev_stream(qs->h3conn, &stream_id, &fin, vec,
                   1910:                                           sizeof(vec) / sizeof(vec[0]));
                   1911:       if(veccnt < 0) {
                   1912:         failf(conn->data, "nghttp3_conn_writev_stream returned error: %s\n",
                   1913:               nghttp3_strerror((int)veccnt));
                   1914:         return CURLE_SEND_ERROR;
                   1915:       }
                   1916:       else if(veccnt > 0) {
                   1917:         outlen =
                   1918:           ngtcp2_conn_writev_stream(qs->qconn, &ps.path,
                   1919:                                     out, pktlen, &ndatalen,
                   1920:                                     NGTCP2_WRITE_STREAM_FLAG_MORE,
                   1921:                                     stream_id, fin,
                   1922:                                     (const ngtcp2_vec *)vec, veccnt, ts);
                   1923:         if(outlen == 0) {
                   1924:           break;
                   1925:         }
                   1926:         if(outlen < 0) {
                   1927:           if(outlen == NGTCP2_ERR_STREAM_DATA_BLOCKED ||
                   1928:              outlen == NGTCP2_ERR_STREAM_SHUT_WR) {
                   1929:             rv = nghttp3_conn_block_stream(qs->h3conn, stream_id);
                   1930:             if(rv != 0) {
                   1931:               failf(conn->data,
                   1932:                     "nghttp3_conn_block_stream returned error: %s\n",
                   1933:                     nghttp3_strerror(rv));
                   1934:               return CURLE_SEND_ERROR;
                   1935:             }
                   1936:             continue;
                   1937:           }
                   1938:           else if(outlen == NGTCP2_ERR_WRITE_STREAM_MORE) {
                   1939:             assert(ndatalen > 0);
                   1940:             rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id,
                   1941:                                                ndatalen);
                   1942:             if(rv != 0) {
                   1943:               failf(conn->data,
                   1944:                     "nghttp3_conn_add_write_offset returned error: %s\n",
                   1945:                     nghttp3_strerror(rv));
                   1946:               return CURLE_SEND_ERROR;
                   1947:             }
                   1948:             continue;
                   1949:           }
                   1950:           else {
                   1951:             failf(conn->data, "ngtcp2_conn_writev_stream returned error: %s\n",
                   1952:                   ngtcp2_strerror((int)outlen));
                   1953:             return CURLE_SEND_ERROR;
                   1954:           }
                   1955:         }
                   1956:         else if(ndatalen >= 0) {
                   1957:           rv = nghttp3_conn_add_write_offset(qs->h3conn, stream_id, ndatalen);
                   1958:           if(rv != 0) {
                   1959:             failf(conn->data,
                   1960:                   "nghttp3_conn_add_write_offset returned error: %s\n",
                   1961:                   nghttp3_strerror(rv));
                   1962:             return CURLE_SEND_ERROR;
                   1963:           }
                   1964:         }
                   1965:       }
                   1966:     }
                   1967:     if(outlen < 0) {
                   1968:       outlen = ngtcp2_conn_write_pkt(qs->qconn, &ps.path, out, pktlen, ts);
                   1969:       if(outlen < 0) {
                   1970:         failf(conn->data, "ngtcp2_conn_write_pkt returned error: %s\n",
                   1971:               ngtcp2_strerror((int)outlen));
                   1972:         return CURLE_SEND_ERROR;
                   1973:       }
                   1974:       if(outlen == 0)
                   1975:         break;
                   1976:     }
                   1977: 
                   1978:     memcpy(&remote_addr, ps.path.remote.addr, ps.path.remote.addrlen);
                   1979:     while((sent = send(sockfd, out, outlen, 0)) == -1 &&
                   1980:           SOCKERRNO == EINTR)
                   1981:       ;
                   1982: 
                   1983:     if(sent == -1) {
                   1984:       if(SOCKERRNO == EAGAIN || SOCKERRNO == EWOULDBLOCK) {
                   1985:         /* TODO Cache packet */
                   1986:         break;
                   1987:       }
                   1988:       else {
                   1989:         failf(conn->data, "send() returned %zd (errno %d)\n", sent,
                   1990:               SOCKERRNO);
                   1991:         return CURLE_SEND_ERROR;
                   1992:       }
                   1993:     }
                   1994:   }
                   1995: 
                   1996:   expiry = ngtcp2_conn_get_expiry(qs->qconn);
                   1997:   if(expiry != UINT64_MAX) {
                   1998:     if(expiry <= ts) {
                   1999:       timeout = NGTCP2_MILLISECONDS;
                   2000:     }
                   2001:     else {
                   2002:       timeout = expiry - ts;
                   2003:     }
                   2004:     Curl_expire(conn->data, timeout / NGTCP2_MILLISECONDS, EXPIRE_QUIC);
                   2005:   }
                   2006: 
                   2007:   return CURLE_OK;
                   2008: }
                   2009: 
                   2010: /*
                   2011:  * Called from transfer.c:done_sending when we stop HTTP/3 uploading.
                   2012:  */
                   2013: CURLcode Curl_quic_done_sending(struct connectdata *conn)
                   2014: {
                   2015:   if(conn->handler == &Curl_handler_http3) {
                   2016:     /* only for HTTP/3 transfers */
                   2017:     struct HTTP *stream = conn->data->req.protop;
                   2018:     struct quicsocket *qs = conn->quic;
                   2019:     stream->upload_done = TRUE;
                   2020:     (void)nghttp3_conn_resume_stream(qs->h3conn, stream->stream3_id);
                   2021:   }
                   2022: 
                   2023:   return CURLE_OK;
                   2024: }
                   2025: 
                   2026: /*
                   2027:  * Called from http.c:Curl_http_done when a request completes.
                   2028:  */
                   2029: void Curl_quic_done(struct Curl_easy *data, bool premature)
                   2030: {
                   2031:   (void)premature;
                   2032:   if(data->conn->handler == &Curl_handler_http3) {
                   2033:     /* only for HTTP/3 transfers */
                   2034:     struct HTTP *stream = data->req.protop;
                   2035:     Curl_safefree(stream->overflow_buf);
                   2036:   }
                   2037: }
                   2038: 
                   2039: /*
                   2040:  * Called from transfer.c:data_pending to know if we should keep looping
                   2041:  * to receive more data from the connection.
                   2042:  */
                   2043: bool Curl_quic_data_pending(const struct Curl_easy *data)
                   2044: {
                   2045:   /* We may have received more data than we're able to hold in the receive
                   2046:      buffer and allocated an overflow buffer. Since it's possible that
                   2047:      there's no more data coming on the socket, we need to keep reading
                   2048:      until the overflow buffer is empty. */
                   2049:   const struct HTTP *stream = data->req.protop;
                   2050:   return stream->overflow_buflen > 0;
                   2051: }
                   2052: 
                   2053: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>