You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by ma...@apache.org on 2019/02/05 05:16:00 UTC
[trafficserver] branch quic-latest updated: Check decoded header
list size on QPACK
This is an automated email from the ASF dual-hosted git repository.
masaori pushed a commit to branch quic-latest
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/quic-latest by this push:
new 90e1bca Check decoded header list size on QPACK
90e1bca is described below
commit 90e1bca570574ef1d2179b8669e5fe90ce29a777
Author: Masaori Koshiba <ma...@apache.org>
AuthorDate: Tue Feb 5 14:13:47 2019 +0900
Check decoded header list size on QPACK
---
proxy/http3/Http3.cc | 6 ++++
proxy/http3/Http3.h | 5 +++
proxy/http3/Http3App.cc | 31 +++++++++++++------
proxy/http3/Http3App.h | 6 +++-
proxy/http3/Http3ClientSession.cc | 4 +--
proxy/http3/QPACK.cc | 65 ++++++++++++++++++++++++++++++---------
proxy/http3/QPACK.h | 29 ++++++++++-------
7 files changed, 109 insertions(+), 37 deletions(-)
diff --git a/proxy/http3/Http3.cc b/proxy/http3/Http3.cc
index 74f811b..ce88558 100644
--- a/proxy/http3/Http3.cc
+++ b/proxy/http3/Http3.cc
@@ -23,6 +23,12 @@
#include "Http3.h"
+// Default values of settings defined by specs (draft-17)
+const uint32_t HTTP3_DEFAULT_HEADER_TABLE_SIZE = 0;
+const uint32_t HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE = UINT32_MAX;
+const uint32_t HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS = 0;
+const uint32_t HTTP3_DEFAULT_NUM_PLACEHOLDERS = 0;
+
RecRawStatBlock *http3_rsb;
void
diff --git a/proxy/http3/Http3.h b/proxy/http3/Http3.h
index b3da732..f390e06 100644
--- a/proxy/http3/Http3.h
+++ b/proxy/http3/Http3.h
@@ -27,6 +27,11 @@
#include "records/I_RecDefs.h"
#include "records/I_RecProcess.h"
+extern const uint32_t HTTP3_DEFAULT_HEADER_TABLE_SIZE;
+extern const uint32_t HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE;
+extern const uint32_t HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS;
+extern const uint32_t HTTP3_DEFAULT_NUM_PLACEHOLDERS;
+
extern RecRawStatBlock *http3_rsb; // Container for statistics.
class Http3
diff --git a/proxy/http3/Http3App.cc b/proxy/http3/Http3App.cc
index 7369908..e4bde93 100644
--- a/proxy/http3/Http3App.cc
+++ b/proxy/http3/Http3App.cc
@@ -34,12 +34,6 @@
static constexpr char tag[] = "http3";
static constexpr char tag_v[] = "v_http3";
-// Default values of settings defined by specs.
-static constexpr uint32_t HTTP3_DEFAULT_HEADER_TABLE_SIZE = 0;
-static constexpr uint32_t HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE = UINT32_MAX;
-static constexpr uint32_t HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS = 0;
-static constexpr uint32_t HTTP3_DEFAULT_NUM_PLACEHOLDERS = 0;
-
Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl) : QUICApplication(client_vc)
{
this->_client_session = new Http3ClientSession(client_vc);
@@ -48,7 +42,7 @@ Http3App::Http3App(QUICNetVConnection *client_vc, IpAllow::ACL session_acl) : QU
this->_qc->stream_manager()->set_default_application(this);
- this->_settings_handler = new Http3SettingsHandler();
+ this->_settings_handler = new Http3SettingsHandler(this->_client_session);
this->_control_stream_dispatcher.add_handler(this->_settings_handler);
this->_settings_framer = new Http3SettingsFramer();
@@ -294,13 +288,32 @@ Http3SettingsHandler::handle_frame(std::shared_ptr<const Http3Frame> frame)
return Http3ErrorUPtr(new Http3NoError());
}
+ // TODO: Add length check: the maximum number of values are 2^62 - 1, but some fields have shorter maximum than it.
+ if (settings_frame->contains(Http3SettingsId::HEADER_TABLE_SIZE)) {
+ uint64_t header_table_size = settings_frame->get(Http3SettingsId::HEADER_TABLE_SIZE);
+ this->_session->remote_qpack()->update_max_table_size(header_table_size);
+
+ Debug("http3", "SETTINGS_HEADER_TABLE_SIZE: %" PRId64, header_table_size);
+ }
+
if (settings_frame->contains(Http3SettingsId::MAX_HEADER_LIST_SIZE)) {
- uint64_t header_list_size = settings_frame->get(Http3SettingsId::MAX_HEADER_LIST_SIZE);
- Debug("http3", "SETTINGS_MAX_HEADER_LIST_SIZE: %" PRId64, header_list_size);
+ uint64_t max_header_list_size = settings_frame->get(Http3SettingsId::MAX_HEADER_LIST_SIZE);
+ this->_session->remote_qpack()->update_max_header_list_size(max_header_list_size);
+
+ Debug("http3", "SETTINGS_MAX_HEADER_LIST_SIZE: %" PRId64, max_header_list_size);
+ }
+
+ if (settings_frame->contains(Http3SettingsId::QPACK_BLOCKED_STREAMS)) {
+ uint64_t qpack_blocked_streams = settings_frame->get(Http3SettingsId::QPACK_BLOCKED_STREAMS);
+ this->_session->remote_qpack()->update_max_blocking_streams(qpack_blocked_streams);
+
+ Debug("http3", "SETTINGS_QPACK_BLOCKED_STREAMS: %" PRId64, qpack_blocked_streams);
}
if (settings_frame->contains(Http3SettingsId::NUM_PLACEHOLDERS)) {
uint64_t num_placeholders = settings_frame->get(Http3SettingsId::NUM_PLACEHOLDERS);
+ // TODO: update settings for priority tree
+
Debug("http3", "SETTINGS_NUM_PLACEHOLDERS: %" PRId64, num_placeholders);
}
diff --git a/proxy/http3/Http3App.h b/proxy/http3/Http3App.h
index 49e0e07..959ad2e 100644
--- a/proxy/http3/Http3App.h
+++ b/proxy/http3/Http3App.h
@@ -77,11 +77,15 @@ private:
class Http3SettingsHandler : public Http3FrameHandler
{
public:
- Http3SettingsHandler(){};
+ Http3SettingsHandler(Http3ClientSession *session) : _session(session){};
// Http3FrameHandler
std::vector<Http3FrameType> interests() override;
Http3ErrorUPtr handle_frame(std::shared_ptr<const Http3Frame> frame) override;
+
+private:
+ // TODO: clarify Http3ClientSession I/F for Http3SettingsHandler and Http3App
+ Http3ClientSession *_session = nullptr;
};
class Http3SettingsFramer : public Http3FrameGenerator
diff --git a/proxy/http3/Http3ClientSession.cc b/proxy/http3/Http3ClientSession.cc
index c5c04b2..0b8e294 100644
--- a/proxy/http3/Http3ClientSession.cc
+++ b/proxy/http3/Http3ClientSession.cc
@@ -25,8 +25,8 @@
Http3ClientSession::Http3ClientSession(NetVConnection *vc) : _client_vc(vc)
{
- this->_local_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc), 0, 0);
- this->_remote_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc), 0, 0);
+ this->_local_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc));
+ this->_remote_qpack = new QPACK(static_cast<QUICNetVConnection *>(vc));
}
Http3ClientSession::~Http3ClientSession()
diff --git a/proxy/http3/QPACK.cc b/proxy/http3/QPACK.cc
index 8193dcb..bd8f51d 100644
--- a/proxy/http3/QPACK.cc
+++ b/proxy/http3/QPACK.cc
@@ -132,9 +132,10 @@ const QPACK::Header QPACK::StaticTable::STATIC_HEADER_FIELDS[] = {
{"x-frame-options", "deny"},
{"x-frame-options", "sameorigin"}};
-QPACK::QPACK(QUICConnection *qc, uint16_t max_table_size, uint16_t max_blocking_streams)
+QPACK::QPACK(QUICConnection *qc, uint32_t max_header_list_size, uint16_t max_table_size, uint16_t max_blocking_streams)
: QUICApplication(qc),
_dynamic_table(max_table_size),
+ _max_header_list_size(max_header_list_size),
_max_table_size(max_table_size),
_max_blocking_streams(max_blocking_streams)
{
@@ -267,6 +268,24 @@ QPACK::set_decoder_stream(QUICStreamIO *stream_io)
this->set_stream(stream_io);
}
+void
+QPACK::update_max_header_list_size(uint32_t max_header_list_size)
+{
+ this->_max_header_list_size = max_header_list_size;
+}
+
+void
+QPACK::update_max_table_size(uint16_t max_table_size)
+{
+ this->_max_table_size = max_table_size;
+}
+
+void
+QPACK::update_max_blocking_streams(uint16_t max_blocking_streams)
+{
+ this->_max_blocking_streams = max_blocking_streams;
+}
+
int
QPACK::_encode_prefix(uint16_t largest_reference, uint16_t base_index, IOBufferBlock *prefix)
{
@@ -615,7 +634,7 @@ QPACK::_encode_literal_header_field_with_postbase_name_ref(uint16_t index, uint1
}
int
-QPACK::_decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr)
+QPACK::_decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr, uint32_t &header_len)
{
// Read index field
int len = 0;
@@ -644,9 +663,8 @@ QPACK::_decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size
}
// Create and attach a header
- MIMEField *new_field = hdr.field_create(name, name_len);
- new_field->value_set(hdr.m_heap, hdr.m_mime, value, value_len);
- hdr.field_attach(new_field);
+ 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);
@@ -655,7 +673,8 @@ QPACK::_decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size
}
int
-QPACK::_decode_literal_header_field_with_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr)
+QPACK::_decode_literal_header_field_with_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len)
{
int read_len = 0;
@@ -701,6 +720,7 @@ QPACK::_decode_literal_header_field_with_name_ref(int16_t base_index, const uint
// Create and attach a header
this->_attach_header(hdr, name, name_len, value, value_len, never_index);
+ 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);
@@ -709,7 +729,7 @@ QPACK::_decode_literal_header_field_with_name_ref(int16_t base_index, const uint
}
int
-QPACK::_decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t buf_len, HTTPHdr &hdr)
+QPACK::_decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t buf_len, HTTPHdr &hdr, uint32_t &header_len)
{
int read_len = 0;
@@ -738,6 +758,7 @@ QPACK::_decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t
// Create and attach a header
this->_attach_header(hdr, name, name_len, value, value_len, never_index);
+ header_len = name_len + value_len;
QPACKDebug("Decoded Literal Header Field Without Name Ref: name=%.*s, value=%.*s", static_cast<uint16_t>(name_len), name,
static_cast<uint16_t>(value_len), value);
@@ -746,7 +767,8 @@ QPACK::_decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t
}
int
-QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr)
+QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len)
{
// Read index field
int len = 0;
@@ -772,6 +794,7 @@ QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, cons
// Create and attach a header
this->_attach_header(hdr, name, name_len, value, value_len, false);
+ 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);
@@ -780,7 +803,8 @@ QPACK::_decode_indexed_header_field_with_postbase_index(int16_t base_index, cons
}
int
-QPACK::_decode_literal_header_field_with_postbase_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr)
+QPACK::_decode_literal_header_field_with_postbase_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len)
{
int read_len = 0;
@@ -822,6 +846,7 @@ QPACK::_decode_literal_header_field_with_postbase_name_ref(int16_t base_index, c
// Create and attach a header
this->_attach_header(hdr, name, name_len, value, value_len, never_index);
+ 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);
@@ -859,22 +884,34 @@ QPACK::_decode_header(const uint8_t *header_block, size_t header_block_len, HTTP
}
pos += ret;
+ uint32_t decoded_header_list_size = 0;
+
// Decode Instructions
while (pos < header_block + header_block_len) {
+ uint32_t header_len = 0;
+
if (pos[0] & 0x80) { // Index Header Field
- ret = this->_decode_indexed_header_field(base_index, pos, remain_len, hdr);
+ ret = this->_decode_indexed_header_field(base_index, pos, remain_len, hdr, header_len);
} else if (pos[0] & 0x40) { // Literal Header Field With Name Reference
- ret = this->_decode_literal_header_field_with_name_ref(base_index, pos, remain_len, hdr);
+ ret = this->_decode_literal_header_field_with_name_ref(base_index, pos, remain_len, hdr, header_len);
} else if (pos[0] & 0x20) { // Literal Header Field Without Name Reference
- ret = this->_decode_literal_header_field_without_name_ref(pos, remain_len, hdr);
+ ret = this->_decode_literal_header_field_without_name_ref(pos, remain_len, hdr, header_len);
} else if (pos[0] & 0x10) { // Indexed Header Field With Post-Base Index
- ret = this->_decode_indexed_header_field_with_postbase_index(base_index, pos, remain_len, hdr);
+ ret = this->_decode_indexed_header_field_with_postbase_index(base_index, pos, remain_len, hdr, header_len);
} else { // Literal Header Field With Post-Base Name Reference
- ret = this->_decode_literal_header_field_with_postbase_name_ref(base_index, pos, remain_len, hdr);
+ ret = this->_decode_literal_header_field_with_postbase_name_ref(base_index, pos, remain_len, hdr, header_len);
}
+
if (ret < 0) {
break;
}
+
+ decoded_header_list_size += header_len;
+ if (decoded_header_list_size > this->_max_header_list_size) {
+ ret = -2;
+ break;
+ }
+
pos += ret;
}
diff --git a/proxy/http3/QPACK.h b/proxy/http3/QPACK.h
index 68c67ac..54c3c2b 100644
--- a/proxy/http3/QPACK.h
+++ b/proxy/http3/QPACK.h
@@ -29,6 +29,8 @@
#include "MIME.h"
#include "QUICApplication.h"
+#include "Http3.h"
+
class HTTPHdr;
enum {
@@ -36,15 +38,12 @@ enum {
QPACK_EVENT_DECODE_FAILED,
};
-// FIXME This setting should be passed by HTTP/3
-constexpr int SETTINGS_HEADER_TABLE_SIZE = 0;
-constexpr int SETTINGS_QPACK_BLOCKED_STREAMS = 0;
-
class QPACK : public QUICApplication
{
public:
- QPACK(QUICConnection *qc, uint16_t max_table_size = SETTINGS_HEADER_TABLE_SIZE,
- uint16_t max_blocking_streams = SETTINGS_QPACK_BLOCKED_STREAMS);
+ QPACK(QUICConnection *qc, uint32_t max_header_list_size = HTTP3_DEFAULT_MAX_HEADER_LIST_SIZE,
+ uint16_t max_table_size = HTTP3_DEFAULT_HEADER_TABLE_SIZE,
+ uint16_t max_blocking_streams = HTTP3_DEFAULT_QPACK_BLOCKED_STREAMS);
virtual ~QPACK();
int event_handler(int event, Event *data);
@@ -68,6 +67,10 @@ public:
void set_encoder_stream(QUICStreamIO *stream_io);
void set_decoder_stream(QUICStreamIO *stream_io);
+ void update_max_header_list_size(uint32_t max_header_list_size);
+ void update_max_table_size(uint16_t max_table_size);
+ void update_max_blocking_streams(uint16_t max_blocking_streams);
+
static size_t estimate_header_block_size(const HTTPHdr &header_set);
private:
@@ -241,6 +244,7 @@ private:
DynamicTable _dynamic_table;
std::map<uint64_t, struct EntryReference> _references;
+ uint32_t _max_header_list_size = 0;
uint16_t _max_table_size = 0;
uint16_t _max_blocking_streams = 0;
@@ -295,11 +299,14 @@ private:
void _decode(EThread *ethread, Continuation *cont, uint64_t stream_id, const uint8_t *header_block, size_t header_block_len,
HTTPHdr &hdr);
int _decode_header(const uint8_t *header_block, size_t header_block_len, HTTPHdr &hdr);
- int _decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr);
- int _decode_indexed_header_field_with_postbase_index(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr);
- int _decode_literal_header_field_with_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr);
- int _decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t buf_len, HTTPHdr &hdr);
- int _decode_literal_header_field_with_postbase_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr);
+ int _decode_indexed_header_field(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr, uint32_t &header_len);
+ int _decode_indexed_header_field_with_postbase_index(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len);
+ int _decode_literal_header_field_with_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len);
+ int _decode_literal_header_field_without_name_ref(const uint8_t *buf, size_t buf_len, HTTPHdr &hdr, uint32_t &header_len);
+ int _decode_literal_header_field_with_postbase_name_ref(int16_t base_index, const uint8_t *buf, size_t buf_len, HTTPHdr &hdr,
+ uint32_t &header_len);
// Utilities
uint16_t _calc_absolute_index_from_relative_index(uint16_t base_index, uint16_t relative_index);