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 <openssl/ssl.h> | 7 #include <openssl/ssl.h> |
8 | 8 |
9 #include <utility> | 9 #include <utility> |
10 | 10 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 // connection migration. A new Reader is created every time this endpoint's | 50 // connection migration. A new Reader is created every time this endpoint's |
51 // IP address changes. | 51 // IP address changes. |
52 const size_t kMaxReadersPerQuicSession = 5; | 52 const size_t kMaxReadersPerQuicSession = 5; |
53 | 53 |
54 // Size of the MRU cache of Token Binding signatures. Since the material being | 54 // Size of the MRU cache of Token Binding signatures. Since the material being |
55 // signed is constant and there aren't many keys being used to sign, a fairly | 55 // signed is constant and there aren't many keys being used to sign, a fairly |
56 // small number was chosen, somewhat arbitrarily, and to match | 56 // small number was chosen, somewhat arbitrarily, and to match |
57 // SSLClientSocketImpl. | 57 // SSLClientSocketImpl. |
58 const size_t kTokenBindingSignatureMapSize = 10; | 58 const size_t kTokenBindingSignatureMapSize = 10; |
59 | 59 |
| 60 // Time to wait (in seconds) when no networks are available and |
| 61 // migrating sessions need to wait for a new network to connect. |
| 62 const size_t kWaitTimeForNewNetworkSecs = 10; |
| 63 |
60 // Histograms for tracking down the crashes from http://crbug.com/354669 | 64 // Histograms for tracking down the crashes from http://crbug.com/354669 |
61 // Note: these values must be kept in sync with the corresponding values in: | 65 // Note: these values must be kept in sync with the corresponding values in: |
62 // tools/metrics/histograms/histograms.xml | 66 // tools/metrics/histograms/histograms.xml |
63 enum Location { | 67 enum Location { |
64 DESTRUCTOR = 0, | 68 DESTRUCTOR = 0, |
65 ADD_OBSERVER = 1, | 69 ADD_OBSERVER = 1, |
66 TRY_CREATE_STREAM = 2, | 70 TRY_CREATE_STREAM = 2, |
67 CREATE_OUTGOING_RELIABLE_STREAM = 3, | 71 CREATE_OUTGOING_RELIABLE_STREAM = 3, |
68 NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4, | 72 NOTIFY_FACTORY_OF_SESSION_CLOSED_LATER = 4, |
69 NOTIFY_FACTORY_OF_SESSION_CLOSED = 5, | 73 NOTIFY_FACTORY_OF_SESSION_CLOSED = 5, |
(...skipping 923 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
993 // that the actual migration happens from the message loop instead | 997 // that the actual migration happens from the message loop instead |
994 // of under the call stack of QuicConnection::WritePacket. | 998 // of under the call stack of QuicConnection::WritePacket. |
995 return ERR_IO_PENDING; | 999 return ERR_IO_PENDING; |
996 } | 1000 } |
997 | 1001 |
998 void QuicChromiumClientSession::MigrateSessionOnWriteError() { | 1002 void QuicChromiumClientSession::MigrateSessionOnWriteError() { |
999 // If migration_pending_ is false, an earlier task completed migration. | 1003 // If migration_pending_ is false, an earlier task completed migration. |
1000 if (!migration_pending_) | 1004 if (!migration_pending_) |
1001 return; | 1005 return; |
1002 | 1006 |
1003 if (stream_factory_ != nullptr && | 1007 MigrationResult result = MigrationResult::FAILURE; |
1004 stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR) == | 1008 if (stream_factory_ != nullptr) |
1005 MigrationResult::SUCCESS) { | 1009 result = stream_factory_->MaybeMigrateSingleSession(this, WRITE_ERROR); |
| 1010 |
| 1011 if (result == MigrationResult::SUCCESS) |
| 1012 return; |
| 1013 |
| 1014 if (result == MigrationResult::NO_NEW_NETWORK) { |
| 1015 OnNoNewNetwork(); |
1006 return; | 1016 return; |
1007 } | 1017 } |
1008 | 1018 |
1009 // Close the connection if migration failed. Do not cause a | 1019 // Close the connection if migration failed. Do not cause a |
1010 // connection close packet to be sent since socket may be borked. | 1020 // connection close packet to be sent since socket may be borked. |
1011 connection()->CloseConnection(QUIC_PACKET_WRITE_ERROR, | 1021 connection()->CloseConnection(QUIC_PACKET_WRITE_ERROR, |
1012 "Write and subsequent migration failed", | 1022 "Write and subsequent migration failed", |
1013 ConnectionCloseBehavior::SILENT_CLOSE); | 1023 ConnectionCloseBehavior::SILENT_CLOSE); |
1014 } | 1024 } |
1015 | 1025 |
| 1026 void QuicChromiumClientSession::OnNoNewNetwork() { |
| 1027 migration_pending_ = true; |
| 1028 |
| 1029 // Block the packet writer to avoid any writes while migration is in progress. |
| 1030 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) |
| 1031 ->set_write_blocked(true); |
| 1032 |
| 1033 // Post a task to maybe close the session if the alarm fires. |
| 1034 task_runner_->PostDelayedTask( |
| 1035 FROM_HERE, base::Bind(&QuicChromiumClientSession::OnMigrationTimeout, |
| 1036 weak_factory_.GetWeakPtr(), sockets_.size()), |
| 1037 base::TimeDelta::FromSeconds(kWaitTimeForNewNetworkSecs)); |
| 1038 } |
| 1039 |
1016 void QuicChromiumClientSession::WriteToNewSocket() { | 1040 void QuicChromiumClientSession::WriteToNewSocket() { |
1017 // Prevent any pending migration from executing. | 1041 // Prevent any pending migration from executing. |
1018 migration_pending_ = false; | 1042 migration_pending_ = false; |
1019 | |
1020 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | 1043 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) |
1021 ->set_write_blocked(false); | 1044 ->set_write_blocked(false); |
1022 DCHECK(!connection()->writer()->IsWriteBlocked()); | |
1023 | |
1024 if (packet_ == nullptr) { | 1045 if (packet_ == nullptr) { |
1025 // Unblock the connection before sending a PING packet, since it | 1046 // Unblock the connection before sending a PING packet, since it |
1026 // may have been blocked before the migration started. | 1047 // may have been blocked before the migration started. |
1027 connection()->OnCanWrite(); | 1048 connection()->OnCanWrite(); |
1028 connection()->SendPing(); | 1049 connection()->SendPing(); |
1029 return; | 1050 return; |
1030 } | 1051 } |
1031 | 1052 |
1032 // Set packet_ to null first before calling WritePacketToSocket since | 1053 // Set packet_ to null first before calling WritePacketToSocket since |
1033 // that method may set packet_ if there is a write error. | 1054 // that method may set packet_ if there is a write error. |
1034 scoped_refptr<StringIOBuffer> packet = packet_; | 1055 scoped_refptr<StringIOBuffer> packet = packet_; |
1035 packet_ = nullptr; | 1056 packet_ = nullptr; |
1036 | 1057 |
1037 // The connection is waiting for the original write to complete | 1058 // The connection is waiting for the original write to complete |
1038 // asynchronously. The new writer will notify the connection if the | 1059 // asynchronously. The new writer will notify the connection if the |
1039 // write below completes asynchronously, but a synchronous competion | 1060 // write below completes asynchronously, but a synchronous competion |
1040 // must be propagated back to the connection here. | 1061 // must be propagated back to the connection here. |
1041 WriteResult result = | 1062 WriteResult result = |
1042 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) | 1063 static_cast<QuicChromiumPacketWriter*>(connection()->writer()) |
1043 ->WritePacketToSocket(packet); | 1064 ->WritePacketToSocket(packet); |
1044 | |
1045 if (result.error_code == ERR_IO_PENDING) | 1065 if (result.error_code == ERR_IO_PENDING) |
1046 return; | 1066 return; |
| 1067 |
1047 // All write errors should be mapped into ERR_IO_PENDING by | 1068 // All write errors should be mapped into ERR_IO_PENDING by |
1048 // HandleWriteError. | 1069 // HandleWriteError. |
1049 DCHECK_LT(0, result.error_code); | 1070 DCHECK_LT(0, result.error_code); |
1050 connection()->OnCanWrite(); | 1071 connection()->OnCanWrite(); |
1051 } | 1072 } |
1052 | 1073 |
| 1074 void QuicChromiumClientSession::OnMigrationTimeout(size_t num_sockets) { |
| 1075 // If number of sockets has changed, this migration task is stale. |
| 1076 if (num_sockets != sockets_.size()) |
| 1077 return; |
| 1078 UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.ConnectionMigration", |
| 1079 MIGRATION_STATUS_NO_ALTERNATE_NETWORK, |
| 1080 MIGRATION_STATUS_MAX); |
| 1081 CloseSessionOnError(ERR_NETWORK_CHANGED, |
| 1082 QUIC_CONNECTION_MIGRATION_NO_NEW_NETWORK); |
| 1083 } |
| 1084 |
| 1085 void QuicChromiumClientSession::OnNetworkConnected( |
| 1086 NetworkChangeNotifier::NetworkHandle network, |
| 1087 const BoundNetLog& bound_net_log) { |
| 1088 // If migration_pending_ is false, there was no migration pending or |
| 1089 // an earlier task completed migration. |
| 1090 if (!migration_pending_) |
| 1091 return; |
| 1092 |
| 1093 // TODO(jri): Ensure that OnSessionGoingAway is called consistently, |
| 1094 // and that it's always called at the same time in the whole |
| 1095 // migration process. Allows tests to be more uniform. |
| 1096 stream_factory_->OnSessionGoingAway(this); |
| 1097 stream_factory_->MigrateSessionToNewNetwork( |
| 1098 this, network, /*close_session_on_error=*/true, net_log_); |
| 1099 } |
| 1100 |
1053 void QuicChromiumClientSession::OnWriteError(int error_code) { | 1101 void QuicChromiumClientSession::OnWriteError(int error_code) { |
1054 DCHECK_NE(ERR_IO_PENDING, error_code); | 1102 DCHECK_NE(ERR_IO_PENDING, error_code); |
1055 DCHECK_GT(0, error_code); | 1103 DCHECK_GT(0, error_code); |
1056 connection()->OnWriteError(error_code); | 1104 connection()->OnWriteError(error_code); |
1057 } | 1105 } |
1058 | 1106 |
1059 void QuicChromiumClientSession::OnWriteUnblocked() { | 1107 void QuicChromiumClientSession::OnWriteUnblocked() { |
1060 connection()->OnCanWrite(); | 1108 connection()->OnCanWrite(); |
1061 } | 1109 } |
1062 | 1110 |
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1331 } | 1379 } |
1332 | 1380 |
1333 void QuicChromiumClientSession::DeletePromised( | 1381 void QuicChromiumClientSession::DeletePromised( |
1334 QuicClientPromisedInfo* promised) { | 1382 QuicClientPromisedInfo* promised) { |
1335 if (IsOpenStream(promised->id())) | 1383 if (IsOpenStream(promised->id())) |
1336 streams_pushed_and_claimed_count_++; | 1384 streams_pushed_and_claimed_count_++; |
1337 QuicClientSessionBase::DeletePromised(promised); | 1385 QuicClientSessionBase::DeletePromised(promised); |
1338 } | 1386 } |
1339 | 1387 |
1340 } // namespace net | 1388 } // namespace net |
OLD | NEW |