Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Unified Diff: net/spdy/spdy_framer.cc

Issue 290003006: Land recent SPDY changes (through 67282679) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase on nullptr => NULL Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/spdy/spdy_framer.cc
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
index 73aa53299ce8bc418cd8a4f8909e7e4d861217ee..79a529f5724f172ffb4d9e07718dbd3087f8582c 100644
--- a/net/spdy/spdy_framer.cc
+++ b/net/spdy/spdy_framer.cc
@@ -13,6 +13,7 @@
#include "net/spdy/spdy_bitmasks.h"
#include "third_party/zlib/zlib.h"
+using base::StringPiece;
using std::string;
using std::vector;
@@ -50,7 +51,6 @@ const uint8 kNoFlags = 0;
const SpdyStreamId SpdyFramer::kInvalidStream = -1;
const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024;
-// The size of the control frame buffer. Must be >= the minimum size of the
// largest control frame, which is SYN_STREAM. See GetSynStreamMinimumSize() for
// calculation details.
const size_t SpdyFramer::kControlFrameBufferSize = 18;
@@ -109,6 +109,9 @@ void SettingsFlagsAndId::ConvertFlagsAndIdForSpdy2(uint32* val) {
std::swap(wire_array[1], wire_array[2]);
}
+SpdyAltSvcScratch::SpdyAltSvcScratch() { Reset(); }
+SpdyAltSvcScratch::~SpdyAltSvcScratch() {}
+
bool SpdyFramerVisitorInterface::OnGoAwayFrameData(const char* goaway_data,
size_t len) {
return true;
@@ -134,12 +137,6 @@ SpdyFramer::SpdyFramer(SpdyMajorVersion version)
DCHECK_GE(spdy_version_, SPDY_MIN_VERSION);
DCHECK_LE(spdy_version_, SPDY_MAX_VERSION);
Reset();
-
- // SPDY4 and up use HPACK. Allocate instances for these protocol versions.
- if (spdy_version_ > SPDY3) {
- hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
- hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
- }
}
SpdyFramer::~SpdyFramer() {
@@ -163,6 +160,7 @@ void SpdyFramer::Reset() {
current_frame_length_ = 0;
current_frame_stream_id_ = kInvalidStream;
settings_scratch_.Reset();
+ altsvc_scratch_.Reset();
remaining_padding_payload_length_ = 0;
remaining_padding_length_fields_ = 0;
}
@@ -307,12 +305,28 @@ size_t SpdyFramer::GetPushPromiseMinimumSize() const {
return GetControlFrameHeaderSize() + 4;
}
-size_t SpdyFramer::GetContinuationMinimumSize() const {
+size_t SpdyFramer::GetContinuationMinimumSize() const {
// Size, in bytes, of a CONTINUATION frame not including the variable-length
// headers fragments.
return GetControlFrameHeaderSize();
}
+size_t SpdyFramer::GetAltSvcMinimumSize() const {
+ // Size, in bytes, of an ALTSVC frame not including the Protocol-ID, Host, and
+ // (optional) Origin fields, all of which can vary in length.
+ // Note that this gives a lower bound on the frame size rather than a true
+ // minimum; the actual frame should always be larger than this.
+ // Calculated as frame prefix + 4 (max-age) + 2 (port) + 1 (reserved byte)
+ // + 1 (pid_len) + 1 (host_len).
+ return GetControlFrameHeaderSize() + 9;
+}
+
+size_t SpdyFramer::GetPrioritySize() const {
+ // Size, in bytes, of a PRIORITY frame.
+ // Calculated as frame prefix + 4 (stream dependency) + 1 (weight)
+ return GetControlFrameHeaderSize() + 5;
+}
+
size_t SpdyFramer::GetFrameMinimumSize() const {
return std::min(GetDataFrameMinimumSize(), GetControlFrameHeaderSize());
}
@@ -359,6 +373,8 @@ const char* SpdyFramer::StateToString(int state) {
return "SPDY_RST_STREAM_FRAME_PAYLOAD";
case SPDY_SETTINGS_FRAME_PAYLOAD:
return "SPDY_SETTINGS_FRAME_PAYLOAD";
+ case SPDY_ALTSVC_FRAME_PAYLOAD:
+ return "SPDY_ALTSVC_FRAME_PAYLOAD";
}
return "UNKNOWN_STATE";
}
@@ -466,6 +482,10 @@ const char* SpdyFramer::FrameTypeToString(SpdyFrameType type) {
return "PUSH_PROMISE";
case CONTINUATION:
return "CONTINUATION";
+ case ALTSVC:
+ return "ALTSVC";
+ case PRIORITY:
+ return "PRIORITY";
}
return "UNKNOWN_CONTROL_TYPE";
}
@@ -545,6 +565,13 @@ size_t SpdyFramer::ProcessInput(const char* data, size_t len) {
break;
}
+ case SPDY_ALTSVC_FRAME_PAYLOAD: {
+ size_t bytes_read = ProcessAltSvcFramePayload(data, len);
+ len -= bytes_read;
+ data += bytes_read;
+ break;
+ }
+
case SPDY_CONTROL_FRAME_PAYLOAD: {
size_t bytes_read = ProcessControlFramePayload(data, len);
len -= bytes_read;
@@ -902,9 +929,11 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
} else if (protocol_version() <= SPDY3 &&
current_frame_flags_ & ~CONTROL_FLAG_FIN) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 && current_frame_flags_ &
- ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
- HEADERS_FLAG_END_HEADERS)) {
+ } else if (protocol_version() > SPDY3 &&
+ current_frame_flags_ &
+ ~(CONTROL_FLAG_FIN | HEADERS_FLAG_PRIORITY |
+ HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_END_SEGMENT |
+ HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
}
@@ -917,7 +946,9 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
}
break;
case BLOCKED:
- if (current_frame_length_ != GetBlockedSize()) {
+ if (current_frame_length_ != GetBlockedSize() ||
+ protocol_version() <= SPDY3) {
+ // TODO(mlavan): BLOCKED frames are no longer part of SPDY4.
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
@@ -928,8 +959,10 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
set_error(SPDY_INVALID_CONTROL_FRAME);
} else if (protocol_version() <= SPDY3 && current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
- } else if (protocol_version() > SPDY3 && current_frame_flags_ &
- ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE) {
+ } else if (protocol_version() > SPDY3 &&
+ current_frame_flags_ &
+ ~(PUSH_PROMISE_FLAG_END_PUSH_PROMISE |
+ HEADERS_FLAG_PAD_LOW | HEADERS_FLAG_PAD_HIGH)) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
@@ -937,7 +970,24 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
if (current_frame_length_ < GetContinuationMinimumSize() ||
protocol_version() <= SPDY3) {
set_error(SPDY_INVALID_CONTROL_FRAME);
- } else if (current_frame_flags_ & ~HEADERS_FLAG_END_HEADERS) {
+ } else if (current_frame_flags_ &
+ ~(HEADERS_FLAG_END_HEADERS | HEADERS_FLAG_PAD_LOW |
+ HEADERS_FLAG_PAD_HIGH)) {
+ set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
+ }
+ break;
+ case ALTSVC:
+ if (current_frame_length_ <= GetAltSvcMinimumSize()) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ } else if (current_frame_flags_ != 0) {
+ set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
+ }
+ break;
+ case PRIORITY:
+ if (current_frame_length_ != GetPrioritySize() ||
+ protocol_version() <= SPDY3) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ } else if (current_frame_flags_ != 0) {
set_error(SPDY_INVALID_CONTROL_FRAME_FLAGS);
}
break;
@@ -975,6 +1025,10 @@ void SpdyFramer::ProcessControlFrameHeader(uint16 control_frame_type_field) {
return;
}
+ if (current_frame_type_ == ALTSVC) {
+ CHANGE_STATE(SPDY_ALTSVC_FRAME_PAYLOAD);
+ return;
+ }
// Determine the frame size without variable-length data.
int32 frame_size_without_variable_data;
switch (current_frame_type_) {
@@ -1396,7 +1450,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
expect_continuation_ == 0);
}
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
case PUSH_PROMISE:
{
@@ -1427,7 +1481,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
PUSH_PROMISE_FLAG_END_PUSH_PROMISE) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
case CONTINUATION:
{
@@ -1453,7 +1507,7 @@ size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data,
(current_frame_flags_ &
HEADERS_FLAG_END_HEADERS) != 0);
}
- CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ CHANGE_STATE(SPDY_READ_PADDING_LENGTH);
break;
default:
DCHECK(false);
@@ -1479,11 +1533,11 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
current_frame_type_ != CONTINUATION) {
LOG(DFATAL) << "Unhandled frame type in ProcessControlFrameHeaderBlock.";
}
- size_t process_bytes = std::min(data_len, remaining_data_length_);
+ size_t process_bytes = std::min(
+ data_len, remaining_data_length_ - remaining_padding_payload_length_);
if (is_hpack_header_block) {
- if (!hpack_decoder_->HandleControlFrameHeadersData(current_frame_stream_id_,
- data,
- process_bytes)) {
+ if (!GetHpackDecoder()->HandleControlFrameHeadersData(
+ current_frame_stream_id_, data, process_bytes)) {
// TODO(jgraettinger): Finer-grained HPACK error codes.
set_error(SPDY_DECOMPRESS_FAILURE);
processed_successfully = false;
@@ -1500,11 +1554,12 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
remaining_data_length_ -= process_bytes;
// Handle the case that there is no futher data in this frame.
- if (remaining_data_length_ == 0 && processed_successfully) {
+ if (remaining_data_length_ == remaining_padding_payload_length_ &&
+ processed_successfully) {
if (expect_continuation_ == 0) {
if (is_hpack_header_block) {
- if (!hpack_decoder_->HandleControlFrameHeadersComplete(
- current_frame_stream_id_)) {
+ if (!GetHpackDecoder()->HandleControlFrameHeadersComplete(
+ current_frame_stream_id_)) {
set_error(SPDY_DECOMPRESS_FAILURE);
processed_successfully = false;
} else {
@@ -1520,14 +1575,10 @@ size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data,
// OnControlFrameHeaderData() to indicate this.
visitor_->OnControlFrameHeaderData(current_frame_stream_id_, NULL, 0);
}
- // If this is a FIN, tell the caller.
- if ((current_frame_flags_ & CONTROL_FLAG_FIN) || end_stream_when_done_) {
- end_stream_when_done_ = false;
- visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
- }
}
- if (processed_successfully)
- CHANGE_STATE(SPDY_AUTO_RESET);
+ if (processed_successfully) {
+ CHANGE_STATE(SPDY_CONSUME_PADDING);
+ }
}
// Handle error.
@@ -1597,9 +1648,9 @@ size_t SpdyFramer::ProcessSettingsFramePayload(const char* data,
void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
DCHECK_LT(SPDY3, protocol_version());
- DCHECK_EQ(0u, remaining_data_length_);
+ DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
- const SpdyNameValueBlock& block = hpack_decoder_->decoded_block();
+ const SpdyNameValueBlock& block = GetHpackDecoder()->decoded_block();
if (block.empty()) {
// Special-case this to make tests happy.
ProcessControlFrameHeaderBlock(NULL, 0, false);
@@ -1612,8 +1663,16 @@ void SpdyFramer::DeliverHpackBlockAsSpdy3Block() {
SerializeNameValueBlockWithoutCompression(&builder, block);
scoped_ptr<SpdyFrame> frame(builder.take());
+ // Preserve padding length, and reset it after the re-entrant call.
+ size_t remaining_padding = remaining_padding_payload_length_;
+
+ remaining_padding_payload_length_ = 0;
remaining_data_length_ = frame->size();
+
ProcessControlFrameHeaderBlock(frame->data(), frame->size(), false);
+
+ remaining_padding_payload_length_ = remaining_padding;
+ remaining_data_length_ = remaining_padding;
}
bool SpdyFramer::ProcessSetting(const char* data) {
@@ -1717,6 +1776,13 @@ size_t SpdyFramer::ProcessControlFramePayload(const char* data, size_t len) {
visitor_->OnBlocked(current_frame_stream_id_);
}
break;
+ case PRIORITY: {
+ DCHECK_LT(SPDY3, protocol_version());
+ // TODO(hkhalil): Process PRIORITY frames rather than ignore them.
+ reader.Seek(5);
+ DCHECK(reader.IsDoneReading());
+ }
+ break;
default:
// Unreachable.
LOG(FATAL) << "Unhandled control frame " << current_frame_type_;
@@ -1863,6 +1929,133 @@ size_t SpdyFramer::ProcessRstStreamFramePayload(const char* data, size_t len) {
return original_len;
}
+size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
+ if (len == 0) {
+ return 0;
+ }
+
+ // Clamp to the actual remaining payload.
+ len = std::min(len, remaining_data_length_);
+
+ size_t processed_bytes = 0;
+ size_t processing = 0;
+ size_t bytes_remaining;
+ char* buffer;
+ size_t* buffer_len;
+
+ while (len > 0) {
+ if (altsvc_scratch_.pid_len == 0) {
+ // The size of the frame up to the PID_LEN field.
+ size_t fixed_len_portion = GetAltSvcMinimumSize() - 1;
+ bytes_remaining = fixed_len_portion - current_frame_buffer_length_;
+ processing = std::min(len, bytes_remaining);
+ // Buffer the new ALTSVC bytes we got.
+ UpdateCurrentFrameBuffer(&data, &len, processing);
+
+ // Do we have enough to parse the length of the protocol id?
+ if (current_frame_buffer_length_ == fixed_len_portion) {
+ // Parse out the max age, port, and pid_len.
+ SpdyFrameReader reader(current_frame_buffer_.get(),
+ current_frame_buffer_length_);
+ reader.Seek(GetControlFrameHeaderSize()); // Seek past frame header.
+ bool successful_read = reader.ReadUInt32(&altsvc_scratch_.max_age);
+ reader.ReadUInt16(&altsvc_scratch_.port);
+ reader.Seek(1); // Reserved byte.
+ successful_read = successful_read &&
+ reader.ReadUInt8(&altsvc_scratch_.pid_len);
+ DCHECK(successful_read);
+ // Sanity check length value.
+ if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len >=
+ current_frame_length_) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ return 0;
+ }
+ altsvc_scratch_.protocol_id.reset(
+ new char[size_t(altsvc_scratch_.pid_len)]);
+ }
+ processed_bytes += processing;
+ continue;
+ } else if (altsvc_scratch_.pid_buf_len < altsvc_scratch_.pid_len) {
+ // Buffer protocol id field as in comes in.
+ buffer = altsvc_scratch_.protocol_id.get();
+ buffer_len = &altsvc_scratch_.pid_buf_len;
+ bytes_remaining = altsvc_scratch_.pid_len - altsvc_scratch_.pid_buf_len;
+ } else if (altsvc_scratch_.host_len == 0) {
+ // Parse out the host length.
+ processing = 1;
+ altsvc_scratch_.host_len = *reinterpret_cast<const uint8*>(data);
+ // Sanity check length value.
+ if (GetAltSvcMinimumSize() + altsvc_scratch_.pid_len +
+ altsvc_scratch_.host_len > current_frame_length_) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ return 0;
+ }
+ altsvc_scratch_.host.reset(new char[altsvc_scratch_.host_len]);
+ // Once we have host length, we can also determine the origin length
+ // by process of elimination.
+ altsvc_scratch_.origin_len = current_frame_length_ -
+ GetAltSvcMinimumSize() -
+ altsvc_scratch_.pid_len -
+ altsvc_scratch_.host_len;
+ if (altsvc_scratch_.origin_len > 0) {
+ altsvc_scratch_.origin.reset(new char[altsvc_scratch_.origin_len]);
+ }
+ data += processing;
+ processed_bytes += processing;
+ len -= processing;
+ continue;
+ } else if (altsvc_scratch_.host_buf_len < altsvc_scratch_.host_len) {
+ // Buffer host field as it comes in.
+ // TODO(mlavan): check formatting for host and origin
+ buffer = altsvc_scratch_.host.get();
+ buffer_len = &altsvc_scratch_.host_buf_len;
+ bytes_remaining = altsvc_scratch_.host_len - altsvc_scratch_.host_buf_len;
+ } else {
+ // Buffer (optional) origin field as it comes in.
+ if (altsvc_scratch_.origin_len <= 0) {
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ return 0;
+ }
+ buffer = altsvc_scratch_.origin.get();
+ buffer_len = &altsvc_scratch_.origin_buf_len;
+ bytes_remaining = remaining_data_length_ -
+ processed_bytes -
+ altsvc_scratch_.origin_buf_len;
+ if (len > bytes_remaining) {
+ // This is our last field; there shouldn't be any more bytes.
+ set_error(SPDY_INVALID_CONTROL_FRAME);
+ return 0;
+ }
+ }
+
+ // Copy data bytes into the appropriate field.
+ processing = std::min(len, bytes_remaining);
+ memcpy(buffer + *buffer_len,
+ data,
+ processing);
+ *buffer_len += processing;
+ data += processing;
+ processed_bytes += processing;
+ len -= processing;
+ }
+
+ remaining_data_length_ -= processed_bytes;
+ if (remaining_data_length_ == 0) {
+ visitor_->OnAltSvc(current_frame_stream_id_,
+ altsvc_scratch_.max_age,
+ altsvc_scratch_.port,
+ StringPiece(altsvc_scratch_.protocol_id.get(),
+ altsvc_scratch_.pid_len),
+ StringPiece(altsvc_scratch_.host.get(),
+ altsvc_scratch_.host_len),
+ StringPiece(altsvc_scratch_.origin.get(),
+ altsvc_scratch_.origin_len));
+ CHANGE_STATE(SPDY_AUTO_RESET);
+ }
+
+ return processed_bytes;
+}
+
size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
DCHECK_EQ(SPDY_READ_PADDING_LENGTH, state_);
@@ -1902,7 +2095,17 @@ size_t SpdyFramer::ProcessFramePaddingLength(const char* data, size_t len) {
set_error(SPDY_INVALID_DATA_FRAME_FLAGS);
return 0;
}
- CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
+ if (current_frame_type_ == DATA) {
+ CHANGE_STATE(SPDY_FORWARD_STREAM_FRAME);
+ } else {
+ DCHECK(current_frame_type_ == HEADERS ||
+ current_frame_type_ == PUSH_PROMISE ||
+ current_frame_type_ == CONTINUATION ||
+ current_frame_type_ == SYN_STREAM ||
+ current_frame_type_ == SYN_REPLY)
+ << current_frame_type_;
+ CHANGE_STATE(SPDY_CONTROL_FRAME_HEADER_BLOCK);
+ }
}
return original_len - len;
}
@@ -1914,10 +2117,10 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
if (remaining_padding_payload_length_ > 0) {
DCHECK_EQ(remaining_padding_payload_length_, remaining_data_length_);
size_t amount_to_discard = std::min(remaining_padding_payload_length_, len);
- // The visitor needs to know about padding so it can send window updates.
- // Communicate the padding to the visitor through a NULL data pointer, with
- // a nonzero size.
- if (amount_to_discard) {
+ if (current_frame_type_ == DATA && amount_to_discard > 0) {
+ // The visitor needs to know about padding so it can send window updates.
+ // Communicate the padding to the visitor through a NULL data pointer,
+ // with a nonzero size.
visitor_->OnStreamFrameData(
current_frame_stream_id_, NULL, amount_to_discard, false);
}
@@ -1928,12 +2131,14 @@ size_t SpdyFramer::ProcessFramePadding(const char* data, size_t len) {
}
if (remaining_data_length_ == 0) {
- // If the FIN flag is set, and there is no more data in this data frame,
+ // If the FIN flag is set, or this ends a header block which set FIN,
// inform the visitor of EOF via a 0-length data frame.
- if (current_frame_flags_ & DATA_FLAG_FIN) {
+ if (expect_continuation_ == 0 &&
+ ((current_frame_flags_ & CONTROL_FLAG_FIN) != 0 ||
+ end_stream_when_done_)) {
+ end_stream_when_done_ = false;
visitor_->OnStreamFrameData(current_frame_stream_id_, NULL, 0, true);
}
-
CHANGE_STATE(SPDY_AUTO_RESET);
}
return original_len - len;
@@ -2148,10 +2353,10 @@ SpdySerializedFrame* SpdyFramer::SerializeSynStream(
string hpack_encoding;
if (protocol_version() > SPDY3) {
if (enable_compression_) {
- hpack_encoder_->EncodeHeaderSet(
+ GetHpackEncoder()->EncodeHeaderSet(
syn_stream.name_value_block(), &hpack_encoding);
} else {
- hpack_encoder_->EncodeHeaderSetWithoutCompression(
+ GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
syn_stream.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
@@ -2213,10 +2418,10 @@ SpdySerializedFrame* SpdyFramer::SerializeSynReply(
string hpack_encoding;
if (protocol_version() > SPDY3) {
if (enable_compression_) {
- hpack_encoder_->EncodeHeaderSet(
+ GetHpackEncoder()->EncodeHeaderSet(
syn_reply.name_value_block(), &hpack_encoding);
} else {
- hpack_encoder_->EncodeHeaderSetWithoutCompression(
+ GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
syn_reply.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
@@ -2433,10 +2638,10 @@ SpdySerializedFrame* SpdyFramer::SerializeHeaders(
string hpack_encoding;
if (protocol_version() > SPDY3) {
if (enable_compression_) {
- hpack_encoder_->EncodeHeaderSet(
+ GetHpackEncoder()->EncodeHeaderSet(
headers.name_value_block(), &hpack_encoding);
} else {
- hpack_encoder_->EncodeHeaderSetWithoutCompression(
+ GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
headers.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
@@ -2526,10 +2731,10 @@ SpdyFrame* SpdyFramer::SerializePushPromise(
string hpack_encoding;
if (protocol_version() > SPDY3) {
if (enable_compression_) {
- hpack_encoder_->EncodeHeaderSet(
+ GetHpackEncoder()->EncodeHeaderSet(
push_promise.name_value_block(), &hpack_encoding);
} else {
- hpack_encoder_->EncodeHeaderSetWithoutCompression(
+ GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
push_promise.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
@@ -2586,10 +2791,10 @@ SpdyFrame* SpdyFramer::SerializeContinuation(
size_t size = GetContinuationMinimumSize();
string hpack_encoding;
if (enable_compression_) {
- hpack_encoder_->EncodeHeaderSet(
+ GetHpackEncoder()->EncodeHeaderSet(
continuation.name_value_block(), &hpack_encoding);
} else {
- hpack_encoder_->EncodeHeaderSetWithoutCompression(
+ GetHpackEncoder()->EncodeHeaderSetWithoutCompression(
continuation.name_value_block(), &hpack_encoding);
}
size += hpack_encoding.size();
@@ -2610,6 +2815,29 @@ SpdyFrame* SpdyFramer::SerializeContinuation(
return builder.take();
}
+SpdyFrame* SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc) {
+ DCHECK_LT(SPDY3, protocol_version());
+ size_t size = GetAltSvcMinimumSize();
+ size += altsvc.protocol_id().length();
+ size += altsvc.host().length();
+ size += altsvc.origin().length();
+
+ SpdyFrameBuilder builder(size, protocol_version());
+ builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
+
+ builder.WriteUInt32(altsvc.max_age());
+ builder.WriteUInt16(altsvc.port());
+ builder.WriteUInt8(0); // Reserved.
+ builder.WriteUInt8(altsvc.protocol_id().length());
+ builder.WriteBytes(altsvc.protocol_id().data(),
+ altsvc.protocol_id().length());
+ builder.WriteUInt8(altsvc.host().length());
+ builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
+ builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
+ DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
+ return builder.take();
+}
+
namespace {
class FrameSerializationVisitor : public SpdyFrameVisitor {
@@ -2658,6 +2886,9 @@ class FrameSerializationVisitor : public SpdyFrameVisitor {
const SpdyContinuationIR& continuation) OVERRIDE {
frame_.reset(framer_->SerializeContinuation(continuation));
}
+ virtual void VisitAltSvc(const SpdyAltSvcIR& altsvc) OVERRIDE {
+ frame_.reset(framer_->SerializeAltSvc(altsvc));
+ }
private:
SpdyFramer* framer_;
@@ -2808,6 +3039,22 @@ z_stream* SpdyFramer::GetHeaderDecompressor() {
return header_decompressor_.get();
}
+HpackEncoder* SpdyFramer::GetHpackEncoder() {
+ DCHECK_LT(SPDY3, spdy_version_);
+ if (hpack_encoder_.get() == NULL) {
+ hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable()));
+ }
+ return hpack_encoder_.get();
+}
+
+HpackDecoder* SpdyFramer::GetHpackDecoder() {
+ DCHECK_LT(SPDY3, spdy_version_);
+ if (hpack_decoder_.get() == NULL) {
+ hpack_decoder_.reset(new HpackDecoder(ObtainHpackHuffmanTable()));
+ }
+ return hpack_decoder_.get();
+}
+
// Incrementally decompress the control frame's header block, feeding the
// result to the visitor in chunks. Continue this until the visitor
// indicates that it cannot process any more data, or (more commonly) we
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698