[Clean-up] Remove NetworkStats code, which has been dead code since July 2014.
[chromium-blink-merge.git] / remoting / host / heartbeat_sender.h
blob84a6ad077c4db666646f39e7c9e126bbea11ca7f
1 // Copyright (c) 2012 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.
5 #ifndef REMOTING_HOST_HEARTBEAT_SENDER_H_
6 #define REMOTING_HOST_HEARTBEAT_SENDER_H_
8 #include <string>
10 #include "base/callback.h"
11 #include "base/compiler_specific.h"
12 #include "base/gtest_prod_util.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/threading/thread_checker.h"
16 #include "base/timer/timer.h"
17 #include "remoting/base/rsa_key_pair.h"
18 #include "remoting/signaling/signal_strategy.h"
20 namespace base {
21 class MessageLoopProxy;
22 class TimeDelta;
23 } // namespace base
25 namespace buzz {
26 class XmlElement;
27 } // namespace buzz
29 namespace remoting {
31 class RsaKeyPair;
32 class IqRequest;
33 class IqSender;
35 // HeartbeatSender periodically sends heartbeat stanzas to the Chromoting Bot.
36 // Each heartbeat stanza looks as follows:
38 // <iq type="set" to="remoting@bot.talk.google.com"
39 // from="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
40 // <rem:heartbeat rem:hostid="a1ddb11e-8aef-11df-bccf-18a905b9cb5a"
41 // rem:sequence-id="456"
42 // xmlns:rem="google:remoting">
43 // <rem:signature>.signature.</rem:signature>
44 // </rem:heartbeat>
45 // </iq>
47 // Normally the heartbeat indicates that the host is healthy and ready to
48 // accept new connections from a client, but the rem:heartbeat xml element can
49 // optionally include a rem:host-offline-reason attribute, which indicates that
50 // the host cannot accept connections from the client (and might possibly be
51 // shutting down). The value of the host-offline-reason attribute can be either
52 // a string from host_exit_codes.cc (i.e. "INVALID_HOST_CONFIGURATION" string)
53 // or one of kHostOfflineReasonXxx constants (i.e. "POLICY_READ_ERROR" string).
55 // The sequence-id attribute of the heartbeat is a zero-based incrementally
56 // increasing integer unique to each heartbeat from a single host.
57 // The Bot checks the value, and if it is incorrect, includes the
58 // correct value in the result stanza. The host should then send another
59 // heartbeat, with the correct sequence-id, and increment the sequence-id in
60 // susbequent heartbeats.
61 // The signature is a base-64 encoded SHA-1 hash, signed with the host's
62 // private RSA key. The message being signed is the full Jid concatenated with
63 // the sequence-id, separated by one space. For example, for the heartbeat
64 // stanza above, the message that is signed is
65 // "user@gmail.com/chromoting123123 456".
67 // The Bot sends the following result stanza in response to each successful
68 // heartbeat:
70 // <iq type="set" from="remoting@bot.talk.google.com"
71 // to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
72 // <rem:heartbeat-result xmlns:rem="google:remoting">
73 // <rem:set-interval>300</rem:set-interval>
74 // </rem:heartbeat-result>
75 // </iq>
77 // The set-interval tag is used to specify desired heartbeat interval
78 // in seconds. The heartbeat-result and the set-interval tags are
79 // optional. Host uses default heartbeat interval if it doesn't find
80 // set-interval tag in the result Iq stanza it receives from the
81 // server.
82 // If the heartbeat's sequence-id was incorrect, the Bot sends a result
83 // stanza of this form:
85 // <iq type="set" from="remoting@bot.talk.google.com"
86 // to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
87 // <rem:heartbeat-result xmlns:rem="google:remoting">
88 // <rem:expected-sequence-id>654</rem:expected-sequence-id>
89 // </rem:heartbeat-result>
90 // </iq>
91 class HeartbeatSender : public SignalStrategy::Listener {
92 public:
93 // |signal_strategy| and |delegate| must outlive this
94 // object. Heartbeats will start when the supplied SignalStrategy
95 // enters the CONNECTED state.
97 // |on_heartbeat_successful_callback| is invoked after the first successful
98 // heartbeat.
100 // |on_unknown_host_id_error| is invoked when the host ID is permanently not
101 // recognized by the server.
102 HeartbeatSender(const base::Closure& on_heartbeat_successful_callback,
103 const base::Closure& on_unknown_host_id_error,
104 const std::string& host_id,
105 SignalStrategy* signal_strategy,
106 const scoped_refptr<const RsaKeyPair>& host_key_pair,
107 const std::string& directory_bot_jid);
108 ~HeartbeatSender() override;
110 // Sets host offline reason for future heartbeat stanzas, and initiates
111 // sending a stanza right away.
113 // For discussion of allowed values for |host_offline_reason| argument,
114 // please see the description of rem:host-offline-reason xml attribute in
115 // the class-level comments above.
117 // |ack_callback| will be called once, when the bot acks receiving the
118 // |host_offline_reason| or when |timeout| is reached.
119 void SetHostOfflineReason(
120 const std::string& host_offline_reason,
121 const base::TimeDelta& timeout,
122 const base::Callback<void(bool success)>& ack_callback);
124 // SignalStrategy::Listener interface.
125 void OnSignalStrategyStateChange(SignalStrategy::State state) override;
126 bool OnSignalStrategyIncomingStanza(const buzz::XmlElement* stanza) override;
128 private:
129 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest,
130 DoSendStanzaWithExpectedSequenceId);
131 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, ProcessResponseSetInterval);
132 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest,
133 ProcessResponseExpectedSequenceId);
134 friend class HeartbeatSenderTest;
136 void SendStanza();
137 void ResendStanza();
138 void DoSendStanza();
139 void ProcessResponse(bool is_offline_heartbeat_response,
140 IqRequest* request,
141 const buzz::XmlElement* response);
142 void SetInterval(int interval);
143 void SetSequenceId(int sequence_id);
145 // Handlers for host-offline-reason completion and timeout.
146 void OnHostOfflineReasonTimeout();
147 void OnHostOfflineReasonAck();
149 // Helper methods used by DoSendStanza() to generate heartbeat stanzas.
150 scoped_ptr<buzz::XmlElement> CreateHeartbeatMessage();
151 scoped_ptr<buzz::XmlElement> CreateSignature();
153 base::Closure on_heartbeat_successful_callback_;
154 base::Closure on_unknown_host_id_error_;
155 std::string host_id_;
156 SignalStrategy* signal_strategy_;
157 scoped_refptr<const RsaKeyPair> host_key_pair_;
158 std::string directory_bot_jid_;
159 scoped_ptr<IqSender> iq_sender_;
160 scoped_ptr<IqRequest> request_;
161 int interval_ms_;
162 base::RepeatingTimer<HeartbeatSender> timer_;
163 base::OneShotTimer<HeartbeatSender> timer_resend_;
164 int sequence_id_;
165 bool sequence_id_was_set_;
166 int sequence_id_recent_set_num_;
167 bool heartbeat_succeeded_;
168 int failed_startup_heartbeat_count_;
170 // Fields to send and indicate completion of sending host-offline-reason.
171 std::string host_offline_reason_;
172 base::Callback<void(bool success)> host_offline_reason_ack_callback_;
173 base::OneShotTimer<HeartbeatSender> host_offline_reason_timeout_timer_;
175 base::ThreadChecker thread_checker_;
177 DISALLOW_COPY_AND_ASSIGN(HeartbeatSender);
180 } // namespace remoting
182 #endif // REMOTING_HOST_HEARTBEAT_SENDER_H_