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;
-}

Reply via email to