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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef GOOGLE_APIS_GCM_ENGINE_HEARTBEAT_MANAGER_H_
#define GOOGLE_APIS_GCM_ENGINE_HEARTBEAT_MANAGER_H_
#include <memory>
#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
#include "base/power_monitor/power_observer.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "google_apis/gcm/base/gcm_export.h"
#include "google_apis/gcm/engine/connection_factory.h"
namespace base {
class RetainingOneShotTimer;
}
namespace mcs_proto {
class HeartbeatConfig;
}
namespace gcm {
// A heartbeat management class, capable of sending and handling heartbeat
// receipt/failures and triggering reconnection as necessary.
class GCM_EXPORT HeartbeatManager : public base::PowerSuspendObserver {
public:
using ReconnectCallback =
base::RepeatingCallback<void(ConnectionFactory::ConnectionResetReason)>;
// |io_task_runner|: for running IO tasks.
// |maybe_power_wrapped_io_task_runner|: for running IO tasks, where if the
// feature is provided, it could be a wrapper on top of |io_task_runner|
// to provide power management featueres so that a delayed task posted to
// it can wake the system up from sleep to perform the task.
explicit HeartbeatManager(
scoped_refptr<base::SequencedTaskRunner> io_task_runner,
scoped_refptr<base::SequencedTaskRunner>
maybe_power_wrapped_io_task_runner);
HeartbeatManager(const HeartbeatManager&) = delete;
HeartbeatManager& operator=(const HeartbeatManager&) = delete;
~HeartbeatManager() override;
// Start the heartbeat logic.
// |send_heartbeat_callback_| is the callback the HeartbeatManager uses to
// send new heartbeats. Only one heartbeat can be outstanding at a time.
void Start(const base::RepeatingClosure& send_heartbeat_callback,
const ReconnectCallback& trigger_reconnect_callback);
// Stop the timer. Start(..) must be called again to begin sending heartbeats
// afterwards.
void Stop();
// Reset the heartbeat timer. It is valid to call this even if no heartbeat
// is associated with the ack (for example if another signal is used to
// determine that the connection is alive).
void OnHeartbeatAcked();
// Updates the current heartbeat interval.
void UpdateHeartbeatConfig(const mcs_proto::HeartbeatConfig& config);
// Returns the next scheduled heartbeat time. A null time means
// no heartbeat is pending. If non-null and less than the
// current time (in ticks), the heartbeat has been triggered and an ack is
// pending.
base::TimeTicks GetNextHeartbeatTime() const;
// Updates the timer used for scheduling heartbeats.
void UpdateHeartbeatTimer(std::unique_ptr<base::RetainingOneShotTimer> timer);
// base::PowerSuspendObserver override.
void OnSuspend() override;
void OnResume() override;
// Maximum and minimum of the custom client interval that can be requested,
// calculated based on the network conditions.
int GetMaxClientHeartbeatIntervalMs();
int GetMinClientHeartbeatIntervalMs();
// Sets, gets and validates the custom client interval. If the interval is
// less than the current custom heartbeat interval, the connection will be
// reset to update the receiving server.
void SetClientHeartbeatIntervalMs(int interval_ms);
int GetClientHeartbeatIntervalMs();
bool HasClientHeartbeatInterval();
bool IsValidClientHeartbeatInterval(int interval);
protected:
// Helper method to send heartbeat on timer trigger.
void OnHeartbeatTriggered();
// Periodic check to see if the heartbeat has been missed due to some system
// issue (e.g. the machine was suspended and the timer did not account for
// that).
void CheckForMissedHeartbeat();
private:
// Restarts the heartbeat timer.
void RestartTimer();
// Calculates and sets the current heartbeat interval.
void UpdateHeartbeatInterval();
// Calculates default heartbeat interval, depending on current network.
int GetDefaultHeartbeatInterval();
// Stops the heartbeat and triggers connection reset with a |reason|.
void ResetConnection(ConnectionFactory::ConnectionResetReason reason);
// The base::Time at which the heartbeat timer is expected to fire. Used to
// check if a heartbeat was somehow lost/delayed.
base::Time heartbeat_expected_time_;
// Whether the last heartbeat ping sent has been acknowledged or not.
bool waiting_for_ack_;
// The current heartbeat interval.
int heartbeat_interval_ms_;
// The most recent server-provided heartbeat interval (0 if none has been
// provided).
int server_interval_ms_;
// Custom interval requested by the client.
int client_interval_ms_;
const scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
// Timer for triggering heartbeats.
std::unique_ptr<base::RetainingOneShotTimer> heartbeat_timer_;
// Time at which the machine was last suspended.
base::Time suspend_time_;
// Callbacks for interacting with the the connection.
base::RepeatingClosure send_heartbeat_callback_;
ReconnectCallback trigger_reconnect_callback_;
base::WeakPtrFactory<HeartbeatManager> weak_ptr_factory_{this};
};
} // namespace gcm
#endif // GOOGLE_APIS_GCM_ENGINE_HEARTBEAT_MANAGER_H_
|