Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(840)

Side by Side Diff: net/spdy/spdy_framer.cc

Issue 2753043002: Create new versions of SerializeXXX() functions that uses pre-allocated buffer in SpdyFrameBuilder. (Closed)
Patch Set: git cl format Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/spdy/spdy_framer.h ('k') | net/spdy/spdy_framer_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698