1/*
2 * libjingle
3 * Copyright 2004--2006, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 *  1. Redistributions of source code must retain the above copyright notice,
9 *     this list of conditions and the following disclaimer.
10 *  2. Redistributions in binary form must reproduce the above copyright notice,
11 *     this list of conditions and the following disclaimer in the documentation
12 *     and/or other materials provided with the distribution.
13 *  3. The name of the author may not be used to endorse or promote products
14 *     derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef _XMPPTASK_H_
29#define _XMPPTASK_H_
30
31#include <string>
32#include <deque>
33#include "talk/base/sigslot.h"
34#include "talk/xmpp/xmppengine.h"
35#include "talk/base/task.h"
36
37namespace buzz {
38
39/////////////////////////////////////////////////////////////////////
40//
41// XMPPTASK
42//
43/////////////////////////////////////////////////////////////////////
44//
45// See Task and XmppClient first.
46//
47// XmppTask is a task that is designed to go underneath XmppClient and be
48// useful there.  It has a way of finding its XmppClient parent so you
49// can have it nested arbitrarily deep under an XmppClient and it can
50// still find the XMPP services.
51//
52// Tasks register themselves to listen to particular kinds of stanzas
53// that are sent out by the client.  Rather than processing stanzas
54// right away, they should decide if they own the sent stanza,
55// and if so, queue it and Wake() the task, or if a stanza does not belong
56// to you, return false right away so the next XmppTask can take a crack.
57// This technique (synchronous recognize, but asynchronous processing)
58// allows you to have arbitrary logic for recognizing stanzas yet still,
59// for example, disconnect a client while processing a stanza -
60// without reentrancy problems.
61//
62/////////////////////////////////////////////////////////////////////
63
64class XmppClient;
65
66class XmppTask :
67  public talk_base::Task,
68  public XmppStanzaHandler,
69  public sigslot::has_slots<>
70{
71 public:
72  XmppTask(talk_base::TaskParent* parent,
73           XmppEngine::HandlerLevel level = XmppEngine::HL_NONE);
74  virtual ~XmppTask();
75
76  virtual XmppClient* GetClient() const { return client_; }
77  std::string task_id() const { return id_; }
78  void set_task_id(std::string id) { id_ = id; }
79
80#ifdef _DEBUG
81  void set_debug_force_timeout(const bool f) { debug_force_timeout_ = f; }
82#endif
83
84 protected:
85  friend class XmppClient;
86
87  XmppReturnStatus SendStanza(const XmlElement* stanza);
88  XmppReturnStatus SetResult(const std::string& code);
89  XmppReturnStatus SendStanzaError(const XmlElement* element_original,
90                                   XmppStanzaError code,
91                                   const std::string& text);
92
93  virtual void Stop();
94  virtual bool HandleStanza(const XmlElement* stanza) { return false; }
95  virtual void OnDisconnect();
96  virtual int ProcessReponse() { return STATE_DONE; }
97
98  virtual void QueueStanza(const XmlElement* stanza);
99  const XmlElement* NextStanza();
100
101  bool MatchResponseIq(const XmlElement* stanza, const Jid& to,
102                       const std::string& task_id);
103
104  static bool MatchRequestIq(const XmlElement* stanza, const std::string& type,
105                             const QName& qn);
106  static XmlElement *MakeIqResult(const XmlElement* query);
107  static XmlElement *MakeIq(const std::string& type,
108                            const Jid& to, const std::string& task_id);
109
110  // Returns true if the task is under the specified rate limit and updates the
111  // rate limit accordingly
112  bool VerifyTaskRateLimit(const std::string task_name, int max_count,
113                           int per_x_seconds);
114
115private:
116  void StopImpl();
117
118  XmppClient* client_;
119  std::deque<XmlElement*> stanza_queue_;
120  talk_base::scoped_ptr<XmlElement> next_stanza_;
121  std::string id_;
122
123#ifdef _DEBUG
124  bool debug_force_timeout_;
125#endif
126};
127
128}
129
130#endif
131