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(); |
} |