1 // Copyright (c) 2020 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/third_party/quiche/src/quic/core/quic_idle_network_detector.h"
6
7 #include "net/third_party/quiche/src/quic/core/quic_constants.h"
8
9 namespace quic {
10
11 namespace {
12
13 class AlarmDelegate : public QuicAlarm::Delegate {
14 public:
AlarmDelegate(QuicIdleNetworkDetector * detector)15 explicit AlarmDelegate(QuicIdleNetworkDetector* detector)
16 : detector_(detector) {}
17 AlarmDelegate(const AlarmDelegate&) = delete;
18 AlarmDelegate& operator=(const AlarmDelegate&) = delete;
19
OnAlarm()20 void OnAlarm() override { detector_->OnAlarm(); }
21
22 private:
23 QuicIdleNetworkDetector* detector_;
24 };
25
26 } // namespace
27
QuicIdleNetworkDetector(Delegate * delegate,QuicTime now,QuicConnectionArena * arena,QuicAlarmFactory * alarm_factory)28 QuicIdleNetworkDetector::QuicIdleNetworkDetector(
29 Delegate* delegate,
30 QuicTime now,
31 QuicConnectionArena* arena,
32 QuicAlarmFactory* alarm_factory)
33 : delegate_(delegate),
34 start_time_(now),
35 handshake_timeout_(QuicTime::Delta::Infinite()),
36 time_of_last_received_packet_(now),
37 time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
38 idle_network_timeout_(QuicTime::Delta::Infinite()),
39 alarm_(
40 alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
41
OnAlarm()42 void QuicIdleNetworkDetector::OnAlarm() {
43 if (handshake_timeout_.IsInfinite()) {
44 delegate_->OnIdleNetworkDetected();
45 return;
46 }
47 if (idle_network_timeout_.IsInfinite()) {
48 delegate_->OnHandshakeTimeout();
49 return;
50 }
51 if (last_network_activity_time() + idle_network_timeout_ >
52 start_time_ + handshake_timeout_) {
53 delegate_->OnHandshakeTimeout();
54 return;
55 }
56 delegate_->OnIdleNetworkDetected();
57 }
58
SetTimeouts(QuicTime::Delta handshake_timeout,QuicTime::Delta idle_network_timeout)59 void QuicIdleNetworkDetector::SetTimeouts(
60 QuicTime::Delta handshake_timeout,
61 QuicTime::Delta idle_network_timeout) {
62 handshake_timeout_ = handshake_timeout;
63 idle_network_timeout_ = idle_network_timeout;
64
65 SetAlarm();
66 }
67
StopDetection()68 void QuicIdleNetworkDetector::StopDetection() {
69 alarm_->Cancel();
70 handshake_timeout_ = QuicTime::Delta::Infinite();
71 idle_network_timeout_ = QuicTime::Delta::Infinite();
72 }
73
OnPacketSent(QuicTime now)74 void QuicIdleNetworkDetector::OnPacketSent(QuicTime now) {
75 if (time_of_first_packet_sent_after_receiving_ >
76 time_of_last_received_packet_) {
77 return;
78 }
79 time_of_first_packet_sent_after_receiving_ =
80 std::max(time_of_first_packet_sent_after_receiving_, now);
81
82 SetAlarm();
83 }
84
OnPacketReceived(QuicTime now)85 void QuicIdleNetworkDetector::OnPacketReceived(QuicTime now) {
86 time_of_last_received_packet_ = std::max(time_of_last_received_packet_, now);
87
88 SetAlarm();
89 }
90
SetAlarm()91 void QuicIdleNetworkDetector::SetAlarm() {
92 // Set alarm to the nearer deadline.
93 QuicTime new_deadline = QuicTime::Zero();
94 if (!handshake_timeout_.IsInfinite()) {
95 new_deadline = start_time_ + handshake_timeout_;
96 }
97 if (!idle_network_timeout_.IsInfinite()) {
98 const QuicTime idle_network_deadline =
99 last_network_activity_time() + idle_network_timeout_;
100 if (new_deadline.IsInitialized()) {
101 new_deadline = std::min(new_deadline, idle_network_deadline);
102 } else {
103 new_deadline = idle_network_deadline;
104 }
105 }
106 alarm_->Update(new_deadline, kAlarmGranularity);
107 }
108
109 } // namespace quic
110