summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-10 03:57:54 +0000
committerrtenneti@chromium.org <rtenneti@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-10 03:57:54 +0000
commit6d1b4ed17cbad3f89394490b287a29108037567b (patch)
tree5ee638a15ff19160b26decc8d8a2f46f02ad9ef5 /net
parent929fb4e415bec4565b9eea7254f5ac019c7648b5 (diff)
downloadchromium_src-6d1b4ed17cbad3f89394490b287a29108037567b.zip
chromium_src-6d1b4ed17cbad3f89394490b287a29108037567b.tar.gz
chromium_src-6d1b4ed17cbad3f89394490b287a29108037567b.tar.bz2
First step at enabling QUIC over HTTPS.
- Added code to enable proof verifier and integrated CertVerifier. TODO: - Make ProofVerifier work with multiple verifications at the same time. - Use the correct NPN for NextProto instead of kProtoSPDY3. - Write unit tests for QUIC over HTTPS. R=rch@chromium.org Review URL: https://chromiumcodereview.appspot.com/18084015 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@210732 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/http/http_network_session.cc1
-rw-r--r--net/http/http_network_session.h1
-rw-r--r--net/http/http_stream_factory.cc8
-rw-r--r--net/http/http_stream_factory_impl.cc6
-rw-r--r--net/http/http_stream_factory_impl_job.cc44
-rw-r--r--net/quic/quic_crypto_client_stream.cc4
-rw-r--r--net/quic/quic_http_stream.cc2
-rw-r--r--net/quic/quic_network_transaction_unittest.cc98
-rw-r--r--net/quic/quic_session.cc10
-rw-r--r--net/quic/quic_session.h10
-rw-r--r--net/quic/quic_stream_factory.cc33
-rw-r--r--net/quic/quic_stream_factory.h21
-rw-r--r--net/quic/quic_stream_factory_test.cc33
-rw-r--r--net/socket/next_proto.h4
-rw-r--r--net/socket/ssl_client_socket.cc4
-rw-r--r--net/spdy/spdy_network_transaction_unittest.cc2
-rw-r--r--net/spdy/spdy_test_util_common.cc2
17 files changed, 183 insertions, 100 deletions
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index 7c64d1d..208e95b 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -81,6 +81,7 @@ HttpNetworkSession::Params::Params()
spdy_max_concurrent_streams_limit(0),
time_func(&base::TimeTicks::Now),
enable_quic(false),
+ enable_quic_https(false),
quic_clock(NULL),
quic_random(NULL),
enable_user_alternate_protocol_ports(false),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 3ca928e..09ced59 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -85,6 +85,7 @@ class NET_EXPORT HttpNetworkSession
SpdySessionPool::TimeFunc time_func;
std::string trusted_spdy_proxy;
bool enable_quic;
+ bool enable_quic_https;
HostPortPair origin_to_force_quic_on;
QuicClock* quic_clock; // Will be owned by QuicStreamFactory.
QuicRandom* quic_random;
diff --git a/net/http/http_stream_factory.cc b/net/http/http_stream_factory.cc
index 1c707f2..89ba518 100644
--- a/net/http/http_stream_factory.cc
+++ b/net/http/http_stream_factory.cc
@@ -143,7 +143,7 @@ void HttpStreamFactory::EnableNpnSpdy() {
set_use_alternate_protocols(true);
std::vector<std::string> next_protos;
next_protos.push_back("http/1.1");
- next_protos.push_back("quic");
+ next_protos.push_back("quic/1+spdy/3");
next_protos.push_back("spdy/2");
SetNextProtos(next_protos);
}
@@ -164,7 +164,7 @@ void HttpStreamFactory::EnableNpnSpdy3() {
set_use_alternate_protocols(true);
std::vector<std::string> next_protos;
next_protos.push_back("http/1.1");
- next_protos.push_back("quic");
+ next_protos.push_back("quic/1+spdy/3");
next_protos.push_back("spdy/2");
next_protos.push_back("spdy/3");
SetNextProtos(next_protos);
@@ -175,7 +175,7 @@ void HttpStreamFactory::EnableNpnSpdy31() {
set_use_alternate_protocols(true);
std::vector<std::string> next_protos;
next_protos.push_back("http/1.1");
- next_protos.push_back("quic");
+ next_protos.push_back("quic/1+spdy/3");
next_protos.push_back("spdy/2");
next_protos.push_back("spdy/3");
next_protos.push_back("spdy/3.1");
@@ -217,7 +217,7 @@ void HttpStreamFactory::SetNextProtos(const std::vector<std::string>& value) {
enabled_protocols_[NPN_SPDY_3_1] = true;
} else if (value[i] == "spdy/4a2") {
enabled_protocols_[NPN_SPDY_4A2] = true;
- } else if (value[i] == "quic") {
+ } else if (value[i] == "quic/1+spdy/3") {
enabled_protocols_[QUIC] = true;
}
}
diff --git a/net/http/http_stream_factory_impl.cc b/net/http/http_stream_factory_impl.cc
index 8094f4b..7ee16d8 100644
--- a/net/http/http_stream_factory_impl.cc
+++ b/net/http/http_stream_factory_impl.cc
@@ -238,8 +238,10 @@ PortAlternateProtocolPair HttpStreamFactoryImpl::GetAlternateProtocolRequestFor(
} else {
DCHECK_EQ(QUIC, alternate.protocol);
if (!session_->params().enable_quic ||
- !original_url.SchemeIs("http"))
- return kNoAlternateProtocol;
+ !(original_url.SchemeIs("http") ||
+ session_->params().enable_quic_https)) {
+ return kNoAlternateProtocol;
+ }
// TODO(rch): Figure out how to make QUIC iteract with PAC
// scripts. By not re-writing the URL, we will query the PAC script
// for the proxy to use to reach the original URL via TCP. But
diff --git a/net/http/http_stream_factory_impl_job.cc b/net/http/http_stream_factory_impl_job.cc
index b6226ae..da0b456 100644
--- a/net/http/http_stream_factory_impl_job.cc
+++ b/net/http/http_stream_factory_impl_job.cc
@@ -705,9 +705,9 @@ bool HttpStreamFactoryImpl::Job::ShouldForceSpdyWithoutSSL() const {
}
bool HttpStreamFactoryImpl::Job::ShouldForceQuic() const {
- return session_->params().enable_quic && request_info_.url.SchemeIs("http") &&
- session_->params().origin_to_force_quic_on.Equals(origin_) &&
- proxy_info_.is_direct();
+ return session_->params().enable_quic &&
+ session_->params().origin_to_force_quic_on.Equals(origin_) &&
+ proxy_info_.is_direct();
}
int HttpStreamFactoryImpl::Job::DoWaitForJob() {
@@ -746,6 +746,7 @@ int HttpStreamFactoryImpl::Job::DoInitConnection() {
next_state_ = STATE_INIT_CONNECTION_COMPLETE;
const ProxyServer& proxy_server = proxy_info_.proxy_server();
int rv = quic_request_.Request(HostPortProxyPair(origin_, proxy_server),
+ using_ssl_, session_->cert_verifier(),
net_log_, io_callback_);
if (rv != OK) {
// OK, there's no available QUIC session. Let |waiting_job_| resume
@@ -913,26 +914,33 @@ int HttpStreamFactoryImpl::Job::DoInitConnectionComplete(int result) {
connection_->is_ssl_error());
if (ssl_started && (result == OK || IsCertificateError(result))) {
- SSLClientSocket* ssl_socket =
- static_cast<SSLClientSocket*>(connection_->socket());
- if (ssl_socket->WasNpnNegotiated()) {
+ if (using_quic_ && result == OK) {
was_npn_negotiated_ = true;
- std::string proto;
- std::string server_protos;
- SSLClientSocket::NextProtoStatus status =
- ssl_socket->GetNextProto(&proto, &server_protos);
NextProto protocol_negotiated =
- SSLClientSocket::NextProtoFromString(proto);
+ SSLClientSocket::NextProtoFromString("quic/1+spdy/3");
protocol_negotiated_ = protocol_negotiated;
- net_log_.AddEvent(
- NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO,
- base::Bind(&NetLogHttpStreamProtoCallback,
- status, &proto, &server_protos));
- if (ssl_socket->was_spdy_negotiated())
+ } else {
+ SSLClientSocket* ssl_socket =
+ static_cast<SSLClientSocket*>(connection_->socket());
+ if (ssl_socket->WasNpnNegotiated()) {
+ was_npn_negotiated_ = true;
+ std::string proto;
+ std::string server_protos;
+ SSLClientSocket::NextProtoStatus status =
+ ssl_socket->GetNextProto(&proto, &server_protos);
+ NextProto protocol_negotiated =
+ SSLClientSocket::NextProtoFromString(proto);
+ protocol_negotiated_ = protocol_negotiated;
+ net_log_.AddEvent(
+ NetLog::TYPE_HTTP_STREAM_REQUEST_PROTO,
+ base::Bind(&NetLogHttpStreamProtoCallback,
+ status, &proto, &server_protos));
+ if (ssl_socket->was_spdy_negotiated())
+ SwitchToSpdyMode();
+ }
+ if (ShouldForceSpdySSL())
SwitchToSpdyMode();
}
- if (ShouldForceSpdySSL())
- SwitchToSpdyMode();
} else if (proxy_info_.is_https() && connection_->socket() &&
result == OK) {
ProxyClientSocket* proxy_socket =
diff --git a/net/quic/quic_crypto_client_stream.cc b/net/quic/quic_crypto_client_stream.cc
index 7b6eb7a..ab548b2 100644
--- a/net/quic/quic_crypto_client_stream.cc
+++ b/net/quic/quic_crypto_client_stream.cc
@@ -148,7 +148,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
return;
}
if (!cached->proof_valid()) {
- ProofVerifier* verifier = session()->proof_verifier();
+ ProofVerifier* verifier = crypto_config_->proof_verifier();
if (!verifier) {
// If no verifier is set then we don't check the certificates.
cached->SetProofValid();
@@ -160,7 +160,7 @@ void QuicCryptoClientStream::DoHandshakeLoop(
next_state_ = STATE_SEND_CHLO;
break;
case STATE_VERIFY_PROOF: {
- ProofVerifier* verifier = session()->proof_verifier();
+ ProofVerifier* verifier = crypto_config_->proof_verifier();
DCHECK(verifier);
next_state_ = STATE_VERIFY_PROOF_COMPLETE;
generation_counter_ = cached->generation_counter();
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc
index c7a5827..5976c79 100644
--- a/net/quic/quic_http_stream.cc
+++ b/net/quic/quic_http_stream.cc
@@ -48,7 +48,7 @@ int QuicHttpStream::InitializeStream(const HttpRequestInfo* request_info,
if (!stream_)
return ERR_SOCKET_NOT_CONNECTED;
- DCHECK_EQ("http", request_info->url.scheme());
+ //DCHECK_EQ("http", request_info->url.scheme());
stream_net_log_ = stream_net_log;
request_info_ = request_info;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc
index 53e69ee..69ac658 100644
--- a/net/quic/quic_network_transaction_unittest.cc
+++ b/net/quic/quic_network_transaction_unittest.cc
@@ -47,7 +47,8 @@ namespace {
// This is the expected return from a current server advertising QUIC.
static const char kQuicAlternateProtocolHttpHeader[] =
"Alternate-Protocol: 80:quic\r\n\r\n";
-
+static const char kQuicAlternateProtocolHttpsHeader[] =
+ "Alternate-Protocol: 443:quic\r\n\r\n";
} // namespace
namespace net {
@@ -151,12 +152,13 @@ class QuicNetworkTransactionTest : public PlatformTest {
}
std::string GetRequestString(const std::string& method,
+ const std::string& scheme,
const std::string& path) {
SpdyHeaderBlock headers;
headers[":method"] = method;
headers[":host"] = "www.google.com";
headers[":path"] = path;
- headers[":scheme"] = "http";
+ headers[":scheme"] = scheme;
headers[":version"] = "HTTP/1.1";
return SerializeHeaderBlock(headers);
}
@@ -333,7 +335,7 @@ TEST_F(QuicNetworkTransactionTest, ForceQuic) {
QuicStreamId stream_id = 3;
scoped_ptr<QuicEncryptedPacket> req(
ConstructDataPacket(1, stream_id, true, true, 0,
- GetRequestString("GET", "/")));
+ GetRequestString("GET", "http", "/")));
scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
MockWrite quic_writes[] = {
@@ -459,7 +461,8 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
socket_factory_.AddSocketDataProvider(&http_data);
scoped_ptr<QuicEncryptedPacket> req(
- ConstructDataPacket(1, 3, true, true, 0, GetRequestString("GET", "/")));
+ ConstructDataPacket(1, 3, true, true, 0,
+ GetRequestString("GET", "http", "/")));
scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
MockWrite quic_writes[] = {
@@ -492,6 +495,59 @@ TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuic) {
SendRequestAndExpectQuicResponse("hello!");
}
+TEST_F(QuicNetworkTransactionTest, UseAlternateProtocolForQuicForHttps) {
+ params_.origin_to_force_quic_on =
+ HostPortPair::FromString("www.google.com:443");
+ params_.enable_quic_https = true;
+ HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
+
+ MockRead http_reads[] = {
+ MockRead("HTTP/1.1 200 OK\r\n"),
+ MockRead(kQuicAlternateProtocolHttpsHeader),
+ MockRead("hello world"),
+ MockRead(SYNCHRONOUS, ERR_TEST_PEER_CLOSE_AFTER_NEXT_MOCK_READ),
+ MockRead(ASYNC, OK)
+ };
+
+ StaticSocketDataProvider http_data(http_reads, arraysize(http_reads),
+ NULL, 0);
+ socket_factory_.AddSocketDataProvider(&http_data);
+
+ scoped_ptr<QuicEncryptedPacket> req(
+ ConstructDataPacket(1, 3, true, true, 0,
+ GetRequestString("GET", "https", "/")));
+ scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
+
+ MockWrite quic_writes[] = {
+ MockWrite(SYNCHRONOUS, req->data(), req->length()),
+ MockWrite(SYNCHRONOUS, ack->data(), ack->length()),
+ };
+
+ scoped_ptr<QuicEncryptedPacket> resp(
+ ConstructDataPacket(
+ 1, 3, false, true, 0, GetResponseString("200 OK", "hello!")));
+ MockRead quic_reads[] = {
+ MockRead(SYNCHRONOUS, resp->data(), resp->length()),
+ MockRead(ASYNC, OK), // EOF
+ };
+
+ DelayedSocketData quic_data(
+ 1, // wait for one write to finish before reading.
+ quic_reads, arraysize(quic_reads),
+ quic_writes, arraysize(quic_writes));
+
+ socket_factory_.AddSocketDataProvider(&quic_data);
+
+ // The non-alternate protocol job needs to hang in order to guarantee that
+ // the alternate-protocol job will "win".
+ AddHangingNonAlternateProtocolSocketData();
+
+ CreateSession();
+
+ // TODO(rtenneti): Test QUIC over HTTPS, GetSSLInfo().
+ SendRequestAndExpectHttpResponse("hello world");
+}
+
TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
crypto_client_stream_factory_.set_handshake_mode(
@@ -551,39 +607,12 @@ TEST_F(QuicNetworkTransactionTest, HungAlternateProtocol) {
ASSERT_TRUE(!quic_data.at_write_eof());
}
-TEST_F(QuicNetworkTransactionTest, DontUseAlternateProtocolForQuicHttps) {
- HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
-
- MockRead http_reads[] = {
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Content-length: 11\r\n"),
- MockRead(kQuicAlternateProtocolHttpHeader),
- MockRead("hello world"),
-
- MockRead("HTTP/1.1 200 OK\r\n"),
- MockRead("Content-length: 6\r\n"),
- MockRead(kQuicAlternateProtocolHttpHeader),
- MockRead("hello!"),
- };
-
- StaticSocketDataProvider data(http_reads, arraysize(http_reads), NULL, 0);
- socket_factory_.AddSocketDataProvider(&data);
- SSLSocketDataProvider ssl(ASYNC, OK);
- socket_factory_.AddSSLSocketDataProvider(&ssl);
-
- request_.url = GURL("https://www.google.com/");
-
- CreateSession();
-
- SendRequestAndExpectHttpResponse("hello world");
- SendRequestAndExpectHttpResponse("hello!");
-}
-
TEST_F(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
scoped_ptr<QuicEncryptedPacket> req(
- ConstructDataPacket(1, 3, true, true, 0, GetRequestString("GET", "/")));
+ ConstructDataPacket(1, 3, true, true, 0,
+ GetRequestString("GET", "http", "/")));
scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
MockWrite quic_writes[] = {
@@ -619,7 +648,8 @@ TEST_F(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
HttpStreamFactory::EnableNpnSpdy(); // Enables QUIC too.
scoped_ptr<QuicEncryptedPacket> req(
- ConstructDataPacket(1, 3, true, true, 0, GetRequestString("GET", "/")));
+ ConstructDataPacket(1, 3, true, true, 0,
+ GetRequestString("GET", "http", "/")));
scoped_ptr<QuicEncryptedPacket> ack(ConstructAckPacket(1, 0));
MockWrite quic_writes[] = {
diff --git a/net/quic/quic_session.cc b/net/quic/quic_session.cc
index 10cad83..e3bb136 100644
--- a/net/quic/quic_session.cc
+++ b/net/quic/quic_session.cc
@@ -258,16 +258,6 @@ void QuicSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) {
}
}
-// TODO(rtenneti): Don't port proof_verifier code back to google3 until we have
-// a way to have single ProofVerifier that can handle multiple requests.
-ProofVerifier* QuicSession::proof_verifier() const {
- return proof_verifier_.get();
-}
-
-void QuicSession::set_proof_verifier(ProofVerifier* verifier) {
- proof_verifier_.reset(verifier);
-}
-
QuicConfig* QuicSession::config() {
return &config_;
}
diff --git a/net/quic/quic_session.h b/net/quic/quic_session.h
index f70ebb2..31a05fe 100644
--- a/net/quic/quic_session.h
+++ b/net/quic/quic_session.h
@@ -23,7 +23,6 @@
namespace net {
-class ProofVerifier;
class QuicCryptoStream;
class ReliableQuicStream;
class VisitorShim;
@@ -105,14 +104,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
// Servers will simply call it once with HANDSHAKE_CONFIRMED.
virtual void OnCryptoHandshakeEvent(CryptoHandshakeEvent event);
- virtual ProofVerifier* proof_verifier() const;
-
- // set_proof_verifier takes ownership of a |ProofVerifier| that clients are
- // free to use in order to verify certificate chains from servers. If a
- // ProofVerifier is set then the client will request a certificate chain from
- // the server.
- virtual void set_proof_verifier(ProofVerifier* verifier);
-
// Returns mutable config for this session. Returned config is owned
// by QuicSession.
QuicConfig* config();
@@ -223,7 +214,6 @@ class NET_EXPORT_PRIVATE QuicSession : public QuicConnectionVisitorInterface {
QuicSpdyCompressor compressor_;
QuicConfig config_;
- scoped_ptr<ProofVerifier> proof_verifier_;
// Returns the maximum number of streams this connection can open.
size_t max_open_streams_;
diff --git a/net/quic/quic_stream_factory.cc b/net/quic/quic_stream_factory.cc
index c4e695f..619c125 100644
--- a/net/quic/quic_stream_factory.cc
+++ b/net/quic/quic_stream_factory.cc
@@ -13,8 +13,10 @@
#include "base/stl_util.h"
#include "base/values.h"
#include "net/base/net_errors.h"
+#include "net/cert/cert_verifier.h"
#include "net/dns/host_resolver.h"
#include "net/dns/single_request_host_resolver.h"
+#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/quic/crypto/quic_random.h"
#include "net/quic/quic_client_session.h"
#include "net/quic/quic_clock.h"
@@ -34,6 +36,8 @@ class QuicStreamFactory::Job {
Job(QuicStreamFactory* factory,
HostResolver* host_resolver,
const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log);
~Job();
@@ -69,6 +73,8 @@ class QuicStreamFactory::Job {
QuicStreamFactory* factory_;
SingleRequestHostResolver host_resolver_;
const HostPortProxyPair host_port_proxy_pair_;
+ bool is_https_;
+ CertVerifier* cert_verifier_;
const BoundNetLog net_log_;
QuicClientSession* session_;
CompletionCallback callback_;
@@ -80,10 +86,14 @@ QuicStreamFactory::Job::Job(
QuicStreamFactory* factory,
HostResolver* host_resolver,
const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log)
: factory_(factory),
host_resolver_(host_resolver),
host_port_proxy_pair_(host_port_proxy_pair),
+ is_https_(is_https),
+ cert_verifier_(cert_verifier),
net_log_(net_log) {
}
@@ -172,13 +182,18 @@ QuicStreamRequest::~QuicStreamRequest() {
int QuicStreamRequest::Request(
const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log,
const CompletionCallback& callback) {
DCHECK(!stream_);
DCHECK(callback_.is_null());
- int rv = factory_->Create(host_port_proxy_pair, net_log, this);
+ int rv = factory_->Create(host_port_proxy_pair, is_https, cert_verifier,
+ net_log, this);
if (rv == ERR_IO_PENDING) {
host_port_proxy_pair_ = host_port_proxy_pair;
+ is_https_ = is_https;
+ cert_verifier_ = cert_verifier;
net_log_ = net_log;
callback_ = callback;
} else {
@@ -207,8 +222,8 @@ scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() {
int QuicStreamFactory::Job::DoConnect() {
io_state_ = STATE_CONNECT_COMPLETE;
- session_ = factory_->CreateSession(host_port_proxy_pair_, address_list_,
- net_log_);
+ session_ = factory_->CreateSession(host_port_proxy_pair_, is_https_,
+ cert_verifier_, address_list_, net_log_);
session_->StartReading();
int rv = session_->CryptoConnect(
base::Bind(&QuicStreamFactory::Job::OnIOComplete,
@@ -251,6 +266,8 @@ QuicStreamFactory::~QuicStreamFactory() {
}
int QuicStreamFactory::Create(const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log,
QuicStreamRequest* request) {
if (HasActiveSession(host_port_proxy_pair)) {
@@ -265,8 +282,8 @@ int QuicStreamFactory::Create(const HostPortProxyPair& host_port_proxy_pair,
return ERR_IO_PENDING;
}
- scoped_ptr<Job> job(
- new Job(this, host_resolver_, host_port_proxy_pair, net_log));
+ scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_proxy_pair,
+ is_https, cert_verifier, net_log));
int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
base::Unretained(this), job.get()));
@@ -386,6 +403,8 @@ bool QuicStreamFactory::HasActiveSession(
QuicClientSession* QuicStreamFactory::CreateSession(
const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const AddressList& address_list,
const BoundNetLog& net_log) {
QuicGuid guid = random_generator_->RandUint64();
@@ -433,6 +452,10 @@ QuicClientSession* QuicStreamFactory::CreateSession(
host_port_proxy_pair.first.host(), config_,
crypto_config, net_log.net_log());
all_sessions_.insert(session); // owning pointer
+ if (is_https) {
+ crypto_config->SetProofVerifier(
+ new ProofVerifierChromium(cert_verifier, net_log));
+ }
return session;
}
diff --git a/net/quic/quic_stream_factory.h b/net/quic/quic_stream_factory.h
index db3e7ac..963a603 100644
--- a/net/quic/quic_stream_factory.h
+++ b/net/quic/quic_stream_factory.h
@@ -22,8 +22,9 @@
namespace net {
-class HostResolver;
+class CertVerifier;
class ClientSocketFactory;
+class HostResolver;
class QuicClock;
class QuicClientSession;
class QuicCryptoClientStreamFactory;
@@ -38,7 +39,10 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
explicit QuicStreamRequest(QuicStreamFactory* factory);
~QuicStreamRequest();
+ // For http, |is_https| is false and |cert_verifier| can be null.
int Request(const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log,
const CompletionCallback& callback);
@@ -55,6 +59,8 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
private:
QuicStreamFactory* factory_;
HostPortProxyPair host_port_proxy_pair_;
+ bool is_https_;
+ CertVerifier* cert_verifier_;
BoundNetLog net_log_;
CompletionCallback callback_;
scoped_ptr<QuicHttpStream> stream_;
@@ -76,10 +82,15 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
virtual ~QuicStreamFactory();
// Creates a new QuicHttpStream to |host_port_proxy_pair| which will be
- // owned by |request|. If a matching session already exists, this
- // method will return OK. If no matching session exists, this will
- // return ERR_IO_PENDING and will invoke OnRequestComplete asynchronously.
+ // owned by |request|. |is_https| specifies if the protocol is https or not.
+ // |cert_verifier| is used by ProofVerifier for verifying the certificate
+ // chain and signature. For http, this can be null. If a matching session
+ // already exists, this method will return OK. If no matching session exists,
+ // this will return ERR_IO_PENDING and will invoke OnRequestComplete
+ // asynchronously.
int Create(const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const BoundNetLog& net_log,
QuicStreamRequest* request);
@@ -127,6 +138,8 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
bool HasActiveJob(const HostPortProxyPair& host_port_proxy_pair);
QuicClientSession* CreateSession(
const HostPortProxyPair& host_port_proxy_pair,
+ bool is_https,
+ CertVerifier* cert_verifier,
const AddressList& address_list,
const BoundNetLog& net_log);
void ActivateSession(const HostPortProxyPair& host_port_proxy_pair,
diff --git a/net/quic/quic_stream_factory_test.cc b/net/quic/quic_stream_factory_test.cc
index afa8bf6..8fdc27b 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/cert/cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -31,7 +32,9 @@ class QuicStreamFactoryTest : public ::testing::Test {
&crypto_client_stream_factory_,
&random_generator_, clock_),
host_port_proxy_pair_(HostPortPair("www.google.com", 443),
- ProxyServer::Direct()) {
+ ProxyServer::Direct()),
+ is_https_(false),
+ cert_verifier_(CertVerifier::CreateDefault()) {
}
scoped_ptr<QuicEncryptedPacket> ConstructRstPacket(
@@ -119,6 +122,8 @@ class QuicStreamFactoryTest : public ::testing::Test {
MockClock* clock_; // Owned by factory_.
QuicStreamFactory factory_;
HostPortProxyPair host_port_proxy_pair_;
+ bool is_https_;
+ CertVerifier* cert_verifier_;
BoundNetLog net_log_;
TestCompletionCallback callback_;
};
@@ -137,7 +142,8 @@ TEST_F(QuicStreamFactoryTest, Create) {
socket_data.StopAfter(1);
QuicStreamRequest request(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
@@ -148,8 +154,11 @@ TEST_F(QuicStreamFactoryTest, Create) {
stream = factory_.CreateIfSessionExists(host_port_proxy_pair_, net_log_);
EXPECT_TRUE(stream.get());
+ // TODO(rtenneti): We should probably have a tests that HTTP and HTTPS result
+ // in streams on different sessions.
QuicStreamRequest request2(&factory_);
- EXPECT_EQ(OK, request2.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(OK, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
stream = request2.ReleaseStream(); // Will reset stream 5.
stream.reset(); // Will reset stream 7.
@@ -165,7 +174,8 @@ TEST_F(QuicStreamFactoryTest, CreateError) {
host_resolver_.rules()->AddSimulatedFailure("www.google.com");
QuicStreamRequest request(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(ERR_NAME_NOT_RESOLVED, callback_.WaitForResult());
@@ -182,7 +192,8 @@ TEST_F(QuicStreamFactoryTest, CancelCreate) {
socket_factory_.AddSocketDataProvider(&socket_data);
{
QuicStreamRequest request(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
}
@@ -215,7 +226,8 @@ TEST_F(QuicStreamFactoryTest, CloseAllSessions) {
socket_data2.StopAfter(1);
QuicStreamRequest request(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
@@ -230,7 +242,8 @@ TEST_F(QuicStreamFactoryTest, CloseAllSessions) {
// a new session.
QuicStreamRequest request2(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
@@ -259,7 +272,8 @@ TEST_F(QuicStreamFactoryTest, OnIPAddressChanged) {
socket_data2.StopAfter(1);
QuicStreamRequest request(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
@@ -274,7 +288,8 @@ TEST_F(QuicStreamFactoryTest, OnIPAddressChanged) {
// a new session.
QuicStreamRequest request2(&factory_);
- EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, net_log_,
+ EXPECT_EQ(ERR_IO_PENDING, request2.Request(host_port_proxy_pair_, is_https_,
+ cert_verifier_, net_log_,
callback_.callback()));
EXPECT_EQ(OK, callback_.WaitForResult());
diff --git a/net/socket/next_proto.h b/net/socket/next_proto.h
index f9c1659..00cec80 100644
--- a/net/socket/next_proto.h
+++ b/net/socket/next_proto.h
@@ -27,7 +27,9 @@ enum NextProto {
kProtoSPDY4a2 = 7,
kProtoSPDYMaximumVersion = kProtoSPDY4a2,
- kProtoMaximumVersion = kProtoSPDYMaximumVersion,
+ kProtoQUIC1SPDY3 = 8,
+
+ kProtoMaximumVersion = kProtoQUIC1SPDY3,
};
} // namespace net
diff --git a/net/socket/ssl_client_socket.cc b/net/socket/ssl_client_socket.cc
index 2b73a1b..70b2a87 100644
--- a/net/socket/ssl_client_socket.cc
+++ b/net/socket/ssl_client_socket.cc
@@ -30,6 +30,8 @@ NextProto SSLClientSocket::NextProtoFromString(
return kProtoSPDY31;
} else if (proto_string == "spdy/4a2") {
return kProtoSPDY4a2;
+ } else if (proto_string == "quic/1+spdy/3") {
+ return kProtoQUIC1SPDY3;
} else {
return kProtoUnknown;
}
@@ -50,6 +52,8 @@ const char* SSLClientSocket::NextProtoToString(NextProto next_proto) {
return "spdy/3.1";
case kProtoSPDY4a2:
return "spdy/4a2";
+ case kProtoQUIC1SPDY3:
+ return "quic/1+spdy/3";
default:
break;
}
diff --git a/net/spdy/spdy_network_transaction_unittest.cc b/net/spdy/spdy_network_transaction_unittest.cc
index e0e9cfc..db1dc7d 100644
--- a/net/spdy/spdy_network_transaction_unittest.cc
+++ b/net/spdy/spdy_network_transaction_unittest.cc
@@ -71,6 +71,8 @@ HttpResponseInfo::ConnectionInfo NextProtoToConnectionInfo(
return HttpResponseInfo::CONNECTION_INFO_SPDY3;
case kProtoSPDY4a2:
return HttpResponseInfo::CONNECTION_INFO_SPDY4;
+ case kProtoQUIC1SPDY3:
+ return HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3;
case kProtoUnknown:
case kProtoHTTP11:
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 54982b9..1574c87 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -690,6 +690,8 @@ AlternateProtocol AlternateProtocolFromNextProto(NextProto next_proto) {
return NPN_SPDY_3_1;
case kProtoSPDY4a2:
return NPN_SPDY_4A2;
+ case kProtoQUIC1SPDY3:
+ return QUIC;
case kProtoUnknown:
case kProtoHTTP11: