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