summaryrefslogtreecommitdiffstats
path: root/net/socket
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-20 16:30:19 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-20 16:30:19 +0000
commitd0672be51d1a4c25f3dd7d91f9d9c1293b33adc6 (patch)
tree93a2a7f1b8d3426a4e65692b56e12e4011b60241 /net/socket
parenta5e842bf6fda331cdacf3a8d56da19a3ea8d3d0b (diff)
downloadchromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.zip
chromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.tar.gz
chromium_src-d0672be51d1a4c25f3dd7d91f9d9c1293b33adc6.tar.bz2
net: move SSL host info serialisation into SSLHostInfo
This is a prelude to SSLHostInfo being able to kick off certificate validation based on predicted certificates. In order for that to happen, SSLHostInfo has to be able to parse the contents of the saved data, therefore the serialisation/deserialisation is moved into SSLHostInfo and we use a protocol buffer to clean things up. TEST=net_unittests BUG=none Review URL: http://codereview.chromium.org/3915001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@63221 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/socket')
-rw-r--r--net/socket/client_socket_factory.cc2
-rw-r--r--net/socket/client_socket_pool_base_unittest.cc1
-rw-r--r--net/socket/socket_test_util.cc1
-rw-r--r--net/socket/ssl_client_socket_mac_factory.cc1
-rw-r--r--net/socket/ssl_client_socket_nss.cc193
-rw-r--r--net/socket/ssl_client_socket_nss.h2
-rw-r--r--net/socket/ssl_client_socket_nss_factory.cc1
-rw-r--r--net/socket/ssl_client_socket_pool.cc2
-rw-r--r--net/socket/ssl_host_info.cc100
-rw-r--r--net/socket/ssl_host_info.h89
-rw-r--r--net/socket/ssl_host_info.proto34
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc1
12 files changed, 270 insertions, 157 deletions
diff --git a/net/socket/client_socket_factory.cc b/net/socket/client_socket_factory.cc
index a31af007..90bcdc5 100644
--- a/net/socket/client_socket_factory.cc
+++ b/net/socket/client_socket_factory.cc
@@ -6,7 +6,6 @@
#include "base/singleton.h"
#include "build/build_config.h"
-#include "net/base/ssl_host_info.h"
#include "net/socket/client_socket_handle.h"
#if defined(OS_WIN)
#include "net/socket/ssl_client_socket_win.h"
@@ -18,6 +17,7 @@
#include "net/socket/ssl_client_socket_mac.h"
#include "net/socket/ssl_client_socket_nss.h"
#endif
+#include "net/socket/ssl_host_info.h"
#include "net/socket/tcp_client_socket.h"
namespace net {
diff --git a/net/socket/client_socket_pool_base_unittest.cc b/net/socket/client_socket_pool_base_unittest.cc
index 1f99b3d..820b030 100644
--- a/net/socket/client_socket_pool_base_unittest.cc
+++ b/net/socket/client_socket_pool_base_unittest.cc
@@ -23,6 +23,7 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 9854cc5..53bcf89 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -21,6 +21,7 @@
#include "net/http/http_response_headers.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#define NET_TRACE(level, s) DLOG(level) << s << __FUNCTION__ << "() "
diff --git a/net/socket/ssl_client_socket_mac_factory.cc b/net/socket/ssl_client_socket_mac_factory.cc
index bc26261..7f0c5ce 100644
--- a/net/socket/ssl_client_socket_mac_factory.cc
+++ b/net/socket/ssl_client_socket_mac_factory.cc
@@ -5,6 +5,7 @@
#include "net/socket/client_socket_factory.h"
#include "net/socket/ssl_client_socket_mac.h"
+#include "net/socket/ssl_host_info.h"
namespace net {
diff --git a/net/socket/ssl_client_socket_nss.cc b/net/socket/ssl_client_socket_nss.cc
index 95458fa..136f138 100644
--- a/net/socket/ssl_client_socket_nss.cc
+++ b/net/socket/ssl_client_socket_nss.cc
@@ -83,11 +83,11 @@
#include "net/base/net_log.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_connection_status_flags.h"
-#include "net/base/ssl_host_info.h"
#include "net/base/ssl_info.h"
#include "net/base/sys_addrinfo.h"
#include "net/ocsp/nss_ocsp.h"
#include "net/socket/client_socket_handle.h"
+#include "net/socket/ssl_host_info.h"
static const int kRecvBufferSize = 4096;
@@ -461,15 +461,9 @@ int SSLClientSocketNSS::Init() {
return OK;
}
-// This is a version number of the Snap Start information saved by
-// |SaveSnapStartInfo| and loaded by |LoadSnapStartInfo|. Since the information
-// can be saved on disk we might have version skew in the future. Any data with
-// a different version is ignored by |LoadSnapStartInfo|.
-static const uint8 kSnapStartInfoVersion = 0;
-
-// SaveSnapStartInfo serialises the information needed to perform a Snap Start
-// with this server in the future (if any) and tells
-// |ssl_host_info_| to preserve it.
+// SaveSnapStartInfo extracts the information needed to perform a Snap Start
+// with this server in the future (if any) and tells |ssl_host_info_| to
+// preserve it.
void SSLClientSocketNSS::SaveSnapStartInfo() {
if (!ssl_host_info_.get())
return;
@@ -501,32 +495,12 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
return;
if (hello_data_len > std::numeric_limits<uint16>::max())
return;
+ SSLHostInfo::State* state = ssl_host_info_->mutable_state();
+ state->server_hello =
+ std::string(reinterpret_cast<const char *>(hello_data), hello_data_len);
- // The format of the saved info looks like:
- // struct Cert {
- // uint16 length
- // opaque certificate[length];
- // }
- //
- // uint8 version (kSnapStartInfoVersion)
- // uint8 npn_status
- // uint8 npn_proto_len
- // uint8 npn_proto[npn_proto_len]
- // uint16 hello_data_len
- // opaque hello_data[hello_data_len]
- // uint8 num_certs;
- // Cert[num_certs];
-
- std::string npn_proto;
- NextProtoStatus npn_status = GetNextProto(&npn_proto);
-
- unsigned num_certs = 0;
- unsigned len = 3;
- DCHECK_LT(npn_proto.size(), 256u);
- len += npn_proto.size();
- len += 2; // for hello_data_len
- len += hello_data_len;
- len++; // for |num_certs|
+ state->npn_valid = true;
+ state->npn_status = GetNextProto(&state->npn_protocol);
// TODO(wtc): CERT_GetCertChainFromCert might not return the same cert chain
// that the Certificate message actually contained. http://crbug.com/48854
@@ -535,67 +509,22 @@ void SSLClientSocketNSS::SaveSnapStartInfo() {
if (!cert_list)
return;
- unsigned last_cert_len = 0;
- bool last_cert_is_root = false;
for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
!CERT_LIST_END(node, cert_list);
node = CERT_LIST_NEXT(node)) {
- num_certs++;
if (node->cert->derCert.len > std::numeric_limits<uint16>::max()) {
CERT_DestroyCertList(cert_list);
return;
}
- last_cert_len = node->cert->derCert.len;
- len += 2 + last_cert_len;
- last_cert_is_root = node->cert->isRoot == PR_TRUE;
- }
-
- if (num_certs == 0 || num_certs > std::numeric_limits<uint8>::max()) {
- CERT_DestroyCertList(cert_list);
- return;
- }
-
- if (num_certs > 1 && last_cert_is_root) {
- // The cert list included the root certificate, which we don't want to
- // save. (Since we need to predict the server's certificates we don't want
- // to predict the root cert because the server won't send it to us. We
- // could implement this logic either here, or in the code which loads the
- // certificates. But, by doing it here, we save a little disk space).
- //
- // Note that, when the TODO above (http://crbug.com/48854) is handled, this
- // point will be moot.
- len -= 2 + last_cert_len;
- num_certs--;
- }
-
- std::vector<uint8> data(len);
- unsigned j = 0;
- data[j++] = kSnapStartInfoVersion;
- data[j++] = static_cast<uint8>(npn_status);
- data[j++] = static_cast<uint8>(npn_proto.size());
- memcpy(&data[j], npn_proto.data(), npn_proto.size());
- j += npn_proto.size();
- data[j++] = hello_data_len >> 8;
- data[j++] = hello_data_len;
- memcpy(&data[j], hello_data, hello_data_len);
- j += hello_data_len;
- data[j++] = num_certs;
-
- unsigned i = 0;
- for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
- i < num_certs;
- node = CERT_LIST_NEXT(node), i++) {
- data[j++] = node->cert->derCert.len >> 8;
- data[j++] = node->cert->derCert.len;
- memcpy(&data[j], node->cert->derCert.data, node->cert->derCert.len);
- j += node->cert->derCert.len;
+ if (node->cert->isRoot == PR_TRUE)
+ continue;
+ state->certs.push_back(std::string(
+ reinterpret_cast<char*>(node->cert->derCert.data),
+ node->cert->derCert.len));
}
- DCHECK_EQ(j, len);
-
- LOG(ERROR) << "Setting Snap Start info " << hostname_ << " " << len;
- ssl_host_info_->Set(std::string(
- reinterpret_cast<const char *>(&data[0]), len));
+ LOG(ERROR) << "Setting Snap Start info " << hostname_;
+ ssl_host_info_->Persist();
CERT_DestroyCertList(cert_list);
}
@@ -609,69 +538,29 @@ static void DestroyCertificates(CERTCertificate** certs, unsigned len) {
// by |SaveSnapStartInfo|, and sets the predicted certificates and ServerHello
// data on the NSS socket. Returns true on success. If this function returns
// false, the caller should try a normal TLS handshake.
-bool SSLClientSocketNSS::LoadSnapStartInfo(const std::string& info) {
- const unsigned char* data =
- reinterpret_cast<const unsigned char*>(info.data());
- SECStatus rv;
-
- // See the comment in |SaveSnapStartInfo| for the format of the data.
- if (info.size() < 3 ||
- data[0] != kSnapStartInfoVersion) {
- return false;
- }
+bool SSLClientSocketNSS::LoadSnapStartInfo() {
+ const SSLHostInfo::State& state(ssl_host_info_->state());
- unsigned j = 1;
- const uint8 npn_status = data[j++];
- const uint8 npn_proto_len = data[j++];
- if (static_cast<unsigned>(npn_proto_len) + j > info.size()) {
- NOTREACHED();
+ if (state.server_hello.empty() ||
+ state.certs.empty() ||
+ !state.npn_valid) {
return false;
}
- const std::string npn_proto(info.substr(j, npn_proto_len));
- j += npn_proto_len;
- if (j + 2 > info.size()) {
- NOTREACHED();
- return false;
- }
- uint16 hello_data_len = static_cast<uint16>(data[j]) << 8 |
- static_cast<uint16>(data[j+1]);
- j += 2;
- if (static_cast<unsigned>(hello_data_len) + j > info.size()) {
- NOTREACHED();
- return false;
- }
-
- rv = SSL_SetPredictedServerHelloData(nss_fd_, &data[j], hello_data_len);
+ SECStatus rv;
+ rv = SSL_SetPredictedServerHelloData(
+ nss_fd_,
+ reinterpret_cast<const uint8*>(state.server_hello.data()),
+ state.server_hello.size());
DCHECK_EQ(SECSuccess, rv);
- j += hello_data_len;
-
- if (j + 1 > info.size()) {
- NOTREACHED();
- return false;
- }
- unsigned num_certs = data[j++];
- scoped_array<CERTCertificate*> certs(new CERTCertificate*[num_certs]);
- for (unsigned i = 0; i < num_certs; i++) {
- if (j + 2 > info.size()) {
- DestroyCertificates(&certs[0], i);
- NOTREACHED();
- // It's harmless to call only SSL_SetPredictedServerHelloData.
- return false;
- }
- uint16 cert_len = static_cast<uint16>(data[j]) << 8 |
- static_cast<uint16>(data[j+1]);
- j += 2;
- if (static_cast<unsigned>(cert_len) + j > info.size()) {
- DestroyCertificates(&certs[0], i);
- NOTREACHED();
- return false;
- }
+ const std::vector<std::string>& certs_in = state.certs;
+ scoped_array<CERTCertificate*> certs(new CERTCertificate*[certs_in.size()]);
+ for (size_t i = 0; i < certs_in.size(); i++) {
SECItem derCert;
- derCert.data = const_cast<uint8*>(data + j);
- derCert.len = cert_len;
- j += cert_len;
+ derCert.data =
+ const_cast<uint8*>(reinterpret_cast<const uint8*>(certs_in[i].data()));
+ derCert.len = certs_in[i].size();
certs[i] = CERT_NewTempCertificate(
CERT_GetDefaultCertDB(), &derCert, NULL /* no nickname given */,
PR_FALSE /* not permanent */, PR_TRUE /* copy DER data */);
@@ -682,16 +571,14 @@ bool SSLClientSocketNSS::LoadSnapStartInfo(const std::string& info) {
}
}
- rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), num_certs);
- DestroyCertificates(&certs[0], num_certs);
+ rv = SSL_SetPredictedPeerCertificates(nss_fd_, certs.get(), certs_in.size());
+ DestroyCertificates(&certs[0], certs_in.size());
DCHECK_EQ(SECSuccess, rv);
- predicted_npn_status_ = static_cast<NextProtoStatus>(npn_status);
- predicted_npn_proto_ = npn_proto;
-
- // We ignore any trailing data that might be in |info|.
- if (j != info.size())
- LOG(WARNING) << "Trailing data found in SSLHostInfo";
+ if (state.npn_valid) {
+ predicted_npn_status_ = state.npn_status;
+ predicted_npn_proto_ = state.npn_protocol;
+ }
return true;
}
@@ -1974,9 +1861,7 @@ int SSLClientSocketNSS::DoSnapStartLoadInfo() {
int rv = ssl_host_info_->WaitForDataReady(&handshake_io_callback_);
if (rv == OK) {
- LOG(ERROR) << "SSL host info size " << hostname_ << " "
- << ssl_host_info_->data().size();
- if (LoadSnapStartInfo(ssl_host_info_->data())) {
+ if (LoadSnapStartInfo()) {
pseudo_connected_ = true;
GotoState(STATE_SNAP_START_WAIT_FOR_WRITE);
if (user_connect_callback_)
diff --git a/net/socket/ssl_client_socket_nss.h b/net/socket/ssl_client_socket_nss.h
index 8518084..56d16b2 100644
--- a/net/socket/ssl_client_socket_nss.h
+++ b/net/socket/ssl_client_socket_nss.h
@@ -103,7 +103,7 @@ class SSLClientSocketNSS : public SSLClientSocket {
int DoPayloadWrite();
int Init();
void SaveSnapStartInfo();
- bool LoadSnapStartInfo(const std::string& info);
+ bool LoadSnapStartInfo();
bool IsNPNProtocolMispredicted();
void UncorkAfterTimeout();
diff --git a/net/socket/ssl_client_socket_nss_factory.cc b/net/socket/ssl_client_socket_nss_factory.cc
index b5488d9..efa6e23 100644
--- a/net/socket/ssl_client_socket_nss_factory.cc
+++ b/net/socket/ssl_client_socket_nss_factory.cc
@@ -6,6 +6,7 @@
#include "build/build_config.h"
#include "net/socket/ssl_client_socket_nss.h"
+#include "net/socket/ssl_host_info.h"
#if defined(OS_WIN)
#include "net/socket/ssl_client_socket_win.h"
#endif
diff --git a/net/socket/ssl_client_socket_pool.cc b/net/socket/ssl_client_socket_pool.cc
index 048ff4b..98e3b09 100644
--- a/net/socket/ssl_client_socket_pool.cc
+++ b/net/socket/ssl_client_socket_pool.cc
@@ -8,13 +8,13 @@
#include "base/values.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_cert_request_info.h"
-#include "net/base/ssl_host_info.h"
#include "net/http/http_proxy_client_socket.h"
#include "net/http/http_proxy_client_socket_pool.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socks_client_socket_pool.h"
#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_host_info.h"
#include "net/socket/tcp_client_socket_pool.h"
namespace net {
diff --git a/net/socket/ssl_host_info.cc b/net/socket/ssl_host_info.cc
new file mode 100644
index 0000000..4b5bb02
--- /dev/null
+++ b/net/socket/ssl_host_info.cc
@@ -0,0 +1,100 @@
+// Copyright (c) 2010 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/socket/ssl_host_info.h"
+
+#include "net/socket/ssl_client_socket.h"
+#include "net/socket/ssl_host_info.pb.h"
+
+namespace net {
+
+SSLHostInfo::SSLHostInfo() {
+ state_.npn_valid = false;
+}
+
+SSLHostInfo::~SSLHostInfo() {}
+
+// This array and the next two functions serve to map between the internal NPN
+// status enum (which might change across versions) and the protocol buffer
+// based enum (which will not).
+static const struct {
+ SSLClientSocket::NextProtoStatus npn_status;
+ SSLHostInfoProto::NextProtoStatus proto_status;
+} kNPNStatusMapping[] = {
+ { SSLClientSocket::kNextProtoUnsupported, SSLHostInfoProto::UNSUPPORTED },
+ { SSLClientSocket::kNextProtoNegotiated, SSLHostInfoProto::NEGOTIATED },
+ { SSLClientSocket::kNextProtoNoOverlap, SSLHostInfoProto::NO_OVERLAP },
+};
+
+static SSLClientSocket::NextProtoStatus NPNStatusFromProtoStatus(
+ SSLHostInfoProto::NextProtoStatus proto_status) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
+ if (kNPNStatusMapping[i].proto_status == proto_status)
+ return kNPNStatusMapping[i].npn_status;
+ }
+ return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1].npn_status;
+}
+
+static SSLHostInfoProto::NextProtoStatus ProtoStatusFromNPNStatus(
+ SSLClientSocket::NextProtoStatus npn_status) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kNPNStatusMapping) - 1; i++) {
+ if (kNPNStatusMapping[i].npn_status == npn_status)
+ return kNPNStatusMapping[i].proto_status;
+ }
+ return kNPNStatusMapping[ARRAYSIZE_UNSAFE(kNPNStatusMapping)-1].proto_status;
+}
+
+const SSLHostInfo::State& SSLHostInfo::state() const {
+ return state_;
+}
+
+SSLHostInfo::State* SSLHostInfo::mutable_state() {
+ return &state_;
+}
+
+bool SSLHostInfo::Parse(const std::string& data) {
+ SSLHostInfoProto proto;
+ State* state = mutable_state();
+
+ state->certs.clear();
+ state->server_hello.clear();
+ state->npn_valid = false;
+
+ if (!proto.ParseFromString(data))
+ return false;
+
+ for (int i = 0; i < proto.certificate_der_size(); i++)
+ state->certs.push_back(proto.certificate_der(i));
+ if (proto.has_server_hello())
+ state->server_hello = proto.server_hello();
+ if (proto.has_npn_status() && proto.has_npn_protocol()) {
+ state->npn_valid = true;
+ state->npn_status = NPNStatusFromProtoStatus(proto.npn_status());
+ state->npn_protocol = proto.npn_protocol();
+ }
+
+ return true;
+}
+
+std::string SSLHostInfo::Serialize() const {
+ SSLHostInfoProto proto;
+
+ for (std::vector<std::string>::const_iterator
+ i = state_.certs.begin(); i != state_.certs.end(); i++) {
+ proto.add_certificate_der(*i);
+ }
+ if (!state_.server_hello.empty())
+ proto.set_server_hello(state_.server_hello);
+
+ if (state_.npn_valid) {
+ proto.set_npn_status(ProtoStatusFromNPNStatus(state_.npn_status));
+ proto.set_npn_protocol(state_.npn_protocol);
+ }
+
+ return proto.SerializeAsString();
+}
+
+SSLHostInfoFactory::~SSLHostInfoFactory() {}
+
+} // namespace net
diff --git a/net/socket/ssl_host_info.h b/net/socket/ssl_host_info.h
new file mode 100644
index 0000000..8065b47
--- /dev/null
+++ b/net/socket/ssl_host_info.h
@@ -0,0 +1,89 @@
+// Copyright (c) 2010 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.
+
+#ifndef NET_SOCKET_SSL_HOST_INFO_H
+#define NET_SOCKET_SSL_HOST_INFO_H
+
+#include <string>
+#include <vector>
+
+#include "base/ref_counted.h"
+#include "net/base/completion_callback.h"
+#include "net/socket/ssl_client_socket.h"
+
+namespace net {
+
+// SSLHostInfo is an interface for fetching information about an SSL server.
+// This information may be stored on disk so does not include keys or session
+// information etc. Primarily it's intended for caching the server's
+// certificates.
+class SSLHostInfo {
+ public:
+ SSLHostInfo();
+ virtual ~SSLHostInfo();
+
+ // Start will commence the lookup. This must be called before any other
+ // methods. By opportunistically calling this early, it may be possible to
+ // overlap this object's lookup and reduce latency.
+ virtual void Start() = 0;
+
+ // WaitForDataReady returns OK if the fetch of the requested data has
+ // completed. Otherwise it returns ERR_IO_PENDING and will call |callback| on
+ // the current thread when ready.
+ //
+ // Only a single callback can be outstanding at a given time and, in the
+ // event that WaitForDataReady returns OK, it's the caller's responsibility
+ // to delete |callback|.
+ //
+ // |callback| may be NULL, in which case ERR_IO_PENDING may still be returned
+ // but, obviously, a callback will never be made.
+ virtual int WaitForDataReady(CompletionCallback* callback) = 0;
+
+ // Persist allows for the host information to be updated for future users.
+ // This is a fire and forget operation: the caller may drop its reference
+ // from this object and the store operation will still complete. This can
+ // only be called once WaitForDataReady has returned OK or called its
+ // callback.
+ virtual void Persist() = 0;
+
+ struct State {
+ // certs is a vector of DER encoded X.509 certificates, as the server
+ // returned them and in the same order.
+ std::vector<std::string> certs;
+ // server_hello contains the bytes of the ServerHello message (or may be
+ // empty if the server doesn't support Snap Start.)
+ std::string server_hello;
+ // npn_valid is true iff |npn_status| and |npn_protocol| is successful.
+ bool npn_valid;
+ // these members contain the NPN result of a connection to the server.
+ SSLClientSocket::NextProtoStatus npn_status;
+ std::string npn_protocol;
+ };
+
+ // Once the data is ready, it can be read using the following members. These
+ // members can then be updated before calling |Persist|.
+ const State& state() const;
+ State* mutable_state();
+
+ protected:
+ // Parse parses an opaque blob of data and fills out the public member fields
+ // of this object. It returns true iff the parse was successful. The public
+ // member fields will be set to something sane in any case.
+ bool Parse(const std::string& data);
+ std::string Serialize() const;
+ State state_;
+};
+
+class SSLHostInfoFactory {
+ public:
+ virtual ~SSLHostInfoFactory();
+
+ // GetForHost returns a fresh, allocated SSLHostInfo for the given hostname
+ // or NULL on failure.
+ virtual SSLHostInfo* GetForHost(const std::string& hostname) = 0;
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_SSL_HOST_INFO_H
diff --git a/net/socket/ssl_host_info.proto b/net/socket/ssl_host_info.proto
new file mode 100644
index 0000000..d74a872
--- /dev/null
+++ b/net/socket/ssl_host_info.proto
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 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.
+
+syntax = "proto2";
+
+option optimize_for = LITE_RUNTIME;
+
+package net;
+
+// SSLHostInfoProto contains information which we store about a given HTTPS
+// server.
+message SSLHostInfoProto {
+ // The certificate chain, as returned by the server, as a series of DER
+ // encoded X.509 certificates.
+ repeated bytes certificate_der = 1;
+ // The contents of the server's ServerHello message. Needed in order to
+ // predict its response in the case of Snap Start.
+ optional bytes server_hello = 2;
+
+ // This is a mirror of SSLClientSocket::NextProtoStatus. We use this in order
+ // to be robust against changes to that enum, which isn't required to be
+ // stable across versions. See the comments there for details.
+ enum NextProtoStatus {
+ UNSUPPORTED = 0;
+ NEGOTIATED = 1;
+ NO_OVERLAP = 2;
+ }
+
+ // When doing Snap Start, we also need to know what protocol we expect the
+ // server to negotiate.
+ optional NextProtoStatus npn_status = 3;
+ optional bytes npn_protocol = 4;
+};
diff --git a/net/socket/tcp_client_socket_pool_unittest.cc b/net/socket/tcp_client_socket_pool_unittest.cc
index 32ac9f8..80de0aa 100644
--- a/net/socket/tcp_client_socket_pool_unittest.cc
+++ b/net/socket/tcp_client_socket_pool_unittest.cc
@@ -15,6 +15,7 @@
#include "net/socket/client_socket_handle.h"
#include "net/socket/client_socket_pool_histograms.h"
#include "net/socket/socket_test_util.h"
+#include "net/socket/ssl_host_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {