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 #include "net/spdy/spdy_framer.h" | 5 #include "net/spdy/spdy_framer.h" |
6 | 6 |
7 #include <string.h> | 7 #include <string.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <cctype> | 10 #include <cctype> |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); | 107 const SpdyStreamId SpdyFramer::kInvalidStream = static_cast<SpdyStreamId>(-1); |
108 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; | 108 const size_t SpdyFramer::kHeaderDataChunkMaxSize = 1024; |
109 // Even though the length field is 24 bits, we keep this 16 kB | 109 // Even though the length field is 24 bits, we keep this 16 kB |
110 // limit on control frame size for legacy reasons and to | 110 // limit on control frame size for legacy reasons and to |
111 // mitigate DOS attacks. | 111 // mitigate DOS attacks. |
112 const size_t SpdyFramer::kMaxControlFrameSize = (1 << 14) - 1; | 112 const size_t SpdyFramer::kMaxControlFrameSize = (1 << 14) - 1; |
113 const size_t SpdyFramer::kMaxDataPayloadSendSize = 1 << 14; | 113 const size_t SpdyFramer::kMaxDataPayloadSendSize = 1 << 14; |
114 // The size of the control frame buffer. Must be >= the minimum size of the | 114 // The size of the control frame buffer. Must be >= the minimum size of the |
115 // largest control frame. | 115 // largest control frame. |
116 const size_t SpdyFramer::kControlFrameBufferSize = 19; | 116 const size_t SpdyFramer::kControlFrameBufferSize = 19; |
117 const size_t SpdyFramer::kOneSettingParameterSize = 6; | |
117 | 118 |
118 #ifdef DEBUG_SPDY_STATE_CHANGES | 119 #ifdef DEBUG_SPDY_STATE_CHANGES |
119 #define CHANGE_STATE(newstate) \ | 120 #define CHANGE_STATE(newstate) \ |
120 do { \ | 121 do { \ |
121 DVLOG(1) << "Changing state from: " \ | 122 DVLOG(1) << "Changing state from: " \ |
122 << StateToString(state_) \ | 123 << StateToString(state_) \ |
123 << " to " << StateToString(newstate) << "\n"; \ | 124 << " to " << StateToString(newstate) << "\n"; \ |
124 DCHECK(state_ != SPDY_ERROR); \ | 125 DCHECK(state_ != SPDY_ERROR); \ |
125 DCHECK_EQ(previous_state_, state_); \ | 126 DCHECK_EQ(previous_state_, state_); \ |
126 previous_state_ = state_; \ | 127 previous_state_ = state_; \ |
(...skipping 645 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
772 } else if (current_frame_flags_ != 0) { | 773 } else if (current_frame_flags_ != 0) { |
773 VLOG(1) << "Undefined frame flags for RST_STREAM frame: " << hex | 774 VLOG(1) << "Undefined frame flags for RST_STREAM frame: " << hex |
774 << static_cast<int>(current_frame_flags_); | 775 << static_cast<int>(current_frame_flags_); |
775 current_frame_flags_ = 0; | 776 current_frame_flags_ = 0; |
776 } | 777 } |
777 break; | 778 break; |
778 case SETTINGS: | 779 case SETTINGS: |
779 { | 780 { |
780 // Make sure that we have an integral number of 8-byte key/value pairs, | 781 // Make sure that we have an integral number of 8-byte key/value pairs, |
781 // Size of each key/value pair in bytes. | 782 // Size of each key/value pair in bytes. |
782 int setting_size = 6; | |
783 if (current_frame_length_ < GetSettingsMinimumSize() || | 783 if (current_frame_length_ < GetSettingsMinimumSize() || |
784 (current_frame_length_ - GetFrameHeaderSize()) % setting_size != 0) { | 784 (current_frame_length_ - GetFrameHeaderSize()) % |
785 kOneSettingParameterSize != | |
786 0) { | |
785 DLOG(WARNING) << "Invalid length for SETTINGS frame: " | 787 DLOG(WARNING) << "Invalid length for SETTINGS frame: " |
786 << current_frame_length_; | 788 << current_frame_length_; |
787 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE); | 789 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE); |
788 } else if (current_frame_flags_ & SETTINGS_FLAG_ACK && | 790 } else if (current_frame_flags_ & SETTINGS_FLAG_ACK && |
789 current_frame_length_ > GetSettingsMinimumSize()) { | 791 current_frame_length_ > GetSettingsMinimumSize()) { |
790 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE); | 792 set_error(SPDY_INVALID_CONTROL_FRAME_SIZE); |
791 } else if (current_frame_flags_ & ~SETTINGS_FLAG_ACK) { | 793 } else if (current_frame_flags_ & ~SETTINGS_FLAG_ACK) { |
792 VLOG(1) << "Undefined frame flags for SETTINGS frame: " << hex | 794 VLOG(1) << "Undefined frame flags for SETTINGS frame: " << hex |
793 << static_cast<int>(current_frame_flags_); | 795 << static_cast<int>(current_frame_flags_); |
794 current_frame_flags_ &= SETTINGS_FLAG_ACK; | 796 current_frame_flags_ &= SETTINGS_FLAG_ACK; |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1256 return bytes_read; | 1258 return bytes_read; |
1257 } | 1259 } |
1258 | 1260 |
1259 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, | 1261 size_t SpdyFramer::ProcessSettingsFramePayload(const char* data, |
1260 size_t data_len) { | 1262 size_t data_len) { |
1261 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); | 1263 DCHECK_EQ(SPDY_SETTINGS_FRAME_PAYLOAD, state_); |
1262 DCHECK_EQ(SETTINGS, current_frame_type_); | 1264 DCHECK_EQ(SETTINGS, current_frame_type_); |
1263 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); | 1265 size_t unprocessed_bytes = std::min(data_len, remaining_data_length_); |
1264 size_t processed_bytes = 0; | 1266 size_t processed_bytes = 0; |
1265 | 1267 |
1266 size_t setting_size = 6; | |
1267 | |
1268 // Loop over our incoming data. | 1268 // Loop over our incoming data. |
1269 while (unprocessed_bytes > 0) { | 1269 while (unprocessed_bytes > 0) { |
1270 // Process up to one setting at a time. | 1270 // Process up to one setting at a time. |
1271 size_t processing = std::min(unprocessed_bytes, | 1271 size_t processing = |
1272 setting_size - settings_scratch_.buffer.len()); | 1272 std::min(unprocessed_bytes, |
1273 kOneSettingParameterSize - settings_scratch_.buffer.len()); | |
1273 | 1274 |
1274 // Check if we have a complete setting in our input. | 1275 // Check if we have a complete setting in our input. |
1275 if (processing == setting_size) { | 1276 if (processing == kOneSettingParameterSize) { |
1276 // Parse the setting directly out of the input without buffering. | 1277 // Parse the setting directly out of the input without buffering. |
1277 if (!ProcessSetting(data + processed_bytes)) { | 1278 if (!ProcessSetting(data + processed_bytes)) { |
1278 set_error(SPDY_INVALID_CONTROL_FRAME); | 1279 set_error(SPDY_INVALID_CONTROL_FRAME); |
1279 return processed_bytes; | 1280 return processed_bytes; |
1280 } | 1281 } |
1281 } else { | 1282 } else { |
1282 // Continue updating settings_scratch_.setting_buf. | 1283 // Continue updating settings_scratch_.setting_buf. |
1283 settings_scratch_.buffer.CopyFrom(data + processed_bytes, processing); | 1284 settings_scratch_.buffer.CopyFrom(data + processed_bytes, processing); |
1284 | 1285 |
1285 // Check if we have a complete setting buffered. | 1286 // Check if we have a complete setting buffered. |
1286 if (settings_scratch_.buffer.len() == setting_size) { | 1287 if (settings_scratch_.buffer.len() == kOneSettingParameterSize) { |
1287 if (!ProcessSetting(settings_scratch_.buffer.data())) { | 1288 if (!ProcessSetting(settings_scratch_.buffer.data())) { |
1288 set_error(SPDY_INVALID_CONTROL_FRAME); | 1289 set_error(SPDY_INVALID_CONTROL_FRAME); |
1289 return processed_bytes; | 1290 return processed_bytes; |
1290 } | 1291 } |
1291 // Rewind settings buffer for our next setting. | 1292 // Rewind settings buffer for our next setting. |
1292 settings_scratch_.buffer.Rewind(); | 1293 settings_scratch_.buffer.Rewind(); |
1293 } | 1294 } |
1294 } | 1295 } |
1295 | 1296 |
1296 // Iterate. | 1297 // Iterate. |
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1738 headers_ir_->set_end_headers(!has_next_frame_); | 1739 headers_ir_->set_end_headers(!has_next_frame_); |
1739 return framer_->SerializeHeadersGivenEncoding(*headers_ir_, *encoding); | 1740 return framer_->SerializeHeadersGivenEncoding(*headers_ir_, *encoding); |
1740 } else { | 1741 } else { |
1741 SpdyContinuationIR continuation_ir(headers_ir_->stream_id()); | 1742 SpdyContinuationIR continuation_ir(headers_ir_->stream_id()); |
1742 continuation_ir.set_end_headers(!has_next_frame_); | 1743 continuation_ir.set_end_headers(!has_next_frame_); |
1743 continuation_ir.take_encoding(std::move(encoding)); | 1744 continuation_ir.take_encoding(std::move(encoding)); |
1744 return framer_->SerializeContinuation(continuation_ir); | 1745 return framer_->SerializeContinuation(continuation_ir); |
1745 } | 1746 } |
1746 } | 1747 } |
1747 | 1748 |
1749 void SpdyFramer::SerializeDataBuilderHelper(const SpdyDataIR& data_ir, | |
1750 uint8_t* flags, | |
1751 int* num_padding_fields, | |
1752 size_t* size_with_padding) const { | |
1753 if (data_ir.fin()) { | |
1754 *flags = DATA_FLAG_FIN; | |
1755 } | |
1756 | |
1757 if (data_ir.padded()) { | |
1758 *flags = *flags | DATA_FLAG_PADDED; | |
1759 ++*num_padding_fields; | |
1760 } | |
1761 | |
1762 *size_with_padding = *num_padding_fields + data_ir.data_len() + | |
1763 data_ir.padding_payload_len() + | |
1764 GetDataFrameMinimumSize(); | |
1765 } | |
1766 | |
1748 SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const { | 1767 SpdySerializedFrame SpdyFramer::SerializeData(const SpdyDataIR& data_ir) const { |
1749 uint8_t flags = DATA_FLAG_NONE; | 1768 uint8_t flags = DATA_FLAG_NONE; |
1750 if (data_ir.fin()) { | 1769 int num_padding_fields = 0; |
1751 flags = DATA_FLAG_FIN; | 1770 size_t size_with_padding = 0; |
1752 } | 1771 SerializeDataBuilderHelper(data_ir, &flags, &num_padding_fields, |
1772 &size_with_padding); | |
1753 | 1773 |
1754 int num_padding_fields = 0; | |
1755 if (data_ir.padded()) { | |
1756 flags |= DATA_FLAG_PADDED; | |
1757 ++num_padding_fields; | |
1758 } | |
1759 | |
1760 const size_t size_with_padding = num_padding_fields + data_ir.data_len() + | |
1761 data_ir.padding_payload_len() + | |
1762 GetDataFrameMinimumSize(); | |
1763 SpdyFrameBuilder builder(size_with_padding); | 1774 SpdyFrameBuilder builder(size_with_padding); |
1764 builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); | 1775 builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); |
1765 if (data_ir.padded()) { | 1776 if (data_ir.padded()) { |
1766 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | 1777 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
1767 } | 1778 } |
1768 builder.WriteBytes(data_ir.data(), data_ir.data_len()); | 1779 builder.WriteBytes(data_ir.data(), data_ir.data_len()); |
1769 if (data_ir.padding_payload_len() > 0) { | 1780 if (data_ir.padding_payload_len() > 0) { |
1770 string padding(data_ir.padding_payload_len(), 0); | 1781 string padding(data_ir.padding_payload_len(), 0); |
1771 builder.WriteBytes(padding.data(), padding.length()); | 1782 builder.WriteBytes(padding.data(), padding.length()); |
1772 } | 1783 } |
1773 DCHECK_EQ(size_with_padding, builder.length()); | 1784 DCHECK_EQ(size_with_padding, builder.length()); |
1774 return builder.take(); | 1785 return builder.take(); |
1775 } | 1786 } |
1776 | 1787 |
1788 void SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper( | |
1789 const SpdyDataIR& data_ir, | |
1790 uint8_t* flags, | |
1791 size_t* frame_size, | |
1792 size_t* num_padding_fields) const { | |
1793 *flags = DATA_FLAG_NONE; | |
1794 if (data_ir.fin()) { | |
1795 *flags = DATA_FLAG_FIN; | |
1796 } | |
1797 | |
1798 *frame_size = GetDataFrameMinimumSize(); | |
1799 if (data_ir.padded()) { | |
1800 *flags = *flags | DATA_FLAG_PADDED; | |
1801 ++(*num_padding_fields); | |
1802 *frame_size = *frame_size + *num_padding_fields; | |
1803 } | |
1804 } | |
1805 | |
1777 SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( | 1806 SpdySerializedFrame SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( |
1778 const SpdyDataIR& data_ir) const { | 1807 const SpdyDataIR& data_ir) const { |
1779 uint8_t flags = DATA_FLAG_NONE; | 1808 uint8_t flags = DATA_FLAG_NONE; |
1780 if (data_ir.fin()) { | 1809 size_t frame_size = 0; |
1781 flags = DATA_FLAG_FIN; | |
1782 } | |
1783 | |
1784 size_t frame_size = GetDataFrameMinimumSize(); | |
1785 size_t num_padding_fields = 0; | 1810 size_t num_padding_fields = 0; |
1786 if (data_ir.padded()) { | 1811 SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper( |
1787 flags |= DATA_FLAG_PADDED; | 1812 data_ir, &flags, &frame_size, &num_padding_fields); |
1788 ++num_padding_fields; | |
1789 frame_size += num_padding_fields; | |
1790 } | |
1791 | 1813 |
1792 SpdyFrameBuilder builder(frame_size); | 1814 SpdyFrameBuilder builder(frame_size); |
1793 if (!skip_rewritelength_) { | 1815 if (!skip_rewritelength_) { |
1794 builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); | 1816 builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); |
1795 if (data_ir.padded()) { | 1817 if (data_ir.padded()) { |
1796 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | 1818 builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); |
1797 } | 1819 } |
1798 builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() + | 1820 builder.OverwriteLength(*this, num_padding_fields + data_ir.data_len() + |
1799 data_ir.padding_payload_len()); | 1821 data_ir.padding_payload_len()); |
1800 } else { | 1822 } else { |
(...skipping 14 matching lines...) Expand all Loading... | |
1815 SpdyFrameBuilder builder(expected_length); | 1837 SpdyFrameBuilder builder(expected_length); |
1816 | 1838 |
1817 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); | 1839 builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); |
1818 | 1840 |
1819 builder.WriteUInt32(rst_stream.error_code()); | 1841 builder.WriteUInt32(rst_stream.error_code()); |
1820 | 1842 |
1821 DCHECK_EQ(expected_length, builder.length()); | 1843 DCHECK_EQ(expected_length, builder.length()); |
1822 return builder.take(); | 1844 return builder.take(); |
1823 } | 1845 } |
1824 | 1846 |
1847 void SpdyFramer::SerializeSettingsBuilderHelper(const SpdySettingsIR& settings, | |
1848 uint8_t* flags, | |
1849 const SettingsMap* values, | |
1850 size_t* size) const { | |
1851 if (settings.is_ack()) { | |
1852 *flags = *flags | SETTINGS_FLAG_ACK; | |
1853 } | |
1854 *size = | |
1855 GetSettingsMinimumSize() + (values->size() * kOneSettingParameterSize); | |
1856 } | |
1857 | |
1825 SpdySerializedFrame SpdyFramer::SerializeSettings( | 1858 SpdySerializedFrame SpdyFramer::SerializeSettings( |
Bence
2017/03/16 18:12:54
9 lines were removed from this method and 6 added
yasong
2017/03/16 22:28:52
Nice catch!! How did find them?
Bence
2017/03/16 22:40:58
By going through the two diffs side by side. Unfo
| |
1826 const SpdySettingsIR& settings) const { | 1859 const SpdySettingsIR& settings) const { |
1827 uint8_t flags = 0; | 1860 uint8_t flags = 0; |
1828 | 1861 |
1829 if (settings.is_ack()) { | 1862 if (settings.is_ack()) { |
1830 flags |= SETTINGS_FLAG_ACK; | 1863 flags |= SETTINGS_FLAG_ACK; |
1831 } | 1864 } |
1832 const SettingsMap* values = &(settings.values()); | 1865 const SettingsMap* values = &(settings.values()); |
1833 | 1866 |
1834 int setting_size = 6; | 1867 int setting_size = 6; |
1835 // Size, in bytes, of this SETTINGS frame. | 1868 // Size, in bytes, of this SETTINGS frame. |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1886 // GOAWAY frames may also specify opaque data. | 1919 // GOAWAY frames may also specify opaque data. |
1887 if (!goaway.description().empty()) { | 1920 if (!goaway.description().empty()) { |
1888 builder.WriteBytes(goaway.description().data(), | 1921 builder.WriteBytes(goaway.description().data(), |
1889 goaway.description().size()); | 1922 goaway.description().size()); |
1890 } | 1923 } |
1891 | 1924 |
1892 DCHECK_EQ(expected_length, builder.length()); | 1925 DCHECK_EQ(expected_length, builder.length()); |
1893 return builder.take(); | 1926 return builder.take(); |
1894 } | 1927 } |
1895 | 1928 |
1929 void SpdyFramer::SerializeHeadersBuilderHelper(const SpdyHeadersIR& headers, | |
1930 uint8_t* flags, | |
1931 size_t* size, | |
1932 string* hpack_encoding, | |
1933 int* weight, | |
1934 size_t* length_field) { | |
1935 if (headers.fin()) { | |
1936 *flags = *flags | CONTROL_FLAG_FIN; | |
1937 } | |
1938 // This will get overwritten if we overflow into a CONTINUATION frame. | |
1939 *flags = *flags | HEADERS_FLAG_END_HEADERS; | |
1940 if (headers.has_priority()) { | |
1941 *flags = *flags | HEADERS_FLAG_PRIORITY; | |
1942 } | |
1943 if (headers.padded()) { | |
1944 *flags = *flags | HEADERS_FLAG_PADDED; | |
1945 } | |
1946 | |
1947 *size = GetHeadersMinimumSize(); | |
1948 | |
1949 if (headers.padded()) { | |
1950 *size = *size + kPadLengthFieldSize; | |
1951 *size = *size + headers.padding_payload_len(); | |
1952 } | |
1953 | |
1954 if (headers.has_priority()) { | |
1955 *weight = ClampHttp2Weight(headers.weight()); | |
1956 *size = *size + 5; | |
1957 } | |
1958 | |
1959 GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), hpack_encoding); | |
1960 *size = *size + hpack_encoding->size(); | |
1961 if (*size > kMaxControlFrameSize) { | |
1962 *size = *size + GetNumberRequiredContinuationFrames(*size) * | |
1963 GetContinuationMinimumSize(); | |
1964 *flags = *flags & ~HEADERS_FLAG_END_HEADERS; | |
1965 } | |
1966 // Compute frame length field. | |
1967 if (headers.padded()) { | |
1968 *length_field = *length_field + 1; // Padding length field. | |
1969 } | |
1970 if (headers.has_priority()) { | |
1971 *length_field = *length_field + 4; // Dependency field. | |
1972 *length_field = *length_field + 1; // Weight field. | |
1973 } | |
1974 *length_field = *length_field + headers.padding_payload_len(); | |
1975 *length_field = *length_field + hpack_encoding->size(); | |
1976 // If the HEADERS frame with payload would exceed the max frame size, then | |
1977 // WritePayloadWithContinuation() will serialize CONTINUATION frames as | |
1978 // necessary. | |
1979 *length_field = | |
1980 std::min(*length_field, kMaxControlFrameSize - GetFrameHeaderSize()); | |
1981 } | |
1982 | |
1896 SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) { | 1983 SpdySerializedFrame SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers) { |
1897 uint8_t flags = 0; | 1984 uint8_t flags = 0; |
1898 if (headers.fin()) { | |
1899 flags |= CONTROL_FLAG_FIN; | |
1900 } | |
1901 // This will get overwritten if we overflow into a CONTINUATION frame. | |
1902 flags |= HEADERS_FLAG_END_HEADERS; | |
1903 if (headers.has_priority()) { | |
1904 flags |= HEADERS_FLAG_PRIORITY; | |
1905 } | |
1906 if (headers.padded()) { | |
1907 flags |= HEADERS_FLAG_PADDED; | |
1908 } | |
1909 | |
1910 // The size of this frame, including padding (if there is any) and | 1985 // The size of this frame, including padding (if there is any) and |
1911 // variable-length header block. | 1986 // variable-length header block. |
1912 size_t size = GetHeadersMinimumSize(); | 1987 size_t size = 0; |
1913 | 1988 string hpack_encoding; |
1914 if (headers.padded()) { | |
1915 size += kPadLengthFieldSize; | |
1916 size += headers.padding_payload_len(); | |
1917 } | |
1918 | |
1919 int weight = 0; | 1989 int weight = 0; |
1920 if (headers.has_priority()) { | 1990 size_t length_field = 0; |
1921 weight = ClampHttp2Weight(headers.weight()); | 1991 SerializeHeadersBuilderHelper(headers, &flags, &size, &hpack_encoding, |
1922 size += 5; | 1992 &weight, &length_field); |
1923 } | |
1924 | |
1925 string hpack_encoding; | |
1926 GetHpackEncoder()->EncodeHeaderSet(headers.header_block(), &hpack_encoding); | |
1927 size += hpack_encoding.size(); | |
1928 if (size > kMaxControlFrameSize) { | |
1929 size += GetNumberRequiredContinuationFrames(size) * | |
1930 GetContinuationMinimumSize(); | |
1931 flags &= ~HEADERS_FLAG_END_HEADERS; | |
1932 } | |
1933 | 1993 |
1934 SpdyFrameBuilder builder(size); | 1994 SpdyFrameBuilder builder(size); |
1935 | 1995 |
1936 if (!skip_rewritelength_) { | 1996 if (!skip_rewritelength_) { |
1937 builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id()); | 1997 builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id()); |
1938 } else { | 1998 } else { |
1939 // Compute frame length field. | |
1940 size_t length_field = 0; | |
1941 if (headers.padded()) { | |
1942 length_field += 1; // Padding length field. | |
1943 } | |
1944 if (headers.has_priority()) { | |
1945 length_field += 4; // Dependency field. | |
1946 length_field += 1; // Weight field. | |
1947 } | |
1948 length_field += headers.padding_payload_len(); | |
1949 length_field += hpack_encoding.size(); | |
1950 // If the HEADERS frame with payload would exceed the max frame size, then | |
1951 // WritePayloadWithContinuation() will serialize CONTINUATION frames as | |
1952 // necessary. | |
1953 length_field = | |
1954 std::min(length_field, kMaxControlFrameSize - GetFrameHeaderSize()); | |
1955 builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(), | 1999 builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(), |
1956 length_field); | 2000 length_field); |
1957 } | 2001 } |
1958 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | 2002 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); |
1959 | 2003 |
1960 int padding_payload_len = 0; | 2004 int padding_payload_len = 0; |
1961 if (headers.padded()) { | 2005 if (headers.padded()) { |
1962 builder.WriteUInt8(headers.padding_payload_len()); | 2006 builder.WriteUInt8(headers.padding_payload_len()); |
1963 padding_payload_len = headers.padding_payload_len(); | 2007 padding_payload_len = headers.padding_payload_len(); |
1964 } | 2008 } |
(...skipping 30 matching lines...) Expand all Loading... | |
1995 return builder.take(); | 2039 return builder.take(); |
1996 } | 2040 } |
1997 | 2041 |
1998 SpdySerializedFrame SpdyFramer::SerializeBlocked( | 2042 SpdySerializedFrame SpdyFramer::SerializeBlocked( |
1999 const SpdyBlockedIR& blocked) const { | 2043 const SpdyBlockedIR& blocked) const { |
2000 SpdyFrameBuilder builder(GetBlockedSize()); | 2044 SpdyFrameBuilder builder(GetBlockedSize()); |
2001 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); | 2045 builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); |
2002 return builder.take(); | 2046 return builder.take(); |
2003 } | 2047 } |
2004 | 2048 |
2049 void SpdyFramer::SerializePushPromiseBuilderHelper( | |
2050 const SpdyPushPromiseIR& push_promise, | |
2051 uint8_t* flags, | |
2052 string* hpack_encoding, | |
2053 size_t* size) { | |
2054 *flags = 0; | |
2055 // This will get overwritten if we overflow into a CONTINUATION frame. | |
2056 *flags = *flags | PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | |
2057 // The size of this frame, including variable-length name-value block. | |
2058 *size = GetPushPromiseMinimumSize(); | |
2059 | |
2060 if (push_promise.padded()) { | |
2061 *flags = *flags | PUSH_PROMISE_FLAG_PADDED; | |
2062 *size = *size + kPadLengthFieldSize; | |
2063 *size = *size + push_promise.padding_payload_len(); | |
2064 } | |
2065 | |
2066 GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(), | |
2067 hpack_encoding); | |
2068 *size = *size + hpack_encoding->size(); | |
2069 if (*size > kMaxControlFrameSize) { | |
2070 *size = *size + GetNumberRequiredContinuationFrames(*size) * | |
2071 GetContinuationMinimumSize(); | |
2072 *flags = *flags & ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | |
2073 } | |
2074 } | |
2075 | |
2005 SpdySerializedFrame SpdyFramer::SerializePushPromise( | 2076 SpdySerializedFrame SpdyFramer::SerializePushPromise( |
2006 const SpdyPushPromiseIR& push_promise) { | 2077 const SpdyPushPromiseIR& push_promise) { |
2007 uint8_t flags = 0; | 2078 uint8_t flags = 0; |
2008 // This will get overwritten if we overflow into a CONTINUATION frame. | 2079 size_t size = 0; |
2009 flags |= PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | |
2010 // The size of this frame, including variable-length name-value block. | |
2011 size_t size = GetPushPromiseMinimumSize(); | |
2012 | |
2013 if (push_promise.padded()) { | |
2014 flags |= PUSH_PROMISE_FLAG_PADDED; | |
2015 size += kPadLengthFieldSize; | |
2016 size += push_promise.padding_payload_len(); | |
2017 } | |
2018 | |
2019 string hpack_encoding; | 2080 string hpack_encoding; |
2020 GetHpackEncoder()->EncodeHeaderSet(push_promise.header_block(), | 2081 SerializePushPromiseBuilderHelper(push_promise, &flags, &hpack_encoding, |
2021 &hpack_encoding); | 2082 &size); |
2022 size += hpack_encoding.size(); | |
2023 if (size > kMaxControlFrameSize) { | |
2024 size += GetNumberRequiredContinuationFrames(size) * | |
2025 GetContinuationMinimumSize(); | |
2026 flags &= ~PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | |
2027 } | |
2028 | 2083 |
2029 SpdyFrameBuilder builder(size); | 2084 SpdyFrameBuilder builder(size); |
2030 if (!skip_rewritelength_) { | 2085 if (!skip_rewritelength_) { |
2031 builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id()); | 2086 builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id()); |
2032 } else { | 2087 } else { |
2033 size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize(); | 2088 size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize(); |
2034 builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id(), | 2089 builder.BeginNewFrame(*this, PUSH_PROMISE, flags, push_promise.stream_id(), |
2035 length); | 2090 length); |
2036 } | 2091 } |
2037 int padding_payload_len = 0; | 2092 int padding_payload_len = 0; |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2100 | 2155 |
2101 SpdySerializedFrame SpdyFramer::SerializeContinuation( | 2156 SpdySerializedFrame SpdyFramer::SerializeContinuation( |
2102 const SpdyContinuationIR& continuation) const { | 2157 const SpdyContinuationIR& continuation) const { |
2103 const string& encoding = continuation.encoding(); | 2158 const string& encoding = continuation.encoding(); |
2104 size_t frame_size = GetContinuationMinimumSize() + encoding.size(); | 2159 size_t frame_size = GetContinuationMinimumSize() + encoding.size(); |
2105 SpdyFrameBuilder builder(frame_size); | 2160 SpdyFrameBuilder builder(frame_size); |
2106 uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0; | 2161 uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0; |
2107 builder.BeginNewFrame(*this, CONTINUATION, flags, continuation.stream_id()); | 2162 builder.BeginNewFrame(*this, CONTINUATION, flags, continuation.stream_id()); |
2108 DCHECK_EQ(GetFrameHeaderSize(), builder.length()); | 2163 DCHECK_EQ(GetFrameHeaderSize(), builder.length()); |
2109 | 2164 |
2110 builder.WriteBytes(&encoding[0], encoding.size()); | 2165 builder.WriteBytes(encoding.data(), encoding.size()); |
2111 return builder.take(); | 2166 return builder.take(); |
2112 } | 2167 } |
2113 | 2168 |
2169 void SpdyFramer::SerializeAltSvcBuilderHelper(const SpdyAltSvcIR& altsvc_ir, | |
2170 string* value, | |
2171 size_t* size) const { | |
2172 *size = GetAltSvcMinimumSize(); | |
2173 *size = *size + altsvc_ir.origin().length(); | |
2174 *value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | |
2175 altsvc_ir.altsvc_vector()); | |
2176 *size = *size + value->length(); | |
2177 } | |
2178 | |
2114 SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) { | 2179 SpdySerializedFrame SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir) { |
2115 size_t size = GetAltSvcMinimumSize(); | 2180 string value; |
2116 size += altsvc_ir.origin().length(); | 2181 size_t size = 0; |
2117 string value = SpdyAltSvcWireFormat::SerializeHeaderFieldValue( | 2182 SerializeAltSvcBuilderHelper(altsvc_ir, &value, &size); |
2118 altsvc_ir.altsvc_vector()); | |
2119 size += value.length(); | |
2120 | |
2121 SpdyFrameBuilder builder(size); | 2183 SpdyFrameBuilder builder(size); |
2122 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id()); | 2184 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id()); |
2123 | 2185 |
2124 builder.WriteUInt16(altsvc_ir.origin().length()); | 2186 builder.WriteUInt16(altsvc_ir.origin().length()); |
2125 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length()); | 2187 builder.WriteBytes(altsvc_ir.origin().data(), altsvc_ir.origin().length()); |
2126 builder.WriteBytes(value.data(), value.length()); | 2188 builder.WriteBytes(value.data(), value.length()); |
2127 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); | 2189 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); |
2128 return builder.take(); | 2190 return builder.take(); |
2129 } | 2191 } |
2130 | 2192 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2285 frame.Visit(&visitor); | 2347 frame.Visit(&visitor); |
2286 return visitor.ReleaseSerializedFrame(); | 2348 return visitor.ReleaseSerializedFrame(); |
2287 } | 2349 } |
2288 | 2350 |
2289 uint8_t SpdyFramer::GetSerializedFlags(const SpdyFrameIR& frame) { | 2351 uint8_t SpdyFramer::GetSerializedFlags(const SpdyFrameIR& frame) { |
2290 FlagsSerializationVisitor visitor; | 2352 FlagsSerializationVisitor visitor; |
2291 frame.Visit(&visitor); | 2353 frame.Visit(&visitor); |
2292 return visitor.flags(); | 2354 return visitor.flags(); |
2293 } | 2355 } |
2294 | 2356 |
2357 bool SpdyFramer::SerializeData(const SpdyDataIR& data_ir, | |
2358 ZeroCopyOutputBuffer* output) const { | |
2359 uint8_t flags = DATA_FLAG_NONE; | |
2360 int num_padding_fields = 0; | |
2361 size_t size_with_padding = 0; | |
2362 SerializeDataBuilderHelper(data_ir, &flags, &num_padding_fields, | |
2363 &size_with_padding); | |
2364 SpdyFrameBuilder builder(size_with_padding, output); | |
2365 | |
2366 bool ok = builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); | |
2367 | |
2368 if (data_ir.padded()) { | |
2369 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | |
2370 } | |
2371 | |
2372 ok = ok && builder.WriteBytes(data_ir.data(), data_ir.data_len()); | |
2373 if (data_ir.padding_payload_len() > 0) { | |
2374 string padding; | |
2375 padding = string(data_ir.padding_payload_len(), 0); | |
2376 ok = ok && builder.WriteBytes(padding.data(), padding.length()); | |
2377 } | |
2378 DCHECK_EQ(size_with_padding, builder.length()); | |
2379 return ok; | |
2380 } | |
2381 | |
2382 bool SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField( | |
2383 const SpdyDataIR& data_ir, | |
2384 ZeroCopyOutputBuffer* output) const { | |
2385 uint8_t flags = DATA_FLAG_NONE; | |
2386 size_t frame_size = 0; | |
2387 size_t num_padding_fields = 0; | |
2388 SerializeDataFrameHeaderWithPaddingLengthFieldBuilderHelper( | |
2389 data_ir, &flags, &frame_size, &num_padding_fields); | |
2390 | |
2391 SpdyFrameBuilder builder(frame_size, output); | |
2392 bool ok = true; | |
2393 if (!skip_rewritelength_) { | |
2394 ok = builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id()); | |
2395 if (data_ir.padded()) { | |
2396 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | |
2397 } | |
2398 ok = ok && builder.OverwriteLength(*this, | |
2399 num_padding_fields + data_ir.data_len() + | |
2400 data_ir.padding_payload_len()); | |
2401 } else { | |
2402 ok = ok && builder.BeginNewFrame(*this, DATA, flags, data_ir.stream_id(), | |
2403 num_padding_fields + data_ir.data_len() + | |
2404 data_ir.padding_payload_len()); | |
2405 if (data_ir.padded()) { | |
2406 ok = ok && builder.WriteUInt8(data_ir.padding_payload_len() & 0xff); | |
2407 } | |
2408 } | |
2409 DCHECK_EQ(frame_size, builder.length()); | |
2410 return ok; | |
2411 } | |
2412 | |
2413 bool SpdyFramer::SerializeRstStream(const SpdyRstStreamIR& rst_stream, | |
2414 ZeroCopyOutputBuffer* output) const { | |
2415 size_t expected_length = GetRstStreamSize(); | |
2416 SpdyFrameBuilder builder(expected_length, output); | |
2417 bool ok = builder.BeginNewFrame(*this, RST_STREAM, 0, rst_stream.stream_id()); | |
2418 ok = ok && builder.WriteUInt32(rst_stream.error_code()); | |
2419 | |
2420 DCHECK_EQ(expected_length, builder.length()); | |
2421 return ok; | |
2422 } | |
2423 | |
2424 bool SpdyFramer::SerializeSettings(const SpdySettingsIR& settings, | |
2425 ZeroCopyOutputBuffer* output) const { | |
2426 uint8_t flags = 0; | |
2427 // Size, in bytes, of this SETTINGS frame. | |
2428 size_t size = 0; | |
2429 const SettingsMap* values = &(settings.values()); | |
2430 SerializeSettingsBuilderHelper(settings, &flags, values, &size); | |
2431 SpdyFrameBuilder builder(size, output); | |
2432 bool ok = builder.BeginNewFrame(*this, SETTINGS, flags, 0); | |
2433 | |
2434 // If this is an ACK, payload should be empty. | |
2435 if (settings.is_ack()) { | |
2436 return ok; | |
2437 } | |
2438 | |
2439 DCHECK_EQ(GetSettingsMinimumSize(), builder.length()); | |
2440 for (SettingsMap::const_iterator it = values->begin(); it != values->end(); | |
2441 ++it) { | |
2442 int setting_id = it->first; | |
2443 DCHECK_GE(setting_id, 0); | |
2444 ok = ok && builder.WriteUInt16(static_cast<uint16_t>(setting_id)) && | |
2445 builder.WriteUInt32(it->second); | |
2446 } | |
2447 DCHECK_EQ(size, builder.length()); | |
2448 return ok; | |
2449 } | |
2450 | |
2451 bool SpdyFramer::SerializePing(const SpdyPingIR& ping, | |
2452 ZeroCopyOutputBuffer* output) const { | |
2453 SpdyFrameBuilder builder(GetPingSize(), output); | |
2454 uint8_t flags = 0; | |
2455 if (ping.is_ack()) { | |
2456 flags |= PING_FLAG_ACK; | |
2457 } | |
2458 bool ok = builder.BeginNewFrame(*this, PING, flags, 0); | |
2459 ok = ok && builder.WriteUInt64(ping.id()); | |
2460 DCHECK_EQ(GetPingSize(), builder.length()); | |
2461 return ok; | |
2462 } | |
2463 | |
2464 bool SpdyFramer::SerializeGoAway(const SpdyGoAwayIR& goaway, | |
2465 ZeroCopyOutputBuffer* output) const { | |
2466 // Compute the output buffer size, take opaque data into account. | |
2467 size_t expected_length = GetGoAwayMinimumSize(); | |
2468 expected_length += goaway.description().size(); | |
2469 SpdyFrameBuilder builder(expected_length, output); | |
2470 | |
2471 // Serialize the GOAWAY frame. | |
2472 bool ok = builder.BeginNewFrame(*this, GOAWAY, 0, 0); | |
2473 | |
2474 // GOAWAY frames specify the last good stream id. | |
2475 ok = ok && builder.WriteUInt32(goaway.last_good_stream_id()) && | |
2476 // GOAWAY frames also specify the error status code. | |
2477 builder.WriteUInt32(goaway.error_code()); | |
2478 | |
2479 // GOAWAY frames may also specify opaque data. | |
2480 if (!goaway.description().empty()) { | |
2481 ok = ok && builder.WriteBytes(goaway.description().data(), | |
2482 goaway.description().size()); | |
2483 } | |
2484 | |
2485 DCHECK_EQ(expected_length, builder.length()); | |
2486 return ok; | |
2487 } | |
2488 | |
2489 bool SpdyFramer::SerializeHeaders(const SpdyHeadersIR& headers, | |
2490 ZeroCopyOutputBuffer* output) { | |
2491 uint8_t flags = 0; | |
2492 // The size of this frame, including padding (if there is any) and | |
2493 // variable-length header block. | |
2494 size_t size = 0; | |
2495 string hpack_encoding; | |
2496 int weight = 0; | |
2497 size_t length_field = 0; | |
2498 SerializeHeadersBuilderHelper(headers, &flags, &size, &hpack_encoding, | |
2499 &weight, &length_field); | |
2500 | |
2501 bool ok = true; | |
2502 SpdyFrameBuilder builder(size, output); | |
2503 if (!skip_rewritelength_) { | |
2504 ok = builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id()); | |
2505 } else { | |
2506 ok = ok && builder.BeginNewFrame(*this, HEADERS, flags, headers.stream_id(), | |
2507 length_field); | |
2508 } | |
2509 DCHECK_EQ(GetHeadersMinimumSize(), builder.length()); | |
2510 | |
2511 int padding_payload_len = 0; | |
2512 if (headers.padded()) { | |
2513 ok = ok && builder.WriteUInt8(headers.padding_payload_len()); | |
2514 padding_payload_len = headers.padding_payload_len(); | |
2515 } | |
2516 if (headers.has_priority()) { | |
2517 ok = ok && | |
2518 builder.WriteUInt32(PackStreamDependencyValues( | |
2519 headers.exclusive(), headers.parent_stream_id())) && | |
2520 // Per RFC 7540 section 6.3, serialized weight value is weight - 1. | |
2521 builder.WriteUInt8(weight - 1); | |
2522 } | |
2523 ok = ok && WritePayloadWithContinuation(&builder, hpack_encoding, | |
2524 headers.stream_id(), HEADERS, | |
2525 padding_payload_len); | |
2526 | |
2527 if (debug_visitor_) { | |
2528 // HTTP2 uses HPACK for header compression. However, continue to | |
2529 // use GetSerializedLength() for an apples-to-apples comparision of | |
2530 // compression performance between HPACK and SPDY w/ deflate. | |
2531 const size_t payload_len = GetSerializedLength(&(headers.header_block())); | |
2532 debug_visitor_->OnSendCompressedFrame(headers.stream_id(), HEADERS, | |
2533 payload_len, builder.length()); | |
2534 } | |
2535 | |
2536 return ok; | |
2537 } | |
2538 | |
2539 bool SpdyFramer::SerializeWindowUpdate(const SpdyWindowUpdateIR& window_update, | |
2540 ZeroCopyOutputBuffer* output) const { | |
2541 SpdyFrameBuilder builder(GetWindowUpdateSize(), output); | |
2542 bool ok = builder.BeginNewFrame(*this, WINDOW_UPDATE, kNoFlags, | |
2543 window_update.stream_id()); | |
2544 ok = ok && builder.WriteUInt32(window_update.delta()); | |
2545 DCHECK_EQ(GetWindowUpdateSize(), builder.length()); | |
2546 return ok; | |
2547 } | |
2548 | |
2549 bool SpdyFramer::SerializeBlocked(const SpdyBlockedIR& blocked, | |
2550 ZeroCopyOutputBuffer* output) const { | |
2551 SpdyFrameBuilder builder(GetBlockedSize(), output); | |
2552 return builder.BeginNewFrame(*this, BLOCKED, kNoFlags, blocked.stream_id()); | |
2553 } | |
2554 | |
2555 bool SpdyFramer::SerializePushPromise(const SpdyPushPromiseIR& push_promise, | |
2556 ZeroCopyOutputBuffer* output) { | |
2557 uint8_t flags = 0; | |
2558 size_t size = 0; | |
2559 string hpack_encoding; | |
2560 SerializePushPromiseBuilderHelper(push_promise, &flags, &hpack_encoding, | |
2561 &size); | |
2562 | |
2563 bool ok = true; | |
2564 SpdyFrameBuilder builder(size, output); | |
2565 if (!skip_rewritelength_) { | |
2566 ok = builder.BeginNewFrame(*this, PUSH_PROMISE, flags, | |
2567 push_promise.stream_id()); | |
2568 } else { | |
2569 size_t length = std::min(size, kMaxControlFrameSize) - GetFrameHeaderSize(); | |
2570 ok = builder.BeginNewFrame(*this, PUSH_PROMISE, flags, | |
2571 push_promise.stream_id(), length); | |
2572 } | |
2573 | |
2574 int padding_payload_len = 0; | |
2575 if (push_promise.padded()) { | |
2576 ok = ok && builder.WriteUInt8(push_promise.padding_payload_len()) && | |
2577 builder.WriteUInt32(push_promise.promised_stream_id()); | |
2578 DCHECK_EQ(GetPushPromiseMinimumSize() + kPadLengthFieldSize, | |
2579 builder.length()); | |
2580 | |
2581 padding_payload_len = push_promise.padding_payload_len(); | |
2582 } else { | |
2583 ok = ok && builder.WriteUInt32(push_promise.promised_stream_id()); | |
2584 DCHECK_EQ(GetPushPromiseMinimumSize(), builder.length()); | |
2585 } | |
2586 | |
2587 ok = ok && WritePayloadWithContinuation(&builder, hpack_encoding, | |
2588 push_promise.stream_id(), | |
2589 PUSH_PROMISE, padding_payload_len); | |
2590 | |
2591 if (debug_visitor_) { | |
2592 // HTTP2 uses HPACK for header compression. However, continue to | |
2593 // use GetSerializedLength() for an apples-to-apples comparision of | |
2594 // compression performance between HPACK and SPDY w/ deflate. | |
2595 const size_t payload_len = | |
2596 GetSerializedLength(&(push_promise.header_block())); | |
2597 debug_visitor_->OnSendCompressedFrame( | |
2598 push_promise.stream_id(), PUSH_PROMISE, payload_len, builder.length()); | |
2599 } | |
2600 | |
2601 return ok; | |
2602 } | |
2603 | |
2604 bool SpdyFramer::SerializeContinuation(const SpdyContinuationIR& continuation, | |
2605 ZeroCopyOutputBuffer* output) const { | |
2606 const string& encoding = continuation.encoding(); | |
2607 size_t frame_size = GetContinuationMinimumSize() + encoding.size(); | |
2608 SpdyFrameBuilder builder(frame_size, output); | |
2609 uint8_t flags = continuation.end_headers() ? HEADERS_FLAG_END_HEADERS : 0; | |
2610 bool ok = builder.BeginNewFrame(*this, CONTINUATION, flags, | |
2611 continuation.stream_id()); | |
2612 DCHECK_EQ(GetFrameHeaderSize(), builder.length()); | |
2613 | |
2614 ok = ok && builder.WriteBytes(encoding.data(), encoding.size()); | |
2615 return ok; | |
2616 } | |
2617 | |
2618 bool SpdyFramer::SerializeAltSvc(const SpdyAltSvcIR& altsvc_ir, | |
2619 ZeroCopyOutputBuffer* output) { | |
2620 string value; | |
2621 size_t size = 0; | |
2622 SerializeAltSvcBuilderHelper(altsvc_ir, &value, &size); | |
2623 SpdyFrameBuilder builder(size, output); | |
2624 bool ok = | |
2625 builder.BeginNewFrame(*this, ALTSVC, kNoFlags, altsvc_ir.stream_id()) && | |
2626 builder.WriteUInt16(altsvc_ir.origin().length()) && | |
2627 builder.WriteBytes(altsvc_ir.origin().data(), | |
2628 altsvc_ir.origin().length()) && | |
2629 builder.WriteBytes(value.data(), value.length()); | |
2630 DCHECK_LT(GetAltSvcMinimumSize(), builder.length()); | |
2631 return ok; | |
2632 } | |
2633 | |
2634 bool SpdyFramer::SerializePriority(const SpdyPriorityIR& priority, | |
2635 ZeroCopyOutputBuffer* output) const { | |
2636 size_t size = GetPrioritySize(); | |
2637 | |
2638 SpdyFrameBuilder builder(size, output); | |
2639 bool ok = | |
2640 builder.BeginNewFrame(*this, PRIORITY, kNoFlags, priority.stream_id()); | |
2641 ok = ok && | |
2642 builder.WriteUInt32(PackStreamDependencyValues( | |
2643 priority.exclusive(), priority.parent_stream_id())) && | |
2644 // Per RFC 7540 section 6.3, serialized weight value is actual value - 1. | |
2645 builder.WriteUInt8(priority.weight() - 1); | |
2646 DCHECK_EQ(GetPrioritySize(), builder.length()); | |
2647 return ok; | |
2648 } | |
2649 | |
2650 namespace { | |
2651 | |
2652 class FrameSerializationVisitorWithOutput : public SpdyFrameVisitor { | |
2653 public: | |
2654 explicit FrameSerializationVisitorWithOutput(SpdyFramer* framer, | |
2655 ZeroCopyOutputBuffer* output) | |
2656 : framer_(framer), output_(output), result_(false) {} | |
2657 ~FrameSerializationVisitorWithOutput() override {} | |
2658 | |
2659 bool Result() { return result_; } | |
2660 | |
2661 void VisitData(const SpdyDataIR& data) override { | |
2662 result_ = framer_->SerializeData(data, output_); | |
2663 } | |
2664 void VisitRstStream(const SpdyRstStreamIR& rst_stream) override { | |
2665 result_ = framer_->SerializeRstStream(rst_stream, output_); | |
2666 } | |
2667 void VisitSettings(const SpdySettingsIR& settings) override { | |
2668 result_ = framer_->SerializeSettings(settings, output_); | |
2669 } | |
2670 void VisitPing(const SpdyPingIR& ping) override { | |
2671 result_ = framer_->SerializePing(ping, output_); | |
2672 } | |
2673 void VisitGoAway(const SpdyGoAwayIR& goaway) override { | |
2674 result_ = framer_->SerializeGoAway(goaway, output_); | |
2675 } | |
2676 void VisitHeaders(const SpdyHeadersIR& headers) override { | |
2677 result_ = framer_->SerializeHeaders(headers, output_); | |
2678 } | |
2679 void VisitWindowUpdate(const SpdyWindowUpdateIR& window_update) override { | |
2680 result_ = framer_->SerializeWindowUpdate(window_update, output_); | |
2681 } | |
2682 void VisitBlocked(const SpdyBlockedIR& blocked) override { | |
2683 result_ = framer_->SerializeBlocked(blocked, output_); | |
2684 } | |
2685 void VisitPushPromise(const SpdyPushPromiseIR& push_promise) override { | |
2686 result_ = framer_->SerializePushPromise(push_promise, output_); | |
2687 } | |
2688 void VisitContinuation(const SpdyContinuationIR& continuation) override { | |
2689 result_ = framer_->SerializeContinuation(continuation, output_); | |
2690 } | |
2691 void VisitAltSvc(const SpdyAltSvcIR& altsvc) override { | |
2692 result_ = framer_->SerializeAltSvc(altsvc, output_); | |
2693 } | |
2694 void VisitPriority(const SpdyPriorityIR& priority) override { | |
2695 result_ = framer_->SerializePriority(priority, output_); | |
2696 } | |
2697 | |
2698 private: | |
2699 SpdyFramer* framer_; | |
2700 ZeroCopyOutputBuffer* output_; | |
2701 bool result_; | |
2702 }; | |
2703 | |
2704 } // namespace | |
2705 | |
2706 bool SpdyFramer::SerializeFrame(const SpdyFrameIR& frame, | |
2707 ZeroCopyOutputBuffer* output) { | |
2708 FrameSerializationVisitorWithOutput visitor(this, output); | |
2709 frame.Visit(&visitor); | |
2710 return visitor.Result(); | |
2711 } | |
2712 | |
2295 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { | 2713 size_t SpdyFramer::GetNumberRequiredContinuationFrames(size_t size) { |
2296 DCHECK_GT(size, kMaxControlFrameSize); | 2714 DCHECK_GT(size, kMaxControlFrameSize); |
2297 size_t overflow = size - kMaxControlFrameSize; | 2715 size_t overflow = size - kMaxControlFrameSize; |
2298 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize(); | 2716 size_t payload_size = kMaxControlFrameSize - GetContinuationMinimumSize(); |
2299 // This is ceiling(overflow/payload_size) using integer arithmetics. | 2717 // This is ceiling(overflow/payload_size) using integer arithmetics. |
2300 return (overflow - 1) / payload_size + 1; | 2718 return (overflow - 1) / payload_size + 1; |
2301 } | 2719 } |
2302 | 2720 |
2303 size_t SpdyFramer::GetHeaderFrameSizeSansBlock( | 2721 size_t SpdyFramer::GetHeaderFrameSizeSansBlock( |
2304 const SpdyHeadersIR& header_ir) const { | 2722 const SpdyHeadersIR& header_ir) const { |
(...skipping 22 matching lines...) Expand all Loading... | |
2327 } | 2745 } |
2328 if (header_ir.padded()) { | 2746 if (header_ir.padded()) { |
2329 flags |= HEADERS_FLAG_PADDED; | 2747 flags |= HEADERS_FLAG_PADDED; |
2330 } | 2748 } |
2331 if (header_ir.has_priority()) { | 2749 if (header_ir.has_priority()) { |
2332 flags |= HEADERS_FLAG_PRIORITY; | 2750 flags |= HEADERS_FLAG_PRIORITY; |
2333 } | 2751 } |
2334 return flags; | 2752 return flags; |
2335 } | 2753 } |
2336 | 2754 |
2337 void SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, | 2755 bool SpdyFramer::WritePayloadWithContinuation(SpdyFrameBuilder* builder, |
2338 const string& hpack_encoding, | 2756 const string& hpack_encoding, |
2339 SpdyStreamId stream_id, | 2757 SpdyStreamId stream_id, |
2340 SpdyFrameType type, | 2758 SpdyFrameType type, |
2341 int padding_payload_len) { | 2759 int padding_payload_len) { |
2342 uint8_t end_flag = 0; | 2760 uint8_t end_flag = 0; |
2343 uint8_t flags = 0; | 2761 uint8_t flags = 0; |
2344 if (type == HEADERS) { | 2762 if (type == HEADERS) { |
2345 end_flag = HEADERS_FLAG_END_HEADERS; | 2763 end_flag = HEADERS_FLAG_END_HEADERS; |
2346 } else if (type == PUSH_PROMISE) { | 2764 } else if (type == PUSH_PROMISE) { |
2347 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; | 2765 end_flag = PUSH_PROMISE_FLAG_END_PUSH_PROMISE; |
2348 } else { | 2766 } else { |
2349 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " | 2767 DLOG(FATAL) << "CONTINUATION frames cannot be used with frame type " |
2350 << FrameTypeToString(type); | 2768 << FrameTypeToString(type); |
2351 } | 2769 } |
2352 | 2770 |
2353 // Write all the padding payload and as much of the data payload as possible | 2771 // Write all the padding payload and as much of the data payload as possible |
2354 // into the initial frame. | 2772 // into the initial frame. |
2355 size_t bytes_remaining = 0; | 2773 size_t bytes_remaining = 0; |
2356 bytes_remaining = | 2774 bytes_remaining = |
2357 hpack_encoding.size() - | 2775 hpack_encoding.size() - |
2358 std::min(hpack_encoding.size(), | 2776 std::min(hpack_encoding.size(), |
2359 kMaxControlFrameSize - builder->length() - padding_payload_len); | 2777 kMaxControlFrameSize - builder->length() - padding_payload_len); |
2360 builder->WriteBytes(&hpack_encoding[0], | 2778 bool ret = builder->WriteBytes(&hpack_encoding[0], |
2361 hpack_encoding.size() - bytes_remaining); | 2779 hpack_encoding.size() - bytes_remaining); |
2362 if (padding_payload_len > 0) { | 2780 if (padding_payload_len > 0) { |
2363 string padding = string(padding_payload_len, 0); | 2781 string padding = string(padding_payload_len, 0); |
2364 builder->WriteBytes(padding.data(), padding.length()); | 2782 ret &= builder->WriteBytes(padding.data(), padding.length()); |
2365 } | 2783 } |
2366 if (bytes_remaining > 0 && !skip_rewritelength_) { | 2784 if (bytes_remaining > 0 && !skip_rewritelength_) { |
2367 builder->OverwriteLength(*this, | 2785 ret &= builder->OverwriteLength( |
2368 kMaxControlFrameSize - GetFrameHeaderSize()); | 2786 *this, kMaxControlFrameSize - GetFrameHeaderSize()); |
2369 } | 2787 } |
2370 | 2788 |
2371 // Tack on CONTINUATION frames for the overflow. | 2789 // Tack on CONTINUATION frames for the overflow. |
2372 while (bytes_remaining > 0) { | 2790 while (bytes_remaining > 0 && ret) { |
2373 size_t bytes_to_write = std::min( | 2791 size_t bytes_to_write = std::min( |
2374 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize()); | 2792 bytes_remaining, kMaxControlFrameSize - GetContinuationMinimumSize()); |
2375 // Write CONTINUATION frame prefix. | 2793 // Write CONTINUATION frame prefix. |
2376 if (bytes_remaining == bytes_to_write) { | 2794 if (bytes_remaining == bytes_to_write) { |
2377 flags |= end_flag; | 2795 flags |= end_flag; |
2378 } | 2796 } |
2379 if (!skip_rewritelength_) { | 2797 if (!skip_rewritelength_) { |
2380 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id); | 2798 ret &= builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id); |
2381 } else { | 2799 } else { |
2382 builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id, | 2800 ret &= builder->BeginNewFrame(*this, CONTINUATION, flags, stream_id, |
2383 bytes_to_write); | 2801 bytes_to_write); |
2384 } | 2802 } |
2385 // Write payload fragment. | 2803 // Write payload fragment. |
2386 builder->WriteBytes( | 2804 ret &= builder->WriteBytes( |
2387 &hpack_encoding[hpack_encoding.size() - bytes_remaining], | 2805 &hpack_encoding[hpack_encoding.size() - bytes_remaining], |
2388 bytes_to_write); | 2806 bytes_to_write); |
2389 bytes_remaining -= bytes_to_write; | 2807 bytes_remaining -= bytes_to_write; |
2390 } | 2808 } |
2809 return ret; | |
2391 } | 2810 } |
2392 | 2811 |
2393 HpackEncoder* SpdyFramer::GetHpackEncoder() { | 2812 HpackEncoder* SpdyFramer::GetHpackEncoder() { |
2394 if (hpack_encoder_.get() == nullptr) { | 2813 if (hpack_encoder_.get() == nullptr) { |
2395 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); | 2814 hpack_encoder_.reset(new HpackEncoder(ObtainHpackHuffmanTable())); |
2396 if (!compression_enabled()) { | 2815 if (!compression_enabled()) { |
2397 hpack_encoder_->DisableCompression(); | 2816 hpack_encoder_->DisableCompression(); |
2398 } | 2817 } |
2399 } | 2818 } |
2400 return hpack_encoder_.get(); | 2819 return hpack_encoder_.get(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2461 builder->WriteUInt32(header_block.size()); | 2880 builder->WriteUInt32(header_block.size()); |
2462 | 2881 |
2463 // Serialize each header. | 2882 // Serialize each header. |
2464 for (const auto& header : header_block) { | 2883 for (const auto& header : header_block) { |
2465 builder->WriteStringPiece32(base::ToLowerASCII(header.first)); | 2884 builder->WriteStringPiece32(base::ToLowerASCII(header.first)); |
2466 builder->WriteStringPiece32(header.second); | 2885 builder->WriteStringPiece32(header.second); |
2467 } | 2886 } |
2468 } | 2887 } |
2469 | 2888 |
2470 } // namespace net | 2889 } // namespace net |
OLD | NEW |