|  | // 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() = default; | 
|  | }; | 
|  |  | 
|  | 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, | 
|  | 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_; | 
|  |  | 
|  | // Full JID of this device. | 
|  | std::string jid_; | 
|  |  | 
|  | // OAuth access token for the account. Expires fairly frequently. | 
|  | std::string access_token_; | 
|  |  | 
|  | 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_ |