Chromium Code Reviews| 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/chromium/quic_chromium_client_session.h" | 5 #include "net/quic/chromium/quic_chromium_client_session.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/callback_helpers.h" | 9 #include "base/callback_helpers.h" |
| 10 #include "base/location.h" | 10 #include "base/location.h" |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 180 const GURL& GetURL() const override { return request_url_; } | 180 const GURL& GetURL() const override { return request_url_; } |
| 181 | 181 |
| 182 private: | 182 private: |
| 183 base::WeakPtr<QuicChromiumClientSession> session_; | 183 base::WeakPtr<QuicChromiumClientSession> session_; |
| 184 const GURL request_url_; | 184 const GURL request_url_; |
| 185 }; | 185 }; |
| 186 | 186 |
| 187 } // namespace | 187 } // namespace |
| 188 | 188 |
| 189 QuicChromiumClientSession::StreamRequest::StreamRequest( | 189 QuicChromiumClientSession::StreamRequest::StreamRequest( |
| 190 const base::WeakPtr<QuicChromiumClientSession>& session) | 190 const base::WeakPtr<QuicChromiumClientSession>& session, |
|
xunjieli
2017/05/01 20:15:06
Does |session| always outlive the StreamRequest? W
Ryan Hamilton
2017/05/01 21:42:33
The StreamRequest may well outlive the session. Th
xunjieli
2017/05/02 17:23:05
Got it. That makes sense. The "Handle" approach is
| |
| 191 : session_(session), stream_(nullptr) {} | 191 bool requires_confirmation) |
| 192 : session_(session), | |
| 193 requires_confirmation_(requires_confirmation), | |
| 194 stream_(nullptr), | |
| 195 next_state_(STATE_NONE), | |
| 196 weak_factory_(this) {} | |
| 192 | 197 |
| 193 QuicChromiumClientSession::StreamRequest::~StreamRequest() { | 198 QuicChromiumClientSession::StreamRequest::~StreamRequest() { |
| 194 if (stream_) | 199 if (stream_) |
| 195 stream_->Reset(QUIC_STREAM_CANCELLED); | 200 stream_->Reset(QUIC_STREAM_CANCELLED); |
| 196 | 201 |
| 197 if (session_) | 202 if (session_) |
| 198 session_->CancelRequest(this); | 203 session_->CancelRequest(this); |
| 199 } | 204 } |
| 200 | 205 |
| 201 int QuicChromiumClientSession::StreamRequest::StartRequest( | 206 int QuicChromiumClientSession::StreamRequest::StartRequest( |
| 202 const CompletionCallback& callback) { | 207 const CompletionCallback& callback) { |
| 203 DCHECK(session_); | 208 DCHECK(session_); |
| 204 int rv = session_->TryCreateStream(this); | 209 |
| 205 if (rv == ERR_IO_PENDING) { | 210 next_state_ = STATE_WAIT_FOR_CONFIRMATION; |
| 211 int rv = DoLoop(OK); | |
| 212 if (rv == ERR_IO_PENDING) | |
| 206 callback_ = callback; | 213 callback_ = callback; |
| 207 } else { | |
| 208 session_.reset(); | |
| 209 } | |
| 210 | 214 |
| 211 return rv; | 215 return rv; |
| 212 } | 216 } |
| 213 | 217 |
| 214 QuicChromiumClientStream* | 218 QuicChromiumClientStream* |
| 215 QuicChromiumClientSession::StreamRequest::ReleaseStream() { | 219 QuicChromiumClientSession::StreamRequest::ReleaseStream() { |
| 216 DCHECK(stream_); | 220 DCHECK(stream_); |
| 217 QuicChromiumClientStream* stream = stream_; | 221 QuicChromiumClientStream* stream = stream_; |
| 218 stream_ = nullptr; | 222 stream_ = nullptr; |
| 219 return stream; | 223 return stream; |
| 220 } | 224 } |
| 221 | 225 |
| 222 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteSuccess( | 226 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteSuccess( |
| 223 QuicChromiumClientStream* stream) { | 227 QuicChromiumClientStream* stream) { |
| 228 DCHECK_EQ(STATE_REQUEST_STREAM_COMPLETE, next_state_); | |
| 224 session_.reset(); | 229 session_.reset(); |
| 225 stream_ = stream; | 230 stream_ = stream; |
| 226 base::ResetAndReturn(&callback_).Run(OK); | 231 if (callback_) |
|
xunjieli
2017/05/01 20:15:05
I think callback_ is always valid, right? It's nev
Ryan Hamilton
2017/05/01 21:42:35
Ah. Good question. No, it's not guaranteed to be v
xunjieli
2017/05/02 17:23:05
Ah, that's subtle. Thanks for the comment.
| |
| 232 DoCallback(OK); | |
| 227 } | 233 } |
| 228 | 234 |
| 229 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteFailure( | 235 void QuicChromiumClientSession::StreamRequest::OnRequestCompleteFailure( |
| 230 int rv) { | 236 int rv) { |
| 237 DCHECK_EQ(STATE_REQUEST_STREAM_COMPLETE, next_state_); | |
| 231 session_.reset(); | 238 session_.reset(); |
| 239 if (callback_) | |
| 240 DoCallback(rv); | |
| 241 } | |
| 242 | |
| 243 void QuicChromiumClientSession::StreamRequest::OnIOComplete(int rv) { | |
| 244 rv = DoLoop(rv); | |
| 245 | |
| 246 if (rv != ERR_IO_PENDING && !callback_.is_null()) { | |
| 247 DoCallback(rv); | |
| 248 } | |
| 249 } | |
| 250 | |
| 251 void QuicChromiumClientSession::StreamRequest::DoCallback(int rv) { | |
| 252 CHECK_NE(rv, ERR_IO_PENDING); | |
| 253 CHECK(!callback_.is_null()); | |
| 254 | |
| 255 // The client callback can do anything, including destroying this class, | |
| 256 // so any pending callback must be issued after everything else is done. | |
| 232 base::ResetAndReturn(&callback_).Run(rv); | 257 base::ResetAndReturn(&callback_).Run(rv); |
| 233 } | 258 } |
| 234 | 259 |
| 260 int QuicChromiumClientSession::StreamRequest::DoLoop(int rv) { | |
| 261 do { | |
| 262 State state = next_state_; | |
| 263 next_state_ = STATE_NONE; | |
| 264 switch (state) { | |
| 265 case STATE_WAIT_FOR_CONFIRMATION: | |
| 266 CHECK_EQ(OK, rv); | |
| 267 rv = DoWaitForConfirmation(); | |
| 268 break; | |
| 269 case STATE_WAIT_FOR_CONFIRMATION_COMPLETE: | |
| 270 rv = DoWaitForConfirmationComplete(rv); | |
| 271 break; | |
| 272 case STATE_REQUEST_STREAM: | |
| 273 CHECK_EQ(OK, rv); | |
| 274 rv = DoRequestStream(); | |
| 275 break; | |
| 276 case STATE_REQUEST_STREAM_COMPLETE: | |
| 277 rv = DoRequestStreamComplete(rv); | |
| 278 break; | |
| 279 default: | |
| 280 NOTREACHED() << "next_state_: " << next_state_; | |
| 281 break; | |
| 282 } | |
| 283 } while (next_state_ != STATE_NONE && next_state_ && rv != ERR_IO_PENDING); | |
| 284 | |
| 285 return rv; | |
| 286 } | |
| 287 | |
| 288 int QuicChromiumClientSession::StreamRequest::DoWaitForConfirmation() { | |
| 289 next_state_ = STATE_WAIT_FOR_CONFIRMATION_COMPLETE; | |
| 290 if (requires_confirmation_) | |
|
xunjieli
2017/05/01 20:15:05
nit: add curly braces or use early return.
Ryan Hamilton
2017/05/01 21:42:35
Done.
| |
| 291 return session_->WaitForHandshakeConfirmation( | |
| 292 base::Bind(&QuicChromiumClientSession::StreamRequest::OnIOComplete, | |
| 293 weak_factory_.GetWeakPtr())); | |
| 294 | |
| 295 return OK; | |
| 296 } | |
| 297 | |
| 298 int QuicChromiumClientSession::StreamRequest::DoWaitForConfirmationComplete( | |
| 299 int rv) { | |
|
xunjieli
2017/05/01 20:15:05
nit: maybe add a DCHECK_NE(ERR_IO_PENDING, rv) her
Ryan Hamilton
2017/05/01 21:42:35
Done.
| |
| 300 if (rv < 0) | |
| 301 return rv; | |
| 302 | |
| 303 next_state_ = STATE_REQUEST_STREAM; | |
| 304 return OK; | |
| 305 } | |
| 306 | |
| 307 int QuicChromiumClientSession::StreamRequest::DoRequestStream() { | |
| 308 next_state_ = STATE_REQUEST_STREAM_COMPLETE; | |
| 309 | |
| 310 return session_->TryCreateStream(this); | |
| 311 } | |
| 312 | |
| 313 int QuicChromiumClientSession::StreamRequest::DoRequestStreamComplete(int rv) { | |
| 314 DCHECK(rv == OK || !stream_); | |
| 315 session_.reset(); | |
| 316 | |
| 317 return rv; | |
| 318 } | |
| 319 | |
| 235 QuicChromiumClientSession::QuicChromiumClientSession( | 320 QuicChromiumClientSession::QuicChromiumClientSession( |
| 236 QuicConnection* connection, | 321 QuicConnection* connection, |
| 237 std::unique_ptr<DatagramClientSocket> socket, | 322 std::unique_ptr<DatagramClientSocket> socket, |
| 238 QuicStreamFactory* stream_factory, | 323 QuicStreamFactory* stream_factory, |
| 239 QuicCryptoClientStreamFactory* crypto_client_stream_factory, | 324 QuicCryptoClientStreamFactory* crypto_client_stream_factory, |
| 240 QuicClock* clock, | 325 QuicClock* clock, |
| 241 TransportSecurityState* transport_security_state, | 326 TransportSecurityState* transport_security_state, |
| 242 std::unique_ptr<QuicServerInfo> server_info, | 327 std::unique_ptr<QuicServerInfo> server_info, |
| 243 const QuicServerId& server_id, | 328 const QuicServerId& server_id, |
| 244 bool require_confirmation, | 329 bool require_confirmation, |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 296 IPEndPoint address; | 381 IPEndPoint address; |
| 297 if (socket && socket->GetLocalAddress(&address) == OK && | 382 if (socket && socket->GetLocalAddress(&address) == OK && |
| 298 address.GetFamily() == ADDRESS_FAMILY_IPV6) { | 383 address.GetFamily() == ADDRESS_FAMILY_IPV6) { |
| 299 connection->SetMaxPacketLength(connection->max_packet_length() - | 384 connection->SetMaxPacketLength(connection->max_packet_length() - |
| 300 kAdditionalOverheadForIPv6); | 385 kAdditionalOverheadForIPv6); |
| 301 } | 386 } |
| 302 connect_timing_.dns_start = dns_resolution_start_time; | 387 connect_timing_.dns_start = dns_resolution_start_time; |
| 303 connect_timing_.dns_end = dns_resolution_end_time; | 388 connect_timing_.dns_end = dns_resolution_end_time; |
| 304 } | 389 } |
| 305 | 390 |
| 306 QuicChromiumClientSession::~QuicChromiumClientSession() { | 391 QuicChromiumClientSession::~QuicChromiumClientSession() { |
|
xunjieli
2017/05/01 20:15:06
Maybe we can add a DCHECK(waiting_for_confirmation
Ryan Hamilton
2017/05/01 21:42:35
Done.
| |
| 307 DCHECK(callback_.is_null()); | 392 DCHECK(callback_.is_null()); |
| 308 | 393 |
| 309 net_log_.EndEvent(NetLogEventType::QUIC_SESSION); | 394 net_log_.EndEvent(NetLogEventType::QUIC_SESSION); |
| 310 if (!dynamic_streams().empty()) | 395 if (!dynamic_streams().empty()) |
| 311 RecordUnexpectedOpenStreams(DESTRUCTOR); | 396 RecordUnexpectedOpenStreams(DESTRUCTOR); |
| 312 if (!observers_.empty()) | 397 if (!observers_.empty()) |
| 313 RecordUnexpectedObservers(DESTRUCTOR); | 398 RecordUnexpectedObservers(DESTRUCTOR); |
| 314 if (!going_away_) | 399 if (!going_away_) |
| 315 RecordUnexpectedNotGoingAway(DESTRUCTOR); | 400 RecordUnexpectedNotGoingAway(DESTRUCTOR); |
| 316 | 401 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 448 DCHECK(!base::ContainsKey(observers_, observer)); | 533 DCHECK(!base::ContainsKey(observers_, observer)); |
| 449 observers_.insert(observer); | 534 observers_.insert(observer); |
| 450 } | 535 } |
| 451 | 536 |
| 452 void QuicChromiumClientSession::RemoveObserver(Observer* observer) { | 537 void QuicChromiumClientSession::RemoveObserver(Observer* observer) { |
| 453 DCHECK(base::ContainsKey(observers_, observer)); | 538 DCHECK(base::ContainsKey(observers_, observer)); |
| 454 observers_.erase(observer); | 539 observers_.erase(observer); |
| 455 } | 540 } |
| 456 | 541 |
| 457 std::unique_ptr<QuicChromiumClientSession::StreamRequest> | 542 std::unique_ptr<QuicChromiumClientSession::StreamRequest> |
| 458 QuicChromiumClientSession::CreateStreamRequest() { | 543 QuicChromiumClientSession::CreateStreamRequest(bool requires_confirmation) { |
| 459 // base::MakeUnique does not work because the StreamRequest constructor | 544 // base::MakeUnique does not work because the StreamRequest constructor |
| 460 // is private. | 545 // is private. |
| 461 return std::unique_ptr<StreamRequest>( | 546 return std::unique_ptr<StreamRequest>( |
| 462 new StreamRequest(weak_factory_.GetWeakPtr())); | 547 new StreamRequest(weak_factory_.GetWeakPtr(), requires_confirmation)); |
| 548 } | |
| 549 | |
| 550 int QuicChromiumClientSession::WaitForHandshakeConfirmation( | |
| 551 const CompletionCallback& callback) { | |
| 552 if (!connection()->connected()) | |
| 553 return ERR_CONNECTION_CLOSED; | |
| 554 | |
| 555 if (IsCryptoHandshakeConfirmed()) | |
| 556 return OK; | |
| 557 | |
| 558 waiting_for_confirmation_callbacks_.push_back(callback); | |
| 559 return ERR_IO_PENDING; | |
| 463 } | 560 } |
| 464 | 561 |
| 465 int QuicChromiumClientSession::TryCreateStream(StreamRequest* request) { | 562 int QuicChromiumClientSession::TryCreateStream(StreamRequest* request) { |
| 466 if (goaway_received()) { | 563 if (goaway_received()) { |
| 467 DVLOG(1) << "Going away."; | 564 DVLOG(1) << "Going away."; |
| 468 return ERR_CONNECTION_CLOSED; | 565 return ERR_CONNECTION_CLOSED; |
| 469 } | 566 } |
| 470 | 567 |
| 471 if (!connection()->connected()) { | 568 if (!connection()->connected()) { |
| 472 DVLOG(1) << "Already closed."; | 569 DVLOG(1) << "Already closed."; |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 857 "Net.QuicSession.HostResolution.HandshakeConfirmedTime", | 954 "Net.QuicSession.HostResolution.HandshakeConfirmedTime", |
| 858 base::TimeTicks::Now() - connect_timing_.dns_end); | 955 base::TimeTicks::Now() - connect_timing_.dns_end); |
| 859 } | 956 } |
| 860 | 957 |
| 861 ObserverSet::iterator it = observers_.begin(); | 958 ObserverSet::iterator it = observers_.begin(); |
| 862 while (it != observers_.end()) { | 959 while (it != observers_.end()) { |
| 863 Observer* observer = *it; | 960 Observer* observer = *it; |
| 864 ++it; | 961 ++it; |
| 865 observer->OnCryptoHandshakeConfirmed(); | 962 observer->OnCryptoHandshakeConfirmed(); |
| 866 } | 963 } |
| 964 | |
| 965 NotifyAllWaitingForConfirmation(OK); | |
|
xunjieli
2017/05/01 20:15:05
I like the new notification API!
Ryan Hamilton
2017/05/01 21:42:34
\o/ Thanks!
| |
| 867 } | 966 } |
| 868 QuicSpdySession::OnCryptoHandshakeEvent(event); | 967 QuicSpdySession::OnCryptoHandshakeEvent(event); |
| 869 } | 968 } |
| 870 | 969 |
| 871 void QuicChromiumClientSession::OnCryptoHandshakeMessageSent( | 970 void QuicChromiumClientSession::OnCryptoHandshakeMessageSent( |
| 872 const CryptoHandshakeMessage& message) { | 971 const CryptoHandshakeMessage& message) { |
| 873 logger_->OnCryptoHandshakeMessageSent(message); | 972 logger_->OnCryptoHandshakeMessageSent(message); |
| 874 } | 973 } |
| 875 | 974 |
| 876 void QuicChromiumClientSession::OnCryptoHandshakeMessageReceived( | 975 void QuicChromiumClientSession::OnCryptoHandshakeMessageReceived( |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 999 base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR); | 1098 base::ResetAndReturn(&callback_).Run(ERR_QUIC_PROTOCOL_ERROR); |
| 1000 } | 1099 } |
| 1001 | 1100 |
| 1002 for (auto& socket : sockets_) { | 1101 for (auto& socket : sockets_) { |
| 1003 socket->Close(); | 1102 socket->Close(); |
| 1004 } | 1103 } |
| 1005 DCHECK(dynamic_streams().empty()); | 1104 DCHECK(dynamic_streams().empty()); |
| 1006 CloseAllStreams(ERR_UNEXPECTED); | 1105 CloseAllStreams(ERR_UNEXPECTED); |
| 1007 CloseAllObservers(ERR_UNEXPECTED); | 1106 CloseAllObservers(ERR_UNEXPECTED); |
| 1008 CancelAllRequests(ERR_CONNECTION_CLOSED); | 1107 CancelAllRequests(ERR_CONNECTION_CLOSED); |
| 1108 NotifyAllWaitingForConfirmation(ERR_CONNECTION_CLOSED); | |
| 1009 NotifyFactoryOfSessionClosedLater(); | 1109 NotifyFactoryOfSessionClosedLater(); |
| 1010 } | 1110 } |
| 1011 | 1111 |
| 1012 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation( | 1112 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation( |
| 1013 const QuicVersion& version) { | 1113 const QuicVersion& version) { |
| 1014 logger_->OnSuccessfulVersionNegotiation(version); | 1114 logger_->OnSuccessfulVersionNegotiation(version); |
| 1015 QuicSpdySession::OnSuccessfulVersionNegotiation(version); | 1115 QuicSpdySession::OnSuccessfulVersionNegotiation(version); |
| 1016 | 1116 |
| 1017 ObserverSet::iterator it = observers_.begin(); | 1117 ObserverSet::iterator it = observers_.begin(); |
| 1018 while (it != observers_.end()) { | 1118 while (it != observers_.end()) { |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1267 UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.AbortedPendingStreamRequests", | 1367 UMA_HISTOGRAM_COUNTS_1000("Net.QuicSession.AbortedPendingStreamRequests", |
| 1268 stream_requests_.size()); | 1368 stream_requests_.size()); |
| 1269 | 1369 |
| 1270 while (!stream_requests_.empty()) { | 1370 while (!stream_requests_.empty()) { |
| 1271 StreamRequest* request = stream_requests_.front(); | 1371 StreamRequest* request = stream_requests_.front(); |
| 1272 stream_requests_.pop_front(); | 1372 stream_requests_.pop_front(); |
| 1273 request->OnRequestCompleteFailure(net_error); | 1373 request->OnRequestCompleteFailure(net_error); |
| 1274 } | 1374 } |
| 1275 } | 1375 } |
| 1276 | 1376 |
| 1377 void QuicChromiumClientSession::NotifyAllWaitingForConfirmation(int net_error) { | |
| 1378 // Post tasks to avoid reentrancy. | |
| 1379 for (auto callback : waiting_for_confirmation_callbacks_) | |
|
xunjieli
2017/05/01 20:15:06
nit: need a pair of {} here for the for-loop.
Ryan Hamilton
2017/05/01 21:42:32
Hm. I thought this was not needed because the body
xunjieli
2017/05/02 17:23:05
Got it. I didn't know that braces are optional for
| |
| 1380 task_runner_->PostTask(FROM_HERE, base::Bind(callback, net_error)); | |
| 1381 | |
| 1382 waiting_for_confirmation_callbacks_.clear(); | |
| 1383 } | |
| 1384 | |
| 1277 std::unique_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue( | 1385 std::unique_ptr<base::Value> QuicChromiumClientSession::GetInfoAsValue( |
| 1278 const std::set<HostPortPair>& aliases) { | 1386 const std::set<HostPortPair>& aliases) { |
| 1279 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); | 1387 std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
| 1280 dict->SetString("version", QuicVersionToString(connection()->version())); | 1388 dict->SetString("version", QuicVersionToString(connection()->version())); |
| 1281 dict->SetInteger("open_streams", GetNumOpenOutgoingStreams()); | 1389 dict->SetInteger("open_streams", GetNumOpenOutgoingStreams()); |
| 1282 std::unique_ptr<base::ListValue> stream_list(new base::ListValue()); | 1390 std::unique_ptr<base::ListValue> stream_list(new base::ListValue()); |
| 1283 for (DynamicStreamMap::const_iterator it = dynamic_streams().begin(); | 1391 for (DynamicStreamMap::const_iterator it = dynamic_streams().begin(); |
| 1284 it != dynamic_streams().end(); ++it) { | 1392 it != dynamic_streams().end(); ++it) { |
| 1285 stream_list->AppendString(base::UintToString(it->second->id())); | 1393 stream_list->AppendString(base::UintToString(it->second->id())); |
| 1286 } | 1394 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1497 } | 1605 } |
| 1498 | 1606 |
| 1499 size_t QuicChromiumClientSession::EstimateMemoryUsage() const { | 1607 size_t QuicChromiumClientSession::EstimateMemoryUsage() const { |
| 1500 // TODO(xunjieli): Estimate |crypto_stream_|, QuicSpdySession's | 1608 // TODO(xunjieli): Estimate |crypto_stream_|, QuicSpdySession's |
| 1501 // QuicHeaderList, QuicSession's QuiCWriteBlockedList, open streams and | 1609 // QuicHeaderList, QuicSession's QuiCWriteBlockedList, open streams and |
| 1502 // unacked packet map. | 1610 // unacked packet map. |
| 1503 return base::trace_event::EstimateMemoryUsage(packet_readers_); | 1611 return base::trace_event::EstimateMemoryUsage(packet_readers_); |
| 1504 } | 1612 } |
| 1505 | 1613 |
| 1506 } // namespace net | 1614 } // namespace net |
| OLD | NEW |