text: // Copyright 2014 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "net/quic/crypto/quic_server_info.h"
  
  #include <limits>
  
  #include "base/pickle.h"
  
  using std::string;
  
  namespace {
  
  const int kQuicCryptoConfigVersion = 1;
  
  }  // namespace
  
  namespace net {
  
  QuicServerInfo::State::State() {}
  
  QuicServerInfo::State::~State() {}
  
  void QuicServerInfo::State::Clear() {
    server_config.clear();
    source_address_token.clear();
    server_config_sig.clear();
    certs.clear();
  }
  
  QuicServerInfo::QuicServerInfo(const string& hostname) : hostname_(hostname) {
  }
  
  QuicServerInfo::~QuicServerInfo() {
  }
  
  const QuicServerInfo::State& QuicServerInfo::state() const {
    return state_;
  }
  
  QuicServerInfo::State* QuicServerInfo::mutable_state() {
    return &state_;
  }
  
  bool QuicServerInfo::Parse(const string& data) {
    State* state = mutable_state();
  
    state->Clear();
  
    bool r = ParseInner(data);
    if (!r)
      state->Clear();
    return r;
  }
  
  bool QuicServerInfo::ParseInner(const string& data) {
    State* state = mutable_state();
  
    // No data was read from the disk cache.
    if (data.empty()) {
      return false;
    }
  
    Pickle p(data.data(), data.size());
    PickleIterator iter(p);
  
    int version = -1;
    if (!p.ReadInt(&iter, &version)) {
      DVLOG(1) << "Missing version";
      return false;
    }
  
    if (version != kQuicCryptoConfigVersion) {
      DVLOG(1) << "Unsupported version";
      return false;
    }
  
    if (!p.ReadString(&iter, &state->server_config)) {
      DVLOG(1) << "Malformed server_config";
      return false;
    }
    if (!p.ReadString(&iter, &state->source_address_token)) {
      DVLOG(1) << "Malformed source_address_token";
      return false;
    }
    if (!p.ReadString(&iter, &state->server_config_sig)) {
      DVLOG(1) << "Malformed server_config_sig";
      return false;
    }
  
    // Read certs.
    uint32 num_certs;
    if (!p.ReadUInt32(&iter, &num_certs)) {
      DVLOG(1) << "Malformed num_certs";
      return false;
    }
  
    for (uint32 i = 0; i < num_certs; i++) {
      string cert;
      if (!p.ReadString(&iter, &cert)) {
        DVLOG(1) << "Malformed cert";
        return false;
      }
      state->certs.push_back(cert);
    }
  
    return true;
  }
  
  string QuicServerInfo::Serialize() const {
    Pickle p(sizeof(Pickle::Header));
  
    if (!p.WriteInt(kQuicCryptoConfigVersion) ||
        !p.WriteString(state_.server_config) ||
        !p.WriteString(state_.source_address_token) ||
        !p.WriteString(state_.server_config_sig) ||
        state_.certs.size() > std::numeric_limits<uint32>::max() ||
        !p.WriteUInt32(state_.certs.size())) {
      return string();
    }
  
    for (size_t i = 0; i < state_.certs.size(); i++) {
      if (!p.WriteString(state_.certs[i])) {
        return string();
      }
    }
  
    return string(reinterpret_cast<const char *>(p.data()), p.size());
  }
  
  QuicServerInfoFactory::~QuicServerInfoFactory() {}
  
  }  // namespace net
  