summaryrefslogtreecommitdiffstats
path: root/remoting/host/heartbeat_sender.h
blob: 07e2568e53b26af7c6075fba8110669b3ab6c8b1 (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
// Copyright (c) 2010 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/scoped_ptr.h"
#include "base/ref_counted.h"
#include "remoting/host/host_key_pair.h"
#include "remoting/jingle_glue/iq_request.h"
#include "testing/gtest/include/gtest/gtest_prod.h"

namespace remoting {

class IqRequest;
class HostKeyPair;
class JingleClient;
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".
// TODO(sergeyu): Is it enough to sign JID and nothing else?
class HeartbeatSender : public base::RefCountedThreadSafe<HeartbeatSender> {
 public:
  HeartbeatSender();
  virtual ~HeartbeatSender();

  // Initializes heart-beating for |jingle_client| with the specified
  // config. Returns false if the config is invalid (e.g. private key
  // cannot be parsed).
  bool Init(MutableHostConfig* config, JingleClient* jingle_client);

  // Starts heart-beating. Must be called after init.
  void Start();

  // Stops heart-beating. Must be called before corresponding JingleClient
  // is destroyed. This object will not be deleted until Stop() is called,
  // and it may (and will) crash after JingleClient is destroyed. Heartbeating
  // cannot be restarted after it has been stopped, A new sender must be created
  // instead.
  void Stop();

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

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

  void DoSendStanza();

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

  void ProcessResponse(const buzz::XmlElement* response);

  State state_;
  scoped_refptr<MutableHostConfig> config_;
  JingleClient* jingle_client_;
  scoped_ptr<IqRequest> request_;
  std::string host_id_;
  HostKeyPair key_pair_;
};

}  // namespace remoting

#endif  // REMOTING_HOST_HEARTBEAT_SENDER_H_