| 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 |