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 |