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 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 // connection migration. A new Reader is created every time this endpoint's | 46 // connection migration. A new Reader is created every time this endpoint's |
| 47 // IP address changes. | 47 // IP address changes. |
| 48 const size_t kMaxReadersPerQuicSession = 5; | 48 const size_t kMaxReadersPerQuicSession = 5; |
| 49 | 49 |
| 50 // Size of the MRU cache of Token Binding signatures. Since the material being | 50 // Size of the MRU cache of Token Binding signatures. Since the material being |
| 51 // signed is constant and there aren't many keys being used to sign, a fairly | 51 // signed is constant and there aren't many keys being used to sign, a fairly |
| 52 // small number was chosen, somewhat arbitrarily, and to match | 52 // small number was chosen, somewhat arbitrarily, and to match |
| 53 // SSLClientSocketImpl. | 53 // SSLClientSocketImpl. |
| 54 const size_t kTokenBindingSignatureMapSize = 10; | 54 const size_t kTokenBindingSignatureMapSize = 10; |
| 55 | 55 |
| 56 // Time to wait (in seconds) when no networks are available and | |
| 57 // migrating sessions need to wait for a new network to connect. | |
| 58 const size_t kWaitTimeForNewNetworkSecs = 10; | |
| 59 | |
| 56 // Histograms for tracking down the crashes from http://crbug.com/354669 | 60 // Histograms for tracking down the crashes from http://crbug.com/354669 |
| 57 // Note: these values must be kept in sync with the corresponding values in: | 61 // Note: these values must be kept in sync with the corresponding values in: |
| 58 // tools/metrics/histograms/histograms.xml | 62 // tools/metrics/histograms/histograms.xml |
| 59 enum Location { | 63 enum Location { |
| 60 DESTRUCTOR = 0, | 64 DESTRUCTOR = 0, |
| 61 ADD_OBSERVER = 1, | 65 ADD_OBSERVER = 1, |
| 62 TRY_CREATE_STREAM = 2, | 66 TRY_CREATE_STREAM = 2, |
| 63 CREATE_OUTGOING_RELIABLE_STREAM = 3, | 67 CREATE_OUTGOING_RELIABLE_STREAM = 3, |
| 64 NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4, | 68 NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4, |
| 65 NOTIFY_FACTORY_OF_SESSION_CLOSED = 5, | 69 NOTIFY_FACTORY_OF_SESSION_CLOSED = 5, |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 std::move(socket_performance_watcher), | 236 std::move(socket_performance_watcher), |
| 233 net_log_)), | 237 net_log_)), |
| 234 going_away_(false), | 238 going_away_(false), |
| 235 port_migration_detected_(false), | 239 port_migration_detected_(false), |
| 236 disabled_reason_(QUIC_DISABLED_NOT), | 240 disabled_reason_(QUIC_DISABLED_NOT), |
| 237 token_binding_signatures_(kTokenBindingSignatureMapSize), | 241 token_binding_signatures_(kTokenBindingSignatureMapSize), |
| 238 streams_pushed_count_(0), | 242 streams_pushed_count_(0), |
| 239 streams_pushed_and_claimed_count_(0), | 243 streams_pushed_and_claimed_count_(0), |
| 240 migration_pending_(false), | 244 migration_pending_(false), |
| 241 write_pending_(false), | 245 write_pending_(false), |
| 246 migration_alarm_pending_(false), | |
| 242 weak_factory_(this) { | 247 weak_factory_(this) { |
| 243 sockets_.push_back(std::move(socket)); | 248 sockets_.push_back(std::move(socket)); |
| 244 packet_readers_.push_back(base::WrapUnique(new QuicChromiumPacketReader( | 249 packet_readers_.push_back(base::WrapUnique(new QuicChromiumPacketReader( |
| 245 sockets_.back().get(), clock, this, yield_after_packets, | 250 sockets_.back().get(), clock, this, yield_after_packets, |
| 246 yield_after_duration, net_log_))); | 251 yield_after_duration, net_log_))); |
| 247 crypto_stream_.reset( | 252 crypto_stream_.reset( |
| 248 crypto_client_stream_factory->CreateQuicCryptoClientStream( | 253 crypto_client_stream_factory->CreateQuicCryptoClientStream( |
| 249 server_id, this, base::WrapUnique(new ProofVerifyContextChromium( | 254 server_id, this, base::WrapUnique(new ProofVerifyContextChromium( |
| 250 cert_verify_flags, net_log_)), | 255 cert_verify_flags, net_log_)), |
| 251 crypto_config)); | 256 crypto_config)); |
| (...skipping 698 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 950 | 955 |
| 951 int QuicChromiumClientSession::HandleWriteError( | 956 int QuicChromiumClientSession::HandleWriteError( |
| 952 int error_code, | 957 int error_code, |
| 953 scoped_refptr<StringIOBuffer> packet) { | 958 scoped_refptr<StringIOBuffer> packet) { |
| 954 DCHECK(packet != nullptr); | 959 DCHECK(packet != nullptr); |
| 955 DCHECK_NE(ERR_IO_PENDING, error_code); | 960 DCHECK_NE(ERR_IO_PENDING, error_code); |
| 956 DCHECK_GT(0, error_code); | 961 DCHECK_GT(0, error_code); |
| 957 DCHECK(!migration_pending_); | 962 DCHECK(!migration_pending_); |
| 958 DCHECK(packet_ == nullptr); | 963 DCHECK(packet_ == nullptr); |
| 959 | 964 |
| 965 DLOG(INFO) << "Write error encountered."; | |
| 960 // Post a task to migrate the session onto a new network. | 966 // Post a task to migrate the session onto a new network. |
| 961 task_runner_->PostTask( | 967 task_runner_->PostTask( |
| 962 FROM_HERE, | 968 FROM_HERE, |
| 963 base::Bind(&QuicChromiumClientSession::MigrateSessionOnWriteError, | 969 base::Bind(&QuicChromiumClientSession::MigrateSessionOnWriteError, |
| 964 weak_factory_.GetWeakPtr())); | 970 weak_factory_.GetWeakPtr())); |
| 965 | 971 |
| 966 // Store packet in the session since the actual migration and packet rewrite | 972 // Store packet in the session since the actual migration and packet rewrite |
| 967 // can happen via this posted task or via an async network notification. | 973 // can happen via this posted task or via an async network notification. |
| 968 packet_ = packet; | 974 packet_ = packet; |
| 969 migration_pending_ = true; | 975 migration_pending_ = true; |
| 970 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | 976 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) |
| 971 ->set_write_blocked(true); | 977 ->set_write_blocked(true); |
| 972 | 978 |
| 973 // Cause the packet writer to return ERR_IO_PENDING and block so | 979 // Cause the packet writer to return ERR_IO_PENDING and block so |
| 974 // that the actual migration happens from the message loop instead | 980 // that the actual migration happens from the message loop instead |
| 975 // of under the call stack of QuicConnection::WritePacket. | 981 // of under the call stack of QuicConnection::WritePacket. |
| 976 return ERR_IO_PENDING; | 982 return ERR_IO_PENDING; |
| 977 } | 983 } |
| 978 | 984 |
| 979 void QuicChromiumClientSession::MigrateSessionOnWriteError() { | 985 void QuicChromiumClientSession::MigrateSessionOnWriteError() { |
| 980 // If migration_pending_ is false, an earlier task completed migration. | 986 // If migration_pending_ is false, an earlier task completed migration. |
| 981 if (!migration_pending_) | 987 if (!migration_pending_) |
| 982 return; | 988 return; |
| 983 | 989 |
| 984 if (stream_factory_ != nullptr && | 990 MigrationResult result = MigrationResult::FAILURE; |
| 985 stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR) == | 991 if (stream_factory_ != nullptr) { |
| 986 MigrationResult::SUCCESS) | 992 result = stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR); |
| 993 } | |
| 994 | |
| 995 if (result == MigrationResult::SUCCESS) | |
| 987 return; | 996 return; |
| 988 | 997 |
| 998 if (result == MigrationResult::NO_NEW_NETWORK) { | |
| 999 OnNoNewNetwork(); | |
| 1000 return; | |
| 1001 } | |
| 1002 | |
| 989 // Close the connection if migration failed. Do not cause a | 1003 // Close the connection if migration failed. Do not cause a |
| 990 // connection close packet to be sent since socket may be borked. | 1004 // connection close packet to be sent since socket may be borked. |
| 991 connection()->CloseConnection(QUIC_PACKET_WRITE_ERROR, | 1005 connection()->CloseConnection(QUIC_PACKET_WRITE_ERROR, |
| 992 "Write and subsequent migration failed", | 1006 "Write and subsequent migration failed", |
| 993 ConnectionCloseBehavior::SILENT_CLOSE); | 1007 ConnectionCloseBehavior::SILENT_CLOSE); |
| 994 } | 1008 } |
| 995 | 1009 |
| 1010 void QuicChromiumClientSession::OnNoNewNetwork() { | |
|
Ryan Hamilton
2016/09/12 03:42:01
So this is called, obviously, from the write error
Jana
2016/09/12 23:11:01
Yes. It's called only for the DISCONNECTED event,
| |
| 1011 if (migration_alarm_pending_) | |
| 1012 return; | |
| 1013 migration_alarm_pending_ = true; | |
| 1014 | |
| 1015 // Block the packet writer to avoid any writes while migration is in progress. | |
| 1016 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | |
| 1017 ->set_write_blocked(true); | |
|
Ryan Hamilton
2016/09/12 03:42:01
I don't understand the motivation for this. What h
Jana
2016/09/12 23:11:01
This causes an NCN notification to block the socke
Ryan Hamilton
2016/09/13 00:33:18
What makes the socket "disconnected" in this case?
Jana
2016/09/13 01:12:18
Something in Android? So this is the case where we
| |
| 1018 | |
| 1019 // Post a task to maybe close the session if the alarm fires. | |
| 1020 task_runner_->PostDelayedTask( | |
| 1021 FROM_HERE, base::Bind(&QuicChromiumClientSession::OnMigrationTimeout, | |
| 1022 weak_factory_.GetWeakPtr()), | |
| 1023 base::TimeDelta::FromSeconds(kWaitTimeForNewNetworkSecs)); | |
| 1024 } | |
| 1025 | |
| 996 void QuicChromiumClientSession::WriteToNewSocket() { | 1026 void QuicChromiumClientSession::WriteToNewSocket() { |
| 997 // If write_pending_ is false, an earlier task wrote to the new socket. | 1027 // If write_pending_ is false, an earlier task wrote to the new socket. |
| 998 if (!write_pending_) | 1028 if (!write_pending_) |
| 999 return; | 1029 return; |
| 1000 // Prevent any pending migration or write tasks from executing. | 1030 // Prevent any pending migration or write tasks from executing. |
| 1001 write_pending_ = false; | 1031 write_pending_ = false; |
| 1002 migration_pending_ = false; | 1032 migration_pending_ = false; |
| 1003 | 1033 |
| 1004 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | 1034 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) |
| 1005 ->set_write_blocked(false); | 1035 ->set_write_blocked(false); |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 1030 ->WritePacketToSocket(packet); | 1060 ->WritePacketToSocket(packet); |
| 1031 | 1061 |
| 1032 if (result.error_code == ERR_IO_PENDING) | 1062 if (result.error_code == ERR_IO_PENDING) |
| 1033 return; | 1063 return; |
| 1034 // All write errors should be mapped into ERR_IO_PENDING by | 1064 // All write errors should be mapped into ERR_IO_PENDING by |
| 1035 // HandleWriteError. | 1065 // HandleWriteError. |
| 1036 DCHECK(result.error_code >= 0); | 1066 DCHECK(result.error_code >= 0); |
| 1037 connection()->OnCanWrite(); | 1067 connection()->OnCanWrite(); |
| 1038 } | 1068 } |
| 1039 | 1069 |
| 1070 void QuicChromiumClientSession::OnMigrationTimeout() { | |
| 1071 if (!migration_alarm_pending_) | |
| 1072 return; | |
|
Ryan Hamilton
2016/09/12 03:42:01
So does this mean that if multiple timeouts are qu
Jana
2016/09/12 23:11:01
I don't think it matters much, since it's either D
| |
| 1073 migration_alarm_pending_ = false; | |
| 1074 migration_pending_ = false; | |
| 1075 write_pending_ = false; | |
| 1076 /* | |
| 1077 UMA_HISTOGRAM_ENUMERATION( | |
| 1078 "Net.QuicSession.ConnectionMigration", | |
| 1079 static_cast<int>(MigrationStatus::NO_ALTERNATE_NETWORK), | |
| 1080 static_cast<int>(MigrationStatus::MAX)); | |
| 1081 */ | |
| 1082 CloseSessionOnError(ERR_NETWORK_CHANGED, | |
| 1083 QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK); | |
| 1084 } | |
| 1085 | |
| 1086 void QuicChromiumClientSession::OnNetworkConnected( | |
| 1087 NetworkChangeNotifier::NetworkHandle network, | |
| 1088 const BoundNetLog& bound_net_log) { | |
| 1089 // Cancel migration alarm. | |
| 1090 migration_alarm_pending_ = false; | |
| 1091 // If migration_pending_ is false, an earlier task completed migration. | |
| 1092 if (!migration_pending_) | |
|
Ryan Hamilton
2016/09/12 03:42:01
With this CL, migration_pending_ is now true both
Jana
2016/09/13 01:12:18
That's correct.
| |
| 1093 return; | |
| 1094 // TODO(jri): Ensure that OnSessionGoingAway is called consistently, | |
| 1095 // and that it's always called at the same time in the whole | |
| 1096 // migration process. Allows tests to be more uniform. | |
| 1097 stream_factory_->OnSessionGoingAway(this); | |
| 1098 stream_factory_->MigrateSessionToNewNetwork( | |
| 1099 this, network, /*close_session_on_error=*/true, net_log_); | |
| 1100 } | |
| 1101 | |
| 1040 void QuicChromiumClientSession::OnWriteError(int error_code) { | 1102 void QuicChromiumClientSession::OnWriteError(int error_code) { |
| 1041 DCHECK_NE(ERR_IO_PENDING, error_code); | 1103 DCHECK_NE(ERR_IO_PENDING, error_code); |
| 1042 DCHECK_GT(0, error_code); | 1104 DCHECK_GT(0, error_code); |
| 1043 connection()->OnWriteError(error_code); | 1105 connection()->OnWriteError(error_code); |
| 1044 } | 1106 } |
| 1045 | 1107 |
| 1046 void QuicChromiumClientSession::OnWriteUnblocked() { | 1108 void QuicChromiumClientSession::OnWriteUnblocked() { |
| 1047 connection()->OnCanWrite(); | 1109 connection()->OnCanWrite(); |
| 1048 } | 1110 } |
| 1049 | 1111 |
| (...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1321 } | 1383 } |
| 1322 | 1384 |
| 1323 void QuicChromiumClientSession::DeletePromised( | 1385 void QuicChromiumClientSession::DeletePromised( |
| 1324 QuicClientPromisedInfo* promised) { | 1386 QuicClientPromisedInfo* promised) { |
| 1325 if (IsOpenStream(promised->id())) | 1387 if (IsOpenStream(promised->id())) |
| 1326 streams_pushed_and_claimed_count_++; | 1388 streams_pushed_and_claimed_count_++; |
| 1327 QuicClientSessionBase::DeletePromised(promised); | 1389 QuicClientSessionBase::DeletePromised(promised); |
| 1328 } | 1390 } |
| 1329 | 1391 |
| 1330 } // namespace net | 1392 } // namespace net |
| OLD | NEW |