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