1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
|
// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/host/zombie_host_detector.h"
#include "base/check.h"
#include "base/logging.h"
#include "net/base/network_change_notifier.h"
namespace {
bool IsMaxDurationExceeded(base::TimeTicks event_time,
base::TimeDelta max_duration,
const std::string& event_name) {
if (event_time.is_null()) {
VLOG(1) << "Last " << event_name << " is null.";
return false;
}
base::TimeDelta event_duration = base::TimeTicks::Now() - event_time;
DCHECK_GE(event_duration, base::TimeDelta()) << "Event duration is negative.";
bool is_exceeded = event_duration > max_duration;
if (is_exceeded) {
LOG(ERROR) << "Last " << event_name << " happened " << event_duration
<< " ago, exceeding max duration of " << max_duration;
} else {
VLOG(1) << "Last " << event_name << " happened " << event_duration
<< " ago.";
}
return is_exceeded;
}
} // namespace
namespace remoting {
// static
constexpr base::TimeDelta ZombieHostDetector::kZombieStateDetectionInterval;
constexpr base::TimeDelta ZombieHostDetector::kMaxHeartbeatInterval;
constexpr base::TimeDelta ZombieHostDetector::kMaxSignalingActiveInterval;
ZombieHostDetector::ZombieHostDetector(
base::OnceClosure on_zombie_state_detected) {
DCHECK(on_zombie_state_detected);
on_zombie_state_detected_ = std::move(on_zombie_state_detected);
}
ZombieHostDetector::~ZombieHostDetector() = default;
void ZombieHostDetector::Start() {
check_zombie_state_timer_.Start(FROM_HERE, kZombieStateDetectionInterval,
this, &ZombieHostDetector::CheckZombieState);
}
void ZombieHostDetector::OnHeartbeatSent() {
last_heartbeat_time_ = base::TimeTicks::Now();
}
void ZombieHostDetector::OnSignalingActive() {
last_signaling_active_time_ = base::TimeTicks::Now();
}
base::TimeTicks ZombieHostDetector::GetNextDetectionTime() const {
return check_zombie_state_timer_.desired_run_time();
}
void ZombieHostDetector::CheckZombieState() {
VLOG(1) << "Detecting zombie state...";
if (net::NetworkChangeNotifier::GetConnectionType() ==
net::NetworkChangeNotifier::CONNECTION_NONE) {
// The host shouldn't be considered in zombie state if it has no connection.
VLOG(1) << "No internet connectivity. Skipping zombie state check...";
previously_offline_ = true;
return;
}
if (previously_offline_) {
// If the host was previously offline, heartbeat/signaling might not have
// happened at this point due to backoff. Reset them to |now| to allow them
// to come through.
previously_offline_ = false;
VLOG(1) << "Host is going online. Previous heartbeat time: "
<< last_heartbeat_time_ << ", previous signaling active time: "
<< last_signaling_active_time_ << ". These will be reset to |now|.";
// Don't reset if they are null, which happens when the first
// heartbeat/signaling attempt has not succeeded yet.
if (!last_heartbeat_time_.is_null()) {
OnHeartbeatSent();
}
if (!last_signaling_active_time_.is_null()) {
OnSignalingActive();
}
return;
}
if (IsMaxDurationExceeded(last_heartbeat_time_, kMaxHeartbeatInterval,
"heartbeat") ||
IsMaxDurationExceeded(last_signaling_active_time_,
kMaxSignalingActiveInterval,
"signaling activity")) {
LOG(ERROR) << "Host zombie state detected.";
check_zombie_state_timer_.Stop();
std::move(on_zombie_state_detected_).Run();
return;
}
VLOG(1) << "No zombie state detected.";
}
} // namespace remoting
|