1/*
2 * libjingle
3 * Copyright 2004--2005, 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 TALK_XMPP_XMPPTHREAD_H_
29#define TALK_XMPP_XMPPTHREAD_H_
30
31#include "talk/xmpp/moduleimpl.h"
32#include "talk/xmpp/rostermodule.h"
33
34namespace buzz {
35
36//! Presence Information
37//! This class stores both presence information for outgoing presence and is
38//! returned by methods in XmppRosterModule to represent received incoming
39//! presence information.  When this class is writeable (non-const) then each
40//! update to any property will set the inner xml.  Setting the raw_xml will
41//! rederive all of the other properties.
42class XmppPresenceImpl : public XmppPresence {
43public:
44  virtual ~XmppPresenceImpl() {}
45
46  //! The from Jid of for the presence information.
47  //! Typically this will be a full Jid with resource specified.  For outgoing
48  //! presence this should remain JID_NULL and will be scrubbed from the
49  //! stanza when being sent.
50  virtual const Jid jid() const;
51
52  //! Is the contact available?
53  virtual XmppPresenceAvailable available() const;
54
55  //! Sets if the user is available or not
56  virtual XmppReturnStatus set_available(XmppPresenceAvailable available);
57
58  //! The show value of the presence info
59  virtual XmppPresenceShow presence_show() const;
60
61  //! Set the presence show value
62  virtual XmppReturnStatus set_presence_show(XmppPresenceShow show);
63
64  //! The Priority of the presence info
65  virtual int priority() const;
66
67  //! Set the priority of the presence
68  virtual XmppReturnStatus set_priority(int priority);
69
70  //! The plain text status of the presence info.
71  //! If there are multiple status because of language, this will either be a
72  //! status that is not tagged for language or the first available
73  virtual const std::string status() const;
74
75  //! Sets the status for the presence info.
76  //! If there is more than one status present already then this will remove
77  //! them all and replace it with one status element we no specified language
78  virtual XmppReturnStatus set_status(const std::string& status);
79
80  //! The connection status
81  virtual XmppPresenceConnectionStatus connection_status() const;
82
83  //! The focus obfuscated GAIA id
84  virtual const std::string google_user_id() const;
85
86  //! The nickname in the presence
87  virtual const std::string nickname() const;
88
89  //! The raw xml of the presence update
90  virtual const XmlElement* raw_xml() const;
91
92  //! Sets the raw presence stanza for the presence update
93  //! This will cause all other data items in this structure to be rederived
94  virtual XmppReturnStatus set_raw_xml(const XmlElement * xml);
95
96private:
97  XmppPresenceImpl();
98
99  friend class XmppPresence;
100  friend class XmppRosterModuleImpl;
101
102  void CreateRawXmlSkeleton();
103
104  // Store everything in the XML element. If this becomes a perf issue we can
105  // cache the data.
106  rtc::scoped_ptr<XmlElement> raw_xml_;
107};
108
109//! A contact as given by the server
110class XmppRosterContactImpl : public XmppRosterContact {
111public:
112  virtual ~XmppRosterContactImpl() {}
113
114  //! The jid for the contact.
115  //! Typically this will be a bare Jid.
116  virtual const Jid jid() const;
117
118  //! Sets the jid for the roster contact update
119  virtual XmppReturnStatus set_jid(const Jid& jid);
120
121  //! The name (nickname) stored for this contact
122  virtual const std::string name() const;
123
124  //! Sets the name
125  virtual XmppReturnStatus set_name(const std::string& name);
126
127  //! The Presence subscription state stored on the server for this contact
128  //! This is never settable and will be ignored when generating a roster
129  //! add/update request
130  virtual XmppSubscriptionState subscription_state() const;
131
132  //! The number of Groups applied to this contact
133  virtual size_t GetGroupCount() const;
134
135  //! Gets a Group applied to the contact based on index.
136  virtual const std::string GetGroup(size_t index) const;
137
138  //! Adds a group to this contact.
139  //! This will return a no error if the group is already present.
140  virtual XmppReturnStatus AddGroup(const std::string& group);
141
142  //! Removes a group from the contact.
143  //! This will return no error if the group isn't there
144  virtual XmppReturnStatus RemoveGroup(const std::string& group);
145
146  //! The raw xml for this roster contact
147  virtual const XmlElement* raw_xml() const;
148
149  //! Sets the raw presence stanza for the presence update
150  //! This will cause all other data items in this structure to be rederived
151  virtual XmppReturnStatus set_raw_xml(const XmlElement * xml);
152
153private:
154  XmppRosterContactImpl();
155
156  void CreateRawXmlSkeleton();
157  void SetXmlFromWire(const XmlElement * xml);
158  void ResetGroupCache();
159
160  bool FindGroup(const std::string& group,
161                 XmlElement** element,
162                 XmlChild** child_before);
163
164
165  friend class XmppRosterContact;
166  friend class XmppRosterModuleImpl;
167
168  int group_count_;
169  int group_index_returned_;
170  XmlElement * group_returned_;
171  rtc::scoped_ptr<XmlElement> raw_xml_;
172};
173
174//! An XmppModule for handle roster and presence functionality
175class XmppRosterModuleImpl : public XmppModuleImpl,
176  public XmppRosterModule, public XmppIqHandler {
177public:
178  virtual ~XmppRosterModuleImpl();
179
180  IMPLEMENT_XMPPMODULE
181
182  //! Sets the roster handler (callbacks) for the module
183  virtual XmppReturnStatus set_roster_handler(XmppRosterHandler * handler);
184
185  //! Gets the roster handler for the module
186  virtual XmppRosterHandler* roster_handler();
187
188  // USER PRESENCE STATE -------------------------------------------------------
189
190  //! Gets the aggregate outgoing presence
191  //! This object is non-const and be edited directly.  No update is sent
192  //! to the server until a Broadcast is sent
193  virtual XmppPresence* outgoing_presence();
194
195  //! Broadcasts that the user is available.
196  //! Nothing with respect to presence is sent until this is called.
197  virtual XmppReturnStatus BroadcastPresence();
198
199  //! Sends a directed presence to a Jid
200  //! Note that the client doesn't store where directed presence notifications
201  //! have been sent.  The server can keep the appropriate state
202  virtual XmppReturnStatus SendDirectedPresence(const XmppPresence* presence,
203                                                const Jid& to_jid);
204
205  // INCOMING PRESENCE STATUS --------------------------------------------------
206
207  //! Returns the number of incoming presence data recorded
208  virtual size_t GetIncomingPresenceCount();
209
210  //! Returns an incoming presence datum based on index
211  virtual const XmppPresence* GetIncomingPresence(size_t index);
212
213  //! Gets the number of presence data for a bare Jid
214  //! There may be a datum per resource
215  virtual size_t GetIncomingPresenceForJidCount(const Jid& jid);
216
217  //! Returns a single presence data for a Jid based on index
218  virtual const XmppPresence* GetIncomingPresenceForJid(const Jid& jid,
219                                                        size_t index);
220
221  // ROSTER MANAGEMENT ---------------------------------------------------------
222
223  //! Requests an update of the roster from the server
224  //! This must be called to initialize the client side cache of the roster
225  //! After this is sent the server should keep this module apprised of any
226  //! changes.
227  virtual XmppReturnStatus RequestRosterUpdate();
228
229  //! Returns the number of contacts in the roster
230  virtual size_t GetRosterContactCount();
231
232  //! Returns a contact by index
233  virtual const XmppRosterContact* GetRosterContact(size_t index);
234
235  //! Finds a contact by Jid
236  virtual const XmppRosterContact* FindRosterContact(const Jid& jid);
237
238  //! Send a request to the server to add a contact
239  //! Note that the contact won't show up in the roster until the server can
240  //! respond.  This happens async when the socket is being serviced
241  virtual XmppReturnStatus RequestRosterChange(
242    const XmppRosterContact* contact);
243
244  //! Request that the server remove a contact
245  //! The jabber protocol specifies that the server should also cancel any
246  //! subscriptions when this is done.  Like adding, this contact won't be
247  //! removed until the server responds.
248  virtual XmppReturnStatus RequestRosterRemove(const Jid& jid);
249
250  // SUBSCRIPTION MANAGEMENT ---------------------------------------------------
251
252  //! Request a subscription to presence notifications form a Jid
253  virtual XmppReturnStatus RequestSubscription(const Jid& jid);
254
255  //! Cancel a subscription to presence notifications from a Jid
256  virtual XmppReturnStatus CancelSubscription(const Jid& jid);
257
258  //! Approve a request to deliver presence notifications to a jid
259  virtual XmppReturnStatus ApproveSubscriber(const Jid& jid);
260
261  //! Deny or cancel presence notification deliver to a jid
262  virtual XmppReturnStatus CancelSubscriber(const Jid& jid);
263
264  // XmppIqHandler IMPLEMENTATION ----------------------------------------------
265  virtual void IqResponse(XmppIqCookie cookie, const XmlElement * stanza);
266
267protected:
268  // XmppModuleImpl OVERRIDES --------------------------------------------------
269  virtual bool HandleStanza(const XmlElement *);
270
271  // PRIVATE DATA --------------------------------------------------------------
272private:
273  friend class XmppRosterModule;
274  XmppRosterModuleImpl();
275
276  // Helper functions
277  void DeleteIncomingPresence();
278  void DeleteContacts();
279  XmppReturnStatus SendSubscriptionRequest(const Jid& jid,
280                                           const std::string& type);
281  void InternalSubscriptionRequest(const Jid& jid, const XmlElement* stanza,
282                                   XmppSubscriptionRequestType request_type);
283  void InternalIncomingPresence(const Jid& jid, const XmlElement* stanza);
284  void InternalIncomingPresenceError(const Jid& jid, const XmlElement* stanza);
285  void InternalRosterItems(const XmlElement* stanza);
286
287  // Member data
288  XmppPresenceImpl outgoing_presence_;
289  XmppRosterHandler* roster_handler_;
290
291  typedef std::vector<XmppPresenceImpl*> PresenceVector;
292  typedef std::map<Jid, PresenceVector*> JidPresenceVectorMap;
293  rtc::scoped_ptr<JidPresenceVectorMap> incoming_presence_map_;
294  rtc::scoped_ptr<PresenceVector> incoming_presence_vector_;
295
296  typedef std::vector<XmppRosterContactImpl*> ContactVector;
297  rtc::scoped_ptr<ContactVector> contacts_;
298};
299
300}
301
302#endif  // TALK_XMPP_XMPPTHREAD_H_
303