Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 103 additions & 50 deletions proxy/http2/HPACK.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
{
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -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();
Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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)
{
Expand Down
17 changes: 6 additions & 11 deletions proxy/http2/HPACK.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down Expand Up @@ -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
Expand All @@ -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);
Expand All @@ -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;
Expand All @@ -160,7 +155,7 @@ class HpackIndexingTable
void update_maximum_size(uint32_t new_size);

private:
HpackDynamicTable *_dynamic_table;
HpackDynamicTable _dynamic_table;
};

// Low level interfaces
Expand Down