blob: bdddd91c2fcf9a3036e8fecf3e17e34115e39b84 [file] [log] [blame]
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07001// Copyright 2015 The Chromium OS 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.
4
5#ifndef BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
6#define BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
7
Alex Vakulenkobf71f702015-05-18 14:30:56 -07008#include <map>
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07009#include <memory>
10#include <string>
11#include <vector>
12
13#include <base/callback_forward.h>
14#include <base/macros.h>
15#include <base/memory/weak_ptr.h>
Alex Vakulenkodea76b22015-06-01 13:18:06 -070016#include <base/single_thread_task_runner.h>
Alex Vakulenko5cd79972015-06-01 13:21:18 -070017#include <base/timer/timer.h>
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070018#include <chromeos/backoff_entry.h>
19#include <chromeos/streams/stream.h>
20
21#include "buffet/notification/notification_channel.h"
Alex Vakulenkodea76b22015-06-01 13:18:06 -070022#include "buffet/notification/xmpp_iq_stanza_handler.h"
Alex Vakulenkobf71f702015-05-18 14:30:56 -070023#include "buffet/notification/xmpp_stream_parser.h"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070024
25namespace buffet {
26
Alex Vakulenkodea76b22015-06-01 13:18:06 -070027// Simple interface to abstract XmppChannel's SendMessage() method.
28class XmppChannelInterface {
29 public:
30 virtual void SendMessage(const std::string& message) = 0;
31
32 protected:
33 virtual ~XmppChannelInterface() = default;
34};
35
Alex Vakulenkobf71f702015-05-18 14:30:56 -070036class XmppChannel : public NotificationChannel,
Alex Vakulenkodea76b22015-06-01 13:18:06 -070037 public XmppStreamParser::Delegate,
38 public XmppChannelInterface {
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070039 public:
40 // |account| is the robot account for buffet and |access_token|
41 // it the OAuth token. Note that the OAuth token expires fairly frequently
42 // so you will need to reset the XmppClient every time this happens.
43 XmppChannel(const std::string& account,
44 const std::string& access_token,
Alex Vakulenkodea76b22015-06-01 13:18:06 -070045 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
Alex Vakulenko534a3122015-05-22 15:48:53 -070046 ~XmppChannel() override = default;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070047
48 // Overrides from NotificationChannel.
49 std::string GetName() const override;
Alex Vakulenko6b028ae2015-05-29 09:38:59 -070050 bool IsConnected() const override;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070051 void AddChannelParameters(base::DictionaryValue* channel_json) override;
52 void Start(NotificationDelegate* delegate) override;
53 void Stop() override;
54
Alex Vakulenkodea76b22015-06-01 13:18:06 -070055 const std::string& jid() const { return jid_; }
56
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070057 // Internal states for the XMPP stream.
58 enum class XmppState {
59 kNotStarted,
60 kStarted,
Alex Vakulenko2684b512015-05-19 13:42:10 -070061 kTlsStarted,
62 kTlsCompleted,
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070063 kAuthenticationStarted,
64 kAuthenticationFailed,
65 kStreamRestartedPostAuthentication,
66 kBindSent,
67 kSessionStarted,
68 kSubscribeStarted,
69 kSubscribed,
70 };
71
72 protected:
Alex Vakulenkodea76b22015-06-01 13:18:06 -070073 // These methods are internal helpers that can be overloaded by unit tests
74 // to help provide unit-test-specific functionality.
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070075 virtual void Connect(const std::string& host, uint16_t port,
76 const base::Closure& callback);
Alex Vakulenko5cd79972015-06-01 13:21:18 -070077 virtual void StartPingTimer();
78 virtual void StopPingTimer();
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070079
80 XmppState state_{XmppState::kNotStarted};
81
82 // The connection socket stream to the XMPP server.
83 chromeos::Stream* stream_{nullptr};
84
85 private:
Alex Vakulenkodea76b22015-06-01 13:18:06 -070086 friend class IqStanzaHandler;
87
Alex Vakulenkobf71f702015-05-18 14:30:56 -070088 // Overrides from XmppStreamParser::Delegate.
89 void OnStreamStart(const std::string& node_name,
90 std::map<std::string, std::string> attributes) override;
91 void OnStreamEnd(const std::string& node_name) override;
92 void OnStanza(std::unique_ptr<XmlNode> stanza) override;
93
Alex Vakulenkodea76b22015-06-01 13:18:06 -070094 // Overrides from XmppChannelInterface.
95 void SendMessage(const std::string& message) override;
96
Alex Vakulenkobf71f702015-05-18 14:30:56 -070097 void HandleStanza(std::unique_ptr<XmlNode> stanza);
Alex Vakulenko6e3c30e2015-05-21 17:39:25 -070098 void HandleMessageStanza(std::unique_ptr<XmlNode> stanza);
Alex Vakulenkobf71f702015-05-18 14:30:56 -070099 void RestartXmppStream();
100
Alex Vakulenko2684b512015-05-19 13:42:10 -0700101 void StartTlsHandshake();
102 void OnTlsHandshakeComplete(chromeos::StreamPtr tls_stream);
103 void OnTlsError(const chromeos::Error* error);
104
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700105 void WaitForMessage();
106
107 void OnConnected();
108 void OnMessageRead(size_t size);
109 void OnMessageSent();
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700110 void OnReadError(const chromeos::Error* error);
111 void OnWriteError(const chromeos::Error* error);
112 void Restart();
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700113 void CloseStream();
114
115 // XMPP connection state machine's state handlers.
116 void OnBindCompleted(std::unique_ptr<XmlNode> reply);
117 void OnSessionEstablished(std::unique_ptr<XmlNode> reply);
118 void OnSubscribed(std::unique_ptr<XmlNode> reply);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700119
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700120 // Sends a ping request to the server to check if the connection is still
121 // valid.
122 void PingServer();
123 void OnPingResponse(std::unique_ptr<XmlNode> reply);
124 void OnPingTimeout();
125
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700126 // Robot account name for the device.
127 std::string account_;
128
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700129 // Full JID of this device.
130 std::string jid_;
131
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700132 // OAuth access token for the account. Expires fairly frequently.
133 std::string access_token_;
134
135 chromeos::StreamPtr raw_socket_;
Alex Vakulenko26f557b2015-05-26 16:47:40 -0700136 chromeos::StreamPtr tls_stream_; // Must follow |raw_socket_|.
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700137
138 // Read buffer for incoming message packets.
139 std::vector<char> read_socket_data_;
140 // Write buffer for outgoing message packets.
141 std::string write_socket_data_;
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700142 std::string queued_write_data_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700143
Alex Vakulenko2684b512015-05-19 13:42:10 -0700144 // XMPP server name and port used for connection.
145 std::string host_;
146 uint16_t port_{0};
147
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700148 chromeos::BackoffEntry backoff_entry_;
149 NotificationDelegate* delegate_{nullptr};
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700150 scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700151 XmppStreamParser stream_parser_{this};
152 bool read_pending_{false};
153 bool write_pending_{false};
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700154 std::unique_ptr<IqStanzaHandler> iq_stanza_handler_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700155
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700156 base::Timer ping_timer_{true, true};
157
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700158 base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this};
159 DISALLOW_COPY_AND_ASSIGN(XmppChannel);
160};
161
162} // namespace buffet
163
164#endif // BUFFET_NOTIFICATION_XMPP_CHANNEL_H_
165