summaryrefslogtreecommitdiffstats
path: root/net/quic
diff options
context:
space:
mode:
authorrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-23 18:57:38 +0000
committerrch@chromium.org <rch@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-12-23 18:57:38 +0000
commiteed749f90554fcb7f561c935bcee60b8e1235de2 (patch)
tree7a4d304ebcb722ecad33ae952da8ca6475d42aa8 /net/quic
parentb7e14683a6986670c56106b743fa3bd6433a9362 (diff)
downloadchromium_src-eed749f90554fcb7f561c935bcee60b8e1235de2.zip
chromium_src-eed749f90554fcb7f561c935bcee60b8e1235de2.tar.gz
chromium_src-eed749f90554fcb7f561c935bcee60b8e1235de2.tar.bz2
Implement connection pooling in QUIC.
Review URL: https://codereview.chromium.org/105873007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@242391 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/quic')
-rw-r--r--net/quic/quic_client_session.cc29
-rw-r--r--net/quic/quic_client_session.h8
-rw-r--r--net/quic/quic_crypto_client_stream.h2
-rw-r--r--net/quic/quic_stream_factory.cc57
-rw-r--r--net/quic/quic_stream_factory.h6
-rw-r--r--net/quic/quic_stream_factory_test.cc212
-rw-r--r--net/quic/test_tools/mock_crypto_client_stream.cc18
-rw-r--r--net/quic/test_tools/mock_crypto_client_stream.h7
-rw-r--r--net/quic/test_tools/mock_crypto_client_stream_factory.cc7
-rw-r--r--net/quic/test_tools/mock_crypto_client_stream_factory.h5
10 files changed, 337 insertions, 14 deletions
diff --git a/net/quic/quic_client_session.cc b/net/quic/quic_client_session.cc
index ab70e7f..60c57de 100644
--- a/net/quic/quic_client_session.cc
+++ b/net/quic/quic_client_session.cc
@@ -277,6 +277,21 @@ int QuicClientSession::GetNumSentClientHellos() const {
return crypto_stream_->num_sent_client_hellos();
}
+bool QuicClientSession::CanPool(const std::string& hostname) const {
+ // TODO(rch): When QUIC supports channel ID or client certificates, this
+ // logic will need to be revised.
+ DCHECK(connection()->connected());
+ SSLInfo ssl_info;
+ bool unused = false;
+ DCHECK(crypto_stream_);
+ if (!crypto_stream_->GetSSLInfo(&ssl_info) || !ssl_info.cert) {
+ // We can always pool with insecure QUIC sessions.
+ return true;
+ }
+ // Only pool secure QUIC sessions if the cert matches the new hostname.
+ return ssl_info.cert->VerifyNameMatch(hostname, &unused);
+}
+
QuicDataStream* QuicClientSession::CreateIncomingDataStream(
QuicStreamId id) {
DLOG(ERROR) << "Server push not supported";
@@ -451,15 +466,25 @@ void QuicClientSession::CloseAllObservers(int net_error) {
}
}
-base::Value* QuicClientSession::GetInfoAsValue(const HostPortPair& pair) const {
+base::Value* QuicClientSession::GetInfoAsValue(
+ const std::set<HostPortProxyPair>& aliases) const {
base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetString("host_port_pair", pair.ToString());
+ // TODO(rch): remove "host_port_pair" when Chrome 34 is stable.
+ dict->SetString("host_port_pair", aliases.begin()->first.ToString());
dict->SetString("version", QuicVersionToString(connection()->version()));
dict->SetInteger("open_streams", GetNumOpenStreams());
dict->SetInteger("total_streams", num_total_streams_);
dict->SetString("peer_address", peer_address().ToString());
dict->SetString("guid", base::Uint64ToString(guid()));
dict->SetBoolean("connected", connection()->connected());
+
+ base::ListValue* alias_list = new base::ListValue();
+ for (std::set<HostPortProxyPair>::const_iterator it = aliases.begin();
+ it != aliases.end(); it++) {
+ alias_list->Append(new base::StringValue(it->first.ToString()));
+ }
+ dict->Set("aliases", alias_list);
+
return dict;
}
diff --git a/net/quic/quic_client_session.h b/net/quic/quic_client_session.h
index 07da96a..943c206 100644
--- a/net/quic/quic_client_session.h
+++ b/net/quic/quic_client_session.h
@@ -15,6 +15,7 @@
#include "base/containers/hash_tables.h"
#include "base/memory/scoped_ptr.h"
#include "net/base/completion_callback.h"
+#include "net/proxy/proxy_server.h"
#include "net/quic/quic_connection_logger.h"
#include "net/quic/quic_crypto_client_stream.h"
#include "net/quic/quic_reliable_client_stream.h"
@@ -143,7 +144,7 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
// that this session has been closed, which will delete the session.
void CloseSessionOnError(int error);
- base::Value* GetInfoAsValue(const HostPortPair& pair) const;
+ base::Value* GetInfoAsValue(const std::set<HostPortProxyPair>& aliases) const;
const BoundNetLog& net_log() const { return net_log_; }
@@ -154,6 +155,11 @@ class NET_EXPORT_PRIVATE QuicClientSession : public QuicSession {
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+ // Returns true if |hostname| may be pooled onto this session. If this
+ // is a secure QUIC session, then |hostname| must match the certificate
+ // presented during the handshake.
+ bool CanPool(const std::string& hostname) const;
+
protected:
// QuicSession methods:
virtual QuicDataStream* CreateIncomingDataStream(QuicStreamId id) OVERRIDE;
diff --git a/net/quic/quic_crypto_client_stream.h b/net/quic/quic_crypto_client_stream.h
index ca2fea7..1ca423f 100644
--- a/net/quic/quic_crypto_client_stream.h
+++ b/net/quic/quic_crypto_client_stream.h
@@ -46,7 +46,7 @@ class NET_EXPORT_PRIVATE QuicCryptoClientStream : public QuicCryptoStream {
int num_sent_client_hellos() const;
// Gets the SSL connection information.
- bool GetSSLInfo(SSLInfo* ssl_info);
+ virtual bool GetSSLInfo(SSLInfo* ssl_info);
private:
// ProofVerifierCallbackImpl is passed as the callback method to VerifyProof.
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index d68e80d..efa9fca 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -169,6 +169,13 @@ int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
return rv;
DCHECK(!factory_->HasActiveSession(host_port_proxy_pair_));
+
+ // Inform the factory of this resolution, which will set up
+ // a session alias, if possible.
+ if (factory_->OnResolution(host_port_proxy_pair_, address_list_)) {
+ return OK;
+ }
+
io_state_ = STATE_CONNECT;
return OK;
}
@@ -189,6 +196,7 @@ int QuicStreamRequest::Request(
const CompletionCallback& callback) {
DCHECK(!stream_);
DCHECK(callback_.is_null());
+ DCHECK(factory_);
int rv = factory_->Create(host_port_proxy_pair, is_https, cert_verifier,
net_log, this);
if (rv == ERR_IO_PENDING) {
@@ -244,6 +252,15 @@ int QuicStreamFactory::Job::DoConnectComplete(int rv) {
return rv;
DCHECK(!factory_->HasActiveSession(host_port_proxy_pair_));
+ // There may well now be an active session for this IP. If so, use the
+ // existing session instead.
+ AddressList address(session_->connection()->peer_address());
+ if (factory_->OnResolution(host_port_proxy_pair_, address)) {
+ session_->connection()->SendConnectionClose(QUIC_NO_ERROR);
+ session_ = NULL;
+ return OK;
+ }
+
factory_->ActivateSession(host_port_proxy_pair_, session_);
return OK;
@@ -319,6 +336,29 @@ int QuicStreamFactory::Create(const HostPortProxyPair& host_port_proxy_pair,
return rv;
}
+bool QuicStreamFactory::OnResolution(
+ const HostPortProxyPair& host_port_proxy_pair,
+ const AddressList& address_list) {
+ DCHECK(!HasActiveSession(host_port_proxy_pair));
+ for (size_t i = 0; i < address_list.size(); ++i) {
+ const IPEndPoint& address = address_list[i];
+ if (!ContainsKey(ip_aliases_, address))
+ continue;
+
+ const SessionSet& sessions = ip_aliases_[address];
+ for (SessionSet::const_iterator i = sessions.begin();
+ i != sessions.end(); ++i) {
+ QuicClientSession* session = *i;
+ if (!session->CanPool(host_port_proxy_pair.first.host()))
+ continue;
+ active_sessions_[host_port_proxy_pair] = session;
+ session_aliases_[session].insert(host_port_proxy_pair);
+ return true;
+ }
+ }
+ return false;
+}
+
void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
if (rv == OK) {
require_confirmation_ = false;
@@ -381,6 +421,11 @@ void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) {
http_server_properties_->SetBrokenAlternateProtocol(it->first);
}
}
+ IPEndPoint peer_address = session->connection()->peer_address();
+ ip_aliases_[peer_address].erase(session);
+ if (ip_aliases_[peer_address].empty()) {
+ ip_aliases_.erase(peer_address);
+ }
session_aliases_.erase(session);
}
@@ -418,9 +463,12 @@ base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
for (SessionMap::const_iterator it = active_sessions_.begin();
it != active_sessions_.end(); ++it) {
const HostPortProxyPair& pair = it->first;
- const QuicClientSession* session = it->second;
-
- list->Append(session->GetInfoAsValue(pair.first));
+ QuicClientSession* session = it->second;
+ const AliasSet& aliases = session_aliases_.find(session)->second;
+ if (pair.first.Equals(aliases.begin()->first) &&
+ pair.second == aliases.begin()->second) {
+ list->Append(session->GetInfoAsValue(aliases));
+ }
}
return list;
}
@@ -528,6 +576,9 @@ void QuicStreamFactory::ActivateSession(
DCHECK(!HasActiveSession(host_port_proxy_pair));
active_sessions_[host_port_proxy_pair] = session;
session_aliases_[session].insert(host_port_proxy_pair);
+ DCHECK(!ContainsKey(ip_aliases_[session->connection()->peer_address()],
+ session));
+ ip_aliases_[session->connection()->peer_address()].insert(session);
}
QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig(
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index 8a915b6..709cbb0 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -158,6 +158,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
typedef std::set<HostPortProxyPair> AliasSet;
typedef std::map<QuicClientSession*, AliasSet> SessionAliasMap;
typedef std::set<QuicClientSession*> SessionSet;
+ typedef std::map<IPEndPoint, SessionSet> IPAliasMap;
typedef std::map<HostPortProxyPair, QuicCryptoClientConfig*> CryptoConfigMap;
typedef std::map<HostPortPair, HostPortProxyPair> CanonicalHostMap;
typedef std::map<HostPortProxyPair, Job*> JobMap;
@@ -165,6 +166,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
typedef std::set<QuicStreamRequest*> RequestSet;
typedef std::map<Job*, RequestSet> JobRequestsMap;
+ bool OnResolution(const HostPortProxyPair& host_port_proxy_pair,
+ const AddressList& address_list);
void OnJobComplete(Job* job, int rv);
bool HasActiveSession(const HostPortProxyPair& host_port_proxy_pair);
bool HasActiveJob(const HostPortProxyPair& host_port_proxy_pair);
@@ -205,7 +208,10 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// Contains non-owning pointers to currently active session
// (not going away session, once they're implemented).
SessionMap active_sessions_;
+ // Map from session to set of aliases that this session is known by.
SessionAliasMap session_aliases_;
+ // Map from IP address to sessions which are connected to this address.
+ IPAliasMap ip_aliases_;
// Contains owning pointers to QuicCryptoClientConfig. QuicCryptoClientConfig
// contains configuration and cached state about servers.
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index 4cdea8b18f..8f3bdde 100644
--- a/net/quic/quic_stream_factory_test.cc
+++ b/net/quic/quic_stream_factory_test.cc
@@ -6,6 +6,7 @@
#include "base/run_loop.h"
#include "base/strings/string_util.h"
+#include "net/base/test_data_directory.h"
#include "net/cert/cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
@@ -21,6 +22,7 @@
#include "net/quic/test_tools/quic_test_packet_maker.h"
#include "net/quic/test_tools/quic_test_utils.h"
#include "net/socket/socket_test_util.h"
+#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::StringPiece;
@@ -187,6 +189,216 @@ TEST_P(QuicStreamFactoryTest, Create) {
EXPECT_TRUE(socket_data.at_write_eof());
}
+TEST_P(QuicStreamFactoryTest, Pooling) {
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ HostPortProxyPair server2 = HostPortProxyPair(
+ HostPortPair("mail.google.com", kDefaultServerPort),
+ host_port_proxy_pair_.second);
+
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(
+ kDefaultServerHostName, "192.168.0.1", "");
+ host_resolver_.rules()->AddIPLiteralRule(
+ "mail.google.com", "192.168.0.1", "");
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(OK, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+
+ TestCompletionCallback callback;
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(OK, request2.Request(server2, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback.callback()));
+ scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_EQ(
+ QuicStreamFactoryPeer::GetActiveSession(&factory_, host_port_proxy_pair_),
+ QuicStreamFactoryPeer::GetActiveSession(&factory_, server2));
+
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data1(reads, arraysize(reads), NULL, 0);
+ DeterministicSocketData socket_data2(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data1);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+ socket_data1.StopAfter(1);
+ socket_data2.StopAfter(1);
+
+ HostPortProxyPair server2 = HostPortProxyPair(
+ HostPortPair("mail.google.com", kDefaultServerPort),
+ host_port_proxy_pair_.second);
+
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(
+ kDefaultServerHostName, "192.168.0.1", "");
+ host_resolver_.rules()->AddIPLiteralRule(
+ "mail.google.com", "192.168.0.1", "");
+
+ QuicStreamRequest request(&factory_);
+ EXPECT_EQ(OK, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+
+ TestCompletionCallback callback;
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(OK, request2.Request(server2, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback.callback()));
+ scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ EXPECT_TRUE(stream2.get());
+
+ factory_.OnSessionGoingAway(
+ QuicStreamFactoryPeer::GetActiveSession(&factory_,
+ host_port_proxy_pair_));
+ EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(&factory_,
+ host_port_proxy_pair_));
+ EXPECT_FALSE(QuicStreamFactoryPeer::HasActiveSession(&factory_, server2));
+
+ TestCompletionCallback callback3;
+ QuicStreamRequest request3(&factory_);
+ EXPECT_EQ(OK, request3.Request(server2, is_https_,
+ cert_verifier_.get(), net_log_,
+ callback3.callback()));
+ scoped_ptr<QuicHttpStream> stream3 = request3.ReleaseStream();
+ EXPECT_TRUE(stream3.get());
+
+ EXPECT_TRUE(QuicStreamFactoryPeer::HasActiveSession(&factory_, server2));
+
+ EXPECT_TRUE(socket_data1.at_read_eof());
+ EXPECT_TRUE(socket_data1.at_write_eof());
+ EXPECT_TRUE(socket_data2.at_read_eof());
+ EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, HttpsPooling) {
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data);
+ socket_data.StopAfter(1);
+
+ HostPortProxyPair server1(HostPortPair("www.example.org", 443),
+ ProxyServer::Direct());
+ HostPortProxyPair server2(HostPortPair("mail.example.org", 443),
+ ProxyServer::Direct());
+
+ // Load a cert that is valid for:
+ // www.example.org (server1)
+ // mail.example.org (server2)
+ // www.example.com
+ base::FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> test_cert(
+ ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
+ SSLInfo ssl_info;
+ ssl_info.cert = test_cert.get();
+ crypto_client_stream_factory_.set_ssl_info(&ssl_info);
+
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(
+ server1.first.host(), "192.168.0.1", "");
+ host_resolver_.rules()->AddIPLiteralRule(
+ server2.first.host(), "192.168.0.1", "");
+
+ QuicStreamRequest request(&factory_);
+ is_https_ = true;
+ EXPECT_EQ(OK, request.Request(server1, is_https_, cert_verifier_.get(),
+ net_log_, callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+
+ TestCompletionCallback callback;
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(OK, request2.Request(server2, is_https_, cert_verifier_.get(),
+ net_log_, callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_EQ(QuicStreamFactoryPeer::GetActiveSession(&factory_, server1),
+ QuicStreamFactoryPeer::GetActiveSession(&factory_, server2));
+
+ EXPECT_TRUE(socket_data.at_read_eof());
+ EXPECT_TRUE(socket_data.at_write_eof());
+}
+
+TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithCertMismatch) {
+ MockRead reads[] = {
+ MockRead(ASYNC, OK, 0) // EOF
+ };
+ DeterministicSocketData socket_data1(reads, arraysize(reads), NULL, 0);
+ DeterministicSocketData socket_data2(reads, arraysize(reads), NULL, 0);
+ socket_factory_.AddSocketDataProvider(&socket_data1);
+ socket_factory_.AddSocketDataProvider(&socket_data2);
+ socket_data1.StopAfter(1);
+ socket_data2.StopAfter(1);
+
+ HostPortProxyPair server1(HostPortPair("www.example.org", 443),
+ ProxyServer::Direct());
+ HostPortProxyPair server2(HostPortPair("mail.google.com", 443),
+ ProxyServer::Direct());
+
+ // Load a cert that is valid for:
+ // www.example.org (server1)
+ // mail.example.org
+ // www.example.com
+ // But is not valid for mail.google.com (server2).
+ base::FilePath certs_dir = GetTestCertsDirectory();
+ scoped_refptr<X509Certificate> test_cert(
+ ImportCertFromFile(certs_dir, "spdy_pooling.pem"));
+ ASSERT_NE(static_cast<X509Certificate*>(NULL), test_cert);
+ SSLInfo ssl_info;
+ ssl_info.cert = test_cert.get();
+ crypto_client_stream_factory_.set_ssl_info(&ssl_info);
+
+ host_resolver_.set_synchronous_mode(true);
+ host_resolver_.rules()->AddIPLiteralRule(
+ server1.first.host(), "192.168.0.1", "");
+ host_resolver_.rules()->AddIPLiteralRule(
+ server2.first.host(), "192.168.0.1", "");
+
+ QuicStreamRequest request(&factory_);
+ is_https_ = true;
+ EXPECT_EQ(OK, request.Request(server1, is_https_, cert_verifier_.get(),
+ net_log_, callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream = request.ReleaseStream();
+ EXPECT_TRUE(stream.get());
+
+ TestCompletionCallback callback;
+ QuicStreamRequest request2(&factory_);
+ EXPECT_EQ(OK, request2.Request(server2, is_https_, cert_verifier_.get(),
+ net_log_, callback_.callback()));
+ scoped_ptr<QuicHttpStream> stream2 = request2.ReleaseStream();
+ EXPECT_TRUE(stream2.get());
+
+ EXPECT_NE(QuicStreamFactoryPeer::GetActiveSession(&factory_, server1),
+ QuicStreamFactoryPeer::GetActiveSession(&factory_, server2));
+
+ EXPECT_TRUE(socket_data1.at_read_eof());
+ EXPECT_TRUE(socket_data1.at_write_eof());
+ EXPECT_TRUE(socket_data2.at_read_eof());
+ EXPECT_TRUE(socket_data2.at_write_eof());
+}
+
TEST_P(QuicStreamFactoryTest, Goaway) {
MockRead reads[] = {
MockRead(ASYNC, OK, 0) // EOF
diff --git a/net/quic/test_tools/mock_crypto_client_stream.cc b/net/quic/test_tools/mock_crypto_client_stream.cc
index bfeb06f..7dd3ffe 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/quic/test_tools/mock_crypto_client_stream.h"
+#include "net/ssl/ssl_info.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
@@ -11,9 +12,11 @@ MockCryptoClientStream::MockCryptoClientStream(
const string& server_hostname,
QuicSession* session,
QuicCryptoClientConfig* crypto_config,
- HandshakeMode handshake_mode)
- : QuicCryptoClientStream(server_hostname, session, crypto_config),
- handshake_mode_(handshake_mode) {
+ HandshakeMode handshake_mode,
+ const SSLInfo* ssl_info)
+ : QuicCryptoClientStream(server_hostname, session, crypto_config),
+ handshake_mode_(handshake_mode),
+ ssl_info_(ssl_info) {
}
MockCryptoClientStream::~MockCryptoClientStream() {
@@ -51,6 +54,15 @@ bool MockCryptoClientStream::CryptoConnect() {
return true;
}
+bool MockCryptoClientStream::GetSSLInfo(SSLInfo* ssl_info) {
+ ssl_info->Reset();
+ if (!ssl_info_) {
+ return false;
+ }
+ *ssl_info = *ssl_info_;
+ return true;
+}
+
void MockCryptoClientStream::SendOnCryptoHandshakeEvent(
QuicSession::CryptoHandshakeEvent event) {
encryption_established_ = true;
diff --git a/net/quic/test_tools/mock_crypto_client_stream.h b/net/quic/test_tools/mock_crypto_client_stream.h
index ada1b68..ab393e8 100644
--- a/net/quic/test_tools/mock_crypto_client_stream.h
+++ b/net/quic/test_tools/mock_crypto_client_stream.h
@@ -37,7 +37,8 @@ class MockCryptoClientStream : public QuicCryptoClientStream {
const string& server_hostname,
QuicSession* session,
QuicCryptoClientConfig* crypto_config,
- HandshakeMode handshake_mode);
+ HandshakeMode handshake_mode,
+ const SSLInfo* ssl_info);
virtual ~MockCryptoClientStream();
// CryptoFramerVisitorInterface implementation.
@@ -47,6 +48,8 @@ class MockCryptoClientStream : public QuicCryptoClientStream {
// QuicCryptoClientStream implementation.
virtual bool CryptoConnect() OVERRIDE;
+ virtual bool GetSSLInfo(SSLInfo* ssl_info) OVERRIDE;
+
// Invokes the sessions's CryptoHandshakeEvent method with the specified
// event.
void SendOnCryptoHandshakeEvent(QuicSession::CryptoHandshakeEvent event);
@@ -55,6 +58,8 @@ class MockCryptoClientStream : public QuicCryptoClientStream {
private:
void SetConfigNegotiated();
+
+ const SSLInfo* ssl_info_;
};
} // namespace net
diff --git a/net/quic/test_tools/mock_crypto_client_stream_factory.cc b/net/quic/test_tools/mock_crypto_client_stream_factory.cc
index e54fb41..671a872 100644
--- a/net/quic/test_tools/mock_crypto_client_stream_factory.cc
+++ b/net/quic/test_tools/mock_crypto_client_stream_factory.cc
@@ -13,7 +13,8 @@ namespace net {
MockCryptoClientStreamFactory::MockCryptoClientStreamFactory()
: handshake_mode_(MockCryptoClientStream::CONFIRM_HANDSHAKE),
- last_stream_(NULL) {
+ last_stream_(NULL),
+ ssl_info_(NULL) {
}
QuicCryptoClientStream*
@@ -21,8 +22,8 @@ MockCryptoClientStreamFactory::CreateQuicCryptoClientStream(
const string& server_hostname,
QuicSession* session,
QuicCryptoClientConfig* crypto_config) {
- last_stream_ = new MockCryptoClientStream(server_hostname, session,
- crypto_config, handshake_mode_);
+ last_stream_ = new MockCryptoClientStream(
+ server_hostname, session, crypto_config, handshake_mode_, ssl_info_);
return last_stream_;
}
diff --git a/net/quic/test_tools/mock_crypto_client_stream_factory.h b/net/quic/test_tools/mock_crypto_client_stream_factory.h
index 9d056cb..94feb0b 100644
--- a/net/quic/test_tools/mock_crypto_client_stream_factory.h
+++ b/net/quic/test_tools/mock_crypto_client_stream_factory.h
@@ -29,6 +29,10 @@ class MockCryptoClientStreamFactory : public QuicCryptoClientStreamFactory {
handshake_mode_ = handshake_mode;
}
+ void set_ssl_info(const SSLInfo* ssl_info) {
+ ssl_info_ = ssl_info;
+ }
+
MockCryptoClientStream* last_stream() const {
return last_stream_;
}
@@ -36,6 +40,7 @@ class MockCryptoClientStreamFactory : public QuicCryptoClientStreamFactory {
private:
MockCryptoClientStream::HandshakeMode handshake_mode_;
MockCryptoClientStream* last_stream_;
+ const SSLInfo* ssl_info_;
};
} // namespace net