| // 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/quic_server_info.h" |
| |
| #include <limits> |
| |
| #include "base/pickle.h" |
| #include "base/stl_util.h" |
| |
| using std::string; |
| |
| namespace { |
| |
| const int kQuicCryptoConfigVersion = 2; |
| |
| } // namespace |
| |
| namespace net { |
| |
| QuicServerInfo::State::State() {} |
| |
| QuicServerInfo::State::~State() {} |
| |
| void QuicServerInfo::State::Clear() { |
| base::STLClearObject(&server_config); |
| base::STLClearObject(&source_address_token); |
| base::STLClearObject(&cert_sct); |
| base::STLClearObject(&chlo_hash); |
| base::STLClearObject(&server_config_sig); |
| base::STLClearObject(&certs); |
| } |
| |
| QuicServerInfo::QuicServerInfo(const quic::QuicServerId& server_id) |
| : server_id_(server_id) {} |
| |
| 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; |
| } |
| |
| base::Pickle p(data.data(), data.size()); |
| base::PickleIterator iter(p); |
| |
| int version = -1; |
| if (!iter.ReadInt(&version)) { |
| DVLOG(1) << "Missing version"; |
| return false; |
| } |
| |
| if (version != kQuicCryptoConfigVersion) { |
| DVLOG(1) << "Unsupported version"; |
| return false; |
| } |
| |
| if (!iter.ReadString(&state->server_config)) { |
| DVLOG(1) << "Malformed server_config"; |
| return false; |
| } |
| if (!iter.ReadString(&state->source_address_token)) { |
| DVLOG(1) << "Malformed source_address_token"; |
| return false; |
| } |
| if (!iter.ReadString(&state->cert_sct)) { |
| DVLOG(1) << "Malformed cert_sct"; |
| return false; |
| } |
| if (!iter.ReadString(&state->chlo_hash)) { |
| DVLOG(1) << "Malformed chlo_hash"; |
| return false; |
| } |
| if (!iter.ReadString(&state->server_config_sig)) { |
| DVLOG(1) << "Malformed server_config_sig"; |
| return false; |
| } |
| |
| // Read certs. |
| uint32_t num_certs; |
| if (!iter.ReadUInt32(&num_certs)) { |
| DVLOG(1) << "Malformed num_certs"; |
| return false; |
| } |
| |
| for (uint32_t i = 0; i < num_certs; i++) { |
| string cert; |
| if (!iter.ReadString(&cert)) { |
| DVLOG(1) << "Malformed cert"; |
| return false; |
| } |
| state->certs.push_back(cert); |
| } |
| |
| return true; |
| } |
| |
| string QuicServerInfo::Serialize() { |
| string pickled_data = SerializeInner(); |
| state_.Clear(); |
| return pickled_data; |
| } |
| |
| string QuicServerInfo::SerializeInner() const { |
| if (state_.certs.size() > std::numeric_limits<uint32_t>::max()) |
| return std::string(); |
| |
| base::Pickle p; |
| p.WriteInt(kQuicCryptoConfigVersion); |
| p.WriteString(state_.server_config); |
| p.WriteString(state_.source_address_token); |
| p.WriteString(state_.cert_sct); |
| p.WriteString(state_.chlo_hash); |
| p.WriteString(state_.server_config_sig); |
| p.WriteUInt32(state_.certs.size()); |
| |
| for (size_t i = 0; i < state_.certs.size(); i++) |
| p.WriteString(state_.certs[i]); |
| |
| return string(reinterpret_cast<const char*>(p.data()), p.size()); |
| } |
| |
| } // namespace net |