diff --git a/proxy/http2/HPACK.cc b/proxy/http2/HPACK.cc index 97a2626e049..1704fb67d3a 100644 --- a/proxy/http2/HPACK.cc +++ b/proxy/http2/HPACK.cc @@ -24,6 +24,8 @@ #include "HPACK.h" #include "HuffmanCodec.h" +namespace +{ // [RFC 7541] 4.1. Calculating Table Size // The size of an entry is the sum of its name's length in octets (as defined in Section 5.2), // its value's length in octets, and 32. @@ -181,10 +183,10 @@ static const StaticTable STATIC_TABLE[] = {{"", ""}, */ static constexpr uint32_t HPACK_HDR_HEAP_THRESHOLD = sizeof(MIMEHdrImpl) + sizeof(MIMEFieldBlockImpl) * (2 + 7 + 15); -/****************** - * Local functions - ******************/ -static inline bool +// +// Local functions +// +bool hpack_field_is_literal(HpackField ftype) { return ftype == HpackField::INDEXED_LITERAL || ftype == HpackField::NOINDEX_LITERAL || ftype == HpackField::NEVERINDEX_LITERAL; @@ -218,9 +220,45 @@ hpack_parse_field_type(uint8_t ftype) return HpackField::NOINDEX_LITERAL; } -/************************ - * HpackIndexingTable - ************************/ +// +// HpackStaticTable +// +namespace HpackStaticTable +{ + HpackLookupResult + lookup(const char *name, int name_len, const char *value, int value_len) + { + HpackLookupResult result; + + for (unsigned int index = 1; index < TS_HPACK_STATIC_TABLE_ENTRY_NUM; ++index) { + const char *table_name = STATIC_TABLE[index].name; + int table_name_len = STATIC_TABLE[index].name_size; + const char *table_value = STATIC_TABLE[index].value; + int table_value_len = STATIC_TABLE[index].value_size; + + // Check whether name (and value) are matched + if (ptr_len_casecmp(name, name_len, table_name, table_name_len) == 0) { + if ((value_len == table_value_len) && (memcmp(value, table_value, value_len) == 0)) { + result.index = index; + result.index_type = HpackIndex::STATIC; + result.match_type = HpackMatch::EXACT; + break; + } else if (!result.index) { + result.index = index; + result.index_type = HpackIndex::STATIC; + result.match_type = HpackMatch::NAME; + } + } + } + + return result; + } +} // namespace HpackStaticTable +} // namespace + +// +// HpackIndexingTable +// HpackLookupResult HpackIndexingTable::lookup(const MIMEFieldWrapper &field) const { @@ -233,45 +271,18 @@ HpackIndexingTable::lookup(const MIMEFieldWrapper &field) const HpackLookupResult HpackIndexingTable::lookup(const char *name, int name_len, const char *value, int value_len) const { - HpackLookupResult result; - const unsigned int entry_num = TS_HPACK_STATIC_TABLE_ENTRY_NUM + _dynamic_table->length(); - - for (unsigned int index = 1; index < entry_num; ++index) { - const char *table_name, *table_value; - int table_name_len = 0, table_value_len = 0; - - if (index < TS_HPACK_STATIC_TABLE_ENTRY_NUM) { - // static table - table_name = STATIC_TABLE[index].name; - table_value = STATIC_TABLE[index].value; - table_name_len = STATIC_TABLE[index].name_size; - table_value_len = STATIC_TABLE[index].value_size; - } else { - // dynamic table - const MIMEField *m_field = _dynamic_table->get_header_field(index - TS_HPACK_STATIC_TABLE_ENTRY_NUM); + // static table + HpackLookupResult result = HpackStaticTable::lookup(name, name_len, value, value_len); - table_name = m_field->name_get(&table_name_len); - table_value = m_field->value_get(&table_value_len); - } - - // Check whether name (and value) are matched - if (ptr_len_casecmp(name, name_len, table_name, table_name_len) == 0) { - if ((value_len == table_value_len) && (memcmp(value, table_value, value_len) == 0)) { - result.index = index; - result.match_type = HpackMatch::EXACT; - break; - } else if (!result.index) { - result.index = index; - result.match_type = HpackMatch::NAME; - } - } + // if result is not EXACT match, lookup dynamic table + if (result.match_type == HpackMatch::EXACT) { + return result; } - if (result.match_type != HpackMatch::NONE) { - if (result.index < TS_HPACK_STATIC_TABLE_ENTRY_NUM) { - result.index_type = HpackIndex::STATIC; - } else { - result.index_type = HpackIndex::DYNAMIC; - } + + // dynamic table + if (HpackLookupResult dt_result = this->_dynamic_table.lookup(name, name_len, value, value_len); + dt_result.match_type == HpackMatch::EXACT) { + return dt_result; } return result; @@ -289,9 +300,9 @@ HpackIndexingTable::get_header_field(uint32_t index, MIMEFieldWrapper &field) co // static table field.name_set(STATIC_TABLE[index].name, STATIC_TABLE[index].name_size); field.value_set(STATIC_TABLE[index].value, 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.length()) { // dynamic table - const MIMEField *m_field = _dynamic_table->get_header_field(index - TS_HPACK_STATIC_TABLE_ENTRY_NUM); + const MIMEField *m_field = _dynamic_table.get_header_field(index - TS_HPACK_STATIC_TABLE_ENTRY_NUM); int name_len, value_len; const char *name = m_field->name_get(&name_len); @@ -312,30 +323,36 @@ HpackIndexingTable::get_header_field(uint32_t index, MIMEFieldWrapper &field) co void HpackIndexingTable::add_header_field(const MIMEField *field) { - _dynamic_table->add_header_field(field); + _dynamic_table.add_header_field(field); } uint32_t HpackIndexingTable::maximum_size() const { - return _dynamic_table->maximum_size(); + return _dynamic_table.maximum_size(); } uint32_t HpackIndexingTable::size() const { - return _dynamic_table->size(); + return _dynamic_table.size(); } void HpackIndexingTable::update_maximum_size(uint32_t new_size) { - _dynamic_table->update_maximum_size(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(); @@ -384,6 +401,39 @@ HpackDynamicTable::add_header_field(const MIMEField *field) } } +HpackLookupResult +HpackDynamicTable::lookup(const char *name, int name_len, const char *value, int value_len) 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->get_header_field(index - TS_HPACK_STATIC_TABLE_ENTRY_NUM); + + int table_name_len = 0; + const char *table_name = m_field->name_get(&table_name_len); + + int table_value_len = 0; + const char *table_value = m_field->value_get(&table_value_len); + + // Check whether name (and value) are matched + if (ptr_len_casecmp(name, name_len, table_name, table_name_len) == 0) { + if ((value_len == table_value_len) && (memcmp(value, table_value, value_len) == 0)) { + 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 { @@ -463,6 +513,9 @@ HpackDynamicTable::_mime_hdr_gc() } } +// +// Global functions +// int64_t encode_indexed_header_field(uint8_t *buf_start, const uint8_t *buf_end, uint32_t index) { diff --git a/proxy/http2/HPACK.h b/proxy/http2/HPACK.h index 70f95eddf92..ffe67eb512d 100644 --- a/proxy/http2/HPACK.h +++ b/proxy/http2/HPACK.h @@ -56,8 +56,7 @@ enum class HpackMatch { // Result of looking for a header field in IndexingTable struct HpackLookupResult { - HpackLookupResult() {} - int index = 0; + uint32_t index = 0; HpackIndex index_type = HpackIndex::NONE; HpackMatch match_type = HpackMatch::NONE; }; @@ -106,12 +105,7 @@ class MIMEFieldWrapper class HpackDynamicTable { public: - explicit HpackDynamicTable(uint32_t size) : _current_size(0), _maximum_size(size) - { - _mhdr = new MIMEHdr(); - _mhdr->create(); - } - + explicit HpackDynamicTable(uint32_t size); ~HpackDynamicTable(); // noncopyable @@ -121,6 +115,7 @@ class HpackDynamicTable const MIMEField *get_header_field(uint32_t index) const; void add_header_field(const MIMEField *field); + HpackLookupResult lookup(const char *name, int name_len, const char *value, int value_len) const; uint32_t maximum_size() const; uint32_t size() const; void update_maximum_size(uint32_t new_size); @@ -143,8 +138,8 @@ class HpackDynamicTable class HpackIndexingTable { public: - explicit HpackIndexingTable(uint32_t size) { _dynamic_table = new HpackDynamicTable(size); } - ~HpackIndexingTable() { delete _dynamic_table; } + explicit HpackIndexingTable(uint32_t size) : _dynamic_table(size){}; + ~HpackIndexingTable() {} // noncopyable HpackIndexingTable(HpackIndexingTable &) = delete; @@ -160,7 +155,7 @@ class HpackIndexingTable void update_maximum_size(uint32_t new_size); private: - HpackDynamicTable *_dynamic_table; + HpackDynamicTable _dynamic_table; }; // Low level interfaces