1 /* 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef THIRD_PARTY_LIBJINGLE_XMPP_XMPP_XMPPTASK_H_ 12 #define THIRD_PARTY_LIBJINGLE_XMPP_XMPP_XMPPTASK_H_ 13 14 #include <deque> 15 #include <memory> 16 #include <string> 17 18 #include "base/macros.h" 19 #include "third_party/libjingle_xmpp/task_runner/task.h" 20 #include "third_party/libjingle_xmpp/task_runner/taskparent.h" 21 #include "third_party/libjingle_xmpp/xmpp/xmppengine.h" 22 #include "third_party/webrtc/rtc_base/third_party/sigslot/sigslot.h" 23 24 namespace jingle_xmpp { 25 26 ///////////////////////////////////////////////////////////////////// 27 // 28 // XMPPTASK 29 // 30 ///////////////////////////////////////////////////////////////////// 31 // 32 // See Task and XmppClient first. 33 // 34 // XmppTask is a task that is designed to go underneath XmppClient and be 35 // useful there. It has a way of finding its XmppClient parent so you 36 // can have it nested arbitrarily deep under an XmppClient and it can 37 // still find the XMPP services. 38 // 39 // Tasks register themselves to listen to particular kinds of stanzas 40 // that are sent out by the client. Rather than processing stanzas 41 // right away, they should decide if they own the sent stanza, 42 // and if so, queue it and Wake() the task, or if a stanza does not belong 43 // to you, return false right away so the next XmppTask can take a crack. 44 // This technique (synchronous recognize, but asynchronous processing) 45 // allows you to have arbitrary logic for recognizing stanzas yet still, 46 // for example, disconnect a client while processing a stanza - 47 // without reentrancy problems. 48 // 49 ///////////////////////////////////////////////////////////////////// 50 51 class XmppTask; 52 53 // XmppClientInterface is an abstract interface for sending and 54 // handling stanzas. It can be implemented for unit tests or 55 // different network environments. It will usually be implemented by 56 // XmppClient. 57 class XmppClientInterface { 58 public: 59 XmppClientInterface(); 60 virtual ~XmppClientInterface(); 61 62 virtual XmppEngine::State GetState() const = 0; 63 virtual const Jid& jid() const = 0; 64 virtual std::string NextId() = 0; 65 virtual XmppReturnStatus SendStanza(const XmlElement* stanza) = 0; 66 virtual XmppReturnStatus SendStanzaError(const XmlElement* original_stanza, 67 XmppStanzaError error_code, 68 const std::string& message) = 0; 69 virtual void AddXmppTask(XmppTask* task, XmppEngine::HandlerLevel level) = 0; 70 virtual void RemoveXmppTask(XmppTask* task) = 0; 71 sigslot::signal0<> SignalDisconnected; 72 73 DISALLOW_COPY_AND_ASSIGN(XmppClientInterface); 74 }; 75 76 // XmppTaskParentInterface is the interface require for any parent of 77 // an XmppTask. It needs, for example, a way to get an 78 // XmppClientInterface. 79 80 // We really ought to inherit from a TaskParentInterface, but we tried 81 // that and it's way too complicated to change 82 // Task/TaskParent/TaskRunner. For now, this works. 83 class XmppTaskParentInterface : public jingle_xmpp::Task { 84 public: XmppTaskParentInterface(jingle_xmpp::TaskParent * parent)85 explicit XmppTaskParentInterface(jingle_xmpp::TaskParent* parent) 86 : Task(parent) { 87 } ~XmppTaskParentInterface()88 virtual ~XmppTaskParentInterface() {} 89 90 virtual XmppClientInterface* GetClient() = 0; 91 92 DISALLOW_COPY_AND_ASSIGN(XmppTaskParentInterface); 93 }; 94 95 class XmppTaskBase : public XmppTaskParentInterface { 96 public: XmppTaskBase(XmppTaskParentInterface * parent)97 explicit XmppTaskBase(XmppTaskParentInterface* parent) 98 : XmppTaskParentInterface(parent), 99 parent_(parent) { 100 } ~XmppTaskBase()101 virtual ~XmppTaskBase() {} 102 GetClient()103 virtual XmppClientInterface* GetClient() { 104 return parent_->GetClient(); 105 } 106 107 protected: 108 XmppTaskParentInterface* parent_; 109 110 DISALLOW_COPY_AND_ASSIGN(XmppTaskBase); 111 }; 112 113 class XmppTask : public XmppTaskBase, 114 public XmppStanzaHandler, 115 public sigslot::has_slots<> 116 { 117 public: 118 XmppTask(XmppTaskParentInterface* parent, 119 XmppEngine::HandlerLevel level = XmppEngine::HL_NONE); 120 virtual ~XmppTask(); 121 task_id()122 std::string task_id() const { return id_; } set_task_id(std::string id)123 void set_task_id(std::string id) { id_ = id; } 124 125 #if !defined(NDEBUG) set_debug_force_timeout(const bool f)126 void set_debug_force_timeout(const bool f) { debug_force_timeout_ = f; } 127 #endif 128 HandleStanza(const XmlElement * stanza)129 virtual bool HandleStanza(const XmlElement* stanza) { return false; } 130 131 protected: 132 XmppReturnStatus SendStanza(const XmlElement* stanza); 133 XmppReturnStatus SetResult(const std::string& code); 134 XmppReturnStatus SendStanzaError(const XmlElement* element_original, 135 XmppStanzaError code, 136 const std::string& text); 137 138 virtual void Stop(); 139 virtual void OnDisconnect(); 140 141 virtual void QueueStanza(const XmlElement* stanza); 142 const XmlElement* NextStanza(); 143 144 bool MatchStanzaFrom(const XmlElement* stanza, const Jid& match_jid); 145 146 bool MatchResponseIq(const XmlElement* stanza, const Jid& to, 147 const std::string& task_id); 148 149 static bool MatchRequestIq(const XmlElement* stanza, const std::string& type, 150 const QName& qn); 151 static XmlElement *MakeIqResult(const XmlElement* query); 152 static XmlElement *MakeIq(const std::string& type, 153 const Jid& to, const std::string& task_id); 154 155 // Returns true if the task is under the specified rate limit and updates the 156 // rate limit accordingly 157 bool VerifyTaskRateLimit(const std::string task_name, int max_count, 158 int per_x_seconds); 159 160 private: 161 void StopImpl(); 162 163 bool stopped_; 164 std::deque<XmlElement*> stanza_queue_; 165 std::unique_ptr<XmlElement> next_stanza_; 166 std::string id_; 167 168 #if !defined(NDEBUG) 169 bool debug_force_timeout_; 170 #endif 171 }; 172 173 } // namespace jingle_xmpp 174 175 #endif // THIRD_PARTY_LIBJINGLE_XMPP_XMPP_XMPPTASK_H_ 176