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
43 changes: 42 additions & 1 deletion proxy/http2/HPACK.cc
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,12 @@ HpackIndexingTable::add_header_field(const MIMEField *field)
_dynamic_table->add_header_field(field);
}

uint32_t
HpackIndexingTable::maximum_size() const
{
return _dynamic_table->maximum_size();
}

uint32_t
HpackIndexingTable::size() const
{
Expand Down Expand Up @@ -351,6 +357,12 @@ HpackDynamicTable::add_header_field(const MIMEField *field)
}
}

uint32_t
HpackDynamicTable::maximum_size() const
{
return _maximum_size;
}

uint32_t
HpackDynamicTable::size() const
{
Expand Down Expand Up @@ -619,6 +631,18 @@ encode_literal_header_field_with_new_name(uint8_t *buf_start, const uint8_t *buf
return p - buf_start;
}

int64_t
encode_dynamic_table_size_update(uint8_t *buf_start, const uint8_t *buf_end, uint32_t size)
{
const int64_t len = encode_integer(buf_start, buf_end, size, 5);
if (len == -1) {
return -1;
}
buf_start[0] |= 0x20;

return len;
}

//
// [RFC 7541] 5.1. Integer representation
//
Expand Down Expand Up @@ -928,14 +952,25 @@ hpack_decode_header_block(HpackIndexingTable &indexing_table, HTTPHdr *hdr, cons
}

int64_t
hpack_encode_header_block(HpackIndexingTable &indexing_table, uint8_t *out_buf, const size_t out_buf_len, HTTPHdr *hdr)
hpack_encode_header_block(HpackIndexingTable &indexing_table, uint8_t *out_buf, const size_t out_buf_len, HTTPHdr *hdr,
int32_t maximum_table_size)
{
uint8_t *cursor = out_buf;
const uint8_t *const out_buf_end = out_buf + out_buf_len;
int64_t written = 0;

ink_assert(http_hdr_type_get(hdr->m_http) != HTTP_TYPE_UNKNOWN);

// Update dynamic table size
if (maximum_table_size >= 0) {
indexing_table.update_maximum_size(maximum_table_size);
written = encode_dynamic_table_size_update(cursor, out_buf_end, maximum_table_size);
if (written == HPACK_ERROR_COMPRESSION_ERROR) {
return HPACK_ERROR_COMPRESSION_ERROR;
}
cursor += written;
}

MIMEFieldIter field_iter;
for (MIMEField *field = hdr->iter_get_first(&field_iter); field != nullptr; field = hdr->iter_get_next(&field_iter)) {
HpackField field_type;
Expand Down Expand Up @@ -977,3 +1012,9 @@ hpack_encode_header_block(HpackIndexingTable &indexing_table, uint8_t *out_buf,
}
return cursor - out_buf;
}

int32_t
hpack_get_maximum_table_size(HpackIndexingTable &indexing_table)
{
return indexing_table.maximum_size();
}
6 changes: 5 additions & 1 deletion proxy/http2/HPACK.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ class HpackDynamicTable
const MIMEField *get_header_field(uint32_t index) const;
void add_header_field(const MIMEField *field);

uint32_t maximum_size() const;
uint32_t size() const;
bool update_maximum_size(uint32_t new_size);

Expand All @@ -146,6 +147,7 @@ class HpackIndexingTable
int get_header_field(uint32_t index, MIMEFieldWrapper &header_field) const;

void add_header_field(const MIMEField *field);
uint32_t maximum_size() const;
uint32_t size() const;
bool update_maximum_size(uint32_t new_size);

Expand Down Expand Up @@ -173,6 +175,8 @@ int64_t update_dynamic_table_size(const uint8_t *buf_start, const uint8_t *buf_e
typedef HpackIndexingTable HpackHandle;
int64_t hpack_decode_header_block(HpackHandle &handle, HTTPHdr *hdr, const uint8_t *in_buf, const size_t in_buf_len,
uint32_t max_header_size);
int64_t hpack_encode_header_block(HpackHandle &handle, uint8_t *out_buf, const size_t out_buf_len, HTTPHdr *hdr);
int64_t hpack_encode_header_block(HpackHandle &handle, uint8_t *out_buf, const size_t out_buf_len, HTTPHdr *hdr,
int32_t maximum_table_size = -1);
int32_t hpack_get_maximum_table_size(HpackHandle &handle);

#endif /* __HPACK_H__ */
16 changes: 12 additions & 4 deletions proxy/http2/HTTP2.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ const unsigned HTTP2_LEN_AUTHORITY = countof(":authority") - 1;
const unsigned HTTP2_LEN_PATH = countof(":path") - 1;
const unsigned HTTP2_LEN_STATUS = countof(":status") - 1;

static size_t HTTP2_LEN_STATUS_VALUE_STR = 3;
static size_t HTTP2_LEN_STATUS_VALUE_STR = 3;
static const int HTTP2_MAX_TABLE_SIZE_LIMIT = 64 * 1024;

// Statistics
RecRawStatBlock *http2_rsb;
Expand Down Expand Up @@ -597,10 +598,17 @@ http2_generate_h2_header_from_1_1(HTTPHdr *headers, HTTPHdr *h2_headers)
}

Http2ErrorCode
http2_encode_header_blocks(HTTPHdr *in, uint8_t *out, uint32_t out_len, uint32_t *len_written, HpackHandle &handle)
{
http2_encode_header_blocks(HTTPHdr *in, uint8_t *out, uint32_t out_len, uint32_t *len_written, HpackHandle &handle,
int32_t maximum_table_size)
{
// Limit the maximum table size to 64kB, which is the size advertised by major clients
maximum_table_size = min(maximum_table_size, HTTP2_MAX_TABLE_SIZE_LIMIT);
// Set maximum table size only if it is different from current maximum size
if (maximum_table_size == hpack_get_maximum_table_size(handle)) {
maximum_table_size = -1;
}
// TODO: It would be better to split Cookie header value
int64_t result = hpack_encode_header_block(handle, out, out_len, in);
int64_t result = hpack_encode_header_block(handle, out, out_len, in, maximum_table_size);
if (result < 0) {
return Http2ErrorCode::HTTP2_ERROR_COMPRESSION_ERROR;
}
Expand Down
2 changes: 1 addition & 1 deletion proxy/http2/HTTP2.h
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ bool http2_parse_window_update(IOVec, uint32_t &);

Http2ErrorCode http2_decode_header_blocks(HTTPHdr *, const uint8_t *, const uint32_t, uint32_t *, HpackHandle &, bool &);

Http2ErrorCode http2_encode_header_blocks(HTTPHdr *, uint8_t *, uint32_t, uint32_t *, HpackHandle &);
Http2ErrorCode http2_encode_header_blocks(HTTPHdr *, uint8_t *, uint32_t, uint32_t *, HpackHandle &, int32_t);

ParseResult http2_convert_header_from_2_to_1_1(HTTPHdr *);
void http2_generate_h2_header_from_1_1(HTTPHdr *headers, HTTPHdr *h2_headers);
Expand Down
6 changes: 4 additions & 2 deletions proxy/http2/Http2ConnectionState.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1324,7 +1324,8 @@ Http2ConnectionState::send_headers_frame(Http2Stream *stream)
h2_hdr.destroy();
return;
}
Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle));
Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle),
client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
h2_hdr.destroy();
ats_free(buf);
Expand Down Expand Up @@ -1413,7 +1414,8 @@ Http2ConnectionState::send_push_promise_frame(Http2Stream *stream, URL &url)
h2_hdr.destroy();
return;
}
Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle));
Http2ErrorCode result = http2_encode_header_blocks(&h2_hdr, buf, buf_len, &header_blocks_size, *(this->remote_hpack_handle),
client_settings.get(HTTP2_SETTINGS_HEADER_TABLE_SIZE));
if (result != Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
h2_hdr.destroy();
ats_free(buf);
Expand Down