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