| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/quic/quic_multipath_sent_packet_manager.h" | |
| 6 | |
| 7 #include <cstdint> | |
| 8 | |
| 9 #include "base/strings/string_number_conversions.h" | |
| 10 #include "net/quic/quic_bug_tracker.h" | |
| 11 | |
| 12 using std::string; | |
| 13 using std::max; | |
| 14 | |
| 15 namespace net { | |
| 16 | |
| 17 QuicMultipathSentPacketManager::QuicMultipathSentPacketManager( | |
| 18 QuicSentPacketManagerInterface* manager, | |
| 19 QuicConnectionCloseDelegateInterface* delegate) | |
| 20 : delegate_(delegate) { | |
| 21 path_managers_info_.push_back(PathSentPacketManagerInfo(manager, ACTIVE)); | |
| 22 } | |
| 23 | |
| 24 QuicMultipathSentPacketManager::~QuicMultipathSentPacketManager() { | |
| 25 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 26 delete path_manager_info.manager; | |
| 27 } | |
| 28 } | |
| 29 | |
| 30 void QuicMultipathSentPacketManager::SetFromConfig(const QuicConfig& config) { | |
| 31 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 32 if (path_manager_info.manager != nullptr) { | |
| 33 path_manager_info.manager->SetFromConfig(config); | |
| 34 } | |
| 35 } | |
| 36 } | |
| 37 | |
| 38 void QuicMultipathSentPacketManager::ResumeConnectionState( | |
| 39 const CachedNetworkParameters& cached_network_params, | |
| 40 bool max_bandwidth_resumption) { | |
| 41 QuicSentPacketManagerInterface* path_manager = | |
| 42 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 43 if (path_manager == nullptr) { | |
| 44 OnUnrecoverablePathError(kDefaultPathId); | |
| 45 return; | |
| 46 } | |
| 47 path_manager->ResumeConnectionState(cached_network_params, | |
| 48 max_bandwidth_resumption); | |
| 49 } | |
| 50 | |
| 51 void QuicMultipathSentPacketManager::SetNumOpenStreams(size_t num_streams) { | |
| 52 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 53 if (path_manager_info.manager != nullptr) { | |
| 54 path_manager_info.manager->SetNumOpenStreams(num_streams); | |
| 55 } | |
| 56 } | |
| 57 } | |
| 58 | |
| 59 void QuicMultipathSentPacketManager::SetMaxPacingRate( | |
| 60 QuicBandwidth max_pacing_rate) { | |
| 61 QuicSentPacketManagerInterface* path_manager = | |
| 62 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 63 if (path_manager == nullptr) { | |
| 64 OnUnrecoverablePathError(kDefaultPathId); | |
| 65 return; | |
| 66 } | |
| 67 path_manager->SetMaxPacingRate(max_pacing_rate); | |
| 68 } | |
| 69 | |
| 70 void QuicMultipathSentPacketManager::SetHandshakeConfirmed() { | |
| 71 QuicSentPacketManagerInterface* path_manager = | |
| 72 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 73 if (path_manager == nullptr) { | |
| 74 OnUnrecoverablePathError(kDefaultPathId); | |
| 75 return; | |
| 76 } | |
| 77 path_manager->SetHandshakeConfirmed(); | |
| 78 } | |
| 79 | |
| 80 void QuicMultipathSentPacketManager::OnIncomingAck( | |
| 81 const QuicAckFrame& ack_frame, | |
| 82 QuicTime ack_receive_time) { | |
| 83 if (ack_frame.path_id >= path_managers_info_.size() || | |
| 84 path_managers_info_[ack_frame.path_id].state != ACTIVE) { | |
| 85 return; | |
| 86 } | |
| 87 path_managers_info_[ack_frame.path_id].manager->OnIncomingAck( | |
| 88 ack_frame, ack_receive_time); | |
| 89 } | |
| 90 | |
| 91 void QuicMultipathSentPacketManager::RetransmitUnackedPackets( | |
| 92 TransmissionType retransmission_type) { | |
| 93 QuicSentPacketManagerInterface* path_manager = | |
| 94 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 95 if (path_manager == nullptr) { | |
| 96 OnUnrecoverablePathError(kDefaultPathId); | |
| 97 return; | |
| 98 } | |
| 99 path_manager->RetransmitUnackedPackets(retransmission_type); | |
| 100 } | |
| 101 | |
| 102 bool QuicMultipathSentPacketManager::MaybeRetransmitTailLossProbe() { | |
| 103 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 104 if (path_manager_info.manager != nullptr && | |
| 105 path_manager_info.state == ACTIVE) { | |
| 106 if (path_manager_info.manager->MaybeRetransmitTailLossProbe()) { | |
| 107 return true; | |
| 108 } | |
| 109 } | |
| 110 } | |
| 111 return false; | |
| 112 } | |
| 113 | |
| 114 void QuicMultipathSentPacketManager::NeuterUnencryptedPackets() { | |
| 115 QuicSentPacketManagerInterface* path_manager = | |
| 116 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 117 if (path_manager == nullptr) { | |
| 118 OnUnrecoverablePathError(kDefaultPathId); | |
| 119 return; | |
| 120 } | |
| 121 path_manager->NeuterUnencryptedPackets(); | |
| 122 } | |
| 123 | |
| 124 bool QuicMultipathSentPacketManager::HasPendingRetransmissions() const { | |
| 125 // TODO(fayang): Move pending_retransmissions_ from path sent packet manager | |
| 126 // to multipath sent packet manager. | |
| 127 QuicSentPacketManagerInterface* path_manager = | |
| 128 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 129 return path_manager != nullptr && path_manager->HasPendingRetransmissions(); | |
| 130 } | |
| 131 | |
| 132 PendingRetransmission | |
| 133 QuicMultipathSentPacketManager::NextPendingRetransmission() { | |
| 134 // TODO(fayang): Move pending_retransmissions_ from path sent packet manager | |
| 135 // to multipath sent packet manager. | |
| 136 QuicSentPacketManagerInterface* path_manager = | |
| 137 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 138 if (path_manager == nullptr) { | |
| 139 OnUnrecoverablePathError(kDefaultPathId); | |
| 140 QuicFrames retransmittable_frames; | |
| 141 return PendingRetransmission(kInvalidPathId, 0u, NOT_RETRANSMISSION, | |
| 142 retransmittable_frames, false, 0, | |
| 143 ENCRYPTION_NONE, PACKET_1BYTE_PACKET_NUMBER); | |
| 144 } | |
| 145 return path_manager->NextPendingRetransmission(); | |
| 146 } | |
| 147 | |
| 148 bool QuicMultipathSentPacketManager::HasUnackedPackets() const { | |
| 149 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 150 if (path_manager_info.manager != nullptr && | |
| 151 path_manager_info.state == ACTIVE && | |
| 152 path_manager_info.manager->HasUnackedPackets()) { | |
| 153 return true; | |
| 154 } | |
| 155 } | |
| 156 return false; | |
| 157 } | |
| 158 | |
| 159 QuicPacketNumber QuicMultipathSentPacketManager::GetLeastUnacked( | |
| 160 QuicPathId path_id) const { | |
| 161 QuicSentPacketManagerInterface* path_manager = | |
| 162 MaybeGetSentPacketManagerForPath(path_id); | |
| 163 if (path_manager == nullptr) { | |
| 164 return 0; | |
| 165 } | |
| 166 return path_manager->GetLeastUnacked(path_id); | |
| 167 } | |
| 168 | |
| 169 bool QuicMultipathSentPacketManager::OnPacketSent( | |
| 170 SerializedPacket* serialized_packet, | |
| 171 QuicPathId original_path_id, | |
| 172 QuicPacketNumber original_packet_number, | |
| 173 QuicTime sent_time, | |
| 174 TransmissionType transmission_type, | |
| 175 HasRetransmittableData has_retransmittable_data) { | |
| 176 QuicSentPacketManagerInterface* path_manager = | |
| 177 MaybeGetSentPacketManagerForActivePath(serialized_packet->path_id); | |
| 178 // TODO(fayang): Handle packets retransmitted on different path. | |
| 179 DCHECK(original_packet_number == 0 || | |
| 180 original_path_id == serialized_packet->path_id); | |
| 181 if (path_manager == nullptr) { | |
| 182 OnUnrecoverablePathError(serialized_packet->path_id); | |
| 183 return false; | |
| 184 } | |
| 185 | |
| 186 return path_manager->OnPacketSent( | |
| 187 serialized_packet, original_path_id, original_packet_number, sent_time, | |
| 188 transmission_type, has_retransmittable_data); | |
| 189 } | |
| 190 | |
| 191 void QuicMultipathSentPacketManager::OnRetransmissionTimeout() { | |
| 192 QuicPathId rto_path = DetermineRetransmissionTimeoutPath(); | |
| 193 DCHECK_NE(kInvalidPathId, rto_path); | |
| 194 QuicSentPacketManagerInterface* path_manager = | |
| 195 MaybeGetSentPacketManagerForActivePath(rto_path); | |
| 196 if (path_manager == nullptr) { | |
| 197 OnUnrecoverablePathError(rto_path); | |
| 198 return; | |
| 199 } | |
| 200 path_manager->OnRetransmissionTimeout(); | |
| 201 } | |
| 202 | |
| 203 QuicTime::Delta QuicMultipathSentPacketManager::TimeUntilSend( | |
| 204 QuicTime now, | |
| 205 HasRetransmittableData retransmittable, | |
| 206 QuicPathId* path_id) { | |
| 207 QuicTime::Delta delay = QuicTime::Delta::Infinite(); | |
| 208 *path_id = kInvalidPathId; | |
| 209 for (size_t i = 0; i < path_managers_info_.size(); ++i) { | |
| 210 if (path_managers_info_[i].manager == nullptr || | |
| 211 path_managers_info_[i].state != ACTIVE) { | |
| 212 continue; | |
| 213 } | |
| 214 | |
| 215 QuicTime::Delta path_delay = path_managers_info_[i].manager->TimeUntilSend( | |
| 216 now, retransmittable, path_id); | |
| 217 if (!path_delay.IsInfinite() && path_delay < delay) { | |
| 218 delay = path_delay; | |
| 219 *path_id = i; | |
| 220 } | |
| 221 } | |
| 222 DCHECK(*path_id == kInvalidPathId || !delay.IsInfinite()); | |
| 223 return delay; | |
| 224 } | |
| 225 | |
| 226 const QuicTime QuicMultipathSentPacketManager::GetRetransmissionTime() const { | |
| 227 QuicTime retransmission_time = QuicTime::Zero(); | |
| 228 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 229 if (path_manager_info.manager == nullptr || | |
| 230 path_manager_info.state != ACTIVE) { | |
| 231 continue; | |
| 232 } | |
| 233 QuicTime path_retransmission_time = | |
| 234 path_manager_info.manager->GetRetransmissionTime(); | |
| 235 if (!path_retransmission_time.IsInitialized()) { | |
| 236 continue; | |
| 237 } | |
| 238 if (!retransmission_time.IsInitialized() || | |
| 239 path_retransmission_time < retransmission_time) { | |
| 240 retransmission_time = path_retransmission_time; | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 return retransmission_time; | |
| 245 } | |
| 246 | |
| 247 const RttStats* QuicMultipathSentPacketManager::GetRttStats() const { | |
| 248 QuicSentPacketManagerInterface* path_manager = | |
| 249 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 250 if (path_manager == nullptr) { | |
| 251 return nullptr; | |
| 252 } | |
| 253 return path_manager->GetRttStats(); | |
| 254 } | |
| 255 | |
| 256 QuicBandwidth QuicMultipathSentPacketManager::BandwidthEstimate() const { | |
| 257 QuicSentPacketManagerInterface* path_manager = | |
| 258 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 259 if (path_manager == nullptr) { | |
| 260 return QuicBandwidth::Zero(); | |
| 261 } | |
| 262 return path_manager->BandwidthEstimate(); | |
| 263 } | |
| 264 | |
| 265 const QuicSustainedBandwidthRecorder* | |
| 266 QuicMultipathSentPacketManager::SustainedBandwidthRecorder() const { | |
| 267 QuicSentPacketManagerInterface* path_manager = | |
| 268 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 269 if (path_manager == nullptr) { | |
| 270 return nullptr; | |
| 271 } | |
| 272 return path_manager->SustainedBandwidthRecorder(); | |
| 273 } | |
| 274 | |
| 275 QuicPacketCount QuicMultipathSentPacketManager::GetCongestionWindowInTcpMss() | |
| 276 const { | |
| 277 QuicSentPacketManagerInterface* path_manager = | |
| 278 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 279 if (path_manager == nullptr) { | |
| 280 return 0; | |
| 281 } | |
| 282 return path_manager->GetCongestionWindowInTcpMss(); | |
| 283 } | |
| 284 | |
| 285 QuicPacketCount QuicMultipathSentPacketManager::EstimateMaxPacketsInFlight( | |
| 286 QuicByteCount max_packet_length) const { | |
| 287 QuicPacketCount max_packets_in_flight = 0; | |
| 288 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 289 if (path_manager_info.manager != nullptr) { | |
| 290 max_packets_in_flight = | |
| 291 max(max_packets_in_flight, | |
| 292 path_manager_info.manager->EstimateMaxPacketsInFlight( | |
| 293 max_packet_length)); | |
| 294 } | |
| 295 } | |
| 296 DCHECK_LT(0u, max_packets_in_flight); | |
| 297 return max_packets_in_flight; | |
| 298 } | |
| 299 | |
| 300 QuicByteCount QuicMultipathSentPacketManager::GetCongestionWindowInBytes() | |
| 301 const { | |
| 302 QuicSentPacketManagerInterface* path_manager = | |
| 303 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 304 if (path_manager == nullptr) { | |
| 305 return 0; | |
| 306 } | |
| 307 return path_manager->GetCongestionWindowInBytes(); | |
| 308 } | |
| 309 | |
| 310 QuicPacketCount QuicMultipathSentPacketManager::GetSlowStartThresholdInTcpMss() | |
| 311 const { | |
| 312 QuicSentPacketManagerInterface* path_manager = | |
| 313 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 314 if (path_manager == nullptr) { | |
| 315 return 0; | |
| 316 } | |
| 317 return path_manager->GetSlowStartThresholdInTcpMss(); | |
| 318 } | |
| 319 | |
| 320 void QuicMultipathSentPacketManager::CancelRetransmissionsForStream( | |
| 321 QuicStreamId stream_id) { | |
| 322 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 323 if (path_manager_info.manager != nullptr) { | |
| 324 path_manager_info.manager->CancelRetransmissionsForStream(stream_id); | |
| 325 } | |
| 326 } | |
| 327 } | |
| 328 | |
| 329 void QuicMultipathSentPacketManager::OnConnectionMigration( | |
| 330 QuicPathId path_id, | |
| 331 PeerAddressChangeType type) { | |
| 332 QuicSentPacketManagerInterface* path_manager = | |
| 333 MaybeGetSentPacketManagerForActivePath(path_id); | |
| 334 if (path_manager == nullptr) { | |
| 335 OnUnrecoverablePathError(path_id); | |
| 336 return; | |
| 337 } | |
| 338 path_manager->OnConnectionMigration(path_id, type); | |
| 339 } | |
| 340 | |
| 341 bool QuicMultipathSentPacketManager::IsHandshakeConfirmed() const { | |
| 342 QuicSentPacketManagerInterface* path_manager = | |
| 343 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 344 return path_manager != nullptr && path_manager->IsHandshakeConfirmed(); | |
| 345 } | |
| 346 | |
| 347 void QuicMultipathSentPacketManager::SetDebugDelegate( | |
| 348 DebugDelegate* debug_delegate) { | |
| 349 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 350 if (path_manager_info.manager == nullptr) { | |
| 351 continue; | |
| 352 } | |
| 353 path_manager_info.manager->SetDebugDelegate(debug_delegate); | |
| 354 } | |
| 355 } | |
| 356 | |
| 357 QuicPacketNumber QuicMultipathSentPacketManager::GetLargestObserved( | |
| 358 QuicPathId path_id) const { | |
| 359 QuicSentPacketManagerInterface* path_manager = | |
| 360 MaybeGetSentPacketManagerForPath(path_id); | |
| 361 if (path_manager == nullptr) { | |
| 362 return 0; | |
| 363 } | |
| 364 return path_manager->GetLargestObserved(path_id); | |
| 365 } | |
| 366 | |
| 367 QuicPacketNumber QuicMultipathSentPacketManager::GetLargestSentPacket( | |
| 368 QuicPathId path_id) const { | |
| 369 QuicSentPacketManagerInterface* path_manager = | |
| 370 MaybeGetSentPacketManagerForPath(path_id); | |
| 371 if (path_manager == nullptr) { | |
| 372 return 0; | |
| 373 } | |
| 374 return path_manager->GetLargestSentPacket(path_id); | |
| 375 } | |
| 376 | |
| 377 QuicPacketNumber QuicMultipathSentPacketManager::GetLeastPacketAwaitedByPeer( | |
| 378 QuicPathId path_id) const { | |
| 379 QuicSentPacketManagerInterface* path_manager = | |
| 380 MaybeGetSentPacketManagerForPath(path_id); | |
| 381 if (path_manager == nullptr) { | |
| 382 return 0; | |
| 383 } | |
| 384 return path_manager->GetLeastPacketAwaitedByPeer(path_id); | |
| 385 } | |
| 386 | |
| 387 void QuicMultipathSentPacketManager::SetNetworkChangeVisitor( | |
| 388 NetworkChangeVisitor* visitor) { | |
| 389 for (PathSentPacketManagerInfo path_manager_info : path_managers_info_) { | |
| 390 if (path_manager_info.manager == nullptr || | |
| 391 path_manager_info.state != ACTIVE) { | |
| 392 continue; | |
| 393 } | |
| 394 path_manager_info.manager->SetNetworkChangeVisitor(visitor); | |
| 395 } | |
| 396 } | |
| 397 | |
| 398 bool QuicMultipathSentPacketManager::InSlowStart() const { | |
| 399 QuicSentPacketManagerInterface* path_manager = | |
| 400 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 401 return path_manager != nullptr && path_manager->InSlowStart(); | |
| 402 } | |
| 403 | |
| 404 size_t QuicMultipathSentPacketManager::GetConsecutiveRtoCount() const { | |
| 405 QuicSentPacketManagerInterface* path_manager = | |
| 406 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 407 if (path_manager == nullptr) { | |
| 408 return 0; | |
| 409 } | |
| 410 return path_manager->GetConsecutiveRtoCount(); | |
| 411 } | |
| 412 size_t QuicMultipathSentPacketManager::GetConsecutiveTlpCount() const { | |
| 413 QuicSentPacketManagerInterface* path_manager = | |
| 414 MaybeGetSentPacketManagerForActivePath(kDefaultPathId); | |
| 415 if (path_manager == nullptr) { | |
| 416 return 0; | |
| 417 } | |
| 418 return path_manager->GetConsecutiveTlpCount(); | |
| 419 } | |
| 420 | |
| 421 QuicMultipathSentPacketManager::PathSentPacketManagerInfo:: | |
| 422 PathSentPacketManagerInfo() | |
| 423 : manager(nullptr), state(CLOSING) {} | |
| 424 | |
| 425 QuicMultipathSentPacketManager::PathSentPacketManagerInfo:: | |
| 426 PathSentPacketManagerInfo(QuicSentPacketManagerInterface* manager, | |
| 427 PathSentPacketManagerState state) | |
| 428 : manager(manager), state(state) {} | |
| 429 | |
| 430 QuicMultipathSentPacketManager::PathSentPacketManagerInfo:: | |
| 431 PathSentPacketManagerInfo(const PathSentPacketManagerInfo& other) = default; | |
| 432 | |
| 433 QuicSentPacketManagerInterface* | |
| 434 QuicMultipathSentPacketManager::MaybeGetSentPacketManagerForPath( | |
| 435 QuicPathId path_id) const { | |
| 436 if (path_id >= path_managers_info_.size() || | |
| 437 path_managers_info_[path_id].manager == nullptr) { | |
| 438 QUIC_BUG << "Sent packet manager of path: (" + base::IntToString(path_id) + | |
| 439 ") must exist but does not."; | |
| 440 return nullptr; | |
| 441 } | |
| 442 | |
| 443 return path_managers_info_[path_id].manager; | |
| 444 } | |
| 445 | |
| 446 QuicSentPacketManagerInterface* | |
| 447 QuicMultipathSentPacketManager::MaybeGetSentPacketManagerForActivePath( | |
| 448 QuicPathId path_id) const { | |
| 449 QuicSentPacketManagerInterface* path_manager = | |
| 450 MaybeGetSentPacketManagerForPath(path_id); | |
| 451 if (path_manager == nullptr) { | |
| 452 return nullptr; | |
| 453 } | |
| 454 if (path_managers_info_[path_id].state != ACTIVE) { | |
| 455 QUIC_BUG << "Sent packet manager of path: (" + base::IntToString(path_id) + | |
| 456 ") must be active but is not."; | |
| 457 return nullptr; | |
| 458 } | |
| 459 | |
| 460 return path_manager; | |
| 461 } | |
| 462 | |
| 463 QuicPathId QuicMultipathSentPacketManager::DetermineRetransmissionTimeoutPath() | |
| 464 const { | |
| 465 QuicTime retransmission_time = QuicTime::Zero(); | |
| 466 QuicPathId rto_path = kInvalidPathId; | |
| 467 for (size_t i = 0; i < path_managers_info_.size(); ++i) { | |
| 468 if (path_managers_info_[i].manager == nullptr || | |
| 469 path_managers_info_[i].state != ACTIVE) { | |
| 470 continue; | |
| 471 } | |
| 472 QuicTime path_retransmission_time = | |
| 473 path_managers_info_[i].manager->GetRetransmissionTime(); | |
| 474 if (!path_retransmission_time.IsInitialized()) { | |
| 475 continue; | |
| 476 } | |
| 477 if (!retransmission_time.IsInitialized() || | |
| 478 path_retransmission_time < retransmission_time) { | |
| 479 retransmission_time = path_retransmission_time; | |
| 480 rto_path = i; | |
| 481 } | |
| 482 } | |
| 483 return rto_path; | |
| 484 } | |
| 485 | |
| 486 void QuicMultipathSentPacketManager::OnUnrecoverablePathError( | |
| 487 QuicPathId path_id) { | |
| 488 if (MaybeGetSentPacketManagerForPath(path_id) == nullptr) { | |
| 489 const string error_details = "Sent packet manager of path: (" + | |
| 490 base::IntToString(path_id) + | |
| 491 ") must exist but does not."; | |
| 492 delegate_->OnUnrecoverableError(QUIC_MULTIPATH_PATH_DOES_NOT_EXIST, | |
| 493 error_details, | |
| 494 ConnectionCloseSource::FROM_SELF); | |
| 495 return; | |
| 496 } | |
| 497 const string error_details = "Sent packet manager of path: (" + | |
| 498 base::IntToString(path_id) + | |
| 499 ") must be active but is not."; | |
| 500 delegate_->OnUnrecoverableError(QUIC_MULTIPATH_PATH_NOT_ACTIVE, error_details, | |
| 501 ConnectionCloseSource::FROM_SELF); | |
| 502 } | |
| 503 | |
| 504 } // namespace net | |
| OLD | NEW |