Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(617)

Side by Side Diff: net/quic/quic_stream_factory.cc

Issue 190063008: Include the scheme in the key for QUIC the session map. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: net-internals Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/quic_stream_factory.h" 5 #include "net/quic/quic_stream_factory.h"
6 6
7 #include <set> 7 #include <set>
8 8
9 #include "base/message_loop/message_loop.h" 9 #include "base/message_loop/message_loop.h"
10 #include "base/message_loop/message_loop_proxy.h" 10 #include "base/message_loop/message_loop_proxy.h"
(...skipping 20 matching lines...) Expand all
31 #include "net/quic/quic_default_packet_writer.h" 31 #include "net/quic/quic_default_packet_writer.h"
32 #include "net/quic/quic_http_stream.h" 32 #include "net/quic/quic_http_stream.h"
33 #include "net/quic/quic_protocol.h" 33 #include "net/quic/quic_protocol.h"
34 #include "net/socket/client_socket_factory.h" 34 #include "net/socket/client_socket_factory.h"
35 35
36 using std::string; 36 using std::string;
37 using std::vector; 37 using std::vector;
38 38
39 namespace net { 39 namespace net {
40 40
41 QuicStreamFactory::SessionKey::SessionKey() {}
42
43 QuicStreamFactory::SessionKey::SessionKey(
44 HostPortProxyPair host_port_proxy_pair,
45 bool is_https)
46 : host_port_proxy_pair(host_port_proxy_pair),
47 is_https(is_https) {}
48
49 QuicStreamFactory::SessionKey::~SessionKey() {}
50
51 bool QuicStreamFactory::SessionKey::operator<(
52 const QuicStreamFactory::SessionKey &other) const {
53 if (!host_port_proxy_pair.first.Equals(other.host_port_proxy_pair.first)) {
54 return host_port_proxy_pair.first < other.host_port_proxy_pair.first;
55 }
56 if (!(host_port_proxy_pair.second == other.host_port_proxy_pair.second)) {
57 return host_port_proxy_pair.second < other.host_port_proxy_pair.second;
58 }
59 return is_https < other.is_https;
60 }
61
62 bool QuicStreamFactory::SessionKey::operator==(
63 const QuicStreamFactory::SessionKey& other) const {
64 return is_https == other.is_https &&
65 host_port_proxy_pair.second == other.host_port_proxy_pair.second &&
66 host_port_proxy_pair.first.Equals(other.host_port_proxy_pair.first);
67 };
68
69 QuicStreamFactory::IpAliasKey::IpAliasKey() {}
70
71 QuicStreamFactory::IpAliasKey::IpAliasKey(IPEndPoint ip_endpoint,
72 bool is_https)
73 : ip_endpoint(ip_endpoint),
74 is_https(is_https) {}
75
76 QuicStreamFactory::IpAliasKey::~IpAliasKey() {}
77
78 bool QuicStreamFactory::IpAliasKey::operator<(
79 const QuicStreamFactory::IpAliasKey& other) const {
80 if (!(ip_endpoint == other.ip_endpoint)) {
81 return ip_endpoint < other.ip_endpoint;
82 }
83 return is_https < other.is_https;
84 }
85
86 bool QuicStreamFactory::IpAliasKey::operator==(
87 const QuicStreamFactory::IpAliasKey& other) const {
88 return is_https == other.is_https &&
89 ip_endpoint == other.ip_endpoint;
90 };
91
41 // Responsible for creating a new QUIC session to the specified server, and 92 // Responsible for creating a new QUIC session to the specified server, and
42 // for notifying any associated requests when complete. 93 // for notifying any associated requests when complete.
43 class QuicStreamFactory::Job { 94 class QuicStreamFactory::Job {
44 public: 95 public:
45 Job(QuicStreamFactory* factory, 96 Job(QuicStreamFactory* factory,
46 HostResolver* host_resolver, 97 HostResolver* host_resolver,
47 const HostPortProxyPair& host_port_proxy_pair, 98 const HostPortProxyPair& host_port_proxy_pair,
48 bool is_https, 99 bool is_https,
49 base::StringPiece method, 100 base::StringPiece method,
50 CertVerifier* cert_verifier, 101 CertVerifier* cert_verifier,
51 const BoundNetLog& net_log); 102 const BoundNetLog& net_log);
52 103
53 ~Job(); 104 ~Job();
54 105
55 int Run(const CompletionCallback& callback); 106 int Run(const CompletionCallback& callback);
56 107
57 int DoLoop(int rv); 108 int DoLoop(int rv);
58 int DoResolveHost(); 109 int DoResolveHost();
59 int DoResolveHostComplete(int rv); 110 int DoResolveHostComplete(int rv);
60 int DoConnect(); 111 int DoConnect();
61 int DoConnectComplete(int rv); 112 int DoConnectComplete(int rv);
62 113
63 void OnIOComplete(int rv); 114 void OnIOComplete(int rv);
64 115
65 CompletionCallback callback() { 116 CompletionCallback callback() {
66 return callback_; 117 return callback_;
67 } 118 }
68 119
69 const HostPortProxyPair& host_port_proxy_pair() const { 120 const SessionKey session_key() const {
70 return host_port_proxy_pair_; 121 return session_key_;
71 } 122 }
72 123
73 private: 124 private:
74 enum IoState { 125 enum IoState {
75 STATE_NONE, 126 STATE_NONE,
76 STATE_RESOLVE_HOST, 127 STATE_RESOLVE_HOST,
77 STATE_RESOLVE_HOST_COMPLETE, 128 STATE_RESOLVE_HOST_COMPLETE,
78 STATE_CONNECT, 129 STATE_CONNECT,
79 STATE_CONNECT_COMPLETE, 130 STATE_CONNECT_COMPLETE,
80 }; 131 };
81 IoState io_state_; 132 IoState io_state_;
82 133
83 QuicStreamFactory* factory_; 134 QuicStreamFactory* factory_;
84 SingleRequestHostResolver host_resolver_; 135 SingleRequestHostResolver host_resolver_;
85 const HostPortProxyPair host_port_proxy_pair_;
86 bool is_https_; 136 bool is_https_;
137 SessionKey session_key_;
87 bool is_post_; 138 bool is_post_;
88 CertVerifier* cert_verifier_; 139 CertVerifier* cert_verifier_;
89 const BoundNetLog net_log_; 140 const BoundNetLog net_log_;
90 QuicClientSession* session_; 141 QuicClientSession* session_;
91 CompletionCallback callback_; 142 CompletionCallback callback_;
92 AddressList address_list_; 143 AddressList address_list_;
93 DISALLOW_COPY_AND_ASSIGN(Job); 144 DISALLOW_COPY_AND_ASSIGN(Job);
94 }; 145 };
95 146
96 QuicStreamFactory::Job::Job(QuicStreamFactory* factory, 147 QuicStreamFactory::Job::Job(QuicStreamFactory* factory,
97 HostResolver* host_resolver, 148 HostResolver* host_resolver,
98 const HostPortProxyPair& host_port_proxy_pair, 149 const HostPortProxyPair& host_port_proxy_pair,
99 bool is_https, 150 bool is_https,
100 base::StringPiece method, 151 base::StringPiece method,
101 CertVerifier* cert_verifier, 152 CertVerifier* cert_verifier,
102 const BoundNetLog& net_log) 153 const BoundNetLog& net_log)
103 : factory_(factory), 154 : factory_(factory),
104 host_resolver_(host_resolver), 155 host_resolver_(host_resolver),
105 host_port_proxy_pair_(host_port_proxy_pair),
106 is_https_(is_https), 156 is_https_(is_https),
157 session_key_(host_port_proxy_pair, is_https),
107 is_post_(method == "POST"), 158 is_post_(method == "POST"),
108 cert_verifier_(cert_verifier), 159 cert_verifier_(cert_verifier),
109 net_log_(net_log), 160 net_log_(net_log),
110 session_(NULL) {} 161 session_(NULL) {}
111 162
112 QuicStreamFactory::Job::~Job() { 163 QuicStreamFactory::Job::~Job() {
113 } 164 }
114 165
115 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) { 166 int QuicStreamFactory::Job::Run(const CompletionCallback& callback) {
116 io_state_ = STATE_RESOLVE_HOST; 167 io_state_ = STATE_RESOLVE_HOST;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 rv = DoLoop(rv); 203 rv = DoLoop(rv);
153 204
154 if (rv != ERR_IO_PENDING && !callback_.is_null()) { 205 if (rv != ERR_IO_PENDING && !callback_.is_null()) {
155 callback_.Run(rv); 206 callback_.Run(rv);
156 } 207 }
157 } 208 }
158 209
159 int QuicStreamFactory::Job::DoResolveHost() { 210 int QuicStreamFactory::Job::DoResolveHost() {
160 io_state_ = STATE_RESOLVE_HOST_COMPLETE; 211 io_state_ = STATE_RESOLVE_HOST_COMPLETE;
161 return host_resolver_.Resolve( 212 return host_resolver_.Resolve(
162 HostResolver::RequestInfo(host_port_proxy_pair_.first), 213 HostResolver::RequestInfo(session_key_.host_port_proxy_pair.first),
163 DEFAULT_PRIORITY, 214 DEFAULT_PRIORITY,
164 &address_list_, 215 &address_list_,
165 base::Bind(&QuicStreamFactory::Job::OnIOComplete, base::Unretained(this)), 216 base::Bind(&QuicStreamFactory::Job::OnIOComplete, base::Unretained(this)),
166 net_log_); 217 net_log_);
167 } 218 }
168 219
169 int QuicStreamFactory::Job::DoResolveHostComplete(int rv) { 220 int QuicStreamFactory::Job::DoResolveHostComplete(int rv) {
170 if (rv != OK) 221 if (rv != OK)
171 return rv; 222 return rv;
172 223
173 DCHECK(!factory_->HasActiveSession(host_port_proxy_pair_)); 224 DCHECK(!factory_->HasActiveSession(session_key_));
174 225
175 // Inform the factory of this resolution, which will set up 226 // Inform the factory of this resolution, which will set up
176 // a session alias, if possible. 227 // a session alias, if possible.
177 if (factory_->OnResolution(host_port_proxy_pair_, address_list_)) { 228 if (factory_->OnResolution(session_key_, address_list_)) {
178 return OK; 229 return OK;
179 } 230 }
180 231
181 io_state_ = STATE_CONNECT; 232 io_state_ = STATE_CONNECT;
182 return OK; 233 return OK;
183 } 234 }
184 235
185 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory) 236 QuicStreamRequest::QuicStreamRequest(QuicStreamFactory* factory)
186 : factory_(factory) {} 237 : factory_(factory) {}
187 238
188 QuicStreamRequest::~QuicStreamRequest() { 239 QuicStreamRequest::~QuicStreamRequest() {
189 if (factory_ && !callback_.is_null()) 240 if (factory_ && !callback_.is_null())
190 factory_->CancelRequest(this); 241 factory_->CancelRequest(this);
191 } 242 }
192 243
193 int QuicStreamRequest::Request(const HostPortProxyPair& host_port_proxy_pair, 244 int QuicStreamRequest::Request(const HostPortProxyPair& host_port_proxy_pair,
194 bool is_https, 245 bool is_https,
195 base::StringPiece method, 246 base::StringPiece method,
196 CertVerifier* cert_verifier, 247 CertVerifier* cert_verifier,
197 const BoundNetLog& net_log, 248 const BoundNetLog& net_log,
198 const CompletionCallback& callback) { 249 const CompletionCallback& callback) {
199 DCHECK(!stream_); 250 DCHECK(!stream_);
200 DCHECK(callback_.is_null()); 251 DCHECK(callback_.is_null());
201 DCHECK(factory_); 252 DCHECK(factory_);
202 int rv = factory_->Create( 253 int rv = factory_->Create(host_port_proxy_pair, is_https,
203 host_port_proxy_pair, is_https, method, cert_verifier, net_log, this); 254 method, cert_verifier, net_log, this);
204 if (rv == ERR_IO_PENDING) { 255 if (rv == ERR_IO_PENDING) {
205 host_port_proxy_pair_ = host_port_proxy_pair; 256 host_port_proxy_pair_ = host_port_proxy_pair;
206 is_https_ = is_https; 257 is_https_ = is_https;
207 cert_verifier_ = cert_verifier; 258 cert_verifier_ = cert_verifier;
208 net_log_ = net_log; 259 net_log_ = net_log;
209 callback_ = callback; 260 callback_ = callback;
210 } else { 261 } else {
211 factory_ = NULL; 262 factory_ = NULL;
212 } 263 }
213 if (rv == OK) 264 if (rv == OK)
(...skipping 12 matching lines...) Expand all
226 } 277 }
227 278
228 scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() { 279 scoped_ptr<QuicHttpStream> QuicStreamRequest::ReleaseStream() {
229 DCHECK(stream_); 280 DCHECK(stream_);
230 return stream_.Pass(); 281 return stream_.Pass();
231 } 282 }
232 283
233 int QuicStreamFactory::Job::DoConnect() { 284 int QuicStreamFactory::Job::DoConnect() {
234 io_state_ = STATE_CONNECT_COMPLETE; 285 io_state_ = STATE_CONNECT_COMPLETE;
235 286
236 int rv = factory_->CreateSession(host_port_proxy_pair_, is_https_, 287 int rv = factory_->CreateSession(session_key_.host_port_proxy_pair, is_https_,
237 cert_verifier_, address_list_, net_log_, &session_); 288 cert_verifier_, address_list_, net_log_, &session_);
238 if (rv != OK) { 289 if (rv != OK) {
239 DCHECK(rv != ERR_IO_PENDING); 290 DCHECK(rv != ERR_IO_PENDING);
240 DCHECK(!session_); 291 DCHECK(!session_);
241 return rv; 292 return rv;
242 } 293 }
243 294
244 session_->StartReading(); 295 session_->StartReading();
245 if (!session_->connection()->connected()) { 296 if (!session_->connection()->connected()) {
246 return ERR_QUIC_PROTOCOL_ERROR; 297 return ERR_QUIC_PROTOCOL_ERROR;
247 } 298 }
248 rv = session_->CryptoConnect( 299 rv = session_->CryptoConnect(
249 factory_->require_confirmation() || is_https_, 300 factory_->require_confirmation() || is_https_,
250 base::Bind(&QuicStreamFactory::Job::OnIOComplete, 301 base::Bind(&QuicStreamFactory::Job::OnIOComplete,
251 base::Unretained(this))); 302 base::Unretained(this)));
252 return rv; 303 return rv;
253 } 304 }
254 305
255 int QuicStreamFactory::Job::DoConnectComplete(int rv) { 306 int QuicStreamFactory::Job::DoConnectComplete(int rv) {
256 if (rv != OK) 307 if (rv != OK)
257 return rv; 308 return rv;
258 309
259 DCHECK(!factory_->HasActiveSession(host_port_proxy_pair_)); 310 DCHECK(!factory_->HasActiveSession(session_key_));
260 // There may well now be an active session for this IP. If so, use the 311 // There may well now be an active session for this IP. If so, use the
261 // existing session instead. 312 // existing session instead.
262 AddressList address(session_->connection()->peer_address()); 313 AddressList address(session_->connection()->peer_address());
263 if (factory_->OnResolution(host_port_proxy_pair_, address)) { 314 if (factory_->OnResolution(session_key_, address)) {
264 session_->connection()->SendConnectionClose(QUIC_NO_ERROR); 315 session_->connection()->SendConnectionClose(QUIC_NO_ERROR);
265 session_ = NULL; 316 session_ = NULL;
266 return OK; 317 return OK;
267 } 318 }
268 319
269 factory_->ActivateSession(host_port_proxy_pair_, session_); 320 factory_->ActivateSession(session_key_, session_);
270 321
271 return OK; 322 return OK;
272 } 323 }
273 324
274 QuicStreamFactory::QuicStreamFactory( 325 QuicStreamFactory::QuicStreamFactory(
275 HostResolver* host_resolver, 326 HostResolver* host_resolver,
276 ClientSocketFactory* client_socket_factory, 327 ClientSocketFactory* client_socket_factory,
277 base::WeakPtr<HttpServerProperties> http_server_properties, 328 base::WeakPtr<HttpServerProperties> http_server_properties,
278 QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory, 329 QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory,
279 QuicRandom* random_generator, 330 QuicRandom* random_generator,
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 STLDeleteValues(&active_jobs_); 363 STLDeleteValues(&active_jobs_);
313 STLDeleteValues(&all_crypto_configs_); 364 STLDeleteValues(&all_crypto_configs_);
314 } 365 }
315 366
316 int QuicStreamFactory::Create(const HostPortProxyPair& host_port_proxy_pair, 367 int QuicStreamFactory::Create(const HostPortProxyPair& host_port_proxy_pair,
317 bool is_https, 368 bool is_https,
318 base::StringPiece method, 369 base::StringPiece method,
319 CertVerifier* cert_verifier, 370 CertVerifier* cert_verifier,
320 const BoundNetLog& net_log, 371 const BoundNetLog& net_log,
321 QuicStreamRequest* request) { 372 QuicStreamRequest* request) {
322 if (HasActiveSession(host_port_proxy_pair)) { 373 SessionKey session_key(host_port_proxy_pair, is_https);
323 request->set_stream(CreateIfSessionExists(host_port_proxy_pair, net_log)); 374 if (HasActiveSession(session_key)) {
375 request->set_stream(CreateIfSessionExists(session_key, net_log));
324 return OK; 376 return OK;
325 } 377 }
326 378
327 if (HasActiveJob(host_port_proxy_pair)) { 379 if (HasActiveJob(session_key)) {
328 Job* job = active_jobs_[host_port_proxy_pair]; 380 Job* job = active_jobs_[session_key];
329 active_requests_[request] = job; 381 active_requests_[request] = job;
330 job_requests_map_[job].insert(request); 382 job_requests_map_[job].insert(request);
331 return ERR_IO_PENDING; 383 return ERR_IO_PENDING;
332 } 384 }
333 385
334 // Create crypto config and start the process of loading QUIC server 386 // Create crypto config and start the process of loading QUIC server
335 // information from disk cache. 387 // information from disk cache.
336 QuicCryptoClientConfig* crypto_config = 388 QuicCryptoClientConfig* crypto_config = GetOrCreateCryptoConfig(session_key);
337 GetOrCreateCryptoConfig(host_port_proxy_pair);
338 DCHECK(crypto_config); 389 DCHECK(crypto_config);
339 390
340 scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_proxy_pair, 391 scoped_ptr<Job> job(new Job(this, host_resolver_, host_port_proxy_pair,
341 is_https, method, cert_verifier, net_log)); 392 is_https, method, cert_verifier, net_log));
342 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete, 393 int rv = job->Run(base::Bind(&QuicStreamFactory::OnJobComplete,
343 base::Unretained(this), job.get())); 394 base::Unretained(this), job.get()));
344 395
345 if (rv == ERR_IO_PENDING) { 396 if (rv == ERR_IO_PENDING) {
346 active_requests_[request] = job.get(); 397 active_requests_[request] = job.get();
347 job_requests_map_[job.get()].insert(request); 398 job_requests_map_[job.get()].insert(request);
348 active_jobs_[host_port_proxy_pair] = job.release(); 399 active_jobs_[session_key] = job.release();
349 } 400 }
350 if (rv == OK) { 401 if (rv == OK) {
351 DCHECK(HasActiveSession(host_port_proxy_pair)); 402 DCHECK(HasActiveSession(session_key));
352 request->set_stream(CreateIfSessionExists(host_port_proxy_pair, net_log)); 403 request->set_stream(CreateIfSessionExists(session_key, net_log));
353 } 404 }
354 return rv; 405 return rv;
355 } 406 }
356 407
357 bool QuicStreamFactory::OnResolution( 408 bool QuicStreamFactory::OnResolution(
358 const HostPortProxyPair& host_port_proxy_pair, 409 const SessionKey& session_key,
359 const AddressList& address_list) { 410 const AddressList& address_list) {
360 DCHECK(!HasActiveSession(host_port_proxy_pair)); 411 DCHECK(!HasActiveSession(session_key));
361 for (size_t i = 0; i < address_list.size(); ++i) { 412 for (size_t i = 0; i < address_list.size(); ++i) {
362 const IPEndPoint& address = address_list[i]; 413 const IPEndPoint& address = address_list[i];
363 if (!ContainsKey(ip_aliases_, address)) 414 const IpAliasKey ip_alias_key(address, session_key.is_https);
415 if (!ContainsKey(ip_aliases_, ip_alias_key))
364 continue; 416 continue;
365 417
366 const SessionSet& sessions = ip_aliases_[address]; 418 const SessionSet& sessions = ip_aliases_[ip_alias_key];
367 for (SessionSet::const_iterator i = sessions.begin(); 419 for (SessionSet::const_iterator i = sessions.begin();
368 i != sessions.end(); ++i) { 420 i != sessions.end(); ++i) {
369 QuicClientSession* session = *i; 421 QuicClientSession* session = *i;
370 if (!session->CanPool(host_port_proxy_pair.first.host())) 422 if (!session->CanPool(session_key.host_port_proxy_pair.first.host()))
371 continue; 423 continue;
372 active_sessions_[host_port_proxy_pair] = session; 424 active_sessions_[session_key] = session;
373 session_aliases_[session].insert(host_port_proxy_pair); 425 session_aliases_[session].insert(session_key);
374 return true; 426 return true;
375 } 427 }
376 } 428 }
377 return false; 429 return false;
378 } 430 }
379 431
380 void QuicStreamFactory::OnJobComplete(Job* job, int rv) { 432 void QuicStreamFactory::OnJobComplete(Job* job, int rv) {
381 if (rv == OK) { 433 if (rv == OK) {
382 require_confirmation_ = false; 434 require_confirmation_ = false;
383 435
384 // Create all the streams, but do not notify them yet. 436 // Create all the streams, but do not notify them yet.
385 for (RequestSet::iterator it = job_requests_map_[job].begin(); 437 for (RequestSet::iterator it = job_requests_map_[job].begin();
386 it != job_requests_map_[job].end() ; ++it) { 438 it != job_requests_map_[job].end() ; ++it) {
387 DCHECK(HasActiveSession(job->host_port_proxy_pair())); 439 DCHECK(HasActiveSession(job->session_key()));
388 (*it)->set_stream(CreateIfSessionExists(job->host_port_proxy_pair(), 440 (*it)->set_stream(CreateIfSessionExists(job->session_key(),
389 (*it)->net_log())); 441 (*it)->net_log()));
390 } 442 }
391 } 443 }
392 while (!job_requests_map_[job].empty()) { 444 while (!job_requests_map_[job].empty()) {
393 RequestSet::iterator it = job_requests_map_[job].begin(); 445 RequestSet::iterator it = job_requests_map_[job].begin();
394 QuicStreamRequest* request = *it; 446 QuicStreamRequest* request = *it;
395 job_requests_map_[job].erase(it); 447 job_requests_map_[job].erase(it);
396 active_requests_.erase(request); 448 active_requests_.erase(request);
397 // Even though we're invoking callbacks here, we don't need to worry 449 // Even though we're invoking callbacks here, we don't need to worry
398 // about |this| being deleted, because the factory is owned by the 450 // about |this| being deleted, because the factory is owned by the
399 // profile which can not be deleted via callbacks. 451 // profile which can not be deleted via callbacks.
400 request->OnRequestComplete(rv); 452 request->OnRequestComplete(rv);
401 } 453 }
402 active_jobs_.erase(job->host_port_proxy_pair()); 454 active_jobs_.erase(job->session_key());
403 job_requests_map_.erase(job); 455 job_requests_map_.erase(job);
404 delete job; 456 delete job;
405 return; 457 return;
406 } 458 }
407 459
408 // Returns a newly created QuicHttpStream owned by the caller, if a 460 // Returns a newly created QuicHttpStream owned by the caller, if a
409 // matching session already exists. Returns NULL otherwise. 461 // matching session already exists. Returns NULL otherwise.
410 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists( 462 scoped_ptr<QuicHttpStream> QuicStreamFactory::CreateIfSessionExists(
411 const HostPortProxyPair& host_port_proxy_pair, 463 const SessionKey& session_key,
412 const BoundNetLog& net_log) { 464 const BoundNetLog& net_log) {
413 if (!HasActiveSession(host_port_proxy_pair)) { 465 if (!HasActiveSession(session_key)) {
414 DVLOG(1) << "No active session"; 466 DVLOG(1) << "No active session";
415 return scoped_ptr<QuicHttpStream>(); 467 return scoped_ptr<QuicHttpStream>();
416 } 468 }
417 469
418 QuicClientSession* session = active_sessions_[host_port_proxy_pair]; 470 QuicClientSession* session = active_sessions_[session_key];
419 DCHECK(session); 471 DCHECK(session);
420 return scoped_ptr<QuicHttpStream>( 472 return scoped_ptr<QuicHttpStream>(
421 new QuicHttpStream(session->GetWeakPtr())); 473 new QuicHttpStream(session->GetWeakPtr()));
422 } 474 }
423 475
424 void QuicStreamFactory::OnIdleSession(QuicClientSession* session) { 476 void QuicStreamFactory::OnIdleSession(QuicClientSession* session) {
425 } 477 }
426 478
427 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) { 479 void QuicStreamFactory::OnSessionGoingAway(QuicClientSession* session) {
428 const AliasSet& aliases = session_aliases_[session]; 480 const AliasSet& aliases = session_aliases_[session];
429 for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end(); 481 for (AliasSet::const_iterator it = aliases.begin(); it != aliases.end();
430 ++it) { 482 ++it) {
431 DCHECK(active_sessions_.count(*it)); 483 DCHECK(active_sessions_.count(*it));
432 DCHECK_EQ(session, active_sessions_[*it]); 484 DCHECK_EQ(session, active_sessions_[*it]);
433 // Track sessions which have recently gone away so that we can disable 485 // Track sessions which have recently gone away so that we can disable
434 // port suggestions. 486 // port suggestions.
435 if (session->goaway_received()) { 487 if (session->goaway_received()) {
436 gone_away_aliases_.insert(*it); 488 gone_away_aliases_.insert(*it);
437 } 489 }
438 490
439 active_sessions_.erase(*it); 491 active_sessions_.erase(*it);
440 if (!http_server_properties_) 492 if (!http_server_properties_)
441 continue; 493 continue;
442 494
443 if (!session->IsCryptoHandshakeConfirmed()) { 495 if (!session->IsCryptoHandshakeConfirmed()) {
444 // TODO(rch): In the special case where the session has received no 496 // TODO(rch): In the special case where the session has received no
445 // packets from the peer, we should consider blacklisting this 497 // packets from the peer, we should consider blacklisting this
446 // differently so that we still race TCP but we don't consider the 498 // differently so that we still race TCP but we don't consider the
447 // session connected until the handshake has been confirmed. 499 // session connected until the handshake has been confirmed.
448 http_server_properties_->SetBrokenAlternateProtocol(it->first); 500 http_server_properties_->SetBrokenAlternateProtocol(
501 it->host_port_proxy_pair.first);
449 } else { 502 } else {
450 QuicConnectionStats stats = session->connection()->GetStats(); 503 QuicConnectionStats stats = session->connection()->GetStats();
451 HttpServerProperties::NetworkStats network_stats; 504 HttpServerProperties::NetworkStats network_stats;
452 network_stats.rtt = base::TimeDelta::FromMicroseconds(stats.rtt); 505 network_stats.rtt = base::TimeDelta::FromMicroseconds(stats.rtt);
453 network_stats.bandwidth_estimate = stats.estimated_bandwidth; 506 network_stats.bandwidth_estimate = stats.estimated_bandwidth;
454 http_server_properties_->SetServerNetworkStats( 507 http_server_properties_->SetServerNetworkStats(
455 it->first, network_stats); 508 it->host_port_proxy_pair.first, network_stats);
456 } 509 }
457 } 510 }
458 IPEndPoint peer_address = session->connection()->peer_address(); 511 if (!aliases.empty()) {
459 ip_aliases_[peer_address].erase(session); 512 const IpAliasKey ip_alias_key(session->connection()->peer_address(),
460 if (ip_aliases_[peer_address].empty()) { 513 aliases.begin()->is_https);
461 ip_aliases_.erase(peer_address); 514 ip_aliases_[ip_alias_key].erase(session);
515 if (ip_aliases_[ip_alias_key].empty()) {
516 ip_aliases_.erase(ip_alias_key);
517 }
462 } 518 }
463 session_aliases_.erase(session); 519 session_aliases_.erase(session);
464 } 520 }
465 521
466 void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) { 522 void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) {
467 DCHECK_EQ(0u, session->GetNumOpenStreams()); 523 DCHECK_EQ(0u, session->GetNumOpenStreams());
468 OnSessionGoingAway(session); 524 OnSessionGoingAway(session);
469 all_sessions_.erase(session); 525 all_sessions_.erase(session);
470 delete session; 526 delete session;
471 } 527 }
(...skipping 17 matching lines...) Expand all
489 DCHECK_NE(initial_size, all_sessions_.size()); 545 DCHECK_NE(initial_size, all_sessions_.size());
490 } 546 }
491 DCHECK(all_sessions_.empty()); 547 DCHECK(all_sessions_.empty());
492 } 548 }
493 549
494 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const { 550 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const {
495 base::ListValue* list = new base::ListValue(); 551 base::ListValue* list = new base::ListValue();
496 552
497 for (SessionMap::const_iterator it = active_sessions_.begin(); 553 for (SessionMap::const_iterator it = active_sessions_.begin();
498 it != active_sessions_.end(); ++it) { 554 it != active_sessions_.end(); ++it) {
499 const HostPortProxyPair& pair = it->first; 555 const SessionKey& session_key = it->first;
500 QuicClientSession* session = it->second; 556 QuicClientSession* session = it->second;
501 const AliasSet& aliases = session_aliases_.find(session)->second; 557 const AliasSet& aliases = session_aliases_.find(session)->second;
502 if (pair.first.Equals(aliases.begin()->first) && 558 // Only add a session to the list once.
503 pair.second == aliases.begin()->second) { 559 if (session_key == *aliases.begin()) {
504 list->Append(session->GetInfoAsValue(aliases)); 560 std::set<HostPortProxyPair> hosts;
561 for (AliasSet::const_iterator alias_it = aliases.begin();
562 alias_it != aliases.end(); ++alias_it) {
563 hosts.insert(alias_it->host_port_proxy_pair);
564 }
565 list->Append(session->GetInfoAsValue(hosts));
505 } 566 }
506 } 567 }
507 return list; 568 return list;
508 } 569 }
509 570
510 void QuicStreamFactory::OnIPAddressChanged() { 571 void QuicStreamFactory::OnIPAddressChanged() {
511 CloseAllSessions(ERR_NETWORK_CHANGED); 572 CloseAllSessions(ERR_NETWORK_CHANGED);
512 require_confirmation_ = true; 573 require_confirmation_ = true;
513 } 574 }
514 575
515 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { 576 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) {
516 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); 577 CloseAllSessions(ERR_CERT_DATABASE_CHANGED);
517 } 578 }
518 579
519 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { 580 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) {
520 // We should flush the sessions if we removed trust from a 581 // We should flush the sessions if we removed trust from a
521 // cert, because a previously trusted server may have become 582 // cert, because a previously trusted server may have become
522 // untrusted. 583 // untrusted.
523 // 584 //
524 // We should not flush the sessions if we added trust to a cert. 585 // We should not flush the sessions if we added trust to a cert.
525 // 586 //
526 // Since the OnCACertChanged method doesn't tell us what 587 // Since the OnCACertChanged method doesn't tell us what
527 // kind of change it is, we have to flush the socket 588 // kind of change it is, we have to flush the socket
528 // pools to be safe. 589 // pools to be safe.
529 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); 590 CloseAllSessions(ERR_CERT_DATABASE_CHANGED);
530 } 591 }
531 592
532 bool QuicStreamFactory::HasActiveSession( 593 bool QuicStreamFactory::HasActiveSession(const SessionKey& session_key) const {
533 const HostPortProxyPair& host_port_proxy_pair) { 594 return ContainsKey(active_sessions_, session_key);
534 return ContainsKey(active_sessions_, host_port_proxy_pair);
535 } 595 }
536 596
537 int QuicStreamFactory::CreateSession( 597 int QuicStreamFactory::CreateSession(
538 const HostPortProxyPair& host_port_proxy_pair, 598 const HostPortProxyPair& host_port_proxy_pair,
539 bool is_https, 599 bool is_https,
540 CertVerifier* cert_verifier, 600 CertVerifier* cert_verifier,
541 const AddressList& address_list, 601 const AddressList& address_list,
542 const BoundNetLog& net_log, 602 const BoundNetLog& net_log,
543 QuicClientSession** session) { 603 QuicClientSession** session) {
544 bool enable_port_selection = enable_port_selection_; 604 bool enable_port_selection = enable_port_selection_;
605 SessionKey session_key(host_port_proxy_pair, is_https);
545 if (enable_port_selection && 606 if (enable_port_selection &&
546 ContainsKey(gone_away_aliases_, host_port_proxy_pair)) { 607 ContainsKey(gone_away_aliases_, session_key)) {
547 // Disable port selection when the server is going away. 608 // Disable port selection when the server is going away.
548 // There is no point in trying to return to the same server, if 609 // There is no point in trying to return to the same server, if
549 // that server is no longer handling requests. 610 // that server is no longer handling requests.
550 enable_port_selection = false; 611 enable_port_selection = false;
551 gone_away_aliases_.erase(host_port_proxy_pair); 612 gone_away_aliases_.erase(session_key);
552 } 613 }
553 614
554 QuicConnectionId connection_id = random_generator_->RandUint64(); 615 QuicConnectionId connection_id = random_generator_->RandUint64();
555 IPEndPoint addr = *address_list.begin(); 616 IPEndPoint addr = *address_list.begin();
556 scoped_refptr<PortSuggester> port_suggester = 617 scoped_refptr<PortSuggester> port_suggester =
557 new PortSuggester(host_port_proxy_pair.first, port_seed_); 618 new PortSuggester(host_port_proxy_pair.first, port_seed_);
558 DatagramSocket::BindType bind_type = enable_port_selection ? 619 DatagramSocket::BindType bind_type = enable_port_selection ?
559 DatagramSocket::RANDOM_BIND : // Use our callback. 620 DatagramSocket::RANDOM_BIND : // Use our callback.
560 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. 621 DatagramSocket::DEFAULT_BIND; // Use OS to randomize.
561 scoped_ptr<DatagramClientSocket> socket( 622 scoped_ptr<DatagramClientSocket> socket(
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 clock_.get(), random_generator_)); 655 clock_.get(), random_generator_));
595 } 656 }
596 657
597 QuicConnection* connection = new QuicConnection(connection_id, addr, 658 QuicConnection* connection = new QuicConnection(connection_id, addr,
598 helper_.get(), 659 helper_.get(),
599 writer.get(), false, 660 writer.get(), false,
600 supported_versions_); 661 supported_versions_);
601 writer->SetConnection(connection); 662 writer->SetConnection(connection);
602 connection->options()->max_packet_length = max_packet_length_; 663 connection->options()->max_packet_length = max_packet_length_;
603 664
604 QuicCryptoClientConfig* crypto_config = 665 QuicCryptoClientConfig* crypto_config = GetOrCreateCryptoConfig(session_key);
605 GetOrCreateCryptoConfig(host_port_proxy_pair); 666
606 DCHECK(crypto_config); 667 DCHECK(crypto_config);
607 668
608 QuicConfig config = config_; 669 QuicConfig config = config_;
609 if (http_server_properties_) { 670 if (http_server_properties_) {
610 const HttpServerProperties::NetworkStats* stats = 671 const HttpServerProperties::NetworkStats* stats =
611 http_server_properties_->GetServerNetworkStats( 672 http_server_properties_->GetServerNetworkStats(
612 host_port_proxy_pair.first); 673 host_port_proxy_pair.first);
613 if (stats != NULL) { 674 if (stats != NULL) {
614 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(), 675 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(),
615 stats->rtt.InMicroseconds()); 676 stats->rtt.InMicroseconds());
616 } 677 }
617 } 678 }
618 679
619 *session = new QuicClientSession( 680 *session = new QuicClientSession(
620 connection, socket.Pass(), writer.Pass(), this, 681 connection, socket.Pass(), writer.Pass(), this,
621 quic_crypto_client_stream_factory_, host_port_proxy_pair.first.host(), 682 quic_crypto_client_stream_factory_, host_port_proxy_pair.first.host(),
622 config, crypto_config, net_log.net_log()); 683 config, crypto_config, net_log.net_log());
623 all_sessions_.insert(*session); // owning pointer 684 all_sessions_.insert(*session); // owning pointer
624 if (is_https) { 685 if (is_https) {
625 crypto_config->SetProofVerifier( 686 crypto_config->SetProofVerifier(
626 new ProofVerifierChromium(cert_verifier, net_log)); 687 new ProofVerifierChromium(cert_verifier, net_log));
627 } 688 }
628 return OK; 689 return OK;
629 } 690 }
630 691
631 bool QuicStreamFactory::HasActiveJob( 692 bool QuicStreamFactory::HasActiveJob(const SessionKey& key) const {
632 const HostPortProxyPair& host_port_proxy_pair) { 693 return ContainsKey(active_jobs_, key);
633 return ContainsKey(active_jobs_, host_port_proxy_pair);
634 } 694 }
635 695
636 void QuicStreamFactory::ActivateSession( 696 void QuicStreamFactory::ActivateSession(
637 const HostPortProxyPair& host_port_proxy_pair, 697 const SessionKey& session_key,
638 QuicClientSession* session) { 698 QuicClientSession* session) {
639 DCHECK(!HasActiveSession(host_port_proxy_pair)); 699 DCHECK(!HasActiveSession(session_key));
640 active_sessions_[host_port_proxy_pair] = session; 700 active_sessions_[session_key] = session;
641 session_aliases_[session].insert(host_port_proxy_pair); 701 session_aliases_[session].insert(session_key);
642 DCHECK(!ContainsKey(ip_aliases_[session->connection()->peer_address()], 702 const IpAliasKey ip_alias_key(session->connection()->peer_address(),
643 session)); 703 session_key.is_https);
644 ip_aliases_[session->connection()->peer_address()].insert(session); 704 DCHECK(!ContainsKey(ip_aliases_[ip_alias_key], session));
705 ip_aliases_[ip_alias_key].insert(session);
645 } 706 }
646 707
647 QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig( 708 QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig(
648 const HostPortProxyPair& host_port_proxy_pair) { 709 const SessionKey& session_key) {
649 QuicCryptoClientConfig* crypto_config; 710 QuicCryptoClientConfig* crypto_config;
650 711
651 if (ContainsKey(all_crypto_configs_, host_port_proxy_pair)) { 712 if (ContainsKey(all_crypto_configs_, session_key)) {
652 crypto_config = all_crypto_configs_[host_port_proxy_pair]; 713 crypto_config = all_crypto_configs_[session_key];
653 DCHECK(crypto_config); 714 DCHECK(crypto_config);
654 } else { 715 } else {
655 // TODO(rtenneti): if two quic_sessions for the same host_port_proxy_pair 716 // TODO(rtenneti): if two quic_sessions for the same host_port_proxy_pair
656 // share the same crypto_config, will it cause issues? 717 // share the same crypto_config, will it cause issues?
657 crypto_config = new QuicCryptoClientConfig(); 718 crypto_config = new QuicCryptoClientConfig();
658 if (quic_server_info_factory_) { 719 if (quic_server_info_factory_) {
659 QuicCryptoClientConfig::CachedState* cached = 720 QuicCryptoClientConfig::CachedState* cached =
660 crypto_config->Create(host_port_proxy_pair.first.host(), 721 crypto_config->Create(session_key.host_port_proxy_pair.first.host(),
661 quic_server_info_factory_); 722 quic_server_info_factory_);
662 DCHECK(cached); 723 DCHECK(cached);
663 } 724 }
664 crypto_config->SetDefaults(); 725 crypto_config->SetDefaults();
665 all_crypto_configs_[host_port_proxy_pair] = crypto_config; 726 all_crypto_configs_[session_key] = crypto_config;
666 PopulateFromCanonicalConfig(host_port_proxy_pair, crypto_config); 727 PopulateFromCanonicalConfig(session_key, crypto_config);
667 } 728 }
668 return crypto_config; 729 return crypto_config;
669 } 730 }
670 731
671 void QuicStreamFactory::PopulateFromCanonicalConfig( 732 void QuicStreamFactory::PopulateFromCanonicalConfig(
672 const HostPortProxyPair& host_port_proxy_pair, 733 const SessionKey& session_key,
673 QuicCryptoClientConfig* crypto_config) { 734 QuicCryptoClientConfig* crypto_config) {
674 const string server_hostname = host_port_proxy_pair.first.host(); 735 const string server_hostname = session_key.host_port_proxy_pair.first.host();
675 736 const uint16 server_port = session_key.host_port_proxy_pair.first.port();
676 unsigned i = 0; 737 unsigned i = 0;
677 for (; i < canoncial_suffixes_.size(); ++i) { 738 for (; i < canoncial_suffixes_.size(); ++i) {
678 if (EndsWith(server_hostname, canoncial_suffixes_[i], false)) { 739 if (EndsWith(server_hostname, canoncial_suffixes_[i], false)) {
679 break; 740 break;
680 } 741 }
681 } 742 }
682 if (i == canoncial_suffixes_.size()) 743 if (i == canoncial_suffixes_.size())
683 return; 744 return;
684 745
685 HostPortPair canonical_host_port(canoncial_suffixes_[i], 746 HostPortPair suffix_host_port(canoncial_suffixes_[i], server_port);
686 host_port_proxy_pair.first.port()); 747 HostPortProxyPair suffix_host_port_proxy_pair(
687 if (!ContainsKey(canonical_hostname_to_origin_map_, canonical_host_port)) { 748 suffix_host_port, session_key.host_port_proxy_pair.second);
749 SessionKey suffix_session_key(suffix_host_port_proxy_pair,
750 session_key.is_https);
751 if (!ContainsKey(canonical_hostname_to_origin_map_, suffix_session_key)) {
688 // This is the first host we've seen which matches the suffix, so make it 752 // This is the first host we've seen which matches the suffix, so make it
689 // canonical. 753 // canonical.
690 canonical_hostname_to_origin_map_[canonical_host_port] = 754 canonical_hostname_to_origin_map_[suffix_session_key] = session_key;
691 host_port_proxy_pair;
692 return; 755 return;
693 } 756 }
694 757
758 const SessionKey& canonical_session_key =
759 canonical_hostname_to_origin_map_[suffix_session_key];
760 QuicCryptoClientConfig* canonical_crypto_config =
761 all_crypto_configs_[canonical_session_key];
762 DCHECK(canonical_crypto_config);
695 const HostPortProxyPair& canonical_host_port_proxy_pair = 763 const HostPortProxyPair& canonical_host_port_proxy_pair =
696 canonical_hostname_to_origin_map_[canonical_host_port]; 764 canonical_session_key.host_port_proxy_pair;
697 QuicCryptoClientConfig* canonical_crypto_config =
698 all_crypto_configs_[canonical_host_port_proxy_pair];
699 DCHECK(canonical_crypto_config);
700 765
701 // Copy the CachedState for the canonical server from canonical_crypto_config 766 // Copy the CachedState for the canonical server from canonical_crypto_config
702 // as the initial CachedState for the server_hostname in crypto_config. 767 // as the initial CachedState for the server_hostname in crypto_config.
703 crypto_config->InitializeFrom(server_hostname, 768 crypto_config->InitializeFrom(server_hostname,
704 canonical_host_port_proxy_pair.first.host(), 769 canonical_host_port_proxy_pair.first.host(),
705 canonical_crypto_config); 770 canonical_crypto_config);
706 // Update canonical version to point at the "most recent" crypto_config. 771 // Update canonical version to point at the "most recent" crypto_config.
707 canonical_hostname_to_origin_map_[canonical_host_port] = host_port_proxy_pair; 772 canonical_hostname_to_origin_map_[suffix_session_key] =
773 canonical_session_key;
708 } 774 }
709 775
710 } // namespace net 776 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698