File: heartbeat_sender.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (178 lines) | stat: -rw-r--r-- 6,006 bytes parent folder | download | duplicates (6)
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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef REMOTING_HOST_HEARTBEAT_SENDER_H_
#define REMOTING_HOST_HEARTBEAT_SENDER_H_

#include <memory>
#include <optional>
#include <string>

#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/sequence_checker.h"
#include "base/timer/timer.h"
#include "net/base/backoff_entry.h"
#include "remoting/host/heartbeat_service_client.h"
#include "remoting/proto/remoting/v1/directory_messages.pb.h"
#include "remoting/signaling/signal_strategy.h"

namespace base {
class TimeDelta;
}  // namespace base

namespace network {
class SharedURLLoaderFactory;
}  // namespace network

namespace remoting {

class HttpStatus;
class OAuthTokenGetter;

// HeartbeatSender periodically sends heartbeat to the directory service. See
// the HeartbeatRequest message in directory_messages.proto for more details.
//
// Normally the heartbeat indicates that the host is healthy and ready to
// accept new connections from a client, but the message can optionally include
// a host_offline_reason field, which indicates that the host cannot accept
// connections from the client (and might possibly be shutting down).  The value
// of the host_offline_reason field can be either a string from
// host_exit_codes.cc (i.e. "INVALID_HOST_CONFIGURATION" string) or one of
// kHostOfflineReasonXxx constants (i.e. "POLICY_READ_ERROR" string).
//
// The heartbeat sender will verify that the channel is in fact active before
// sending out the heartbeat. If not, it will disconnect the signaling strategy
// so that the signaling connector will try to reconnect signaling.
//
// The server sends a HeartbeatResponse in response to each successful
// heartbeat.
class HeartbeatSender final : public SignalStrategy::Listener {
 public:
  class Delegate {
   public:
    virtual ~Delegate() = default;

    // Invoked after the first successful heartbeat.
    virtual void OnFirstHeartbeatSuccessful() = 0;

    // Invoked when the host owner changes.
    virtual void OnUpdateHostOwner(const std::string& host_owner) = 0;

    // Invoked when |require_session_authorization| is set in HeartbeatResponse.
    virtual void OnUpdateRequireSessionAuthorization(bool require) = 0;

    // Invoked when the host is not found in the directory.
    virtual void OnHostNotFound() = 0;

    // Invoked when the heartbeat sender permanently fails to authenticate the
    // requests.
    virtual void OnAuthFailed() = 0;

   protected:
    Delegate() = default;
  };

  // Interface to track heartbeat events for diagnosis purpose.
  class Observer {
   public:
    virtual ~Observer() = default;

    // Invoked when the heartbeat sender has sent a heartbeat.
    virtual void OnHeartbeatSent() = 0;

   protected:
    Observer() = default;
  };

  // All raw pointers must be non-null and outlive this object.
  HeartbeatSender(
      Delegate* delegate,
      const std::string& host_id,
      SignalStrategy* signal_strategy,
      OAuthTokenGetter* oauth_token_getter,
      std::unique_ptr<HeartbeatServiceClient> service_client,
      Observer* observer,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
      bool is_googler);

  HeartbeatSender(const HeartbeatSender&) = delete;
  HeartbeatSender& operator=(const HeartbeatSender&) = delete;

  ~HeartbeatSender() override;

  // Sets host offline reason for future heartbeat, and initiates sending a
  // heartbeat right away.
  //
  // For discussion of allowed values for |host_offline_reason| argument,
  // please see the description in the class-level comments above.
  //
  // |ack_callback| will be called when the server acks receiving the
  // |host_offline_reason| or when |timeout| is reached.
  void SetHostOfflineReason(
      const std::string& host_offline_reason,
      const base::TimeDelta& timeout,
      base::OnceCallback<void(bool success)> ack_callback);

 private:

  friend class HeartbeatSenderTest;

  // SignalStrategy::Listener interface.
  void OnSignalStrategyStateChange(SignalStrategy::State state) override;
  bool OnSignalStrategyIncomingStanza(
      const jingle_xmpp::XmlElement* stanza) override;

  // Handlers for host-offline-reason completion and timeout.
  void OnHostOfflineReasonTimeout();
  void OnHostOfflineReasonAck();

  void ClearHeartbeatTimer();
  void SendFullHeartbeat();
  void SendLiteHeartbeat(bool useLiteHeartbeat);

  bool CheckHttpStatus(const HttpStatus& status);
  base::TimeDelta CalculateDelay(const HttpStatus& status,
                                 std::optional<base::TimeDelta> optMinDelay);

  void OnLegacyHeartbeatResponse(
      const HttpStatus& status,
      std::optional<base::TimeDelta> wait_interval,
      const std::string& primary_user_email,
      std::optional<bool> require_session_authorization,
      std::optional<bool> use_lite_heartbeat);
  void OnSendHeartbeatResponse(
      const HttpStatus& status,
      std::optional<base::TimeDelta> wait_interval,
      const std::string& primary_user_email,
      std::optional<bool> require_session_authorization,
      std::optional<bool> use_lite_heartbeat);

  raw_ptr<Delegate> delegate_;
  std::string host_id_;
  const raw_ptr<SignalStrategy> signal_strategy_;
  const raw_ptr<OAuthTokenGetter> oauth_token_getter_;
  std::unique_ptr<HeartbeatServiceClient> service_client_;
  raw_ptr<Observer> observer_;

  base::OneShotTimer heartbeat_timer_;

  net::BackoffEntry backoff_;

  bool initial_heartbeat_sent_ = false;

  bool set_fqdn_ = false;

  // Fields to send and indicate completion of sending host-offline-reason.
  std::string host_offline_reason_;
  base::OnceCallback<void(bool success)> host_offline_reason_ack_callback_;
  base::OneShotTimer host_offline_reason_timeout_timer_;

  SEQUENCE_CHECKER(sequence_checker_);
};

}  // namespace remoting

#endif  // REMOTING_HOST_HEARTBEAT_SENDER_H_