blob: 7d4769fffbc838c0c953ff416d70d4ce1aba7918 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// 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
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_packets.h"
6
7#include "net/third_party/quiche/src/quic/core/quic_connection_id.h"
8#include "net/third_party/quiche/src/quic/core/quic_types.h"
9#include "net/third_party/quiche/src/quic/core/quic_utils.h"
10#include "net/third_party/quiche/src/quic/core/quic_versions.h"
rchf0a9f372019-05-15 21:36:43 -070011#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050012#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
13#include "net/third_party/quiche/src/quic/platform/api/quic_ptr_util.h"
14#include "net/third_party/quiche/src/quic/platform/api/quic_str_cat.h"
15#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
fayang1ed1f762019-06-24 11:40:04 -070016#include "net/third_party/quiche/src/quic/platform/api/quic_string_utils.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050017#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
18
19namespace quic {
20
QUICHE team2252b702019-05-14 23:55:14 -040021QuicConnectionId GetServerConnectionIdAsRecipient(
22 const QuicPacketHeader& header,
23 Perspective perspective) {
24 if (perspective == Perspective::IS_SERVER ||
25 !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
26 return header.destination_connection_id;
27 }
28 return header.source_connection_id;
29}
30
dschinaziac6805d2019-05-30 09:44:27 -070031QuicConnectionId GetClientConnectionIdAsRecipient(
32 const QuicPacketHeader& header,
33 Perspective perspective) {
34 DCHECK(GetQuicRestartFlag(quic_do_not_override_connection_id));
35 if (perspective == Perspective::IS_CLIENT) {
36 return header.destination_connection_id;
37 }
38 return header.source_connection_id;
39}
40
QUICHE team2252b702019-05-14 23:55:14 -040041QuicConnectionId GetServerConnectionIdAsSender(const QuicPacketHeader& header,
42 Perspective perspective) {
43 if (perspective == Perspective::IS_CLIENT ||
44 !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
45 return header.destination_connection_id;
46 }
dschinazib9bdd052019-06-05 03:06:33 -070047 QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 3, 7);
QUICHE team2252b702019-05-14 23:55:14 -040048 return header.source_connection_id;
49}
50
51QuicConnectionIdIncluded GetServerConnectionIdIncludedAsSender(
52 const QuicPacketHeader& header,
53 Perspective perspective) {
54 if (perspective == Perspective::IS_CLIENT ||
55 !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
56 return header.destination_connection_id_included;
57 }
dschinazib9bdd052019-06-05 03:06:33 -070058 QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 4, 7);
QUICHE team2252b702019-05-14 23:55:14 -040059 return header.source_connection_id_included;
60}
61
dschinaziac6805d2019-05-30 09:44:27 -070062QuicConnectionId GetClientConnectionIdAsSender(const QuicPacketHeader& header,
63 Perspective perspective) {
64 if (perspective == Perspective::IS_CLIENT ||
65 !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
66 return header.source_connection_id;
67 }
dschinazib9bdd052019-06-05 03:06:33 -070068 QUIC_RESTART_FLAG_COUNT_N(quic_do_not_override_connection_id, 7, 7);
dschinaziac6805d2019-05-30 09:44:27 -070069 return header.destination_connection_id;
70}
71
QUICHE team2252b702019-05-14 23:55:14 -040072QuicConnectionIdIncluded GetClientConnectionIdIncludedAsSender(
73 const QuicPacketHeader& header,
74 Perspective perspective) {
75 if (perspective == Perspective::IS_CLIENT ||
76 !GetQuicRestartFlag(quic_do_not_override_connection_id)) {
77 return header.source_connection_id_included;
78 }
79 return header.destination_connection_id_included;
80}
81
QUICHE teama6ef0a62019-03-07 20:34:33 -050082QuicConnectionIdLength GetIncludedConnectionIdLength(
83 QuicConnectionId connection_id,
84 QuicConnectionIdIncluded connection_id_included) {
85 DCHECK(connection_id_included == CONNECTION_ID_PRESENT ||
86 connection_id_included == CONNECTION_ID_ABSENT);
87 return connection_id_included == CONNECTION_ID_PRESENT
88 ? static_cast<QuicConnectionIdLength>(connection_id.length())
89 : PACKET_0BYTE_CONNECTION_ID;
90}
91
92QuicConnectionIdLength GetIncludedDestinationConnectionIdLength(
93 const QuicPacketHeader& header) {
94 return GetIncludedConnectionIdLength(
95 header.destination_connection_id,
96 header.destination_connection_id_included);
97}
98
99QuicConnectionIdLength GetIncludedSourceConnectionIdLength(
100 const QuicPacketHeader& header) {
101 return GetIncludedConnectionIdLength(header.source_connection_id,
102 header.source_connection_id_included);
103}
104
105size_t GetPacketHeaderSize(QuicTransportVersion version,
106 const QuicPacketHeader& header) {
107 return GetPacketHeaderSize(
108 version, GetIncludedDestinationConnectionIdLength(header),
109 GetIncludedSourceConnectionIdLength(header), header.version_flag,
110 header.nonce != nullptr, header.packet_number_length,
111 header.retry_token_length_length, header.retry_token.length(),
112 header.length_length);
113}
114
115size_t GetPacketHeaderSize(
116 QuicTransportVersion version,
117 QuicConnectionIdLength destination_connection_id_length,
118 QuicConnectionIdLength source_connection_id_length,
119 bool include_version,
120 bool include_diversification_nonce,
121 QuicPacketNumberLength packet_number_length,
122 QuicVariableLengthIntegerLength retry_token_length_length,
123 QuicByteCount retry_token_length,
124 QuicVariableLengthIntegerLength length_length) {
fayangd4291e42019-05-30 10:31:21 -0700125 if (VersionHasIetfInvariantHeader(version)) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500126 if (include_version) {
127 // Long header.
nharperd43f1d62019-07-01 15:18:20 -0700128 size_t size = kPacketHeaderTypeSize + kConnectionIdLengthSize +
129 destination_connection_id_length +
130 source_connection_id_length +
131 (version > QUIC_VERSION_44 ? packet_number_length
132 : PACKET_4BYTE_PACKET_NUMBER) +
133 kQuicVersionSize;
134 if (include_diversification_nonce) {
135 size += kDiversificationNonceSize;
136 }
dschinazi48ac9192019-07-31 00:07:26 -0700137 if (VersionHasLengthPrefixedConnectionIds(version)) {
138 size += kConnectionIdLengthSize;
139 }
nharperd43f1d62019-07-01 15:18:20 -0700140 DCHECK(QuicVersionHasLongHeaderLengths(version) ||
nharper2f6632d2019-07-01 18:01:22 -0700141 !GetQuicReloadableFlag(quic_fix_get_packet_header_size) ||
nharperd43f1d62019-07-01 15:18:20 -0700142 retry_token_length_length + retry_token_length + length_length ==
143 0);
144 if (QuicVersionHasLongHeaderLengths(version) ||
145 !GetQuicReloadableFlag(quic_fix_get_packet_header_size)) {
146 QUIC_RELOADABLE_FLAG_COUNT_N(quic_fix_get_packet_header_size, 1, 3);
147 size += retry_token_length_length + retry_token_length + length_length;
148 }
149 return size;
QUICHE teama6ef0a62019-03-07 20:34:33 -0500150 }
151 // Short header.
152 return kPacketHeaderTypeSize + destination_connection_id_length +
153 packet_number_length;
154 }
QUICHE team2252b702019-05-14 23:55:14 -0400155 // Google QUIC versions <= 43 can only carry one connection ID.
156 DCHECK(destination_connection_id_length == 0 ||
157 source_connection_id_length == 0);
158 DCHECK(source_connection_id_length == 0 ||
159 GetQuicRestartFlag(quic_do_not_override_connection_id));
QUICHE teama6ef0a62019-03-07 20:34:33 -0500160 return kPublicFlagsSize + destination_connection_id_length +
QUICHE team2252b702019-05-14 23:55:14 -0400161 source_connection_id_length +
QUICHE teama6ef0a62019-03-07 20:34:33 -0500162 (include_version ? kQuicVersionSize : 0) + packet_number_length +
163 (include_diversification_nonce ? kDiversificationNonceSize : 0);
164}
165
166size_t GetStartOfEncryptedData(QuicTransportVersion version,
167 const QuicPacketHeader& header) {
168 return GetPacketHeaderSize(version, header);
169}
170
171size_t GetStartOfEncryptedData(
172 QuicTransportVersion version,
173 QuicConnectionIdLength destination_connection_id_length,
174 QuicConnectionIdLength source_connection_id_length,
175 bool include_version,
176 bool include_diversification_nonce,
177 QuicPacketNumberLength packet_number_length,
178 QuicVariableLengthIntegerLength retry_token_length_length,
179 QuicByteCount retry_token_length,
180 QuicVariableLengthIntegerLength length_length) {
181 // Encryption starts before private flags.
182 return GetPacketHeaderSize(
183 version, destination_connection_id_length, source_connection_id_length,
184 include_version, include_diversification_nonce, packet_number_length,
185 retry_token_length_length, retry_token_length, length_length);
186}
187
188QuicPacketHeader::QuicPacketHeader()
189 : destination_connection_id(EmptyQuicConnectionId()),
190 destination_connection_id_included(CONNECTION_ID_PRESENT),
191 source_connection_id(EmptyQuicConnectionId()),
192 source_connection_id_included(CONNECTION_ID_ABSENT),
193 reset_flag(false),
194 version_flag(false),
195 has_possible_stateless_reset_token(false),
196 packet_number_length(PACKET_4BYTE_PACKET_NUMBER),
197 version(UnsupportedQuicVersion()),
198 nonce(nullptr),
199 form(GOOGLE_QUIC_PACKET),
200 long_packet_type(INITIAL),
201 possible_stateless_reset_token(0),
202 retry_token_length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
203 retry_token(QuicStringPiece()),
204 length_length(VARIABLE_LENGTH_INTEGER_LENGTH_0),
205 remaining_packet_length(0) {}
206
207QuicPacketHeader::QuicPacketHeader(const QuicPacketHeader& other) = default;
208
209QuicPacketHeader::~QuicPacketHeader() {}
210
211QuicPublicResetPacket::QuicPublicResetPacket()
212 : connection_id(EmptyQuicConnectionId()), nonce_proof(0) {}
213
214QuicPublicResetPacket::QuicPublicResetPacket(QuicConnectionId connection_id)
215 : connection_id(connection_id), nonce_proof(0) {}
216
217QuicVersionNegotiationPacket::QuicVersionNegotiationPacket()
218 : connection_id(EmptyQuicConnectionId()) {}
219
220QuicVersionNegotiationPacket::QuicVersionNegotiationPacket(
221 QuicConnectionId connection_id)
222 : connection_id(connection_id) {}
223
224QuicVersionNegotiationPacket::QuicVersionNegotiationPacket(
225 const QuicVersionNegotiationPacket& other) = default;
226
227QuicVersionNegotiationPacket::~QuicVersionNegotiationPacket() {}
228
229QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket()
230 : stateless_reset_token(0) {}
231
232QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
233 const QuicPacketHeader& header,
234 QuicUint128 token)
235 : header(header), stateless_reset_token(token) {}
236
237QuicIetfStatelessResetPacket::QuicIetfStatelessResetPacket(
238 const QuicIetfStatelessResetPacket& other) = default;
239
240QuicIetfStatelessResetPacket::~QuicIetfStatelessResetPacket() {}
241
242std::ostream& operator<<(std::ostream& os, const QuicPacketHeader& header) {
243 os << "{ destination_connection_id: " << header.destination_connection_id
244 << " ("
245 << (header.destination_connection_id_included == CONNECTION_ID_PRESENT
246 ? "present"
247 : "absent")
248 << "), source_connection_id: " << header.source_connection_id << " ("
249 << (header.source_connection_id_included == CONNECTION_ID_PRESENT
250 ? "present"
251 : "absent")
252 << "), packet_number_length: " << header.packet_number_length
253 << ", reset_flag: " << header.reset_flag
254 << ", version_flag: " << header.version_flag;
255 if (header.version_flag) {
256 os << ", version: " << ParsedQuicVersionToString(header.version);
257 if (header.long_packet_type != INVALID_PACKET_TYPE) {
258 os << ", long_packet_type: "
259 << QuicUtils::QuicLongHeaderTypetoString(header.long_packet_type);
260 }
261 if (header.retry_token_length_length != VARIABLE_LENGTH_INTEGER_LENGTH_0) {
262 os << ", retry_token_length_length: "
263 << static_cast<int>(header.retry_token_length_length);
264 }
265 if (header.retry_token.length() != 0) {
266 os << ", retry_token_length: " << header.retry_token.length();
267 }
268 if (header.length_length != VARIABLE_LENGTH_INTEGER_LENGTH_0) {
269 os << ", length_length: " << static_cast<int>(header.length_length);
270 }
271 if (header.remaining_packet_length != 0) {
272 os << ", remaining_packet_length: " << header.remaining_packet_length;
273 }
274 }
275 if (header.nonce != nullptr) {
276 os << ", diversification_nonce: "
277 << QuicTextUtils::HexEncode(
278 QuicStringPiece(header.nonce->data(), header.nonce->size()));
279 }
280 os << ", packet_number: " << header.packet_number << " }\n";
281 return os;
282}
283
284QuicData::QuicData(const char* buffer, size_t length)
285 : buffer_(buffer), length_(length), owns_buffer_(false) {}
286
287QuicData::QuicData(const char* buffer, size_t length, bool owns_buffer)
288 : buffer_(buffer), length_(length), owns_buffer_(owns_buffer) {}
289
290QuicData::~QuicData() {
291 if (owns_buffer_) {
292 delete[] const_cast<char*>(buffer_);
293 }
294}
295
296QuicPacket::QuicPacket(
297 char* buffer,
298 size_t length,
299 bool owns_buffer,
300 QuicConnectionIdLength destination_connection_id_length,
301 QuicConnectionIdLength source_connection_id_length,
302 bool includes_version,
303 bool includes_diversification_nonce,
304 QuicPacketNumberLength packet_number_length,
305 QuicVariableLengthIntegerLength retry_token_length_length,
306 QuicByteCount retry_token_length,
307 QuicVariableLengthIntegerLength length_length)
308 : QuicData(buffer, length, owns_buffer),
309 buffer_(buffer),
310 destination_connection_id_length_(destination_connection_id_length),
311 source_connection_id_length_(source_connection_id_length),
312 includes_version_(includes_version),
313 includes_diversification_nonce_(includes_diversification_nonce),
314 packet_number_length_(packet_number_length),
315 retry_token_length_length_(retry_token_length_length),
316 retry_token_length_(retry_token_length),
317 length_length_(length_length) {}
318
dschinazi17d42422019-06-18 16:35:07 -0700319QuicPacket::QuicPacket(QuicTransportVersion /*version*/,
QUICHE teama6ef0a62019-03-07 20:34:33 -0500320 char* buffer,
321 size_t length,
322 bool owns_buffer,
323 const QuicPacketHeader& header)
324 : QuicPacket(buffer,
325 length,
326 owns_buffer,
327 GetIncludedDestinationConnectionIdLength(header),
328 GetIncludedSourceConnectionIdLength(header),
329 header.version_flag,
330 header.nonce != nullptr,
331 header.packet_number_length,
332 header.retry_token_length_length,
333 header.retry_token.length(),
334 header.length_length) {}
335
336QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer, size_t length)
337 : QuicData(buffer, length) {}
338
339QuicEncryptedPacket::QuicEncryptedPacket(const char* buffer,
340 size_t length,
341 bool owns_buffer)
342 : QuicData(buffer, length, owns_buffer) {}
343
344std::unique_ptr<QuicEncryptedPacket> QuicEncryptedPacket::Clone() const {
345 char* buffer = new char[this->length()];
346 memcpy(buffer, this->data(), this->length());
347 return QuicMakeUnique<QuicEncryptedPacket>(buffer, this->length(), true);
348}
349
350std::ostream& operator<<(std::ostream& os, const QuicEncryptedPacket& s) {
351 os << s.length() << "-byte data";
352 return os;
353}
354
355QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
356 size_t length,
357 QuicTime receipt_time)
358 : QuicReceivedPacket(buffer,
359 length,
360 receipt_time,
361 false /* owns_buffer */) {}
362
363QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
364 size_t length,
365 QuicTime receipt_time,
366 bool owns_buffer)
367 : QuicReceivedPacket(buffer,
368 length,
369 receipt_time,
370 owns_buffer,
371 0 /* ttl */,
372 true /* ttl_valid */) {}
373
374QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
375 size_t length,
376 QuicTime receipt_time,
377 bool owns_buffer,
378 int ttl,
379 bool ttl_valid)
380 : quic::QuicReceivedPacket(buffer,
381 length,
382 receipt_time,
383 owns_buffer,
384 ttl,
385 ttl_valid,
386 nullptr /* packet_headers */,
387 0 /* headers_length */,
388 false /* owns_header_buffer */) {}
389
390QuicReceivedPacket::QuicReceivedPacket(const char* buffer,
391 size_t length,
392 QuicTime receipt_time,
393 bool owns_buffer,
394 int ttl,
395 bool ttl_valid,
396 char* packet_headers,
397 size_t headers_length,
398 bool owns_header_buffer)
399 : QuicEncryptedPacket(buffer, length, owns_buffer),
400 receipt_time_(receipt_time),
401 ttl_(ttl_valid ? ttl : -1),
402 packet_headers_(packet_headers),
403 headers_length_(headers_length),
404 owns_header_buffer_(owns_header_buffer) {}
405
406QuicReceivedPacket::~QuicReceivedPacket() {
407 if (owns_header_buffer_) {
408 delete[] static_cast<char*>(packet_headers_);
409 }
410}
411
412std::unique_ptr<QuicReceivedPacket> QuicReceivedPacket::Clone() const {
413 char* buffer = new char[this->length()];
414 memcpy(buffer, this->data(), this->length());
415 if (this->packet_headers()) {
416 char* headers_buffer = new char[this->headers_length()];
417 memcpy(headers_buffer, this->packet_headers(), this->headers_length());
418 return QuicMakeUnique<QuicReceivedPacket>(
419 buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0,
420 headers_buffer, this->headers_length(), true);
421 }
422
423 return QuicMakeUnique<QuicReceivedPacket>(
424 buffer, this->length(), receipt_time(), true, ttl(), ttl() >= 0);
425}
426
427std::ostream& operator<<(std::ostream& os, const QuicReceivedPacket& s) {
428 os << s.length() << "-byte data";
429 return os;
430}
431
432QuicStringPiece QuicPacket::AssociatedData(QuicTransportVersion version) const {
433 return QuicStringPiece(
434 data(),
435 GetStartOfEncryptedData(version, destination_connection_id_length_,
436 source_connection_id_length_, includes_version_,
437 includes_diversification_nonce_,
438 packet_number_length_, retry_token_length_length_,
439 retry_token_length_, length_length_));
440}
441
442QuicStringPiece QuicPacket::Plaintext(QuicTransportVersion version) const {
443 const size_t start_of_encrypted_data = GetStartOfEncryptedData(
444 version, destination_connection_id_length_, source_connection_id_length_,
445 includes_version_, includes_diversification_nonce_, packet_number_length_,
446 retry_token_length_length_, retry_token_length_, length_length_);
447 return QuicStringPiece(data() + start_of_encrypted_data,
448 length() - start_of_encrypted_data);
449}
450
451SerializedPacket::SerializedPacket(QuicPacketNumber packet_number,
452 QuicPacketNumberLength packet_number_length,
453 const char* encrypted_buffer,
454 QuicPacketLength encrypted_length,
455 bool has_ack,
456 bool has_stop_waiting)
457 : encrypted_buffer(encrypted_buffer),
458 encrypted_length(encrypted_length),
459 has_crypto_handshake(NOT_HANDSHAKE),
460 num_padding_bytes(0),
461 packet_number(packet_number),
462 packet_number_length(packet_number_length),
QUICHE team6987b4a2019-03-15 16:23:04 -0700463 encryption_level(ENCRYPTION_INITIAL),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500464 has_ack(has_ack),
465 has_stop_waiting(has_stop_waiting),
466 transmission_type(NOT_RETRANSMISSION) {}
467
468SerializedPacket::SerializedPacket(const SerializedPacket& other) = default;
469
470SerializedPacket& SerializedPacket::operator=(const SerializedPacket& other) =
471 default;
472
473SerializedPacket::SerializedPacket(SerializedPacket&& other)
474 : encrypted_buffer(other.encrypted_buffer),
475 encrypted_length(other.encrypted_length),
476 has_crypto_handshake(other.has_crypto_handshake),
477 num_padding_bytes(other.num_padding_bytes),
478 packet_number(other.packet_number),
479 packet_number_length(other.packet_number_length),
480 encryption_level(other.encryption_level),
481 has_ack(other.has_ack),
482 has_stop_waiting(other.has_stop_waiting),
483 transmission_type(other.transmission_type),
484 original_packet_number(other.original_packet_number),
485 largest_acked(other.largest_acked) {
486 retransmittable_frames.swap(other.retransmittable_frames);
487}
488
489SerializedPacket::~SerializedPacket() {}
490
491void ClearSerializedPacket(SerializedPacket* serialized_packet) {
492 if (!serialized_packet->retransmittable_frames.empty()) {
493 DeleteFrames(&serialized_packet->retransmittable_frames);
494 }
495 serialized_packet->encrypted_buffer = nullptr;
496 serialized_packet->encrypted_length = 0;
497 serialized_packet->largest_acked.Clear();
498}
499
500char* CopyBuffer(const SerializedPacket& packet) {
501 char* dst_buffer = new char[packet.encrypted_length];
502 memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length);
503 return dst_buffer;
504}
505
fayang1ed1f762019-06-24 11:40:04 -0700506ReceivedPacketInfo::ReceivedPacketInfo(const QuicSocketAddress& self_address,
507 const QuicSocketAddress& peer_address,
508 const QuicReceivedPacket& packet)
509 : self_address(self_address),
510 peer_address(peer_address),
511 packet(packet),
512 form(GOOGLE_QUIC_PACKET),
513 version_flag(false),
dschinazi48ac9192019-07-31 00:07:26 -0700514 use_length_prefix(false),
fayang1ed1f762019-06-24 11:40:04 -0700515 version_label(0),
516 version(PROTOCOL_UNSUPPORTED, QUIC_VERSION_UNSUPPORTED),
517 destination_connection_id(EmptyQuicConnectionId()),
518 source_connection_id(EmptyQuicConnectionId()) {}
519
520ReceivedPacketInfo::~ReceivedPacketInfo() {}
521
522std::string ReceivedPacketInfo::ToString() const {
523 std::string output =
524 QuicStrCat("{ self_address: ", self_address.ToString(),
525 ", peer_address: ", peer_address.ToString(),
526 ", packet_length: ", packet.length(),
527 ", header_format: ", form, ", version_flag: ", version_flag);
528 if (version_flag) {
529 QuicStrAppend(&output, ", version: ", ParsedQuicVersionToString(version));
530 }
531 QuicStrAppend(
532 &output,
533 ", destination_connection_id: ", destination_connection_id.ToString(),
534 ", source_connection_id: ", source_connection_id.ToString(), " }\n");
535 return output;
536}
537
538std::ostream& operator<<(std::ostream& os,
539 const ReceivedPacketInfo& packet_info) {
540 os << packet_info.ToString();
541 return os;
542}
543
QUICHE teama6ef0a62019-03-07 20:34:33 -0500544} // namespace quic