OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't | 5 // TODO(rtenhove) clean up frame buffer size calculations so that we aren't |
6 // constantly adding and subtracting header sizes; this is ugly and error- | 6 // constantly adding and subtracting header sizes; this is ugly and error- |
7 // prone. | 7 // prone. |
8 | 8 |
9 #include "net/spdy/spdy_framer.h" | 9 #include "net/spdy/spdy_framer.h" |
10 | 10 |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
57 } // namespace | 57 } // namespace |
58 | 58 |
59 const int SpdyFramer::kMinSpdyVersion = 2; | 59 const int SpdyFramer::kMinSpdyVersion = 2; |
60 const int SpdyFramer::kMaxSpdyVersion = 3; | 60 const int SpdyFramer::kMaxSpdyVersion = 3; |
61 const SpdyStreamId SpdyFramer::kInvalidStream = -1; | 61 const SpdyStreamId SpdyFramer::kInvalidStream = -1; |
62 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 62 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
63 const size_t SpdyFramer::kControlFrameBufferSize = | 63 const size_t SpdyFramer::kControlFrameBufferSize = |
64 sizeof(SpdySynStreamControlFrameBlock); | 64 sizeof(SpdySynStreamControlFrameBlock); |
65 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; | 65 const size_t SpdyFramer::kMaxControlFrameSize = 16 * 1024; |
66 | 66 |
67 | |
68 #ifdef DEBUG_SPDY_STATE_CHANGES | 67 #ifdef DEBUG_SPDY_STATE_CHANGES |
69 #define CHANGE_STATE(newstate) \ | 68 #define CHANGE_STATE(newstate) \ |
70 do { \ | 69 do { \ |
71 LOG(INFO) << "Changing state from: " \ | 70 LOG(INFO) << "Changing state from: " \ |
72 << StateToString(state_) \ | 71 << StateToString(state_) \ |
73 << " to " << StateToString(newstate) << "\n"; \ | 72 << " to " << StateToString(newstate) << "\n"; \ |
74 DCHECK(state_ != SPDY_ERROR); \ | 73 DCHECK(state_ != SPDY_ERROR); \ |
75 DCHECK_EQ(previous_state_, state_); \ | 74 DCHECK_EQ(previous_state_, state_); \ |
76 previous_state_ = state_; \ | 75 previous_state_ = state_; \ |
77 state_ = newstate; \ | 76 state_ = newstate; \ |
(...skipping 11 matching lines...) Expand all Loading... |
89 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, | 88 SettingsFlagsAndId SettingsFlagsAndId::FromWireFormat(int version, |
90 uint32 wire) { | 89 uint32 wire) { |
91 if (version < 3) { | 90 if (version < 3) { |
92 ConvertFlagsAndIdForSpdy2(&wire); | 91 ConvertFlagsAndIdForSpdy2(&wire); |
93 } | 92 } |
94 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); | 93 return SettingsFlagsAndId(ntohl(wire) >> 24, ntohl(wire) & 0x00ffffff); |
95 } | 94 } |
96 | 95 |
97 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) | 96 SettingsFlagsAndId::SettingsFlagsAndId(uint8 flags, uint32 id) |
98 : flags_(flags), id_(id & 0x00ffffff) { | 97 : flags_(flags), id_(id & 0x00ffffff) { |
99 DCHECK_GT(static_cast<uint32>(1 << 24), id); | 98 DCHECK_GT(1u << 24, id) << "SPDY setting ID too large."; |
100 } | 99 } |
101 | 100 |
102 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { | 101 uint32 SettingsFlagsAndId::GetWireFormat(int version) const { |
103 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); | 102 uint32 wire = htonl(id_ & 0x00ffffff) | htonl(flags_ << 24); |
104 if (version < 3) { | 103 if (version < 3) { |
105 ConvertFlagsAndIdForSpdy2(&wire); | 104 ConvertFlagsAndIdForSpdy2(&wire); |
106 } | 105 } |
107 return wire; | 106 return wire; |
108 } | 107 } |
109 | 108 |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 case SPDY_IGNORE_REMAINING_PAYLOAD: | 352 case SPDY_IGNORE_REMAINING_PAYLOAD: |
354 // control frame has too-large payload | 353 // control frame has too-large payload |
355 // intentional fallthrough | 354 // intentional fallthrough |
356 case SPDY_FORWARD_STREAM_FRAME: { | 355 case SPDY_FORWARD_STREAM_FRAME: { |
357 size_t bytes_read = ProcessDataFramePayload(data, len); | 356 size_t bytes_read = ProcessDataFramePayload(data, len); |
358 len -= bytes_read; | 357 len -= bytes_read; |
359 data += bytes_read; | 358 data += bytes_read; |
360 break; | 359 break; |
361 } | 360 } |
362 default: | 361 default: |
363 LOG(ERROR) << "Invalid value for " << display_protocol_ | 362 LOG(DFATAL) << "Invalid value for " << display_protocol_ |
364 << " framer state: " << state_; | 363 << " framer state: " << state_; |
365 // This ensures that we don't infinite-loop if state_ gets an | 364 // This ensures that we don't infinite-loop if state_ gets an |
366 // invalid value somehow, such as due to a SpdyFramer getting deleted | 365 // invalid value somehow, such as due to a SpdyFramer getting deleted |
367 // from a callback it calls. | 366 // from a callback it calls. |
368 goto bottom; | 367 goto bottom; |
369 } | 368 } |
370 } while (state_ != previous_state_); | 369 } while (state_ != previous_state_); |
371 bottom: | 370 bottom: |
372 DCHECK(len == 0 || state_ == SPDY_ERROR); | 371 DCHECK(len == 0 || state_ == SPDY_ERROR); |
373 if (current_frame_len_ == 0 && | 372 if (current_frame_len_ == 0 && |
374 remaining_data_ == 0 && | 373 remaining_data_ == 0 && |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
522 break; | 521 break; |
523 case CREDENTIAL: | 522 case CREDENTIAL: |
524 if (current_control_frame.length() < | 523 if (current_control_frame.length() < |
525 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize) | 524 SpdyCredentialControlFrame::size() - SpdyControlFrame::kHeaderSize) |
526 set_error(SPDY_INVALID_CONTROL_FRAME); | 525 set_error(SPDY_INVALID_CONTROL_FRAME); |
527 break; | 526 break; |
528 default: | 527 default: |
529 LOG(WARNING) << "Valid " << display_protocol_ | 528 LOG(WARNING) << "Valid " << display_protocol_ |
530 << " control frame with unhandled type: " | 529 << " control frame with unhandled type: " |
531 << current_control_frame.type(); | 530 << current_control_frame.type(); |
532 DCHECK(false); | 531 DLOG(FATAL); |
533 set_error(SPDY_INVALID_CONTROL_FRAME); | 532 set_error(SPDY_INVALID_CONTROL_FRAME); |
534 break; | 533 break; |
535 } | 534 } |
536 | 535 |
537 if (state_ == SPDY_ERROR) { | 536 if (state_ == SPDY_ERROR) { |
538 return; | 537 return; |
539 } | 538 } |
540 | 539 |
541 remaining_control_payload_ = current_control_frame.length(); | 540 remaining_control_payload_ = current_control_frame.length(); |
542 const size_t total_frame_size = | 541 const size_t total_frame_size = |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
579 case SETTINGS: | 578 case SETTINGS: |
580 frame_size_without_variable_data = SpdySettingsControlFrame::size(); | 579 frame_size_without_variable_data = SpdySettingsControlFrame::size(); |
581 break; | 580 break; |
582 default: | 581 default: |
583 frame_size_without_variable_data = -1; | 582 frame_size_without_variable_data = -1; |
584 break; | 583 break; |
585 } | 584 } |
586 | 585 |
587 if ((frame_size_without_variable_data == -1) && | 586 if ((frame_size_without_variable_data == -1) && |
588 (total_frame_size > kControlFrameBufferSize)) { | 587 (total_frame_size > kControlFrameBufferSize)) { |
| 588 // We should already be in an error state. Double-check. |
589 DCHECK_EQ(SPDY_ERROR, state_); | 589 DCHECK_EQ(SPDY_ERROR, state_); |
590 if (state_ != SPDY_ERROR) { | 590 if (state_ != SPDY_ERROR) { |
591 LOG(DFATAL) << display_protocol_ | 591 LOG(DFATAL) << display_protocol_ |
592 << " control frame buffer too small for fixed-length frame."; | 592 << " control frame buffer too small for fixed-length frame."; |
593 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); | 593 set_error(SPDY_CONTROL_PAYLOAD_TOO_LARGE); |
594 } | 594 } |
595 return; | 595 return; |
596 } | 596 } |
597 if (frame_size_without_variable_data > 0) { | 597 if (frame_size_without_variable_data > 0) { |
598 // We have a control frame with a header block. We need to parse the | 598 // We have a control frame with a header block. We need to parse the |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, | 667 size_t SpdyFramer::ProcessControlFrameBeforeHeaderBlock(const char* data, |
668 size_t len) { | 668 size_t len) { |
669 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); | 669 DCHECK_EQ(SPDY_CONTROL_FRAME_BEFORE_HEADER_BLOCK, state_); |
670 size_t original_len = len; | 670 size_t original_len = len; |
671 | 671 |
672 if (remaining_control_header_ > 0) { | 672 if (remaining_control_header_ > 0) { |
673 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, | 673 size_t bytes_read = UpdateCurrentFrameBuffer(&data, &len, |
674 remaining_control_header_); | 674 remaining_control_header_); |
675 remaining_control_header_ -= bytes_read; | 675 remaining_control_header_ -= bytes_read; |
676 } | 676 } |
| 677 |
677 if (remaining_control_header_ == 0) { | 678 if (remaining_control_header_ == 0) { |
678 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 679 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
679 DCHECK(control_frame.type() == SYN_STREAM || | 680 DCHECK(control_frame.type() == SYN_STREAM || |
680 control_frame.type() == SYN_REPLY || | 681 control_frame.type() == SYN_REPLY || |
681 control_frame.type() == HEADERS || | 682 control_frame.type() == HEADERS || |
682 control_frame.type() == SETTINGS); | 683 control_frame.type() == SETTINGS); |
683 visitor_->OnControl(&control_frame); | 684 visitor_->OnControl(&control_frame); |
684 | 685 |
685 if (control_frame.type() == SETTINGS) { | 686 if (control_frame.type() == SETTINGS) { |
686 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); | 687 CHANGE_STATE(SPDY_SETTINGS_FRAME_PAYLOAD); |
(...skipping 11 matching lines...) Expand all Loading... |
698 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, | 699 size_t SpdyFramer::ProcessControlFrameHeaderBlock(const char* data, |
699 size_t data_len) { | 700 size_t data_len) { |
700 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); | 701 DCHECK_EQ(SPDY_CONTROL_FRAME_HEADER_BLOCK, state_); |
701 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 702 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
702 | 703 |
703 bool processed_successfully = true; | 704 bool processed_successfully = true; |
704 DCHECK(control_frame.type() == SYN_STREAM || | 705 DCHECK(control_frame.type() == SYN_STREAM || |
705 control_frame.type() == SYN_REPLY || | 706 control_frame.type() == SYN_REPLY || |
706 control_frame.type() == HEADERS); | 707 control_frame.type() == HEADERS); |
707 size_t process_bytes = std::min(data_len, remaining_control_payload_); | 708 size_t process_bytes = std::min(data_len, remaining_control_payload_); |
708 | |
709 if (process_bytes > 0) { | 709 if (process_bytes > 0) { |
710 if (enable_compression_) { | 710 if (enable_compression_) { |
711 processed_successfully = IncrementallyDecompressControlFrameHeaderData( | 711 processed_successfully = IncrementallyDecompressControlFrameHeaderData( |
712 &control_frame, data, process_bytes); | 712 &control_frame, data, process_bytes); |
713 } else { | 713 } else { |
714 processed_successfully = IncrementallyDeliverControlFrameHeaderData( | 714 processed_successfully = IncrementallyDeliverControlFrameHeaderData( |
715 &control_frame, data, process_bytes); | 715 &control_frame, data, process_bytes); |
716 } | 716 } |
| 717 |
717 remaining_control_payload_ -= process_bytes; | 718 remaining_control_payload_ -= process_bytes; |
718 remaining_data_ -= process_bytes; | 719 remaining_data_ -= process_bytes; |
719 } | 720 } |
720 | 721 |
721 // Handle the case that there is no futher data in this frame. | 722 // Handle the case that there is no futher data in this frame. |
722 if (remaining_control_payload_ == 0 && processed_successfully) { | 723 if (remaining_control_payload_ == 0 && processed_successfully) { |
723 // The complete header block has been delivered. We send a zero-length | 724 // The complete header block has been delivered. We send a zero-length |
724 // OnControlFrameHeaderData() to indicate this. | 725 // OnControlFrameHeaderData() to indicate this. |
725 visitor_->OnControlFrameHeaderData( | 726 visitor_->OnControlFrameHeaderData( |
726 GetControlFrameStreamId(&control_frame), NULL, 0); | 727 GetControlFrameStreamId(&control_frame), NULL, 0); |
(...skipping 13 matching lines...) Expand all Loading... |
740 } | 741 } |
741 | 742 |
742 // Return amount processed. | 743 // Return amount processed. |
743 return process_bytes; | 744 return process_bytes; |
744 } | 745 } |
745 | 746 |
746 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, | 747 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, |
747 size_t data_len) { | 748 size_t data_len) { |
748 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); | 749 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); |
749 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); | 750 SpdyControlFrame control_frame(current_frame_buffer_.get(), false); |
750 DCHECK_EQ(control_frame.type(), SETTINGS); | 751 DCHECK_EQ(SETTINGS, control_frame.type()); |
751 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_); | 752 size_t unprocessed_bytes = std::min(data_len, remaining_control_payload_); |
752 size_t processed_bytes = 0; | 753 size_t processed_bytes = 0; |
753 | 754 |
754 // Loop over our incoming data. | 755 // Loop over our incoming data. |
755 while (unprocessed_bytes > 0) { | 756 while (unprocessed_bytes > 0) { |
756 // Process up to one setting at a time. | 757 // Process up to one setting at a time. |
757 size_t processing = std::min( | 758 size_t processing = std::min( |
758 unprocessed_bytes, | 759 unprocessed_bytes, |
759 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); | 760 static_cast<size_t>(8 - settings_scratch_.setting_buf_len)); |
760 | 761 |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
881 return len; | 882 return len; |
882 } | 883 } |
883 | 884 |
884 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { | 885 size_t SpdyFramer::ProcessDataFramePayload(const char* data, size_t len) { |
885 size_t original_len = len; | 886 size_t original_len = len; |
886 | 887 |
887 SpdyDataFrame current_data_frame(current_frame_buffer_.get(), false); | 888 SpdyDataFrame current_data_frame(current_frame_buffer_.get(), false); |
888 if (remaining_data_ > 0) { | 889 if (remaining_data_ > 0) { |
889 size_t amount_to_forward = std::min(remaining_data_, len); | 890 size_t amount_to_forward = std::min(remaining_data_, len); |
890 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { | 891 if (amount_to_forward && state_ != SPDY_IGNORE_REMAINING_PAYLOAD) { |
891 // Only inform the visitor if there is data. | 892 // Only inform the visitor if there is data. |
892 if (amount_to_forward) { | 893 if (amount_to_forward) { |
893 visitor_->OnStreamFrameData(current_data_frame.stream_id(), | 894 visitor_->OnStreamFrameData(current_data_frame.stream_id(), |
894 data, amount_to_forward); | 895 data, amount_to_forward); |
895 } | 896 } |
896 } | 897 } |
897 data += amount_to_forward; | 898 data += amount_to_forward; |
898 len -= amount_to_forward; | 899 len -= amount_to_forward; |
899 remaining_data_ -= amount_to_forward; | 900 remaining_data_ -= amount_to_forward; |
900 | 901 |
901 // If the FIN flag is set, and there is no more data in this data | 902 // If the FIN flag is set, and there is no more data in this data |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
937 for (uint32 index = 0; index < num_headers; ++index) { | 938 for (uint32 index = 0; index < num_headers; ++index) { |
938 base::StringPiece temp; | 939 base::StringPiece temp; |
939 | 940 |
940 // Read header name. | 941 // Read header name. |
941 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) | 942 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) |
942 : !reader.ReadStringPiece32(&temp)) { | 943 : !reader.ReadStringPiece32(&temp)) { |
943 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " | 944 DLOG(INFO) << "Unable to read header name (" << index + 1 << " of " |
944 << num_headers << ")."; | 945 << num_headers << ")."; |
945 return false; | 946 return false; |
946 } | 947 } |
947 std::string name; | 948 std::string name = temp.as_string(); |
948 temp.CopyToString(&name); | |
949 | 949 |
950 // Read header value. | 950 // Read header value. |
951 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) | 951 if ((spdy_version_ < 3) ? !reader.ReadStringPiece16(&temp) |
952 : !reader.ReadStringPiece32(&temp)) { | 952 : !reader.ReadStringPiece32(&temp)) { |
953 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " | 953 DLOG(INFO) << "Unable to read header value (" << index + 1 << " of " |
954 << num_headers << ")."; | 954 << num_headers << ")."; |
955 return false; | 955 return false; |
956 } | 956 } |
957 std::string value; | 957 std::string value = temp.as_string(); |
958 temp.CopyToString(&value); | |
959 | 958 |
960 // Ensure no duplicates. | 959 // Ensure no duplicates. |
961 if (block->find(name) != block->end()) { | 960 if (block->find(name) != block->end()) { |
962 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " | 961 DLOG(INFO) << "Duplicate header '" << name << "' (" << index + 1 << " of " |
963 << num_headers << ")."; | 962 << num_headers << ")."; |
964 return false; | 963 return false; |
965 } | 964 } |
966 | 965 |
967 // Store header. | 966 // Store header. |
968 (*block)[name] = value; | 967 (*block)[name] = value; |
969 } | 968 } |
970 return true; | 969 return true; |
971 } | 970 } |
972 | 971 |
| 972 // TODO(hkhalil): Remove, or move to test utils kit. |
973 /* static */ | 973 /* static */ |
974 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, | 974 bool SpdyFramer::ParseSettings(const SpdySettingsControlFrame* frame, |
975 SettingsMap* settings) { | 975 SettingsMap* settings) { |
976 DCHECK_EQ(frame->type(), SETTINGS); | 976 DCHECK_EQ(frame->type(), SETTINGS); |
977 DCHECK(settings); | 977 DCHECK(settings); |
978 | 978 |
979 SpdyFrameReader parser(frame->header_block(), frame->header_block_len()); | 979 SpdyFrameReader parser(frame->header_block(), frame->header_block_len()); |
980 for (size_t index = 0; index < frame->num_entries(); ++index) { | 980 for (size_t index = 0; index < frame->num_entries(); ++index) { |
981 uint32 id_and_flags_wire; | 981 uint32 id_and_flags_wire; |
982 uint32 value; | 982 uint32 value; |
(...skipping 21 matching lines...) Expand all Loading... |
1004 | 1004 |
1005 SpdyFrameReader parser(data, len); | 1005 SpdyFrameReader parser(data, len); |
1006 base::StringPiece temp; | 1006 base::StringPiece temp; |
1007 if (!parser.ReadUInt16(&credential->slot)) { | 1007 if (!parser.ReadUInt16(&credential->slot)) { |
1008 return false; | 1008 return false; |
1009 } | 1009 } |
1010 | 1010 |
1011 if (!parser.ReadStringPiece32(&temp)) { | 1011 if (!parser.ReadStringPiece32(&temp)) { |
1012 return false; | 1012 return false; |
1013 } | 1013 } |
1014 temp.CopyToString(&credential->proof); | 1014 credential->proof = temp.as_string(); |
1015 | 1015 |
1016 while (!parser.IsDoneReading()) { | 1016 while (!parser.IsDoneReading()) { |
1017 if (!parser.ReadStringPiece32(&temp)) { | 1017 if (!parser.ReadStringPiece32(&temp)) { |
1018 return false; | 1018 return false; |
1019 } | 1019 } |
1020 std::string cert; | 1020 credential->certs.push_back(temp.as_string()); |
1021 temp.CopyToString(&cert); | |
1022 credential->certs.push_back(cert); | |
1023 } | 1021 } |
1024 return true; | 1022 return true; |
1025 } | 1023 } |
1026 | 1024 |
1027 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( | 1025 SpdySynStreamControlFrame* SpdyFramer::CreateSynStream( |
1028 SpdyStreamId stream_id, | 1026 SpdyStreamId stream_id, |
1029 SpdyStreamId associated_stream_id, | 1027 SpdyStreamId associated_stream_id, |
1030 SpdyPriority priority, | 1028 SpdyPriority priority, |
1031 uint8 credential_slot, | 1029 uint8 credential_slot, |
1032 SpdyControlFlags flags, | 1030 SpdyControlFlags flags, |
1033 bool compressed, | 1031 bool compressed, |
1034 const SpdyHeaderBlock* headers) { | 1032 const SpdyHeaderBlock* headers) { |
1035 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1033 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
1036 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); | 1034 DCHECK_EQ(0u, associated_stream_id & ~kStreamIdMask); |
1037 | 1035 |
1038 // Find our length. | 1036 // Find our length. |
1039 size_t frame_size = SpdySynStreamControlFrame::size() + | 1037 size_t frame_size = SpdySynStreamControlFrame::size() + |
1040 GetSerializedLength(headers); | 1038 GetSerializedLength(headers); |
1041 | 1039 |
1042 SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); | 1040 SpdyFrameBuilder frame(SYN_STREAM, flags, spdy_version_, frame_size); |
1043 frame.WriteUInt32(stream_id); | 1041 frame.WriteUInt32(stream_id); |
1044 frame.WriteUInt32(associated_stream_id); | 1042 frame.WriteUInt32(associated_stream_id); |
1045 // Cap as appropriate. | 1043 // Cap as appropriate. |
1046 if (priority > GetLowestPriority()) { | 1044 if (priority > GetLowestPriority()) { |
1047 DLOG(ERROR) << "Priority out-of-bounds."; | 1045 DLOG(DFATAL) << "Priority out-of-bounds."; |
1048 priority = GetLowestPriority(); | 1046 priority = GetLowestPriority(); |
1049 } | 1047 } |
1050 // Priority is 2 bits for <spdy3, 3 bits otherwise. | 1048 // Priority is 2 bits for <spdy3, 3 bits otherwise. |
1051 frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); | 1049 frame.WriteUInt8(priority << ((spdy_version_ < 3) ? 6 : 5)); |
1052 frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); | 1050 frame.WriteUInt8((spdy_version_ < 3) ? 0 : credential_slot); |
1053 WriteHeaderBlock(&frame, headers); | 1051 WriteHeaderBlock(&frame, headers); |
1054 DCHECK_EQ(frame.length(), frame_size); | 1052 DCHECK_EQ(frame.length(), frame_size); |
1055 | 1053 |
1056 scoped_ptr<SpdySynStreamControlFrame> syn_frame( | 1054 scoped_ptr<SpdySynStreamControlFrame> syn_frame( |
1057 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); | 1055 reinterpret_cast<SpdySynStreamControlFrame*>(frame.take())); |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1161 SpdyStreamId stream_id, | 1159 SpdyStreamId stream_id, |
1162 SpdyControlFlags flags, | 1160 SpdyControlFlags flags, |
1163 bool compressed, | 1161 bool compressed, |
1164 const SpdyHeaderBlock* headers) { | 1162 const SpdyHeaderBlock* headers) { |
1165 // Basically the same as CreateSynReply(). | 1163 // Basically the same as CreateSynReply(). |
1166 DCHECK_GT(stream_id, 0u); | 1164 DCHECK_GT(stream_id, 0u); |
1167 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1165 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
1168 | 1166 |
1169 // Find our length. | 1167 // Find our length. |
1170 size_t frame_size = SpdyHeadersControlFrame::size() + | 1168 size_t frame_size = SpdyHeadersControlFrame::size() + |
1171 GetSerializedLength(headers); | 1169 GetSerializedLength(headers); |
1172 // In SPDY 2, there were 2 unused bytes before payload. | 1170 // In SPDY 2, there were 2 unused bytes before payload. |
1173 if (spdy_version_ < 3) { | 1171 if (spdy_version_ < 3) { |
1174 frame_size += 2; | 1172 frame_size += 2; |
1175 } | 1173 } |
1176 | 1174 |
1177 SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); | 1175 SpdyFrameBuilder frame(HEADERS, flags, spdy_version_, frame_size); |
1178 frame.WriteUInt32(stream_id); | 1176 frame.WriteUInt32(stream_id); |
1179 if (spdy_version_ < 3) { | 1177 if (spdy_version_ < 3) { |
1180 frame.WriteUInt16(0); // Unused | 1178 frame.WriteUInt16(0); // Unused |
1181 } | 1179 } |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1235 frame.WriteBytes(cert->c_str(), cert->length()); | 1233 frame.WriteBytes(cert->c_str(), cert->length()); |
1236 } | 1234 } |
1237 DCHECK_EQ(frame.length(), frame_size); | 1235 DCHECK_EQ(frame.length(), frame_size); |
1238 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); | 1236 return reinterpret_cast<SpdyCredentialControlFrame*>(frame.take()); |
1239 } | 1237 } |
1240 | 1238 |
1241 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, | 1239 SpdyDataFrame* SpdyFramer::CreateDataFrame(SpdyStreamId stream_id, |
1242 const char* data, | 1240 const char* data, |
1243 uint32 len, SpdyDataFlags flags) { | 1241 uint32 len, SpdyDataFlags flags) { |
1244 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); | 1242 DCHECK_EQ(0u, stream_id & ~kStreamIdMask); |
1245 | |
1246 size_t frame_size = SpdyDataFrame::size() + len; | 1243 size_t frame_size = SpdyDataFrame::size() + len; |
1247 SpdyFrameBuilder frame(stream_id, flags, frame_size); | 1244 SpdyFrameBuilder frame(stream_id, flags, frame_size); |
1248 frame.WriteBytes(data, len); | 1245 frame.WriteBytes(data, len); |
1249 DCHECK_EQ(frame.length(), frame_size); | 1246 DCHECK_EQ(frame.length(), frame_size); |
1250 return reinterpret_cast<SpdyDataFrame*>(frame.take()); | 1247 return reinterpret_cast<SpdyDataFrame*>(frame.take()); |
1251 } | 1248 } |
1252 | 1249 |
1253 // The following compression setting are based on Brian Olson's analysis. See | 1250 // The following compression setting are based on Brian Olson's analysis. See |
1254 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 | 1251 // https://groups.google.com/group/spdy-dev/browse_thread/thread/dfaf498542fac79
2 |
1255 // for more details. | 1252 // for more details. |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1380 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); | 1377 base::StatsCounter post_compress_bytes("spdy.PostCompressSize"); |
1381 | 1378 |
1382 if (!enable_compression_) | 1379 if (!enable_compression_) |
1383 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame)); | 1380 return reinterpret_cast<SpdyControlFrame*>(DuplicateFrame(frame)); |
1384 | 1381 |
1385 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) | 1382 if (!GetFrameBoundaries(frame, &payload_length, &header_length, &payload)) |
1386 return NULL; | 1383 return NULL; |
1387 | 1384 |
1388 // Create an output frame. | 1385 // Create an output frame. |
1389 int compressed_max_size = deflateBound(compressor, payload_length); | 1386 int compressed_max_size = deflateBound(compressor, payload_length); |
1390 int new_frame_size = header_length + compressed_max_size; | 1387 size_t new_frame_size = header_length + compressed_max_size; |
1391 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && | 1388 if ((frame.type() == SYN_REPLY || frame.type() == HEADERS) && |
1392 spdy_version_ < 3) { | 1389 spdy_version_ < 3) { |
1393 new_frame_size += 2; | 1390 new_frame_size += 2; |
1394 } | 1391 } |
1395 DCHECK_GE(new_frame_size, | 1392 DCHECK_GE(new_frame_size, frame.length() + SpdyFrame::kHeaderSize); |
1396 static_cast<int>(frame.length() + SpdyFrame::kHeaderSize)); | |
1397 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size)); | 1393 scoped_ptr<SpdyControlFrame> new_frame(new SpdyControlFrame(new_frame_size)); |
1398 memcpy(new_frame->data(), frame.data(), | 1394 memcpy(new_frame->data(), frame.data(), |
1399 frame.length() + SpdyFrame::kHeaderSize); | 1395 frame.length() + SpdyFrame::kHeaderSize); |
1400 | 1396 |
1401 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); | 1397 compressor->next_in = reinterpret_cast<Bytef*>(const_cast<char*>(payload)); |
1402 compressor->avail_in = payload_length; | 1398 compressor->avail_in = payload_length; |
1403 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + | 1399 compressor->next_out = reinterpret_cast<Bytef*>(new_frame->data()) + |
1404 header_length; | 1400 header_length; |
1405 compressor->avail_out = compressed_max_size; | 1401 compressor->avail_out = compressed_max_size; |
1406 | 1402 |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1577 case HEADERS: | 1573 case HEADERS: |
1578 return SpdyHeadersControlFrame::size(); | 1574 return SpdyHeadersControlFrame::size(); |
1579 case WINDOW_UPDATE: | 1575 case WINDOW_UPDATE: |
1580 return SpdyWindowUpdateControlFrame::size(); | 1576 return SpdyWindowUpdateControlFrame::size(); |
1581 case CREDENTIAL: | 1577 case CREDENTIAL: |
1582 return SpdyCredentialControlFrame::size(); | 1578 return SpdyCredentialControlFrame::size(); |
1583 case NUM_CONTROL_FRAME_TYPES: | 1579 case NUM_CONTROL_FRAME_TYPES: |
1584 break; | 1580 break; |
1585 } | 1581 } |
1586 LOG(ERROR) << "Unknown control frame type " << type; | 1582 LOG(ERROR) << "Unknown control frame type " << type; |
1587 return 0x7FFFFFFF; // Max signed 32bit int | 1583 return std::numeric_limits<size_t>::max(); |
1588 } | 1584 } |
1589 | 1585 |
1590 /* static */ | 1586 /* static */ |
1591 SpdyStreamId SpdyFramer::GetControlFrameStreamId( | 1587 SpdyStreamId SpdyFramer::GetControlFrameStreamId( |
1592 const SpdyControlFrame* control_frame) { | 1588 const SpdyControlFrame* control_frame) { |
1593 SpdyStreamId stream_id = kInvalidStream; | 1589 SpdyStreamId stream_id = kInvalidStream; |
1594 if (control_frame != NULL) { | 1590 if (control_frame != NULL) { |
1595 switch (control_frame->type()) { | 1591 switch (control_frame->type()) { |
1596 case SYN_STREAM: | 1592 case SYN_STREAM: |
1597 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( | 1593 stream_id = reinterpret_cast<const SpdySynStreamControlFrame*>( |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1631 | 1627 |
1632 void SpdyFramer::set_enable_compression(bool value) { | 1628 void SpdyFramer::set_enable_compression(bool value) { |
1633 enable_compression_ = value; | 1629 enable_compression_ = value; |
1634 } | 1630 } |
1635 | 1631 |
1636 void SpdyFramer::set_enable_compression_default(bool value) { | 1632 void SpdyFramer::set_enable_compression_default(bool value) { |
1637 g_enable_compression_default = value; | 1633 g_enable_compression_default = value; |
1638 } | 1634 } |
1639 | 1635 |
1640 } // namespace net | 1636 } // namespace net |
OLD | NEW |