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.
5 #include "net/spdy/spdy_protocol.h"
9 SpdyFrameWithNameValueBlockIR::SpdyFrameWithNameValueBlockIR(
10 SpdyStreamId stream_id) : SpdyFrameWithFinIR(stream_id) {}
12 SpdyFrameWithNameValueBlockIR::~SpdyFrameWithNameValueBlockIR() {}
14 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id, const base::StringPiece& data)
15 : SpdyFrameWithFinIR(stream_id),
18 padding_payload_len_(0) {
22 SpdyDataIR::SpdyDataIR(SpdyStreamId stream_id)
23 : SpdyFrameWithFinIR(stream_id),
26 padding_payload_len_(0) {}
28 SpdyDataIR::~SpdyDataIR() {}
30 bool SpdyConstants::IsValidFrameType(SpdyMajorVersion version,
31 int frame_type_field) {
35 // SYN_STREAM is the first valid frame.
36 if (frame_type_field < SerializeFrameType(version, SYN_STREAM)) {
40 // WINDOW_UPDATE is the last valid frame.
41 if (frame_type_field > SerializeFrameType(version, WINDOW_UPDATE)) {
45 // The valid range is non-contiguous.
46 if (frame_type_field == NOOP) {
53 // DATA is the first valid frame.
54 if (frame_type_field < SerializeFrameType(version, DATA)) {
58 // BLOCKED is the last valid frame.
59 if (frame_type_field > SerializeFrameType(version, BLOCKED)) {
66 LOG(DFATAL) << "Unhandled SPDY version " << version;
70 SpdyFrameType SpdyConstants::ParseFrameType(SpdyMajorVersion version,
71 int frame_type_field) {
75 switch (frame_type_field) {
96 switch (frame_type_field) {
101 // TODO(hkhalil): Add PRIORITY.
113 return WINDOW_UPDATE;
122 LOG(DFATAL) << "Unhandled frame type " << frame_type_field;
126 int SpdyConstants::SerializeFrameType(SpdyMajorVersion version,
127 SpdyFrameType frame_type) {
131 switch (frame_type) {
149 LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
154 switch (frame_type) {
159 // TODO(hkhalil): Add PRIORITY.
177 LOG(DFATAL) << "Serializing unhandled frame type " << frame_type;
182 LOG(DFATAL) << "Unhandled SPDY version " << version;
186 bool SpdyConstants::IsValidSettingId(SpdyMajorVersion version,
187 int setting_id_field) {
191 // UPLOAD_BANDWIDTH is the first valid setting id.
192 if (setting_id_field <
193 SerializeSettingId(version, SETTINGS_UPLOAD_BANDWIDTH)) {
197 // INITIAL_WINDOW_SIZE is the last valid setting id.
198 if (setting_id_field >
199 SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
206 // HEADER_TABLE_SIZE is the first valid setting id.
207 if (setting_id_field <
208 SerializeSettingId(version, SETTINGS_HEADER_TABLE_SIZE)) {
212 // INITIAL_WINDOW_SIZE is the last valid setting id.
213 if (setting_id_field >
214 SerializeSettingId(version, SETTINGS_INITIAL_WINDOW_SIZE)) {
221 LOG(DFATAL) << "Unhandled SPDY version " << version;
225 SpdySettingsIds SpdyConstants::ParseSettingId(SpdyMajorVersion version,
226 int setting_id_field) {
230 switch (setting_id_field) {
232 return SETTINGS_UPLOAD_BANDWIDTH;
234 return SETTINGS_DOWNLOAD_BANDWIDTH;
236 return SETTINGS_ROUND_TRIP_TIME;
238 return SETTINGS_MAX_CONCURRENT_STREAMS;
240 return SETTINGS_CURRENT_CWND;
242 return SETTINGS_DOWNLOAD_RETRANS_RATE;
244 return SETTINGS_INITIAL_WINDOW_SIZE;
249 switch (setting_id_field) {
251 return SETTINGS_HEADER_TABLE_SIZE;
253 return SETTINGS_ENABLE_PUSH;
255 return SETTINGS_MAX_CONCURRENT_STREAMS;
257 return SETTINGS_INITIAL_WINDOW_SIZE;
262 LOG(DFATAL) << "Unhandled setting ID " << setting_id_field;
263 return SETTINGS_UPLOAD_BANDWIDTH;
266 int SpdyConstants::SerializeSettingId(SpdyMajorVersion version,
267 SpdySettingsIds id) {
272 case SETTINGS_UPLOAD_BANDWIDTH:
274 case SETTINGS_DOWNLOAD_BANDWIDTH:
276 case SETTINGS_ROUND_TRIP_TIME:
278 case SETTINGS_MAX_CONCURRENT_STREAMS:
280 case SETTINGS_CURRENT_CWND:
282 case SETTINGS_DOWNLOAD_RETRANS_RATE:
284 case SETTINGS_INITIAL_WINDOW_SIZE:
287 LOG(DFATAL) << "Serializing unhandled setting id " << id;
293 case SETTINGS_HEADER_TABLE_SIZE:
295 case SETTINGS_ENABLE_PUSH:
297 case SETTINGS_MAX_CONCURRENT_STREAMS:
299 case SETTINGS_INITIAL_WINDOW_SIZE:
302 LOG(DFATAL) << "Serializing unhandled setting id " << id;
306 LOG(DFATAL) << "Unhandled SPDY version " << version;
310 bool SpdyConstants::IsValidRstStreamStatus(SpdyMajorVersion version,
311 int rst_stream_status_field) {
315 // PROTOCOL_ERROR is the valid first status code.
316 if (rst_stream_status_field <
317 SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
321 // FRAME_TOO_LARGE is the valid last status code.
322 if (rst_stream_status_field >
323 SerializeRstStreamStatus(version, RST_STREAM_FRAME_TOO_LARGE)) {
330 // NO_ERROR is the first valid status code.
331 if (rst_stream_status_field <
332 SerializeRstStreamStatus(version, RST_STREAM_PROTOCOL_ERROR)) {
336 // TODO(hkhalil): Omit COMPRESSION_ERROR and SETTINGS_TIMEOUT
338 // This works because GOAWAY and RST_STREAM share a namespace.
339 if (rst_stream_status_field ==
340 SerializeGoAwayStatus(version, GOAWAY_COMPRESSION_ERROR) ||
341 rst_stream_status_field ==
342 SerializeGoAwayStatus(version, GOAWAY_SETTINGS_TIMEOUT)) {
347 // ENHANCE_YOUR_CALM is the last valid status code.
348 if (rst_stream_status_field >
349 SerializeRstStreamStatus(version, RST_STREAM_ENHANCE_YOUR_CALM)) {
355 LOG(DFATAL) << "Unhandled SPDY version " << version;
359 SpdyRstStreamStatus SpdyConstants::ParseRstStreamStatus(
360 SpdyMajorVersion version,
361 int rst_stream_status_field) {
365 switch (rst_stream_status_field) {
367 return RST_STREAM_PROTOCOL_ERROR;
369 return RST_STREAM_INVALID_STREAM;
371 return RST_STREAM_REFUSED_STREAM;
373 return RST_STREAM_UNSUPPORTED_VERSION;
375 return RST_STREAM_CANCEL;
377 return RST_STREAM_INTERNAL_ERROR;
379 return RST_STREAM_FLOW_CONTROL_ERROR;
381 return RST_STREAM_STREAM_IN_USE;
383 return RST_STREAM_STREAM_ALREADY_CLOSED;
385 return RST_STREAM_INVALID_CREDENTIALS;
387 return RST_STREAM_FRAME_TOO_LARGE;
392 switch (rst_stream_status_field) {
394 return RST_STREAM_PROTOCOL_ERROR;
396 return RST_STREAM_INTERNAL_ERROR;
398 return RST_STREAM_FLOW_CONTROL_ERROR;
400 return RST_STREAM_STREAM_CLOSED;
402 return RST_STREAM_FRAME_SIZE_ERROR;
404 return RST_STREAM_REFUSED_STREAM;
406 return RST_STREAM_CANCEL;
408 return RST_STREAM_CONNECT_ERROR;
410 return RST_STREAM_ENHANCE_YOUR_CALM;
415 LOG(DFATAL) << "Invalid RST_STREAM status " << rst_stream_status_field;
416 return RST_STREAM_PROTOCOL_ERROR;
419 int SpdyConstants::SerializeRstStreamStatus(
420 SpdyMajorVersion version,
421 SpdyRstStreamStatus rst_stream_status) {
425 switch (rst_stream_status) {
426 case RST_STREAM_PROTOCOL_ERROR:
428 case RST_STREAM_INVALID_STREAM:
430 case RST_STREAM_REFUSED_STREAM:
432 case RST_STREAM_UNSUPPORTED_VERSION:
434 case RST_STREAM_CANCEL:
436 case RST_STREAM_INTERNAL_ERROR:
438 case RST_STREAM_FLOW_CONTROL_ERROR:
440 case RST_STREAM_STREAM_IN_USE:
442 case RST_STREAM_STREAM_ALREADY_CLOSED:
444 case RST_STREAM_INVALID_CREDENTIALS:
446 case RST_STREAM_FRAME_TOO_LARGE:
449 LOG(DFATAL) << "Unhandled RST_STREAM status "
450 << rst_stream_status;
455 switch (rst_stream_status) {
456 case RST_STREAM_PROTOCOL_ERROR:
458 case RST_STREAM_INTERNAL_ERROR:
460 case RST_STREAM_FLOW_CONTROL_ERROR:
462 case RST_STREAM_STREAM_CLOSED:
464 case RST_STREAM_FRAME_SIZE_ERROR:
466 case RST_STREAM_REFUSED_STREAM:
468 case RST_STREAM_CANCEL:
470 case RST_STREAM_CONNECT_ERROR:
472 case RST_STREAM_ENHANCE_YOUR_CALM:
475 LOG(DFATAL) << "Unhandled RST_STREAM status "
476 << rst_stream_status;
480 LOG(DFATAL) << "Unhandled SPDY version " << version;
484 bool SpdyConstants::IsValidGoAwayStatus(SpdyMajorVersion version,
485 int goaway_status_field) {
489 // GOAWAY_OK is the first valid status.
490 if (goaway_status_field < SerializeGoAwayStatus(version, GOAWAY_OK)) {
494 // GOAWAY_INTERNAL_ERROR is the last valid status.
495 if (goaway_status_field > SerializeGoAwayStatus(version,
496 GOAWAY_INTERNAL_ERROR)) {
503 // GOAWAY_NO_ERROR is the first valid status.
504 if (goaway_status_field < SerializeGoAwayStatus(version,
509 // GOAWAY_INADEQUATE_SECURITY is the last valid status.
510 if (goaway_status_field >
511 SerializeGoAwayStatus(version, GOAWAY_INADEQUATE_SECURITY)) {
517 LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
521 SpdyGoAwayStatus SpdyConstants::ParseGoAwayStatus(SpdyMajorVersion version,
522 int goaway_status_field) {
526 switch (goaway_status_field) {
530 return GOAWAY_PROTOCOL_ERROR;
532 return GOAWAY_INTERNAL_ERROR;
537 switch (goaway_status_field) {
539 return GOAWAY_NO_ERROR;
541 return GOAWAY_PROTOCOL_ERROR;
543 return GOAWAY_INTERNAL_ERROR;
545 return GOAWAY_FLOW_CONTROL_ERROR;
547 return GOAWAY_SETTINGS_TIMEOUT;
549 return GOAWAY_STREAM_CLOSED;
551 return GOAWAY_FRAME_SIZE_ERROR;
553 return GOAWAY_REFUSED_STREAM;
555 return GOAWAY_CANCEL;
557 return GOAWAY_COMPRESSION_ERROR;
559 return GOAWAY_CONNECT_ERROR;
561 return GOAWAY_ENHANCE_YOUR_CALM;
563 return GOAWAY_INADEQUATE_SECURITY;
568 LOG(DFATAL) << "Unhandled GOAWAY status " << goaway_status_field;
569 return GOAWAY_PROTOCOL_ERROR;
572 SpdyMajorVersion SpdyConstants::ParseMajorVersion(int version_number) {
573 switch (version_number) {
583 LOG(DFATAL) << "Unsupported SPDY version number: " << version_number;
588 int SpdyConstants::SerializeMajorVersion(SpdyMajorVersion version) {
599 LOG(DFATAL) << "Unsupported SPDY major version: " << version;
604 std::string SpdyConstants::GetVersionString(SpdyMajorVersion version) {
615 LOG(DFATAL) << "Unsupported SPDY major version: " << version;
620 int SpdyConstants::SerializeGoAwayStatus(SpdyMajorVersion version,
621 SpdyGoAwayStatus status) {
628 case GOAWAY_PROTOCOL_ERROR:
630 case GOAWAY_INTERNAL_ERROR:
633 LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
639 case GOAWAY_NO_ERROR:
641 case GOAWAY_PROTOCOL_ERROR:
643 case GOAWAY_INTERNAL_ERROR:
645 case GOAWAY_FLOW_CONTROL_ERROR:
647 case GOAWAY_SETTINGS_TIMEOUT:
649 case GOAWAY_STREAM_CLOSED:
651 case GOAWAY_FRAME_SIZE_ERROR:
653 case GOAWAY_REFUSED_STREAM:
657 case GOAWAY_COMPRESSION_ERROR:
659 case GOAWAY_CONNECT_ERROR:
661 case GOAWAY_ENHANCE_YOUR_CALM:
663 case GOAWAY_INADEQUATE_SECURITY:
666 LOG(DFATAL) << "Serializing unhandled GOAWAY status " << status;
670 LOG(DFATAL) << "Unknown SpdyMajorVersion " << version;
674 size_t SpdyConstants::GetDataFrameMinimumSize() {
678 size_t SpdyConstants::GetControlFrameHeaderSize(SpdyMajorVersion version) {
686 LOG(DFATAL) << "Unhandled SPDY version.";
690 size_t SpdyConstants::GetPrefixLength(SpdyFrameType type,
691 SpdyMajorVersion version) {
693 return GetControlFrameHeaderSize(version);
695 return GetDataFrameMinimumSize();
699 size_t SpdyConstants::GetFrameMaximumSize(SpdyMajorVersion version) {
700 if (version < SPDY4) {
701 // 24-bit length field plus eight-byte frame header.
702 return ((1<<24) - 1) + 8;
704 // 14-bit length field.
709 void SpdyDataIR::Visit(SpdyFrameVisitor* visitor) const {
710 return visitor->VisitData(*this);
713 void SpdySynStreamIR::Visit(SpdyFrameVisitor* visitor) const {
714 return visitor->VisitSynStream(*this);
717 void SpdySynReplyIR::Visit(SpdyFrameVisitor* visitor) const {
718 return visitor->VisitSynReply(*this);
721 SpdyRstStreamIR::SpdyRstStreamIR(SpdyStreamId stream_id,
722 SpdyRstStreamStatus status,
723 base::StringPiece description)
724 : SpdyFrameWithStreamIdIR(stream_id),
725 description_(description) {
729 SpdyRstStreamIR::~SpdyRstStreamIR() {}
731 void SpdyRstStreamIR::Visit(SpdyFrameVisitor* visitor) const {
732 return visitor->VisitRstStream(*this);
735 SpdySettingsIR::SpdySettingsIR()
736 : clear_settings_(false),
739 SpdySettingsIR::~SpdySettingsIR() {}
741 void SpdySettingsIR::Visit(SpdyFrameVisitor* visitor) const {
742 return visitor->VisitSettings(*this);
745 void SpdyPingIR::Visit(SpdyFrameVisitor* visitor) const {
746 return visitor->VisitPing(*this);
749 SpdyGoAwayIR::SpdyGoAwayIR(SpdyStreamId last_good_stream_id,
750 SpdyGoAwayStatus status,
751 const base::StringPiece& description)
752 : description_(description) {
753 set_last_good_stream_id(last_good_stream_id);
757 SpdyGoAwayIR::~SpdyGoAwayIR() {}
759 const base::StringPiece& SpdyGoAwayIR::description() const {
763 void SpdyGoAwayIR::Visit(SpdyFrameVisitor* visitor) const {
764 return visitor->VisitGoAway(*this);
767 void SpdyHeadersIR::Visit(SpdyFrameVisitor* visitor) const {
768 return visitor->VisitHeaders(*this);
771 void SpdyWindowUpdateIR::Visit(SpdyFrameVisitor* visitor) const {
772 return visitor->VisitWindowUpdate(*this);
775 void SpdyBlockedIR::Visit(SpdyFrameVisitor* visitor) const {
776 return visitor->VisitBlocked(*this);
779 void SpdyPushPromiseIR::Visit(SpdyFrameVisitor* visitor) const {
780 return visitor->VisitPushPromise(*this);
783 void SpdyContinuationIR::Visit(SpdyFrameVisitor* visitor) const {
784 return visitor->VisitContinuation(*this);