| Index: net/spdy/spdy_framer.cc
|
| diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc
|
| index eebddf6156df582292da90c2d3c4ffb46948e34f..e0dd61d055467c1a12555eb9a88266c9652a923e 100644
|
| --- a/net/spdy/spdy_framer.cc
|
| +++ b/net/spdy/spdy_framer.cc
|
| @@ -4,9 +4,14 @@
|
|
|
| #include "net/spdy/spdy_framer.h"
|
|
|
| +#include <algorithm>
|
| +#include <limits>
|
| +#include <string>
|
| +
|
| #include "base/lazy_instance.h"
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/third_party/valgrind/memcheck.h"
|
| +#include "net/spdy/spdy_alt_svc_wire_format.h"
|
| #include "net/spdy/spdy_frame_builder.h"
|
| #include "net/spdy/spdy_frame_reader.h"
|
| #include "net/spdy/spdy_bitmasks.h"
|
| @@ -343,13 +348,12 @@ size_t SpdyFramer::GetContinuationMinimumSize() const {
|
| }
|
|
|
| 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, in bytes, of an ALTSVC frame not including the Field-Value and
|
| + // (optional) Origin fields, both 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 + 2 (origin_len).
|
| + return GetControlFrameHeaderSize() + 2;
|
| }
|
|
|
| size_t SpdyFramer::GetPrioritySize() const {
|
| @@ -2029,124 +2033,47 @@ size_t SpdyFramer::ProcessAltSvcFramePayload(const char* data, size_t len) {
|
| // 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 (altsvc_scratch_.pid_len == 0 ||
|
| - 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;
|
| + if (altsvc_scratch_.buffer.get() == nullptr) {
|
| + altsvc_scratch_.buffer.reset(
|
| + new char[current_frame_length_ - GetControlFrameHeaderSize()]);
|
| + altsvc_scratch_.buffer_length = 0;
|
| + }
|
| + memcpy(altsvc_scratch_.buffer.get() + altsvc_scratch_.buffer_length, data,
|
| + len);
|
| + altsvc_scratch_.buffer_length += len;
|
| + remaining_data_length_ -= len;
|
| + if (remaining_data_length_ > 0) {
|
| + return len;
|
| }
|
|
|
| - 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);
|
| + SpdyFrameReader reader(altsvc_scratch_.buffer.get(),
|
| + altsvc_scratch_.buffer_length);
|
| + StringPiece origin;
|
| + bool successful_read = reader.ReadStringPiece16(&origin);
|
| + if (!successful_read) {
|
| + set_error(SPDY_INVALID_CONTROL_FRAME);
|
| + return 0;
|
| + }
|
| + StringPiece value(altsvc_scratch_.buffer.get() + reader.GetBytesConsumed(),
|
| + altsvc_scratch_.buffer_length - reader.GetBytesConsumed());
|
| +
|
| + string protocol_id;
|
| + string host;
|
| + uint16 port;
|
| + uint32 max_age;
|
| + double p;
|
| + bool success = SpdyAltSvcWireFormat::ParseHeaderFieldValue(
|
| + value, &protocol_id, &host, &port, &max_age, &p);
|
| + if (!success || protocol_id.length() == 0) {
|
| + set_error(SPDY_INVALID_CONTROL_FRAME);
|
| + return 0;
|
| }
|
|
|
| - return processed_bytes;
|
| + // TODO(bnc): Pass on |p|.
|
| + visitor_->OnAltSvc(current_frame_stream_id_, max_age, port, protocol_id, host,
|
| + origin);
|
| + CHANGE_STATE(SPDY_AUTO_RESET);
|
| + return len;
|
| }
|
|
|
| size_t SpdyFramer::ProcessDataFramePaddingLength(const char* data, size_t len) {
|
| @@ -2847,25 +2774,21 @@ SpdyFrame* SpdyFramer::SerializeContinuation(
|
|
|
| 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();
|
| + // TODO(bnc): Add probability to SpdyAltSvcIR and pass it on.
|
| + string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue(
|
| + altsvc.protocol_id(), altsvc.host(), altsvc.port(), altsvc.max_age(),
|
| + 1.0);
|
| + size += value.length();
|
|
|
| SpdyFrameBuilder builder(size, protocol_version());
|
| builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc.stream_id());
|
|
|
| - // TODO(bnc): http://crbug.com/438263
|
| - // Update the binary format here to the new text-based payload format.
|
| - builder.WriteUInt32(altsvc.max_age());
|
| - builder.WriteUInt16(altsvc.port());
|
| - builder.WriteUInt8(0); // Reserved.
|
| - builder.WriteUInt8(static_cast<uint8>(altsvc.protocol_id().length()));
|
| - builder.WriteBytes(altsvc.protocol_id().data(),
|
| - altsvc.protocol_id().length());
|
| - builder.WriteUInt8(static_cast<uint8>(altsvc.host().length()));
|
| - builder.WriteBytes(altsvc.host().data(), altsvc.host().length());
|
| + builder.WriteUInt16(altsvc.origin().length());
|
| builder.WriteBytes(altsvc.origin().data(), altsvc.origin().length());
|
| + builder.WriteBytes(value.data(), value.length());
|
| DCHECK_LT(GetAltSvcMinimumSize(), builder.length());
|
| return builder.take();
|
| }
|
|
|