2
Copyright (c) 2004-2009 by Jakob Schroeter <js@camaya.net>
3
This file is part of the gloox library. http://camaya.net/gloox
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.
10
This software is distributed without any warranty.
17
#include "clientbase.h"
31
* @brief This class implements a basic Jabber Client.
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.
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>
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
45
* Simple usage example:
47
* using namespace gloox;
49
* void TestProg::doIt()
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" );
58
* virtual void TestProg::presenceHandler( Presence* presence )
60
* // handle incoming presence packets here
64
* However, you can skip the presence handling stuff if you make use of the RosterManager.
66
* By default, the library handles a few (incoming) IQ namespaces on the application's behalf. These
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
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.
79
* @section sasl_auth SASL Authentication
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
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.)
94
* Of course, all these mechanisms are not tried unless the server offers them.
96
* @author Jakob Schroeter <js@camaya.net>
98
class GLOOX_API Client : public ClientBase
102
friend class NonSaslAuth;
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.
111
Client( const std::string& server );
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.
123
Client( const JID& jid, const std::string& password, int port = -1 );
126
* Virtual destructor.
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.
145
bool bindResource( const std::string& resource )
146
{ return bindOperation( resource, true ); }
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
157
bool selectResource( const std::string& resource );
160
* This function can be used to find out whether the server supports binding of multiple
162
* @return @b True if binding of multiple resources is supported by the server,
163
* @b false otherwise.
165
bool hasResourceBind() const { return ((m_streamFeatures & StreamFeatureUnbind) == StreamFeatureUnbind); }
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.
175
bool unbindResource( const std::string& resource )
176
{ return bindOperation( resource, false ); }
179
* Returns the current prepped main resource.
180
* @return The resource used to connect.
182
const std::string& resource() const { return m_jid.resource(); }
185
* Returns the current priority.
186
* @return The priority of the current resource.
188
int priority() const { return m_presence.priority(); }
191
* Sets the username to use to connect to the XMPP server.
192
* @param username The username to authenticate with.
194
void setUsername( const std::string &username );
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.
200
void setResource( const std::string &resource ) { m_jid.setResource( resource ); }
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.
212
void setPresence( const JID& to, Presence::PresenceType pres, int priority,
213
const std::string& status = EmptyString );
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.
228
void setPresence( Presence::PresenceType pres, int priority,
229
const std::string& status = EmptyString );
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.
242
void setPresence() { sendPresence( m_presence ); }
245
* Returns the current presence.
246
* @return The current presence.
248
Presence& presence() { return m_presence; }
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.
255
GLOOX_DEPRECATED void setForceNonSasl( bool force = true ) { m_forceNonSasl = force; }
258
* Disables the automatic roster management.
259
* You have to keep track of incoming presence yourself if
260
* you want to have a roster.
262
void disableRoster();
265
* This function gives access to the @c RosterManager object.
266
* @return A pointer to the RosterManager.
268
RosterManager* rosterManager() { return m_rosterManager; }
271
* Disconnects from the server.
276
* Initiates a login attempt (currently SASL External not supported).
277
* This is useful after registering a new account. Simply use setUsername() and setPassword(),
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.
286
* Initiates non-SASL login.
292
* @brief This is an implementation of a resource binding StanzaExtension.
294
* @author Jakob Schroeter <js@camaya.net>
297
class ResourceBind : public StanzaExtension
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).
307
ResourceBind( const std::string& resource, bool bind = true );
310
* Constructs a new object from the given Tag.
311
* @param tag The Tag to parse.
313
ResourceBind( const Tag* tag );
321
* Returns the requested resource.
322
* @return The requested resource.
324
const std::string& resource() const { return m_resource; }
327
* Returns the assigned JID.
328
* @return The assigned JID.
330
const JID& jid() const { return m_jid; }
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.
337
bool unbind() const { return !m_bind; }
339
// reimplemented from StanzaExtension
340
virtual const std::string& filterString() const;
342
// reimplemented from StanzaExtension
343
virtual StanzaExtension* newInstance( const Tag* tag ) const
345
return new ResourceBind( tag );
348
// reimplemented from StanzaExtension
349
virtual Tag* tag() const;
351
// reimplemented from StanzaExtension
352
virtual StanzaExtension* clone() const
354
return new ResourceBind( *this );
358
std::string m_resource;
364
* @brief This is an implementation of a session creating StanzaExtension.
366
* @author Jakob Schroeter <js@camaya.net>
369
class SessionCreation : public StanzaExtension
374
* Constructs a new object.
376
SessionCreation() : StanzaExtension( ExtSessionCreation ) {}
381
~SessionCreation() {}
383
// reimplemented from StanzaExtension
384
virtual const std::string& filterString() const { return EmptyString; }
386
// reimplemented from StanzaExtension
387
virtual StanzaExtension* newInstance( const Tag* tag ) const
388
{ (void)tag; return 0; }
390
// reimplemented from StanzaExtension
391
virtual Tag* tag() const;
393
// reimplemented from StanzaExtension
394
virtual StanzaExtension* clone() const
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 );
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 );
413
virtual void rosterFilled();
414
virtual void cleanup();
415
bool bindOperation( const std::string& resource, bool bind );
421
CtxResourceBind = 1000, // must be higher than the last element in ClientBase's TrackContext
423
CtxSessionEstablishment
426
RosterManager* m_rosterManager;
431
bool m_resourceBound;
435
int m_streamFeatures;