Merge from Chromium at DEPS revision r202854

This commit was generated by merge_to_master.py.

Change-Id: Idca323f71ef844a9e04f454d4f070b1e398f2deb
diff --git a/net/quic/crypto/crypto_handshake.cc b/net/quic/crypto/crypto_handshake.cc
index 16d32d6..445361a 100644
--- a/net/quic/crypto/crypto_handshake.cc
+++ b/net/quic/crypto/crypto_handshake.cc
@@ -8,6 +8,7 @@
 
 #include "base/memory/scoped_ptr.h"
 #include "base/stl_util.h"
+#include "base/stringprintf.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "crypto/secure_hash.h"
@@ -27,18 +28,22 @@
 #include "net/quic/quic_utils.h"
 
 using base::StringPiece;
+using base::StringPrintf;
 using std::map;
 using std::string;
 using std::vector;
 
 namespace net {
 
-CryptoHandshakeMessage::CryptoHandshakeMessage() : tag_(0) {}
+CryptoHandshakeMessage::CryptoHandshakeMessage()
+    : tag_(0),
+      minimum_size_(0) {}
 
 CryptoHandshakeMessage::CryptoHandshakeMessage(
     const CryptoHandshakeMessage& other)
     : tag_(other.tag_),
-      tag_value_map_(other.tag_value_map_) {
+      tag_value_map_(other.tag_value_map_),
+      minimum_size_(other.minimum_size_) {
   // Don't copy serialized_. scoped_ptr doesn't have a copy constructor.
   // The new object can reconstruct serialized_ lazily.
 }
@@ -52,12 +57,14 @@
   // Don't copy serialized_. scoped_ptr doesn't have an assignment operator.
   // However, invalidate serialized_.
   serialized_.reset();
+  minimum_size_ = other.minimum_size_;
   return *this;
 }
 
 void CryptoHandshakeMessage::Clear() {
   tag_ = 0;
   tag_value_map_.clear();
+  minimum_size_ = 0;
   serialized_.reset();
 }
 
@@ -107,7 +114,6 @@
                                                  const QuicTag** out_tags,
                                                  size_t* out_len) const {
   QuicTagValueMap::const_iterator it = tag_value_map_.find(tag);
-  *out_len = 0;
   QuicErrorCode ret = QUIC_NO_ERROR;
 
   if (it == tag_value_map_.end()) {
@@ -197,6 +203,29 @@
   return GetPOD(tag, out, sizeof(uint64));
 }
 
+size_t CryptoHandshakeMessage::size() const {
+  size_t ret = sizeof(QuicTag) +
+               sizeof(uint16) /* number of entries */ +
+               sizeof(uint16) /* padding */;
+  ret += (sizeof(QuicTag) + sizeof(uint32) /* end offset */) *
+         tag_value_map_.size();
+  for (QuicTagValueMap::const_iterator i = tag_value_map_.begin();
+       i != tag_value_map_.end(); ++i) {
+    ret += i->second.size();
+  }
+
+  return ret;
+}
+
+void CryptoHandshakeMessage::set_minimum_size(size_t min_bytes) {
+  serialized_.reset();
+  minimum_size_ = min_bytes;
+}
+
+size_t CryptoHandshakeMessage::minimum_size() const {
+  return minimum_size_;
+}
+
 string CryptoHandshakeMessage::DebugString() const {
   return DebugStringInternal(0);
 }
@@ -221,40 +250,12 @@
   return ret;
 }
 
-// TagToString is a utility function for pretty-printing handshake messages
-// that converts a tag to a string. It will try to maintain the human friendly
-// name if possible (i.e. kABCD -> "ABCD"), or will just treat it as a number
-// if not.
-static string TagToString(QuicTag tag) {
-  char chars[4];
-  bool ascii = true;
-  const QuicTag orig_tag = tag;
-
-  for (size_t i = 0; i < sizeof(chars); i++) {
-    chars[i] = tag;
-    if (chars[i] == 0 && i == 3) {
-      chars[i] = ' ';
-    }
-    if (!isprint(static_cast<unsigned char>(chars[i]))) {
-      ascii = false;
-      break;
-    }
-    tag >>= 8;
-  }
-
-  if (ascii) {
-    return string(chars, sizeof(chars));
-  }
-
-  return base::UintToString(orig_tag);
-}
-
 string CryptoHandshakeMessage::DebugStringInternal(size_t indent) const {
-  string ret = string(2 * indent, ' ') + TagToString(tag_) + "<\n";
+  string ret = string(2 * indent, ' ') + QuicUtils::TagToString(tag_) + "<\n";
   ++indent;
   for (QuicTagValueMap::const_iterator it = tag_value_map_.begin();
        it != tag_value_map_.end(); ++it) {
-    ret += string(2 * indent, ' ') + TagToString(it->first) + ": ";
+    ret += string(2 * indent, ' ') + QuicUtils::TagToString(it->first) + ": ";
 
     bool done = false;
     switch (it->first) {
@@ -280,7 +281,7 @@
             if (j > 0) {
               ret += ",";
             }
-            ret += TagToString(tag);
+            ret += QuicUtils::TagToString(tag);
           }
           done = true;
         }
@@ -298,6 +299,11 @@
           }
         }
         break;
+      case kPAD:
+        ret += StringPrintf("(%d bytes of padding)",
+                            static_cast<int>(it->second.size()));
+        done = true;
+        break;
     }
 
     if (!done) {
@@ -331,7 +337,7 @@
 
 QuicCryptoConfig::QuicCryptoConfig()
     : version(0),
-      common_cert_set_(new CommonCertSetsQUIC) {
+      common_cert_sets(new CommonCertSetsQUIC) {
 }
 
 QuicCryptoConfig::~QuicCryptoConfig() {}
@@ -365,11 +371,16 @@
 }
 
 bool QuicCryptoClientConfig::CachedState::SetServerConfig(StringPiece scfg) {
+  if (scfg == server_config_) {
+    return true;
+  }
+
   scfg_.reset(CryptoFramer::ParseMessage(scfg));
   if (!scfg_.get()) {
     return false;
   }
   server_config_ = scfg.as_string();
+  server_config_valid_ = false;
   return true;
 }
 
@@ -462,12 +473,11 @@
     QuicCryptoNegotiatedParameters* out_params,
     CryptoHandshakeMessage* out) const {
   out->set_tag(kCHLO);
+  out->set_minimum_size(kClientHelloMinimumSize);
 
-  // Server name indication.
-  // If server_hostname is not an IP address literal, it is a DNS hostname.
-  IPAddressNumber ip;
-  if (!server_hostname.empty() &&
-      !ParseIPLiteralToNumber(server_hostname, &ip)) {
+  // Server name indication. We only send SNI if it's a valid domain name, as
+  // per the spec.
+  if (CryptoUtils::IsValidSNI(server_hostname)) {
     out->SetStringPiece(kSNI, server_hostname);
   }
   out->SetValue(kVERS, version);
@@ -476,13 +486,19 @@
     out->SetStringPiece(kSourceAddressTokenTag, cached->source_address_token());
   }
 
-  out->SetTaglist(kPDMD, kX509, 0);
+  if (proof_verifier_.get()) {
+    out->SetTaglist(kPDMD, kX509, 0);
+  }
 
-  if (common_cert_set_.get()) {
-    out->SetStringPiece(kCCS, common_cert_set_->GetCommonHashes());
+  if (common_cert_sets.get()) {
+    out->SetStringPiece(kCCS, common_cert_sets->GetCommonHashes());
   }
 
   const vector<string>& certs = cached->certs();
+  // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
+  // client config is being used for multiple connections, another connection
+  // doesn't update the cached certificates and cause us to be unable to
+  // process the server's compressed certificate chain.
   out_params->cached_certs = certs;
   if (!certs.empty()) {
     vector<uint64> hashes;
@@ -492,10 +508,6 @@
       hashes.push_back(QuicUtils::FNV1a_64_Hash(i->data(), i->size()));
     }
     out->SetVector(kCCRT, hashes);
-    // We save |certs| in the QuicCryptoNegotiatedParameters so that, if the
-    // client config is being used for multiple connections, another connection
-    // doesn't update the cached certificates and cause us to be unable to
-    // process the server's compressed certificate chain.
   }
 }
 
@@ -557,12 +569,12 @@
   }
 
   size_t key_exchange_index;
-  if (!CryptoUtils::FindMutualTag(aead, their_aeads, num_their_aeads,
-                                  CryptoUtils::PEER_PRIORITY, &out_params->aead,
-                                  NULL) ||
-      !CryptoUtils::FindMutualTag(
+  if (!QuicUtils::FindMutualTag(aead, their_aeads, num_their_aeads,
+                                QuicUtils::PEER_PRIORITY, &out_params->aead,
+                                NULL) ||
+      !QuicUtils::FindMutualTag(
           kexs, their_key_exchanges, num_their_key_exchanges,
-          CryptoUtils::PEER_PRIORITY, &out_params->key_exchange,
+          QuicUtils::PEER_PRIORITY, &out_params->key_exchange,
           &key_exchange_index)) {
     *error_details = "Unsupported AEAD or KEXS";
     return QUIC_CRYPTO_NO_SUPPORT;
@@ -667,7 +679,7 @@
       rej.GetStringPiece(kCertificateTag, &cert_bytes)) {
     vector<string> certs;
     if (!CertCompressor::DecompressChain(cert_bytes, out_params->cached_certs,
-                                         common_cert_set_.get(), &certs)) {
+                                         common_cert_sets.get(), &certs)) {
       *error_details = "Certificate data invalid";
       return QUIC_INVALID_CRYPTO_MESSAGE_PARAMETER;
     }