| // Copyright (c) 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "quiche/quic/core/qpack/qpack_required_insert_count.h" |
| |
| #include <limits> |
| |
| #include "quiche/quic/platform/api/quic_logging.h" |
| |
| namespace quic { |
| |
| uint64_t QpackEncodeRequiredInsertCount(uint64_t required_insert_count, |
| uint64_t max_entries) { |
| if (required_insert_count == 0) { |
| return 0; |
| } |
| |
| return required_insert_count % (2 * max_entries) + 1; |
| } |
| |
| bool QpackDecodeRequiredInsertCount(uint64_t encoded_required_insert_count, |
| uint64_t max_entries, |
| uint64_t total_number_of_inserts, |
| uint64_t* required_insert_count) { |
| if (encoded_required_insert_count == 0) { |
| *required_insert_count = 0; |
| return true; |
| } |
| |
| // |max_entries| is calculated by dividing an unsigned 64-bit integer by 32, |
| // precluding all calculations in this method from overflowing. |
| QUICHE_DCHECK_LE(max_entries, std::numeric_limits<uint64_t>::max() / 32); |
| |
| if (encoded_required_insert_count > 2 * max_entries) { |
| return false; |
| } |
| |
| *required_insert_count = encoded_required_insert_count - 1; |
| QUICHE_DCHECK_LT(*required_insert_count, |
| std::numeric_limits<uint64_t>::max() / 16); |
| |
| uint64_t current_wrapped = total_number_of_inserts % (2 * max_entries); |
| QUICHE_DCHECK_LT(current_wrapped, std::numeric_limits<uint64_t>::max() / 16); |
| |
| if (current_wrapped >= *required_insert_count + max_entries) { |
| // Required Insert Count wrapped around 1 extra time. |
| *required_insert_count += 2 * max_entries; |
| } else if (current_wrapped + max_entries < *required_insert_count) { |
| // Decoder wrapped around 1 extra time. |
| current_wrapped += 2 * max_entries; |
| } |
| |
| if (*required_insert_count > |
| std::numeric_limits<uint64_t>::max() - total_number_of_inserts) { |
| return false; |
| } |
| |
| *required_insert_count += total_number_of_inserts; |
| |
| // Prevent underflow, also disallow invalid value 0 for Required Insert Count. |
| if (current_wrapped >= *required_insert_count) { |
| return false; |
| } |
| |
| *required_insert_count -= current_wrapped; |
| |
| return true; |
| } |
| |
| } // namespace quic |