summaryrefslogtreecommitdiffstats
path: root/remoting/host/heartbeat_sender.h
blob: 0cb71bbf475863d4800b25ed706b103a7c1ae8e7 (plain)
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
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// 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 <string>

#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/timer.h"
#include "remoting/host/host_key_pair.h"
#include "remoting/host/host_status_observer.h"
#include "remoting/jingle_glue/iq_request.h"
#include "testing/gtest/include/gtest/gtest_prod.h"

namespace remoting {

class IqRequest;
class HostKeyPair;
class MutableHostConfig;

// HeartbeatSender periodically sends heartbeat stanzas to the Chromoting Bot.
// Each heartbeat stanza looks as follows:
//
// <iq type="set" to="remoting@bot.talk.google.com"
//     from="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
//   <rem:heartbeat rem:hostid="a1ddb11e-8aef-11df-bccf-18a905b9cb5a"
//                  xmlns:rem="google:remoting">
//     <rem:signature rem:time="1279061748">.signature.</rem:signature>
//   </rem:heartbeat>
// </iq>
//
// The time attribute of the signature is the decimal time when the message
// was sent in second since the epoch (01/01/1970). The signature is a BASE64
// encoded SHA-1/RSA signature created with the host's private key. The message
// being signed is the full Jid concatenated with the time value, separated by
// space. For example, for the heartbeat stanza above the message that is being
// signed is "user@gmail.com/chromoting123123 1279061748".
//
// Bot sends the following result stanza in response to each heartbeat:
//
//  <iq type="set" from="remoting@bot.talk.google.com"
//      to="user@gmail.com/chromoting123123" id="5" xmlns="jabber:client">
//    <rem:heartbeat-result xmlns:rem="google:remoting">
//      <rem:set-interval>300</rem:set-interval>
//    </rem:heartbeat>
//  </iq>
//
// The set-interval tag is used to specify desired heartbeat interval
// in seconds. The heartbeat-result and the set-interval tags are
// optional. Host uses default heartbeat interval if it doesn't find
// set-interval tag in the result Iq stanza it receives from the
// server.
//
// TODO(sergeyu): Is it enough to sign JID and nothing else?
class HeartbeatSender : public HostStatusObserver {
 public:
  HeartbeatSender(MessageLoop* main_loop,
                  MutableHostConfig* config);
  virtual ~HeartbeatSender();

  // Initializes heart-beating for |jingle_client_| with |config_|. Returns
  // false if the config is invalid (e.g. private key cannot be parsed).
  bool Init();

  // HostStatusObserver implementation.
  virtual void OnSignallingConnected(SignalStrategy* signal_strategy,
                                     const std::string& full_jid) OVERRIDE;
  virtual void OnSignallingDisconnected() OVERRIDE;
  virtual void OnAuthenticatedClientsChanged(int clients) OVERRIDE;
  virtual void OnAccessDenied() OVERRIDE;
  virtual void OnShutdown() OVERRIDE;

 private:
  FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, DoSendStanza);
  FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, CreateHeartbeatMessage);
  FRIEND_TEST_ALL_PREFIXES(HeartbeatSenderTest, ProcessResponse);

  enum State {
    CREATED,
    INITIALIZED,
    STARTED,
    STOPPED,
  };

  void DoSendStanza();
  void ProcessResponse(const buzz::XmlElement* response);
  void SetInterval(int interval);

  // Helper methods used by DoSendStanza() to generate heartbeat stanzas.
  // Caller owns the result.
  buzz::XmlElement* CreateHeartbeatMessage();
  buzz::XmlElement* CreateSignature();

  State state_;
  MessageLoop* message_loop_;
  scoped_refptr<MutableHostConfig> config_;
  std::string host_id_;
  HostKeyPair key_pair_;
  std::string full_jid_;
  scoped_ptr<IqRequest> request_;
  int interval_ms_;
  base::RepeatingTimer<HeartbeatSender> timer_;

  DISALLOW_COPY_AND_ASSIGN(HeartbeatSender);
};

}  // namespace remoting

#endif  // REMOTING_HOST_HEARTBEAT_SENDER_H_