| // Copyright 2015 The Weave 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 LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_ | |
| #define LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_ | |
| #include <map> | |
| #include <memory> | |
| #include <string> | |
| #include <vector> | |
| #include <base/callback_forward.h> | |
| #include <base/macros.h> | |
| #include <base/memory/weak_ptr.h> | |
| #include <weave/stream.h> | |
| #include "src/backoff_entry.h" | |
| #include "src/notification/notification_channel.h" | |
| #include "src/notification/xmpp_iq_stanza_handler.h" | |
| #include "src/notification/xmpp_stream_parser.h" | |
| namespace weave { | |
| namespace provider { | |
| class Network; | |
| class TaskRunner; | |
| } | |
| // Simple interface to abstract XmppChannel's SendMessage() method. | |
| class XmppChannelInterface { | |
| public: | |
| virtual void SendMessage(const std::string& message) = 0; | |
| protected: | |
| virtual ~XmppChannelInterface() {} | |
| }; | |
| class XmppChannel : public NotificationChannel, | |
| public XmppStreamParser::Delegate, | |
| public XmppChannelInterface { | |
| public: | |
| // |account| is the robot account for buffet and |access_token| | |
| // it the OAuth token. Note that the OAuth token expires fairly frequently | |
| // so you will need to reset the XmppClient every time this happens. | |
| XmppChannel(const std::string& account, | |
| const std::string& access_token, | |
| const std::string& xmpp_endpoint, | |
| provider::TaskRunner* task_runner, | |
| provider::Network* network); | |
| ~XmppChannel() override = default; | |
| // Overrides from NotificationChannel. | |
| std::string GetName() const override; | |
| bool IsConnected() const override; | |
| void AddChannelParameters(base::DictionaryValue* channel_json) override; | |
| void Start(NotificationDelegate* delegate) override; | |
| void Stop() override; | |
| const std::string& jid() const { return jid_; } | |
| // Internal states for the XMPP stream. | |
| enum class XmppState { | |
| kNotStarted, | |
| kConnecting, | |
| kConnected, | |
| kAuthenticationStarted, | |
| kAuthenticationFailed, | |
| kStreamRestartedPostAuthentication, | |
| kBindSent, | |
| kSessionStarted, | |
| kSubscribeStarted, | |
| kSubscribed, | |
| }; | |
| protected: | |
| // These methods are internal helpers that can be overloaded by unit tests | |
| // to help provide unit-test-specific functionality. | |
| virtual void SchedulePing(base::TimeDelta interval, base::TimeDelta timeout); | |
| void ScheduleRegularPing(); | |
| void ScheduleFastPing(); | |
| private: | |
| friend class IqStanzaHandler; | |
| friend class FakeXmppChannel; | |
| // Overrides from XmppStreamParser::Delegate. | |
| void OnStreamStart(const std::string& node_name, | |
| std::map<std::string, std::string> attributes) override; | |
| void OnStreamEnd(const std::string& node_name) override; | |
| void OnStanza(std::unique_ptr<XmlNode> stanza) override; | |
| // Overrides from XmppChannelInterface. | |
| void SendMessage(const std::string& message) override; | |
| void HandleStanza(std::unique_ptr<XmlNode> stanza); | |
| void HandleMessageStanza(std::unique_ptr<XmlNode> stanza); | |
| void RestartXmppStream(); | |
| void CreateSslSocket(); | |
| void OnSslSocketReady(std::unique_ptr<Stream> stream, ErrorPtr error); | |
| void WaitForMessage(); | |
| void OnMessageRead(size_t size, ErrorPtr error); | |
| void OnMessageSent(ErrorPtr error); | |
| void Restart(); | |
| void CloseStream(); | |
| // XMPP connection state machine's state handlers. | |
| void OnBindCompleted(std::unique_ptr<XmlNode> reply); | |
| void OnSessionEstablished(std::unique_ptr<XmlNode> reply); | |
| void OnSubscribed(std::unique_ptr<XmlNode> reply); | |
| // Sends a ping request to the server to check if the connection is still | |
| // valid. | |
| void PingServer(base::TimeDelta timeout); | |
| void OnPingResponse(base::Time sent_time, std::unique_ptr<XmlNode> reply); | |
| void OnPingTimeout(base::Time sent_time); | |
| void OnConnectivityChanged(); | |
| XmppState state_{XmppState::kNotStarted}; | |
| // Robot account name for the device. | |
| std::string account_; | |
| // OAuth access token for the account. Expires fairly frequently. | |
| std::string access_token_; | |
| // Xmpp endpoint. | |
| std::string xmpp_endpoint_; | |
| // Full JID of this device. | |
| std::string jid_; | |
| provider::Network* network_{nullptr}; | |
| std::unique_ptr<Stream> stream_; | |
| // Read buffer for incoming message packets. | |
| std::vector<char> read_socket_data_; | |
| // Write buffer for outgoing message packets. | |
| std::string write_socket_data_; | |
| std::string queued_write_data_; | |
| // XMPP server name and port used for connection. | |
| std::string host_; | |
| uint16_t port_{0}; | |
| BackoffEntry backoff_entry_; | |
| NotificationDelegate* delegate_{nullptr}; | |
| provider::TaskRunner* task_runner_{nullptr}; | |
| XmppStreamParser stream_parser_{this}; | |
| bool read_pending_{false}; | |
| bool write_pending_{false}; | |
| std::unique_ptr<IqStanzaHandler> iq_stanza_handler_; | |
| base::WeakPtrFactory<XmppChannel> ping_ptr_factory_{this}; | |
| base::WeakPtrFactory<XmppChannel> task_ptr_factory_{this}; | |
| base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this}; | |
| DISALLOW_COPY_AND_ASSIGN(XmppChannel); | |
| }; | |
| } // namespace weave | |
| #endif // LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_ |