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 |