diff --git a/lib/ngtcp2_pkt.c b/lib/ngtcp2_pkt.c index 0e8d774709ca29196f6cd59fe2d3bc0c77343181..ad69c01a962e860bb7a938a04092e6a388c711e6 100644 --- a/lib/ngtcp2_pkt.c +++ b/lib/ngtcp2_pkt.c @@ -1997,15 +1997,27 @@ size_t ngtcp2_pkt_stream_max_datalen(uint64_t stream_id, uint64_t offset, size_t n = 1 /* type */ + ngtcp2_put_varint_len(stream_id) + (offset ? ngtcp2_put_varint_len(offset) : 0); - if (left < n) { + if (left <= n) { return (size_t)-1; } - n += ngtcp2_put_varint_len(ngtcp2_min(len, left - n)); + left -= n; - if (left < n) { - return (size_t)-1; + if (left > 8 + 1073741823 && len > 1073741823) { + len = ngtcp2_min(len, 4611686018427387903lu); + return ngtcp2_min(len, left - 8); + } + + if (left > 4 + 16383 && len > 16383) { + len = ngtcp2_min(len, 1073741823); + return ngtcp2_min(len, left - 4); + } + + if (left > 2 + 63 && len > 63) { + len = ngtcp2_min(len, 16383); + return ngtcp2_min(len, left - 2); } - return ngtcp2_min(len, left - n); + len = ngtcp2_min(len, 63); + return ngtcp2_min(len, left - 1); } diff --git a/tests/main.c b/tests/main.c index 29398e26875572af297e758a00a253ea4d59003f..4fdfb00771ff18651a7d27c6412ce2ef47ad4dd1 100644 --- a/tests/main.c +++ b/tests/main.c @@ -124,6 +124,8 @@ int main() { !CU_add_test(pSuite, "pkt_write_retry", test_ngtcp2_pkt_write_retry) || !CU_add_test(pSuite, "pkt_write_version_negotiation", test_ngtcp2_pkt_write_version_negotiation) || + !CU_add_test(pSuite, "pkt_stream_max_datalen", + test_ngtcp2_pkt_stream_max_datalen) || !CU_add_test(pSuite, "get_varint", test_ngtcp2_get_varint) || !CU_add_test(pSuite, "get_varint_len", test_ngtcp2_get_varint_len) || !CU_add_test(pSuite, "put_varint_len", test_ngtcp2_put_varint_len) || diff --git a/tests/ngtcp2_pkt_test.c b/tests/ngtcp2_pkt_test.c index 51b3000ba31153f7eb9b3aac34ebd9fabb73535c..00818c28167d5a9f7992acfe04016a20904decea 100644 --- a/tests/ngtcp2_pkt_test.c +++ b/tests/ngtcp2_pkt_test.c @@ -1158,3 +1158,67 @@ void test_ngtcp2_pkt_write_version_negotiation(void) { CU_ASSERT(sv[i] == ngtcp2_get_uint32(p)); } } + +void test_ngtcp2_pkt_stream_max_datalen(void) { + size_t len; + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 0, 2); + + CU_ASSERT((size_t)-1 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 0, 3); + + CU_ASSERT(0 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1, 3); + + CU_ASSERT(0 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1, 4); + + CU_ASSERT(1 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 1, 1, 4); + + CU_ASSERT(0 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 63, 66); + + CU_ASSERT(63 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 63, 65); + + CU_ASSERT(62 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 1400); + + CU_ASSERT(1396 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 1399); + + CU_ASSERT(1395 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1396, 9); + + CU_ASSERT(6 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 16385, 16391); + + CU_ASSERT(16385 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 16385, 16390); + + CU_ASSERT(16384 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1073741824, 1073741834); + + CU_ASSERT(1073741824 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 1073741824, 1073741833); + + CU_ASSERT(1073741823 == len); + + len = ngtcp2_pkt_stream_max_datalen(63, 0, 16383, 16387); + + CU_ASSERT(16383 == len); +} diff --git a/tests/ngtcp2_pkt_test.h b/tests/ngtcp2_pkt_test.h index 23223fc099766b3cfef395e31d83875b1faa7303..34b9b3720eca102e2ae72346dd017b5c717b2b28 100644 --- a/tests/ngtcp2_pkt_test.h +++ b/tests/ngtcp2_pkt_test.h @@ -58,5 +58,6 @@ void test_ngtcp2_pkt_validate_ack(void); void test_ngtcp2_pkt_write_stateless_reset(void); void test_ngtcp2_pkt_write_retry(void); void test_ngtcp2_pkt_write_version_negotiation(void); +void test_ngtcp2_pkt_stream_max_datalen(void); #endif /* NGTCP2_PKT_TEST_H */