OLD | NEW |
| (Empty) |
1 // 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/quic/quic_utils.h" | |
6 | |
7 #include <ctype.h> | |
8 #include <stdint.h> | |
9 | |
10 #include <algorithm> | |
11 #include <vector> | |
12 | |
13 #include "base/containers/adapters.h" | |
14 #include "base/logging.h" | |
15 #include "base/strings/string_number_conversions.h" | |
16 #include "base/strings/string_split.h" | |
17 #include "base/strings/stringprintf.h" | |
18 #include "net/base/ip_address.h" | |
19 #include "net/quic/quic_flags.h" | |
20 #include "net/quic/quic_write_blocked_list.h" | |
21 | |
22 using base::StringPiece; | |
23 using std::string; | |
24 | |
25 namespace net { | |
26 namespace { | |
27 | |
28 // We know that >= GCC 4.8 and Clang have a __uint128_t intrinsic. Other | |
29 // compilers don't necessarily, notably MSVC. | |
30 #if defined(__x86_64__) && \ | |
31 ((defined(__GNUC__) && \ | |
32 (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))) || \ | |
33 defined(__clang__)) | |
34 #define QUIC_UTIL_HAS_UINT128 1 | |
35 #endif | |
36 | |
37 #ifdef QUIC_UTIL_HAS_UINT128 | |
38 uint128 IncrementalHashFast(uint128 uhash, const char* data, size_t len) { | |
39 // This code ends up faster than the naive implementation for 2 reasons: | |
40 // 1. uint128 from base/int128.h is sufficiently complicated that the compiler | |
41 // cannot transform the multiplication by kPrime into a shift-multiply-add; | |
42 // it has go through all of the instructions for a 128-bit multiply. | |
43 // 2. Because there are so fewer instructions (around 13), the hot loop fits | |
44 // nicely in the instruction queue of many Intel CPUs. | |
45 // kPrime = 309485009821345068724781371 | |
46 static const __uint128_t kPrime = | |
47 (static_cast<__uint128_t>(16777216) << 64) + 315; | |
48 __uint128_t xhash = (static_cast<__uint128_t>(Uint128High64(uhash)) << 64) + | |
49 Uint128Low64(uhash); | |
50 const uint8_t* octets = reinterpret_cast<const uint8_t*>(data); | |
51 for (size_t i = 0; i < len; ++i) { | |
52 xhash = (xhash ^ octets[i]) * kPrime; | |
53 } | |
54 return uint128(static_cast<uint64_t>(xhash >> 64), | |
55 static_cast<uint64_t>(xhash & UINT64_C(0xFFFFFFFFFFFFFFFF))); | |
56 } | |
57 #endif | |
58 | |
59 #ifndef QUIC_UTIL_HAS_UINT128 | |
60 // Slow implementation of IncrementalHash. In practice, only used by Chromium. | |
61 uint128 IncrementalHashSlow(uint128 hash, const char* data, size_t len) { | |
62 // kPrime = 309485009821345068724781371 | |
63 static const uint128 kPrime(16777216, 315); | |
64 const uint8_t* octets = reinterpret_cast<const uint8_t*>(data); | |
65 for (size_t i = 0; i < len; ++i) { | |
66 hash = hash ^ uint128(0, octets[i]); | |
67 hash = hash * kPrime; | |
68 } | |
69 return hash; | |
70 } | |
71 #endif | |
72 | |
73 uint128 IncrementalHash(uint128 hash, const char* data, size_t len) { | |
74 #ifdef QUIC_UTIL_HAS_UINT128 | |
75 return IncrementalHashFast(hash, data, len); | |
76 #else | |
77 return IncrementalHashSlow(hash, data, len); | |
78 #endif | |
79 } | |
80 | |
81 bool IsInitializedIPEndPoint(const IPEndPoint& address) { | |
82 return address.address().IsValid(); | |
83 } | |
84 | |
85 } // namespace | |
86 | |
87 // static | |
88 uint64_t QuicUtils::FNV1a_64_Hash(const char* data, int len) { | |
89 static const uint64_t kOffset = UINT64_C(14695981039346656037); | |
90 static const uint64_t kPrime = UINT64_C(1099511628211); | |
91 | |
92 const uint8_t* octets = reinterpret_cast<const uint8_t*>(data); | |
93 | |
94 uint64_t hash = kOffset; | |
95 | |
96 for (int i = 0; i < len; ++i) { | |
97 hash = hash ^ octets[i]; | |
98 hash = hash * kPrime; | |
99 } | |
100 | |
101 return hash; | |
102 } | |
103 | |
104 // static | |
105 uint128 QuicUtils::FNV1a_128_Hash(const char* data, int len) { | |
106 return FNV1a_128_Hash_Two(data, len, nullptr, 0); | |
107 } | |
108 | |
109 // static | |
110 uint128 QuicUtils::FNV1a_128_Hash_Two(const char* data1, | |
111 int len1, | |
112 const char* data2, | |
113 int len2) { | |
114 // The two constants are defined as part of the hash algorithm. | |
115 // see http://www.isthe.com/chongo/tech/comp/fnv/ | |
116 // kOffset = 144066263297769815596495629667062367629 | |
117 const uint128 kOffset(UINT64_C(7809847782465536322), | |
118 UINT64_C(7113472399480571277)); | |
119 | |
120 uint128 hash = IncrementalHash(kOffset, data1, len1); | |
121 if (data2 == nullptr) { | |
122 return hash; | |
123 } | |
124 return IncrementalHash(hash, data2, len2); | |
125 } | |
126 | |
127 // static | |
128 bool QuicUtils::FindMutualTag(const QuicTagVector& our_tags_vector, | |
129 const QuicTag* their_tags, | |
130 size_t num_their_tags, | |
131 Priority priority, | |
132 QuicTag* out_result, | |
133 size_t* out_index) { | |
134 if (our_tags_vector.empty()) { | |
135 return false; | |
136 } | |
137 const size_t num_our_tags = our_tags_vector.size(); | |
138 const QuicTag* our_tags = &our_tags_vector[0]; | |
139 | |
140 size_t num_priority_tags, num_inferior_tags; | |
141 const QuicTag* priority_tags; | |
142 const QuicTag* inferior_tags; | |
143 if (priority == LOCAL_PRIORITY) { | |
144 num_priority_tags = num_our_tags; | |
145 priority_tags = our_tags; | |
146 num_inferior_tags = num_their_tags; | |
147 inferior_tags = their_tags; | |
148 } else { | |
149 num_priority_tags = num_their_tags; | |
150 priority_tags = their_tags; | |
151 num_inferior_tags = num_our_tags; | |
152 inferior_tags = our_tags; | |
153 } | |
154 | |
155 for (size_t i = 0; i < num_priority_tags; i++) { | |
156 for (size_t j = 0; j < num_inferior_tags; j++) { | |
157 if (priority_tags[i] == inferior_tags[j]) { | |
158 *out_result = priority_tags[i]; | |
159 if (out_index) { | |
160 if (priority == LOCAL_PRIORITY) { | |
161 *out_index = j; | |
162 } else { | |
163 *out_index = i; | |
164 } | |
165 } | |
166 return true; | |
167 } | |
168 } | |
169 } | |
170 | |
171 return false; | |
172 } | |
173 | |
174 // static | |
175 void QuicUtils::SerializeUint128Short(uint128 v, uint8_t* out) { | |
176 const uint64_t lo = Uint128Low64(v); | |
177 const uint64_t hi = Uint128High64(v); | |
178 // This assumes that the system is little-endian. | |
179 memcpy(out, &lo, sizeof(lo)); | |
180 memcpy(out + sizeof(lo), &hi, sizeof(hi) / 2); | |
181 } | |
182 | |
183 #define RETURN_STRING_LITERAL(x) \ | |
184 case x: \ | |
185 return #x; | |
186 | |
187 // static | |
188 const char* QuicUtils::StreamErrorToString(QuicRstStreamErrorCode error) { | |
189 switch (error) { | |
190 RETURN_STRING_LITERAL(QUIC_STREAM_NO_ERROR); | |
191 RETURN_STRING_LITERAL(QUIC_STREAM_CONNECTION_ERROR); | |
192 RETURN_STRING_LITERAL(QUIC_ERROR_PROCESSING_STREAM); | |
193 RETURN_STRING_LITERAL(QUIC_MULTIPLE_TERMINATION_OFFSETS); | |
194 RETURN_STRING_LITERAL(QUIC_BAD_APPLICATION_PAYLOAD); | |
195 RETURN_STRING_LITERAL(QUIC_STREAM_PEER_GOING_AWAY); | |
196 RETURN_STRING_LITERAL(QUIC_STREAM_CANCELLED); | |
197 RETURN_STRING_LITERAL(QUIC_RST_ACKNOWLEDGEMENT); | |
198 RETURN_STRING_LITERAL(QUIC_REFUSED_STREAM); | |
199 RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR); | |
200 RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_URL); | |
201 RETURN_STRING_LITERAL(QUIC_UNAUTHORIZED_PROMISE_URL); | |
202 RETURN_STRING_LITERAL(QUIC_DUPLICATE_PROMISE_URL); | |
203 RETURN_STRING_LITERAL(QUIC_PROMISE_VARY_MISMATCH); | |
204 RETURN_STRING_LITERAL(QUIC_INVALID_PROMISE_METHOD); | |
205 } | |
206 // Return a default value so that we return this when |error| doesn't match | |
207 // any of the QuicRstStreamErrorCodes. This can happen when the RstStream | |
208 // frame sent by the peer (attacker) has invalid error code. | |
209 return "INVALID_RST_STREAM_ERROR_CODE"; | |
210 } | |
211 | |
212 // static | |
213 const char* QuicUtils::ErrorToString(QuicErrorCode error) { | |
214 switch (error) { | |
215 RETURN_STRING_LITERAL(QUIC_NO_ERROR); | |
216 RETURN_STRING_LITERAL(QUIC_INTERNAL_ERROR); | |
217 RETURN_STRING_LITERAL(QUIC_STREAM_DATA_AFTER_TERMINATION); | |
218 RETURN_STRING_LITERAL(QUIC_INVALID_PACKET_HEADER); | |
219 RETURN_STRING_LITERAL(QUIC_INVALID_FRAME_DATA); | |
220 RETURN_STRING_LITERAL(QUIC_MISSING_PAYLOAD); | |
221 RETURN_STRING_LITERAL(QUIC_INVALID_FEC_DATA); | |
222 RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_DATA); | |
223 RETURN_STRING_LITERAL(QUIC_OVERLAPPING_STREAM_DATA); | |
224 RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_STREAM_DATA); | |
225 RETURN_STRING_LITERAL(QUIC_INVALID_RST_STREAM_DATA); | |
226 RETURN_STRING_LITERAL(QUIC_INVALID_CONNECTION_CLOSE_DATA); | |
227 RETURN_STRING_LITERAL(QUIC_INVALID_GOAWAY_DATA); | |
228 RETURN_STRING_LITERAL(QUIC_INVALID_WINDOW_UPDATE_DATA); | |
229 RETURN_STRING_LITERAL(QUIC_INVALID_BLOCKED_DATA); | |
230 RETURN_STRING_LITERAL(QUIC_INVALID_STOP_WAITING_DATA); | |
231 RETURN_STRING_LITERAL(QUIC_INVALID_PATH_CLOSE_DATA); | |
232 RETURN_STRING_LITERAL(QUIC_INVALID_ACK_DATA); | |
233 RETURN_STRING_LITERAL(QUIC_INVALID_VERSION_NEGOTIATION_PACKET); | |
234 RETURN_STRING_LITERAL(QUIC_INVALID_PUBLIC_RST_PACKET); | |
235 RETURN_STRING_LITERAL(QUIC_DECRYPTION_FAILURE); | |
236 RETURN_STRING_LITERAL(QUIC_ENCRYPTION_FAILURE); | |
237 RETURN_STRING_LITERAL(QUIC_PACKET_TOO_LARGE); | |
238 RETURN_STRING_LITERAL(QUIC_PEER_GOING_AWAY); | |
239 RETURN_STRING_LITERAL(QUIC_HANDSHAKE_FAILED); | |
240 RETURN_STRING_LITERAL(QUIC_CRYPTO_TAGS_OUT_OF_ORDER); | |
241 RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_ENTRIES); | |
242 RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_REJECTS); | |
243 RETURN_STRING_LITERAL(QUIC_CRYPTO_INVALID_VALUE_LENGTH) | |
244 RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE); | |
245 RETURN_STRING_LITERAL(QUIC_CRYPTO_INTERNAL_ERROR); | |
246 RETURN_STRING_LITERAL(QUIC_CRYPTO_VERSION_NOT_SUPPORTED); | |
247 RETURN_STRING_LITERAL(QUIC_CRYPTO_HANDSHAKE_STATELESS_REJECT); | |
248 RETURN_STRING_LITERAL(QUIC_CRYPTO_NO_SUPPORT); | |
249 RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_TYPE); | |
250 RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER); | |
251 RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND); | |
252 RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP); | |
253 RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND); | |
254 RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_ID); | |
255 RETURN_STRING_LITERAL(QUIC_INVALID_PRIORITY); | |
256 RETURN_STRING_LITERAL(QUIC_TOO_MANY_OPEN_STREAMS); | |
257 RETURN_STRING_LITERAL(QUIC_PUBLIC_RESET); | |
258 RETURN_STRING_LITERAL(QUIC_INVALID_VERSION); | |
259 RETURN_STRING_LITERAL(QUIC_INVALID_HEADER_ID); | |
260 RETURN_STRING_LITERAL(QUIC_INVALID_NEGOTIATED_VALUE); | |
261 RETURN_STRING_LITERAL(QUIC_DECOMPRESSION_FAILURE); | |
262 RETURN_STRING_LITERAL(QUIC_NETWORK_IDLE_TIMEOUT); | |
263 RETURN_STRING_LITERAL(QUIC_HANDSHAKE_TIMEOUT); | |
264 RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_ADDRESS); | |
265 RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_PORT); | |
266 RETURN_STRING_LITERAL(QUIC_PACKET_WRITE_ERROR); | |
267 RETURN_STRING_LITERAL(QUIC_PACKET_READ_ERROR); | |
268 RETURN_STRING_LITERAL(QUIC_EMPTY_STREAM_FRAME_NO_FIN); | |
269 RETURN_STRING_LITERAL(QUIC_INVALID_HEADERS_STREAM_DATA); | |
270 RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_RECEIVED_TOO_MUCH_DATA); | |
271 RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_SENT_TOO_MUCH_DATA); | |
272 RETURN_STRING_LITERAL(QUIC_FLOW_CONTROL_INVALID_WINDOW); | |
273 RETURN_STRING_LITERAL(QUIC_CONNECTION_IP_POOLED); | |
274 RETURN_STRING_LITERAL(QUIC_PROOF_INVALID); | |
275 RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG); | |
276 RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT); | |
277 RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED); | |
278 RETURN_STRING_LITERAL(QUIC_INVALID_CHANNEL_ID_SIGNATURE); | |
279 RETURN_STRING_LITERAL(QUIC_CRYPTO_SYMMETRIC_KEY_SETUP_FAILED); | |
280 RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_WHILE_VALIDATING_CLIENT_HELLO); | |
281 RETURN_STRING_LITERAL(QUIC_CRYPTO_UPDATE_BEFORE_HANDSHAKE_COMPLETE); | |
282 RETURN_STRING_LITERAL(QUIC_VERSION_NEGOTIATION_MISMATCH); | |
283 RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_SENT_PACKETS); | |
284 RETURN_STRING_LITERAL(QUIC_TOO_MANY_OUTSTANDING_RECEIVED_PACKETS); | |
285 RETURN_STRING_LITERAL(QUIC_CONNECTION_CANCELLED); | |
286 RETURN_STRING_LITERAL(QUIC_BAD_PACKET_LOSS_RATE); | |
287 RETURN_STRING_LITERAL(QUIC_PUBLIC_RESETS_POST_HANDSHAKE); | |
288 RETURN_STRING_LITERAL(QUIC_TIMEOUTS_WITH_OPEN_STREAMS); | |
289 RETURN_STRING_LITERAL(QUIC_FAILED_TO_SERIALIZE_PACKET); | |
290 RETURN_STRING_LITERAL(QUIC_TOO_MANY_AVAILABLE_STREAMS); | |
291 RETURN_STRING_LITERAL(QUIC_UNENCRYPTED_FEC_DATA); | |
292 RETURN_STRING_LITERAL(QUIC_BAD_MULTIPATH_FLAG); | |
293 RETURN_STRING_LITERAL(QUIC_IP_ADDRESS_CHANGED); | |
294 RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_MIGRATABLE_STREAMS); | |
295 RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_TOO_MANY_CHANGES); | |
296 RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK); | |
297 RETURN_STRING_LITERAL(QUIC_CONNECTION_MIGRATION_NON_MIGRATABLE_STREAM); | |
298 RETURN_STRING_LITERAL(QUIC_TOO_MANY_RTOS); | |
299 RETURN_STRING_LITERAL(QUIC_ATTEMPT_TO_SEND_UNENCRYPTED_STREAM_DATA); | |
300 RETURN_STRING_LITERAL(QUIC_MAYBE_CORRUPTED_MEMORY); | |
301 RETURN_STRING_LITERAL(QUIC_CRYPTO_CHLO_TOO_LARGE); | |
302 RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST); | |
303 RETURN_STRING_LITERAL(QUIC_MULTIPATH_PATH_NOT_ACTIVE); | |
304 RETURN_STRING_LITERAL(QUIC_LAST_ERROR); | |
305 // Intentionally have no default case, so we'll break the build | |
306 // if we add errors and don't put them here. | |
307 } | |
308 // Return a default value so that we return this when |error| doesn't match | |
309 // any of the QuicErrorCodes. This can happen when the ConnectionClose | |
310 // frame sent by the peer (attacker) has invalid error code. | |
311 return "INVALID_ERROR_CODE"; | |
312 } | |
313 | |
314 // static | |
315 const char* QuicUtils::EncryptionLevelToString(EncryptionLevel level) { | |
316 switch (level) { | |
317 RETURN_STRING_LITERAL(ENCRYPTION_NONE); | |
318 RETURN_STRING_LITERAL(ENCRYPTION_INITIAL); | |
319 RETURN_STRING_LITERAL(ENCRYPTION_FORWARD_SECURE); | |
320 RETURN_STRING_LITERAL(NUM_ENCRYPTION_LEVELS); | |
321 } | |
322 return "INVALID_ENCRYPTION_LEVEL"; | |
323 } | |
324 | |
325 // static | |
326 const char* QuicUtils::TransmissionTypeToString(TransmissionType type) { | |
327 switch (type) { | |
328 RETURN_STRING_LITERAL(NOT_RETRANSMISSION); | |
329 RETURN_STRING_LITERAL(HANDSHAKE_RETRANSMISSION); | |
330 RETURN_STRING_LITERAL(LOSS_RETRANSMISSION); | |
331 RETURN_STRING_LITERAL(ALL_UNACKED_RETRANSMISSION); | |
332 RETURN_STRING_LITERAL(ALL_INITIAL_RETRANSMISSION); | |
333 RETURN_STRING_LITERAL(RTO_RETRANSMISSION); | |
334 RETURN_STRING_LITERAL(TLP_RETRANSMISSION); | |
335 } | |
336 return "INVALID_TRANSMISSION_TYPE"; | |
337 } | |
338 | |
339 // static | |
340 string QuicUtils::TagToString(QuicTag tag) { | |
341 char chars[sizeof tag]; | |
342 bool ascii = true; | |
343 const QuicTag orig_tag = tag; | |
344 | |
345 for (size_t i = 0; i < arraysize(chars); i++) { | |
346 chars[i] = static_cast<char>(tag); | |
347 if ((chars[i] == 0 || chars[i] == '\xff') && i == arraysize(chars) - 1) { | |
348 chars[i] = ' '; | |
349 } | |
350 if (!isprint(static_cast<unsigned char>(chars[i]))) { | |
351 ascii = false; | |
352 break; | |
353 } | |
354 tag >>= 8; | |
355 } | |
356 | |
357 if (ascii) { | |
358 return string(chars, sizeof(chars)); | |
359 } | |
360 | |
361 return base::UintToString(orig_tag); | |
362 } | |
363 | |
364 // static | |
365 QuicTagVector QuicUtils::ParseQuicConnectionOptions( | |
366 const std::string& connection_options) { | |
367 QuicTagVector options; | |
368 // Tokens are expected to be no more than 4 characters long, but we | |
369 // handle overflow gracefully. | |
370 for (const base::StringPiece& token : | |
371 base::SplitStringPiece(connection_options, ",", base::TRIM_WHITESPACE, | |
372 base::SPLIT_WANT_ALL)) { | |
373 uint32_t option = 0; | |
374 for (char token_char : base::Reversed(token)) { | |
375 option <<= 8; | |
376 option |= static_cast<unsigned char>(token_char); | |
377 } | |
378 options.push_back(option); | |
379 } | |
380 return options; | |
381 } | |
382 | |
383 string QuicUtils::PeerAddressChangeTypeToString(PeerAddressChangeType type) { | |
384 switch (type) { | |
385 RETURN_STRING_LITERAL(NO_CHANGE); | |
386 RETURN_STRING_LITERAL(PORT_CHANGE); | |
387 RETURN_STRING_LITERAL(IPV4_SUBNET_CHANGE); | |
388 RETURN_STRING_LITERAL(IPV4_TO_IPV6_CHANGE); | |
389 RETURN_STRING_LITERAL(IPV6_TO_IPV4_CHANGE); | |
390 RETURN_STRING_LITERAL(IPV6_TO_IPV6_CHANGE); | |
391 RETURN_STRING_LITERAL(UNSPECIFIED_CHANGE); | |
392 } | |
393 return "INVALID_PEER_ADDRESS_CHANGE_TYPE"; | |
394 } | |
395 | |
396 // static | |
397 void QuicUtils::DeleteFrames(QuicFrames* frames) { | |
398 for (QuicFrame& frame : *frames) { | |
399 switch (frame.type) { | |
400 // Frames smaller than a pointer are inlined, so don't need to be deleted. | |
401 case PADDING_FRAME: | |
402 case MTU_DISCOVERY_FRAME: | |
403 case PING_FRAME: | |
404 break; | |
405 case STREAM_FRAME: | |
406 delete frame.stream_frame; | |
407 break; | |
408 case ACK_FRAME: | |
409 delete frame.ack_frame; | |
410 break; | |
411 case STOP_WAITING_FRAME: | |
412 delete frame.stop_waiting_frame; | |
413 break; | |
414 case RST_STREAM_FRAME: | |
415 delete frame.rst_stream_frame; | |
416 break; | |
417 case CONNECTION_CLOSE_FRAME: | |
418 delete frame.connection_close_frame; | |
419 break; | |
420 case GOAWAY_FRAME: | |
421 delete frame.goaway_frame; | |
422 break; | |
423 case BLOCKED_FRAME: | |
424 delete frame.blocked_frame; | |
425 break; | |
426 case WINDOW_UPDATE_FRAME: | |
427 delete frame.window_update_frame; | |
428 break; | |
429 case PATH_CLOSE_FRAME: | |
430 delete frame.path_close_frame; | |
431 break; | |
432 case NUM_FRAME_TYPES: | |
433 DCHECK(false) << "Cannot delete type: " << frame.type; | |
434 } | |
435 } | |
436 frames->clear(); | |
437 } | |
438 | |
439 // static | |
440 void QuicUtils::RemoveFramesForStream(QuicFrames* frames, | |
441 QuicStreamId stream_id) { | |
442 QuicFrames::iterator it = frames->begin(); | |
443 while (it != frames->end()) { | |
444 if (it->type != STREAM_FRAME || it->stream_frame->stream_id != stream_id) { | |
445 ++it; | |
446 continue; | |
447 } | |
448 delete it->stream_frame; | |
449 it = frames->erase(it); | |
450 } | |
451 } | |
452 | |
453 // static | |
454 void QuicUtils::ClearSerializedPacket(SerializedPacket* serialized_packet) { | |
455 if (!serialized_packet->retransmittable_frames.empty()) { | |
456 DeleteFrames(&serialized_packet->retransmittable_frames); | |
457 } | |
458 serialized_packet->encrypted_buffer = nullptr; | |
459 serialized_packet->encrypted_length = 0; | |
460 } | |
461 | |
462 // static | |
463 uint64_t QuicUtils::PackPathIdAndPacketNumber(QuicPathId path_id, | |
464 QuicPacketNumber packet_number) { | |
465 // Setting the nonce below relies on QuicPathId and QuicPacketNumber being | |
466 // specific sizes. | |
467 static_assert(sizeof(path_id) == 1, "Size of QuicPathId changed."); | |
468 static_assert(sizeof(packet_number) == 8, | |
469 "Size of QuicPacketNumber changed."); | |
470 // Use path_id and lower 7 bytes of packet_number as lower 8 bytes of nonce. | |
471 uint64_t path_id_packet_number = | |
472 (static_cast<uint64_t>(path_id) << 56) | packet_number; | |
473 DCHECK(path_id != kDefaultPathId || path_id_packet_number == packet_number); | |
474 return path_id_packet_number; | |
475 } | |
476 | |
477 // static | |
478 char* QuicUtils::CopyBuffer(const SerializedPacket& packet) { | |
479 char* dst_buffer = new char[packet.encrypted_length]; | |
480 memcpy(dst_buffer, packet.encrypted_buffer, packet.encrypted_length); | |
481 return dst_buffer; | |
482 } | |
483 | |
484 // static | |
485 PeerAddressChangeType QuicUtils::DetermineAddressChangeType( | |
486 const IPEndPoint& old_address, | |
487 const IPEndPoint& new_address) { | |
488 if (!IsInitializedIPEndPoint(old_address) || | |
489 !IsInitializedIPEndPoint(new_address) || old_address == new_address) { | |
490 return NO_CHANGE; | |
491 } | |
492 | |
493 if (old_address.address() == new_address.address()) { | |
494 return PORT_CHANGE; | |
495 } | |
496 | |
497 bool old_ip_is_ipv4 = old_address.address().IsIPv4(); | |
498 bool migrating_ip_is_ipv4 = new_address.address().IsIPv4(); | |
499 if (old_ip_is_ipv4 && !migrating_ip_is_ipv4) { | |
500 return IPV4_TO_IPV6_CHANGE; | |
501 } | |
502 | |
503 if (!old_ip_is_ipv4) { | |
504 return migrating_ip_is_ipv4 ? IPV6_TO_IPV4_CHANGE : IPV6_TO_IPV6_CHANGE; | |
505 } | |
506 | |
507 if (IPAddressMatchesPrefix(old_address.address(), new_address.address(), | |
508 24)) { | |
509 // Subnet part does not change (here, we use /24), which is considered to be | |
510 // caused by NATs. | |
511 return IPV4_SUBNET_CHANGE; | |
512 } | |
513 | |
514 return UNSPECIFIED_CHANGE; | |
515 } | |
516 | |
517 string QuicUtils::HexEncode(const char* data, size_t length) { | |
518 return HexEncode(StringPiece(data, length)); | |
519 } | |
520 | |
521 string QuicUtils::HexEncode(StringPiece data) { | |
522 return ::base::HexEncode(data.data(), data.size()); | |
523 } | |
524 | |
525 string QuicUtils::HexDecode(const char* data, size_t length) { | |
526 return HexDecode(StringPiece(data, length)); | |
527 } | |
528 | |
529 string QuicUtils::HexDecode(StringPiece data) { | |
530 if (data.empty()) | |
531 return ""; | |
532 std::vector<uint8_t> v; | |
533 if (!base::HexStringToBytes(data.as_string(), &v)) | |
534 return ""; | |
535 string out; | |
536 if (!v.empty()) | |
537 out.assign(reinterpret_cast<const char*>(&v[0]), v.size()); | |
538 return out; | |
539 } | |
540 | |
541 string QuicUtils::HexDump(StringPiece binary_input) { | |
542 int offset = 0; | |
543 const int kBytesPerLine = 16; // Max bytes dumped per line | |
544 const char* buf = binary_input.data(); | |
545 int bytes_remaining = binary_input.size(); | |
546 string s; // our output | |
547 const char* p = buf; | |
548 while (bytes_remaining > 0) { | |
549 const int line_bytes = std::min(bytes_remaining, kBytesPerLine); | |
550 base::StringAppendF(&s, "0x%04x: ", offset); // Do the line header | |
551 for (int i = 0; i < kBytesPerLine; ++i) { | |
552 if (i < line_bytes) { | |
553 base::StringAppendF(&s, "%02x", static_cast<unsigned char>(p[i])); | |
554 } else { | |
555 s += " "; // two-space filler instead of two-space hex digits | |
556 } | |
557 if (i % 2) | |
558 s += ' '; | |
559 } | |
560 s += ' '; | |
561 for (int i = 0; i < line_bytes; ++i) { // Do the ASCII dump | |
562 s += (p[i] > 32 && p[i] < 127) ? p[i] : '.'; | |
563 } | |
564 | |
565 bytes_remaining -= line_bytes; | |
566 offset += line_bytes; | |
567 p += line_bytes; | |
568 s += '\n'; | |
569 } | |
570 return s; | |
571 } | |
572 | |
573 } // namespace net | |
OLD | NEW |