Home | History | Annotate | Download | only in notification
      1 // Copyright 2015 The Weave 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 LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_
      6 #define LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_
      7 
      8 #include <map>
      9 #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>
     16 #include <weave/stream.h>
     17 
     18 #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"
     22 
     23 namespace weave {
     24 
     25 namespace provider {
     26 class Network;
     27 class TaskRunner;
     28 }
     29 
     30 // Simple interface to abstract XmppChannel's SendMessage() method.
     31 class XmppChannelInterface {
     32  public:
     33   virtual void SendMessage(const std::string& message) = 0;
     34 
     35  protected:
     36   virtual ~XmppChannelInterface() {}
     37 };
     38 
     39 class XmppChannel : public NotificationChannel,
     40                     public XmppStreamParser::Delegate,
     41                     public XmppChannelInterface {
     42  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,
     48               const std::string& xmpp_endpoint,
     49               provider::TaskRunner* task_runner,
     50               provider::Network* network);
     51   ~XmppChannel() override = default;
     52 
     53   // Overrides from NotificationChannel.
     54   std::string GetName() const override;
     55   bool IsConnected() const override;
     56   void AddChannelParameters(base::DictionaryValue* channel_json) override;
     57   void Start(NotificationDelegate* delegate) override;
     58   void Stop() override;
     59 
     60   const std::string& jid() const { return jid_; }
     61 
     62   // Internal states for the XMPP stream.
     63   enum class XmppState {
     64     kNotStarted,
     65     kConnecting,
     66     kConnected,
     67     kAuthenticationStarted,
     68     kAuthenticationFailed,
     69     kStreamRestartedPostAuthentication,
     70     kBindSent,
     71     kSessionStarted,
     72     kSubscribeStarted,
     73     kSubscribed,
     74   };
     75 
     76  protected:
     77   // These methods are internal helpers that can be overloaded by unit tests
     78   // to help provide unit-test-specific functionality.
     79   virtual void SchedulePing(base::TimeDelta interval, base::TimeDelta timeout);
     80   void ScheduleRegularPing();
     81   void ScheduleFastPing();
     82 
     83  private:
     84   friend class IqStanzaHandler;
     85   friend class FakeXmppChannel;
     86 
     87   // Overrides from XmppStreamParser::Delegate.
     88   void OnStreamStart(const std::string& node_name,
     89                      std::map<std::string, std::string> attributes) override;
     90   void OnStreamEnd(const std::string& node_name) override;
     91   void OnStanza(std::unique_ptr<XmlNode> stanza) override;
     92 
     93   // Overrides from XmppChannelInterface.
     94   void SendMessage(const std::string& message) override;
     95 
     96   void HandleStanza(std::unique_ptr<XmlNode> stanza);
     97   void HandleMessageStanza(std::unique_ptr<XmlNode> stanza);
     98   void RestartXmppStream();
     99 
    100   void CreateSslSocket();
    101   void OnSslSocketReady(std::unique_ptr<Stream> stream, ErrorPtr error);
    102 
    103   void WaitForMessage();
    104 
    105   void OnMessageRead(size_t size, ErrorPtr error);
    106   void OnMessageSent(ErrorPtr error);
    107   void Restart();
    108   void CloseStream();
    109 
    110   // XMPP connection state machine's state handlers.
    111   void OnBindCompleted(std::unique_ptr<XmlNode> reply);
    112   void OnSessionEstablished(std::unique_ptr<XmlNode> reply);
    113   void OnSubscribed(std::unique_ptr<XmlNode> reply);
    114 
    115   // Sends a ping request to the server to check if the connection is still
    116   // valid.
    117   void PingServer(base::TimeDelta timeout);
    118   void OnPingResponse(base::Time sent_time, std::unique_ptr<XmlNode> reply);
    119   void OnPingTimeout(base::Time sent_time);
    120 
    121   void OnConnectivityChanged();
    122 
    123   XmppState state_{XmppState::kNotStarted};
    124 
    125   // Robot account name for the device.
    126   std::string account_;
    127 
    128   // OAuth access token for the account. Expires fairly frequently.
    129   std::string access_token_;
    130 
    131   // Xmpp endpoint.
    132   std::string xmpp_endpoint_;
    133 
    134   // Full JID of this device.
    135   std::string jid_;
    136 
    137   provider::Network* network_{nullptr};
    138   std::unique_ptr<Stream> stream_;
    139 
    140   // Read buffer for incoming message packets.
    141   std::vector<char> read_socket_data_;
    142   // Write buffer for outgoing message packets.
    143   std::string write_socket_data_;
    144   std::string queued_write_data_;
    145 
    146   // XMPP server name and port used for connection.
    147   std::string host_;
    148   uint16_t port_{0};
    149 
    150   BackoffEntry backoff_entry_;
    151   NotificationDelegate* delegate_{nullptr};
    152   provider::TaskRunner* task_runner_{nullptr};
    153   XmppStreamParser stream_parser_{this};
    154   bool read_pending_{false};
    155   bool write_pending_{false};
    156   std::unique_ptr<IqStanzaHandler> iq_stanza_handler_;
    157 
    158   base::WeakPtrFactory<XmppChannel> ping_ptr_factory_{this};
    159   base::WeakPtrFactory<XmppChannel> task_ptr_factory_{this};
    160   base::WeakPtrFactory<XmppChannel> weak_ptr_factory_{this};
    161   DISALLOW_COPY_AND_ASSIGN(XmppChannel);
    162 };
    163 
    164 }  // namespace weave
    165 
    166 #endif  // LIBWEAVE_SRC_NOTIFICATION_XMPP_CHANNEL_H_
    167