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 |