Home | History | Annotate | Download | only in quic
      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 
      9 #include "base/logging.h"
     10 #include "base/port.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/strings/string_number_conversions.h"
     13 
     14 using base::StringPiece;
     15 using std::string;
     16 
     17 namespace net {
     18 
     19 // static
     20 uint64 QuicUtils::FNV1a_64_Hash(const char* data, int len) {
     21   static const uint64 kOffset = GG_UINT64_C(14695981039346656037);
     22   static const uint64 kPrime = GG_UINT64_C(1099511628211);
     23 
     24   const uint8* octets = reinterpret_cast<const uint8*>(data);
     25 
     26   uint64 hash = kOffset;
     27 
     28   for (int i = 0; i < len; ++i) {
     29     hash = hash ^ octets[i];
     30     hash = hash * kPrime;
     31   }
     32 
     33   return hash;
     34 }
     35 
     36 // static
     37 uint128 QuicUtils::FNV1a_128_Hash(const char* data, int len) {
     38   // The following two constants are defined as part of the hash algorithm.
     39   // see http://www.isthe.com/chongo/tech/comp/fnv/
     40   // 309485009821345068724781371
     41   const uint128 kPrime(16777216, 315);
     42   // 144066263297769815596495629667062367629
     43   const uint128 kOffset(GG_UINT64_C(7809847782465536322),
     44                         GG_UINT64_C(7113472399480571277));
     45 
     46   const uint8* octets = reinterpret_cast<const uint8*>(data);
     47 
     48   uint128 hash = kOffset;
     49 
     50   for (int i = 0; i < len; ++i) {
     51     hash  = hash ^ uint128(0, octets[i]);
     52     hash = hash * kPrime;
     53   }
     54 
     55   return hash;
     56 }
     57 
     58 // static
     59 bool QuicUtils::FindMutualTag(const QuicTagVector& our_tags_vector,
     60                               const QuicTag* their_tags,
     61                               size_t num_their_tags,
     62                               Priority priority,
     63                               QuicTag* out_result,
     64                               size_t* out_index) {
     65   if (our_tags_vector.empty()) {
     66     return false;
     67   }
     68   const size_t num_our_tags = our_tags_vector.size();
     69   const QuicTag* our_tags = &our_tags_vector[0];
     70 
     71   size_t num_priority_tags, num_inferior_tags;
     72   const QuicTag* priority_tags;
     73   const QuicTag* inferior_tags;
     74   if (priority == LOCAL_PRIORITY) {
     75     num_priority_tags = num_our_tags;
     76     priority_tags = our_tags;
     77     num_inferior_tags = num_their_tags;
     78     inferior_tags = their_tags;
     79   } else {
     80     num_priority_tags = num_their_tags;
     81     priority_tags = their_tags;
     82     num_inferior_tags = num_our_tags;
     83     inferior_tags = our_tags;
     84   }
     85 
     86   for (size_t i = 0; i < num_priority_tags; i++) {
     87     for (size_t j = 0; j < num_inferior_tags; j++) {
     88       if (priority_tags[i] == inferior_tags[j]) {
     89         *out_result = priority_tags[i];
     90         if (out_index) {
     91           if (priority == LOCAL_PRIORITY) {
     92             *out_index = j;
     93           } else {
     94             *out_index = i;
     95           }
     96         }
     97         return true;
     98       }
     99     }
    100   }
    101 
    102   return false;
    103 }
    104 
    105 // static
    106 void QuicUtils::SerializeUint128(uint128 v, uint8* out) {
    107   const uint64 lo = Uint128Low64(v);
    108   const uint64 hi = Uint128High64(v);
    109   // This assumes that the system is little-endian.
    110   memcpy(out, &lo, sizeof(lo));
    111   memcpy(out + sizeof(lo), &hi, sizeof(hi));
    112 }
    113 
    114 // static
    115 uint128 QuicUtils::ParseUint128(const uint8* in) {
    116   uint64 lo, hi;
    117   memcpy(&lo, in, sizeof(lo));
    118   memcpy(&hi, in + sizeof(lo), sizeof(hi));
    119   return uint128(hi, lo);
    120 }
    121 
    122 #define RETURN_STRING_LITERAL(x) \
    123 case x: \
    124 return #x;
    125 
    126 // static
    127 const char* QuicUtils::StreamErrorToString(QuicRstStreamErrorCode error) {
    128   switch (error) {
    129     RETURN_STRING_LITERAL(QUIC_STREAM_NO_ERROR);
    130     RETURN_STRING_LITERAL(QUIC_STREAM_CONNECTION_ERROR);
    131     RETURN_STRING_LITERAL(QUIC_SERVER_ERROR_PROCESSING_STREAM);
    132     RETURN_STRING_LITERAL(QUIC_MULTIPLE_TERMINATION_OFFSETS);
    133     RETURN_STRING_LITERAL(QUIC_BAD_APPLICATION_PAYLOAD);
    134     RETURN_STRING_LITERAL(QUIC_STREAM_PEER_GOING_AWAY);
    135     RETURN_STRING_LITERAL(QUIC_STREAM_LAST_ERROR);
    136   }
    137   // Return a default value so that we return this when |error| doesn't match
    138   // any of the QuicRstStreamErrorCodes. This can happen when the RstStream
    139   // frame sent by the peer (attacker) has invalid error code.
    140   return "INVALID_RST_STREAM_ERROR_CODE";
    141 }
    142 
    143 // static
    144 const char* QuicUtils::ErrorToString(QuicErrorCode error) {
    145   switch (error) {
    146     RETURN_STRING_LITERAL(QUIC_NO_ERROR);
    147     RETURN_STRING_LITERAL(QUIC_INTERNAL_ERROR);
    148     RETURN_STRING_LITERAL(QUIC_STREAM_DATA_AFTER_TERMINATION);
    149     RETURN_STRING_LITERAL(QUIC_INVALID_PACKET_HEADER);
    150     RETURN_STRING_LITERAL(QUIC_INVALID_FRAME_DATA);
    151     RETURN_STRING_LITERAL(QUIC_INVALID_FEC_DATA);
    152     RETURN_STRING_LITERAL(QUIC_INVALID_RST_STREAM_DATA);
    153     RETURN_STRING_LITERAL(QUIC_INVALID_CONNECTION_CLOSE_DATA);
    154     RETURN_STRING_LITERAL(QUIC_INVALID_GOAWAY_DATA);
    155     RETURN_STRING_LITERAL(QUIC_INVALID_ACK_DATA);
    156     RETURN_STRING_LITERAL(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
    157     RETURN_STRING_LITERAL(QUIC_INVALID_PUBLIC_RST_PACKET);
    158     RETURN_STRING_LITERAL(QUIC_DECRYPTION_FAILURE);
    159     RETURN_STRING_LITERAL(QUIC_ENCRYPTION_FAILURE);
    160     RETURN_STRING_LITERAL(QUIC_PACKET_TOO_LARGE);
    161     RETURN_STRING_LITERAL(QUIC_PACKET_FOR_NONEXISTENT_STREAM);
    162     RETURN_STRING_LITERAL(QUIC_PEER_GOING_AWAY);
    163     RETURN_STRING_LITERAL(QUIC_HANDSHAKE_FAILED);
    164     RETURN_STRING_LITERAL(QUIC_CRYPTO_TAGS_OUT_OF_ORDER);
    165     RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_ENTRIES);
    166     RETURN_STRING_LITERAL(QUIC_CRYPTO_TOO_MANY_REJECTS);
    167     RETURN_STRING_LITERAL(QUIC_CRYPTO_INVALID_VALUE_LENGTH)
    168     RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_AFTER_HANDSHAKE_COMPLETE);
    169     RETURN_STRING_LITERAL(QUIC_CRYPTO_INTERNAL_ERROR);
    170     RETURN_STRING_LITERAL(QUIC_CRYPTO_VERSION_NOT_SUPPORTED);
    171     RETURN_STRING_LITERAL(QUIC_CRYPTO_NO_SUPPORT);
    172     RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_TYPE);
    173     RETURN_STRING_LITERAL(QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER);
    174     RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NOT_FOUND);
    175     RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_PARAMETER_NO_OVERLAP);
    176     RETURN_STRING_LITERAL(QUIC_CRYPTO_MESSAGE_INDEX_NOT_FOUND);
    177     RETURN_STRING_LITERAL(QUIC_INVALID_STREAM_ID);
    178     RETURN_STRING_LITERAL(QUIC_TOO_MANY_OPEN_STREAMS);
    179     RETURN_STRING_LITERAL(QUIC_PUBLIC_RESET);
    180     RETURN_STRING_LITERAL(QUIC_INVALID_VERSION);
    181     RETURN_STRING_LITERAL(QUIC_STREAM_RST_BEFORE_HEADERS_DECOMPRESSED);
    182     RETURN_STRING_LITERAL(QUIC_INVALID_HEADER_ID);
    183     RETURN_STRING_LITERAL(QUIC_INVALID_NEGOTIATED_VALUE);
    184     RETURN_STRING_LITERAL(QUIC_DECOMPRESSION_FAILURE);
    185     RETURN_STRING_LITERAL(QUIC_CONNECTION_TIMED_OUT);
    186     RETURN_STRING_LITERAL(QUIC_ERROR_MIGRATING_ADDRESS);
    187     RETURN_STRING_LITERAL(QUIC_PACKET_WRITE_ERROR);
    188     RETURN_STRING_LITERAL(QUIC_PROOF_INVALID);
    189     RETURN_STRING_LITERAL(QUIC_CRYPTO_DUPLICATE_TAG);
    190     RETURN_STRING_LITERAL(QUIC_CRYPTO_ENCRYPTION_LEVEL_INCORRECT);
    191     RETURN_STRING_LITERAL(QUIC_CRYPTO_SERVER_CONFIG_EXPIRED);
    192     RETURN_STRING_LITERAL(QUIC_LAST_ERROR);
    193     // Intentionally have no default case, so we'll break the build
    194     // if we add errors and don't put them here.
    195   }
    196   // Return a default value so that we return this when |error| doesn't match
    197   // any of the QuicErrorCodes. This can happen when the ConnectionClose
    198   // frame sent by the peer (attacker) has invalid error code.
    199   return "INVALID_ERROR_CODE";
    200 }
    201 
    202 // static
    203 const char* QuicUtils::EncryptionLevelToString(EncryptionLevel level) {
    204   switch (level) {
    205     RETURN_STRING_LITERAL(ENCRYPTION_NONE);
    206     RETURN_STRING_LITERAL(ENCRYPTION_INITIAL);
    207     RETURN_STRING_LITERAL(ENCRYPTION_FORWARD_SECURE);
    208     RETURN_STRING_LITERAL(NUM_ENCRYPTION_LEVELS);
    209   }
    210   return "INVALID_ENCRYPTION_LEVEL";
    211 }
    212 
    213 // static
    214 string QuicUtils::TagToString(QuicTag tag) {
    215   char chars[4];
    216   bool ascii = true;
    217   const QuicTag orig_tag = tag;
    218 
    219   for (size_t i = 0; i < sizeof(chars); i++) {
    220     chars[i] = tag;
    221     if (chars[i] == 0 && i == 3) {
    222       chars[i] = ' ';
    223     }
    224     if (!isprint(static_cast<unsigned char>(chars[i]))) {
    225       ascii = false;
    226       break;
    227     }
    228     tag >>= 8;
    229   }
    230 
    231   if (ascii) {
    232     return string(chars, sizeof(chars));
    233   }
    234 
    235   return base::UintToString(orig_tag);
    236 }
    237 
    238 // static
    239 string QuicUtils::StringToHexASCIIDump(StringPiece in_buffer) {
    240   int offset = 0;
    241   const int kBytesPerLine = 16;   // Max bytes dumped per line
    242   const char* buf = in_buffer.data();
    243   int bytes_remaining = in_buffer.size();
    244   string s;   // our output
    245   const char* p = buf;
    246   while (bytes_remaining > 0) {
    247     const int line_bytes = std::min(bytes_remaining, kBytesPerLine);
    248     base::StringAppendF(&s, "0x%04x:  ", offset);  // Do the line header
    249     for (int i = 0; i < kBytesPerLine; ++i) {
    250       if (i < line_bytes) {
    251         base::StringAppendF(&s, "%02x", static_cast<unsigned char>(p[i]));
    252       } else {
    253         s += "  ";    // two-space filler instead of two-space hex digits
    254       }
    255       if (i % 2) s += ' ';
    256     }
    257     s += ' ';
    258     for (int i = 0; i < line_bytes; ++i) {  // Do the ASCII dump
    259       s+= (p[i] >  32 && p[i] < 127) ? p[i] : '.';
    260     }
    261 
    262     bytes_remaining -= line_bytes;
    263     offset += line_bytes;
    264     p += line_bytes;
    265     s += '\n';
    266   }
    267   return s;
    268 }
    269 
    270 }  // namespace net
    271