OLD | NEW |
(Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/http2/tools/http2_frame_builder.h" |
| 6 |
| 7 #ifdef WIN32 |
| 8 #include <winsock2.h> // for htonl() functions |
| 9 #else |
| 10 #include <arpa/inet.h> |
| 11 #include <netinet/in.h> // for htonl, htons |
| 12 #endif |
| 13 |
| 14 #include "testing/gtest/include/gtest/gtest.h" |
| 15 |
| 16 using base::StringPiece; |
| 17 |
| 18 namespace net { |
| 19 namespace test { |
| 20 |
| 21 Http2FrameBuilder::Http2FrameBuilder(Http2FrameType type, |
| 22 uint8_t flags, |
| 23 uint32_t stream_id) { |
| 24 AppendUInt24(0); // Frame payload length, unknown so far. |
| 25 Append(type); |
| 26 AppendUInt8(flags); |
| 27 AppendUInt31(stream_id); |
| 28 } |
| 29 |
| 30 Http2FrameBuilder::Http2FrameBuilder(const Http2FrameHeader& v) { |
| 31 Append(v); |
| 32 } |
| 33 |
| 34 void Http2FrameBuilder::Append(StringPiece s) { |
| 35 s.AppendToString(&buffer_); |
| 36 } |
| 37 |
| 38 void Http2FrameBuilder::AppendBytes(const void* data, uint32_t num_bytes) { |
| 39 Append(StringPiece(static_cast<const char*>(data), num_bytes)); |
| 40 } |
| 41 |
| 42 void Http2FrameBuilder::AppendZeroes(size_t num_zero_bytes) { |
| 43 char zero = 0; |
| 44 buffer_.append(num_zero_bytes, zero); |
| 45 } |
| 46 |
| 47 void Http2FrameBuilder::AppendUInt8(uint8_t value) { |
| 48 AppendBytes(&value, 1); |
| 49 } |
| 50 |
| 51 void Http2FrameBuilder::AppendUInt16(uint16_t value) { |
| 52 value = htons(value); |
| 53 AppendBytes(&value, 2); |
| 54 } |
| 55 |
| 56 void Http2FrameBuilder::AppendUInt24(uint32_t value) { |
| 57 // Doesn't make sense to try to append a larger value, as that doesn't |
| 58 // simulate something an encoder could do (i.e. the other 8 bits simply aren't |
| 59 // there to be occupied). |
| 60 EXPECT_EQ(value, value & 0xffffff); |
| 61 value = htonl(value); |
| 62 AppendBytes(reinterpret_cast<char*>(&value) + 1, 3); |
| 63 } |
| 64 |
| 65 void Http2FrameBuilder::AppendUInt31(uint32_t value) { |
| 66 // If you want to test the high-bit being set, call AppendUInt32 instead. |
| 67 uint32_t tmp = value & StreamIdMask(); |
| 68 EXPECT_EQ(value, value & StreamIdMask()) |
| 69 << "High-bit of uint32 should be clear."; |
| 70 value = htonl(tmp); |
| 71 AppendBytes(&value, 4); |
| 72 } |
| 73 |
| 74 void Http2FrameBuilder::AppendUInt32(uint32_t value) { |
| 75 value = htonl(value); |
| 76 AppendBytes(&value, sizeof(value)); |
| 77 } |
| 78 |
| 79 void Http2FrameBuilder::Append(Http2ErrorCode error_code) { |
| 80 AppendUInt32(static_cast<uint32_t>(error_code)); |
| 81 } |
| 82 |
| 83 void Http2FrameBuilder::Append(Http2FrameType type) { |
| 84 AppendUInt8(static_cast<uint8_t>(type)); |
| 85 } |
| 86 |
| 87 void Http2FrameBuilder::Append(Http2SettingsParameter parameter) { |
| 88 AppendUInt16(static_cast<uint16_t>(parameter)); |
| 89 } |
| 90 |
| 91 void Http2FrameBuilder::Append(const Http2FrameHeader& v) { |
| 92 AppendUInt24(v.payload_length); |
| 93 Append(v.type); |
| 94 AppendUInt8(v.flags); |
| 95 AppendUInt31(v.stream_id); |
| 96 } |
| 97 |
| 98 void Http2FrameBuilder::Append(const Http2PriorityFields& v) { |
| 99 // The EXCLUSIVE flag is the high-bit of the 32-bit stream dependency field. |
| 100 uint32_t tmp = v.stream_dependency & StreamIdMask(); |
| 101 EXPECT_EQ(tmp, v.stream_dependency); |
| 102 if (v.is_exclusive) { |
| 103 tmp |= 0x80000000; |
| 104 } |
| 105 AppendUInt32(tmp); |
| 106 |
| 107 // The PRIORITY frame's weight field is logically in the range [1, 256], |
| 108 // but is encoded as a byte in the range [0, 255]. |
| 109 ASSERT_LE(1u, v.weight); |
| 110 ASSERT_LE(v.weight, 256u); |
| 111 AppendUInt8(v.weight - 1); |
| 112 } |
| 113 |
| 114 void Http2FrameBuilder::Append(const Http2RstStreamFields& v) { |
| 115 Append(v.error_code); |
| 116 } |
| 117 |
| 118 void Http2FrameBuilder::Append(const Http2SettingFields& v) { |
| 119 Append(v.parameter); |
| 120 AppendUInt32(v.value); |
| 121 } |
| 122 |
| 123 void Http2FrameBuilder::Append(const Http2PushPromiseFields& v) { |
| 124 AppendUInt31(v.promised_stream_id); |
| 125 } |
| 126 |
| 127 void Http2FrameBuilder::Append(const Http2PingFields& v) { |
| 128 AppendBytes(v.opaque_data, sizeof Http2PingFields::opaque_data); |
| 129 } |
| 130 |
| 131 void Http2FrameBuilder::Append(const Http2GoAwayFields& v) { |
| 132 AppendUInt31(v.last_stream_id); |
| 133 Append(v.error_code); |
| 134 } |
| 135 |
| 136 void Http2FrameBuilder::Append(const Http2WindowUpdateFields& v) { |
| 137 EXPECT_NE(0u, v.window_size_increment) << "Increment must be non-zero."; |
| 138 AppendUInt31(v.window_size_increment); |
| 139 } |
| 140 |
| 141 void Http2FrameBuilder::Append(const Http2AltSvcFields& v) { |
| 142 AppendUInt16(v.origin_length); |
| 143 } |
| 144 |
| 145 // Methods for changing existing buffer contents. |
| 146 |
| 147 void Http2FrameBuilder::WriteAt(StringPiece s, size_t offset) { |
| 148 ASSERT_LE(offset, buffer_.size()); |
| 149 size_t len = offset + s.size(); |
| 150 if (len > buffer_.size()) { |
| 151 buffer_.resize(len); |
| 152 } |
| 153 for (size_t ndx = 0; ndx < s.size(); ++ndx) { |
| 154 buffer_[offset + ndx] = s[ndx]; |
| 155 } |
| 156 } |
| 157 |
| 158 void Http2FrameBuilder::WriteBytesAt(const void* data, |
| 159 uint32_t num_bytes, |
| 160 size_t offset) { |
| 161 WriteAt(StringPiece(static_cast<const char*>(data), num_bytes), offset); |
| 162 } |
| 163 |
| 164 void Http2FrameBuilder::WriteUInt24At(uint32_t value, size_t offset) { |
| 165 ASSERT_LT(value, static_cast<uint32_t>(1 << 24)); |
| 166 value = htonl(value); |
| 167 WriteBytesAt(reinterpret_cast<char*>(&value) + 1, sizeof(value) - 1, offset); |
| 168 } |
| 169 |
| 170 void Http2FrameBuilder::SetPayloadLength(uint32_t payload_length) { |
| 171 WriteUInt24At(payload_length, 0); |
| 172 } |
| 173 |
| 174 size_t Http2FrameBuilder::SetPayloadLength() { |
| 175 EXPECT_GE(size(), Http2FrameHeader::EncodedSize()); |
| 176 uint32_t payload_length = size() - Http2FrameHeader::EncodedSize(); |
| 177 SetPayloadLength(payload_length); |
| 178 return payload_length; |
| 179 } |
| 180 |
| 181 } // namespace test |
| 182 } // namespace net |
OLD | NEW |