This source file includes following definitions.
- NextProtoToSpdyMajorVersion
- frames_received_
- set_visitor
- set_debug_visitor
- OnError
- OnSynStream
- OnHeaders
- OnSynReply
- OnControlFrameHeaderData
- OnDataFrameHeader
- OnStreamFrameData
- OnSettings
- OnSetting
- OnSettingsAck
- OnSettingsEnd
- OnPing
- OnRstStream
- OnGoAway
- OnWindowUpdate
- OnPushPromise
- OnContinuation
- protocol_version
- ProcessInput
- Reset
- error_code
- state
- MessageFullyRead
- HasError
- CreateSynStream
- CreateSynReply
- CreateRstStream
- CreateSettings
- CreatePingFrame
- CreateGoAway
- CreateHeaders
- CreateWindowUpdate
- CreateDataFrame
- GetHighestPriority
- InitHeaderStreaming
#include "net/spdy/buffered_spdy_framer.h"
#include "base/logging.h"
namespace net {
SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) {
switch (next_proto) {
case kProtoDeprecatedSPDY2:
return SPDY2;
case kProtoSPDY3:
case kProtoSPDY31:
return SPDY3;
case kProtoSPDY4a2:
case kProtoHTTP2Draft04:
return SPDY4;
case kProtoUnknown:
case kProtoHTTP11:
case kProtoQUIC1SPDY3:
break;
}
NOTREACHED();
return SPDY2;
}
BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version,
bool enable_compression)
: spdy_framer_(version),
visitor_(NULL),
header_buffer_used_(0),
header_buffer_valid_(false),
header_stream_id_(SpdyFramer::kInvalidStream),
frames_received_(0) {
spdy_framer_.set_enable_compression(enable_compression);
memset(header_buffer_, 0, sizeof(header_buffer_));
}
BufferedSpdyFramer::~BufferedSpdyFramer() {
}
void BufferedSpdyFramer::set_visitor(
BufferedSpdyFramerVisitorInterface* visitor) {
visitor_ = visitor;
spdy_framer_.set_visitor(this);
}
void BufferedSpdyFramer::set_debug_visitor(
SpdyFramerDebugVisitorInterface* debug_visitor) {
spdy_framer_.set_debug_visitor(debug_visitor);
}
void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) {
DCHECK(spdy_framer);
visitor_->OnError(spdy_framer->error_code());
}
void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
bool fin,
bool unidirectional) {
frames_received_++;
DCHECK(!control_frame_fields_.get());
control_frame_fields_.reset(new ControlFrameFields());
control_frame_fields_->type = SYN_STREAM;
control_frame_fields_->stream_id = stream_id;
control_frame_fields_->associated_stream_id = associated_stream_id;
control_frame_fields_->priority = priority;
control_frame_fields_->fin = fin;
control_frame_fields_->unidirectional = unidirectional;
InitHeaderStreaming(stream_id);
}
void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id,
bool fin,
bool end) {
frames_received_++;
DCHECK(!control_frame_fields_.get());
control_frame_fields_.reset(new ControlFrameFields());
control_frame_fields_->type = HEADERS;
control_frame_fields_->stream_id = stream_id;
control_frame_fields_->fin = fin;
InitHeaderStreaming(stream_id);
}
void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id,
bool fin) {
frames_received_++;
DCHECK(!control_frame_fields_.get());
control_frame_fields_.reset(new ControlFrameFields());
control_frame_fields_->type = SYN_REPLY;
control_frame_fields_->stream_id = stream_id;
control_frame_fields_->fin = fin;
InitHeaderStreaming(stream_id);
}
bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id,
const char* header_data,
size_t len) {
CHECK_EQ(header_stream_id_, stream_id);
if (len == 0) {
CHECK(header_buffer_valid_);
SpdyHeaderBlock headers;
size_t parsed_len = spdy_framer_.ParseHeaderBlockInBuffer(
header_buffer_, header_buffer_used_, &headers);
if (parsed_len == 0) {
visitor_->OnStreamError(
stream_id, "Could not parse Spdy Control Frame Header.");
return false;
}
DCHECK(control_frame_fields_.get());
switch (control_frame_fields_->type) {
case SYN_STREAM:
visitor_->OnSynStream(control_frame_fields_->stream_id,
control_frame_fields_->associated_stream_id,
control_frame_fields_->priority,
control_frame_fields_->fin,
control_frame_fields_->unidirectional,
headers);
break;
case SYN_REPLY:
visitor_->OnSynReply(control_frame_fields_->stream_id,
control_frame_fields_->fin,
headers);
break;
case HEADERS:
visitor_->OnHeaders(control_frame_fields_->stream_id,
control_frame_fields_->fin,
headers);
break;
default:
DCHECK(false) << "Unexpect control frame type: "
<< control_frame_fields_->type;
break;
}
control_frame_fields_.reset(NULL);
return true;
}
const size_t available = kHeaderBufferSize - header_buffer_used_;
if (len > available) {
header_buffer_valid_ = false;
visitor_->OnStreamError(
stream_id, "Received more data than the allocated size.");
return false;
}
memcpy(header_buffer_ + header_buffer_used_, header_data, len);
header_buffer_used_ += len;
return true;
}
void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id,
size_t length,
bool fin) {
frames_received_++;
header_stream_id_ = stream_id;
visitor_->OnDataFrameHeader(stream_id, length, fin);
}
void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id,
const char* data,
size_t len,
bool fin) {
visitor_->OnStreamFrameData(stream_id, data, len, fin);
}
void BufferedSpdyFramer::OnSettings(bool clear_persisted) {
visitor_->OnSettings(clear_persisted);
}
void BufferedSpdyFramer::OnSetting(SpdySettingsIds id,
uint8 flags,
uint32 value) {
visitor_->OnSetting(id, flags, value);
}
void BufferedSpdyFramer::OnSettingsAck() {
visitor_->OnSettingsAck();
}
void BufferedSpdyFramer::OnSettingsEnd() {
visitor_->OnSettingsEnd();
}
void BufferedSpdyFramer::OnPing(SpdyPingId unique_id, bool is_ack) {
visitor_->OnPing(unique_id, is_ack);
}
void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id,
SpdyRstStreamStatus status) {
visitor_->OnRstStream(stream_id, status);
}
void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) {
visitor_->OnGoAway(last_accepted_stream_id, status);
}
void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id,
uint32 delta_window_size) {
visitor_->OnWindowUpdate(stream_id, delta_window_size);
}
void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id,
SpdyStreamId promised_stream_id,
bool end) {
visitor_->OnPushPromise(stream_id, promised_stream_id);
}
void BufferedSpdyFramer::OnContinuation(SpdyStreamId stream_id, bool end) {
}
SpdyMajorVersion BufferedSpdyFramer::protocol_version() {
return spdy_framer_.protocol_version();
}
size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) {
return spdy_framer_.ProcessInput(data, len);
}
void BufferedSpdyFramer::Reset() {
spdy_framer_.Reset();
}
SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const {
return spdy_framer_.error_code();
}
SpdyFramer::SpdyState BufferedSpdyFramer::state() const {
return spdy_framer_.state();
}
bool BufferedSpdyFramer::MessageFullyRead() {
return state() == SpdyFramer::SPDY_AUTO_RESET;
}
bool BufferedSpdyFramer::HasError() {
return spdy_framer_.HasError();
}
SpdyFrame* BufferedSpdyFramer::CreateSynStream(
SpdyStreamId stream_id,
SpdyStreamId associated_stream_id,
SpdyPriority priority,
SpdyControlFlags flags,
const SpdyHeaderBlock* headers) {
SpdySynStreamIR syn_stream(stream_id);
syn_stream.set_associated_to_stream_id(associated_stream_id);
syn_stream.set_priority(priority);
syn_stream.set_fin((flags & CONTROL_FLAG_FIN) != 0);
syn_stream.set_unidirectional((flags & CONTROL_FLAG_UNIDIRECTIONAL) != 0);
syn_stream.set_name_value_block(*headers);
return spdy_framer_.SerializeSynStream(syn_stream);
}
SpdyFrame* BufferedSpdyFramer::CreateSynReply(
SpdyStreamId stream_id,
SpdyControlFlags flags,
const SpdyHeaderBlock* headers) {
SpdySynReplyIR syn_reply(stream_id);
syn_reply.set_fin(flags & CONTROL_FLAG_FIN);
syn_reply.set_name_value_block(*headers);
return spdy_framer_.SerializeSynReply(syn_reply);
}
SpdyFrame* BufferedSpdyFramer::CreateRstStream(
SpdyStreamId stream_id,
SpdyRstStreamStatus status) const {
SpdyRstStreamIR rst_ir(stream_id, status, "RST");
return spdy_framer_.SerializeRstStream(rst_ir);
}
SpdyFrame* BufferedSpdyFramer::CreateSettings(
const SettingsMap& values) const {
SpdySettingsIR settings_ir;
for (SettingsMap::const_iterator it = values.begin();
it != values.end();
++it) {
settings_ir.AddSetting(
it->first,
(it->second.first & SETTINGS_FLAG_PLEASE_PERSIST) != 0,
(it->second.first & SETTINGS_FLAG_PERSISTED) != 0,
it->second.second);
}
return spdy_framer_.SerializeSettings(settings_ir);
}
SpdyFrame* BufferedSpdyFramer::CreatePingFrame(uint32 unique_id,
bool is_ack) const {
SpdyPingIR ping_ir(unique_id);
ping_ir.set_is_ack(is_ack);
return spdy_framer_.SerializePing(ping_ir);
}
SpdyFrame* BufferedSpdyFramer::CreateGoAway(
SpdyStreamId last_accepted_stream_id,
SpdyGoAwayStatus status) const {
SpdyGoAwayIR go_ir(last_accepted_stream_id, status, "");
return spdy_framer_.SerializeGoAway(go_ir);
}
SpdyFrame* BufferedSpdyFramer::CreateHeaders(
SpdyStreamId stream_id,
SpdyControlFlags flags,
const SpdyHeaderBlock* headers) {
SpdyHeadersIR headers_ir(stream_id);
headers_ir.set_fin((flags & CONTROL_FLAG_FIN) != 0);
headers_ir.set_name_value_block(*headers);
return spdy_framer_.SerializeHeaders(headers_ir);
}
SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate(
SpdyStreamId stream_id,
uint32 delta_window_size) const {
SpdyWindowUpdateIR update_ir(stream_id, delta_window_size);
return spdy_framer_.SerializeWindowUpdate(update_ir);
}
SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id,
const char* data,
uint32 len,
SpdyDataFlags flags) {
SpdyDataIR data_ir(stream_id,
base::StringPiece(data, len));
data_ir.set_fin((flags & DATA_FLAG_FIN) != 0);
return spdy_framer_.SerializeData(data_ir);
}
SpdyPriority BufferedSpdyFramer::GetHighestPriority() const {
return spdy_framer_.GetHighestPriority();
}
void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) {
memset(header_buffer_, 0, kHeaderBufferSize);
header_buffer_used_ = 0;
header_buffer_valid_ = true;
header_stream_id_ = stream_id;
DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream);
}
}