| 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 |