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 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 230 logger_(new QuicConnectionLogger(this, | 230 logger_(new QuicConnectionLogger(this, |
| 231 connection_description, | 231 connection_description, |
| 232 std::move(socket_performance_watcher), | 232 std::move(socket_performance_watcher), |
| 233 net_log_)), | 233 net_log_)), |
| 234 going_away_(false), | 234 going_away_(false), |
| 235 port_migration_detected_(false), | 235 port_migration_detected_(false), |
| 236 disabled_reason_(QUIC_DISABLED_NOT), | 236 disabled_reason_(QUIC_DISABLED_NOT), |
| 237 token_binding_signatures_(kTokenBindingSignatureMapSize), | 237 token_binding_signatures_(kTokenBindingSignatureMapSize), |
| 238 streams_pushed_count_(0), | 238 streams_pushed_count_(0), |
| 239 streams_pushed_and_claimed_count_(0), | 239 streams_pushed_and_claimed_count_(0), |
| 240 error_code_from_rewrite_(OK), | 240 migration_pending_(false), |
| 241 use_error_code_from_rewrite_(false), | 241 should_write_block_(false), |
| 242 weak_factory_(this) { | 242 weak_factory_(this) { |
| 243 sockets_.push_back(std::move(socket)); | 243 sockets_.push_back(std::move(socket)); |
| 244 packet_readers_.push_back(base::WrapUnique(new QuicChromiumPacketReader( | 244 packet_readers_.push_back(base::WrapUnique(new QuicChromiumPacketReader( |
| 245 sockets_.back().get(), clock, this, yield_after_packets, | 245 sockets_.back().get(), clock, this, yield_after_packets, |
| 246 yield_after_duration, net_log_))); | 246 yield_after_duration, net_log_))); |
| 247 crypto_stream_.reset( | 247 crypto_stream_.reset( |
| 248 crypto_client_stream_factory->CreateQuicCryptoClientStream( | 248 crypto_client_stream_factory->CreateQuicCryptoClientStream( |
| 249 server_id, this, base::WrapUnique(new ProofVerifyContextChromium( | 249 server_id, this, base::WrapUnique(new ProofVerifyContextChromium( |
| 250 cert_verify_flags, net_log_)), | 250 cert_verify_flags, net_log_)), |
| 251 crypto_config)); | 251 crypto_config)); |
| (...skipping 693 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 945 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation( | 945 void QuicChromiumClientSession::OnSuccessfulVersionNegotiation( |
| 946 const QuicVersion& version) { | 946 const QuicVersion& version) { |
| 947 logger_->OnSuccessfulVersionNegotiation(version); | 947 logger_->OnSuccessfulVersionNegotiation(version); |
| 948 QuicSpdySession::OnSuccessfulVersionNegotiation(version); | 948 QuicSpdySession::OnSuccessfulVersionNegotiation(version); |
| 949 } | 949 } |
| 950 | 950 |
| 951 int QuicChromiumClientSession::HandleWriteError( | 951 int QuicChromiumClientSession::HandleWriteError( |
| 952 int error_code, | 952 int error_code, |
| 953 scoped_refptr<StringIOBuffer> packet) { | 953 scoped_refptr<StringIOBuffer> packet) { |
| 954 DCHECK(packet != nullptr); | 954 DCHECK(packet != nullptr); |
| 955 use_error_code_from_rewrite_ = false; | 955 DCHECK_NE(ERR_IO_PENDING, error_code); |
| 956 if (stream_factory_) { | 956 DCHECK_GT(0, error_code); |
| 957 stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR, packet); | 957 DCHECK(!migration_pending_); |
| 958 DCHECK(packet_ == nullptr); | |
| 959 | |
| 960 // Post a task to migrate the session onto a new network. | |
| 961 task_runner_->PostTask( | |
| 962 FROM_HERE, | |
| 963 base::Bind(&QuicChromiumClientSession::MigrateSessionOnWriteError, | |
| 964 weak_factory_.GetWeakPtr())); | |
| 965 | |
| 966 // 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. | |
| 968 packet_ = packet; | |
| 969 migration_pending_ = true; | |
| 970 | |
| 971 // Cause the packet writer to return ERR_IO_PENDING and block so | |
| 972 // that the actual migration happens from the message loop instead | |
| 973 // of under the call stack of QuicConnection::WritePacket. | |
| 974 return ERR_IO_PENDING; | |
| 975 } | |
| 976 | |
| 977 void QuicChromiumClientSession::MigrateSessionOnWriteError() { | |
| 978 // There are two async steps in the migration process due to write error: | |
| 979 // MigrateSessionOnWriteError (this method) and WriteToNewPacket. | |
| 980 // If migration_pending_ is false, a notification-triggered | |
| 981 // migration completed migration before this method was executed. | |
| 982 // If packet_ is null, a notification-triggered migration wrote the | |
| 983 // stashed packet on a new network post-migration before this method | |
| 984 // was executed. Either ways, do not trigger another migration. | |
| 985 if (migration_pending_ == false || packet_ == nullptr) | |
| 986 return; | |
| 987 | |
| 988 if (stream_factory_ != nullptr && | |
| 989 stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR) == | |
| 990 MigrationResult::SUCCESS) | |
| 991 return; | |
| 992 | |
| 993 // Close the connection if migration failed. Do not cause a | |
| 994 // connection close packet to be sent since socket may be borked. | |
| 995 connection()->CloseConnection(QUIC_PACKET_WRITE_ERROR, | |
| 996 "Write and subsequent migration failed", | |
| 997 ConnectionCloseBehavior::SILENT_CLOSE); | |
| 998 } | |
| 999 | |
| 1000 void QuicChromiumClientSession::WriteToNewSocket() { | |
| 1001 // This method can be called via a write error event or via an | |
| 1002 // notifier (NetworkChangeNotifier) event. If there's only a notifier | |
| 1003 // event that leads here, packet must be null and the connection is | |
| 1004 // not write blocked. If there's only a write error that leads | |
|
Ryan Hamilton
2016/09/11 15:38:42
I'm not sure this statement is correct. Consider t
Jana
2016/09/11 18:32:30
So your example sequence of events is what I calle
| |
| 1005 // here, then packet must be non-null, since HandleWriteError stores | |
| 1006 // a packet in the packet_ member. The packet_ member is cleared | |
| 1007 // only in this method below. | |
| 1008 // | |
| 1009 // If the WriteError event and a notifier event are interleaved, | |
| 1010 // leading to two WriteToNewSocket()s being posted and executed, it | |
| 1011 // doesn't matter which WriteToNewSocket occurs first. The first one | |
| 1012 // will write packet_ and unblock the connection (or close on | |
| 1013 // error), and the second one will send a PING packet. | |
| 1014 | |
| 1015 // Unblock the writer so it can be used. | |
| 1016 should_write_block_ = false; | |
| 1017 | |
| 1018 if (packet_ == nullptr) { | |
| 1019 connection()->SendPing(); | |
| 1020 return; | |
| 958 } | 1021 } |
| 959 return use_error_code_from_rewrite_ ? error_code_from_rewrite_ : error_code; | 1022 |
| 1023 // Set packet_ to null first. We cannot set packet_ to null after | |
| 1024 // the following write since the write may result in packet_ being | |
| 1025 // reused via a write error. | |
| 1026 scoped_refptr<StringIOBuffer> packet = packet_; | |
| 1027 packet_ = nullptr; | |
| 1028 | |
| 1029 // The connection is waiting for the original write to complete | |
| 1030 // asynchronously. The new writer will notify the connection if the | |
| 1031 // write below completes asynchronously, but a synchronous competion | |
| 1032 // must be propagated back to the connection here. | |
| 1033 WriteResult result = | |
| 1034 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | |
| 1035 ->WritePacketToSocket(packet); | |
| 1036 | |
| 1037 if (result.error_code == ERR_IO_PENDING) | |
| 1038 return; | |
| 1039 // All write errors should be mapped into ERR_IO_PENDING by | |
| 1040 // HandleWriteError. | |
| 1041 DCHECK(result.error_code >= 0); | |
| 1042 connection()->OnCanWrite(); | |
| 960 } | 1043 } |
| 961 | 1044 |
| 962 void QuicChromiumClientSession::OnWriteError(int error_code) { | 1045 void QuicChromiumClientSession::OnWriteError(int error_code) { |
| 963 DCHECK_NE(ERR_IO_PENDING, error_code); | 1046 DCHECK_NE(ERR_IO_PENDING, error_code); |
| 964 DCHECK_GT(0, error_code); | 1047 DCHECK_GT(0, error_code); |
| 965 connection()->OnWriteError(error_code); | 1048 connection()->OnWriteError(error_code); |
| 966 } | 1049 } |
| 967 | 1050 |
| 968 void QuicChromiumClientSession::OnWriteUnblocked() { | 1051 void QuicChromiumClientSession::OnWriteUnblocked() { |
| 969 connection()->OnCanWrite(); | 1052 connection()->OnCanWrite(); |
| 970 } | 1053 } |
| 971 | 1054 |
| 1055 bool QuicChromiumClientSession::ShouldWriteBlock() { | |
| 1056 return should_write_block_; | |
| 1057 } | |
| 1058 | |
| 972 void QuicChromiumClientSession::OnPathDegrading() { | 1059 void QuicChromiumClientSession::OnPathDegrading() { |
| 973 if (stream_factory_) { | 1060 if (stream_factory_) { |
| 974 stream_factory_->MaybeMigrateSingleSession(this, EARLY_MIGRATION, nullptr); | 1061 stream_factory_->MaybeMigrateSingleSession(this, EARLY_MIGRATION); |
| 975 } | 1062 } |
| 976 } | 1063 } |
| 977 | 1064 |
| 978 bool QuicChromiumClientSession::HasOpenDynamicStreams() const { | 1065 bool QuicChromiumClientSession::HasOpenDynamicStreams() const { |
| 979 return QuicSession::HasOpenDynamicStreams() || | 1066 return QuicSession::HasOpenDynamicStreams() || |
| 980 GetNumDrainingOutgoingStreams() > 0; | 1067 GetNumDrainingOutgoingStreams() > 0; |
| 981 } | 1068 } |
| 982 | 1069 |
| 983 void QuicChromiumClientSession::OnProofValid( | 1070 void QuicChromiumClientSession::OnProofValid( |
| 984 const QuicCryptoClientConfig::CachedState& cached) { | 1071 const QuicCryptoClientConfig::CachedState& cached) { |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1171 going_away_ = true; | 1258 going_away_ = true; |
| 1172 DCHECK_EQ(0u, GetNumActiveStreams()); | 1259 DCHECK_EQ(0u, GetNumActiveStreams()); |
| 1173 // Will delete |this|. | 1260 // Will delete |this|. |
| 1174 if (stream_factory_) | 1261 if (stream_factory_) |
| 1175 stream_factory_->OnSessionClosed(this); | 1262 stream_factory_->OnSessionClosed(this); |
| 1176 } | 1263 } |
| 1177 | 1264 |
| 1178 bool QuicChromiumClientSession::MigrateToSocket( | 1265 bool QuicChromiumClientSession::MigrateToSocket( |
| 1179 std::unique_ptr<DatagramClientSocket> socket, | 1266 std::unique_ptr<DatagramClientSocket> socket, |
| 1180 std::unique_ptr<QuicChromiumPacketReader> reader, | 1267 std::unique_ptr<QuicChromiumPacketReader> reader, |
| 1181 std::unique_ptr<QuicChromiumPacketWriter> writer, | 1268 std::unique_ptr<QuicChromiumPacketWriter> writer) { |
| 1182 scoped_refptr<StringIOBuffer> packet) { | |
| 1183 DCHECK_EQ(sockets_.size(), packet_readers_.size()); | 1269 DCHECK_EQ(sockets_.size(), packet_readers_.size()); |
| 1184 if (sockets_.size() >= kMaxReadersPerQuicSession) { | 1270 if (sockets_.size() >= kMaxReadersPerQuicSession) |
| 1185 return false; | 1271 return false; |
| 1186 } | 1272 |
| 1187 // TODO(jri): Make SetQuicPacketWriter take a scoped_ptr. | 1273 // TODO(jri): Make SetQuicPacketWriter take a scoped_ptr. |
| 1188 packet_readers_.push_back(std::move(reader)); | 1274 packet_readers_.push_back(std::move(reader)); |
| 1189 sockets_.push_back(std::move(socket)); | 1275 sockets_.push_back(std::move(socket)); |
| 1190 StartReading(); | 1276 StartReading(); |
| 1191 QuicChromiumPacketWriter* raw_writer = writer.get(); | |
| 1192 connection()->SetQuicPacketWriter(writer.release(), /*owns_writer=*/true); | 1277 connection()->SetQuicPacketWriter(writer.release(), /*owns_writer=*/true); |
| 1193 if (packet == nullptr) { | 1278 |
| 1194 connection()->SendPing(); | 1279 // Post task to write the pending packet or a PING packet to the new |
| 1195 return true; | 1280 // socket. Also block the writer to prevent is being used until |
| 1196 } | 1281 // WriteToNewSocket completes. |
| 1197 // Packet rewrite after migration on socket write error. | 1282 task_runner_->PostTask( |
| 1198 error_code_from_rewrite_ = raw_writer->WritePacketToSocket(packet.get()); | 1283 FROM_HERE, base::Bind(&QuicChromiumClientSession::WriteToNewSocket, |
| 1199 use_error_code_from_rewrite_ = true; | 1284 weak_factory_.GetWeakPtr())); |
| 1285 should_write_block_ = true; | |
| 1286 | |
| 1287 // Migration completed. | |
| 1288 migration_pending_ = false; | |
| 1200 return true; | 1289 return true; |
| 1201 } | 1290 } |
| 1202 | 1291 |
| 1203 void QuicChromiumClientSession::PopulateNetErrorDetails( | 1292 void QuicChromiumClientSession::PopulateNetErrorDetails( |
| 1204 NetErrorDetails* details) { | 1293 NetErrorDetails* details) { |
| 1205 details->quic_port_migration_detected = port_migration_detected_; | 1294 details->quic_port_migration_detected = port_migration_detected_; |
| 1206 } | 1295 } |
| 1207 | 1296 |
| 1208 const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket() | 1297 const DatagramClientSocket* QuicChromiumClientSession::GetDefaultSocket() |
| 1209 const { | 1298 const { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 1237 } | 1326 } |
| 1238 | 1327 |
| 1239 void QuicChromiumClientSession::DeletePromised( | 1328 void QuicChromiumClientSession::DeletePromised( |
| 1240 QuicClientPromisedInfo* promised) { | 1329 QuicClientPromisedInfo* promised) { |
| 1241 if (IsOpenStream(promised->id())) | 1330 if (IsOpenStream(promised->id())) |
| 1242 streams_pushed_and_claimed_count_++; | 1331 streams_pushed_and_claimed_count_++; |
| 1243 QuicClientSessionBase::DeletePromised(promised); | 1332 QuicClientSessionBase::DeletePromised(promised); |
| 1244 } | 1333 } |
| 1245 | 1334 |
| 1246 } // namespace net | 1335 } // namespace net |
| OLD | NEW |