This is an automated email from the ASF dual-hosted git repository.
maskit pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 367962abc5 Unify Dynamic Table implementation (#10997)
367962abc5 is described below
commit 367962abc5f9f8773b7a1d40b05e2845d984af91
Author: Masakazu Kitajo <[email protected]>
AuthorDate: Tue Jan 30 10:20:50 2024 -0700
Unify Dynamic Table implementation (#10997)
---
include/proxy/hdrs/XPACK.h | 78 +++++++
include/proxy/http2/HPACK.h | 35 +---
include/proxy/http3/QPACK.h | 77 +------
src/proxy/hdrs/CMakeLists.txt | 4 +-
src/proxy/hdrs/XPACK.cc | 354 +++++++++++++++++++++++++++++++
src/proxy/hdrs/unit_tests/test_XPACK.cc | 182 ++++++++++++++++
src/proxy/http2/HPACK.cc | 231 ++-------------------
src/proxy/http3/QPACK.cc | 357 ++++++--------------------------
8 files changed, 706 insertions(+), 612 deletions(-)
diff --git a/include/proxy/hdrs/XPACK.h b/include/proxy/hdrs/XPACK.h
index 70814a512b..f4b705a761 100644
--- a/include/proxy/hdrs/XPACK.h
+++ b/include/proxy/hdrs/XPACK.h
@@ -24,6 +24,7 @@
#pragma once
#include <cstdint>
+#include <string_view>
#include "tscore/Arena.h"
const static int XPACK_ERROR_COMPRESSION_ERROR = -1;
@@ -35,3 +36,80 @@ int64_t xpack_decode_integer(uint64_t &dst, const uint8_t
*buf_start, const uint
int64_t xpack_encode_string(uint8_t *buf_start, const uint8_t *buf_end, const
char *value, uint64_t value_len, uint8_t n = 7);
int64_t xpack_decode_string(Arena &arena, char **str, uint64_t &str_length,
const uint8_t *buf_start, const uint8_t *buf_end,
uint8_t n = 7);
+
+struct XpackLookupResult {
+ uint32_t index = 0;
+ enum MatchType { NONE, NAME, EXACT } match_type = MatchType::NONE;
+};
+
+struct XpackDynamicTableEntry {
+ uint32_t index = 0;
+ uint32_t offset = 0;
+ uint32_t name_len = 0;
+ uint32_t value_len = 0;
+ uint32_t ref_count = 0;
+ const char *wks = nullptr;
+};
+
+class XpackDynamicTableStorage
+{
+public:
+ XpackDynamicTableStorage(uint32_t size);
+ ~XpackDynamicTableStorage();
+ void read(uint32_t offset, const char **name, uint32_t name_len, const char
**value, uint32_t value_len) const;
+ uint32_t write(const char *name, uint32_t name_len, const char *value,
uint32_t value_len);
+ void erase(uint32_t name_len, uint32_t value_len);
+
+private:
+ uint32_t _overwrite_threshold = 0;
+ uint8_t *_data = nullptr;
+ uint32_t _data_size = 0;
+ uint32_t _head = 0;
+ uint32_t _tail = 0;
+};
+
+class XpackDynamicTable
+{
+public:
+ XpackDynamicTable(uint32_t size);
+ ~XpackDynamicTable();
+
+ const XpackLookupResult lookup(uint32_t absolute_index, const char **name,
size_t *name_len, const char **value,
+ size_t *value_len) const;
+ const XpackLookupResult lookup(const char *name, size_t name_len, const char
*value, size_t value_len) const;
+ const XpackLookupResult lookup(const std::string_view name, const
std::string_view value) const;
+ const XpackLookupResult lookup_relative(uint32_t relative_index, const char
**name, size_t *name_len, const char **value,
+ size_t *value_len) const;
+ const XpackLookupResult lookup_relative(const char *name, size_t name_len,
const char *value, size_t value_len) const;
+ const XpackLookupResult lookup_relative(const std::string_view name, const
std::string_view value) const;
+ const XpackLookupResult insert_entry(const char *name, size_t name_len,
const char *value, size_t value_len);
+ const XpackLookupResult insert_entry(const std::string_view name, const
std::string_view value);
+ const XpackLookupResult duplicate_entry(uint32_t current_index);
+ bool should_duplicate(uint32_t index);
+ bool update_maximum_size(uint32_t max_size);
+ uint32_t size() const;
+ uint32_t maximum_size() const;
+ void ref_entry(uint32_t index);
+ void unref_entry(uint32_t index);
+ bool is_empty() const;
+ uint32_t largest_index() const;
+ uint32_t count() const;
+
+private:
+ static constexpr uint8_t ADDITIONAL_32_BYTES = 32;
+ uint32_t _maximum_size = 0;
+ uint32_t _available = 0;
+ uint32_t _entries_inserted = 0;
+
+ struct XpackDynamicTableEntry *_entries = nullptr;
+ uint32_t _max_entries = 0;
+ uint32_t _entries_head = 0;
+ uint32_t _entries_tail = 0;
+ XpackDynamicTableStorage _storage;
+
+ /**
+ * The type of reuired_size is uint64 so that we can handle a size that is
begger than the table capacity.
+ * Passing a value more than UINT32_MAX evicts every entry and return false.
+ */
+ bool _make_space(uint64_t required_size);
+};
diff --git a/include/proxy/http2/HPACK.h b/include/proxy/http2/HPACK.h
index b3d7440e60..f8e93856ce 100644
--- a/include/proxy/http2/HPACK.h
+++ b/include/proxy/http2/HPACK.h
@@ -107,39 +107,6 @@ private:
MIMEHdrImpl *_mh;
};
-// [RFC 7541] 2.3.2. Dynamic Table
-class HpackDynamicTable
-{
-public:
- explicit HpackDynamicTable(uint32_t size);
- ~HpackDynamicTable();
-
- // noncopyable
- HpackDynamicTable(HpackDynamicTable &) = delete;
- HpackDynamicTable &operator=(const HpackDynamicTable &) = delete;
-
- const MIMEField *get_header_field(uint32_t index) const;
- void add_header_field(const HpackHeaderField &header);
-
- HpackLookupResult lookup(const HpackHeaderField &header) const;
- uint32_t maximum_size() const;
- uint32_t size() const;
- void update_maximum_size(uint32_t new_size);
-
- uint32_t length() const;
-
-private:
- void _evict_overflowed_entries();
- void _mime_hdr_gc();
-
- uint32_t _current_size = 0;
- uint32_t _maximum_size = 0;
-
- MIMEHdr *_mhdr = nullptr;
- MIMEHdr *_mhdr_old = nullptr;
- std::deque<MIMEField *> _headers;
-};
-
// [RFC 7541] 2.3. Indexing Table
class HpackIndexingTable
{
@@ -160,7 +127,7 @@ public:
void update_maximum_size(uint32_t new_size);
private:
- HpackDynamicTable _dynamic_table;
+ XpackDynamicTable _dynamic_table;
};
// Low level interfaces
diff --git a/include/proxy/http3/QPACK.h b/include/proxy/http3/QPACK.h
index 5dbc0f5013..21b294149c 100644
--- a/include/proxy/http3/QPACK.h
+++ b/include/proxy/http3/QPACK.h
@@ -33,6 +33,7 @@
#include "tscore/Arena.h"
#include "proxy/hdrs/MIME.h"
#include "proxy/hdrs/HTTP.h"
+#include "proxy/hdrs/XPACK.h"
#include "iocore/net/quic/QUICApplication.h"
#include "iocore/net/quic/QUICStreamVCAdapter.h"
#include "iocore/net/quic/QUICConnection.h"
@@ -80,83 +81,25 @@ public:
static size_t estimate_header_block_size(const HTTPHdr &header_set);
private:
- struct LookupResult {
- uint16_t index = 0;
- enum MatchType { NONE, NAME, EXACT } match_type = MatchType::NONE;
- };
-
struct Header {
Header(const char *n, const char *v) : name(n), value(v),
name_len(strlen(name)), value_len(strlen(value)) {}
const char *name;
const char *value;
- const int name_len;
- const int value_len;
+ const size_t name_len;
+ const size_t value_len;
};
class StaticTable
{
public:
- static const LookupResult lookup(uint16_t index, const char **name, int
*name_len, const char **value, int *value_len);
- static const LookupResult lookup(const char *name, int name_len, const
char *value, int value_len);
+ static const XpackLookupResult lookup(uint16_t index, const char **name,
size_t *name_len, const char **value,
+ size_t *value_len);
+ static const XpackLookupResult lookup(const char *name, size_t name_len,
const char *value, size_t value_len);
private:
static const Header STATIC_HEADER_FIELDS[];
};
- struct DynamicTableEntry {
- uint16_t index = 0;
- uint16_t offset = 0;
- uint16_t name_len = 0;
- uint16_t value_len = 0;
- uint16_t ref_count = 0;
- };
-
- class DynamicTableStorage
- {
- public:
- DynamicTableStorage(uint16_t size);
- ~DynamicTableStorage();
- void read(uint16_t offset, const char **name, uint16_t name_len, const
char **value, uint16_t value_len) const;
- uint16_t write(const char *name, uint16_t name_len, const char *value,
uint16_t value_len);
- void erase(uint16_t name_len, uint16_t value_len);
-
- private:
- uint16_t _overwrite_threshold = 0;
- uint8_t *_data = nullptr;
- uint16_t _data_size = 0;
- uint16_t _head = 0;
- uint16_t _tail = 0;
- };
-
- class DynamicTable
- {
- public:
- DynamicTable(uint16_t size);
- ~DynamicTable();
-
- const LookupResult lookup(uint16_t index, const char **name, int
*name_len, const char **value, int *value_len);
- const LookupResult lookup(const char *name, int name_len, const char
*value, int value_len);
- const LookupResult insert_entry(bool is_static, uint16_t index, const char
*value, uint16_t value_len);
- const LookupResult insert_entry(const char *name, uint16_t name_len, const
char *value, uint16_t value_len);
- const LookupResult duplicate_entry(uint16_t current_index);
- bool should_duplicate(uint16_t index);
- void update_size(uint16_t max_size);
- void ref_entry(uint16_t index);
- void unref_entry(uint16_t index);
- uint16_t largest_index() const;
-
- private:
- uint16_t _available = 0;
- uint16_t _entries_inserted = 0;
-
- // FIXME It may be better to split this array into small arrays to reduce
memory footprint
- struct DynamicTableEntry *_entries = nullptr;
- uint16_t _max_entries = 0;
- uint16_t _entries_head = 0;
- uint16_t _entries_tail = 0;
- DynamicTableStorage *_storage = nullptr;
- };
-
class DecodeRequest
{
public:
@@ -248,7 +191,7 @@ private:
uint16_t largest;
};
- DynamicTable _dynamic_table;
+ XpackDynamicTable _dynamic_table;
std::map<uint64_t, struct EntryReference> _references;
uint32_t _max_field_section_size = 0;
uint16_t _max_table_size = 0;
@@ -271,9 +214,9 @@ private:
// Encoder Stream
int _read_insert_with_name_ref(IOBufferReader &reader, bool &is_static,
uint16_t &index, Arena &arena, char **value,
- uint16_t &value_len);
- int _read_insert_without_name_ref(IOBufferReader &reader, Arena &arena, char
**name, uint16_t &name_len, char **value,
- uint16_t &value_len);
+ size_t &value_len);
+ int _read_insert_without_name_ref(IOBufferReader &reader, Arena &arena, char
**name, size_t &name_len, char **value,
+ size_t &value_len);
int _read_duplicate(IOBufferReader &reader, uint16_t &index);
int _read_dynamic_table_size_update(IOBufferReader &reader, uint16_t
&max_size);
int _write_insert_with_name_ref(uint16_t index, bool dynamic, const char
*value, uint16_t value_len);
diff --git a/src/proxy/hdrs/CMakeLists.txt b/src/proxy/hdrs/CMakeLists.txt
index 9e0bc6e10f..dd8bad770c 100644
--- a/src/proxy/hdrs/CMakeLists.txt
+++ b/src/proxy/hdrs/CMakeLists.txt
@@ -54,7 +54,7 @@ if(BUILD_TESTING)
target_link_libraries(test_proxy_hdrs PRIVATE ts::hdrs ts::tscore
ts::inkevent catch2::catch2)
add_test(NAME test_proxy_hdrs COMMAND test_proxy_hdrs)
- add_executable(test_proxy_hdrs_xpack XPACK.cc HuffmanCodec.cc
unit_tests/test_XPACK.cc)
- target_link_libraries(test_proxy_hdrs_xpack PRIVATE ts::tscore ts::tsutil
libswoc catch2::catch2)
+ add_executable(test_proxy_hdrs_xpack unit_tests/test_XPACK.cc)
+ target_link_libraries(test_proxy_hdrs_xpack PRIVATE ts::hdrs ts::tscore
ts::tsutil libswoc catch2::catch2)
add_test(NAME test_proxy_hdrs_xpack COMMAND test_proxy_hdrs_xpack)
endif()
diff --git a/src/proxy/hdrs/XPACK.cc b/src/proxy/hdrs/XPACK.cc
index 3a0a271973..8e458cc52d 100644
--- a/src/proxy/hdrs/XPACK.cc
+++ b/src/proxy/hdrs/XPACK.cc
@@ -23,11 +23,33 @@
#include "proxy/hdrs/XPACK.h"
#include "proxy/hdrs/HuffmanCodec.h"
+#include "proxy/hdrs/HdrToken.h"
#include "tscore/Arena.h"
+#include "tscore/Diags.h"
#include "tscore/ink_memory.h"
#include "tsutil/LocalBuffer.h"
+#define XPACKDebug(fmt, ...) Debug("xpack", fmt, ##__VA_ARGS__)
+
+static inline bool
+match(const char *s1, int s1_len, const char *s2, int s2_len)
+{
+ if (s1_len != s2_len) {
+ return false;
+ }
+
+ if (s1 == s2) {
+ return true;
+ }
+
+ if (memcmp(s1, s2, s1_len) != 0) {
+ return false;
+ }
+
+ return true;
+}
+
//
// [RFC 7541] 5.1. Integer representation
//
@@ -188,3 +210,335 @@ xpack_encode_string(uint8_t *buf_start, const uint8_t
*buf_end, const char *valu
return p - buf_start;
}
+
+//
+// DynamicTable
+//
+XpackDynamicTable::XpackDynamicTable(uint32_t size) : _maximum_size(size),
_available(size), _max_entries(size), _storage(size)
+{
+ XPACKDebug("Dynamic table size: %u", size);
+ this->_entries = static_cast<struct XpackDynamicTableEntry
*>(ats_malloc(sizeof(struct XpackDynamicTableEntry) * size));
+ this->_entries_head = size - 1;
+ this->_entries_tail = size - 1;
+}
+
+XpackDynamicTable::~XpackDynamicTable()
+{
+ if (this->_entries) {
+ delete this->_entries;
+ this->_entries = nullptr;
+ }
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup(uint32_t index, const char **name, size_t *name_len,
const char **value, size_t *value_len) const
+{
+ XPACKDebug("Lookup entry: abs_index=%u", index);
+
+ if (this->is_empty()) {
+ // There's no entry
+ return {0, XpackLookupResult::MatchType::NONE};
+ }
+
+ if (index > this->_entries[this->_entries_head].index) {
+ // The index is invalid
+ return {0, XpackLookupResult::MatchType::NONE};
+ }
+
+ if (index < this->_entries[(this->_entries_tail + 1) %
this->_max_entries].index) {
+ // The index is invalid
+ return {0, XpackLookupResult::MatchType::NONE};
+ }
+
+ uint32_t pos = (this->_entries_head -
(this->_entries[this->_entries_head].index - index)) % this->_max_entries;
+ *name_len = this->_entries[pos].name_len;
+ *value_len = this->_entries[pos].value_len;
+ this->_storage.read(this->_entries[pos].offset, name, *name_len, value,
*value_len);
+ if (this->_entries[pos].wks) {
+ *name = this->_entries[pos].wks;
+ }
+ return {index, XpackLookupResult::MatchType::EXACT};
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup(const char *name, size_t name_len, const char
*value, size_t value_len) const
+{
+ XPACKDebug("Lookup entry: name=%.*s, value=%.*s",
static_cast<int>(name_len), name, static_cast<int>(value_len), value);
+ XpackLookupResult::MatchType match_type = XpackLookupResult::MatchType::NONE;
+ uint32_t i = (this->_entries_tail + 1) %
this->_max_entries;
+ uint32_t end = (this->_entries_head + 1) %
this->_max_entries;
+ uint32_t candidate_index = 0;
+ const char *tmp_name = nullptr;
+ const char *tmp_value = nullptr;
+
+ // DynamicTable is empty
+ if (this->is_empty()) {
+ return {candidate_index, match_type};
+ }
+
+ for (; i != end; i = (i + 1) % this->_max_entries) {
+ if (name_len != 0 && this->_entries[i].name_len == name_len) {
+ this->_storage.read(this->_entries[i].offset, &tmp_name,
this->_entries[i].name_len, &tmp_value, this->_entries[i].value_len);
+ if (match(name, name_len, tmp_name, this->_entries[i].name_len)) {
+ candidate_index = this->_entries[i].index;
+ if (match(value, value_len, tmp_value, this->_entries[i].value_len)) {
+ // Exact match
+ match_type = XpackLookupResult::MatchType::EXACT;
+ break;
+ } else {
+ // Name match -- Keep it for no exact matches
+ match_type = XpackLookupResult::MatchType::NAME;
+ }
+ }
+ }
+ }
+
+ XPACKDebug("Lookup entry: candidate_index=%u, match_type=%u",
candidate_index, match_type);
+ return {candidate_index, match_type};
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup(const std::string_view name, const std::string_view
value) const
+{
+ return lookup(name.data(), name.length(), value.data(), value.length());
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup_relative(uint32_t relative_index, const char **name,
size_t *name_len, const char **value,
+ size_t *value_len) const
+{
+ XPACKDebug("Lookup entry: rel_index=%u", relative_index);
+ return this->lookup(this->_entries[this->_entries_head].index -
relative_index, name, name_len, value, value_len);
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup_relative(const char *name, size_t name_len, const
char *value, size_t value_len) const
+{
+ XpackLookupResult result = this->lookup(name, name_len, value, value_len);
+ result.index = this->_entries[this->_entries_head].index -
result.index;
+ return result;
+}
+
+const XpackLookupResult
+XpackDynamicTable::lookup_relative(const std::string_view name, const
std::string_view value) const
+{
+ return this->lookup_relative(name.data(), name.length(), value.data(),
value.length());
+}
+
+const XpackLookupResult
+XpackDynamicTable::insert_entry(const char *name, size_t name_len, const char
*value, size_t value_len)
+{
+ if (this->_max_entries == 0) {
+ return {UINT32_C(0), XpackLookupResult::MatchType::NONE};
+ }
+
+ // Make enough space to insert a new entry
+ uint64_t required_size = static_cast<uint64_t>(name_len) +
static_cast<uint64_t>(value_len) + ADDITIONAL_32_BYTES;
+ if (required_size > this->_available) {
+ if (!this->_make_space(required_size - this->_available)) {
+ // We can't insert a new entry because some stream(s) refer an entry
that need to be evicted or the header is too big to
+ // store. This is fine with HPACK, but not with QPACK.
+ return {UINT32_C(0), XpackLookupResult::MatchType::NONE};
+ }
+ }
+
+ // Insert
+ const char *wks = nullptr;
+ hdrtoken_tokenize(name, name_len, &wks);
+ this->_entries_head = (this->_entries_head + 1) %
this->_max_entries;
+ this->_entries[this->_entries_head] = {
+ this->_entries_inserted++,
+ this->_storage.write(name, static_cast<uint32_t>(name_len), value,
static_cast<uint32_t>(value_len)),
+ static_cast<uint32_t>(name_len),
+ static_cast<uint32_t>(value_len),
+ 0,
+ wks};
+ this->_available -= required_size;
+
+ XPACKDebug("Insert Entry: entry=%u, index=%u, size=%zu",
this->_entries_head, this->_entries_inserted - 1, name_len + value_len);
+ XPACKDebug("Available size: %u", this->_available);
+ return {this->_entries_inserted, value_len ?
XpackLookupResult::MatchType::EXACT : XpackLookupResult::MatchType::NAME};
+}
+
+const XpackLookupResult
+XpackDynamicTable::insert_entry(const std::string_view name, const
std::string_view value)
+{
+ return insert_entry(name.data(), name.length(), value.data(),
value.length());
+}
+
+const XpackLookupResult
+XpackDynamicTable::duplicate_entry(uint32_t current_index)
+{
+ const char *name = nullptr;
+ size_t name_len = 0;
+ const char *value = nullptr;
+ size_t value_len = 0;
+ char *duped_name;
+ char *duped_value;
+
+ XpackLookupResult result = this->lookup(current_index, &name, &name_len,
&value, &value_len);
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
+ return result;
+ }
+
+ // We need to dup name and value to avoid memcpy-param-overlap
+ duped_name = ats_strndup(name, name_len);
+ duped_value = ats_strndup(value, value_len);
+ result = this->insert_entry(duped_name, name_len, duped_value,
value_len);
+ ats_free(duped_name);
+ ats_free(duped_value);
+
+ return result;
+}
+
+bool
+XpackDynamicTable::should_duplicate(uint32_t index)
+{
+ // TODO: Check whether a specified entry should be duplicated
+ // Just return false for now
+ return false;
+}
+
+bool
+XpackDynamicTable::update_maximum_size(uint32_t new_max_size)
+{
+ uint32_t used = this->_maximum_size - this->_available;
+ if (used < new_max_size) {
+ this->_maximum_size = new_max_size;
+ this->_available = new_max_size - used;
+ return true;
+ }
+
+ bool ret = this->_make_space(used - new_max_size);
+ // Size update must suceeds
+ if (ret) {
+ this->_available = new_max_size - (this->_maximum_size -
this->_available);
+ this->_maximum_size = new_max_size;
+ }
+ return ret;
+}
+
+uint32_t
+XpackDynamicTable::size() const
+{
+ return this->_maximum_size - this->_available;
+}
+
+uint32_t
+XpackDynamicTable::maximum_size() const
+{
+ return this->_maximum_size;
+}
+
+void
+XpackDynamicTable::ref_entry(uint32_t index)
+{
+ uint32_t pos = (this->_entries_head + (index -
this->_entries[this->_entries_head].index)) % this->_max_entries;
+ ++this->_entries[pos].ref_count;
+}
+
+void
+XpackDynamicTable::unref_entry(uint32_t index)
+{
+ uint32_t pos = (this->_entries_head + (index -
this->_entries[this->_entries_head].index)) % this->_max_entries;
+ --this->_entries[pos].ref_count;
+}
+
+bool
+XpackDynamicTable::is_empty() const
+{
+ return this->_entries_head == this->_entries_tail;
+}
+
+uint32_t
+XpackDynamicTable::largest_index() const
+{
+ ink_assert(!this->is_empty());
+ return this->_entries_inserted - 1;
+}
+
+uint32_t
+XpackDynamicTable::count() const
+{
+ if (is_empty()) {
+ return 0;
+ } else if (this->_entries_head > this->_entries_tail) {
+ return this->_entries_head - this->_entries_tail;
+ } else {
+ return (this->_max_entries - this->_entries_tail - 1) +
(this->_entries_head + 1);
+ }
+}
+
+bool
+XpackDynamicTable::_make_space(uint64_t required_size)
+{
+ uint32_t freed = 0;
+ uint32_t tail = (this->_entries_tail + 1) % this->_max_entries;
+
+ while (required_size > freed) {
+ if (this->_entries_head < tail) {
+ break;
+ }
+ if (this->_entries[tail].ref_count) {
+ break;
+ }
+ freed += this->_entries[tail].name_len + this->_entries[tail].value_len +
ADDITIONAL_32_BYTES;
+ tail = (tail + 1) % this->_max_entries;
+ }
+
+ // Evict
+ if (freed > 0) {
+ XPACKDebug("Evict entries: from %u to %u",
this->_entries[(this->_entries_tail + 1) % this->_max_entries].index,
+ this->_entries[tail - 1].index);
+ this->_available += freed;
+ this->_entries_tail = tail - 1;
+ XPACKDebug("Available size: %u", this->_available);
+ }
+
+ return required_size <= this->_available;
+}
+
+//
+// DynamicTableStorage
+//
+
+XpackDynamicTableStorage::XpackDynamicTableStorage(uint32_t size) : _head(size
* 2 - 1), _tail(size * 2 - 1)
+{
+ this->_data_size = size * 2;
+ this->_data = reinterpret_cast<uint8_t
*>(ats_malloc(this->_data_size));
+ this->_overwrite_threshold = size;
+}
+
+XpackDynamicTableStorage::~XpackDynamicTableStorage()
+{
+ ats_free(this->_data);
+ this->_data = nullptr;
+}
+
+void
+XpackDynamicTableStorage::read(uint32_t offset, const char **name, uint32_t
name_len, const char **value, uint32_t value_len) const
+{
+ *name = reinterpret_cast<const char *>(this->_data + offset);
+ *value = reinterpret_cast<const char *>(this->_data + offset + name_len);
+}
+
+uint32_t
+XpackDynamicTableStorage::write(const char *name, uint32_t name_len, const
char *value, uint32_t value_len)
+{
+ uint32_t offset = (this->_head + 1) % this->_data_size;
+ memcpy(this->_data + offset, name, name_len);
+ memcpy(this->_data + offset + name_len, value, value_len);
+
+ this->_head = (this->_head + (name_len + value_len)) % this->_data_size;
+ if (this->_head > this->_overwrite_threshold) {
+ this->_head = 0;
+ }
+
+ return offset;
+}
+
+void
+XpackDynamicTableStorage::erase(uint32_t name_len, uint32_t value_len)
+{
+ this->_tail = (this->_tail + (name_len + value_len)) % this->_data_size;
+}
diff --git a/src/proxy/hdrs/unit_tests/test_XPACK.cc
b/src/proxy/hdrs/unit_tests/test_XPACK.cc
index 6a860053ac..222289c2f3 100644
--- a/src/proxy/hdrs/unit_tests/test_XPACK.cc
+++ b/src/proxy/hdrs/unit_tests/test_XPACK.cc
@@ -125,4 +125,186 @@ TEST_CASE("XPACK_String", "[xpack]")
REQUIRE(memcmp(actual, i.raw_string, actual_len) == 0);
}
}
+
+ SECTION("Dynamic Table")
+ {
+ constexpr uint16_t MAX_SIZE = 128;
+ XpackDynamicTable dt(MAX_SIZE);
+ XpackLookupResult result;
+ const char *name = nullptr;
+ size_t name_len = 0;
+ const char *value = nullptr;
+ size_t value_len = 0;
+
+ // Check the initial state
+ REQUIRE(dt.size() == 0);
+ REQUIRE(dt.maximum_size() == MAX_SIZE);
+ REQUIRE(dt.is_empty());
+ REQUIRE(dt.count() == 0);
+ result = dt.lookup(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE - 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE + 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ // Insert one entry
+ dt.insert_entry("name1", "value1");
+ REQUIRE(dt.size() == strlen("name1") + strlen("value1") + 32);
+ REQUIRE(dt.maximum_size() == MAX_SIZE);
+ REQUIRE(dt.count() == 1);
+ REQUIRE(dt.largest_index() == 0);
+ result = dt.lookup(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name1"));
+ REQUIRE(memcmp(name, "name1", name_len) == 0);
+ REQUIRE(value_len == strlen("value1"));
+ REQUIRE(memcmp(value, "value1", value_len) == 0);
+ result = dt.lookup(dt.largest_index() + 1, &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ result = dt.lookup(MAX_SIZE - 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE + 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ // Insert one more entry
+ dt.insert_entry("name2", "value2");
+ REQUIRE(dt.size() == strlen("name1") + strlen("value1") + 32 +
strlen("name2") + strlen("value2") + 32);
+ REQUIRE(dt.maximum_size() == MAX_SIZE);
+ REQUIRE(dt.count() == 2);
+ REQUIRE(dt.largest_index() == 1);
+ result = dt.lookup(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name1"));
+ REQUIRE(memcmp(name, "name1", name_len) == 0);
+ REQUIRE(value_len == strlen("value1"));
+ REQUIRE(memcmp(value, "value1", value_len) == 0);
+ result = dt.lookup(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name2"));
+ REQUIRE(memcmp(name, "name2", name_len) == 0);
+ REQUIRE(value_len == strlen("value2"));
+ REQUIRE(memcmp(value, "value2", value_len) == 0);
+ result = dt.lookup(dt.largest_index() + 1, &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup_relative(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name2"));
+ REQUIRE(memcmp(name, "name2", name_len) == 0);
+ REQUIRE(value_len == strlen("value2"));
+ REQUIRE(memcmp(value, "value2", value_len) == 0);
+ result = dt.lookup_relative(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name1"));
+ REQUIRE(memcmp(name, "name1", name_len) == 0);
+ REQUIRE(value_len == strlen("value1"));
+ REQUIRE(memcmp(value, "value1", value_len) == 0);
+ result = dt.lookup(MAX_SIZE - 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(MAX_SIZE + 1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ // Insert one more entry (this should evict the first entry)
+ dt.insert_entry("name3", "value3");
+ REQUIRE(dt.size() == strlen("name2") + strlen("value2") + 32 +
strlen("name3") + strlen("value3") + 32);
+ REQUIRE(dt.maximum_size() == MAX_SIZE);
+ REQUIRE(dt.count() == 2);
+ REQUIRE(dt.largest_index() == 2);
+ result = dt.lookup(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name2"));
+ REQUIRE(memcmp(name, "name2", name_len) == 0);
+ REQUIRE(value_len == strlen("value2"));
+ REQUIRE(memcmp(value, "value2", value_len) == 0);
+ result = dt.lookup(2, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name3"));
+ REQUIRE(memcmp(name, "name3", name_len) == 0);
+ REQUIRE(value_len == strlen("value3"));
+ REQUIRE(memcmp(value, "value3", value_len) == 0);
+ result = dt.lookup(dt.largest_index() + 1, &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup_relative(0, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name3"));
+ REQUIRE(memcmp(name, "name3", name_len) == 0);
+ REQUIRE(value_len == strlen("value3"));
+ REQUIRE(memcmp(value, "value3", value_len) == 0);
+ result = dt.lookup_relative(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name2"));
+ REQUIRE(memcmp(name, "name2", name_len) == 0);
+ REQUIRE(value_len == strlen("value2"));
+ REQUIRE(memcmp(value, "value2", value_len) == 0);
+
+ // Insert one more entry (this should evict all existing entries)
+ dt.insert_entry("name4-1234567890123456789012345",
"value4-9876543210987654321098765");
+ REQUIRE(dt.size() == strlen("name4-1234567890123456789012345") +
strlen("value4-9876543210987654321098765") + 32);
+ REQUIRE(dt.maximum_size() == MAX_SIZE);
+ REQUIRE(dt.count() == 1);
+ REQUIRE(dt.largest_index() == 3);
+ result = dt.lookup(3, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name4-1234567890123456789012345"));
+ REQUIRE(memcmp(name, "name4-1234567890123456789012345", name_len) == 0);
+ REQUIRE(value_len == strlen("value4-9876543210987654321098765"));
+ REQUIRE(memcmp(value, "value4-9876543210987654321098765", value_len) == 0);
+ result = dt.lookup(dt.largest_index() - 1, &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(dt.largest_index(), &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ result = dt.lookup(dt.largest_index() + 1, &name, &name_len, &value,
&value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ // Update the maximum size (this should not evict anything)
+ size_t current_size = dt.size();
+ dt.update_maximum_size(current_size);
+ REQUIRE(dt.size() == current_size);
+ REQUIRE(dt.maximum_size() == current_size);
+ REQUIRE(dt.count() == 1);
+ REQUIRE(dt.largest_index() == 3);
+ result = dt.lookup(3, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::EXACT);
+ REQUIRE(name_len == strlen("name4-1234567890123456789012345"));
+ REQUIRE(memcmp(name, "name4-1234567890123456789012345", name_len) == 0);
+ REQUIRE(value_len == strlen("value4-9876543210987654321098765"));
+ REQUIRE(memcmp(value, "value4-9876543210987654321098765", value_len) == 0);
+
+ // Update the maximum size (this should evict everything)
+ dt.update_maximum_size(0);
+ REQUIRE(dt.size() == 0);
+ REQUIRE(dt.maximum_size() == 0);
+ REQUIRE(dt.is_empty());
+ REQUIRE(dt.count() == 0);
+ result = dt.lookup(1, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+ result = dt.lookup(2, &name, &name_len, &value, &value_len);
+ REQUIRE(result.match_type == XpackLookupResult::MatchType::NONE);
+
+ // Reset the maximum size
+ dt.update_maximum_size(4096);
+ REQUIRE(dt.size() == 0);
+ REQUIRE(dt.maximum_size() == 4096);
+ REQUIRE(dt.is_empty());
+ REQUIRE(dt.count() == 0);
+
+ // Insert an oversided item
+ dt.insert_entry("name1", "value1"); // This should be evicted
+ dt.insert_entry("", UINT32_MAX, "", UINT32_MAX); // This should not even
cause a buffer over run
+ REQUIRE(dt.size() == 0);
+ REQUIRE(dt.maximum_size() == 4096);
+ REQUIRE(dt.is_empty());
+ REQUIRE(dt.count() == 0);
+ }
}
diff --git a/src/proxy/http2/HPACK.cc b/src/proxy/http2/HPACK.cc
index 367caed935..db66c08387 100644
--- a/src/proxy/http2/HPACK.cc
+++ b/src/proxy/http2/HPACK.cc
@@ -196,21 +196,6 @@ constexpr HpackHeaderField STATIC_TABLE[] = {
constexpr std::string_view HPACK_HDR_FIELD_COOKIE =
STATIC_TABLE[TS_HPACK_STATIC_TABLE_COOKIE].name;
constexpr std::string_view HPACK_HDR_FIELD_AUTHORIZATION =
STATIC_TABLE[TS_HPACK_STATIC_TABLE_AUTHORIZATION].name;
-/**
- Threshold for total HdrHeap size which used by HPAK Dynamic Table.
- The HdrHeap is filled by MIMEHdrImpl and MIMEFieldBlockImpl like below.
- This threshold allow to allocate 3 HdrHeap at maximum.
-
- +------------------+-----------------------------+
- HdrHeap 1 (2048): | MIMEHdrImpl(592) | MIMEFieldBlockImpl(528) x 2 |
- +------------------+-----------------------------+--...--+
- HdrHeap 2 (4096): | MIMEFieldBlockImpl(528) x 7 |
-
+------------------------------------------------+--...--+--...--+
- HdrHeap 3 (8192): | MIMEFieldBlockImpl(528) x 15
|
-
+------------------------------------------------+--...--+--...--+
-*/
-static constexpr uint32_t HPACK_HDR_HEAP_THRESHOLD = sizeof(MIMEHdrImpl) +
sizeof(MIMEFieldBlockImpl) * (2 + 7 + 15);
-
//
// Local functions
//
@@ -241,24 +226,6 @@ match(const char *s1, int s1_len, const char *s2, int
s2_len)
return true;
}
-static inline bool
-match_ignore_case(const char *s1, int s1_len, const char *s2, int s2_len)
-{
- if (s1_len != s2_len) {
- return false;
- }
-
- if (s1 == s2) {
- return true;
- }
-
- if (strncasecmp(s1, s2, s1_len) != 0) {
- return false;
- }
-
- return true;
-}
-
//
// The first byte of an HPACK field unambiguously tells us what
// kind of field it is. Field types are specified in the high 4 bits
@@ -350,8 +317,10 @@ HpackIndexingTable::lookup(const HpackHeaderField &header)
const
}
// dynamic table
- if (HpackLookupResult dt_result = this->_dynamic_table.lookup(header);
dt_result.match_type == HpackMatch::EXACT) {
- return dt_result;
+ if (XpackLookupResult dt_result =
this->_dynamic_table.lookup_relative(header.name, header.value);
+ dt_result.match_type == XpackLookupResult::MatchType::EXACT) {
+ return {static_cast<uint32_t>(TS_HPACK_STATIC_TABLE_ENTRY_NUM +
dt_result.index), HpackIndex::DYNAMIC,
+ static_cast<HpackMatch>(dt_result.match_type)};
}
return result;
@@ -369,13 +338,16 @@ HpackIndexingTable::get_header_field(uint32_t index,
MIMEFieldWrapper &field) co
// static table
field.name_set(STATIC_TABLE[index].name.data(),
STATIC_TABLE[index].name.size());
field.value_set(STATIC_TABLE[index].value.data(),
STATIC_TABLE[index].value.size());
- } else if (index < TS_HPACK_STATIC_TABLE_ENTRY_NUM +
_dynamic_table.length()) {
+ } else if (index < (TS_HPACK_STATIC_TABLE_ENTRY_NUM +
_dynamic_table.count())) {
// dynamic table
- const MIMEField *m_field = _dynamic_table.get_header_field(index -
TS_HPACK_STATIC_TABLE_ENTRY_NUM);
+ size_t name_len, value_len;
+ const char *name;
+ const char *value;
- int name_len, value_len;
- const char *name = m_field->name_get(&name_len);
- const char *value = m_field->value_get(&value_len);
+ auto result = _dynamic_table.lookup_relative(index -
TS_HPACK_STATIC_TABLE_ENTRY_NUM, &name, &name_len, &value, &value_len);
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
+ return HPACK_ERROR_COMPRESSION_ERROR;
+ }
field.name_set(name, name_len);
field.value_set(value, value_len);
@@ -392,7 +364,7 @@ HpackIndexingTable::get_header_field(uint32_t index,
MIMEFieldWrapper &field) co
void
HpackIndexingTable::add_header_field(const HpackHeaderField &header)
{
- _dynamic_table.add_header_field(header);
+ _dynamic_table.insert_entry(header.name, header.value);
}
uint32_t
@@ -413,183 +385,6 @@ HpackIndexingTable::update_maximum_size(uint32_t new_size)
_dynamic_table.update_maximum_size(new_size);
}
-//
-// HpackDynamicTable
-//
-HpackDynamicTable::HpackDynamicTable(uint32_t size) : _maximum_size(size)
-{
- _mhdr = new MIMEHdr();
- _mhdr->create();
-}
-
-HpackDynamicTable::~HpackDynamicTable()
-{
- this->_headers.clear();
-
- this->_mhdr->fields_clear();
- this->_mhdr->destroy();
- delete this->_mhdr;
-
- if (this->_mhdr_old != nullptr) {
- this->_mhdr_old->fields_clear();
- this->_mhdr_old->destroy();
- delete this->_mhdr_old;
- }
-}
-
-const MIMEField *
-HpackDynamicTable::get_header_field(uint32_t index) const
-{
- return this->_headers.at(index);
-}
-
-void
-HpackDynamicTable::add_header_field(const HpackHeaderField &header)
-{
- uint32_t header_size = ADDITIONAL_OCTETS + header.name.size() +
header.value.size();
-
- if (header_size > _maximum_size) {
- // [RFC 7541] 4.4. Entry Eviction When Adding New Entries
- // It is not an error to attempt to add an entry that is larger than
- // the maximum size; an attempt to add an entry larger than the entire
- // table causes the table to be emptied of all existing entries.
- this->_headers.clear();
- this->_mhdr->fields_clear();
-
- if (this->_mhdr_old) {
- this->_mhdr_old->fields_clear();
- this->_mhdr_old->destroy();
- delete this->_mhdr_old;
- this->_mhdr_old = nullptr;
- }
-
- this->_current_size = 0;
- } else {
- this->_current_size += header_size;
- this->_evict_overflowed_entries();
-
- MIMEField *new_field = this->_mhdr->field_create(header.name.data(),
header.name.size());
- new_field->value_set(this->_mhdr->m_heap, this->_mhdr->m_mime,
header.value.data(), header.value.size());
- this->_mhdr->field_attach(new_field);
- this->_headers.push_front(new_field);
- }
-}
-
-HpackLookupResult
-HpackDynamicTable::lookup(const HpackHeaderField &header) const
-{
- HpackLookupResult result;
- const unsigned int entry_num = TS_HPACK_STATIC_TABLE_ENTRY_NUM +
this->length();
-
- for (unsigned int index = TS_HPACK_STATIC_TABLE_ENTRY_NUM; index <
entry_num; ++index) {
- const MIMEField *m_field = this->_headers.at(index -
TS_HPACK_STATIC_TABLE_ENTRY_NUM);
- std::string_view name = m_field->name_get();
- std::string_view value = m_field->value_get();
-
- // Check whether name (and value) are matched
- if (match_ignore_case(header.name.data(), header.name.length(),
name.data(), name.length())) {
- if (match(header.value.data(), header.value.length(), value.data(),
value.length())) {
- result.index = index;
- result.index_type = HpackIndex::DYNAMIC;
- result.match_type = HpackMatch::EXACT;
- break;
- } else if (!result.index) {
- result.index = index;
- result.index_type = HpackIndex::DYNAMIC;
- result.match_type = HpackMatch::NAME;
- }
- }
- }
-
- return result;
-}
-
-uint32_t
-HpackDynamicTable::maximum_size() const
-{
- return _maximum_size;
-}
-
-uint32_t
-HpackDynamicTable::size() const
-{
- return _current_size;
-}
-
-//
-// [RFC 7541] 4.3. Entry Eviction when Header Table Size Changes
-//
-// Whenever the maximum size for the header table is reduced, entries
-// are evicted from the end of the header table until the size of the
-// header table is less than or equal to the maximum size.
-//
-void
-HpackDynamicTable::update_maximum_size(uint32_t new_size)
-{
- this->_maximum_size = new_size;
- this->_evict_overflowed_entries();
-}
-
-uint32_t
-HpackDynamicTable::length() const
-{
- return this->_headers.size();
-}
-
-void
-HpackDynamicTable::_evict_overflowed_entries()
-{
- if (this->_current_size <= this->_maximum_size) {
- // Do nothing
- return;
- }
-
- while (!this->_headers.empty()) {
- auto h = this->_headers.back();
- int name_len, value_len;
- h->name_get(&name_len);
- h->value_get(&value_len);
-
- this->_current_size -= ADDITIONAL_OCTETS + name_len + value_len;
-
- if (this->_mhdr_old && this->_mhdr_old->fields_count() != 0) {
- this->_mhdr_old->field_delete(h, false);
- } else {
- this->_mhdr->field_delete(h, false);
- }
-
- this->_headers.pop_back();
-
- if (this->_current_size <= this->_maximum_size) {
- break;
- }
- }
-
- this->_mime_hdr_gc();
-}
-
-/**
- When HdrHeap size of current MIMEHdr exceeds the threshold, allocate new
MIMEHdr and HdrHeap.
- The old MIMEHdr and HdrHeap will be freed, when all MIMEFiled are deleted
by HPACK Entry Eviction.
- */
-void
-HpackDynamicTable::_mime_hdr_gc()
-{
- if (this->_mhdr_old == nullptr) {
- if (this->_mhdr->m_heap->total_used_size() >= HPACK_HDR_HEAP_THRESHOLD) {
- this->_mhdr_old = this->_mhdr;
- this->_mhdr = new MIMEHdr();
- this->_mhdr->create();
- }
- } else {
- if (this->_mhdr_old->fields_count() == 0) {
- this->_mhdr_old->destroy();
- delete this->_mhdr_old;
- this->_mhdr_old = nullptr;
- }
- }
-}
-
//
// Global functions
//
diff --git a/src/proxy/http3/QPACK.cc b/src/proxy/http3/QPACK.cc
index c8dd5094c2..54cf3f5fac 100644
--- a/src/proxy/http3/QPACK.cc
+++ b/src/proxy/http3/QPACK.cc
@@ -360,41 +360,41 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
bool never_index = false;
// Find from tables, and insert / duplicate a entry prior to encode it
- LookupResult lookup_result_static;
- LookupResult lookup_result_dynamic;
+ XpackLookupResult lookup_result_static;
+ XpackLookupResult lookup_result_dynamic;
lookup_result_static = StaticTable::lookup(lowered_name, name_len, value,
value_len);
- if (lookup_result_static.match_type != LookupResult::MatchType::EXACT) {
+ if (lookup_result_static.match_type != XpackLookupResult::MatchType::EXACT) {
lookup_result_dynamic = this->_dynamic_table.lookup(lowered_name,
name_len, value, value_len);
- if (lookup_result_dynamic.match_type == LookupResult::MatchType::EXACT) {
+ if (lookup_result_dynamic.match_type ==
XpackLookupResult::MatchType::EXACT) {
if (this->_dynamic_table.should_duplicate(lookup_result_dynamic.index)) {
// Duplicate an entry and use the new entry
uint16_t current_index = lookup_result_dynamic.index;
lookup_result_dynamic =
this->_dynamic_table.duplicate_entry(current_index);
- if (lookup_result_dynamic.match_type != LookupResult::MatchType::NONE)
{
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_duplicate(current_index);
QPACKDebug("Wrote Duplicate: current_index=%d", current_index);
this->_dynamic_table.ref_entry(current_index);
}
}
- } else if (lookup_result_static.match_type ==
LookupResult::MatchType::NAME) {
+ } else if (lookup_result_static.match_type ==
XpackLookupResult::MatchType::NAME) {
if (never_index) {
// Name in static table is always available. Do nothing.
} else {
// Insert both the name and the value
lookup_result_dynamic =
this->_dynamic_table.insert_entry(lowered_name, name_len, value, value_len);
- if (lookup_result_dynamic.match_type != LookupResult::MatchType::NONE)
{
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_insert_with_name_ref(lookup_result_static.index, false,
value, value_len);
QPACKDebug("Wrote Insert With Name Ref: index=%u, dynamic_table=%d
value=%.*s", lookup_result_static.index, false,
value_len, value);
}
}
- } else if (lookup_result_dynamic.match_type ==
LookupResult::MatchType::NAME) {
+ } else if (lookup_result_dynamic.match_type ==
XpackLookupResult::MatchType::NAME) {
if (never_index) {
if
(this->_dynamic_table.should_duplicate(lookup_result_dynamic.index)) {
// Duplicate an entry and use the new entry
uint16_t current_index = lookup_result_dynamic.index;
lookup_result_dynamic =
this->_dynamic_table.duplicate_entry(current_index);
- if (lookup_result_dynamic.match_type !=
LookupResult::MatchType::NONE) {
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_duplicate(current_index);
QPACKDebug("Wrote Duplicate: current_index=%d", current_index);
this->_dynamic_table.ref_entry(current_index);
@@ -405,7 +405,7 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
// Duplicate an entry and use the new entry
uint16_t current_index = lookup_result_dynamic.index;
lookup_result_dynamic =
this->_dynamic_table.duplicate_entry(current_index);
- if (lookup_result_dynamic.match_type !=
LookupResult::MatchType::NONE) {
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_duplicate(current_index);
QPACKDebug("Wrote Duplicate: current_index=%d", current_index);
this->_dynamic_table.ref_entry(current_index);
@@ -414,7 +414,7 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
// Insert both the name and the value
uint16_t current_index = lookup_result_dynamic.index;
lookup_result_dynamic =
this->_dynamic_table.insert_entry(lowered_name, name_len, value, value_len);
- if (lookup_result_dynamic.match_type !=
LookupResult::MatchType::NONE) {
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_insert_with_name_ref(current_index, true, value,
value_len);
QPACKDebug("Wrote Insert With Name Ref: index=%u,
dynamic_table=%d, value=%.*s", current_index, true, value_len, value);
}
@@ -424,14 +424,14 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
if (never_index) {
// Insert only the name
lookup_result_dynamic =
this->_dynamic_table.insert_entry(lowered_name, name_len, "", 0);
- if (lookup_result_dynamic.match_type != LookupResult::MatchType::NONE)
{
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_insert_without_name_ref(lowered_name, name_len, "", 0);
QPACKDebug("Wrote Insert Without Name Ref: name=%.*s value=%.*s",
name_len, lowered_name, 0, "");
}
} else {
// Insert both the name and the value
lookup_result_dynamic =
this->_dynamic_table.insert_entry(lowered_name, name_len, value, value_len);
- if (lookup_result_dynamic.match_type != LookupResult::MatchType::NONE)
{
+ if (lookup_result_dynamic.match_type !=
XpackLookupResult::MatchType::NONE) {
this->_write_insert_without_name_ref(lowered_name, name_len, value,
value_len);
QPACKDebug("Wrote Insert Without Name Ref: name=%.*s value=%.*s",
name_len, lowered_name, value_len, value);
}
@@ -440,12 +440,12 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
}
// Encode
- if (lookup_result_static.match_type == LookupResult::MatchType::EXACT) {
+ if (lookup_result_static.match_type == XpackLookupResult::MatchType::EXACT) {
this->_encode_indexed_header_field(lookup_result_static.index, base_index,
false, compressed_header);
QPACKDebug("Encoded Indexed Header Field: abs_index=%d, base_index=%d,
dynamic_table=%d", lookup_result_static.index,
base_index, false);
referred_index = 0;
- } else if (lookup_result_dynamic.match_type ==
LookupResult::MatchType::EXACT) {
+ } else if (lookup_result_dynamic.match_type ==
XpackLookupResult::MatchType::EXACT) {
if (lookup_result_dynamic.index < this->_largest_known_received_index) {
this->_encode_indexed_header_field(lookup_result_dynamic.index,
base_index, true, compressed_header);
QPACKDebug("Encoded Indexed Header Field: abs_index=%d, base_index=%d,
dynamic_table=%d", lookup_result_dynamic.index,
@@ -458,14 +458,14 @@ QPACK::_encode_header(const MIMEField &field, uint16_t
base_index, IOBufferBlock
}
this->_dynamic_table.ref_entry(lookup_result_dynamic.index);
referred_index = lookup_result_dynamic.index;
- } else if (lookup_result_static.match_type == LookupResult::MatchType::NAME)
{
+ } else if (lookup_result_static.match_type ==
XpackLookupResult::MatchType::NAME) {
this->_encode_literal_header_field_with_name_ref(lookup_result_static.index,
false, base_index, value, value_len, never_index,
compressed_header);
QPACKDebug(
"Encoded Literal Header Field With Name Ref: abs_index=%d,
base_index=%d, dynamic_table=%d, value=%.*s, never_index=%d",
lookup_result_static.index, base_index, false, value_len, value,
never_index);
referred_index = 0;
- } else if (lookup_result_dynamic.match_type ==
LookupResult::MatchType::NAME) {
+ } else if (lookup_result_dynamic.match_type ==
XpackLookupResult::MatchType::NAME) {
if (lookup_result_dynamic.index <= this->_largest_known_received_index) {
this->_encode_literal_header_field_with_name_ref(lookup_result_dynamic.index,
true, base_index, value, value_len, never_index,
compressed_header);
@@ -676,10 +676,10 @@ QPACK::_decode_indexed_header_field(int16_t base_index,
const uint8_t *buf, size
// Lookup a table
const char *name = nullptr;
- int name_len = 0;
+ size_t name_len = 0;
const char *value = nullptr;
- int value_len = 0;
- QPACK::LookupResult result;
+ size_t value_len = 0;
+ XpackLookupResult result;
if (buf[0] & 0x40) { // Static table
result = StaticTable::lookup(index, &name, &name_len, &value, &value_len);
@@ -687,7 +687,7 @@ QPACK::_decode_indexed_header_field(int16_t base_index,
const uint8_t *buf, size
result =
this->_dynamic_table.lookup(this->_calc_absolute_index_from_relative_index(base_index,
index), &name, &name_len,
&value, &value_len);
}
- if (result.match_type != QPACK::LookupResult::MatchType::EXACT) {
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
return -1;
}
@@ -695,8 +695,8 @@ QPACK::_decode_indexed_header_field(int16_t base_index,
const uint8_t *buf, size
this->_attach_header(hdr, name, name_len, value, value_len, false);
header_len = name_len + value_len;
- QPACKDebug("Decoded Indexed Header Field: base_index=%d, abs_index=%d,
name=%.*s, value=%.*s", base_index, result.index, name_len,
- name, value_len, value);
+ QPACKDebug("Decoded Indexed Header Field: base_index=%d, abs_index=%d,
name=%.*s, value=%.*s", base_index, result.index,
+ static_cast<int>(name_len), name, static_cast<int>(value_len),
value);
return len;
}
@@ -723,10 +723,10 @@ QPACK::_decode_literal_header_field_with_name_ref(int16_t
base_index, const uint
// Lookup the name
const char *name = nullptr;
- int name_len = 0;
+ size_t name_len = 0;
const char *dummy = nullptr;
- int dummy_len = 0;
- QPACK::LookupResult result;
+ size_t dummy_len = 0;
+ XpackLookupResult result;
if (buf[0] & 0x10) { // Static table
result = StaticTable::lookup(index, &name, &name_len, &dummy, &dummy_len);
@@ -734,7 +734,7 @@ QPACK::_decode_literal_header_field_with_name_ref(int16_t
base_index, const uint
result =
this->_dynamic_table.lookup(this->_calc_absolute_index_from_relative_index(base_index,
index), &name, &name_len,
&dummy, &dummy_len);
}
- if (result.match_type != QPACK::LookupResult::MatchType::EXACT) {
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
return -1;
}
@@ -752,7 +752,7 @@ QPACK::_decode_literal_header_field_with_name_ref(int16_t
base_index, const uint
header_len = name_len + value_len;
QPACKDebug("Decoded Literal Header Field With Name Ref: base_index=%d,
abs_index=%d, name=%.*s, value=%.*s", base_index,
- result.index, name_len, name, static_cast<int>(value_len), value);
+ result.index, static_cast<int>(name_len), name,
static_cast<int>(value_len), value);
return read_len;
}
@@ -810,14 +810,14 @@
QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, cons
// Lookup a table
const char *name = nullptr;
- int name_len = 0;
+ size_t name_len = 0;
const char *value = nullptr;
- int value_len = 0;
- QPACK::LookupResult result;
+ size_t value_len = 0;
+ XpackLookupResult result;
result =
this->_dynamic_table.lookup(this->_calc_absolute_index_from_postbase_index(base_index,
index), &name, &name_len, &value,
&value_len);
- if (result.match_type != QPACK::LookupResult::MatchType::EXACT) {
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
return -1;
}
@@ -826,7 +826,7 @@
QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, cons
header_len = name_len + value_len;
QPACKDebug("Decoded Indexed Header Field With Postbase Index: base_index=%d,
abs_index=%d, name=%.*s, value=%.*s", base_index,
- result.index, name_len, name, value_len, value);
+ result.index, static_cast<int>(name_len), name,
static_cast<int>(value_len), value);
return len;
}
@@ -853,14 +853,14 @@
QPACK::_decode_literal_header_field_with_postbase_name_ref(int16_t base_index, c
// Lookup the name
const char *name = nullptr;
- int name_len = 0;
+ size_t name_len = 0;
const char *dummy = nullptr;
- int dummy_len = 0;
- QPACK::LookupResult result;
+ size_t dummy_len = 0;
+ XpackLookupResult result;
result =
this->_dynamic_table.lookup(this->_calc_absolute_index_from_postbase_index(base_index,
index), &name, &name_len, &dummy,
&dummy_len);
- if (result.match_type != QPACK::LookupResult::MatchType::EXACT) {
+ if (result.match_type != XpackLookupResult::MatchType::EXACT) {
return -1;
}
@@ -878,7 +878,7 @@
QPACK::_decode_literal_header_field_with_postbase_name_ref(int16_t base_index, c
header_len = name_len + value_len;
QPACKDebug("Decoded Literal Header Field With Postbase Name Ref:
base_index=%d, abs_index=%d, name=%.*s, value=%.*s", base_index,
- static_cast<uint16_t>(index), name_len, name,
static_cast<int>(value_len), value);
+ static_cast<uint16_t>(index), static_cast<int>(name_len), name,
static_cast<int>(value_len), value);
return read_len;
}
@@ -1111,25 +1111,32 @@ QPACK::_on_encoder_stream_read_ready(IOBufferReader
&reader)
bool is_static;
uint16_t index;
Arena arena;
+ const char *name;
+ size_t name_len;
+ const char *dummy;
+ size_t dummy_len;
char *value;
- uint16_t value_len;
+ size_t value_len;
if (this->_read_insert_with_name_ref(reader, is_static, index, arena,
&value, value_len) < 0) {
this->_abort_decode();
return EVENT_DONE;
}
- QPACKDebug("Received Insert With Name Ref: is_static=%d, index=%d,
value=%.*s", is_static, index, value_len, value);
- this->_dynamic_table.insert_entry(is_static, index, value, value_len);
+ QPACKDebug("Received Insert With Name Ref: is_static=%d, index=%d,
value=%.*s", is_static, index, static_cast<int>(value_len),
+ value);
+ StaticTable::lookup(index, &name, &name_len, &dummy, &dummy_len);
+ this->_dynamic_table.insert_entry(name, name_len, value, value_len);
} else if (buf & 0x40) { // Insert Without Name Reference
Arena arena;
char *name;
- uint16_t name_len;
+ size_t name_len;
char *value;
- uint16_t value_len;
+ size_t value_len;
if (this->_read_insert_without_name_ref(reader, arena, &name, name_len,
&value, value_len) < 0) {
this->_abort_decode();
return EVENT_DONE;
}
- QPACKDebug("Received Insert Without Name Ref: name=%.*s, value=%.*s",
name_len, name, value_len, value);
+ QPACKDebug("Received Insert Without Name Ref: name=%.*s, value=%.*s",
static_cast<int>(name_len), name,
+ static_cast<int>(value_len), value);
this->_dynamic_table.insert_entry(name, name_len, value, value_len);
} else if (buf & 0x20) { // Dynamic Table Size Update
uint16_t max_size;
@@ -1138,7 +1145,7 @@ QPACK::_on_encoder_stream_read_ready(IOBufferReader
&reader)
return EVENT_DONE;
}
QPACKDebug("Received Dynamic Table Size Update: max_size=%d", max_size);
- this->_dynamic_table.update_size(max_size);
+ this->_dynamic_table.update_maximum_size(max_size);
} else { // Duplicates
uint16_t index;
if (this->_read_duplicate(reader, index) < 0) {
@@ -1178,24 +1185,24 @@ QPACK::estimate_header_block_size(const HTTPHdr &hdr)
return 128 * 1024 * 1024;
}
-const QPACK::LookupResult
-QPACK::StaticTable::lookup(uint16_t index, const char **name, int *name_len,
const char **value, int *value_len)
+const XpackLookupResult
+QPACK::StaticTable::lookup(uint16_t index, const char **name, size_t
*name_len, const char **value, size_t *value_len)
{
const Header &header = STATIC_HEADER_FIELDS[index];
*name = header.name;
*name_len = header.name_len;
*value = header.value;
*value_len = header.value_len;
- return {index, QPACK::LookupResult::MatchType::EXACT};
+ return {index, XpackLookupResult::MatchType::EXACT};
}
-const QPACK::LookupResult
-QPACK::StaticTable::lookup(const char *name, int name_len, const char *value,
int value_len)
+const XpackLookupResult
+QPACK::StaticTable::lookup(const char *name, size_t name_len, const char
*value, size_t value_len)
{
- QPACK::LookupResult::MatchType match_type =
QPACK::LookupResult::MatchType::NONE;
- uint16_t i = 0;
- uint16_t candidate_index = 0;
- int n = countof(STATIC_HEADER_FIELDS);
+ XpackLookupResult::MatchType match_type = XpackLookupResult::MatchType::NONE;
+ uint16_t i = 0;
+ uint16_t candidate_index = 0;
+ int n = countof(STATIC_HEADER_FIELDS);
for (; i < n; ++i) {
const Header &h = STATIC_HEADER_FIELDS[i];
@@ -1204,11 +1211,11 @@ QPACK::StaticTable::lookup(const char *name, int
name_len, const char *value, in
candidate_index = i;
if (value_len == h.value_len && memcmp(value, h.value, value_len) ==
0) {
// Exact match
- match_type = QPACK::LookupResult::MatchType::EXACT;
+ match_type = XpackLookupResult::MatchType::EXACT;
break;
} else {
// Name match -- Keep it for no exact matches
- match_type = QPACK::LookupResult::MatchType::NAME;
+ match_type = XpackLookupResult::MatchType::NAME;
}
}
}
@@ -1249,192 +1256,6 @@ QPACK::_attach_header(HTTPHdr &hdr, const char *name,
int name_len, const char *
hdr.field_attach(new_field);
}
-//
-// DynamicTable
-//
-QPACK::DynamicTable::DynamicTable(uint16_t size) : _available(size),
_max_entries(size), _storage(new DynamicTableStorage(size))
-{
- QPACKDTDebug("Dynamic table size: %u", size);
- this->_entries = static_cast<struct DynamicTableEntry
*>(ats_malloc(sizeof(struct DynamicTableEntry) * size));
- this->_entries_head = size - 1;
- this->_entries_tail = size - 1;
-}
-
-QPACK::DynamicTable::~DynamicTable()
-{
- if (this->_storage) {
- delete this->_storage;
- this->_storage = nullptr;
- }
- if (this->_entries) {
- delete this->_entries;
- this->_entries = nullptr;
- }
-}
-
-const QPACK::LookupResult
-QPACK::DynamicTable::lookup(uint16_t index, const char **name, int *name_len,
const char **value, int *value_len)
-{
- // ink_assert(index >= this->_entries[(this->_entries_tail + 1) %
this->_max_entries].index);
- // ink_assert(index <= this->_entries[this->_entries_head].index);
- uint16_t pos = (this->_entries_head + (index -
this->_entries[this->_entries_head].index)) % this->_max_entries;
- *name_len = this->_entries[pos].name_len;
- *value_len = this->_entries[pos].value_len;
- this->_storage->read(this->_entries[pos].offset, name, *name_len, value,
*value_len);
- return {index, QPACK::LookupResult::MatchType::EXACT};
-}
-
-const QPACK::LookupResult
-QPACK::DynamicTable::lookup(const char *name, int name_len, const char *value,
int value_len)
-{
- QPACK::LookupResult::MatchType match_type =
QPACK::LookupResult::MatchType::NONE;
- uint16_t i = this->_entries_tail + 1;
- int end = this->_entries_head;
- uint16_t candidate_index = 0;
- const char *tmp_name = nullptr;
- const char *tmp_value = nullptr;
-
- // DynamicTable is empty
- if (this->_entries_inserted == 0) {
- return {candidate_index, match_type};
- }
-
- // TODO Use a tree for better performance
- for (; i <= end; i = (i + 1) % this->_max_entries) {
- if (name_len != 0 && this->_entries[i].name_len == name_len) {
- this->_storage->read(this->_entries[i].offset, &tmp_name,
this->_entries[i].name_len, &tmp_value,
- this->_entries[i].value_len);
- if (memcmp(name, tmp_name, name_len) == 0) {
- candidate_index = this->_entries[i].index;
- if (value_len == this->_entries[i].value_len && memcmp(value,
tmp_value, value_len) == 0) {
- // Exact match
- match_type = QPACK::LookupResult::MatchType::EXACT;
- break;
- } else {
- // Name match -- Keep it for no exact matches
- match_type = QPACK::LookupResult::MatchType::NAME;
- }
- }
- }
- }
-
- return {candidate_index, match_type};
-}
-
-const QPACK::LookupResult
-QPACK::DynamicTable::insert_entry(bool is_static, uint16_t index, const char
*value, uint16_t value_len)
-{
- const char *name;
- int name_len;
- const char *dummy;
- int dummy_len;
-
- if (is_static) {
- StaticTable::lookup(index, &name, &name_len, &dummy, &dummy_len);
- } else {
- this->lookup(index, &name, &name_len, &dummy, &dummy_len);
- }
- return this->insert_entry(name, name_len, value, value_len);
-}
-
-const QPACK::LookupResult
-QPACK::DynamicTable::insert_entry(const char *name, uint16_t name_len, const
char *value, uint16_t value_len)
-{
- if (this->_max_entries == 0) {
- return {UINT16_C(0), QPACK::LookupResult::MatchType::NONE};
- }
-
- // Check if we can make enough space to insert a new entry
- uint16_t required_len = name_len + value_len;
- uint16_t available = this->_available;
- uint16_t tail = (this->_entries_tail + 1) % this->_max_entries;
- while (available < required_len) {
- if (this->_entries[tail].ref_count) {
- break;
- }
- available += this->_entries[tail].name_len +
this->_entries[tail].value_len;
- tail = (tail + 1) % this->_max_entries;
- }
- if (available < required_len) {
- // We can't insert a new entry because some stream(s) refer an entry that
need to be evicted
- return {UINT16_C(0), QPACK::LookupResult::MatchType::NONE};
- }
-
- // Evict
- if (this->_available != available) {
- QPACKDTDebug("Evict entries: from %u to %u",
this->_entries[(this->_entries_tail + 1) % this->_max_entries].index,
- this->_entries[tail - 1].index);
- this->_available = available;
- this->_entries_tail = tail - 1;
- QPACKDTDebug("Available size: %u", this->_available);
- }
-
- // Insert
- this->_entries_head = (this->_entries_head + 1) %
this->_max_entries;
- this->_entries[this->_entries_head] = {++this->_entries_inserted,
this->_storage->write(name, name_len, value, value_len),
- name_len, value_len, 0};
- this->_available -= required_len;
-
- QPACKDTDebug("Insert Entry: entry=%u, index=%u, size=%u",
this->_entries_head, this->_entries_inserted, name_len + value_len);
- QPACKDTDebug("Available size: %u", this->_available);
- return {this->_entries_inserted, value_len ? LookupResult::MatchType::EXACT
: LookupResult::MatchType::NAME};
-}
-
-const QPACK::LookupResult
-QPACK::DynamicTable::duplicate_entry(uint16_t current_index)
-{
- const char *name;
- int name_len;
- const char *value;
- int value_len;
- char *duped_name;
- char *duped_value;
-
- this->lookup(current_index, &name, &name_len, &value, &value_len);
- // We need to dup name and value to avoid memcpy-param-overlap
- duped_name = ats_strndup(name, name_len);
- duped_value = ats_strndup(value, value_len);
- const LookupResult result = this->insert_entry(duped_name, name_len,
duped_value, value_len);
- ats_free(duped_name);
- ats_free(duped_value);
-
- return result;
-}
-
-bool
-QPACK::DynamicTable::should_duplicate(uint16_t index)
-{
- // TODO: Check whether a specified entry should be duplicated
- // Just return false for now
- return false;
-}
-
-void
-QPACK::DynamicTable::update_size(uint16_t max_size)
-{
- // TODO Implement it
-}
-
-void
-QPACK::DynamicTable::ref_entry(uint16_t index)
-{
- uint16_t pos = (this->_entries_head + (index -
this->_entries[this->_entries_head].index)) % this->_max_entries;
- ++this->_entries[pos].ref_count;
-}
-
-void
-QPACK::DynamicTable::unref_entry(uint16_t index)
-{
- uint16_t pos = (this->_entries_head + (index -
this->_entries[this->_entries_head].index)) % this->_max_entries;
- --this->_entries[pos].ref_count;
-}
-
-uint16_t
-QPACK::DynamicTable::largest_index() const
-{
- return this->_entries_inserted;
-}
-
int
QPACK::_write_insert_with_name_ref(uint16_t index, bool dynamic, const char
*value, uint16_t value_len)
{
@@ -1646,7 +1467,7 @@ QPACK::_write_stream_cancellation(uint64_t stream_id)
int
QPACK::_read_insert_with_name_ref(IOBufferReader &reader, bool &is_static,
uint16_t &index, Arena &arena, char **value,
- uint16_t &value_len)
+ size_t &value_len)
{
size_t read_len = 0;
int ret;
@@ -1678,8 +1499,8 @@ QPACK::_read_insert_with_name_ref(IOBufferReader &reader,
bool &is_static, uint1
}
int
-QPACK::_read_insert_without_name_ref(IOBufferReader &reader, Arena &arena,
char **name, uint16_t &name_len, char **value,
- uint16_t &value_len)
+QPACK::_read_insert_without_name_ref(IOBufferReader &reader, Arena &arena,
char **name, size_t &name_len, char **value,
+ size_t &value_len)
{
size_t read_len = 0;
int ret;
@@ -1814,49 +1635,3 @@ QPACK::_read_stream_cancellation(IOBufferReader &reader,
uint64_t &stream_id)
return 0;
}
-
-//
-// DynamicTableStorage
-//
-
-QPACK::DynamicTableStorage::DynamicTableStorage(uint16_t size) : _head(size *
2 - 1), _tail(size * 2 - 1)
-{
- this->_data_size = size * 2;
- this->_data = reinterpret_cast<uint8_t
*>(ats_malloc(this->_data_size));
- this->_overwrite_threshold = size;
-}
-
-QPACK::DynamicTableStorage::~DynamicTableStorage()
-{
- ats_free(this->_data);
- this->_data = nullptr;
-}
-
-void
-QPACK::DynamicTableStorage::read(uint16_t offset, const char **name, uint16_t
name_len, const char **value,
- uint16_t value_len) const
-{
- *name = reinterpret_cast<const char *>(this->_data + offset);
- *value = reinterpret_cast<const char *>(this->_data + offset + name_len);
-}
-
-uint16_t
-QPACK::DynamicTableStorage::write(const char *name, uint16_t name_len, const
char *value, uint16_t value_len)
-{
- uint16_t offset = (this->_head + 1) % this->_data_size;
- memcpy(this->_data + offset, name, name_len);
- memcpy(this->_data + offset + name_len, value, value_len);
-
- this->_head = (this->_head + (name_len + value_len)) % this->_data_size;
- if (this->_head > this->_overwrite_threshold) {
- this->_head = 0;
- }
-
- return offset;
-}
-
-void
-QPACK::DynamicTableStorage::erase(uint16_t name_len, uint16_t value_len)
-{
- this->_tail = (this->_tail + (name_len + value_len)) % this->_data_size;
-}