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