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