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/spdy_protocol.h" | |
6 | |
7 #include <ostream> | |
8 | |
9 #include "base/memory/ptr_util.h" | |
10 #include "net/spdy/spdy_bug_tracker.h" | |
11 | |
12 namespace net { | |
13 | |
14 const char* const kHttp2ConnectionHeaderPrefix = | |
15 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n"; | |
16 | |
17 std::ostream& operator<<(std::ostream& out, SpdySettingsIds id) { | |
18 return out << static_cast<uint16_t>(id); | |
19 } | |
20 | |
21 std::ostream& operator<<(std::ostream& out, SpdyFrameType frame_type) { | |
22 return out << SerializeFrameType(frame_type); | |
23 } | |
24 | |
25 SpdyPriority ClampSpdy3Priority(SpdyPriority priority) { | |
26 if (priority < kV3HighestPriority) { | |
27 SPDY_BUG << "Invalid priority: " << static_cast<int>(priority); | |
28 return kV3HighestPriority; | |
29 } | |
30 if (priority > kV3LowestPriority) { | |
31 SPDY_BUG << "Invalid priority: " << static_cast<int>(priority); | |
32 return kV3LowestPriority; | |
33 } | |
34 return priority; | |
35 } | |
36 | |
37 int ClampHttp2Weight(int weight) { | |
38 if (weight < kHttp2MinStreamWeight) { | |
39 SPDY_BUG << "Invalid weight: " << weight; | |
40 return kHttp2MinStreamWeight; | |
41 } | |
42 if (weight > kHttp2MaxStreamWeight) { | |
43 SPDY_BUG << "Invalid weight: " << weight; | |
44 return kHttp2MaxStreamWeight; | |
45 } | |
46 return weight; | |
47 } | |
48 | |
49 int Spdy3PriorityToHttp2Weight(SpdyPriority priority) { | |
50 priority = ClampSpdy3Priority(priority); | |
51 const float kSteps = 255.9f / 7.f; | |
52 return static_cast<int>(kSteps * (7.f - priority)) + 1; | |
53 } | |
54 | |
55 SpdyPriority Http2WeightToSpdy3Priority(int weight) { | |
56 weight = ClampHttp2Weight(weight); | |
57 const float kSteps = 255.9f / 7.f; | |
58 return static_cast<SpdyPriority>(7.f - (weight - 1) / kSteps); | |
59 } | |
60 | |
61 bool IsDefinedFrameType(uint8_t frame_type_field) { | |
62 return frame_type_field <= SerializeFrameType(SpdyFrameType::MAX_FRAME_TYPE); | |
63 } | |
64 | |
65 SpdyFrameType ParseFrameType(uint8_t frame_type_field) { | |
66 SPDY_BUG_IF(!IsDefinedFrameType(frame_type_field)) | |
67 << "Frame type not defined: " << static_cast<int>(frame_type_field); | |
68 return static_cast<SpdyFrameType>(frame_type_field); | |
69 } | |
70 | |
71 uint8_t SerializeFrameType(SpdyFrameType frame_type) { | |
72 return static_cast<uint8_t>(frame_type); | |
73 } | |
74 | |
75 bool IsValidHTTP2FrameStreamId(SpdyStreamId current_frame_stream_id, | |
76 SpdyFrameType frame_type_field) { | |
77 if (current_frame_stream_id == 0) { | |
78 switch (frame_type_field) { | |
79 case SpdyFrameType::DATA: | |
80 case SpdyFrameType::HEADERS: | |
81 case SpdyFrameType::PRIORITY: | |
82 case SpdyFrameType::RST_STREAM: | |
83 case SpdyFrameType::CONTINUATION: | |
84 case SpdyFrameType::PUSH_PROMISE: | |
85 // These frame types must specify a stream | |
86 return false; | |
87 default: | |
88 return true; | |
89 } | |
90 } else { | |
91 switch (frame_type_field) { | |
92 case SpdyFrameType::GOAWAY: | |
93 case SpdyFrameType::SETTINGS: | |
94 case SpdyFrameType::PING: | |
95 // These frame types must not specify a stream | |
96 return false; | |
97 default: | |
98 return true; | |
99 } | |
100 } | |
101 } | |
102 | |
103 const char* FrameTypeToString(SpdyFrameType frame_type) { | |
104 switch (frame_type) { | |
105 case SpdyFrameType::DATA: | |
106 return "DATA"; | |
107 case SpdyFrameType::RST_STREAM: | |
108 return "RST_STREAM"; | |
109 case SpdyFrameType::SETTINGS: | |
110 return "SETTINGS"; | |
111 case SpdyFrameType::PING: | |
112 return "PING"; | |
113 case SpdyFrameType::GOAWAY: | |
114 return "GOAWAY"; | |
115 case SpdyFrameType::HEADERS: | |
116 return "HEADERS"; | |
117 case SpdyFrameType::WINDOW_UPDATE: | |
118 return "WINDOW_UPDATE"; | |
119 case SpdyFrameType::PUSH_PROMISE: | |
120 return "PUSH_PROMISE"; | |
121 case SpdyFrameType::CONTINUATION: | |
122 return "CONTINUATION"; | |
123 case SpdyFrameType::PRIORITY: | |
124 return "PRIORITY"; | |
125 case SpdyFrameType::ALTSVC: | |
126 return "ALTSVC"; | |
127 case SpdyFrameType::EXTENSION: | |
128 return "EXTENSION (unspecified)"; | |
129 } | |
130 return "UNKNOWN_FRAME_TYPE"; | |
131 } | |
132 | |
133 bool ParseSettingsId(uint16_t wire_setting_id, SpdySettingsIds* setting_id) { | |
134 if (wire_setting_id < SETTINGS_MIN || wire_setting_id > SETTINGS_MAX) { | |
135 return false; | |
136 } | |
137 | |
138 *setting_id = static_cast<SpdySettingsIds>(wire_setting_id); | |
139 return true; | |
140 } | |
141 | |
142 bool SettingsIdToString(SpdySettingsIds id, const char** settings_id_string) { | |
143 switch (id) { | |
144 case SETTINGS_HEADER_TABLE_SIZE: | |
145 *settings_id_string = "SETTINGS_HEADER_TABLE_SIZE"; | |
146 return true; | |
147 case SETTINGS_ENABLE_PUSH: | |
148 *settings_id_string = "SETTINGS_ENABLE_PUSH"; | |
149 return true; | |
150 case SETTINGS_MAX_CONCURRENT_STREAMS: | |
151 *settings_id_string = "SETTINGS_MAX_CONCURRENT_STREAMS"; | |
152 return true; | |
153 case SETTINGS_INITIAL_WINDOW_SIZE: | |
154 *settings_id_string = "SETTINGS_INITIAL_WINDOW_SIZE"; | |
155 return true; | |
156 case SETTINGS_MAX_FRAME_SIZE: | |
157 *settings_id_string = "SETTINGS_MAX_FRAME_SIZE"; | |
158 return true; | |
159 case SETTINGS_MAX_HEADER_LIST_SIZE: | |
160 *settings_id_string = "SETTINGS_MAX_HEADER_LIST_SIZE"; | |
161 return true; | |
162 } | |
163 | |
164 *settings_id_string = "SETTINGS_UNKNOWN"; | |
165 return false; | |
166 } | |
167 | |
168 SpdyErrorCode ParseErrorCode(uint32_t wire_error_code) { | |
169 if (wire_error_code > ERROR_CODE_MAX) { | |
170 return ERROR_CODE_INTERNAL_ERROR; | |
171 } | |
172 | |
173 return static_cast<SpdyErrorCode>(wire_error_code); | |
174 } | |
175 | |
176 const char* ErrorCodeToString(SpdyErrorCode error_code) { | |
177 switch (error_code) { | |
178 case ERROR_CODE_NO_ERROR: | |
179 return "NO_ERROR"; | |
180 case ERROR_CODE_PROTOCOL_ERROR: | |
181 return "PROTOCOL_ERROR"; | |
182 case ERROR_CODE_INTERNAL_ERROR: | |
183 return "INTERNAL_ERROR"; | |
184 case ERROR_CODE_FLOW_CONTROL_ERROR: | |
185 return "FLOW_CONTROL_ERROR"; | |
186 case ERROR_CODE_SETTINGS_TIMEOUT: | |
187 return "SETTINGS_TIMEOUT"; | |
188 case ERROR_CODE_STREAM_CLOSED: | |
189 return "STREAM_CLOSED"; | |
190 case ERROR_CODE_FRAME_SIZE_ERROR: | |
191 return "FRAME_SIZE_ERROR"; | |
192 case ERROR_CODE_REFUSED_STREAM: | |
193 return "REFUSED_STREAM"; | |
194 case ERROR_CODE_CANCEL: | |
195 return "CANCEL"; | |
196 case ERROR_CODE_COMPRESSION_ERROR: | |
197 return "COMPRESSION_ERROR"; | |
198 case ERROR_CODE_CONNECT_ERROR: | |
199 return "CONNECT_ERROR"; | |
200 case ERROR_CODE_ENHANCE_YOUR_CALM: | |
201 return "ENHANCE_YOUR_CALM"; | |
202 case ERROR_CODE_INADEQUATE_SECURITY: | |
203 return "INADEQUATE_SECURITY"; | |
204 case ERROR_CODE_HTTP_1_1_REQUIRED: | |
205 return "HTTP_1_1_REQUIRED"; | |
206 } | |
207 return "UNKNOWN_ERROR_CODE"; | |
208 } | |
209 | |
210 const char* const kHttp2Npn = "h2"; | |
211 | |
212 SpdyFrameWithHeaderBlockIR::SpdyFrameWithHeaderBlockIR( | |
213 SpdyStreamId stream_id, | |
214 SpdyHeaderBlock header_block) | |
215 : SpdyFrameWithFinIR(stream_id), header_block_(std::move(header_block)) {} | |
216 | |
217 SpdyFrameWithHeaderBlockIR::~SpdyFrameWithHeaderBlockIR() {} | |
218 | |
219 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, SpdyStringPiece data) | |
220 : SpdyFrameWithFinIR(stream_id), | |
221 data_(nullptr), | |
222 data_len_(0), | |
223 padded_(false), | |
224 padding_payload_len_(0) { | |
225 SetDataDeep(data); | |
226 } | |
227 | |
228 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, const char* data) | |
229 : SpdyDataIR(stream_id, SpdyStringPiece(data)) {} | |
230 | |
231 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, SpdyString data) | |
232 : SpdyFrameWithFinIR(stream_id), | |
233 data_store_(base::MakeUnique<SpdyString>(std::move(data))), | |
234 data_(data_store_->data()), | |
235 data_len_(data_store_->size()), | |
236 padded_(false), | |
237 padding_payload_len_(0) {} | |
238 | |
239 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id) | |
240 : SpdyFrameWithFinIR(stream_id), | |
241 data_(nullptr), | |
242 data_len_(0), | |
243 padded_(false), | |
244 padding_payload_len_(0) {} | |
245 | |
246 SpdyDataIR::~SpdyDataIR() {} | |
247 | |
248 void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const { | |
249 return visitor->VisitData(*this); | |
250 } | |
251 | |
252 SpdyFrameType SpdyDataIR::frame_type() const { | |
253 return SpdyFrameType::DATA; | |
254 } | |
255 | |
256 SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id, | |
257 SpdyErrorCode error_code) | |
258 : SpdyFrameWithStreamIdIR(stream_id) { | |
259 set_error_code(error_code); | |
260 } | |
261 | |
262 SpdyRstStreamIR::~SpdyRstStreamIR() {} | |
263 | |
264 void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const { | |
265 return visitor->VisitRstStream(*this); | |
266 } | |
267 | |
268 SpdyFrameType SpdyRstStreamIR::frame_type() const { | |
269 return SpdyFrameType::RST_STREAM; | |
270 } | |
271 | |
272 SpdySettingsIR::SpdySettingsIR() : is_ack_(false) {} | |
273 | |
274 SpdySettingsIR::~SpdySettingsIR() {} | |
275 | |
276 void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const { | |
277 return visitor->VisitSettings(*this); | |
278 } | |
279 | |
280 SpdyFrameType SpdySettingsIR::frame_type() const { | |
281 return SpdyFrameType::SETTINGS; | |
282 } | |
283 | |
284 void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const { | |
285 return visitor->VisitPing(*this); | |
286 } | |
287 | |
288 SpdyFrameType SpdyPingIR::frame_type() const { | |
289 return SpdyFrameType::PING; | |
290 } | |
291 | |
292 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id, | |
293 SpdyErrorCode error_code, | |
294 SpdyStringPiece description) | |
295 : description_(description) { | |
296 set_last_good_stream_id(last_good_stream_id); | |
297 set_error_code(error_code); | |
298 } | |
299 | |
300 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id, | |
301 SpdyErrorCode error_code, | |
302 const char* description) | |
303 : SpdyGoAwayIR(last_good_stream_id, | |
304 error_code, | |
305 SpdyStringPiece(description)) {} | |
306 | |
307 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id, | |
308 SpdyErrorCode error_code, | |
309 SpdyString description) | |
310 : description_store_(std::move(description)), | |
311 description_(description_store_) { | |
312 set_last_good_stream_id(last_good_stream_id); | |
313 set_error_code(error_code); | |
314 } | |
315 | |
316 SpdyGoAwayIR::~SpdyGoAwayIR() {} | |
317 | |
318 void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const { | |
319 return visitor->VisitGoAway(*this); | |
320 } | |
321 | |
322 SpdyFrameType SpdyGoAwayIR::frame_type() const { | |
323 return SpdyFrameType::GOAWAY; | |
324 } | |
325 | |
326 SpdyContinuationIR::SpdyContinuationIR(SpdyStreamId stream_id) | |
327 : SpdyFrameWithStreamIdIR(stream_id), end_headers_(false) { | |
328 encoding_ = base::MakeUnique<SpdyString>(); | |
329 } | |
330 | |
331 SpdyContinuationIR::~SpdyContinuationIR() {} | |
332 | |
333 void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const { | |
334 return visitor->VisitContinuation(*this); | |
335 } | |
336 | |
337 SpdyFrameType SpdyContinuationIR::frame_type() const { | |
338 return SpdyFrameType::CONTINUATION; | |
339 } | |
340 | |
341 void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const { | |
342 return visitor->VisitHeaders(*this); | |
343 } | |
344 | |
345 SpdyFrameType SpdyHeadersIR::frame_type() const { | |
346 return SpdyFrameType::HEADERS; | |
347 } | |
348 | |
349 void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const { | |
350 return visitor->VisitWindowUpdate(*this); | |
351 } | |
352 | |
353 SpdyFrameType SpdyWindowUpdateIR::frame_type() const { | |
354 return SpdyFrameType::WINDOW_UPDATE; | |
355 } | |
356 | |
357 void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const { | |
358 return visitor->VisitPushPromise(*this); | |
359 } | |
360 | |
361 SpdyFrameType SpdyPushPromiseIR::frame_type() const { | |
362 return SpdyFrameType::PUSH_PROMISE; | |
363 } | |
364 | |
365 SpdyAltSvcIR::SpdyAltSvcIR(SpdyStreamId stream_id) | |
366 : SpdyFrameWithStreamIdIR(stream_id) { | |
367 } | |
368 | |
369 SpdyAltSvcIR::~SpdyAltSvcIR() { | |
370 } | |
371 | |
372 void SpdyAltSvcIR::Visit(SpdyFrameVisitor* visitor) const { | |
373 return visitor->VisitAltSvc(*this); | |
374 } | |
375 | |
376 SpdyFrameType SpdyAltSvcIR::frame_type() const { | |
377 return SpdyFrameType::ALTSVC; | |
378 } | |
379 | |
380 void SpdyPriorityIR::Visit(SpdyFrameVisitor* visitor) const { | |
381 return visitor->VisitPriority(*this); | |
382 } | |
383 | |
384 SpdyFrameType SpdyPriorityIR::frame_type() const { | |
385 return SpdyFrameType::PRIORITY; | |
386 } | |
387 | |
388 } // namespace net | |
OLD | NEW |