Index: net/spdy/spdy_framer.cc |
diff --git a/net/spdy/spdy_framer.cc b/net/spdy/spdy_framer.cc |
index 21615a0f44742f2572dd2fa921688afd08a98016..96ccf9a9b87082f1a604ac44e05b51d93c453493 100644 |
--- a/net/spdy/spdy_framer.cc |
+++ b/net/spdy/spdy_framer.cc |
@@ -46,6 +46,9 @@ struct DictionaryIds { |
// initialized lazily to avoid static initializers. |
base::LazyInstance<DictionaryIds>::Leaky g_dictionary_ids; |
+// Used to indicate no flags in a SPDY flags field. |
+const uint8 kNoFlags = 0; |
+ |
} // namespace |
const int SpdyFramer::kMinSpdyVersion = 2; |
@@ -677,15 +680,13 @@ void SpdyFramer::WriteHeaderBlock(SpdyFrameBuilder* frame, |
} |
SpdyHeaderBlock::const_iterator it; |
for (it = headers->begin(); it != headers->end(); ++it) { |
- bool wrote_header; |
if (spdy_version < 3) { |
- wrote_header = frame->WriteString(it->first); |
- wrote_header &= frame->WriteString(it->second); |
+ frame->WriteString(it->first); |
+ frame->WriteString(it->second); |
} else { |
- wrote_header = frame->WriteStringPiece32(it->first); |
- wrote_header &= frame->WriteStringPiece32(it->second); |
+ frame->WriteStringPiece32(it->first); |
+ frame->WriteStringPiece32(it->second); |
} |
- DCHECK(wrote_header); |
} |
} |
@@ -1291,29 +1292,20 @@ SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
SpdyControlFlags flags, |
bool compressed, |
const SpdyHeaderBlock* headers) { |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); |
- |
- // Find our length. |
- size_t frame_size = SpdySynStreamControlFrame::size() + |
- GetSerializedLength(spdy_version_, headers); |
+ DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN & ~CONTROL_FLAG_UNIDIRECTIONAL); |
- SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); |
- frame.WriteUInt32(stream_id); |
- frame.WriteUInt32(associated_stream_id); |
- // Cap as appropriate. |
- if (priority > GetLowestPriority()) { |
- DLOG(DFATAL) << "Priority out-of-bounds."; |
- priority = GetLowestPriority(); |
- } |
- // Priority is 2 bits for <spdy3, 3 bits otherwise. |
- frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
- frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); |
- WriteHeaderBlock(&frame, spdy_version_, headers); |
- DCHECK_EQ(frame.length(), frame_size); |
+ SpdySynStreamIR syn_stream(stream_id); |
+ syn_stream.set_associated_to_stream_id(associated_stream_id); |
+ syn_stream.set_priority(priority); |
+ syn_stream.set_slot(credential_slot); |
+ syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0); |
+ syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0); |
+ // TODO(hkhalil): Avoid copy here. |
+ *(syn_stream.GetMutableNameValueBlock()) = *headers; |
scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
- reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); |
+ reinterpret_cast<SpdySynStreamControlFrame*>( |
+ SerializeSynStream(syn_stream))); |
if (compressed) { |
return reinterpret_cast<SpdySynStreamControlFrame*>( |
CompressControlFrame(*syn_frame.get(), headers)); |
@@ -1321,32 +1313,57 @@ SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
return syn_frame.release(); |
} |
+SpdySerializedFrame* SpdyFramer::SerializeSynStream( |
+ const SpdySynStreamIR& syn_stream) { |
+ uint8 flags = 0; |
+ if (syn_stream.fin()) { |
+ flags |= CONTROL_FLAG_FIN; |
+ } |
+ if (syn_stream.unidirectional()) { |
+ flags |= CONTROL_FLAG_UNIDIRECTIONAL; |
+ } |
+ |
+ // The size, in bytes, of this frame not including the variable-length |
+ // name-value block. Calculated as: |
+ // 8 (control frame header) + 2 * 4 (stream IDs) + 1 (priority) + 1 (slot) |
+ const size_t kSynStreamSizeBeforeNameValueBlock = 18; |
+ |
+ // The size of this frame, including variable-length name-value block. |
+ const size_t size = kSynStreamSizeBeforeNameValueBlock |
+ + GetSerializedLength(protocol_version(), |
+ &(syn_stream.name_value_block())); |
+ |
+ SpdyFrameBuilder builder(SYN_STREAM, flags, protocol_version(), size); |
+ builder.WriteUInt32(syn_stream.stream_id()); |
+ builder.WriteUInt32(syn_stream.associated_to_stream_id()); |
+ uint8 priority = syn_stream.priority(); |
+ if (priority > GetLowestPriority()) { |
+ DLOG(DFATAL) << "Priority out-of-bounds."; |
+ priority = GetLowestPriority(); |
+ } |
+ builder.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
+ builder.WriteUInt8(syn_stream.slot()); |
+ DCHECK_EQ(kSynStreamSizeBeforeNameValueBlock, builder.length()); |
+ SerializeNameValueBlock(&builder, syn_stream); |
+ |
+ return builder.take(); |
+} |
+ |
SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
SpdyStreamId stream_id, |
SpdyControlFlags flags, |
bool compressed, |
const SpdyHeaderBlock* headers) { |
- DCHECK_GT(stream_id, 0u); |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
+ DCHECK_EQ(0, flags & ~CONTROL_FLAG_FIN); |
- // Find our length. |
- size_t frame_size = SpdySynReplyControlFrame::size() + |
- GetSerializedLength(spdy_version_, headers); |
- // In SPDY 2, there were 2 unused bytes before payload. |
- if (spdy_version_ < 3) { |
- frame_size += 2; |
- } |
- |
- SpdyFrameBuilder frame(SYN_REPLY, flags, spdy_version_, frame_size); |
- frame.WriteUInt32(stream_id); |
- if (spdy_version_ < 3) { |
- frame.WriteUInt16(0); // Unused |
- } |
- WriteHeaderBlock(&frame, spdy_version_, headers); |
- DCHECK_EQ(frame.length(), frame_size); |
+ SpdySynReplyIR syn_reply(stream_id); |
+ syn_reply.set_fin(flags & CONTROL_FLAG_FIN); |
+ // TODO(hkhalil): Avoid copy here. |
+ *(syn_reply.GetMutableNameValueBlock()) = *headers; |
scoped_ptr<SpdySynReplyControlFrame> reply_frame( |
- reinterpret_cast<SpdySynReplyControlFrame*>(frame.take())); |
+ reinterpret_cast<SpdySynReplyControlFrame*>(SerializeSynReply( |
+ syn_reply))); |
if (compressed) { |
return reinterpret_cast<SpdySynReplyControlFrame*>( |
CompressControlFrame(*reply_frame.get(), headers)); |
@@ -1354,159 +1371,298 @@ SpdySynReplyControlFrame* SpdyFramer::CreateSynReply( |
return reply_frame.release(); |
} |
+SpdySerializedFrame* SpdyFramer::SerializeSynReply( |
+ const SpdySynReplyIR& syn_reply) { |
+ uint8 flags = 0; |
+ if (syn_reply.fin()) { |
+ flags |= CONTROL_FLAG_FIN; |
+ } |
+ |
+ // The size, in bytes, of this frame not including the variable-length |
+ // name-value block. Calculated as: |
+ // 8 (control frame header) + 4 (stream ID) |
+ size_t syn_reply_size_before_name_value_block = 12; |
+ // In SPDY 2, there were 2 unused bytes before payload. |
+ if (protocol_version() < 3) { |
+ syn_reply_size_before_name_value_block += 2; |
+ } |
+ |
+ // The size of this frame, including variable-length name-value block. |
+ size_t size = syn_reply_size_before_name_value_block |
+ + GetSerializedLength(protocol_version(), |
+ &(syn_reply.name_value_block())); |
+ |
+ SpdyFrameBuilder builder(SYN_REPLY, flags, protocol_version(), size); |
+ builder.WriteUInt32(syn_reply.stream_id()); |
+ if (protocol_version() < 3) { |
+ builder.WriteUInt16(0); // Unused. |
+ } |
+ DCHECK_EQ(syn_reply_size_before_name_value_block, builder.length()); |
+ SerializeNameValueBlock(&builder, syn_reply); |
+ |
+ return builder.take(); |
+} |
+ |
SpdyRstStreamControlFrame* SpdyFramer::CreateRstStream( |
SpdyStreamId stream_id, |
SpdyRstStreamStatus status) const { |
- DCHECK_GT(stream_id, 0u); |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- DCHECK_NE(status, RST_STREAM_INVALID); |
- DCHECK_LT(status, RST_STREAM_NUM_STATUS_CODES); |
- |
- size_t frame_size = SpdyRstStreamControlFrame::size(); |
- SpdyFrameBuilder frame(RST_STREAM, CONTROL_FLAG_NONE, spdy_version_, |
- frame_size); |
- frame.WriteUInt32(stream_id); |
- frame.WriteUInt32(status); |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyRstStreamControlFrame*>(frame.take()); |
+ SpdyRstStreamIR rst_stream(stream_id, status); |
+ return reinterpret_cast<SpdyRstStreamControlFrame*>( |
+ SerializeRstStream(rst_stream)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializeRstStream( |
+ const SpdyRstStreamIR& rst_stream) const { |
+ // Size of our RST_STREAM frame. Calculated as: |
+ // 8 (control frame header) + 4 (stream id) + 4 (status code) |
+ const size_t kRstStreamFrameSize = 16; |
+ |
+ SpdyFrameBuilder builder(RST_STREAM, |
+ kNoFlags, |
+ protocol_version(), |
+ kRstStreamFrameSize); |
+ builder.WriteUInt32(rst_stream.stream_id()); |
+ builder.WriteUInt32(rst_stream.status()); |
+ DCHECK_EQ(kRstStreamFrameSize, builder.length()); |
+ return builder.take(); |
} |
SpdySettingsControlFrame* SpdyFramer::CreateSettings( |
const SettingsMap& values) const { |
- size_t frame_size = SpdySettingsControlFrame::size() + 8 * values.size(); |
- SpdyFrameBuilder frame(SETTINGS, CONTROL_FLAG_NONE, spdy_version_, |
- frame_size); |
- frame.WriteUInt32(values.size()); |
+ SpdySettingsIR settings; |
for (SettingsMap::const_iterator it = values.begin(); |
it != values.end(); |
- it++) { |
- SettingsFlagsAndId flags_and_id(it->second.first, it->first); |
- uint32 id_and_flags_wire = flags_and_id.GetWireFormat(spdy_version_); |
- frame.WriteBytes(&id_and_flags_wire, 4); |
- frame.WriteUInt32(it->second.second); |
- } |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdySettingsControlFrame*>(frame.take()); |
+ ++it) { |
+ settings.AddSetting(it->first, |
+ (it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0, |
+ (it->second.first & SETTINGS_FLAG_PERSISTED) != 0, |
+ it->second.second); |
+ } |
+ return reinterpret_cast<SpdySettingsControlFrame*>( |
+ SerializeSettings(settings)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializeSettings( |
+ const SpdySettingsIR& settings) const { |
+ uint8 flags = 0; |
+ if (settings.clear_settings()) { |
+ flags |= SETTINGS_FLAG_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS; |
+ } |
+ const SpdySettingsIR::ValueMap* values = &(settings.values()); |
+ |
+ // Size, in bytes, of this SETTINGS frame not including the IDs and values |
+ // from the variable-length value block. Calculated as: |
+ // 8 (control frame header) + 4 (number of ID/value pairs) |
+ const size_t kSettingsSizeWithoutValues = 12; |
+ // Size, in bytes, of this SETTINGS frame. |
+ const size_t size = kSettingsSizeWithoutValues + (values->size() * 8); |
+ |
+ SpdyFrameBuilder builder(SETTINGS, flags, protocol_version(), size); |
+ builder.WriteUInt32(values->size()); |
+ DCHECK_EQ(kSettingsSizeWithoutValues, builder.length()); |
+ for (SpdySettingsIR::ValueMap::const_iterator it = values->begin(); |
+ it != values->end(); |
+ ++it) { |
+ uint8 setting_flags = 0; |
+ if (it->second.persist_value) { |
+ setting_flags |= SETTINGS_FLAG_PLEASE_PERSIST; |
+ } |
+ if (it->second.persisted) { |
+ setting_flags |= SETTINGS_FLAG_PERSISTED; |
+ } |
+ SettingsFlagsAndId flags_and_id(setting_flags, it->first); |
+ uint32 id_and_flags_wire = flags_and_id.GetWireFormat(protocol_version()); |
+ builder.WriteBytes(&id_and_flags_wire, 4); |
+ builder.WriteUInt32(it->second.value); |
+ } |
+ DCHECK_EQ(size, builder.length()); |
+ return builder.take(); |
} |
SpdyPingControlFrame* SpdyFramer::CreatePingFrame(uint32 unique_id) const { |
- size_t frame_size = SpdyPingControlFrame::size(); |
- SpdyFrameBuilder frame(PING, CONTROL_FLAG_NONE, spdy_version_, frame_size); |
- frame.WriteUInt32(unique_id); |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyPingControlFrame*>(frame.take()); |
+ SpdyPingIR ping(unique_id); |
+ return reinterpret_cast<SpdyPingControlFrame*>(SerializePing(ping)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializePing(const SpdyPingIR& ping) const { |
+ // Size, in bytes, of this PING frame. Calculated as: |
+ // 8 (control frame header) + 4 (id) |
+ const size_t kPingSize = 12; |
+ SpdyFrameBuilder builder(PING, 0, protocol_version(), kPingSize); |
+ builder.WriteUInt32(ping.id()); |
+ DCHECK_EQ(kPingSize, builder.length()); |
+ return builder.take(); |
} |
SpdyGoAwayControlFrame* SpdyFramer::CreateGoAway( |
SpdyStreamId last_accepted_stream_id, |
SpdyGoAwayStatus status) const { |
- DCHECK_EQ(0u, last_accepted_stream_id & ~kStreamIdMask); |
- |
- // SPDY 2 GOAWAY frames are 4 bytes smaller than in SPDY 3. We account for |
- // this difference via a separate offset variable, since |
- // SpdyGoAwayControlFrame::size() returns the SPDY 3 size. |
- const size_t goaway_offset = (protocol_version() < 3) ? 4 : 0; |
- size_t frame_size = SpdyGoAwayControlFrame::size() - goaway_offset; |
- SpdyFrameBuilder frame(GOAWAY, CONTROL_FLAG_NONE, spdy_version_, frame_size); |
- frame.WriteUInt32(last_accepted_stream_id); |
+ SpdyGoAwayIR goaway(last_accepted_stream_id, status); |
+ return reinterpret_cast<SpdyGoAwayControlFrame*>(SerializeGoAway(goaway)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializeGoAway( |
+ const SpdyGoAwayIR& goaway) const { |
+ // Size, in bytes, of this GOAWAY frame. Calculated as: |
+ // 8 (control frame header) + 4 (last good stream id) |
+ size_t size = 12; |
+ // SPDY 3+ GOAWAY frames also contain a status. |
+ if (protocol_version() >= 3) { |
+ size += 4; |
+ } |
+ SpdyFrameBuilder builder(GOAWAY, 0, protocol_version(), size); |
+ builder.WriteUInt32(goaway.last_good_stream_id()); |
if (protocol_version() >= 3) { |
- frame.WriteUInt32(status); |
+ builder.WriteUInt32(goaway.status()); |
} |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyGoAwayControlFrame*>(frame.take()); |
+ DCHECK_EQ(size, builder.length()); |
+ return builder.take(); |
} |
SpdyHeadersControlFrame* SpdyFramer::CreateHeaders( |
SpdyStreamId stream_id, |
SpdyControlFlags flags, |
bool compressed, |
- const SpdyHeaderBlock* headers) { |
+ const SpdyHeaderBlock* header_block) { |
// Basically the same as CreateSynReply(). |
- DCHECK_GT(stream_id, 0u); |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- |
- // Find our length. |
- size_t frame_size = SpdyHeadersControlFrame::size() + |
- GetSerializedLength(spdy_version_, headers); |
- // In SPDY 2, there were 2 unused bytes before payload. |
- if (spdy_version_ < 3) { |
- frame_size += 2; |
- } |
+ DCHECK_EQ(0, flags & (!CONTROL_FLAG_FIN)); |
- SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); |
- frame.WriteUInt32(stream_id); |
- if (spdy_version_ < 3) { |
- frame.WriteUInt16(0); // Unused |
- } |
- WriteHeaderBlock(&frame, spdy_version_, headers); |
- DCHECK_EQ(frame.length(), frame_size); |
+ SpdyHeadersIR headers(stream_id); |
+ headers.set_fin(flags & CONTROL_FLAG_FIN); |
+ // TODO(hkhalil): Avoid copy here. |
+ *(headers.GetMutableNameValueBlock()) = *header_block; |
scoped_ptr<SpdyHeadersControlFrame> headers_frame( |
- reinterpret_cast<SpdyHeadersControlFrame*>(frame.take())); |
+ reinterpret_cast<SpdyHeadersControlFrame*>(SerializeHeaders(headers))); |
if (compressed) { |
return reinterpret_cast<SpdyHeadersControlFrame*>( |
- CompressControlFrame(*headers_frame.get(), headers)); |
+ CompressControlFrame(*headers_frame.get(), |
+ headers.GetMutableNameValueBlock())); |
} |
return headers_frame.release(); |
} |
+SpdySerializedFrame* SpdyFramer::SerializeHeaders( |
+ const SpdyHeadersIR& headers) { |
+ uint8 flags = 0; |
+ if (headers.fin()) { |
+ flags |= CONTROL_FLAG_FIN; |
+ } |
+ |
+ // The size, in bytes, of this frame not including the variable-length |
+ // name-value block. Calculated as: |
+ // 8 (control frame header) + 4 (stream ID) |
+ size_t headers_size_before_name_value_block = 12; |
+ // In SPDY 2, there were 2 unused bytes before payload. |
+ if (protocol_version() < 3) { |
+ headers_size_before_name_value_block += 2; |
+ } |
+ |
+ // The size of this frame, including variable-length name-value block. |
+ size_t size = headers_size_before_name_value_block |
+ + GetSerializedLength(protocol_version(), |
+ &(headers.name_value_block())); |
+ |
+ SpdyFrameBuilder builder(HEADERS, flags, protocol_version(), size); |
+ builder.WriteUInt32(headers.stream_id()); |
+ if (protocol_version() < 3) { |
+ builder.WriteUInt16(0); // Unused. |
+ } |
+ DCHECK_EQ(headers_size_before_name_value_block, builder.length()); |
+ |
+ SerializeNameValueBlock(&builder, headers); |
+ DCHECK_EQ(size, builder.length()); |
+ |
+ return builder.take(); |
+} |
+ |
SpdyWindowUpdateControlFrame* SpdyFramer::CreateWindowUpdate( |
SpdyStreamId stream_id, |
uint32 delta_window_size) const { |
- DCHECK_GT(stream_id, 0u); |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- DCHECK_GT(delta_window_size, 0u); |
- DCHECK_LE(delta_window_size, |
- static_cast<uint32>(kSpdyStreamMaximumWindowSize)); |
- |
- size_t frame_size = SpdyWindowUpdateControlFrame::size(); |
- SpdyFrameBuilder frame(WINDOW_UPDATE, CONTROL_FLAG_NONE, spdy_version_, |
- frame_size); |
- frame.WriteUInt32(stream_id); |
- frame.WriteUInt32(delta_window_size); |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyWindowUpdateControlFrame*>(frame.take()); |
+ SpdyWindowUpdateIR window_update(stream_id, delta_window_size); |
+ return reinterpret_cast<SpdyWindowUpdateControlFrame*>( |
+ SerializeWindowUpdate(window_update)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializeWindowUpdate( |
+ const SpdyWindowUpdateIR& window_update) const { |
+ // Size, in bytes, of this WINDOW_UPDATE frame. Calculated as: |
+ // 8 (control frame header) + 4 (stream id) + 4 (delta) |
+ const size_t kWindowUpdateSize = 16; |
+ |
+ SpdyFrameBuilder builder(WINDOW_UPDATE, |
+ kNoFlags, |
+ protocol_version(), |
+ kWindowUpdateSize); |
+ builder.WriteUInt32(window_update.stream_id()); |
+ builder.WriteUInt32(window_update.delta()); |
+ DCHECK_EQ(kWindowUpdateSize, builder.length()); |
+ return builder.take(); |
} |
+// TODO(hkhalil): Gut with SpdyCredential removal. |
SpdyCredentialControlFrame* SpdyFramer::CreateCredentialFrame( |
const SpdyCredential& credential) const { |
- // Calculate the size of the frame by adding the size of the |
- // variable length data to the size of the fixed length data. |
- size_t frame_size = SpdyCredentialControlFrame::size() + |
- credential.proof.length(); |
- DCHECK_EQ(SpdyCredentialControlFrame::size(), 14u); |
+ SpdyCredentialIR credential_ir(credential.slot); |
+ credential_ir.set_proof(credential.proof); |
for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
cert != credential.certs.end(); |
++cert) { |
- frame_size += sizeof(uint32); // size of the cert_length field |
- frame_size += cert->length(); // size of the cert_data field |
+ credential_ir.AddCertificate(*cert); |
} |
+ return reinterpret_cast<SpdyCredentialControlFrame*>( |
+ SerializeCredential(credential_ir)); |
+} |
- SpdyFrameBuilder frame(CREDENTIAL, CONTROL_FLAG_NONE, spdy_version_, |
- frame_size); |
- frame.WriteUInt16(credential.slot); |
- frame.WriteUInt32(credential.proof.size()); |
- frame.WriteBytes(credential.proof.c_str(), credential.proof.size()); |
- for (std::vector<std::string>::const_iterator cert = credential.certs.begin(); |
- cert != credential.certs.end(); |
- ++cert) { |
- frame.WriteUInt32(cert->length()); |
- frame.WriteBytes(cert->c_str(), cert->length()); |
+SpdySerializedFrame* SpdyFramer::SerializeCredential( |
+ const SpdyCredentialIR& credential) const { |
+ size_t size = 8; // Room for frame header. |
+ size += 2; // Room for slot. |
+ size += 4 + credential.proof().length(); // Room for proof. |
+ for (SpdyCredentialIR::CertificateList::const_iterator it = |
+ credential.certificates()->begin(); |
+ it != credential.certificates()->end(); |
+ ++it) { |
+ size += 4 + it->length(); // Room for certificate. |
+ } |
+ |
+ SpdyFrameBuilder builder(CREDENTIAL, 0, protocol_version(), size); |
+ builder.WriteUInt16(credential.slot()); |
+ builder.WriteStringPiece32(credential.proof()); |
+ for (SpdyCredentialIR::CertificateList::const_iterator it = |
+ credential.certificates()->begin(); |
+ it != credential.certificates()->end(); |
+ ++it) { |
+ builder.WriteStringPiece32(*it); |
} |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); |
+ DCHECK_EQ(size, builder.length()); |
+ return builder.take(); |
} |
SpdyDataFrame* SpdyFramer::CreateDataFrame( |
- SpdyStreamId stream_id, |
- const char* data, |
+ SpdyStreamId stream_id, const char* data, |
uint32 len, SpdyDataFlags flags) const { |
- DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
- size_t frame_size = SpdyDataFrame::size() + len; |
- SpdyFrameBuilder frame(stream_id, flags, frame_size); |
- frame.WriteBytes(data, len); |
- DCHECK_EQ(frame.length(), frame_size); |
- return reinterpret_cast<SpdyDataFrame*>(frame.take()); |
+ DCHECK_EQ(0, flags & (!DATA_FLAG_FIN)); |
+ |
+ SpdyDataIR data_ir(stream_id, base::StringPiece(data, len)); |
+ data_ir.set_fin(flags & DATA_FLAG_FIN); |
+ return reinterpret_cast<SpdyDataFrame*>(SerializeData(data_ir)); |
+} |
+ |
+SpdySerializedFrame* SpdyFramer::SerializeData(const SpdyDataIR& data) const { |
+ // Size, in bytes, of this DATA frame. Calculated as: |
+ // 4 (stream id) + 1 (flags) + 3 (length) + payload length |
+ const size_t size = 8 + data.data().length(); |
+ |
+ SpdyDataFlags flags = DATA_FLAG_NONE; |
+ if (data.fin()) { |
+ flags = DATA_FLAG_FIN; |
+ } |
+ |
+ SpdyFrameBuilder builder(data.stream_id(), flags, size); |
+ builder.WriteBytes(data.data().data(), data.data().length()); |
+ DCHECK_EQ(size, builder.length()); |
+ return builder.take(); |
} |
// The following compression setting are based on Brian Olson's analysis. See |
@@ -1912,8 +2068,30 @@ SpdyStreamId SpdyFramer::GetControlFrameStreamId( |
return stream_id; |
} |
-void SpdyFramer::set_enable_compression(bool value) { |
- enable_compression_ = value; |
+void SpdyFramer::SerializeNameValueBlock( |
+ SpdyFrameBuilder* builder, |
+ const SpdyFrameWithNameValueBlockIR& frame) const { |
+ const SpdyNameValueBlock* name_value_block = &(frame.name_value_block()); |
+ |
+ // Serialize number of headers. |
+ if (protocol_version() < 3) { |
+ builder->WriteUInt16(name_value_block->size()); |
+ } else { |
+ builder->WriteUInt32(name_value_block->size()); |
+ } |
+ |
+ // Serialize each header. |
+ for (SpdyHeaderBlock::const_iterator it = name_value_block->begin(); |
+ it != name_value_block->end(); |
+ ++it) { |
+ if (protocol_version() < 3) { |
+ builder->WriteString(it->first); |
+ builder->WriteString(it->second); |
+ } else { |
+ builder->WriteStringPiece32(it->first); |
+ builder->WriteStringPiece32(it->second); |
+ } |
+ } |
} |
} // namespace net |