Standardize usage of virtual/override/final specifiers in crypto/.
[chromium-blink-merge.git] / remoting / host / heartbeat_sender.h
blob73080be9a6d3683cf1cb3c2869214f3477206fe9
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 } // namespace base
24 namespace buzz {
25 class XmlElement;
26 } // namespace buzz
28 namespace remoting {
30 class RsaKeyPair;
31 class IqRequest;
32 class IqSender;
34 // HeartbeatSender periodically sends heartbeat stanzas to the Chromoting Bot.
35 // Each heartbeat stanza looks as follows:
37 // <iq type="set" to="remoting@bot.talk.google.com"
38 // from="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
39 // <rem:heartbeat rem:hostid="a1ddb11e-8aef-11df-bccf-18a905b9cb5a"
40 // rem:sequence-id="456"
41 // xmlns:rem="google:remoting">
42 // <rem:signature>.signature.</rem:signature>
43 // </rem:heartbeat>
44 // </iq>
46 // Normally the heartbeat indicates that the host is healthy and ready to
47 // accept new connections from a client, but the rem:heartbeat xml element can
48 // optionally include a rem:host-offline-reason attribute, which indicates that
49 // the host cannot accept connections from the client (and might possibly be
50 // shutting down). The value of the host-offline-reason attribute can be a
51 // string from host_exit_codes.cc (i.e. "INVALID_HOST_CONFIGURATION" string).
53 // The sequence-id attribute of the heartbeat is a zero-based incrementally
54 // increasing integer unique to each heartbeat from a single host.
55 // The Bot checks the value, and if it is incorrect, includes the
56 // correct value in the result stanza. The host should then send another
57 // heartbeat, with the correct sequence-id, and increment the sequence-id in
58 // susbequent heartbeats.
59 // The signature is a base-64 encoded SHA-1 hash, signed with the host's
60 // private RSA key. The message being signed is the full Jid concatenated with
61 // the sequence-id, separated by one space. For example, for the heartbeat
62 // stanza above, the message that is signed is
63 // "user@gmail.com/chromoting123123 456".
65 // The Bot sends the following result stanza in response to each successful
66 // heartbeat:
68 // <iq type="set" from="remoting@bot.talk.google.com"
69 // to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
70 // <rem:heartbeat-result xmlns:rem="google:remoting">
71 // <rem:set-interval>300</rem:set-interval>
72 // </rem:heartbeat-result>
73 // </iq>
75 // The set-interval tag is used to specify desired heartbeat interval
76 // in seconds. The heartbeat-result and the set-interval tags are
77 // optional. Host uses default heartbeat interval if it doesn't find
78 // set-interval tag in the result Iq stanza it receives from the
79 // server.
80 // If the heartbeat's sequence-id was incorrect, the Bot sends a result
81 // stanza of this form:
83 // <iq type="set" from="remoting@bot.talk.google.com"
84 // to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
85 // <rem:heartbeat-result xmlns:rem="google:remoting">
86 // <rem:expected-sequence-id>654</rem:expected-sequence-id>
87 // </rem:heartbeat-result>
88 // </iq>
89 class HeartbeatSender : public SignalStrategy::Listener {
90 public:
91 // |signal_strategy| and |delegate| must outlive this
92 // object. Heartbeats will start when the supplied SignalStrategy
93 // enters the CONNECTED state.
94 HeartbeatSender(const base::Closure& on_heartbeat_successful_callback,
95 const base::Closure& on_unknown_host_id_error,
96 const std::string& host_id,
97 SignalStrategy* signal_strategy,
98 scoped_refptr<RsaKeyPair> key_pair,
99 const std::string& directory_bot_jid);
100 ~HeartbeatSender() override;
102 // Sets host offline reason for future heartbeat stanzas,
103 // as well as intiates sending a stanza right away.
105 // See rem:host-offline-reason class-level comments for discussion
106 // of allowed values for |host_offline_reason| string.
108 // |ack_callback| will be called once, when the bot acks
109 // receiving the |host_offline_reason|.
110 void SetHostOfflineReason(
111 const std::string& host_offline_reason,
112 const base::Closure& ack_callback);
114 // SignalStrategy::Listener interface.
115 void OnSignalStrategyStateChange(SignalStrategy::State state) override;
116 bool OnSignalStrategyIncomingStanza(const buzz::XmlElement* stanza) override;
118 private:
119 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest,
120 DoSendStanzaWithExpectedSequenceId);
121 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, ProcessResponseSetInterval);
122 FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest,
123 ProcessResponseExpectedSequenceId);
124 friend class HeartbeatSenderTest;
126 void SendStanza();
127 void ResendStanza();
128 void DoSendStanza();
129 void ProcessResponse(bool is_offline_heartbeat_response,
130 IqRequest* request,
131 const buzz::XmlElement* response);
132 void SetInterval(int interval);
133 void SetSequenceId(int sequence_id);
135 // Helper methods used by DoSendStanza() to generate heartbeat stanzas.
136 scoped_ptr<buzz::XmlElement> CreateHeartbeatMessage();
137 scoped_ptr<buzz::XmlElement> CreateSignature();
139 base::Closure on_heartbeat_successful_callback_;
140 base::Closure on_unknown_host_id_error_;
141 std::string host_id_;
142 SignalStrategy* signal_strategy_;
143 scoped_refptr<RsaKeyPair> key_pair_;
144 std::string directory_bot_jid_;
145 scoped_ptr<IqSender> iq_sender_;
146 scoped_ptr<IqRequest> request_;
147 int interval_ms_;
148 base::RepeatingTimer<HeartbeatSender> timer_;
149 base::OneShotTimer<HeartbeatSender> timer_resend_;
150 int sequence_id_;
151 bool sequence_id_was_set_;
152 int sequence_id_recent_set_num_;
153 bool heartbeat_succeeded_;
154 int failed_startup_heartbeat_count_;
155 std::string host_offline_reason_;
156 base::Closure host_offline_reason_ack_callback_;
158 base::ThreadChecker thread_checker_;
160 DISALLOW_COPY_AND_ASSIGN(HeartbeatSender);
163 } // namespace remoting
165 #endif // REMOTING_HOST_HEARTBEAT_SENDER_H_