summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/base/ssl_config_service.h1
-rw-r--r--net/base/ssl_host_info.cc13
-rw-r--r--net/http/disk_cache_based_ssl_host_info.cc12
-rw-r--r--net/http/disk_cache_based_ssl_host_info.h5
-rw-r--r--net/http/http_cache.cc2
-rw-r--r--net/http/http_network_transaction.cc1
-rw-r--r--net/net.gyp42
-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.h (renamed from net/base/ssl_host_info.h)51
-rw-r--r--net/socket/ssl_host_info.proto34
-rw-r--r--net/socket/tcp_client_socket_pool_unittest.cc1
19 files changed, 268 insertions, 197 deletions
diff --git a/net/base/ssl_config_service.h b/net/base/ssl_config_service.h
index dc48a36..0ab88b2 100644
--- a/net/base/ssl_config_service.h
+++ b/net/base/ssl_config_service.h
@@ -10,7 +10,6 @@
#include "base/observer_list.h"
#include "base/ref_counted.h"
-#include "net/base/ssl_host_info.h"
#include "net/base/x509_certificate.h"
namespace net {
diff --git a/net/base/ssl_host_info.cc b/net/base/ssl_host_info.cc
deleted file mode 100644
index 4b6c0e2..0000000
--- a/net/base/ssl_host_info.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// 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/base/ssl_host_info.h"
-
-namespace net {
-
-SSLHostInfo::~SSLHostInfo() {}
-
-SSLHostInfoFactory::~SSLHostInfoFactory() {}
-
-} // namespace net
diff --git a/net/http/disk_cache_based_ssl_host_info.cc b/net/http/disk_cache_based_ssl_host_info.cc
index f2de223..10b2e15 100644
--- a/net/http/disk_cache_based_ssl_host_info.cc
+++ b/net/http/disk_cache_based_ssl_host_info.cc
@@ -147,11 +147,12 @@ int DiskCacheBasedSSLHostInfo::WaitForDataReadyDone() {
ready_ = true;
callback = user_callback_;
user_callback_ = NULL;
- // We close the entry because, if we shutdown before ::Set is called, then we
- // might leak a cache reference, which causes a DCHECK on shutdown.
+ // We close the entry because, if we shutdown before ::Persist is called,
+ // then we might leak a cache reference, which causes a DCHECK on shutdown.
if (entry_)
entry_->Close();
entry_ = NULL;
+ Parse(data_);
if (callback)
callback->Run(OK);
@@ -172,17 +173,14 @@ int DiskCacheBasedSSLHostInfo::WaitForDataReady(CompletionCallback* callback) {
return ERR_IO_PENDING;
}
-void DiskCacheBasedSSLHostInfo::Set(const std::string& new_data) {
+void DiskCacheBasedSSLHostInfo::Persist() {
DCHECK(CalledOnValidThread());
DCHECK(state_ != GET_BACKEND);
- if (new_data.empty())
- return;
-
DCHECK(new_data_.empty());
CHECK(ready_);
DCHECK(user_callback_ == NULL);
- new_data_ = new_data;
+ new_data_ = Serialize();
if (!backend_)
return;
diff --git a/net/http/disk_cache_based_ssl_host_info.h b/net/http/disk_cache_based_ssl_host_info.h
index 5cab8ff..51a4a91 100644
--- a/net/http/disk_cache_based_ssl_host_info.h
+++ b/net/http/disk_cache_based_ssl_host_info.h
@@ -11,8 +11,8 @@
#include "base/non_thread_safe.h"
#include "base/scoped_ptr.h"
#include "net/base/completion_callback.h"
-#include "net/base/ssl_host_info.h"
#include "net/disk_cache/disk_cache.h"
+#include "net/socket/ssl_host_info.h"
namespace net {
@@ -30,8 +30,7 @@ class DiskCacheBasedSSLHostInfo : public SSLHostInfo,
// Implementation of SSLHostInfo
virtual void Start();
virtual int WaitForDataReady(CompletionCallback* callback);
- virtual const std::string& data() const { return data_; }
- virtual void Set(const std::string& new_data);
+ virtual void Persist();
private:
~DiskCacheBasedSSLHostInfo();
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index 153b5d5..eca95ef 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -24,7 +24,6 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
-#include "net/base/ssl_host_info.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/disk_cache_based_ssl_host_info.h"
#include "net/http/http_cache_transaction.h"
@@ -34,6 +33,7 @@
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
+#include "net/socket/ssl_host_info.h"
#include "net/spdy/spdy_session_pool.h"
namespace net {
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index 0d9f340..e0b9c39 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -26,7 +26,6 @@
#include "net/base/net_util.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/upload_data_stream.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler.h"
diff --git a/net/net.gyp b/net/net.gyp
index e8a32c9..f0306b1 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -173,8 +173,6 @@
'base/ssl_config_service_win.cc',
'base/ssl_config_service_win.h',
'base/ssl_false_start_blacklist.cc',
- 'base/ssl_host_info.cc',
- 'base/ssl_host_info.h',
'base/ssl_info.cc',
'base/ssl_info.h',
'base/static_cookie_policy.cc',
@@ -324,6 +322,7 @@
'../third_party/zlib/zlib.gyp:zlib',
'net_base',
'net_resources',
+ 'ssl_host_info',
],
'sources': [
'disk_cache/addr.cc',
@@ -995,6 +994,45 @@
],
},
{
+ # This is a separate target in order to limit the scope of the protobuf
+ # includes.
+ 'target_name': 'ssl_host_info',
+ 'type': '<(library)',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../third_party/protobuf/protobuf.gyp:protobuf_lite',
+ ],
+ 'sources': [
+ 'socket/ssl_host_info.proto',
+ 'socket/ssl_host_info.cc',
+ 'socket/ssl_host_info.h',
+ ],
+ 'rules': [
+ {
+ 'rule_name': 'genproto',
+ 'extension': 'proto',
+ 'inputs': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.h',
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net/socket/<(RULE_INPUT_ROOT).pb.cc',
+ ],
+ 'action': [
+ '<(PRODUCT_DIR)/<(EXECUTABLE_PREFIX)protoc<(EXECUTABLE_SUFFIX)',
+ 'socket/<(RULE_INPUT_ROOT)<(RULE_INPUT_EXT)',
+ '--cpp_out=<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
+ ],
+ 'message': 'Generating C++ code from <(RULE_INPUT_PATH)',
+ 'process_outputs_as_sources': 1,
+ },
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out/net',
+ '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
+ ],
+ },
+ {
'target_name': 'net_perftests',
'type': 'executable',
'dependencies': [
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/base/ssl_host_info.h b/net/socket/ssl_host_info.h
index ae9ac6a..8065b47 100644
--- a/net/base/ssl_host_info.h
+++ b/net/socket/ssl_host_info.h
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_BASE_SSL_HOST_INFO_H
-#define NET_BASE_SSL_HOST_INFO_H
+#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 {
@@ -17,6 +20,7 @@ namespace net {
// certificates.
class SSLHostInfo {
public:
+ SSLHostInfo();
virtual ~SSLHostInfo();
// Start will commence the lookup. This must be called before any other
@@ -36,16 +40,39 @@ class SSLHostInfo {
// but, obviously, a callback will never be made.
virtual int WaitForDataReady(CompletionCallback* callback) = 0;
- // data returns any host information once WaitForDataReady has indicated that
- // the fetch has completed. In the event of an error, |data| returns an empty
- // string.
- virtual const std::string& data() const = 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();
- // Set 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 Set(const std::string& new_data) = 0;
+ 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 {
@@ -59,4 +86,4 @@ class SSLHostInfoFactory {
} // namespace net
-#endif // NET_BASE_SSL_HOST_INFO_H
+#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 {