001/**
002 *
003 * Copyright 2009 Jive Software.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.jivesoftware.smack;
018
019import org.jivesoftware.smack.SmackException.NoResponseException;
020import org.jivesoftware.smack.SmackException.NotConnectedException;
021import org.jivesoftware.smack.filter.IQReplyFilter;
022import org.jivesoftware.smack.filter.StanzaFilter;
023import org.jivesoftware.smack.iqrequest.IQRequestHandler;
024import org.jivesoftware.smack.packet.ExtensionElement;
025import org.jivesoftware.smack.packet.IQ;
026import org.jivesoftware.smack.packet.Nonza;
027import org.jivesoftware.smack.packet.Stanza;
028
029import org.jxmpp.jid.DomainBareJid;
030import org.jxmpp.jid.EntityFullJid;
031
032/**
033 * The XMPPConnection interface provides an interface for connections to an XMPP server and
034 * implements shared methods which are used by the different types of connections (e.g.
035 * <code>XMPPTCPConnection</code> or <code>XMPPBOSHConnection</code>). To create a connection to an XMPP server
036 * a simple usage of this API might look like the following:
037 * <p>
038 * 
039 * <pre>
040 * // Create a connection to the igniterealtime.org XMPP server.
041 * XMPPTCPConnection con = new XMPPTCPConnection("igniterealtime.org");
042 * // Connect to the server
043 * con.connect();
044 * // Most servers require you to login before performing other tasks.
045 * con.login("jsmith", "mypass");
046 * // Start a new conversation with John Doe and send him a message.
047 * Chat chat = ChatManager.getInstanceFor(con).createChat(<font color="green">"jdoe@igniterealtime.org"</font>, new MessageListener() {
048 *     public void processMessage(Chat chat, Message message) {
049 *         // Print out any messages we get back to standard out.
050 *         System.out.println(<font color="green">"Received message: "</font> + message);
051 *     }
052 * });
053 * chat.sendMessage(<font color="green">"Howdy!"</font>);
054 * // Disconnect from the server
055 * con.disconnect();
056 * </pre>
057 * </p>
058 * <p>
059 * Note that the XMPPConnection interface does intentionally not declare any methods that manipulate
060 * the connection state, e.g. <code>connect()</code>, <code>disconnect()</code>. You should use the
061 * most specific connection type, e.g. <code>XMPPTCPConnection</code> as declared type and use the
062 * XMPPConnection interface when you don't need to manipulate the connection state.
063 * </p>
064 * <p>
065 * XMPPConnections can be reused between connections. This means that an Connection may be connected,
066 * disconnected and then connected again. Listeners of the XMPPConnection will be retained across
067 * connections.
068 * </p>
069 *
070 * @author Matt Tucker
071 * @author Guenther Niess
072 */
073public interface XMPPConnection {
074
075    /**
076     * Returns the name of the service provided by the XMPP server for this connection.
077     * This is also called XMPP domain of the connected server. After
078     * authenticating with the server the returned value may be different.
079     * 
080     * @return the name of the service provided by the XMPP server.
081     // TODO remove this once the java bugs are fixed, causing a warning
082//     * @deprecated use {@link #getXMPPServiceDomain()} instead.
083     */
084//    @Deprecated
085    public DomainBareJid getServiceName();
086
087    /**
088     * Returns the XMPP Domain of the service provided by the XMPP server and used for this connection. After
089     * authenticating with the server the returned value may be different.
090     * 
091     * @return the XMPP domain of this XMPP session.
092     */
093    public DomainBareJid getXMPPServiceDomain();
094
095    /**
096     * Returns the host name of the server where the XMPP server is running. This would be the
097     * IP address of the server or a name that may be resolved by a DNS server.
098     * 
099     * @return the host name of the server where the XMPP server is running or null if not yet connected.
100     */
101    public String getHost();
102
103    /**
104     * Returns the port number of the XMPP server for this connection. The default port
105     * for normal connections is 5222.
106     * 
107     * @return the port number of the XMPP server or 0 if not yet connected.
108     */
109    public int getPort();
110
111    /**
112     * Returns the full XMPP address of the user that is logged in to the connection or
113     * <tt>null</tt> if not logged in yet. An XMPP address is in the form
114     * username@server/resource.
115     * 
116     * @return the full XMPP address of the user logged in.
117     */
118    public EntityFullJid getUser();
119
120    /**
121     * Returns the stream ID for this connection, which is the value set by the server
122     * when opening an XMPP stream. This value will be <tt>null</tt> if not connected to the server.
123     * 
124     * @return the ID of this connection returned from the XMPP server or <tt>null</tt> if
125     *      not connected to the server.
126     * @see <a href="http://xmpp.org/rfcs/rfc6120.html#streams-attr-id">RFC 6120 ยง 4.7.3. id</a>
127     */
128    public String getStreamId();
129
130    /**
131     * Returns true if currently connected to the XMPP server.
132     * 
133     * @return true if connected.
134     */
135    public boolean isConnected();
136
137    /**
138     * Returns true if currently authenticated by successfully calling the login method.
139     * 
140     * @return true if authenticated.
141     */
142    public boolean isAuthenticated();
143
144    /**
145     * Returns true if currently authenticated anonymously.
146     * 
147     * @return true if authenticated anonymously.
148     */
149    public boolean isAnonymous();
150
151    /**
152     * Returns true if the connection to the server has successfully negotiated encryption. 
153     * 
154     * @return true if a secure connection to the server.
155     */
156    public boolean isSecureConnection();
157
158    /**
159     * Returns true if network traffic is being compressed. When using stream compression network
160     * traffic can be reduced up to 90%. Therefore, stream compression is ideal when using a slow
161     * speed network connection. However, the server will need to use more CPU time in order to
162     * un/compress network data so under high load the server performance might be affected.
163     * 
164     * @return true if network traffic is being compressed.
165     */
166    public boolean isUsingCompression();
167
168    /**
169     * Sends the specified stanza(/packet) to the server.
170     * 
171     * @param packet the stanza(/packet) to send.
172     * @throws NotConnectedException 
173     * @throws InterruptedException 
174     * @deprecated use {@link #sendStanza(Stanza)} instead.
175     */
176    @Deprecated
177    public void sendPacket(Stanza packet) throws NotConnectedException, InterruptedException;
178
179    /**
180     * Sends the specified stanza to the server.
181     *
182     * @param stanza the stanza to send.
183     * @throws NotConnectedException if the connection is not connected.
184     * @throws InterruptedException
185     * */
186    public void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException;
187
188    /**
189     * Send a Nonza.
190     * <p>
191     * <b>This method is not meant for end-user usage!</b> It allows sending plain stream elements, which should not be
192     * done by a user manually. <b>Doing so may result in a unstable or unusable connection.</b> Certain Smack APIs use
193     * this method to send plain stream elements.
194     * </p>
195     *
196     * @param nonza the Nonza to send.
197     * @throws NotConnectedException
198     * @throws InterruptedException 
199     */
200    public void sendNonza(Nonza nonza) throws NotConnectedException, InterruptedException;
201
202    /**
203     * Adds a connection listener to this connection that will be notified when
204     * the connection closes or fails.
205     * 
206     * @param connectionListener a connection listener.
207     */
208    public void addConnectionListener(ConnectionListener connectionListener);
209
210    /**
211     * Removes a connection listener from this connection.
212     * 
213     * @param connectionListener a connection listener.
214     */
215    public void removeConnectionListener(ConnectionListener connectionListener);
216
217    /**
218     * Creates a new stanza(/packet) collector collecting packets that are replies to <code>packet</code>.
219     * Does also send <code>packet</code>. The stanza(/packet) filter for the collector is an
220     * {@link IQReplyFilter}, guaranteeing that stanza(/packet) id and JID in the 'from' address have
221     * expected values.
222     *
223     * @param packet the stanza(/packet) to filter responses from
224     * @return a new stanza(/packet) collector.
225     * @throws NotConnectedException 
226     * @throws InterruptedException 
227     */
228    public StanzaCollector createStanzaCollectorAndSend(IQ packet) throws NotConnectedException, InterruptedException;
229
230    /**
231     * Creates a new stanza(/packet) collector for this connection. A stanza(/packet) filter determines
232     * which packets will be accumulated by the collector. A StanzaCollector is
233     * more suitable to use than a {@link StanzaListener} when you need to wait for
234     * a specific result.
235     * 
236     * @param packetFilter the stanza(/packet) filter to use.
237     * @param packet the packet to send right after the collector got created
238     * @return a new stanza(/packet) collector.
239     * @throws InterruptedException 
240     * @throws NotConnectedException 
241     */
242    public StanzaCollector createStanzaCollectorAndSend(StanzaFilter packetFilter, Stanza packet)
243                    throws NotConnectedException, InterruptedException;
244
245    /**
246     * Creates a new stanza(/packet) collector for this connection. A stanza(/packet) filter
247     * determines which packets will be accumulated by the collector. A
248     * StanzaCollector is more suitable to use than a {@link StanzaListener}
249     * when you need to wait for a specific result.
250     * <p>
251     * <b>Note:</b> If you send a Stanza(/Packet) right after using this method, then
252     * consider using
253     * {@link #createStanzaCollectorAndSend(StanzaFilter, Stanza)} instead.
254     * Otherwise make sure cancel the StanzaCollector in every case, e.g. even
255     * if an exception is thrown, or otherwise you may leak the StanzaCollector.
256     * </p>
257     * 
258     * @param packetFilter the stanza(/packet) filter to use.
259     * @return a new stanza(/packet) collector.
260     */
261    public StanzaCollector createStanzaCollector(StanzaFilter packetFilter);
262
263    /**
264     * Create a new stanza(/packet) collector with the given stanza(/packet) collector configuration.
265     * <p>
266     * Please make sure to cancel the collector when it is no longer required. See also
267     * {@link #createStanzaCollector(StanzaFilter)}.
268     * </p>
269     * 
270     * @param configuration the stanza(/packet) collector configuration.
271     * @return a new stanza(/packet) collector.
272     * @since 4.1
273     */
274    public StanzaCollector createStanzaCollector(StanzaCollector.Configuration configuration);
275
276    /**
277     * Remove a stanza(/packet) collector of this connection.
278     * 
279     * @param collector a stanza(/packet) collectors which was created for this connection.
280     */
281    public void removeStanzaCollector(StanzaCollector collector);
282
283    /**
284     * Registers a stanza(/packet) listener with this connection.
285     * <p>
286     * This method has been deprecated. It is important to differentiate between using an asynchronous stanza(/packet) listener
287     * (preferred where possible) and a synchronous stanza(/packet) lister. Refer
288     * {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} and
289     * {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)} for more information.
290     * </p>
291     *
292     * @param packetListener the stanza(/packet) listener to notify of new received packets.
293     * @param packetFilter the stanza(/packet) filter to use.
294     * @deprecated use {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} or
295     *             {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)}.
296     */
297    @Deprecated
298    public void addPacketListener(StanzaListener packetListener, StanzaFilter packetFilter);
299
300    /**
301     * Removes a stanza(/packet) listener for received packets from this connection.
302     * 
303     * @param packetListener the stanza(/packet) listener to remove.
304     * @return true if the stanza(/packet) listener was removed
305     * @deprecated use {@link #removeAsyncStanzaListener(StanzaListener)} or {@link #removeSyncStanzaListener(StanzaListener)}.
306     */
307    @Deprecated
308    public boolean removePacketListener(StanzaListener packetListener);
309
310    /**
311     * Registers a <b>synchronous</b> stanza(/packet) listener with this connection. A stanza(/packet) listener will be invoked only when
312     * an incoming stanza(/packet) is received. A stanza(/packet) filter determines which packets will be delivered to the listener. If
313     * the same stanza(/packet) listener is added again with a different filter, only the new filter will be used.
314     * <p>
315     * <b>Important:</b> This stanza(/packet) listeners will be called in the same <i>single</i> thread that processes all
316     * incoming stanzas. Only use this kind of stanza(/packet) filter if it does not perform any XMPP activity that waits for a
317     * response. Consider using {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} when possible, i.e. when
318     * the invocation order doesn't have to be the same as the order of the arriving packets. If the order of the
319     * arriving packets, consider using a {@link StanzaCollector} when possible.
320     * </p>
321     *
322     * @param packetListener the stanza(/packet) listener to notify of new received packets.
323     * @param packetFilter the stanza(/packet) filter to use.
324     * @see #addPacketInterceptor(StanzaListener, StanzaFilter)
325     * @since 4.1
326     */
327    public void addSyncStanzaListener(StanzaListener packetListener, StanzaFilter packetFilter);
328
329    /**
330     * Removes a stanza(/packet) listener for received packets from this connection.
331     *
332     * @param packetListener the stanza(/packet) listener to remove.
333     * @return true if the stanza(/packet) listener was removed
334     * @since 4.1
335     */
336    public boolean removeSyncStanzaListener(StanzaListener packetListener);
337
338    /**
339     * Registers an <b>asynchronous</b> stanza(/packet) listener with this connection. A stanza(/packet) listener will be invoked only
340     * when an incoming stanza(/packet) is received. A stanza(/packet) filter determines which packets will be delivered to the listener.
341     * If the same stanza(/packet) listener is added again with a different filter, only the new filter will be used.
342     * <p>
343     * Unlike {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} stanza(/packet) listeners added with this method will be
344     * invoked asynchronously in their own thread. Use this method if the order of the stanza(/packet) listeners must not depend
345     * on the order how the stanzas where received.
346     * </p>
347     * 
348     * @param packetListener the stanza(/packet) listener to notify of new received packets.
349     * @param packetFilter the stanza(/packet) filter to use.
350     * @see #addPacketInterceptor(StanzaListener, StanzaFilter)
351     * @since 4.1
352    */
353    public void addAsyncStanzaListener(StanzaListener packetListener, StanzaFilter packetFilter);
354
355    /**
356     * Removes an <b>asynchronous</b> stanza(/packet) listener for received packets from this connection.
357     * 
358     * @param packetListener the stanza(/packet) listener to remove.
359     * @return true if the stanza(/packet) listener was removed
360     * @since 4.1
361     */
362    public boolean removeAsyncStanzaListener(StanzaListener packetListener);
363
364    /**
365     * Registers a stanza(/packet) listener with this connection. The listener will be
366     * notified of every stanza(/packet) that this connection sends. A stanza(/packet) filter determines
367     * which packets will be delivered to the listener. Note that the thread
368     * that writes packets will be used to invoke the listeners. Therefore, each
369     * stanza(/packet) listener should complete all operations quickly or use a different
370     * thread for processing.
371     * 
372     * @param packetListener the stanza(/packet) listener to notify of sent packets.
373     * @param packetFilter   the stanza(/packet) filter to use.
374     */
375    public void addPacketSendingListener(StanzaListener packetListener, StanzaFilter packetFilter);
376
377    /**
378     * Removes a stanza(/packet) listener for sending packets from this connection.
379     * 
380     * @param packetListener the stanza(/packet) listener to remove.
381     */
382    public void removePacketSendingListener(StanzaListener packetListener);
383
384    /**
385     * Registers a stanza(/packet) interceptor with this connection. The interceptor will be
386     * invoked every time a stanza(/packet) is about to be sent by this connection. Interceptors
387     * may modify the stanza(/packet) to be sent. A stanza(/packet) filter determines which packets
388     * will be delivered to the interceptor.
389     * 
390     * <p>
391     * NOTE: For a similar functionality on incoming packets, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}.
392     *
393     * @param packetInterceptor the stanza(/packet) interceptor to notify of packets about to be sent.
394     * @param packetFilter      the stanza(/packet) filter to use.
395     */
396    public void addPacketInterceptor(StanzaListener packetInterceptor, StanzaFilter packetFilter);
397
398    /**
399     * Removes a stanza(/packet) interceptor.
400     *
401     * @param packetInterceptor the stanza(/packet) interceptor to remove.
402     */
403    public void removePacketInterceptor(StanzaListener packetInterceptor);
404
405    /**
406     * Returns the current value of the reply timeout in milliseconds for request for this
407     * XMPPConnection instance.
408     *
409     * @return the stanza(/packet) reply timeout in milliseconds
410     * @deprecated use {@link #getReplyTimeout()} instead.
411     */
412    @Deprecated
413    // TODO Remove in Smack 4.3
414    public long getPacketReplyTimeout();
415
416    /**
417     * Set the stanza(/packet) reply timeout in milliseconds. In most cases, Smack will throw a
418     * {@link NoResponseException} if no reply to a request was received within the timeout period.
419     *
420     * @param timeout the stanza(/packet) reply timeout in milliseconds
421     * @deprecated use {@link #setReplyTimeout(long)} instead.
422     */
423    @Deprecated
424    // TODO Remove in Smack 4.3
425    public void setPacketReplyTimeout(long timeout);
426
427    /**
428     * Returns the current value of the reply timeout in milliseconds for request for this
429     * XMPPConnection instance.
430     *
431     * @return the reply timeout in milliseconds
432     */
433    public long getReplyTimeout();
434
435    /**
436     * Set the stanza(/packet) reply timeout in milliseconds. In most cases, Smack will throw a
437     * {@link NoResponseException} if no reply to a request was received within the timeout period.
438     *
439     * @param timeout for a reply in milliseconds
440     */
441    public void setReplyTimeout(long timeout);
442
443    /**
444     * Get the connection counter of this XMPPConnection instance. Those can be used as ID to
445     * identify the connection, but beware that the ID may not be unique if you create more then
446     * <tt>2*Integer.MAX_VALUE</tt> instances as the counter could wrap.
447     *
448     * @return the connection counter of this XMPPConnection
449     */
450    public int getConnectionCounter();
451
452    public static enum FromMode {
453        /**
454         * Leave the 'from' attribute unchanged. This is the behavior of Smack < 4.0
455         */
456        UNCHANGED,
457        /**
458         * Omit the 'from' attribute. According to RFC 6120 8.1.2.1 1. XMPP servers "MUST (...)
459         * override the 'from' attribute specified by the client". It is therefore safe to specify
460         * FromMode.OMITTED here.
461         */
462        OMITTED,
463        /**
464         * Set the from to the clients full JID. This is usually not required.
465         */
466        USER
467    }
468
469    /**
470     * Set the FromMode for this connection instance. Defines how the 'from' attribute of outgoing
471     * stanzas should be populated by Smack.
472     * 
473     * @param fromMode
474     */
475    public void setFromMode(FromMode fromMode);
476
477    /**
478     * Get the currently active FromMode.
479     *
480     * @return the currently active {@link FromMode}
481     */
482    public FromMode getFromMode();
483
484    /**
485     * Get the feature stanza(/packet) extensions for a given stream feature of the
486     * server, or <code>null</code> if the server doesn't support that feature.
487     * 
488     * @param element
489     * @param namespace
490     * @return a stanza(/packet) extensions of the feature or <code>null</code>
491     */
492    public <F extends ExtensionElement> F getFeature(String element, String namespace);
493
494    /**
495     * Return true if the server supports the given stream feature.
496     * 
497     * @param element
498     * @param namespace
499     * @return true if the server supports the stream feature.
500     */
501    public boolean hasFeature(String element, String namespace);
502
503    /**
504     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
505     * <p>
506     * If there is a response, then <code>callback</code> will be invoked. The callback will be
507     * invoked at most once and it will be not invoked after the connections default reply timeout
508     * has been elapsed.
509     * </p>
510     * 
511     * @param stanza the stanza to send (required)
512     * @param replyFilter the filter used to determine response stanza (required)
513     * @param callback the callback invoked if there is a response (required)
514     * @throws NotConnectedException
515     * @throws InterruptedException 
516     */
517    public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
518                    StanzaListener callback) throws NotConnectedException, InterruptedException;
519
520    /**
521     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
522     * <p>
523     * If there is a response, then <code>callback</code> will be invoked. If there is no response
524     * after the connections default reply timeout, then <code>exceptionCallback</code> will be invoked
525     * with a {@link SmackException.NoResponseException}. The callback will be invoked at most once.
526     * </p>
527     * 
528     * @param stanza the stanza to send (required)
529     * @param replyFilter the filter used to determine response stanza (required)
530     * @param callback the callback invoked if there is a response (required)
531     * @param exceptionCallback the callback invoked if there is an exception (optional)
532     * @throws NotConnectedException
533     * @throws InterruptedException 
534     */
535    public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, StanzaListener callback,
536                    ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
537
538    /**
539     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
540     * <p>
541     * If there is a response, then <code>callback</code> will be invoked. If there is no response
542     * after <code>timeout</code> milliseconds, then <code>exceptionCallback</code> will be invoked
543     * with a {@link SmackException.NoResponseException}. The callback will be invoked at most once.
544     * </p>
545     * 
546     * @param stanza the stanza to send (required)
547     * @param replyFilter the filter used to determine response stanza (required)
548     * @param callback the callback invoked if there is a response (required)
549     * @param exceptionCallback the callback invoked if there is an exception (optional)
550     * @param timeout the timeout in milliseconds to wait for a response
551     * @throws NotConnectedException
552     * @throws InterruptedException 
553     */
554    public void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
555                    final StanzaListener callback, final ExceptionCallback exceptionCallback,
556                    long timeout) throws NotConnectedException, InterruptedException;
557
558    /**
559     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
560     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. The callback will
561     * not be invoked after the connections default reply timeout has been elapsed.
562     * 
563     * @param iqRequest the IQ stanza to send (required)
564     * @param callback the callback invoked if there is result response (required)
565     * @throws NotConnectedException
566     * @throws InterruptedException 
567     */
568    public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback) throws NotConnectedException, InterruptedException;
569
570    /**
571     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
572     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. If there is an
573     * error response <code>exceptionCallback</code> will be invoked, if not null, with the received
574     * error as {@link XMPPException.XMPPErrorException}. If there is no response after the
575     * connections default reply timeout, then <code>exceptionCallback</code> will be invoked with a
576     * {@link SmackException.NoResponseException}.
577     * 
578     * @param iqRequest the IQ stanza to send (required)
579     * @param callback the callback invoked if there is result response (required)
580     * @param exceptionCallback the callback invoked if there is an Exception optional
581     * @throws NotConnectedException
582     * @throws InterruptedException 
583     */
584    public void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
585                    ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
586
587    /**
588     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
589     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. If there is an
590     * error response <code>exceptionCallback</code> will be invoked, if not null, with the received
591     * error as {@link XMPPException.XMPPErrorException}. If there is no response after
592     * <code>timeout</code>, then <code>exceptionCallback</code> will be invoked with a
593     * {@link SmackException.NoResponseException}.
594     * 
595     * @param iqRequest the IQ stanza to send (required)
596     * @param callback the callback invoked if there is result response (required)
597     * @param exceptionCallback the callback invoked if there is an Exception optional
598     * @param timeout the timeout in milliseconds to wait for a response
599     * @throws NotConnectedException
600     * @throws InterruptedException 
601     */
602    public void sendIqWithResponseCallback(IQ iqRequest, final StanzaListener callback,
603                    final ExceptionCallback exceptionCallback, long timeout)
604                    throws NotConnectedException, InterruptedException;
605
606    /**
607     * Add a callback that is called exactly once and synchronously with the incoming stanza that matches the given
608     * stanza(/packet) filter.
609     * 
610     * @param callback the callback invoked once the stanza(/packet) filter matches a stanza.
611     * @param packetFilter the filter to match stanzas or null to match all.
612     */
613    public void addOneTimeSyncCallback(StanzaListener callback, StanzaFilter packetFilter);
614
615    /**
616     * Register an IQ request handler with this connection.
617     * <p>
618     * IQ request handler process incoming IQ requests, i.e. incoming IQ stanzas of type 'get' or 'set', and return a result.
619     * </p>
620     * @param iqRequestHandler the IQ request handler to register.
621     * @return the previously registered IQ request handler or null.
622     */
623    public IQRequestHandler registerIQRequestHandler(IQRequestHandler iqRequestHandler);
624
625    /**
626     * Convenience method for {@link #unregisterIQRequestHandler(String, String, org.jivesoftware.smack.packet.IQ.Type)}.
627     *
628     * @param iqRequestHandler
629     * @return the previously registered IQ request handler or null.
630     */
631    public IQRequestHandler unregisterIQRequestHandler(IQRequestHandler iqRequestHandler);
632
633    /**
634     * Unregister an IQ request handler with this connection.
635     * 
636     * @param element the IQ element the IQ request handler is responsible for.
637     * @param namespace the IQ namespace the IQ request handler is responsible for.
638     * @param type the IQ type the IQ request handler is responsible for.
639     * @return the previously registered IQ request handler or null.
640     */
641    public IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type);
642
643    /**
644     * Returns the timestamp in milliseconds when the last stanza was received.
645     * 
646     * @return the timestamp in milliseconds
647     */
648    public long getLastStanzaReceived();
649
650}