1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/spdy/buffered_spdy_framer.h"
7 #include "base/logging.h"
11 BufferedSpdyFramer::BufferedSpdyFramer(int version
, bool enable_compression
)
12 : spdy_framer_(version
),
14 header_buffer_used_(0),
15 header_buffer_valid_(false),
16 header_stream_id_(SpdyFramer::kInvalidStream
),
18 spdy_framer_
.set_enable_compression(enable_compression
);
19 memset(header_buffer_
, 0, sizeof(header_buffer_
));
22 BufferedSpdyFramer::~BufferedSpdyFramer() {
25 void BufferedSpdyFramer::set_visitor(
26 BufferedSpdyFramerVisitorInterface
* visitor
) {
28 spdy_framer_
.set_visitor(this);
31 void BufferedSpdyFramer::OnError(SpdyFramer
* spdy_framer
) {
33 visitor_
->OnError(spdy_framer
->error_code());
36 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id
,
37 SpdyStreamId associated_stream_id
,
38 SpdyPriority priority
,
39 uint8 credential_slot
,
41 bool unidirectional
) {
43 DCHECK(!control_frame_fields_
.get());
44 control_frame_fields_
.reset(new ControlFrameFields());
45 control_frame_fields_
->type
= SYN_STREAM
;
46 control_frame_fields_
->stream_id
= stream_id
;
47 control_frame_fields_
->associated_stream_id
= associated_stream_id
;
48 control_frame_fields_
->priority
= priority
;
49 control_frame_fields_
->credential_slot
= credential_slot
;
50 control_frame_fields_
->fin
= fin
;
51 control_frame_fields_
->unidirectional
= unidirectional
;
53 InitHeaderStreaming(stream_id
);
56 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id
,
59 DCHECK(!control_frame_fields_
.get());
60 control_frame_fields_
.reset(new ControlFrameFields());
61 control_frame_fields_
->type
= HEADERS
;
62 control_frame_fields_
->stream_id
= stream_id
;
63 control_frame_fields_
->fin
= fin
;
65 InitHeaderStreaming(stream_id
);
68 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id
,
71 DCHECK(!control_frame_fields_
.get());
72 control_frame_fields_
.reset(new ControlFrameFields());
73 control_frame_fields_
->type
= SYN_REPLY
;
74 control_frame_fields_
->stream_id
= stream_id
;
75 control_frame_fields_
->fin
= fin
;
77 InitHeaderStreaming(stream_id
);
80 bool BufferedSpdyFramer::OnCredentialFrameData(const char* frame_data
,
86 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id
,
87 const char* header_data
,
89 CHECK_EQ(header_stream_id_
, stream_id
);
92 // Indicates end-of-header-block.
93 CHECK(header_buffer_valid_
);
95 SpdyHeaderBlock headers
;
96 bool parsed_headers
= spdy_framer_
.ParseHeaderBlockInBuffer(
97 header_buffer_
, header_buffer_used_
, &headers
);
98 if (!parsed_headers
) {
99 visitor_
->OnStreamError(
100 stream_id
, "Could not parse Spdy Control Frame Header.");
103 DCHECK(control_frame_fields_
.get());
104 switch (control_frame_fields_
->type
) {
106 visitor_
->OnSynStream(control_frame_fields_
->stream_id
,
107 control_frame_fields_
->associated_stream_id
,
108 control_frame_fields_
->priority
,
109 control_frame_fields_
->credential_slot
,
110 control_frame_fields_
->fin
,
111 control_frame_fields_
->unidirectional
,
115 visitor_
->OnSynReply(control_frame_fields_
->stream_id
,
116 control_frame_fields_
->fin
,
120 visitor_
->OnHeaders(control_frame_fields_
->stream_id
,
121 control_frame_fields_
->fin
,
125 DCHECK(false) << "Unexpect control frame type: "
126 << control_frame_fields_
->type
;
129 control_frame_fields_
.reset(NULL
);
133 const size_t available
= kHeaderBufferSize
- header_buffer_used_
;
134 if (len
> available
) {
135 header_buffer_valid_
= false;
136 visitor_
->OnStreamError(
137 stream_id
, "Received more data than the allocated size.");
140 memcpy(header_buffer_
+ header_buffer_used_
, header_data
, len
);
141 header_buffer_used_
+= len
;
145 void BufferedSpdyFramer::OnDataFrameHeader(const SpdyDataFrame
* frame
) {
147 header_stream_id_
= frame
->stream_id();
150 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id
,
153 SpdyDataFlags flags
) {
154 visitor_
->OnStreamFrameData(stream_id
, data
, len
, flags
);
157 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id
,
160 visitor_
->OnSetting(id
, flags
, value
);
163 void BufferedSpdyFramer::OnPing(uint32 unique_id
) {
164 visitor_
->OnPing(unique_id
);
167 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id
,
168 SpdyStatusCodes status
) {
169 visitor_
->OnRstStream(stream_id
, status
);
171 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id
,
172 SpdyGoAwayStatus status
) {
173 visitor_
->OnGoAway(last_accepted_stream_id
, status
);
176 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id
,
177 int delta_window_size
) {
178 visitor_
->OnWindowUpdate(stream_id
, delta_window_size
);
181 void BufferedSpdyFramer::OnControlFrameCompressed(
182 const SpdyControlFrame
& uncompressed_frame
,
183 const SpdyControlFrame
& compressed_frame
) {
184 visitor_
->OnControlFrameCompressed(uncompressed_frame
, compressed_frame
);
188 int BufferedSpdyFramer::protocol_version() {
189 return spdy_framer_
.protocol_version();
192 size_t BufferedSpdyFramer::ProcessInput(const char* data
, size_t len
) {
193 return spdy_framer_
.ProcessInput(data
, len
);
196 void BufferedSpdyFramer::Reset() {
197 spdy_framer_
.Reset();
200 SpdyFramer::SpdyError
BufferedSpdyFramer::error_code() const {
201 return spdy_framer_
.error_code();
204 SpdyFramer::SpdyState
BufferedSpdyFramer::state() const {
205 return spdy_framer_
.state();
208 bool BufferedSpdyFramer::MessageFullyRead() {
209 return spdy_framer_
.MessageFullyRead();
212 bool BufferedSpdyFramer::HasError() {
213 return spdy_framer_
.HasError();
216 SpdySynStreamControlFrame
* BufferedSpdyFramer::CreateSynStream(
217 SpdyStreamId stream_id
,
218 SpdyStreamId associated_stream_id
,
219 SpdyPriority priority
,
220 uint8 credential_slot
,
221 SpdyControlFlags flags
,
223 const SpdyHeaderBlock
* headers
) {
224 return spdy_framer_
.CreateSynStream(stream_id
, associated_stream_id
, priority
,
225 credential_slot
, flags
, compressed
,
229 SpdySynReplyControlFrame
* BufferedSpdyFramer::CreateSynReply(
230 SpdyStreamId stream_id
,
231 SpdyControlFlags flags
,
233 const SpdyHeaderBlock
* headers
) {
234 return spdy_framer_
.CreateSynReply(stream_id
, flags
, compressed
, headers
);
237 SpdyRstStreamControlFrame
* BufferedSpdyFramer::CreateRstStream(
238 SpdyStreamId stream_id
,
239 SpdyStatusCodes status
) const {
240 return spdy_framer_
.CreateRstStream(stream_id
, status
);
243 SpdySettingsControlFrame
* BufferedSpdyFramer::CreateSettings(
244 const SettingsMap
& values
) const {
245 return spdy_framer_
.CreateSettings(values
);
248 SpdyPingControlFrame
* BufferedSpdyFramer::CreatePingFrame(
249 uint32 unique_id
) const {
250 return spdy_framer_
.CreatePingFrame(unique_id
);
253 SpdyGoAwayControlFrame
* BufferedSpdyFramer::CreateGoAway(
254 SpdyStreamId last_accepted_stream_id
,
255 SpdyGoAwayStatus status
) const {
256 return spdy_framer_
.CreateGoAway(last_accepted_stream_id
, status
);
259 SpdyHeadersControlFrame
* BufferedSpdyFramer::CreateHeaders(
260 SpdyStreamId stream_id
,
261 SpdyControlFlags flags
,
263 const SpdyHeaderBlock
* headers
) {
264 return spdy_framer_
.CreateHeaders(stream_id
, flags
, compressed
, headers
);
267 SpdyWindowUpdateControlFrame
* BufferedSpdyFramer::CreateWindowUpdate(
268 SpdyStreamId stream_id
,
269 uint32 delta_window_size
) const {
270 return spdy_framer_
.CreateWindowUpdate(stream_id
, delta_window_size
);
273 SpdyCredentialControlFrame
* BufferedSpdyFramer::CreateCredentialFrame(
274 const SpdyCredential
& credential
) const {
275 return spdy_framer_
.CreateCredentialFrame(credential
);
278 SpdyDataFrame
* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id
,
281 SpdyDataFlags flags
) {
282 return spdy_framer_
.CreateDataFrame(stream_id
, data
, len
, flags
);
285 SpdyPriority
BufferedSpdyFramer::GetHighestPriority() const {
286 return spdy_framer_
.GetHighestPriority();
289 bool BufferedSpdyFramer::IsCompressible(const SpdyFrame
& frame
) const {
290 return spdy_framer_
.IsCompressible(frame
);
293 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id
) {
294 memset(header_buffer_
, 0, kHeaderBufferSize
);
295 header_buffer_used_
= 0;
296 header_buffer_valid_
= true;
297 header_stream_id_
= stream_id
;
298 DCHECK_NE(header_stream_id_
, SpdyFramer::kInvalidStream
);