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

Side by Side Diff: net/quic/chromium/quic_chromium_client_session.cc

Issue 2848923004: Move the "wait for QUIC handshake confirmation" logic to QuicChromiumClientSession::StreamRequest (Closed)
Patch Set: Async error Created 3 years, 7 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
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/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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698