@@ -33,12 +33,15 @@ const char Http2Frame::Preamble[25] = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
33
33
void Http2Frame::setHeader (absl::string_view header) {
34
34
ASSERT (header.size () >= HeaderSize);
35
35
data_.assign (HeaderSize, 0 );
36
+ // TODO(adisuissa): memcpy is discouraged as it may be unsafe. This should be
37
+ // use a safer memcpy alternative (example: https://abseil.io/tips/93)
36
38
memcpy (data_.data (), header.data (), HeaderSize);
37
39
data_.resize (HeaderSize + payloadSize ());
38
40
}
39
41
40
42
void Http2Frame::setPayload (absl::string_view payload) {
41
43
ASSERT (payload.size () >= payloadSize ());
44
+ ASSERT (data_.capacity () >= HeaderSize + payloadSize ());
42
45
memcpy (&data_[HeaderSize], payload.data (), payloadSize ());
43
46
}
44
47
@@ -116,6 +119,7 @@ Http2Frame Http2Frame::makePingFrame(absl::string_view data) {
116
119
static constexpr size_t kPingPayloadSize = 8 ;
117
120
Http2Frame frame;
118
121
frame.buildHeader (Type::Ping, kPingPayloadSize );
122
+ ASSERT (frame.data_ .capacity () >= HeaderSize + std::min (kPingPayloadSize , data.size ()));
119
123
if (!data.empty ()) {
120
124
memcpy (&frame.data_ [HeaderSize], data.data (), std::min (kPingPayloadSize , data.size ()));
121
125
}
@@ -152,8 +156,46 @@ Http2Frame Http2Frame::makePriorityFrame(uint32_t stream_index, uint32_t depende
152
156
static constexpr size_t kPriorityPayloadSize = 5 ;
153
157
Http2Frame frame;
154
158
frame.buildHeader (Type::Priority, kPriorityPayloadSize , 0 , makeRequestStreamId (stream_index));
155
- uint32_t dependent_net = makeRequestStreamId (dependent_index);
156
- memcpy (&frame.data_ [HeaderSize], reinterpret_cast <void *>(&dependent_net), sizeof (uint32_t ));
159
+ const uint32_t dependent_net = makeRequestStreamId (dependent_index);
160
+ ASSERT (frame.data_ .capacity () >= HeaderSize + sizeof (uint32_t ));
161
+ memcpy (&frame.data_ [HeaderSize], reinterpret_cast <const void *>(&dependent_net), sizeof (uint32_t ));
162
+ return frame;
163
+ }
164
+
165
+ Http2Frame Http2Frame::makeEmptyPushPromiseFrame (uint32_t stream_index,
166
+ uint32_t promised_stream_index,
167
+ HeadersFlags flags) {
168
+ static constexpr size_t kEmptyPushPromisePayloadSize = 4 ;
169
+ Http2Frame frame;
170
+ frame.buildHeader (Type::PushPromise, kEmptyPushPromisePayloadSize , static_cast <uint8_t >(flags),
171
+ makeRequestStreamId (stream_index));
172
+ const uint32_t promised_stream_id = makeRequestStreamId (promised_stream_index);
173
+ ASSERT (frame.data_ .capacity () >= HeaderSize + sizeof (uint32_t ));
174
+ memcpy (&frame.data_ [HeaderSize], reinterpret_cast <const void *>(&promised_stream_id),
175
+ sizeof (uint32_t ));
176
+ return frame;
177
+ }
178
+
179
+ Http2Frame Http2Frame::makeResetStreamFrame (uint32_t stream_index, ErrorCode error_code) {
180
+ static constexpr size_t kResetStreamPayloadSize = 4 ;
181
+ Http2Frame frame;
182
+ frame.buildHeader (Type::RstStream, kResetStreamPayloadSize , 0 , makeRequestStreamId (stream_index));
183
+ const uint32_t error = static_cast <uint32_t >(error_code);
184
+ ASSERT (frame.data_ .capacity () >= HeaderSize + sizeof (uint32_t ));
185
+ memcpy (&frame.data_ [HeaderSize], reinterpret_cast <const void *>(&error), sizeof (uint32_t ));
186
+ return frame;
187
+ }
188
+
189
+ Http2Frame Http2Frame::makeEmptyGoAwayFrame (uint32_t last_stream_index, ErrorCode error_code) {
190
+ static constexpr size_t kEmptyGoAwayPayloadSize = 8 ;
191
+ Http2Frame frame;
192
+ frame.buildHeader (Type::GoAway, kEmptyGoAwayPayloadSize , 0 , makeRequestStreamId (0 ));
193
+ const uint32_t last_stream_id = makeRequestStreamId (last_stream_index);
194
+ ASSERT (frame.data_ .capacity () >= HeaderSize + 4 + sizeof (uint32_t ));
195
+ memcpy (&frame.data_ [HeaderSize], reinterpret_cast <const void *>(&last_stream_id),
196
+ sizeof (uint32_t ));
197
+ const uint32_t error = static_cast <uint32_t >(error_code);
198
+ memcpy (&frame.data_ [HeaderSize + 4 ], reinterpret_cast <const void *>(&error), sizeof (uint32_t ));
157
199
return frame;
158
200
}
159
201
@@ -162,8 +204,9 @@ Http2Frame Http2Frame::makeWindowUpdateFrame(uint32_t stream_index, uint32_t inc
162
204
Http2Frame frame;
163
205
frame.buildHeader (Type::WindowUpdate, kWindowUpdatePayloadSize , 0 ,
164
206
makeRequestStreamId (stream_index));
165
- uint32_t increment_net = htonl (increment);
166
- memcpy (&frame.data_ [HeaderSize], reinterpret_cast <void *>(&increment_net), sizeof (uint32_t ));
207
+ const uint32_t increment_net = htonl (increment);
208
+ ASSERT (frame.data_ .capacity () >= HeaderSize + sizeof (uint32_t ));
209
+ memcpy (&frame.data_ [HeaderSize], reinterpret_cast <const void *>(&increment_net), sizeof (uint32_t ));
167
210
return frame;
168
211
}
169
212
@@ -218,6 +261,12 @@ Http2Frame Http2Frame::makePostRequest(uint32_t stream_index, absl::string_view
218
261
return frame;
219
262
}
220
263
264
+ Http2Frame Http2Frame::makeGenericFrame (absl::string_view contents) {
265
+ Http2Frame frame;
266
+ frame.appendData (contents);
267
+ return frame;
268
+ }
269
+
221
270
} // namespace Http2
222
271
} // namespace Http
223
272
} // namespace Envoy
0 commit comments