OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 QuicConnectionStats& stats = session->connection()->GetStats(); | 480 const QuicConnectionStats& stats = session->connection()->GetStats(); |
(...skipping 10 matching lines...) Expand all Loading... |
439 | 491 |
440 active_sessions_.erase(*it); | 492 active_sessions_.erase(*it); |
441 if (!http_server_properties_) | 493 if (!http_server_properties_) |
442 continue; | 494 continue; |
443 | 495 |
444 if (!session->IsCryptoHandshakeConfirmed()) { | 496 if (!session->IsCryptoHandshakeConfirmed()) { |
445 // TODO(rch): In the special case where the session has received no | 497 // TODO(rch): In the special case where the session has received no |
446 // packets from the peer, we should consider blacklisting this | 498 // packets from the peer, we should consider blacklisting this |
447 // differently so that we still race TCP but we don't consider the | 499 // differently so that we still race TCP but we don't consider the |
448 // session connected until the handshake has been confirmed. | 500 // session connected until the handshake has been confirmed. |
449 http_server_properties_->SetBrokenAlternateProtocol(it->first); | 501 http_server_properties_->SetBrokenAlternateProtocol( |
| 502 it->host_port_proxy_pair.first); |
450 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived", | 503 UMA_HISTOGRAM_COUNTS("Net.QuicHandshakeNotConfirmedNumPacketsReceived", |
451 stats.packets_received); | 504 stats.packets_received); |
452 continue; | 505 continue; |
453 } | 506 } |
454 | 507 |
455 HttpServerProperties::NetworkStats network_stats; | 508 HttpServerProperties::NetworkStats network_stats; |
456 network_stats.rtt = base::TimeDelta::FromMicroseconds(stats.rtt); | 509 network_stats.rtt = base::TimeDelta::FromMicroseconds(stats.rtt); |
457 network_stats.bandwidth_estimate = stats.estimated_bandwidth; | 510 network_stats.bandwidth_estimate = stats.estimated_bandwidth; |
458 http_server_properties_->SetServerNetworkStats( | 511 http_server_properties_->SetServerNetworkStats( |
459 it->first, network_stats); | 512 it->host_port_proxy_pair.first, network_stats); |
460 } | 513 } |
461 IPEndPoint peer_address = session->connection()->peer_address(); | 514 if (!aliases.empty()) { |
462 ip_aliases_[peer_address].erase(session); | 515 const IpAliasKey ip_alias_key(session->connection()->peer_address(), |
463 if (ip_aliases_[peer_address].empty()) { | 516 aliases.begin()->is_https); |
464 ip_aliases_.erase(peer_address); | 517 ip_aliases_[ip_alias_key].erase(session); |
| 518 if (ip_aliases_[ip_alias_key].empty()) { |
| 519 ip_aliases_.erase(ip_alias_key); |
| 520 } |
465 } | 521 } |
466 session_aliases_.erase(session); | 522 session_aliases_.erase(session); |
467 } | 523 } |
468 | 524 |
469 void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) { | 525 void QuicStreamFactory::OnSessionClosed(QuicClientSession* session) { |
470 DCHECK_EQ(0u, session->GetNumOpenStreams()); | 526 DCHECK_EQ(0u, session->GetNumOpenStreams()); |
471 OnSessionGoingAway(session); | 527 OnSessionGoingAway(session); |
472 all_sessions_.erase(session); | 528 all_sessions_.erase(session); |
473 delete session; | 529 delete session; |
474 } | 530 } |
(...skipping 17 matching lines...) Expand all Loading... |
492 DCHECK_NE(initial_size, all_sessions_.size()); | 548 DCHECK_NE(initial_size, all_sessions_.size()); |
493 } | 549 } |
494 DCHECK(all_sessions_.empty()); | 550 DCHECK(all_sessions_.empty()); |
495 } | 551 } |
496 | 552 |
497 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const { | 553 base::Value* QuicStreamFactory::QuicStreamFactoryInfoToValue() const { |
498 base::ListValue* list = new base::ListValue(); | 554 base::ListValue* list = new base::ListValue(); |
499 | 555 |
500 for (SessionMap::const_iterator it = active_sessions_.begin(); | 556 for (SessionMap::const_iterator it = active_sessions_.begin(); |
501 it != active_sessions_.end(); ++it) { | 557 it != active_sessions_.end(); ++it) { |
502 const HostPortProxyPair& pair = it->first; | 558 const SessionKey& session_key = it->first; |
503 QuicClientSession* session = it->second; | 559 QuicClientSession* session = it->second; |
504 const AliasSet& aliases = session_aliases_.find(session)->second; | 560 const AliasSet& aliases = session_aliases_.find(session)->second; |
505 if (pair.first.Equals(aliases.begin()->first) && | 561 // Only add a session to the list once. |
506 pair.second == aliases.begin()->second) { | 562 if (session_key == *aliases.begin()) { |
507 list->Append(session->GetInfoAsValue(aliases)); | 563 std::set<HostPortProxyPair> hosts; |
| 564 for (AliasSet::const_iterator alias_it = aliases.begin(); |
| 565 alias_it != aliases.end(); ++alias_it) { |
| 566 hosts.insert(alias_it->host_port_proxy_pair); |
| 567 } |
| 568 list->Append(session->GetInfoAsValue(hosts)); |
508 } | 569 } |
509 } | 570 } |
510 return list; | 571 return list; |
511 } | 572 } |
512 | 573 |
513 void QuicStreamFactory::OnIPAddressChanged() { | 574 void QuicStreamFactory::OnIPAddressChanged() { |
514 CloseAllSessions(ERR_NETWORK_CHANGED); | 575 CloseAllSessions(ERR_NETWORK_CHANGED); |
515 require_confirmation_ = true; | 576 require_confirmation_ = true; |
516 } | 577 } |
517 | 578 |
518 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { | 579 void QuicStreamFactory::OnCertAdded(const X509Certificate* cert) { |
519 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 580 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
520 } | 581 } |
521 | 582 |
522 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { | 583 void QuicStreamFactory::OnCACertChanged(const X509Certificate* cert) { |
523 // We should flush the sessions if we removed trust from a | 584 // We should flush the sessions if we removed trust from a |
524 // cert, because a previously trusted server may have become | 585 // cert, because a previously trusted server may have become |
525 // untrusted. | 586 // untrusted. |
526 // | 587 // |
527 // We should not flush the sessions if we added trust to a cert. | 588 // We should not flush the sessions if we added trust to a cert. |
528 // | 589 // |
529 // Since the OnCACertChanged method doesn't tell us what | 590 // Since the OnCACertChanged method doesn't tell us what |
530 // kind of change it is, we have to flush the socket | 591 // kind of change it is, we have to flush the socket |
531 // pools to be safe. | 592 // pools to be safe. |
532 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); | 593 CloseAllSessions(ERR_CERT_DATABASE_CHANGED); |
533 } | 594 } |
534 | 595 |
535 bool QuicStreamFactory::HasActiveSession( | 596 bool QuicStreamFactory::HasActiveSession(const SessionKey& session_key) const { |
536 const HostPortProxyPair& host_port_proxy_pair) { | 597 return ContainsKey(active_sessions_, session_key); |
537 return ContainsKey(active_sessions_, host_port_proxy_pair); | |
538 } | 598 } |
539 | 599 |
540 int QuicStreamFactory::CreateSession( | 600 int QuicStreamFactory::CreateSession( |
541 const HostPortProxyPair& host_port_proxy_pair, | 601 const HostPortProxyPair& host_port_proxy_pair, |
542 bool is_https, | 602 bool is_https, |
543 CertVerifier* cert_verifier, | 603 CertVerifier* cert_verifier, |
544 const AddressList& address_list, | 604 const AddressList& address_list, |
545 const BoundNetLog& net_log, | 605 const BoundNetLog& net_log, |
546 QuicClientSession** session) { | 606 QuicClientSession** session) { |
547 bool enable_port_selection = enable_port_selection_; | 607 bool enable_port_selection = enable_port_selection_; |
| 608 SessionKey session_key(host_port_proxy_pair, is_https); |
548 if (enable_port_selection && | 609 if (enable_port_selection && |
549 ContainsKey(gone_away_aliases_, host_port_proxy_pair)) { | 610 ContainsKey(gone_away_aliases_, session_key)) { |
550 // Disable port selection when the server is going away. | 611 // Disable port selection when the server is going away. |
551 // There is no point in trying to return to the same server, if | 612 // There is no point in trying to return to the same server, if |
552 // that server is no longer handling requests. | 613 // that server is no longer handling requests. |
553 enable_port_selection = false; | 614 enable_port_selection = false; |
554 gone_away_aliases_.erase(host_port_proxy_pair); | 615 gone_away_aliases_.erase(session_key); |
555 } | 616 } |
556 | 617 |
557 QuicConnectionId connection_id = random_generator_->RandUint64(); | 618 QuicConnectionId connection_id = random_generator_->RandUint64(); |
558 IPEndPoint addr = *address_list.begin(); | 619 IPEndPoint addr = *address_list.begin(); |
559 scoped_refptr<PortSuggester> port_suggester = | 620 scoped_refptr<PortSuggester> port_suggester = |
560 new PortSuggester(host_port_proxy_pair.first, port_seed_); | 621 new PortSuggester(host_port_proxy_pair.first, port_seed_); |
561 DatagramSocket::BindType bind_type = enable_port_selection ? | 622 DatagramSocket::BindType bind_type = enable_port_selection ? |
562 DatagramSocket::RANDOM_BIND : // Use our callback. | 623 DatagramSocket::RANDOM_BIND : // Use our callback. |
563 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. | 624 DatagramSocket::DEFAULT_BIND; // Use OS to randomize. |
564 scoped_ptr<DatagramClientSocket> socket( | 625 scoped_ptr<DatagramClientSocket> socket( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 clock_.get(), random_generator_)); | 658 clock_.get(), random_generator_)); |
598 } | 659 } |
599 | 660 |
600 QuicConnection* connection = new QuicConnection(connection_id, addr, | 661 QuicConnection* connection = new QuicConnection(connection_id, addr, |
601 helper_.get(), | 662 helper_.get(), |
602 writer.get(), false, | 663 writer.get(), false, |
603 supported_versions_); | 664 supported_versions_); |
604 writer->SetConnection(connection); | 665 writer->SetConnection(connection); |
605 connection->options()->max_packet_length = max_packet_length_; | 666 connection->options()->max_packet_length = max_packet_length_; |
606 | 667 |
607 QuicCryptoClientConfig* crypto_config = | 668 QuicCryptoClientConfig* crypto_config = GetOrCreateCryptoConfig(session_key); |
608 GetOrCreateCryptoConfig(host_port_proxy_pair); | 669 |
609 DCHECK(crypto_config); | 670 DCHECK(crypto_config); |
610 | 671 |
611 QuicConfig config = config_; | 672 QuicConfig config = config_; |
612 if (http_server_properties_) { | 673 if (http_server_properties_) { |
613 const HttpServerProperties::NetworkStats* stats = | 674 const HttpServerProperties::NetworkStats* stats = |
614 http_server_properties_->GetServerNetworkStats( | 675 http_server_properties_->GetServerNetworkStats( |
615 host_port_proxy_pair.first); | 676 host_port_proxy_pair.first); |
616 if (stats != NULL) { | 677 if (stats != NULL) { |
617 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(), | 678 config.set_initial_round_trip_time_us(stats->rtt.InMicroseconds(), |
618 stats->rtt.InMicroseconds()); | 679 stats->rtt.InMicroseconds()); |
619 } | 680 } |
620 } | 681 } |
621 | 682 |
622 *session = new QuicClientSession( | 683 *session = new QuicClientSession( |
623 connection, socket.Pass(), writer.Pass(), this, | 684 connection, socket.Pass(), writer.Pass(), this, |
624 quic_crypto_client_stream_factory_, host_port_proxy_pair.first.host(), | 685 quic_crypto_client_stream_factory_, host_port_proxy_pair.first.host(), |
625 config, crypto_config, net_log.net_log()); | 686 config, crypto_config, net_log.net_log()); |
626 all_sessions_.insert(*session); // owning pointer | 687 all_sessions_.insert(*session); // owning pointer |
627 if (is_https) { | 688 if (is_https) { |
628 crypto_config->SetProofVerifier( | 689 crypto_config->SetProofVerifier( |
629 new ProofVerifierChromium(cert_verifier, net_log)); | 690 new ProofVerifierChromium(cert_verifier, net_log)); |
630 } | 691 } |
631 return OK; | 692 return OK; |
632 } | 693 } |
633 | 694 |
634 bool QuicStreamFactory::HasActiveJob( | 695 bool QuicStreamFactory::HasActiveJob(const SessionKey& key) const { |
635 const HostPortProxyPair& host_port_proxy_pair) { | 696 return ContainsKey(active_jobs_, key); |
636 return ContainsKey(active_jobs_, host_port_proxy_pair); | |
637 } | 697 } |
638 | 698 |
639 void QuicStreamFactory::ActivateSession( | 699 void QuicStreamFactory::ActivateSession( |
640 const HostPortProxyPair& host_port_proxy_pair, | 700 const SessionKey& session_key, |
641 QuicClientSession* session) { | 701 QuicClientSession* session) { |
642 DCHECK(!HasActiveSession(host_port_proxy_pair)); | 702 DCHECK(!HasActiveSession(session_key)); |
643 active_sessions_[host_port_proxy_pair] = session; | 703 active_sessions_[session_key] = session; |
644 session_aliases_[session].insert(host_port_proxy_pair); | 704 session_aliases_[session].insert(session_key); |
645 DCHECK(!ContainsKey(ip_aliases_[session->connection()->peer_address()], | 705 const IpAliasKey ip_alias_key(session->connection()->peer_address(), |
646 session)); | 706 session_key.is_https); |
647 ip_aliases_[session->connection()->peer_address()].insert(session); | 707 DCHECK(!ContainsKey(ip_aliases_[ip_alias_key], session)); |
| 708 ip_aliases_[ip_alias_key].insert(session); |
648 } | 709 } |
649 | 710 |
650 QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig( | 711 QuicCryptoClientConfig* QuicStreamFactory::GetOrCreateCryptoConfig( |
651 const HostPortProxyPair& host_port_proxy_pair) { | 712 const SessionKey& session_key) { |
652 QuicCryptoClientConfig* crypto_config; | 713 QuicCryptoClientConfig* crypto_config; |
653 | 714 |
654 if (ContainsKey(all_crypto_configs_, host_port_proxy_pair)) { | 715 if (ContainsKey(all_crypto_configs_, session_key)) { |
655 crypto_config = all_crypto_configs_[host_port_proxy_pair]; | 716 crypto_config = all_crypto_configs_[session_key]; |
656 DCHECK(crypto_config); | 717 DCHECK(crypto_config); |
657 } else { | 718 } else { |
658 // TODO(rtenneti): if two quic_sessions for the same host_port_proxy_pair | 719 // TODO(rtenneti): if two quic_sessions for the same host_port_proxy_pair |
659 // share the same crypto_config, will it cause issues? | 720 // share the same crypto_config, will it cause issues? |
660 crypto_config = new QuicCryptoClientConfig(); | 721 crypto_config = new QuicCryptoClientConfig(); |
661 if (quic_server_info_factory_) { | 722 if (quic_server_info_factory_) { |
662 QuicCryptoClientConfig::CachedState* cached = | 723 QuicCryptoClientConfig::CachedState* cached = |
663 crypto_config->Create(host_port_proxy_pair.first.host(), | 724 crypto_config->Create(session_key.host_port_proxy_pair.first.host(), |
664 quic_server_info_factory_); | 725 quic_server_info_factory_); |
665 DCHECK(cached); | 726 DCHECK(cached); |
666 } | 727 } |
667 crypto_config->SetDefaults(); | 728 crypto_config->SetDefaults(); |
668 all_crypto_configs_[host_port_proxy_pair] = crypto_config; | 729 all_crypto_configs_[session_key] = crypto_config; |
669 PopulateFromCanonicalConfig(host_port_proxy_pair, crypto_config); | 730 PopulateFromCanonicalConfig(session_key, crypto_config); |
670 } | 731 } |
671 return crypto_config; | 732 return crypto_config; |
672 } | 733 } |
673 | 734 |
674 void QuicStreamFactory::PopulateFromCanonicalConfig( | 735 void QuicStreamFactory::PopulateFromCanonicalConfig( |
675 const HostPortProxyPair& host_port_proxy_pair, | 736 const SessionKey& session_key, |
676 QuicCryptoClientConfig* crypto_config) { | 737 QuicCryptoClientConfig* crypto_config) { |
677 const string server_hostname = host_port_proxy_pair.first.host(); | 738 const string server_hostname = session_key.host_port_proxy_pair.first.host(); |
678 | 739 const uint16 server_port = session_key.host_port_proxy_pair.first.port(); |
679 unsigned i = 0; | 740 unsigned i = 0; |
680 for (; i < canoncial_suffixes_.size(); ++i) { | 741 for (; i < canoncial_suffixes_.size(); ++i) { |
681 if (EndsWith(server_hostname, canoncial_suffixes_[i], false)) { | 742 if (EndsWith(server_hostname, canoncial_suffixes_[i], false)) { |
682 break; | 743 break; |
683 } | 744 } |
684 } | 745 } |
685 if (i == canoncial_suffixes_.size()) | 746 if (i == canoncial_suffixes_.size()) |
686 return; | 747 return; |
687 | 748 |
688 HostPortPair canonical_host_port(canoncial_suffixes_[i], | 749 HostPortPair suffix_host_port(canoncial_suffixes_[i], server_port); |
689 host_port_proxy_pair.first.port()); | 750 HostPortProxyPair suffix_host_port_proxy_pair( |
690 if (!ContainsKey(canonical_hostname_to_origin_map_, canonical_host_port)) { | 751 suffix_host_port, session_key.host_port_proxy_pair.second); |
| 752 SessionKey suffix_session_key(suffix_host_port_proxy_pair, |
| 753 session_key.is_https); |
| 754 if (!ContainsKey(canonical_hostname_to_origin_map_, suffix_session_key)) { |
691 // This is the first host we've seen which matches the suffix, so make it | 755 // This is the first host we've seen which matches the suffix, so make it |
692 // canonical. | 756 // canonical. |
693 canonical_hostname_to_origin_map_[canonical_host_port] = | 757 canonical_hostname_to_origin_map_[suffix_session_key] = session_key; |
694 host_port_proxy_pair; | |
695 return; | 758 return; |
696 } | 759 } |
697 | 760 |
| 761 const SessionKey& canonical_session_key = |
| 762 canonical_hostname_to_origin_map_[suffix_session_key]; |
| 763 QuicCryptoClientConfig* canonical_crypto_config = |
| 764 all_crypto_configs_[canonical_session_key]; |
| 765 DCHECK(canonical_crypto_config); |
698 const HostPortProxyPair& canonical_host_port_proxy_pair = | 766 const HostPortProxyPair& canonical_host_port_proxy_pair = |
699 canonical_hostname_to_origin_map_[canonical_host_port]; | 767 canonical_session_key.host_port_proxy_pair; |
700 QuicCryptoClientConfig* canonical_crypto_config = | |
701 all_crypto_configs_[canonical_host_port_proxy_pair]; | |
702 DCHECK(canonical_crypto_config); | |
703 | 768 |
704 // Copy the CachedState for the canonical server from canonical_crypto_config | 769 // Copy the CachedState for the canonical server from canonical_crypto_config |
705 // as the initial CachedState for the server_hostname in crypto_config. | 770 // as the initial CachedState for the server_hostname in crypto_config. |
706 crypto_config->InitializeFrom(server_hostname, | 771 crypto_config->InitializeFrom(server_hostname, |
707 canonical_host_port_proxy_pair.first.host(), | 772 canonical_host_port_proxy_pair.first.host(), |
708 canonical_crypto_config); | 773 canonical_crypto_config); |
709 // Update canonical version to point at the "most recent" crypto_config. | 774 // Update canonical version to point at the "most recent" crypto_config. |
710 canonical_hostname_to_origin_map_[canonical_host_port] = host_port_proxy_pair; | 775 canonical_hostname_to_origin_map_[suffix_session_key] = |
| 776 canonical_session_key; |
711 } | 777 } |
712 | 778 |
713 } // namespace net | 779 } // namespace net |
OLD | NEW |