| OLD | NEW |
| (Empty) |
| 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 <algorithm> | |
| 8 #include <utility> | |
| 9 | |
| 10 #include "base/logging.h" | |
| 11 #include "base/memory/ptr_util.h" | |
| 12 #include "base/strings/string_util.h" | |
| 13 #include "net/spdy/platform/api/spdy_estimate_memory_usage.h" | |
| 14 | |
| 15 namespace net { | |
| 16 | |
| 17 namespace { | |
| 18 | |
| 19 // GOAWAY frame debug data is only buffered up to this many bytes. | |
| 20 size_t kGoAwayDebugDataMaxSize = 1024; | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 24 BufferedSpdyFramer::BufferedSpdyFramer() | |
| 25 : spdy_framer_(SpdyFramer::ENABLE_COMPRESSION), | |
| 26 visitor_(NULL), | |
| 27 frames_received_(0) {} | |
| 28 | |
| 29 BufferedSpdyFramer::~BufferedSpdyFramer() { | |
| 30 } | |
| 31 | |
| 32 void BufferedSpdyFramer::set_visitor( | |
| 33 BufferedSpdyFramerVisitorInterface* visitor) { | |
| 34 visitor_ = visitor; | |
| 35 spdy_framer_.set_visitor(this); | |
| 36 } | |
| 37 | |
| 38 void BufferedSpdyFramer::set_debug_visitor( | |
| 39 SpdyFramerDebugVisitorInterface* debug_visitor) { | |
| 40 spdy_framer_.set_debug_visitor(debug_visitor); | |
| 41 } | |
| 42 | |
| 43 void BufferedSpdyFramer::OnError(SpdyFramer* spdy_framer) { | |
| 44 DCHECK(spdy_framer); | |
| 45 visitor_->OnError(spdy_framer->spdy_framer_error()); | |
| 46 } | |
| 47 | |
| 48 void BufferedSpdyFramer::OnHeaders(SpdyStreamId stream_id, | |
| 49 bool has_priority, | |
| 50 int weight, | |
| 51 SpdyStreamId parent_stream_id, | |
| 52 bool exclusive, | |
| 53 bool fin, | |
| 54 bool end) { | |
| 55 frames_received_++; | |
| 56 DCHECK(!control_frame_fields_.get()); | |
| 57 control_frame_fields_.reset(new ControlFrameFields()); | |
| 58 control_frame_fields_->type = SpdyFrameType::HEADERS; | |
| 59 control_frame_fields_->stream_id = stream_id; | |
| 60 control_frame_fields_->has_priority = has_priority; | |
| 61 if (control_frame_fields_->has_priority) { | |
| 62 control_frame_fields_->weight = weight; | |
| 63 control_frame_fields_->parent_stream_id = parent_stream_id; | |
| 64 control_frame_fields_->exclusive = exclusive; | |
| 65 } | |
| 66 control_frame_fields_->fin = fin; | |
| 67 | |
| 68 DCHECK_NE(stream_id, SpdyFramer::kInvalidStream); | |
| 69 } | |
| 70 | |
| 71 void BufferedSpdyFramer::OnDataFrameHeader(SpdyStreamId stream_id, | |
| 72 size_t length, | |
| 73 bool fin) { | |
| 74 frames_received_++; | |
| 75 visitor_->OnDataFrameHeader(stream_id, length, fin); | |
| 76 } | |
| 77 | |
| 78 void BufferedSpdyFramer::OnStreamFrameData(SpdyStreamId stream_id, | |
| 79 const char* data, | |
| 80 size_t len) { | |
| 81 visitor_->OnStreamFrameData(stream_id, data, len); | |
| 82 } | |
| 83 | |
| 84 void BufferedSpdyFramer::OnStreamEnd(SpdyStreamId stream_id) { | |
| 85 visitor_->OnStreamEnd(stream_id); | |
| 86 } | |
| 87 | |
| 88 void BufferedSpdyFramer::OnStreamPadding(SpdyStreamId stream_id, size_t len) { | |
| 89 visitor_->OnStreamPadding(stream_id, len); | |
| 90 } | |
| 91 | |
| 92 SpdyHeadersHandlerInterface* BufferedSpdyFramer::OnHeaderFrameStart( | |
| 93 SpdyStreamId stream_id) { | |
| 94 coalescer_.reset(new HeaderCoalescer()); | |
| 95 return coalescer_.get(); | |
| 96 } | |
| 97 | |
| 98 void BufferedSpdyFramer::OnHeaderFrameEnd(SpdyStreamId stream_id, | |
| 99 bool end_headers) { | |
| 100 if (coalescer_->error_seen()) { | |
| 101 visitor_->OnStreamError(stream_id, | |
| 102 "Could not parse Spdy Control Frame Header."); | |
| 103 control_frame_fields_.reset(); | |
| 104 return; | |
| 105 } | |
| 106 DCHECK(control_frame_fields_.get()); | |
| 107 switch (control_frame_fields_->type) { | |
| 108 case SpdyFrameType::HEADERS: | |
| 109 visitor_->OnHeaders( | |
| 110 control_frame_fields_->stream_id, control_frame_fields_->has_priority, | |
| 111 control_frame_fields_->weight, | |
| 112 control_frame_fields_->parent_stream_id, | |
| 113 control_frame_fields_->exclusive, control_frame_fields_->fin, | |
| 114 coalescer_->release_headers()); | |
| 115 break; | |
| 116 case SpdyFrameType::PUSH_PROMISE: | |
| 117 visitor_->OnPushPromise(control_frame_fields_->stream_id, | |
| 118 control_frame_fields_->promised_stream_id, | |
| 119 coalescer_->release_headers()); | |
| 120 break; | |
| 121 default: | |
| 122 DCHECK(false) << "Unexpect control frame type: " | |
| 123 << control_frame_fields_->type; | |
| 124 break; | |
| 125 } | |
| 126 control_frame_fields_.reset(NULL); | |
| 127 } | |
| 128 | |
| 129 void BufferedSpdyFramer::OnSettings(bool clear_persisted) { | |
| 130 visitor_->OnSettings(); | |
| 131 } | |
| 132 | |
| 133 void BufferedSpdyFramer::OnSetting(SpdySettingsIds id, uint32_t value) { | |
| 134 visitor_->OnSetting(id, value); | |
| 135 } | |
| 136 | |
| 137 void BufferedSpdyFramer::OnSettingsAck() { | |
| 138 visitor_->OnSettingsAck(); | |
| 139 } | |
| 140 | |
| 141 void BufferedSpdyFramer::OnSettingsEnd() { | |
| 142 visitor_->OnSettingsEnd(); | |
| 143 } | |
| 144 | |
| 145 void BufferedSpdyFramer::OnPing(SpdyPingId unique_id, bool is_ack) { | |
| 146 visitor_->OnPing(unique_id, is_ack); | |
| 147 } | |
| 148 | |
| 149 void BufferedSpdyFramer::OnRstStream(SpdyStreamId stream_id, | |
| 150 SpdyErrorCode error_code) { | |
| 151 visitor_->OnRstStream(stream_id, error_code); | |
| 152 } | |
| 153 void BufferedSpdyFramer::OnGoAway(SpdyStreamId last_accepted_stream_id, | |
| 154 SpdyErrorCode error_code) { | |
| 155 DCHECK(!goaway_fields_); | |
| 156 goaway_fields_.reset(new GoAwayFields()); | |
| 157 goaway_fields_->last_accepted_stream_id = last_accepted_stream_id; | |
| 158 goaway_fields_->error_code = error_code; | |
| 159 } | |
| 160 | |
| 161 bool BufferedSpdyFramer::OnGoAwayFrameData(const char* goaway_data, | |
| 162 size_t len) { | |
| 163 if (len > 0) { | |
| 164 if (goaway_fields_->debug_data.size() < kGoAwayDebugDataMaxSize) { | |
| 165 goaway_fields_->debug_data.append( | |
| 166 goaway_data, std::min(len, kGoAwayDebugDataMaxSize - | |
| 167 goaway_fields_->debug_data.size())); | |
| 168 } | |
| 169 return true; | |
| 170 } | |
| 171 visitor_->OnGoAway(goaway_fields_->last_accepted_stream_id, | |
| 172 goaway_fields_->error_code, goaway_fields_->debug_data); | |
| 173 goaway_fields_.reset(); | |
| 174 return true; | |
| 175 } | |
| 176 | |
| 177 void BufferedSpdyFramer::OnWindowUpdate(SpdyStreamId stream_id, | |
| 178 int delta_window_size) { | |
| 179 visitor_->OnWindowUpdate(stream_id, delta_window_size); | |
| 180 } | |
| 181 | |
| 182 void BufferedSpdyFramer::OnPushPromise(SpdyStreamId stream_id, | |
| 183 SpdyStreamId promised_stream_id, | |
| 184 bool end) { | |
| 185 frames_received_++; | |
| 186 DCHECK(!control_frame_fields_.get()); | |
| 187 control_frame_fields_.reset(new ControlFrameFields()); | |
| 188 control_frame_fields_->type = SpdyFrameType::PUSH_PROMISE; | |
| 189 control_frame_fields_->stream_id = stream_id; | |
| 190 control_frame_fields_->promised_stream_id = promised_stream_id; | |
| 191 | |
| 192 DCHECK_NE(stream_id, SpdyFramer::kInvalidStream); | |
| 193 } | |
| 194 | |
| 195 void BufferedSpdyFramer::OnAltSvc( | |
| 196 SpdyStreamId stream_id, | |
| 197 SpdyStringPiece origin, | |
| 198 const SpdyAltSvcWireFormat::AlternativeServiceVector& altsvc_vector) { | |
| 199 visitor_->OnAltSvc(stream_id, origin, altsvc_vector); | |
| 200 } | |
| 201 | |
| 202 void BufferedSpdyFramer::OnContinuation(SpdyStreamId stream_id, bool end) { | |
| 203 } | |
| 204 | |
| 205 bool BufferedSpdyFramer::OnUnknownFrame(SpdyStreamId stream_id, | |
| 206 uint8_t frame_type) { | |
| 207 return visitor_->OnUnknownFrame(stream_id, frame_type); | |
| 208 } | |
| 209 | |
| 210 size_t BufferedSpdyFramer::ProcessInput(const char* data, size_t len) { | |
| 211 return spdy_framer_.ProcessInput(data, len); | |
| 212 } | |
| 213 | |
| 214 void BufferedSpdyFramer::UpdateHeaderDecoderTableSize(uint32_t value) { | |
| 215 spdy_framer_.UpdateHeaderDecoderTableSize(value); | |
| 216 } | |
| 217 | |
| 218 void BufferedSpdyFramer::Reset() { | |
| 219 spdy_framer_.Reset(); | |
| 220 } | |
| 221 | |
| 222 SpdyFramer::SpdyFramerError BufferedSpdyFramer::spdy_framer_error() const { | |
| 223 return spdy_framer_.spdy_framer_error(); | |
| 224 } | |
| 225 | |
| 226 SpdyFramer::SpdyState BufferedSpdyFramer::state() const { | |
| 227 return spdy_framer_.state(); | |
| 228 } | |
| 229 | |
| 230 bool BufferedSpdyFramer::MessageFullyRead() { | |
| 231 return state() == SpdyFramer::SPDY_FRAME_COMPLETE; | |
| 232 } | |
| 233 | |
| 234 bool BufferedSpdyFramer::HasError() { | |
| 235 return spdy_framer_.HasError(); | |
| 236 } | |
| 237 | |
| 238 // TODO(jgraettinger): Eliminate uses of this method (prefer | |
| 239 // SpdyRstStreamIR). | |
| 240 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateRstStream( | |
| 241 SpdyStreamId stream_id, | |
| 242 SpdyErrorCode error_code) const { | |
| 243 SpdyRstStreamIR rst_ir(stream_id, error_code); | |
| 244 return base::MakeUnique<SpdySerializedFrame>( | |
| 245 spdy_framer_.SerializeRstStream(rst_ir)); | |
| 246 } | |
| 247 | |
| 248 // TODO(jgraettinger): Eliminate uses of this method (prefer | |
| 249 // SpdySettingsIR). | |
| 250 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateSettings( | |
| 251 const SettingsMap& values) const { | |
| 252 SpdySettingsIR settings_ir; | |
| 253 for (SettingsMap::const_iterator it = values.begin(); it != values.end(); | |
| 254 ++it) { | |
| 255 settings_ir.AddSetting(it->first, it->second); | |
| 256 } | |
| 257 return base::MakeUnique<SpdySerializedFrame>( | |
| 258 spdy_framer_.SerializeSettings(settings_ir)); | |
| 259 } | |
| 260 | |
| 261 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyPingIR). | |
| 262 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreatePingFrame( | |
| 263 SpdyPingId unique_id, | |
| 264 bool is_ack) const { | |
| 265 SpdyPingIR ping_ir(unique_id); | |
| 266 ping_ir.set_is_ack(is_ack); | |
| 267 return base::MakeUnique<SpdySerializedFrame>( | |
| 268 spdy_framer_.SerializePing(ping_ir)); | |
| 269 } | |
| 270 | |
| 271 // TODO(jgraettinger): Eliminate uses of this method (prefer | |
| 272 // SpdyWindowUpdateIR). | |
| 273 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateWindowUpdate( | |
| 274 SpdyStreamId stream_id, | |
| 275 uint32_t delta_window_size) const { | |
| 276 SpdyWindowUpdateIR update_ir(stream_id, delta_window_size); | |
| 277 return base::MakeUnique<SpdySerializedFrame>( | |
| 278 spdy_framer_.SerializeWindowUpdate(update_ir)); | |
| 279 } | |
| 280 | |
| 281 // TODO(jgraettinger): Eliminate uses of this method (prefer SpdyDataIR). | |
| 282 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreateDataFrame( | |
| 283 SpdyStreamId stream_id, | |
| 284 const char* data, | |
| 285 uint32_t len, | |
| 286 SpdyDataFlags flags) { | |
| 287 SpdyDataIR data_ir(stream_id, SpdyStringPiece(data, len)); | |
| 288 data_ir.set_fin((flags & DATA_FLAG_FIN) != 0); | |
| 289 return base::MakeUnique<SpdySerializedFrame>( | |
| 290 spdy_framer_.SerializeData(data_ir)); | |
| 291 } | |
| 292 | |
| 293 // TODO(jgraettinger): Eliminate uses of this method (prefer | |
| 294 // SpdyPriorityIR). | |
| 295 std::unique_ptr<SpdySerializedFrame> BufferedSpdyFramer::CreatePriority( | |
| 296 SpdyStreamId stream_id, | |
| 297 SpdyStreamId dependency_id, | |
| 298 int weight, | |
| 299 bool exclusive) const { | |
| 300 SpdyPriorityIR priority_ir(stream_id, dependency_id, weight, exclusive); | |
| 301 return base::MakeUnique<SpdySerializedFrame>( | |
| 302 spdy_framer_.SerializePriority(priority_ir)); | |
| 303 } | |
| 304 | |
| 305 SpdyPriority BufferedSpdyFramer::GetHighestPriority() const { | |
| 306 return spdy_framer_.GetHighestPriority(); | |
| 307 } | |
| 308 | |
| 309 size_t BufferedSpdyFramer::EstimateMemoryUsage() const { | |
| 310 return SpdyEstimateMemoryUsage(spdy_framer_) + | |
| 311 SpdyEstimateMemoryUsage(coalescer_) + | |
| 312 SpdyEstimateMemoryUsage(control_frame_fields_) + | |
| 313 SpdyEstimateMemoryUsage(goaway_fields_); | |
| 314 } | |
| 315 | |
| 316 size_t BufferedSpdyFramer::GoAwayFields::EstimateMemoryUsage() const { | |
| 317 return SpdyEstimateMemoryUsage(debug_data); | |
| 318 } | |
| 319 | |
| 320 } // namespace net | |
| OLD | NEW |