diff --git a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h index b102eae8f9ec77..801c6cb2681386 100644 --- a/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h +++ b/deps/ngtcp2/ngtcp2/lib/includes/ngtcp2/version.h @@ -36,7 +36,7 @@ * * Version number of the ngtcp2 library release. */ -#define NGTCP2_VERSION "1.2.0" +#define NGTCP2_VERSION "1.3.0" /** * @macro @@ -46,6 +46,6 @@ * number, 8 bits for minor and 8 bits for patch. Version 1.2.3 * becomes 0x010203. */ -#define NGTCP2_VERSION_NUM 0x010200 +#define NGTCP2_VERSION_NUM 0x010300 #endif /* VERSION_H */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h index 107d413382da20..85b5f4ddf0464a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_buf.h @@ -36,7 +36,7 @@ typedef struct ngtcp2_buf { uint8_t *begin; /* end points to the one beyond of the last byte of the buffer */ uint8_t *end; - /* pos pointers to the start of data. Typically, this points to the + /* pos points to the start of data. Typically, this points to the point that next data should be read. Initially, it points to |begin|. */ uint8_t *pos; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c index ef311ff93c0feb..9ad37fbdb6395a 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_cc.c @@ -27,10 +27,6 @@ #include #include -#if defined(_MSC_VER) -# include -#endif - #include "ngtcp2_log.h" #include "ngtcp2_macro.h" #include "ngtcp2_mem.h" @@ -235,39 +231,27 @@ void ngtcp2_cc_cubic_init(ngtcp2_cc_cubic *cubic, ngtcp2_log *log) { } uint64_t ngtcp2_cbrt(uint64_t n) { - int d; - uint64_t a; - - if (n == 0) { - return 0; - } - -#if defined(_MSC_VER) - { - unsigned long index; -# if defined(_WIN64) - if (_BitScanReverse64(&index, n)) { - d = 61 - index; - } else { - ngtcp2_unreachable(); - } -# else /* !defined(_WIN64) */ - if (_BitScanReverse(&index, (unsigned int)(n >> 32))) { - d = 31 - index; - } else { - d = 32 + 31 - _BitScanReverse(&index, (unsigned int)n); + size_t s; + uint64_t y = 0; + uint64_t b; + + for (s = 63; s > 0; s -= 3) { + y <<= 1; + b = 3 * y * (y + 1) + 1; + if ((n >> s) >= b) { + n -= b << s; + y++; } -# endif /* !defined(_WIN64) */ } -#else /* !defined(_MSC_VER) */ - d = __builtin_clzll(n); -#endif /* !defined(_MSC_VER) */ - a = 1ULL << ((64 - d) / 3 + 1); - for (; a * a * a > n;) { - a = (2 * a + n / a / a) / 3; + y <<= 1; + b = 3 * y * (y + 1) + 1; + if (n >= b) { + n -= b; + y++; } - return a; + + return y; } /* HyStart++ constants */ diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c index a4873eb20c4b86..c8caf47ea76232 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_conn.c @@ -3441,12 +3441,22 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, } switch ((*pfrc)->fr.type) { + case NGTCP2_FRAME_RESET_STREAM: + strm = + ngtcp2_conn_find_stream(conn, (*pfrc)->fr.reset_stream.stream_id); + if (strm == NULL || + !ngtcp2_strm_require_retransmit_reset_stream(strm)) { + frc = *pfrc; + *pfrc = (*pfrc)->next; + ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); + continue; + } + break; case NGTCP2_FRAME_STOP_SENDING: strm = ngtcp2_conn_find_stream(conn, (*pfrc)->fr.stop_sending.stream_id); if (strm == NULL || - ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) && - ngtcp2_strm_rx_offset(strm) == strm->rx.last_offset)) { + !ngtcp2_strm_require_retransmit_stop_sending(strm)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -3476,10 +3486,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, case NGTCP2_FRAME_MAX_STREAM_DATA: strm = ngtcp2_conn_find_stream(conn, (*pfrc)->fr.max_stream_data.stream_id); - if (strm == NULL || - (strm->flags & - (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)) || - (*pfrc)->fr.max_stream_data.max_stream_data < strm->rx.max_offset) { + if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( + strm, &(*pfrc)->fr.max_stream_data)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -3497,8 +3505,8 @@ static ngtcp2_ssize conn_write_pkt(ngtcp2_conn *conn, ngtcp2_pkt_info *pi, case NGTCP2_FRAME_STREAM_DATA_BLOCKED: strm = ngtcp2_conn_find_stream( conn, (*pfrc)->fr.stream_data_blocked.stream_id); - if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_SHUT_WR) || - (*pfrc)->fr.stream_data_blocked.offset != strm->tx.max_offset) { + if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( + strm, &(*pfrc)->fr.stream_data_blocked)) { frc = *pfrc; *pfrc = (*pfrc)->next; ngtcp2_frame_chain_objalloc_del(frc, &conn->frc_objalloc, conn->mem); @@ -7145,7 +7153,7 @@ static int conn_recv_stream(ngtcp2_conn *conn, const ngtcp2_stream *fr) { return rv; } } - } else if (fr->datacnt) { + } else if (fr->datacnt && !(strm->flags & NGTCP2_STRM_FLAG_STOP_SENDING)) { rv = ngtcp2_strm_recv_reordering(strm, fr->data[0].base, fr->data[0].len, fr->offset); if (rv != 0) { @@ -7304,27 +7312,20 @@ static int conn_recv_reset_stream(ngtcp2_conn *conn, } /* Stream is reset before we create ngtcp2_strm object. */ - conn->rx.offset += fr->final_size; - ngtcp2_conn_extend_max_offset(conn, fr->final_size); - - rv = conn_call_stream_reset(conn, fr->stream_id, fr->final_size, - fr->app_error_code, NULL); + strm = ngtcp2_objalloc_strm_get(&conn->strm_objalloc); + if (strm == NULL) { + return NGTCP2_ERR_NOMEM; + } + rv = ngtcp2_conn_init_stream(conn, strm, fr->stream_id, NULL); if (rv != 0) { + ngtcp2_objalloc_strm_release(&conn->strm_objalloc, strm); return rv; } - /* There will be no activity in this stream because we got - RESET_STREAM and don't write stream data any further. This - effectively allows another new stream for peer. */ - if (bidi) { - handle_max_remote_streams_extension(&conn->remote.bidi.unsent_max_streams, - 1); - } else { - handle_max_remote_streams_extension(&conn->remote.uni.unsent_max_streams, - 1); + rv = conn_call_stream_open(conn, strm); + if (rv != 0) { + return rv; } - - return 0; } if ((strm->flags & NGTCP2_STRM_FLAG_SHUT_RD)) { @@ -7461,15 +7462,16 @@ static int conn_recv_stop_sending(ngtcp2_conn *conn, been acknowledged. */ if (!ngtcp2_strm_is_all_tx_data_fin_acked(strm) && !(strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM)) { + strm->flags |= NGTCP2_STRM_FLAG_RESET_STREAM; + rv = conn_reset_stream(conn, strm, fr->app_error_code); if (rv != 0) { return rv; } } - strm->flags |= NGTCP2_STRM_FLAG_SHUT_WR | - NGTCP2_STRM_FLAG_STOP_SENDING_RECVED | - NGTCP2_STRM_FLAG_RESET_STREAM; + strm->flags |= + NGTCP2_STRM_FLAG_SHUT_WR | NGTCP2_STRM_FLAG_STOP_SENDING_RECVED; ngtcp2_strm_streamfrq_clear(strm); @@ -12533,14 +12535,15 @@ static int conn_shutdown_stream_read(ngtcp2_conn *conn, ngtcp2_strm *strm, /* Extend connection flow control window for the amount of data which are not passed to application. */ - if (!(strm->flags & (NGTCP2_STRM_FLAG_STOP_SENDING | - NGTCP2_STRM_FLAG_RESET_STREAM_RECVED))) { + if (!(strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM_RECVED)) { ngtcp2_conn_extend_max_offset(conn, strm->rx.last_offset - ngtcp2_strm_rx_offset(strm)); } strm->flags |= NGTCP2_STRM_FLAG_STOP_SENDING; + ngtcp2_strm_discard_reordered_data(strm); + return conn_stop_sending(conn, strm, app_error_code); } diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c index 2c00af5ea53d99..0a3ecf6a2440cb 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_crypto.c @@ -123,6 +123,25 @@ static uint8_t *write_varint_param(uint8_t *p, ngtcp2_transport_param_id id, return ngtcp2_put_uvarint(p, value); } +/* + * zero_paramlen returns the length of a single transport parameter + * which has zero length value in its parameter. + */ +static size_t zero_paramlen(ngtcp2_transport_param_id id) { + return ngtcp2_put_uvarintlen(id) + 1; +} + +/* + * write_zero_param writes parameter |id| that has zero length value. + * It returns p + the number of bytes written. + */ +static uint8_t *write_zero_param(uint8_t *p, ngtcp2_transport_param_id id) { + p = ngtcp2_put_uvarint(p, id); + *p++ = 0; + + return p; +} + /* * cid_paramlen returns the length of a single transport parameter * which has |cid| as value. @@ -235,9 +254,7 @@ ngtcp2_ssize ngtcp2_transport_params_encode_versioned( params->ack_delay_exponent); } if (params->disable_active_migration) { - len += - ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION) + - ngtcp2_put_uvarintlen(0); + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); } if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { len += varint_paramlen(NGTCP2_TRANSPORT_PARAM_MAX_ACK_DELAY, @@ -258,8 +275,7 @@ ngtcp2_ssize ngtcp2_transport_params_encode_versioned( params->max_datagram_frame_size); } if (params->grease_quic_bit) { - len += ngtcp2_put_uvarintlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT) + - ngtcp2_put_uvarintlen(0); + len += zero_paramlen(NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); } if (params->version_info_present) { version_infolen = @@ -377,8 +393,7 @@ ngtcp2_ssize ngtcp2_transport_params_encode_versioned( } if (params->disable_active_migration) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); - p = ngtcp2_put_uvarint(p, 0); + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION); } if (params->max_ack_delay != NGTCP2_DEFAULT_MAX_ACK_DELAY) { @@ -404,8 +419,7 @@ ngtcp2_ssize ngtcp2_transport_params_encode_versioned( } if (params->grease_quic_bit) { - p = ngtcp2_put_uvarint(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); - p = ngtcp2_put_uvarint(p, 0); + p = write_zero_param(p, NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT); } if (params->version_info_present) { @@ -482,6 +496,22 @@ static int decode_varint_param(uint64_t *pdest, const uint8_t **pp, return 0; } +/* + * decode_zero_param decodes zero length value from the buffer pointed + * by |*pp| of length |end - *pp|. The length is encoded in varint + * form. If it decodes zero length value successfully, it increments + * |*pp| by 1, and returns 0. Otherwise it returns -1. + */ +static int decode_zero_param(const uint8_t **pp, const uint8_t *end) { + if (*pp == end || **pp != 0) { + return -1; + } + + ++*pp; + + return 0; +} + /* * decode_cid_param decodes length prefixed ngtcp2_cid from the buffer * pointed by |*pp| of length |end - *pp|. The length is encoded in @@ -701,10 +731,7 @@ int ngtcp2_transport_params_decode_versioned(int transport_params_version, params->preferred_addr_present = 1; break; case NGTCP2_TRANSPORT_PARAM_DISABLE_ACTIVE_MIGRATION: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen != 0) { + if (decode_zero_param(&p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } params->disable_active_migration = 1; @@ -751,10 +778,7 @@ int ngtcp2_transport_params_decode_versioned(int transport_params_version, } break; case NGTCP2_TRANSPORT_PARAM_GREASE_QUIC_BIT: - if (decode_varint(&valuelen, &p, end) != 0) { - return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; - } - if (valuelen != 0) { + if (decode_zero_param(&p, end) != 0) { return NGTCP2_ERR_MALFORMED_TRANSPORT_PARAM; } params->grease_quic_bit = 1; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c index 6308261369c382..5ebdce7d0e2715 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_rtb.c @@ -237,7 +237,7 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, switch (frc->fr.type) { case NGTCP2_FRAME_STREAM: strm = ngtcp2_conn_find_stream(conn, fr->stream.stream_id); - if (strm == NULL) { + if (strm == NULL || (strm->flags & NGTCP2_STRM_FLAG_RESET_STREAM)) { continue; } @@ -339,26 +339,60 @@ static ngtcp2_ssize rtb_reclaim_frame(ngtcp2_rtb *rtb, uint8_t flags, return rv; } - break; + ++num_reclaimed; + + nfrc->next = *pfrc; + *pfrc = nfrc; + pfrc = &nfrc->next; + + continue; case NGTCP2_FRAME_DATAGRAM: case NGTCP2_FRAME_DATAGRAM_LEN: continue; - default: - rv = ngtcp2_frame_chain_objalloc_new(&nfrc, rtb->frc_objalloc); - if (rv != 0) { - return rv; + case NGTCP2_FRAME_RESET_STREAM: + strm = ngtcp2_conn_find_stream(conn, fr->reset_stream.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_reset_stream(strm)) { + continue; } - nfrc->fr = *fr; + break; + case NGTCP2_FRAME_STOP_SENDING: + strm = ngtcp2_conn_find_stream(conn, fr->stop_sending.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_stop_sending(strm)) { + continue; + } - rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem); - if (rv != 0) { - return rv; + break; + case NGTCP2_FRAME_MAX_STREAM_DATA: + strm = ngtcp2_conn_find_stream(conn, fr->max_stream_data.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_max_stream_data( + strm, &fr->max_stream_data)) { + continue; + } + + break; + case NGTCP2_FRAME_STREAM_DATA_BLOCKED: + strm = ngtcp2_conn_find_stream(conn, fr->stream_data_blocked.stream_id); + if (strm == NULL || !ngtcp2_strm_require_retransmit_stream_data_blocked( + strm, &fr->stream_data_blocked)) { + continue; } break; } + rv = ngtcp2_frame_chain_objalloc_new(&nfrc, rtb->frc_objalloc); + if (rv != 0) { + return rv; + } + + nfrc->fr = *fr; + + rv = ngtcp2_bind_frame_chains(frc, nfrc, rtb->mem); + if (rv != 0) { + return rv; + } + ++num_reclaimed; nfrc->next = *pfrc; diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c index 6bbeb8f9f81fc2..c00e86fa8c1afa 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.c @@ -158,6 +158,18 @@ void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset) { ngtcp2_rob_remove_prefix(strm->rx.rob, offset); } +void ngtcp2_strm_discard_reordered_data(ngtcp2_strm *strm) { + if (strm->rx.rob == NULL) { + return; + } + + strm->rx.cont_offset = ngtcp2_strm_rx_offset(strm); + + ngtcp2_rob_free(strm->rx.rob); + ngtcp2_mem_free(strm->mem, strm->rx.rob); + strm->rx.rob = NULL; +} + void ngtcp2_strm_shutdown(ngtcp2_strm *strm, uint32_t flags) { strm->flags |= flags & NGTCP2_STRM_FLAG_SHUT_RDWR; } @@ -696,3 +708,25 @@ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, strm->flags |= NGTCP2_STRM_FLAG_APP_ERROR_CODE_SET; strm->app_error_code = app_error_code; } + +int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm) { + return !ngtcp2_strm_is_all_tx_data_fin_acked(strm); +} + +int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm) { + return !(strm->flags & NGTCP2_STRM_FLAG_SHUT_RD) || + ngtcp2_strm_rx_offset(strm) != strm->rx.last_offset; +} + +int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, + ngtcp2_max_stream_data *fr) { + return fr->max_stream_data == strm->rx.max_offset && + !(strm->flags & + (NGTCP2_STRM_FLAG_SHUT_RD | NGTCP2_STRM_FLAG_STOP_SENDING)); +} + +int ngtcp2_strm_require_retransmit_stream_data_blocked( + ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr) { + return fr->offset == strm->tx.max_offset && + !(strm->flags & NGTCP2_STRM_FLAG_SHUT_WR); +} diff --git a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h index 223e38fc646b38..385302a5eafa9f 100644 --- a/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h +++ b/deps/ngtcp2/ngtcp2/lib/ngtcp2_strm.h @@ -36,6 +36,7 @@ #include "ngtcp2_gaptr.h" #include "ngtcp2_ksl.h" #include "ngtcp2_pq.h" +#include "ngtcp2_pkt.h" typedef struct ngtcp2_frame_chain ngtcp2_frame_chain; @@ -219,6 +220,12 @@ int ngtcp2_strm_recv_reordering(ngtcp2_strm *strm, const uint8_t *data, */ void ngtcp2_strm_update_rx_offset(ngtcp2_strm *strm, uint64_t offset); +/* + * ngtcp2_strm_discard_reordered_data discards all buffered reordered + * data. + */ +void ngtcp2_strm_discard_reordered_data(ngtcp2_strm *strm); + /* * ngtcp2_strm_shutdown shutdowns |strm|. |flags| should be * NGTCP2_STRM_FLAG_SHUT_RD, and/or NGTCP2_STRM_FLAG_SHUT_WR. @@ -320,4 +327,30 @@ int ngtcp2_strm_ack_data(ngtcp2_strm *strm, uint64_t offset, uint64_t len); */ void ngtcp2_strm_set_app_error_code(ngtcp2_strm *strm, uint64_t app_error_code); +/* + * ngtcp2_strm_require_retransmit_reset_stream returns nonzero if + * RESET_STREAM frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_reset_stream(ngtcp2_strm *strm); + +/* + * ngtcp2_strm_require_retransmit_stop_sending returns nonzero if + * STOP_SENDING frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_stop_sending(ngtcp2_strm *strm); + +/* + * ngtcp2_strm_require_retransmit_max_stream_data returns nonzero if + * MAX_STREAM_DATA frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_max_stream_data(ngtcp2_strm *strm, + ngtcp2_max_stream_data *fr); + +/* + * ngtcp2_strm_require_retransmit_stream_data_blocked returns nonzero + * if STREAM_DATA_BLOCKED frame frame should be retransmitted. + */ +int ngtcp2_strm_require_retransmit_stream_data_blocked( + ngtcp2_strm *strm, ngtcp2_stream_data_blocked *fr); + #endif /* NGTCP2_STRM_H */