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. 4 5 #include "net/spdy/buffered_spdy_framer.h" 6 7 #include "base/logging.h" 8 9 namespace net { 10 11 SpdyMajorVersion NextProtoToSpdyMajorVersion(NextProto next_proto) { 12 switch (next_proto) { 13 case kProtoDeprecatedSPDY2: 14 return SPDY2; 15 case kProtoSPDY3: 16 case kProtoSPDY31: 17 return SPDY3; 18 // SPDY/4 and HTTP/2 share the same framing for now. 19 case kProtoSPDY4a2: 20 case kProtoHTTP2Draft04: 21 return SPDY4; 22 case kProtoUnknown: 23 case kProtoHTTP11: 24 case kProtoQUIC1SPDY3: 25 break; 26 } 27 NOTREACHED(); 28 return SPDY2; 29 } 30 31 BufferedSpdyFramer::BufferedSpdyFramer(SpdyMajorVersion version, 32 bool enable_compression) 33 : spdy_framer_(version), 34 visitor_(NULL), 35 header_buffer_used_(0), 36 header_buffer_valid_(false), 37 header_stream_id_(SpdyFramer::kInvalidStream), 38 frames_received_(0) { 39 spdy_framer_.set_enable_compression(enable_compression); 40 memset(header_buffer_, 0, sizeof(header_buffer_)); 41 } 42 43 BufferedSpdyFramer::~BufferedSpdyFramer() { 44 } 45 46 void BufferedSpdyFramer::set_visitor( 47 BufferedSpdyFramerVisitorInterface* visitor) { 48 visitor_ = visitor; 49 spdy_framer_.set_visitor(this); 50 } 51 52 void BufferedSpdyFramer::set_debug_visitor( 53 SpdyFramerDebugVisitorInterface* debug_visitor) { 54 spdy_framer_.set_debug_visitor(debug_visitor); 55 } 56 57 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) { 58 DCHECK(spdy_framer); 59 visitor_->OnError(spdy_framer->error_code()); 60 } 61 62 void BufferedSpdyFramer::OnSynStream(SpdyStreamId stream_id, 63 SpdyStreamId associated_stream_id, 64 SpdyPriority priority, 65 uint8 credential_slot, 66 bool fin, 67 bool unidirectional) { 68 frames_received_++; 69 DCHECK(!control_frame_fields_.get()); 70 control_frame_fields_.reset(new ControlFrameFields()); 71 control_frame_fields_->type = SYN_STREAM; 72 control_frame_fields_->stream_id = stream_id; 73 control_frame_fields_->associated_stream_id = associated_stream_id; 74 control_frame_fields_->priority = priority; 75 control_frame_fields_->credential_slot = credential_slot; 76 control_frame_fields_->fin = fin; 77 control_frame_fields_->unidirectional = unidirectional; 78 79 InitHeaderStreaming(stream_id); 80 } 81 82 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id, 83 bool fin) { 84 frames_received_++; 85 DCHECK(!control_frame_fields_.get()); 86 control_frame_fields_.reset(new ControlFrameFields()); 87 control_frame_fields_->type = HEADERS; 88 control_frame_fields_->stream_id = stream_id; 89 control_frame_fields_->fin = fin; 90 91 InitHeaderStreaming(stream_id); 92 } 93 94 void BufferedSpdyFramer::OnSynReply(SpdyStreamId stream_id, 95 bool fin) { 96 frames_received_++; 97 DCHECK(!control_frame_fields_.get()); 98 control_frame_fields_.reset(new ControlFrameFields()); 99 control_frame_fields_->type = SYN_REPLY; 100 control_frame_fields_->stream_id = stream_id; 101 control_frame_fields_->fin = fin; 102 103 InitHeaderStreaming(stream_id); 104 } 105 106 bool BufferedSpdyFramer::OnCredentialFrameData(const char* frame_data, 107 size_t len) { 108 DCHECK(false); 109 return false; 110 } 111 112 bool BufferedSpdyFramer::OnControlFrameHeaderData(SpdyStreamId stream_id, 113 const char* header_data, 114 size_t len) { 115 CHECK_EQ(header_stream_id_, stream_id); 116 117 if (len == 0) { 118 // Indicates end-of-header-block. 119 CHECK(header_buffer_valid_); 120 121 SpdyHeaderBlock headers; 122 size_t parsed_len = spdy_framer_.ParseHeaderBlockInBuffer( 123 header_buffer_, header_buffer_used_, &headers); 124 // TODO(rch): this really should be checking parsed_len != len, 125 // but a bunch of tests fail. Need to figure out why. 126 if (parsed_len == 0) { 127 visitor_->OnStreamError( 128 stream_id, "Could not parse Spdy Control Frame Header."); 129 return false; 130 } 131 DCHECK(control_frame_fields_.get()); 132 switch (control_frame_fields_->type) { 133 case SYN_STREAM: 134 visitor_->OnSynStream(control_frame_fields_->stream_id, 135 control_frame_fields_->associated_stream_id, 136 control_frame_fields_->priority, 137 control_frame_fields_->credential_slot, 138 control_frame_fields_->fin, 139 control_frame_fields_->unidirectional, 140 headers); 141 break; 142 case SYN_REPLY: 143 visitor_->OnSynReply(control_frame_fields_->stream_id, 144 control_frame_fields_->fin, 145 headers); 146 break; 147 case HEADERS: 148 visitor_->OnHeaders(control_frame_fields_->stream_id, 149 control_frame_fields_->fin, 150 headers); 151 break; 152 default: 153 DCHECK(false) << "Unexpect control frame type: " 154 << control_frame_fields_->type; 155 break; 156 } 157 control_frame_fields_.reset(NULL); 158 return true; 159 } 160 161 const size_t available = kHeaderBufferSize - header_buffer_used_; 162 if (len > available) { 163 header_buffer_valid_ = false; 164 visitor_->OnStreamError( 165 stream_id, "Received more data than the allocated size."); 166 return false; 167 } 168 memcpy(header_buffer_ + header_buffer_used_, header_data, len); 169 header_buffer_used_ += len; 170 return true; 171 } 172 173 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, 174 size_t length, 175 bool fin) { 176 frames_received_++; 177 header_stream_id_ = stream_id; 178 visitor_->OnDataFrameHeader(stream_id, length, fin); 179 } 180 181 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, 182 const char* data, 183 size_t len, 184 bool fin) { 185 visitor_->OnStreamFrameData(stream_id, data, len, fin); 186 } 187 188 void BufferedSpdyFramer::OnSettings(bool clear_persisted) { 189 visitor_->OnSettings(clear_persisted); 190 } 191 192 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id, 193 uint8 flags, 194 uint32 value) { 195 visitor_->OnSetting(id, flags, value); 196 } 197 198 void BufferedSpdyFramer::OnPing(uint32 unique_id) { 199 visitor_->OnPing(unique_id); 200 } 201 202 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id, 203 SpdyRstStreamStatus status) { 204 visitor_->OnRstStream(stream_id, status); 205 } 206 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id, 207 SpdyGoAwayStatus status) { 208 visitor_->OnGoAway(last_accepted_stream_id, status); 209 } 210 211 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id, 212 uint32 delta_window_size) { 213 visitor_->OnWindowUpdate(stream_id, delta_window_size); 214 } 215 216 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id, 217 SpdyStreamId promised_stream_id) { 218 visitor_->OnPushPromise(stream_id, promised_stream_id); 219 } 220 221 SpdyMajorVersion BufferedSpdyFramer::protocol_version() { 222 return spdy_framer_.protocol_version(); 223 } 224 225 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) { 226 return spdy_framer_.ProcessInput(data, len); 227 } 228 229 void BufferedSpdyFramer::Reset() { 230 spdy_framer_.Reset(); 231 } 232 233 SpdyFramer::SpdyError BufferedSpdyFramer::error_code() const { 234 return spdy_framer_.error_code(); 235 } 236 237 SpdyFramer::SpdyState BufferedSpdyFramer::state() const { 238 return spdy_framer_.state(); 239 } 240 241 bool BufferedSpdyFramer::MessageFullyRead() { 242 return state() == SpdyFramer::SPDY_AUTO_RESET; 243 } 244 245 bool BufferedSpdyFramer::HasError() { 246 return spdy_framer_.HasError(); 247 } 248 249 SpdyFrame* BufferedSpdyFramer::CreateSynStream( 250 SpdyStreamId stream_id, 251 SpdyStreamId associated_stream_id, 252 SpdyPriority priority, 253 uint8 credential_slot, 254 SpdyControlFlags flags, 255 const SpdyHeaderBlock* headers) { 256 return spdy_framer_.CreateSynStream(stream_id, associated_stream_id, priority, 257 credential_slot, flags, headers); 258 } 259 260 SpdyFrame* BufferedSpdyFramer::CreateSynReply( 261 SpdyStreamId stream_id, 262 SpdyControlFlags flags, 263 const SpdyHeaderBlock* headers) { 264 return spdy_framer_.CreateSynReply(stream_id, flags, headers); 265 } 266 267 SpdyFrame* BufferedSpdyFramer::CreateRstStream( 268 SpdyStreamId stream_id, 269 SpdyRstStreamStatus status) const { 270 return spdy_framer_.CreateRstStream(stream_id, status); 271 } 272 273 SpdyFrame* BufferedSpdyFramer::CreateSettings( 274 const SettingsMap& values) const { 275 return spdy_framer_.CreateSettings(values); 276 } 277 278 SpdyFrame* BufferedSpdyFramer::CreatePingFrame( 279 uint32 unique_id) const { 280 return spdy_framer_.CreatePingFrame(unique_id); 281 } 282 283 SpdyFrame* BufferedSpdyFramer::CreateGoAway( 284 SpdyStreamId last_accepted_stream_id, 285 SpdyGoAwayStatus status) const { 286 return spdy_framer_.CreateGoAway(last_accepted_stream_id, status); 287 } 288 289 SpdyFrame* BufferedSpdyFramer::CreateHeaders( 290 SpdyStreamId stream_id, 291 SpdyControlFlags flags, 292 const SpdyHeaderBlock* headers) { 293 return spdy_framer_.CreateHeaders(stream_id, flags, headers); 294 } 295 296 SpdyFrame* BufferedSpdyFramer::CreateWindowUpdate( 297 SpdyStreamId stream_id, 298 uint32 delta_window_size) const { 299 return spdy_framer_.CreateWindowUpdate(stream_id, delta_window_size); 300 } 301 302 SpdyFrame* BufferedSpdyFramer::CreateDataFrame(SpdyStreamId stream_id, 303 const char* data, 304 uint32 len, 305 SpdyDataFlags flags) { 306 return spdy_framer_.CreateDataFrame(stream_id, data, len, flags); 307 } 308 309 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { 310 return spdy_framer_.GetHighestPriority(); 311 } 312 313 void BufferedSpdyFramer::InitHeaderStreaming(SpdyStreamId stream_id) { 314 memset(header_buffer_, 0, kHeaderBufferSize); 315 header_buffer_used_ = 0; 316 header_buffer_valid_ = true; 317 header_stream_id_ = stream_id; 318 DCHECK_NE(header_stream_id_, SpdyFramer::kInvalidStream); 319 } 320 321 } // namespace net 322