blob: 50e84d26a4c1eccd3f91602abecc4a69c5f8c180 [file] [log] [blame]
Vitaly Buka4615e0d2015-10-14 15:35:12 -07001// Copyright 2015 The Weave Authors. All rights reserved.
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Vitaly Buka912b6982015-07-06 11:13:03 -07005#ifndef LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_
6#define LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -07007
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>
Vitaly Buka10c69ec2015-08-12 16:17:16 -070016#include <weave/stream.h>
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070017
Stefan Sauer2d16dfa2015-09-25 17:08:35 +020018#include "src/backoff_entry.h"
19#include "src/notification/notification_channel.h"
20#include "src/notification/xmpp_iq_stanza_handler.h"
21#include "src/notification/xmpp_stream_parser.h"
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070022
Vitaly Bukab6f015a2015-07-09 14:59:23 -070023namespace weave {
24
Vitaly Buka1e363672015-09-25 14:01:16 -070025namespace provider {
26class Network;
Vitaly Buka823fdda2015-08-13 00:33:00 -070027class TaskRunner;
Vitaly Buka1e363672015-09-25 14:01:16 -070028}
Vitaly Buka387b4f42015-07-30 23:55:13 -070029
Alex Vakulenkodea76b22015-06-01 13:18:06 -070030// Simple interface to abstract XmppChannel's SendMessage() method.
31class XmppChannelInterface {
32 public:
33 virtual void SendMessage(const std::string& message) = 0;
34
35 protected:
Vitaly Buka3bfb13d2015-11-24 14:46:13 -080036 virtual ~XmppChannelInterface() {}
Alex Vakulenkodea76b22015-06-01 13:18:06 -070037};
38
Alex Vakulenkobf71f702015-05-18 14:30:56 -070039class XmppChannel : public NotificationChannel,
Alex Vakulenkodea76b22015-06-01 13:18:06 -070040 public XmppStreamParser::Delegate,
41 public XmppChannelInterface {
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070042 public:
43 // |account| is the robot account for buffet and |access_token|
44 // it the OAuth token. Note that the OAuth token expires fairly frequently
45 // so you will need to reset the XmppClient every time this happens.
46 XmppChannel(const std::string& account,
47 const std::string& access_token,
Vitaly Buka1e363672015-09-25 14:01:16 -070048 provider::TaskRunner* task_runner,
49 provider::Network* network);
Alex Vakulenko534a3122015-05-22 15:48:53 -070050 ~XmppChannel() override = default;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070051
52 // Overrides from NotificationChannel.
53 std::string GetName() const override;
Alex Vakulenko6b028ae2015-05-29 09:38:59 -070054 bool IsConnected() const override;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070055 void AddChannelParameters(base::DictionaryValue* channel_json) override;
56 void Start(NotificationDelegate* delegate) override;
57 void Stop() override;
58
Alex Vakulenkodea76b22015-06-01 13:18:06 -070059 const std::string& jid() const { return jid_; }
60
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070061 // Internal states for the XMPP stream.
62 enum class XmppState {
63 kNotStarted,
Vitaly Buka63cc3d22015-06-23 20:11:36 -070064 kConnecting,
65 kConnected,
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070066 kAuthenticationStarted,
67 kAuthenticationFailed,
68 kStreamRestartedPostAuthentication,
69 kBindSent,
70 kSessionStarted,
71 kSubscribeStarted,
72 kSubscribed,
73 };
74
75 protected:
Alex Vakulenkodea76b22015-06-01 13:18:06 -070076 // These methods are internal helpers that can be overloaded by unit tests
77 // to help provide unit-test-specific functionality.
Vitaly Buka63cc3d22015-06-23 20:11:36 -070078 virtual void SchedulePing(base::TimeDelta interval, base::TimeDelta timeout);
79 void ScheduleRegularPing();
80 void ScheduleFastPing();
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070081
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -070082 private:
Alex Vakulenkodea76b22015-06-01 13:18:06 -070083 friend class IqStanzaHandler;
Vitaly Bukaa4b39832015-09-09 02:11:03 -070084 friend class FakeXmppChannel;
Alex Vakulenkodea76b22015-06-01 13:18:06 -070085
Alex Vakulenkobf71f702015-05-18 14:30:56 -070086 // Overrides from XmppStreamParser::Delegate.
87 void OnStreamStart(const std::string& node_name,
88 std::map<std::string, std::string> attributes) override;
89 void OnStreamEnd(const std::string& node_name) override;
90 void OnStanza(std::unique_ptr<XmlNode> stanza) override;
91
Alex Vakulenkodea76b22015-06-01 13:18:06 -070092 // Overrides from XmppChannelInterface.
93 void SendMessage(const std::string& message) override;
94
Alex Vakulenkobf71f702015-05-18 14:30:56 -070095 void HandleStanza(std::unique_ptr<XmlNode> stanza);
Alex Vakulenko6e3c30e2015-05-21 17:39:25 -070096 void HandleMessageStanza(std::unique_ptr<XmlNode> stanza);
Alex Vakulenkobf71f702015-05-18 14:30:56 -070097 void RestartXmppStream();
98
Vitaly Bukaa4b39832015-09-09 02:11:03 -070099 void CreateSslSocket();
Vitaly Buka74763422015-10-11 00:39:52 -0700100 void OnSslSocketReady(std::unique_ptr<Stream> stream, ErrorPtr error);
Alex Vakulenko2684b512015-05-19 13:42:10 -0700101
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700102 void WaitForMessage();
103
Vitaly Buka74763422015-10-11 00:39:52 -0700104 void OnMessageRead(size_t size, ErrorPtr error);
105 void OnMessageSent(ErrorPtr error);
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700106 void Restart();
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700107 void CloseStream();
108
109 // XMPP connection state machine's state handlers.
110 void OnBindCompleted(std::unique_ptr<XmlNode> reply);
111 void OnSessionEstablished(std::unique_ptr<XmlNode> reply);
112 void OnSubscribed(std::unique_ptr<XmlNode> reply);
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700113
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700114 // Sends a ping request to the server to check if the connection is still
115 // valid.
Vitaly Buka63cc3d22015-06-23 20:11:36 -0700116 void PingServer(base::TimeDelta timeout);
117 void OnPingResponse(base::Time sent_time, std::unique_ptr<XmlNode> reply);
118 void OnPingTimeout(base::Time sent_time);
119
Vitaly Bukabf6840a2015-09-21 13:38:56 -0700120 void OnConnectivityChanged();
Alex Vakulenko5cd79972015-06-01 13:21:18 -0700121
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700122 XmppState state_{XmppState::kNotStarted};
123
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700124 // Robot account name for the device.
125 std::string account_;
126
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700127 // Full JID of this device.
128 std::string jid_;
129
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700130 // OAuth access token for the account. Expires fairly frequently.
131 std::string access_token_;
132
Vitaly Buka1e363672015-09-25 14:01:16 -0700133 provider::Network* network_{nullptr};
Vitaly Bukaa4b39832015-09-09 02:11:03 -0700134 std::unique_ptr<Stream> stream_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700135
136 // Read buffer for incoming message packets.
137 std::vector<char> read_socket_data_;
138 // Write buffer for outgoing message packets.
139 std::string write_socket_data_;
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700140 std::string queued_write_data_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700141
Alex Vakulenko2684b512015-05-19 13:42:10 -0700142 // XMPP server name and port used for connection.
143 std::string host_;
144 uint16_t port_{0};
145
Vitaly Buka0f80f7c2015-08-13 00:57:25 -0700146 BackoffEntry backoff_entry_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700147 NotificationDelegate* delegate_{nullptr};
Vitaly Buka1e363672015-09-25 14:01:16 -0700148 provider::TaskRunner* task_runner_{nullptr};
Alex Vakulenkobf71f702015-05-18 14:30:56 -0700149 XmppStreamParser stream_parser_{this};
150 bool read_pending_{false};
151 bool write_pending_{false};
Alex Vakulenkodea76b22015-06-01 13:18:06 -0700152 std::unique_ptr<IqStanzaHandler> iq_stanza_handler_;
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700153
Vitaly Buka63cc3d22015-06-23 20:11:36 -0700154 base::WeakPtrFactory<XmppChannel> ping_ptr_factory_{this};
155 base::WeakPtrFactory<XmppChannel> task_ptr_factory_{this};
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700156 base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this};
157 DISALLOW_COPY_AND_ASSIGN(XmppChannel);
158};
159
Vitaly Bukab6f015a2015-07-09 14:59:23 -0700160} // namespace weave
Alex Vakulenkoeedf3be2015-05-13 17:52:02 -0700161
Vitaly Buka912b6982015-07-06 11:13:03 -0700162#endif // LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_