• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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