1 // Copyright (c) 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 "quiche/quic/core/frames/quic_frame.h"
6
7 #include "quiche/quic/core/frames/quic_new_connection_id_frame.h"
8 #include "quiche/quic/core/frames/quic_reset_stream_at_frame.h"
9 #include "quiche/quic/core/frames/quic_retire_connection_id_frame.h"
10 #include "quiche/quic/core/frames/quic_rst_stream_frame.h"
11 #include "quiche/quic/core/quic_constants.h"
12 #include "quiche/quic/core/quic_types.h"
13 #include "quiche/quic/platform/api/quic_bug_tracker.h"
14 #include "quiche/quic/platform/api/quic_logging.h"
15 #include "quiche/common/platform/api/quiche_mem_slice.h"
16 #include "quiche/common/quiche_buffer_allocator.h"
17
18 namespace quic {
19
QuicFrame()20 QuicFrame::QuicFrame() {}
21
QuicFrame(QuicPaddingFrame padding_frame)22 QuicFrame::QuicFrame(QuicPaddingFrame padding_frame)
23 : padding_frame(padding_frame) {}
24
QuicFrame(QuicStreamFrame stream_frame)25 QuicFrame::QuicFrame(QuicStreamFrame stream_frame)
26 : stream_frame(stream_frame) {}
27
QuicFrame(QuicHandshakeDoneFrame handshake_done_frame)28 QuicFrame::QuicFrame(QuicHandshakeDoneFrame handshake_done_frame)
29 : handshake_done_frame(handshake_done_frame) {}
30
QuicFrame(QuicCryptoFrame * crypto_frame)31 QuicFrame::QuicFrame(QuicCryptoFrame* crypto_frame)
32 : type(CRYPTO_FRAME), crypto_frame(crypto_frame) {}
33
QuicFrame(QuicAckFrame * frame)34 QuicFrame::QuicFrame(QuicAckFrame* frame) : type(ACK_FRAME), ack_frame(frame) {}
35
QuicFrame(QuicMtuDiscoveryFrame frame)36 QuicFrame::QuicFrame(QuicMtuDiscoveryFrame frame)
37 : mtu_discovery_frame(frame) {}
38
QuicFrame(QuicStopWaitingFrame frame)39 QuicFrame::QuicFrame(QuicStopWaitingFrame frame) : stop_waiting_frame(frame) {}
40
QuicFrame(QuicPingFrame frame)41 QuicFrame::QuicFrame(QuicPingFrame frame) : ping_frame(frame) {}
42
QuicFrame(QuicRstStreamFrame * frame)43 QuicFrame::QuicFrame(QuicRstStreamFrame* frame)
44 : type(RST_STREAM_FRAME), rst_stream_frame(frame) {}
45
QuicFrame(QuicConnectionCloseFrame * frame)46 QuicFrame::QuicFrame(QuicConnectionCloseFrame* frame)
47 : type(CONNECTION_CLOSE_FRAME), connection_close_frame(frame) {}
48
QuicFrame(QuicGoAwayFrame * frame)49 QuicFrame::QuicFrame(QuicGoAwayFrame* frame)
50 : type(GOAWAY_FRAME), goaway_frame(frame) {}
51
QuicFrame(QuicWindowUpdateFrame frame)52 QuicFrame::QuicFrame(QuicWindowUpdateFrame frame)
53 : window_update_frame(frame) {}
54
QuicFrame(QuicBlockedFrame frame)55 QuicFrame::QuicFrame(QuicBlockedFrame frame) : blocked_frame(frame) {}
56
QuicFrame(QuicNewConnectionIdFrame * frame)57 QuicFrame::QuicFrame(QuicNewConnectionIdFrame* frame)
58 : type(NEW_CONNECTION_ID_FRAME), new_connection_id_frame(frame) {}
59
QuicFrame(QuicRetireConnectionIdFrame * frame)60 QuicFrame::QuicFrame(QuicRetireConnectionIdFrame* frame)
61 : type(RETIRE_CONNECTION_ID_FRAME), retire_connection_id_frame(frame) {}
62
QuicFrame(QuicMaxStreamsFrame frame)63 QuicFrame::QuicFrame(QuicMaxStreamsFrame frame) : max_streams_frame(frame) {}
64
QuicFrame(QuicStreamsBlockedFrame frame)65 QuicFrame::QuicFrame(QuicStreamsBlockedFrame frame)
66 : streams_blocked_frame(frame) {}
67
QuicFrame(QuicPathResponseFrame frame)68 QuicFrame::QuicFrame(QuicPathResponseFrame frame)
69 : path_response_frame(frame) {}
70
QuicFrame(QuicPathChallengeFrame frame)71 QuicFrame::QuicFrame(QuicPathChallengeFrame frame)
72 : path_challenge_frame(frame) {}
73
QuicFrame(QuicStopSendingFrame frame)74 QuicFrame::QuicFrame(QuicStopSendingFrame frame) : stop_sending_frame(frame) {}
75
QuicFrame(QuicMessageFrame * frame)76 QuicFrame::QuicFrame(QuicMessageFrame* frame)
77 : type(MESSAGE_FRAME), message_frame(frame) {}
78
QuicFrame(QuicNewTokenFrame * frame)79 QuicFrame::QuicFrame(QuicNewTokenFrame* frame)
80 : type(NEW_TOKEN_FRAME), new_token_frame(frame) {}
81
QuicFrame(QuicAckFrequencyFrame * frame)82 QuicFrame::QuicFrame(QuicAckFrequencyFrame* frame)
83 : type(ACK_FREQUENCY_FRAME), ack_frequency_frame(frame) {}
84
QuicFrame(QuicResetStreamAtFrame * frame)85 QuicFrame::QuicFrame(QuicResetStreamAtFrame* frame)
86 : type(RESET_STREAM_AT_FRAME), reset_stream_at_frame(frame) {}
87
DeleteFrames(QuicFrames * frames)88 void DeleteFrames(QuicFrames* frames) {
89 for (QuicFrame& frame : *frames) {
90 DeleteFrame(&frame);
91 }
92 frames->clear();
93 }
94
DeleteFrame(QuicFrame * frame)95 void DeleteFrame(QuicFrame* frame) {
96 #if QUIC_FRAME_DEBUG
97 // If the frame is not inlined, check that it can be safely deleted.
98 if (frame->type != PADDING_FRAME && frame->type != MTU_DISCOVERY_FRAME &&
99 frame->type != PING_FRAME && frame->type != MAX_STREAMS_FRAME &&
100 frame->type != STOP_WAITING_FRAME &&
101 frame->type != STREAMS_BLOCKED_FRAME && frame->type != STREAM_FRAME &&
102 frame->type != HANDSHAKE_DONE_FRAME &&
103 frame->type != WINDOW_UPDATE_FRAME && frame->type != BLOCKED_FRAME &&
104 frame->type != STOP_SENDING_FRAME &&
105 frame->type != PATH_CHALLENGE_FRAME &&
106 frame->type != PATH_RESPONSE_FRAME) {
107 QUICHE_CHECK(!frame->delete_forbidden) << *frame;
108 }
109 #endif // QUIC_FRAME_DEBUG
110 switch (frame->type) {
111 // Frames smaller than a pointer are inlined, so don't need to be deleted.
112 case PADDING_FRAME:
113 case MTU_DISCOVERY_FRAME:
114 case PING_FRAME:
115 case MAX_STREAMS_FRAME:
116 case STOP_WAITING_FRAME:
117 case STREAMS_BLOCKED_FRAME:
118 case STREAM_FRAME:
119 case HANDSHAKE_DONE_FRAME:
120 case WINDOW_UPDATE_FRAME:
121 case BLOCKED_FRAME:
122 case STOP_SENDING_FRAME:
123 case PATH_CHALLENGE_FRAME:
124 case PATH_RESPONSE_FRAME:
125 break;
126 case ACK_FRAME:
127 delete frame->ack_frame;
128 break;
129 case RST_STREAM_FRAME:
130 delete frame->rst_stream_frame;
131 break;
132 case CONNECTION_CLOSE_FRAME:
133 delete frame->connection_close_frame;
134 break;
135 case GOAWAY_FRAME:
136 delete frame->goaway_frame;
137 break;
138 case NEW_CONNECTION_ID_FRAME:
139 delete frame->new_connection_id_frame;
140 break;
141 case RETIRE_CONNECTION_ID_FRAME:
142 delete frame->retire_connection_id_frame;
143 break;
144 case MESSAGE_FRAME:
145 delete frame->message_frame;
146 break;
147 case CRYPTO_FRAME:
148 delete frame->crypto_frame;
149 break;
150 case NEW_TOKEN_FRAME:
151 delete frame->new_token_frame;
152 break;
153 case ACK_FREQUENCY_FRAME:
154 delete frame->ack_frequency_frame;
155 break;
156 case RESET_STREAM_AT_FRAME:
157 delete frame->reset_stream_at_frame;
158 break;
159 case NUM_FRAME_TYPES:
160 QUICHE_DCHECK(false) << "Cannot delete type: " << frame->type;
161 }
162 }
163
RemoveFramesForStream(QuicFrames * frames,QuicStreamId stream_id)164 void RemoveFramesForStream(QuicFrames* frames, QuicStreamId stream_id) {
165 auto it = frames->begin();
166 while (it != frames->end()) {
167 if (it->type != STREAM_FRAME || it->stream_frame.stream_id != stream_id) {
168 ++it;
169 continue;
170 }
171 it = frames->erase(it);
172 }
173 }
174
IsControlFrame(QuicFrameType type)175 bool IsControlFrame(QuicFrameType type) {
176 switch (type) {
177 case RST_STREAM_FRAME:
178 case GOAWAY_FRAME:
179 case WINDOW_UPDATE_FRAME:
180 case BLOCKED_FRAME:
181 case STREAMS_BLOCKED_FRAME:
182 case MAX_STREAMS_FRAME:
183 case PING_FRAME:
184 case STOP_SENDING_FRAME:
185 case NEW_CONNECTION_ID_FRAME:
186 case RETIRE_CONNECTION_ID_FRAME:
187 case HANDSHAKE_DONE_FRAME:
188 case ACK_FREQUENCY_FRAME:
189 case NEW_TOKEN_FRAME:
190 case RESET_STREAM_AT_FRAME:
191 return true;
192 default:
193 return false;
194 }
195 }
196
GetControlFrameId(const QuicFrame & frame)197 QuicControlFrameId GetControlFrameId(const QuicFrame& frame) {
198 switch (frame.type) {
199 case RST_STREAM_FRAME:
200 return frame.rst_stream_frame->control_frame_id;
201 case GOAWAY_FRAME:
202 return frame.goaway_frame->control_frame_id;
203 case WINDOW_UPDATE_FRAME:
204 return frame.window_update_frame.control_frame_id;
205 case BLOCKED_FRAME:
206 return frame.blocked_frame.control_frame_id;
207 case STREAMS_BLOCKED_FRAME:
208 return frame.streams_blocked_frame.control_frame_id;
209 case MAX_STREAMS_FRAME:
210 return frame.max_streams_frame.control_frame_id;
211 case PING_FRAME:
212 return frame.ping_frame.control_frame_id;
213 case STOP_SENDING_FRAME:
214 return frame.stop_sending_frame.control_frame_id;
215 case NEW_CONNECTION_ID_FRAME:
216 return frame.new_connection_id_frame->control_frame_id;
217 case RETIRE_CONNECTION_ID_FRAME:
218 return frame.retire_connection_id_frame->control_frame_id;
219 case HANDSHAKE_DONE_FRAME:
220 return frame.handshake_done_frame.control_frame_id;
221 case ACK_FREQUENCY_FRAME:
222 return frame.ack_frequency_frame->control_frame_id;
223 case NEW_TOKEN_FRAME:
224 return frame.new_token_frame->control_frame_id;
225 case RESET_STREAM_AT_FRAME:
226 return frame.reset_stream_at_frame->control_frame_id;
227 default:
228 return kInvalidControlFrameId;
229 }
230 }
231
SetControlFrameId(QuicControlFrameId control_frame_id,QuicFrame * frame)232 void SetControlFrameId(QuicControlFrameId control_frame_id, QuicFrame* frame) {
233 switch (frame->type) {
234 case RST_STREAM_FRAME:
235 frame->rst_stream_frame->control_frame_id = control_frame_id;
236 return;
237 case GOAWAY_FRAME:
238 frame->goaway_frame->control_frame_id = control_frame_id;
239 return;
240 case WINDOW_UPDATE_FRAME:
241 frame->window_update_frame.control_frame_id = control_frame_id;
242 return;
243 case BLOCKED_FRAME:
244 frame->blocked_frame.control_frame_id = control_frame_id;
245 return;
246 case PING_FRAME:
247 frame->ping_frame.control_frame_id = control_frame_id;
248 return;
249 case STREAMS_BLOCKED_FRAME:
250 frame->streams_blocked_frame.control_frame_id = control_frame_id;
251 return;
252 case MAX_STREAMS_FRAME:
253 frame->max_streams_frame.control_frame_id = control_frame_id;
254 return;
255 case STOP_SENDING_FRAME:
256 frame->stop_sending_frame.control_frame_id = control_frame_id;
257 return;
258 case NEW_CONNECTION_ID_FRAME:
259 frame->new_connection_id_frame->control_frame_id = control_frame_id;
260 return;
261 case RETIRE_CONNECTION_ID_FRAME:
262 frame->retire_connection_id_frame->control_frame_id = control_frame_id;
263 return;
264 case HANDSHAKE_DONE_FRAME:
265 frame->handshake_done_frame.control_frame_id = control_frame_id;
266 return;
267 case ACK_FREQUENCY_FRAME:
268 frame->ack_frequency_frame->control_frame_id = control_frame_id;
269 return;
270 case NEW_TOKEN_FRAME:
271 frame->new_token_frame->control_frame_id = control_frame_id;
272 return;
273 case RESET_STREAM_AT_FRAME:
274 frame->reset_stream_at_frame->control_frame_id = control_frame_id;
275 return;
276 default:
277 QUIC_BUG(quic_bug_12594_1)
278 << "Try to set control frame id of a frame without control frame id";
279 }
280 }
281
CopyRetransmittableControlFrame(const QuicFrame & frame)282 QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame) {
283 QuicFrame copy;
284 switch (frame.type) {
285 case RST_STREAM_FRAME:
286 copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame));
287 break;
288 case GOAWAY_FRAME:
289 copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame));
290 break;
291 case WINDOW_UPDATE_FRAME:
292 copy = QuicFrame(QuicWindowUpdateFrame(frame.window_update_frame));
293 break;
294 case BLOCKED_FRAME:
295 copy = QuicFrame(QuicBlockedFrame(frame.blocked_frame));
296 break;
297 case PING_FRAME:
298 copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
299 break;
300 case STOP_SENDING_FRAME:
301 copy = QuicFrame(QuicStopSendingFrame(frame.stop_sending_frame));
302 break;
303 case NEW_CONNECTION_ID_FRAME:
304 copy = QuicFrame(
305 new QuicNewConnectionIdFrame(*frame.new_connection_id_frame));
306 break;
307 case RETIRE_CONNECTION_ID_FRAME:
308 copy = QuicFrame(
309 new QuicRetireConnectionIdFrame(*frame.retire_connection_id_frame));
310 break;
311 case STREAMS_BLOCKED_FRAME:
312 copy = QuicFrame(QuicStreamsBlockedFrame(frame.streams_blocked_frame));
313 break;
314 case MAX_STREAMS_FRAME:
315 copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame));
316 break;
317 case HANDSHAKE_DONE_FRAME:
318 copy = QuicFrame(
319 QuicHandshakeDoneFrame(frame.handshake_done_frame.control_frame_id));
320 break;
321 case ACK_FREQUENCY_FRAME:
322 copy = QuicFrame(new QuicAckFrequencyFrame(*frame.ack_frequency_frame));
323 break;
324 case NEW_TOKEN_FRAME:
325 copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame));
326 break;
327 case RESET_STREAM_AT_FRAME:
328 copy =
329 QuicFrame(new QuicResetStreamAtFrame(*frame.reset_stream_at_frame));
330 break;
331 default:
332 QUIC_BUG(quic_bug_10533_1)
333 << "Try to copy a non-retransmittable control frame: " << frame;
334 copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
335 break;
336 }
337 return copy;
338 }
339
CopyQuicFrame(quiche::QuicheBufferAllocator * allocator,const QuicFrame & frame)340 QuicFrame CopyQuicFrame(quiche::QuicheBufferAllocator* allocator,
341 const QuicFrame& frame) {
342 QuicFrame copy;
343 switch (frame.type) {
344 case PADDING_FRAME:
345 copy = QuicFrame(QuicPaddingFrame(frame.padding_frame));
346 break;
347 case RST_STREAM_FRAME:
348 copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame));
349 break;
350 case CONNECTION_CLOSE_FRAME:
351 copy = QuicFrame(
352 new QuicConnectionCloseFrame(*frame.connection_close_frame));
353 break;
354 case GOAWAY_FRAME:
355 copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame));
356 break;
357 case WINDOW_UPDATE_FRAME:
358 copy = QuicFrame(QuicWindowUpdateFrame(frame.window_update_frame));
359 break;
360 case BLOCKED_FRAME:
361 copy = QuicFrame(QuicBlockedFrame(frame.blocked_frame));
362 break;
363 case STOP_WAITING_FRAME:
364 copy = QuicFrame(QuicStopWaitingFrame(frame.stop_waiting_frame));
365 break;
366 case PING_FRAME:
367 copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id));
368 break;
369 case CRYPTO_FRAME:
370 copy = QuicFrame(new QuicCryptoFrame(*frame.crypto_frame));
371 break;
372 case STREAM_FRAME:
373 copy = QuicFrame(QuicStreamFrame(frame.stream_frame));
374 break;
375 case ACK_FRAME:
376 copy = QuicFrame(new QuicAckFrame(*frame.ack_frame));
377 break;
378 case MTU_DISCOVERY_FRAME:
379 copy = QuicFrame(QuicMtuDiscoveryFrame(frame.mtu_discovery_frame));
380 break;
381 case NEW_CONNECTION_ID_FRAME:
382 copy = QuicFrame(
383 new QuicNewConnectionIdFrame(*frame.new_connection_id_frame));
384 break;
385 case MAX_STREAMS_FRAME:
386 copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame));
387 break;
388 case STREAMS_BLOCKED_FRAME:
389 copy = QuicFrame(QuicStreamsBlockedFrame(frame.streams_blocked_frame));
390 break;
391 case PATH_RESPONSE_FRAME:
392 copy = QuicFrame(QuicPathResponseFrame(frame.path_response_frame));
393 break;
394 case PATH_CHALLENGE_FRAME:
395 copy = QuicFrame(QuicPathChallengeFrame(frame.path_challenge_frame));
396 break;
397 case STOP_SENDING_FRAME:
398 copy = QuicFrame(QuicStopSendingFrame(frame.stop_sending_frame));
399 break;
400 case MESSAGE_FRAME:
401 copy = QuicFrame(new QuicMessageFrame(frame.message_frame->message_id));
402 copy.message_frame->data = frame.message_frame->data;
403 copy.message_frame->message_length = frame.message_frame->message_length;
404 for (const auto& slice : frame.message_frame->message_data) {
405 quiche::QuicheBuffer buffer =
406 quiche::QuicheBuffer::Copy(allocator, slice.AsStringView());
407 copy.message_frame->message_data.push_back(
408 quiche::QuicheMemSlice(std::move(buffer)));
409 }
410 break;
411 case NEW_TOKEN_FRAME:
412 copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame));
413 break;
414 case RETIRE_CONNECTION_ID_FRAME:
415 copy = QuicFrame(
416 new QuicRetireConnectionIdFrame(*frame.retire_connection_id_frame));
417 break;
418 case HANDSHAKE_DONE_FRAME:
419 copy = QuicFrame(
420 QuicHandshakeDoneFrame(frame.handshake_done_frame.control_frame_id));
421 break;
422 case ACK_FREQUENCY_FRAME:
423 copy = QuicFrame(new QuicAckFrequencyFrame(*frame.ack_frequency_frame));
424 break;
425 case RESET_STREAM_AT_FRAME:
426 copy =
427 QuicFrame(new QuicResetStreamAtFrame(*frame.reset_stream_at_frame));
428 break;
429 default:
430 QUIC_BUG(quic_bug_10533_2) << "Cannot copy frame: " << frame;
431 copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId));
432 break;
433 }
434 return copy;
435 }
436
CopyQuicFrames(quiche::QuicheBufferAllocator * allocator,const QuicFrames & frames)437 QuicFrames CopyQuicFrames(quiche::QuicheBufferAllocator* allocator,
438 const QuicFrames& frames) {
439 QuicFrames copy;
440 for (const auto& frame : frames) {
441 copy.push_back(CopyQuicFrame(allocator, frame));
442 }
443 return copy;
444 }
445
operator <<(std::ostream & os,const QuicFrame & frame)446 std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) {
447 switch (frame.type) {
448 case PADDING_FRAME: {
449 os << "type { PADDING_FRAME } " << frame.padding_frame;
450 break;
451 }
452 case RST_STREAM_FRAME: {
453 os << "type { RST_STREAM_FRAME } " << *(frame.rst_stream_frame);
454 break;
455 }
456 case CONNECTION_CLOSE_FRAME: {
457 os << "type { CONNECTION_CLOSE_FRAME } "
458 << *(frame.connection_close_frame);
459 break;
460 }
461 case GOAWAY_FRAME: {
462 os << "type { GOAWAY_FRAME } " << *(frame.goaway_frame);
463 break;
464 }
465 case WINDOW_UPDATE_FRAME: {
466 os << "type { WINDOW_UPDATE_FRAME } " << frame.window_update_frame;
467 break;
468 }
469 case BLOCKED_FRAME: {
470 os << "type { BLOCKED_FRAME } " << frame.blocked_frame;
471 break;
472 }
473 case STREAM_FRAME: {
474 os << "type { STREAM_FRAME } " << frame.stream_frame;
475 break;
476 }
477 case ACK_FRAME: {
478 os << "type { ACK_FRAME } " << *(frame.ack_frame);
479 break;
480 }
481 case STOP_WAITING_FRAME: {
482 os << "type { STOP_WAITING_FRAME } " << frame.stop_waiting_frame;
483 break;
484 }
485 case PING_FRAME: {
486 os << "type { PING_FRAME } " << frame.ping_frame;
487 break;
488 }
489 case CRYPTO_FRAME: {
490 os << "type { CRYPTO_FRAME } " << *(frame.crypto_frame);
491 break;
492 }
493 case MTU_DISCOVERY_FRAME: {
494 os << "type { MTU_DISCOVERY_FRAME } ";
495 break;
496 }
497 case NEW_CONNECTION_ID_FRAME:
498 os << "type { NEW_CONNECTION_ID } " << *(frame.new_connection_id_frame);
499 break;
500 case RETIRE_CONNECTION_ID_FRAME:
501 os << "type { RETIRE_CONNECTION_ID } "
502 << *(frame.retire_connection_id_frame);
503 break;
504 case MAX_STREAMS_FRAME:
505 os << "type { MAX_STREAMS } " << frame.max_streams_frame;
506 break;
507 case STREAMS_BLOCKED_FRAME:
508 os << "type { STREAMS_BLOCKED } " << frame.streams_blocked_frame;
509 break;
510 case PATH_RESPONSE_FRAME:
511 os << "type { PATH_RESPONSE } " << frame.path_response_frame;
512 break;
513 case PATH_CHALLENGE_FRAME:
514 os << "type { PATH_CHALLENGE } " << frame.path_challenge_frame;
515 break;
516 case STOP_SENDING_FRAME:
517 os << "type { STOP_SENDING } " << frame.stop_sending_frame;
518 break;
519 case MESSAGE_FRAME:
520 os << "type { MESSAGE_FRAME }" << *(frame.message_frame);
521 break;
522 case NEW_TOKEN_FRAME:
523 os << "type { NEW_TOKEN_FRAME }" << *(frame.new_token_frame);
524 break;
525 case HANDSHAKE_DONE_FRAME:
526 os << "type { HANDSHAKE_DONE_FRAME } " << frame.handshake_done_frame;
527 break;
528 case ACK_FREQUENCY_FRAME:
529 os << "type { ACK_FREQUENCY_FRAME } " << *(frame.ack_frequency_frame);
530 break;
531 case RESET_STREAM_AT_FRAME:
532 os << "type { RESET_STREAM_AT_FRAME } " << *(frame.reset_stream_at_frame);
533 break;
534 default: {
535 QUIC_LOG(ERROR) << "Unknown frame type: " << frame.type;
536 break;
537 }
538 }
539 return os;
540 }
541
QuicFrameToString(const QuicFrame & frame)542 QUICHE_EXPORT std::string QuicFrameToString(const QuicFrame& frame) {
543 std::ostringstream os;
544 os << frame;
545 return os.str();
546 }
547
QuicFramesToString(const QuicFrames & frames)548 std::string QuicFramesToString(const QuicFrames& frames) {
549 std::ostringstream os;
550 for (const QuicFrame& frame : frames) {
551 os << frame;
552 }
553 return os.str();
554 }
555
556 } // namespace quic
557