Repository: trafficserver Updated Branches: refs/heads/master 4ace71932 -> 2a84c6b9f
TS-2729: update HTTP/2 to h2-14 draft Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/fc1ea62c Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/fc1ea62c Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/fc1ea62c Branch: refs/heads/master Commit: fc1ea62c1e7edfd93c8f21f707834eaf032a034f Parents: 4ace719 Author: Ryo Okubo <[email protected]> Authored: Fri Oct 3 13:41:29 2014 -0700 Committer: James Peach <[email protected]> Committed: Fri Oct 3 13:53:52 2014 -0700 ---------------------------------------------------------------------- lib/records/RecHttp.cc | 2 +- proxy/http2/HTTP2.cc | 47 ++++++++++++++++++++------------ proxy/http2/HTTP2.h | 17 ++++++------ proxy/http2/Http2ConnectionState.cc | 37 ++++++++++++++----------- 4 files changed, 61 insertions(+), 42 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fc1ea62c/lib/records/RecHttp.cc ---------------------------------------------------------------------- diff --git a/lib/records/RecHttp.cc b/lib/records/RecHttp.cc index 4e62bb2..788b864 100644 --- a/lib/records/RecHttp.cc +++ b/lib/records/RecHttp.cc @@ -36,7 +36,7 @@ SessionProtocolNameRegistry globalSessionProtocolNameRegistry; const char * const TS_NPN_PROTOCOL_HTTP_0_9 = "http/0.9"; const char * const TS_NPN_PROTOCOL_HTTP_1_0 = "http/1.0"; const char * const TS_NPN_PROTOCOL_HTTP_1_1 = "http/1.1"; -const char * const TS_NPN_PROTOCOL_HTTP_2_0 = "h2-12"; // draft-ietf-httpbis-http2-12 +const char * const TS_NPN_PROTOCOL_HTTP_2_0 = "h2-14"; // draft-ietf-httpbis-http2-14 const char * const TS_NPN_PROTOCOL_SPDY_1 = "spdy/1"; // obsolete const char * const TS_NPN_PROTOCOL_SPDY_2 = "spdy/2"; const char * const TS_NPN_PROTOCOL_SPDY_3 = "spdy/3"; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fc1ea62c/proxy/http2/HTTP2.cc ---------------------------------------------------------------------- diff --git a/proxy/http2/HTTP2.cc b/proxy/http2/HTTP2.cc index 567fc3c..59b1e0f 100644 --- a/proxy/http2/HTTP2.cc +++ b/proxy/http2/HTTP2.cc @@ -52,6 +52,8 @@ write_and_advance(byte_pointer& dst, uint32_t src) dst.u8 += sizeof(pval.bytes); } +// Avoid a [-Werror,-Wunused-function] error until we need this overload ... +#if 0 static void write_and_advance(byte_pointer& dst, uint16_t src) { @@ -61,6 +63,7 @@ write_and_advance(byte_pointer& dst, uint16_t src) memcpy(dst.u8, pval.bytes, sizeof(pval.bytes)); dst.u8 += sizeof(pval.bytes); } +#endif static void write_and_advance(byte_pointer& dst, uint8_t src) @@ -127,13 +130,14 @@ bool http2_settings_parameter_is_valid(const Http2SettingsParameter& param) { // Static maximum values for Settings parameters. - static const unsigned settings_max[HTTP2_SETTINGS_MAX] = { + static const uint32_t settings_max[HTTP2_SETTINGS_MAX] = { 0, UINT_MAX, // HTTP2_SETTINGS_HEADER_TABLE_SIZE 1, // HTTP2_SETTINGS_ENABLE_PUSH UINT_MAX, // HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS HTTP2_MAX_WINDOW_SIZE, // HTTP2_SETTINGS_INITIAL_WINDOW_SIZE - 1, // HTTP2_SETTINGS_COMPRESS_DATA + 16777215, // HTTP2_SETTINGS_MAX_FRAME_SIZE + UINT_MAX, // HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE }; if (param.id == 0 || param.id >= HTTP2_SETTINGS_MAX) { @@ -149,13 +153,15 @@ http2_settings_parameter_is_valid(const Http2SettingsParameter& param) // 4.1. Frame Format // -// 0 1 2 3 -// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | R | Length (14) | Type (8) | Flags (8) | +// | Length (24) | +// +---------------+---------------+---------------+ +// | Type (8) | Flags (8) | // +-+-+-----------+---------------+-------------------------------+ // |R| Stream Identifier (31) | -// +-+-------------------------------------------------------------+ +// +=+=============================================================+ // | Frame Payload (0...) ... // +---------------------------------------------------------------+ @@ -163,21 +169,20 @@ bool http2_parse_frame_header(IOVec iov, Http2FrameHeader& hdr) { byte_pointer ptr(iov.iov_base); - byte_addressable_value<uint16_t> length; + byte_addressable_value<uint32_t> length_and_type; byte_addressable_value<uint32_t> streamid; if (unlikely(iov.iov_len < HTTP2_FRAME_HEADER_LEN)) { return false; } - memcpy_and_advance(length.bytes, ptr); - memcpy_and_advance(hdr.type, ptr); + memcpy_and_advance(length_and_type.bytes, ptr); memcpy_and_advance(hdr.flags, ptr); memcpy_and_advance(streamid.bytes, ptr); - length.bytes[0] &= 0x3F; // Clear the 2 reserved high bits + hdr.length = ntohl(length_and_type.value) >> 8; + hdr.type = ntohl(length_and_type.value) & 0xff; streamid.bytes[0] &= 0x7f;// Clear the high reserved bit - hdr.length = ntohs(length.value); hdr.streamid = ntohl(streamid.value); return true; @@ -192,7 +197,13 @@ http2_write_frame_header(const Http2FrameHeader& hdr, IOVec iov) return false; } - write_and_advance(ptr, hdr.length); + byte_addressable_value<uint32_t> length; + length.value = htonl(hdr.length); + // MSB length.bytes[0] is unused. + write_and_advance(ptr, length.bytes[1]); + write_and_advance(ptr, length.bytes[2]); + write_and_advance(ptr, length.bytes[3]); + write_and_advance(ptr, hdr.type); write_and_advance(ptr, hdr.flags); write_and_advance(ptr, hdr.streamid); @@ -232,24 +243,26 @@ http2_write_goaway(const Http2Goaway& goaway, IOVec iov) // 0 1 2 3 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -// | Identifier (8)| Value (32) | -// +---------------+-----------------------------------------------+ -// | | -// +---------------+ +// | Identifier (16) | +// +-------------------------------+-------------------------------+ +// | Value (32) | +// +---------------------------------------------------------------+ bool http2_parse_settings_parameter(IOVec iov, Http2SettingsParameter& param) { byte_pointer ptr(iov.iov_base); + byte_addressable_value<uint16_t> pid; byte_addressable_value<uint32_t> pval; if (unlikely(iov.iov_len < HTTP2_SETTINGS_PARAMETER_LEN)) { return false; } - memcpy_and_advance(param.id, ptr); + memcpy_and_advance(pid.bytes, ptr); memcpy_and_advance(pval.bytes, ptr); + param.id = ntohs(pid.value); param.value = ntohl(pval.value); return true; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fc1ea62c/proxy/http2/HTTP2.h ---------------------------------------------------------------------- diff --git a/proxy/http2/HTTP2.h b/proxy/http2/HTTP2.h index c7c2fec..306d69d 100644 --- a/proxy/http2/HTTP2.h +++ b/proxy/http2/HTTP2.h @@ -36,9 +36,9 @@ typedef int32_t Http2WindowSize; extern const char * const HTTP2_CONNECTION_PREFACE; const size_t HTTP2_CONNECTION_PREFACE_LEN = 24; -const size_t HTTP2_FRAME_HEADER_LEN = 8; +const size_t HTTP2_FRAME_HEADER_LEN = 9; const size_t HTTP2_GOAWAY_LEN = 8; -const size_t HTTP2_SETTINGS_PARAMETER_LEN = 5; +const size_t HTTP2_SETTINGS_PARAMETER_LEN = 6; // 4.2. Frame Size. The absolute maximum size of a frame payload is 2^14-1 (16,383) octets. const size_t HTTP2_MAX_FRAME_PAYLOAD = 16383; @@ -183,7 +183,8 @@ enum Http2SettingsIdentifier HTTP2_SETTINGS_ENABLE_PUSH = 2, HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS = 3, HTTP2_SETTINGS_INITIAL_WINDOW_SIZE = 4, - HTTP2_SETTINGS_COMPRESS_DATA = 5, + HTTP2_SETTINGS_MAX_FRAME_SIZE = 5, + HTTP2_SETTINGS_MAX_HEADER_LIST_SIZE = 6, HTTP2_SETTINGS_MAX }; @@ -191,16 +192,16 @@ enum Http2SettingsIdentifier // 4.1. Frame Format struct Http2FrameHeader { - uint16_t length; - uint8_t type; - uint8_t flags; - Http2StreamId streamid; + uint32_t length; + uint8_t type; + uint8_t flags; + Http2StreamId streamid; }; // 6.5.1. SETTINGS Format struct Http2SettingsParameter { - uint8_t id; + uint16_t id; uint32_t value; }; http://git-wip-us.apache.org/repos/asf/trafficserver/blob/fc1ea62c/proxy/http2/Http2ConnectionState.cc ---------------------------------------------------------------------- diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index afbbceb..cb9640e 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -30,6 +30,22 @@ typedef Http2ErrorCode (*http2_frame_dispatch)(Http2ClientSession&, Http2ConnectionState&, const Http2Frame&); +static const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = +{ + -1, // HTTP2_FRAME_TYPE_DATA + -1, // HTTP2_FRAME_TYPE_HEADERS + -1, // HTTP2_FRAME_TYPE_PRIORITY + -1, // HTTP2_FRAME_TYPE_RST_STREAM + BUFFER_SIZE_INDEX_128, // HTTP2_FRAME_TYPE_SETTINGS + -1, // HTTP2_FRAME_TYPE_PUSH_PROMISE + -1, // HTTP2_FRAME_TYPE_PING + BUFFER_SIZE_INDEX_128, // HTTP2_FRAME_TYPE_GOAWAY + -1, // HTTP2_FRAME_TYPE_WINDOW_UPDATE + -1, // HTTP2_FRAME_TYPE_CONTINUATION + -1, // HTTP2_FRAME_TYPE_ALTSVC + -1, // HTTP2_FRAME_TYPE_BLOCKED +}; + static Http2ErrorCode rcv_settings_frame(Http2ClientSession& cs, Http2ConnectionState& cstate, const Http2Frame& frame) { @@ -69,25 +85,14 @@ rcv_settings_frame(Http2ClientSession& cs, Http2ConnectionState& cstate, const H cstate.client_settings.set((Http2SettingsIdentifier)param.id, param.value); } + // 6.5 Once all values have been applied, the recipient MUST immediately emit a + // SETTINGS frame with the ACK flag set. + Http2Frame ackFrame(HTTP2_FRAME_TYPE_SETTINGS, 0, HTTP2_FLAGS_SETTINGS_ACK); + cstate.ua_session->handleEvent(HTTP2_SESSION_EVENT_XMIT, &ackFrame); + return HTTP2_ERROR_NO_ERROR; } -static const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = -{ - -1, // HTTP2_FRAME_TYPE_DATA - -1, // HTTP2_FRAME_TYPE_HEADERS - -1, // HTTP2_FRAME_TYPE_PRIORITY - -1, // HTTP2_FRAME_TYPE_RST_STREAM - -1, // HTTP2_FRAME_TYPE_SETTINGS - -1, // HTTP2_FRAME_TYPE_PUSH_PROMISE - -1, // HTTP2_FRAME_TYPE_PING - BUFFER_SIZE_INDEX_128, // HTTP2_FRAME_TYPE_GOAWAY - -1, // HTTP2_FRAME_TYPE_WINDOW_UPDATE - -1, // HTTP2_FRAME_TYPE_CONTINUATION - -1, // HTTP2_FRAME_TYPE_ALTSVC - -1, // HTTP2_FRAME_TYPE_BLOCKED -}; - static const http2_frame_dispatch frame_handlers[HTTP2_FRAME_TYPE_MAX] = { NULL, // HTTP2_FRAME_TYPE_DATA
