~ari-tczew/ubuntu/natty/clementine/lp-747113

« back to all changes in this revision

Viewing changes to 3rdparty/gloox/client.h

  • Committer: Artur Rona
  • Date: 2011-04-04 20:05:33 UTC
  • Revision ID: ari-tczew@ubuntu.com-20110404200533-6aclzasj5pp8t1hq
* New upstream release. (LP: #747113)
* Drop all patches, have been applied upstream.
* Update debian/copyright.
* Refresh description in debian/control in order to avoid lintian error.
* Bump debhelper to 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  Copyright (c) 2004-2009 by Jakob Schroeter <js@camaya.net>
 
3
  This file is part of the gloox library. http://camaya.net/gloox
 
4
 
 
5
  This software is distributed under a license. The full license
 
6
  agreement can be found in the file LICENSE in this distribution.
 
7
  This software may not be copied, modified, sold or distributed
 
8
  other than expressed in the named license agreement.
 
9
 
 
10
  This software is distributed without any warranty.
 
11
*/
 
12
 
 
13
 
 
14
#ifndef CLIENT_H__
 
15
#define CLIENT_H__
 
16
 
 
17
#include "clientbase.h"
 
18
#include "presence.h"
 
19
 
 
20
#include <string>
 
21
 
 
22
namespace gloox
 
23
{
 
24
 
 
25
  class Capabilities;
 
26
  class RosterManager;
 
27
  class NonSaslAuth;
 
28
  class IQ;
 
29
 
 
30
  /**
 
31
   * @brief This class implements a basic Jabber Client.
 
32
   *
 
33
   * It supports @ref sasl_auth as well as TLS (Encryption), which can be
 
34
   * switched on/off separately. They are used automatically if the server supports them.
 
35
   *
 
36
   * To use, create a new Client instance and feed it connection credentials, either in the Constructor or
 
37
   * afterwards using the setters. You should then register packet handlers implementing the corresponding
 
38
   * Interfaces (ConnectionListener, PresenceHandler, MessageHandler, IqHandler, SubscriptionHandler),
 
39
   * and call @ref connect() to establish the connection to the server.<br>
 
40
   *
 
41
   * @note While the MessageHandler interface is still available (and will be in future versions)
 
42
   * it is now recommended to use the new @link gloox::MessageSession MessageSession @endlink for any
 
43
   * serious messaging.
 
44
   *
 
45
   * Simple usage example:
 
46
   * @code
 
47
   * using namespace gloox;
 
48
   *
 
49
   * void TestProg::doIt()
 
50
   * {
 
51
   *   Client* j = new Client( "user@server/resource", "password" );
 
52
   *   j->registerPresenceHandler( this );
 
53
   *   j->disco()->setVersion( "TestProg", "1.0" );
 
54
   *   j->disco()->setIdentity( "client", "bot" );
 
55
   *   j->connect();
 
56
   * }
 
57
   *
 
58
   * virtual void TestProg::presenceHandler( Presence* presence )
 
59
   * {
 
60
   *   // handle incoming presence packets here
 
61
   * }
 
62
   * @endcode
 
63
   *
 
64
   * However, you can skip the presence handling stuff if you make use of the RosterManager.
 
65
   *
 
66
   * By default, the library handles a few (incoming) IQ namespaces on the application's behalf. These
 
67
   * include:
 
68
   * @li jabber:iq:roster: by default the server-side roster is fetched and handled. Use
 
69
   * @ref rosterManager() and @ref RosterManager to interact with the Roster.
 
70
   * @li XEP-0092 (Software Version): If no version is specified, a name of "based on gloox" with
 
71
   * gloox's current version is announced.
 
72
   * @li XEP-0030 (Service Discovery): All supported/available services are announced. No items are
 
73
   * returned.
 
74
   * @note As of gloox 0.9, by default a priority of 0 is sent along with the initial presence.
 
75
   * @note As of gloox 0.9, initial presence is automatically sent. Presence: available, Priority: 0.
 
76
   * To disable sending of initial Presence use setPresence() with a value of Unavailable
 
77
   * prior to connecting.
 
78
   *
 
79
   * @section sasl_auth SASL Authentication
 
80
   *
 
81
   * Besides the simple, IQ-based authentication (XEP-0078), gloox supports several SASL (Simple
 
82
   * Authentication and Security Layer, RFC 2222) authentication mechanisms.
 
83
   * @li DIGEST-MD5: This mechanism is preferred over all other mechanisms if username and password are
 
84
   * provided to the Client instance. It is secure even without TLS encryption.
 
85
   * @li PLAIN: This mechanism is used if DIGEST-MD5 is not available. It is @b not secure without
 
86
   * encryption.
 
87
   * @li ANONYMOUS This mechanism is used if neither username nor password are set. The server generates
 
88
   * random, temporary username and resource and may restrict available services.
 
89
   * @li EXTERNAL This mechanism is currently only available if client certificate and private key
 
90
   * are provided. The server tries to figure out who the client is by external means -- for instance,
 
91
   * using the provided certificate or even the IP address. (The restriction to certificate/key
 
92
   * availability is likely to be lifted in the future.)
 
93
   *
 
94
   * Of course, all these mechanisms are not tried unless the server offers them.
 
95
   *
 
96
   * @author Jakob Schroeter <js@camaya.net>
 
97
   */
 
98
  class GLOOX_API Client : public ClientBase
 
99
  {
 
100
    public:
 
101
 
 
102
      friend class NonSaslAuth;
 
103
      friend class Parser;
 
104
 
 
105
      /**
 
106
       * Constructs a new Client which can be used for account registration only.
 
107
       * SASL and TLS are on by default. The port will be determined by looking up SRV records.
 
108
       * Alternatively, you can set the port explicitly by calling @ref setPort().
 
109
       * @param server The server to connect to.
 
110
       */
 
111
      Client( const std::string& server );
 
112
 
 
113
      /**
 
114
       * Constructs a new Client.
 
115
       * SASL and TLS are on by default. This should be the default constructor for most use cases.
 
116
       * The server address will be taken from the JID. The actual host will be resolved using SRV
 
117
       * records. The domain part of the JID is used as a fallback in case no SRV record is found, or
 
118
       * you can set the server address separately by calling @ref setServer().
 
119
       * @param jid A full Jabber ID used for connecting to the server.
 
120
       * @param password The password used for authentication.
 
121
       * @param port The port to connect to. The default of -1 means to look up the port via DNS SRV.
 
122
       */
 
123
      Client( const JID& jid, const std::string& password, int port = -1 );
 
124
 
 
125
      /**
 
126
       * Virtual destructor.
 
127
       */
 
128
      virtual ~Client();
 
129
 
 
130
      /**
 
131
       * Use this function to bind an additional resource or to @b re-try to bind a
 
132
       * resource in case previous binding failed and you were notified by means of
 
133
       * ConnectionListener::onResourceBindError(). Use hasResourceBind() to find out if the
 
134
       * server supports binding of multiple resources. bindResource() is a NOOP if it doesn't.
 
135
       * @note ConnectionListener::onResourceBound() and ConnectionListener::onResourceBindError()
 
136
       * will be called in case of success and failure, respectively.
 
137
       * @param resource The resource identifier to bind. May be empty. In that case
 
138
       * the server will assign a unique resource identifier.
 
139
       * @return Returns @b true if binding of multiple resources is supported, @b false
 
140
       * otherwise. A return value of @b true does not indicate that the resource was
 
141
       * successfully bound.
 
142
       * @note It is not necessary to call this function to bind the initial, main, resource.
 
143
       * @since 1.0
 
144
       */
 
145
      bool bindResource( const std::string& resource )
 
146
        { return bindOperation( resource, true ); }
 
147
 
 
148
      /**
 
149
       * Use this function to select a resource identifier that has been bound
 
150
       * previously by means of bindResource(). It is not necessary to call this function
 
151
       * if only one resource is bound. Use hasResourceBind() to find out if the
 
152
       * server supports binding of multiple resources. selectResource() is a NOOP if it doesn't.
 
153
       * @param resource A resource string that has been bound previously.
 
154
       * @note If the resource string has not been bound previously, future sending of
 
155
       * stanzas will fail.
 
156
       */
 
157
      bool selectResource( const std::string& resource );
 
158
 
 
159
      /**
 
160
       * This function can be used to find out whether the server supports binding of multiple
 
161
       * resources.
 
162
       * @return @b True if binding of multiple resources is supported by the server,
 
163
       * @b false otherwise.
 
164
       */
 
165
      bool hasResourceBind() const { return ((m_streamFeatures & StreamFeatureUnbind) == StreamFeatureUnbind); }
 
166
 
 
167
      /**
 
168
       * Use this function to unbind a resource identifier that has been bound
 
169
       * previously by means of bindResource(). Use hasResourceBind() to find out if the
 
170
       * server supports binding of multiple resources. unbindResource() is a NOOP if it doesn't.
 
171
       * @param resource A resource string that has been bound previously.
 
172
       * @note Servers are encouraged to terminate the connection should the only bound
 
173
       * resource be unbound.
 
174
       */
 
175
      bool unbindResource( const std::string& resource )
 
176
        { return bindOperation( resource, false ); }
 
177
 
 
178
      /**
 
179
       * Returns the current prepped main resource.
 
180
       * @return The resource used to connect.
 
181
       */
 
182
      const std::string& resource() const { return m_jid.resource(); }
 
183
 
 
184
      /**
 
185
       * Returns the current priority.
 
186
       * @return The priority of the current resource.
 
187
       */
 
188
      int priority() const { return m_presence.priority(); }
 
189
 
 
190
      /**
 
191
       * Sets the username to use to connect to the XMPP server.
 
192
       * @param username The username to authenticate with.
 
193
       */
 
194
      void setUsername( const std::string &username );
 
195
 
 
196
      /**
 
197
       * Sets the main resource to use to connect to the XMPP server.
 
198
       * @param resource The resource to use to log into the server.
 
199
       */
 
200
      void setResource( const std::string &resource ) { m_jid.setResource( resource ); }
 
201
 
 
202
      /**
 
203
       * Sends directed presence to the given JID. This is a NOOP if there's no active connection.
 
204
       * To broadcast presence use setPresence( Presence::PresenceType, int, const std::string& ).
 
205
       * @param to The JID to send directed Presence to.
 
206
       * @param pres The presence to send.
 
207
       * @param priority The priority to include. Legal values: -128 <= priority <= 127
 
208
       * @param status The optional status message to include.
 
209
       * @note This function does not include any presence extensions (as added by
 
210
       * means of addPresenceExtension()) to the stanza.
 
211
       */
 
212
      void setPresence( const JID& to, Presence::PresenceType pres, int priority,
 
213
                        const std::string& status = EmptyString );
 
214
 
 
215
      /**
 
216
       * Use this function to set the entity's presence, that is, to broadcast presence to all
 
217
       * subscribed entities. To send directed presence, use
 
218
       * setPresence( const JID&, Presence::PresenceType, int, const std::string& ).
 
219
       * If used prior to establishing a connection, the set values will be sent with
 
220
       * the initial presence stanza.
 
221
       * If used while a connection already is established, a presence stanza will be
 
222
       * sent out immediately.
 
223
       * @param pres The Presence value to set.
 
224
       * @param priority An optional priority value. Legal values: -128 <= priority <= 127
 
225
       * @param status An optional message describing the presence state.
 
226
       * @since 0.9
 
227
       */
 
228
      void setPresence( Presence::PresenceType pres, int priority,
 
229
                        const std::string& status = EmptyString );
 
230
 
 
231
      /**
 
232
       * Use this function to broadcast the entity's presence to all
 
233
       * subscribed entities. This is a NOOP if there's no active connection.
 
234
       * To send directed presence, use
 
235
       * setPresence( const JID&, Presence::PresenceType, int, const std::string& ).
 
236
       * If used while a connection already is established a repective presence stanza will be
 
237
       * sent out immediately. Use presence() to modify the Presence object.
 
238
       * @note When login is finished, initial presence will be sent automatically.
 
239
       * So you do not need to call this function after login.
 
240
       * @since 1.0
 
241
       */
 
242
      void setPresence() { sendPresence( m_presence ); }
 
243
 
 
244
      /**
 
245
       * Returns the current presence.
 
246
       * @return The current presence.
 
247
       */
 
248
      Presence& presence() { return m_presence; }
 
249
 
 
250
      /**
 
251
       * This is a temporary hack to enforce Non-SASL login. You should not need to use it.
 
252
       * @param force Whether to force non-SASL auth. Default @b true.
 
253
       * @deprecated Please update the server to properly support SASL instead.
 
254
       */
 
255
      GLOOX_DEPRECATED void setForceNonSasl( bool force = true ) { m_forceNonSasl = force; }
 
256
 
 
257
      /**
 
258
       * Disables the automatic roster management.
 
259
       * You have to keep track of incoming presence yourself if
 
260
       * you want to have a roster.
 
261
       */
 
262
      void disableRoster();
 
263
 
 
264
      /**
 
265
       * This function gives access to the @c RosterManager object.
 
266
       * @return A pointer to the RosterManager.
 
267
       */
 
268
      RosterManager* rosterManager() { return m_rosterManager; }
 
269
 
 
270
      /**
 
271
       * Disconnects from the server.
 
272
       */
 
273
      void disconnect();
 
274
 
 
275
      /**
 
276
       * Initiates a login attempt (currently SASL External not supported).
 
277
       * This is useful after registering a new account. Simply use setUsername() and setPassword(),
 
278
       * and call login().
 
279
       * @return @b True if a login attempt could be started, @b false otherwise. A return
 
280
       * value of @b true does not indicate that login was successful.
 
281
       */
 
282
      bool login();
 
283
 
 
284
    protected:
 
285
      /**
 
286
       * Initiates non-SASL login.
 
287
       */
 
288
      void nonSaslLogin();
 
289
 
 
290
    private:
 
291
      /**
 
292
       * @brief This is an implementation of a resource binding StanzaExtension.
 
293
       *
 
294
       * @author Jakob Schroeter <js@camaya.net>
 
295
       * @since 1.0
 
296
       */
 
297
      class ResourceBind : public StanzaExtension
 
298
      {
 
299
 
 
300
        public:
 
301
          /**
 
302
           * Constructs a new object with the given resource string.
 
303
           * @param resource The resource to set.
 
304
           * @param bind Indicates whether this is an bind or unbind request.
 
305
           * Defaults to @b true (bind).
 
306
           */
 
307
          ResourceBind( const std::string& resource, bool bind = true );
 
308
 
 
309
          /**
 
310
           * Constructs a new object from the given Tag.
 
311
           * @param tag The Tag to parse.
 
312
           */
 
313
          ResourceBind( const Tag* tag );
 
314
 
 
315
          /**
 
316
           * Destructor.
 
317
           */
 
318
          ~ResourceBind();
 
319
 
 
320
          /**
 
321
           * Returns the requested resource.
 
322
           * @return The requested resource.
 
323
           */
 
324
          const std::string& resource() const { return m_resource; }
 
325
 
 
326
          /**
 
327
           * Returns the assigned JID.
 
328
           * @return The assigned JID.
 
329
           */
 
330
          const JID& jid() const { return m_jid; }
 
331
 
 
332
          /**
 
333
           * Use this function to find out whether the extension contains a
 
334
           * bind or unbind request.
 
335
           * @return @b True if the extension contains an unbind request, @b false otherwise.
 
336
           */
 
337
          bool unbind() const { return !m_bind; }
 
338
 
 
339
          // reimplemented from StanzaExtension
 
340
          virtual const std::string& filterString() const;
 
341
 
 
342
          // reimplemented from StanzaExtension
 
343
          virtual StanzaExtension* newInstance( const Tag* tag ) const
 
344
          {
 
345
            return new ResourceBind( tag );
 
346
          }
 
347
 
 
348
          // reimplemented from StanzaExtension
 
349
          virtual Tag* tag() const;
 
350
 
 
351
          // reimplemented from StanzaExtension
 
352
          virtual StanzaExtension* clone() const
 
353
          {
 
354
            return new ResourceBind( *this );
 
355
          }
 
356
 
 
357
        private:
 
358
          std::string m_resource;
 
359
          JID m_jid;
 
360
          bool m_bind;
 
361
      };
 
362
 
 
363
      /**
 
364
       * @brief This is an implementation of a session creating StanzaExtension.
 
365
       *
 
366
       * @author Jakob Schroeter <js@camaya.net>
 
367
       * @since 1.0
 
368
       */
 
369
      class SessionCreation : public StanzaExtension
 
370
      {
 
371
 
 
372
        public:
 
373
          /**
 
374
           * Constructs a new object.
 
375
           */
 
376
          SessionCreation() : StanzaExtension( ExtSessionCreation ) {}
 
377
 
 
378
          /**
 
379
           * Destructor.
 
380
           */
 
381
          ~SessionCreation() {}
 
382
 
 
383
          // reimplemented from StanzaExtension
 
384
          virtual const std::string& filterString() const { return EmptyString; }
 
385
 
 
386
          // reimplemented from StanzaExtension
 
387
          virtual StanzaExtension* newInstance( const Tag* tag ) const
 
388
            { (void)tag; return 0; }
 
389
 
 
390
          // reimplemented from StanzaExtension
 
391
          virtual Tag* tag() const;
 
392
 
 
393
          // reimplemented from StanzaExtension
 
394
          virtual StanzaExtension* clone() const
 
395
            { return 0; }
 
396
 
 
397
      };
 
398
 
 
399
      virtual void handleStartNode() {}
 
400
      virtual bool handleNormalNode( Tag* tag );
 
401
      virtual void disconnect( ConnectionError reason );
 
402
      virtual void handleIqIDForward( const IQ& iq, int context );
 
403
 
 
404
      int getStreamFeatures( Tag* tag );
 
405
      int getSaslMechs( Tag* tag );
 
406
      int getCompressionMethods( Tag* tag );
 
407
      void processResourceBind( const IQ& iq );
 
408
      void processCreateSession( const IQ& iq );
 
409
      void sendPresence( Presence& pres );
 
410
      void createSession();
 
411
      void negotiateCompression( StreamFeature method );
 
412
      void connected();
 
413
      virtual void rosterFilled();
 
414
      virtual void cleanup();
 
415
      bool bindOperation( const std::string& resource, bool bind );
 
416
 
 
417
      void init();
 
418
 
 
419
      enum TrackContext
 
420
      {
 
421
        CtxResourceBind = 1000,  // must be higher than the last element in ClientBase's TrackContext
 
422
        CtxResourceUnbind,
 
423
        CtxSessionEstablishment
 
424
      };
 
425
 
 
426
      RosterManager* m_rosterManager;
 
427
      NonSaslAuth* m_auth;
 
428
 
 
429
      Presence m_presence;
 
430
 
 
431
      bool m_resourceBound;
 
432
      bool m_forceNonSasl;
 
433
      bool m_manageRoster;
 
434
 
 
435
      int m_streamFeatures;
 
436
 
 
437
  };
 
438
 
 
439
}
 
440
 
 
441
#endif // CLIENT_H__