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.XMPPException.XMPPErrorException;
022import org.jivesoftware.smack.filter.IQReplyFilter;
023import org.jivesoftware.smack.filter.StanzaFilter;
024import org.jivesoftware.smack.iqrequest.IQRequestHandler;
025import org.jivesoftware.smack.packet.ExtensionElement;
026import org.jivesoftware.smack.packet.IQ;
027import org.jivesoftware.smack.packet.Nonza;
028import org.jivesoftware.smack.packet.Stanza;
029
030import org.jxmpp.jid.DomainBareJid;
031import org.jxmpp.jid.EntityFullJid;
032
033/**
034 * The XMPPConnection interface provides an interface for connections to an XMPP server and
035 * implements shared methods which are used by the different types of connections (e.g.
036 * <code>XMPPTCPConnection</code> or <code>XMPPBOSHConnection</code>). To create a connection to an XMPP server
037 * a simple usage of this API might look like the following:
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 * ChatManager chatManager = ChatManager.getInstanceFor(con);
048 * chatManager.addIncomingListener(new IncomingChatMessageListener() {
049 *     public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
050 *         // Print out any messages we get back to standard out.
051 *         System.out.println("Received message: " + message);
052 *     }
053 * });
054 * Chat chat = chatManager.chatWith("jdoe@igniterealtime.org");
055 * chat.send("Howdy!");
056 * // Disconnect from the server
057 * con.disconnect();
058 * </pre>
059 * <p>
060 * Note that the XMPPConnection interface does intentionally not declare any methods that manipulate
061 * the connection state, e.g. <code>connect()</code>, <code>disconnect()</code>. You should use the
062 * most specific connection type, e.g. <code>XMPPTCPConnection</code> as declared type and use the
063 * XMPPConnection interface when you don't need to manipulate the connection state.
064 * </p>
065 * <p>
066 * XMPPConnections can be reused between connections. This means that an Connection may be connected,
067 * disconnected and then connected again. Listeners of the XMPPConnection will be retained across
068 * connections.
069 * </p>
070 *
071 * @author Matt Tucker
072 * @author Guenther Niess
073 */
074public interface XMPPConnection {
075
076    /**
077     * Returns the XMPP Domain of the service provided by the XMPP server and used for this connection. After
078     * authenticating with the server the returned value may be different.
079     *
080     * @return the XMPP domain of this XMPP session.
081     */
082    DomainBareJid getXMPPServiceDomain();
083
084    /**
085     * Returns the host name of the server where the XMPP server is running. This would be the
086     * IP address of the server or a name that may be resolved by a DNS server.
087     *
088     * @return the host name of the server where the XMPP server is running or null if not yet connected.
089     */
090    String getHost();
091
092    /**
093     * Returns the port number of the XMPP server for this connection. The default port
094     * for normal connections is 5222.
095     *
096     * @return the port number of the XMPP server or 0 if not yet connected.
097     */
098    int getPort();
099
100    /**
101     * Returns the full XMPP address of the user that is logged in to the connection or
102     * <tt>null</tt> if not logged in yet. An XMPP address is in the form
103     * username@server/resource.
104     *
105     * @return the full XMPP address of the user logged in.
106     */
107    EntityFullJid getUser();
108
109    /**
110     * Returns the stream ID for this connection, which is the value set by the server
111     * when opening an XMPP stream. This value will be <tt>null</tt> if not connected to the server.
112     *
113     * @return the ID of this connection returned from the XMPP server or <tt>null</tt> if
114     *      not connected to the server.
115     * @see <a href="http://xmpp.org/rfcs/rfc6120.html#streams-attr-id">RFC 6120 ยง 4.7.3. id</a>
116     */
117    String getStreamId();
118
119    /**
120     * Returns true if currently connected to the XMPP server.
121     *
122     * @return true if connected.
123     */
124    boolean isConnected();
125
126    /**
127     * Returns true if currently authenticated by successfully calling the login method.
128     *
129     * @return true if authenticated.
130     */
131    boolean isAuthenticated();
132
133    /**
134     * Returns true if currently authenticated anonymously.
135     *
136     * @return true if authenticated anonymously.
137     */
138    boolean isAnonymous();
139
140    /**
141     * Returns true if the connection to the server has successfully negotiated encryption.
142     *
143     * @return true if a secure connection to the server.
144     */
145    boolean isSecureConnection();
146
147    /**
148     * Returns true if network traffic is being compressed. When using stream compression network
149     * traffic can be reduced up to 90%. Therefore, stream compression is ideal when using a slow
150     * speed network connection. However, the server will need to use more CPU time in order to
151     * un/compress network data so under high load the server performance might be affected.
152     *
153     * @return true if network traffic is being compressed.
154     */
155    boolean isUsingCompression();
156
157    /**
158     * Sends the specified stanza to the server.
159     *
160     * @param stanza the stanza to send.
161     * @throws NotConnectedException if the connection is not connected.
162     * @throws InterruptedException
163     * */
164    void sendStanza(Stanza stanza) throws NotConnectedException, InterruptedException;
165
166    /**
167     * Send a Nonza.
168     * <p>
169     * <b>This method is not meant for end-user usage!</b> It allows sending plain stream elements, which should not be
170     * done by a user manually. <b>Doing so may result in a unstable or unusable connection.</b> Certain Smack APIs use
171     * this method to send plain stream elements.
172     * </p>
173     *
174     * @param nonza the Nonza to send.
175     * @throws NotConnectedException
176     * @throws InterruptedException
177     */
178    void sendNonza(Nonza nonza) throws NotConnectedException, InterruptedException;
179
180    /**
181     * Adds a connection listener to this connection that will be notified when
182     * the connection closes or fails.
183     *
184     * @param connectionListener a connection listener.
185     */
186    void addConnectionListener(ConnectionListener connectionListener);
187
188    /**
189     * Removes a connection listener from this connection.
190     *
191     * @param connectionListener a connection listener.
192     */
193    void removeConnectionListener(ConnectionListener connectionListener);
194
195    /**
196     * Send an IQ request and wait for the response.
197     *
198     * @param request the IQ request
199     * @return an IQ with type 'result'
200     * @throws NoResponseException
201     * @throws XMPPErrorException
202     * @throws NotConnectedException
203     * @throws InterruptedException
204     * @since 4.3
205     */
206    <I extends IQ> I sendIqRequestAndWaitForResponse(IQ request)
207            throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException;
208
209    /**
210     * Creates a new stanza collector collecting IQ responses that are replies to the IQ <code>request</code>.
211     * Does also send the <code>request</code> IQ. The stanza filter for the collector is an
212     * {@link IQReplyFilter}, guaranteeing that stanza id and JID in the 'from' address have
213     * expected values.
214     *
215     * @param request the IQ request to filter responses from
216     * @return a new stanza collector.
217     * @throws NotConnectedException
218     * @throws InterruptedException
219     */
220    StanzaCollector createStanzaCollectorAndSend(IQ request) throws NotConnectedException, InterruptedException;
221
222    /**
223     * Creates a new stanza collector for this connection. A stanza filter determines
224     * which stanzas will be accumulated by the collector. A StanzaCollector is
225     * more suitable to use than a {@link StanzaListener} when you need to wait for
226     * a specific result.
227     *
228     * @param stanzaFilter the stanza filter to use.
229     * @param stanza the stanza to send right after the collector got created
230     * @return a new stanza collector.
231     * @throws InterruptedException
232     * @throws NotConnectedException
233     */
234    StanzaCollector createStanzaCollectorAndSend(StanzaFilter stanzaFilter, Stanza stanza)
235                    throws NotConnectedException, InterruptedException;
236
237    /**
238     * Creates a new stanza collector for this connection. A stanza filter
239     * determines which stanzas will be accumulated by the collector. A
240     * StanzaCollector is more suitable to use than a {@link StanzaListener}
241     * when you need to wait for a specific result.
242     * <p>
243     * <b>Note:</b> If you send a Stanza right after using this method, then
244     * consider using
245     * {@link #createStanzaCollectorAndSend(StanzaFilter, Stanza)} instead.
246     * Otherwise make sure cancel the StanzaCollector in every case, e.g. even
247     * if an exception is thrown, or otherwise you may leak the StanzaCollector.
248     * </p>
249     *
250     * @param stanzaFilter the stanza filter to use.
251     * @return a new stanza collector.
252     */
253    StanzaCollector createStanzaCollector(StanzaFilter stanzaFilter);
254
255    /**
256     * Create a new stanza collector with the given stanza collector configuration.
257     * <p>
258     * Please make sure to cancel the collector when it is no longer required. See also
259     * {@link #createStanzaCollector(StanzaFilter)}.
260     * </p>
261     *
262     * @param configuration the stanza collector configuration.
263     * @return a new stanza collector.
264     * @since 4.1
265     */
266    StanzaCollector createStanzaCollector(StanzaCollector.Configuration configuration);
267
268    /**
269     * Remove a stanza collector of this connection.
270     *
271     * @param collector a stanza collectors which was created for this connection.
272     */
273    void removeStanzaCollector(StanzaCollector collector);
274
275    /**
276     * Registers a <b>synchronous</b> stanza listener with this connection. A stanza listener will be invoked only when
277     * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If
278     * the same stanza listener is added again with a different filter, only the new filter will be used.
279     * <p>
280     * <b>Important:</b> This stanza listeners will be called in the same <i>single</i> thread that processes all
281     * incoming stanzas. Only use this kind of stanza filter if it does not perform any XMPP activity that waits for a
282     * response. Consider using {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} when possible, i.e. when
283     * the invocation order doesn't have to be the same as the order of the arriving stanzas. If the order of the
284     * arriving stanzas, consider using a {@link StanzaCollector} when possible.
285     * </p>
286     *
287     * @param stanzaListener the stanza listener to notify of new received stanzas.
288     * @param stanzaFilter the stanza filter to use.
289     * @see #addStanzaInterceptor(StanzaListener, StanzaFilter)
290     * @since 4.1
291     */
292    void addSyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter);
293
294    /**
295     * Removes a stanza listener for received stanzas from this connection.
296     *
297     * @param stanzaListener the stanza listener to remove.
298     * @return true if the stanza listener was removed
299     * @since 4.1
300     */
301    boolean removeSyncStanzaListener(StanzaListener stanzaListener);
302
303    /**
304     * Registers an <b>asynchronous</b> stanza listener with this connection. A stanza listener will be invoked only
305     * when an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener.
306     * If the same stanza listener is added again with a different filter, only the new filter will be used.
307     * <p>
308     * Unlike {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)} stanza listeners added with this method will be
309     * invoked asynchronously in their own thread. Use this method if the order of the stanza listeners must not depend
310     * on the order how the stanzas where received.
311     * </p>
312     *
313     * @param stanzaListener the stanza listener to notify of new received stanzas.
314     * @param stanzaFilter the stanza filter to use.
315     * @see #addStanzaInterceptor(StanzaListener, StanzaFilter)
316     * @since 4.1
317    */
318    void addAsyncStanzaListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter);
319
320    /**
321     * Removes an <b>asynchronous</b> stanza listener for received stanzas from this connection.
322     *
323     * @param stanzaListener the stanza listener to remove.
324     * @return true if the stanza listener was removed
325     * @since 4.1
326     */
327    boolean removeAsyncStanzaListener(StanzaListener stanzaListener);
328
329    /**
330     * Registers a stanza listener with this connection. The listener will be
331     * notified of every stanza that this connection sends. A stanza filter determines
332     * which stanzas will be delivered to the listener. Note that the thread
333     * that writes stanzas will be used to invoke the listeners. Therefore, each
334     * stanza listener should complete all operations quickly or use a different
335     * thread for processing.
336     *
337     * @param stanzaListener the stanza listener to notify of sent stanzas.
338     * @param stanzaFilter   the stanza filter to use.
339     * @deprecated use {@link #addStanzaSendingListener} instead
340     */
341    // TODO Remove in Smack 4.4
342    @Deprecated
343    void addPacketSendingListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter);
344
345    /**
346     * Registers a stanza listener with this connection. The listener will be
347     * notified of every stanza that this connection sends. A stanza filter determines
348     * which stanzas will be delivered to the listener. Note that the thread
349     * that writes stanzas will be used to invoke the listeners. Therefore, each
350     * stanza listener should complete all operations quickly or use a different
351     * thread for processing.
352     *
353     * @param stanzaListener the stanza listener to notify of sent stanzas.
354     * @param stanzaFilter   the stanza filter to use.
355     */
356    void addStanzaSendingListener(StanzaListener stanzaListener, StanzaFilter stanzaFilter);
357
358    /**
359     * Removes a stanza listener for sending stanzas from this connection.
360     *
361     * @param stanzaListener the stanza listener to remove.
362     * @deprecated use {@link #removeStanzaSendingListener} instead
363     */
364    // TODO Remove in Smack 4.4
365    @Deprecated
366    void removePacketSendingListener(StanzaListener stanzaListener);
367
368    /**
369     * Removes a stanza listener for sending stanzas from this connection.
370     *
371     * @param stanzaListener the stanza listener to remove.
372     */
373    void removeStanzaSendingListener(StanzaListener stanzaListener);
374
375    /**
376     * Registers a stanza interceptor with this connection. The interceptor will be
377     * invoked every time a stanza is about to be sent by this connection. Interceptors
378     * may modify the stanza to be sent. A stanza filter determines which stanzas
379     * will be delivered to the interceptor.
380     *
381     * <p>
382     * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}.
383     * </p>
384     *
385     * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent.
386     * @param stanzaFilter      the stanza filter to use.
387     * @deprecated use {@link #addStanzaInterceptor} instead
388     */
389    // TODO Remove in Smack 4.4
390    @Deprecated
391    void addPacketInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter);
392
393    /**
394     * Registers a stanza interceptor with this connection. The interceptor will be
395     * invoked every time a stanza is about to be sent by this connection. Interceptors
396     * may modify the stanza to be sent. A stanza filter determines which stanzas
397     * will be delivered to the interceptor.
398     *
399     * <p>
400     * NOTE: For a similar functionality on incoming stanzas, see {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}.
401     * </p>
402     *
403     * @param stanzaInterceptor the stanza interceptor to notify of stanzas about to be sent.
404     * @param stanzaFilter      the stanza filter to use.
405     */
406    void addStanzaInterceptor(StanzaListener stanzaInterceptor, StanzaFilter stanzaFilter);
407
408    /**
409     * Removes a stanza interceptor.
410     *
411     * @param stanzaInterceptor the stanza interceptor to remove.
412     * @deprecated user {@link #removeStanzaInterceptor} instead
413     */
414    // TODO Remove in Smack 4.4
415    @Deprecated
416    void removePacketInterceptor(StanzaListener stanzaInterceptor);
417
418    /**
419     * Removes a stanza interceptor.
420     *
421     * @param stanzaInterceptor the stanza interceptor to remove.
422     */
423    void removeStanzaInterceptor(StanzaListener stanzaInterceptor);
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    long getReplyTimeout();
432
433    /**
434     * Set the stanza 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    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    int getConnectionCounter();
449
450    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    void setFromMode(FromMode fromMode);
474
475    /**
476     * Get the currently active FromMode.
477     *
478     * @return the currently active {@link FromMode}
479     */
480    FromMode getFromMode();
481
482    /**
483     * Get the feature stanza 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 extensions of the feature or <code>null</code>
490     */
491    <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    boolean hasFeature(String element, String namespace);
501
502    /**
503     * Send an IQ request asynchronously. The connection's default reply timeout will be used.
504     *
505     * @param request the IQ request to send.
506     * @return a SmackFuture for the response.
507     */
508    SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request);
509
510    /**
511     * Send an IQ request asynchronously.
512     *
513     * @param request the IQ request to send.
514     * @param timeout the reply timeout in milliseconds.
515     * @return a SmackFuture for the response.
516     */
517    SmackFuture<IQ, Exception> sendIqRequestAsync(IQ request, long timeout);
518
519    /**
520     * Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter. The
521     * connection's default reply timeout will be used.
522     *
523     * @param stanza the stanza to send.
524     * @param replyFilter the filter used for the response stanza.
525     * @return a SmackFuture for the response.
526     */
527    <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter);
528
529    /**
530     * Send a stanza asynchronously, waiting for exactly one response stanza using the given reply filter.
531     *
532     * @param stanza the stanza to send.
533     * @param replyFilter the filter used for the response stanza.
534     * @param timeout the reply timeout in milliseconds.
535     * @return a SmackFuture for the response.
536     */
537    <S extends Stanza> SmackFuture<S, Exception> sendAsync(S stanza, StanzaFilter replyFilter, long timeout);
538
539    /**
540     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
541     * <p>
542     * If there is a response, then <code>callback</code> will be invoked. The callback will be
543     * invoked at most once and it will be not invoked after the connections default reply timeout
544     * has been elapsed.
545     * </p>
546     *
547     * @param stanza the stanza to send (required)
548     * @param replyFilter the filter used to determine response stanza (required)
549     * @param callback the callback invoked if there is a response (required)
550     * @throws NotConnectedException
551     * @throws InterruptedException
552     * @deprecated use {@link #sendAsync(Stanza, StanzaFilter)} instead.
553     */
554    @Deprecated
555    // TODO: Remove in Smack 4.4.
556    void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
557                    StanzaListener callback) throws NotConnectedException, InterruptedException;
558
559    /**
560     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
561     * <p>
562     * If there is a response, then <code>callback</code> will be invoked. If there is no response
563     * after the connections default reply timeout, then <code>exceptionCallback</code> will be invoked
564     * with a {@link SmackException.NoResponseException}. The callback will be invoked at most once.
565     * </p>
566     *
567     * @param stanza the stanza to send (required)
568     * @param replyFilter the filter used to determine response stanza (required)
569     * @param callback the callback invoked if there is a response (required)
570     * @param exceptionCallback the callback invoked if there is an exception (optional)
571     * @throws NotConnectedException
572     * @throws InterruptedException
573     * @deprecated use {@link #sendAsync(Stanza, StanzaFilter)} instead.
574     */
575    @Deprecated
576    // TODO: Remove in Smack 4.4.
577    void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter, StanzaListener callback,
578                    @SuppressWarnings("deprecation") ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
579
580    /**
581     * Send a stanza and wait asynchronously for a response by using <code>replyFilter</code>.
582     * <p>
583     * If there is a response, then <code>callback</code> will be invoked. If there is no response
584     * after <code>timeout</code> milliseconds, then <code>exceptionCallback</code> will be invoked
585     * with a {@link SmackException.NoResponseException}. The callback will be invoked at most once.
586     * </p>
587     *
588     * @param stanza the stanza to send (required)
589     * @param replyFilter the filter used to determine response stanza (required)
590     * @param callback the callback invoked if there is a response (required)
591     * @param exceptionCallback the callback invoked if there is an exception (optional)
592     * @param timeout the timeout in milliseconds to wait for a response
593     * @throws NotConnectedException
594     * @throws InterruptedException
595     * @deprecated use {@link #sendAsync(Stanza, StanzaFilter, long)} instead.
596     */
597    @Deprecated
598    // TODO: Remove in Smack 4.4.
599    void sendStanzaWithResponseCallback(Stanza stanza, StanzaFilter replyFilter,
600                    StanzaListener callback, @SuppressWarnings("deprecation") ExceptionCallback exceptionCallback,
601                    long timeout) throws NotConnectedException, InterruptedException;
602
603    /**
604     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
605     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. The callback will
606     * not be invoked after the connections default reply timeout has been elapsed.
607     *
608     * @param iqRequest the IQ stanza to send (required)
609     * @param callback the callback invoked if there is result response (required)
610     * @throws NotConnectedException
611     * @throws InterruptedException
612     * @deprecated use {@link #sendIqRequestAsync(IQ)} instead.
613     */
614    @Deprecated
615    // TODO: Remove in Smack 4.4.
616    void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback) throws NotConnectedException, InterruptedException;
617
618    /**
619     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
620     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. If there is an
621     * error response <code>exceptionCallback</code> will be invoked, if not null, with the received
622     * error as {@link XMPPException.XMPPErrorException}. If there is no response after the
623     * connections default reply timeout, then <code>exceptionCallback</code> will be invoked with a
624     * {@link SmackException.NoResponseException}.
625     *
626     * @param iqRequest the IQ stanza to send (required)
627     * @param callback the callback invoked if there is result response (required)
628     * @param exceptionCallback the callback invoked if there is an Exception optional
629     * @throws NotConnectedException
630     * @throws InterruptedException
631     * @deprecated use {@link #sendIqRequestAsync(IQ)} instead.
632     */
633    @Deprecated
634    // TODO: Remove in Smack 4.4.
635    void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
636                    @SuppressWarnings("deprecation") ExceptionCallback exceptionCallback) throws NotConnectedException, InterruptedException;
637
638    /**
639     * Send a IQ stanza and invoke <code>callback</code> if there is a result of
640     * {@link org.jivesoftware.smack.packet.IQ.Type#result} with that result IQ. If there is an
641     * error response <code>exceptionCallback</code> will be invoked, if not null, with the received
642     * error as {@link XMPPException.XMPPErrorException}. If there is no response after
643     * <code>timeout</code>, then <code>exceptionCallback</code> will be invoked with a
644     * {@link SmackException.NoResponseException}.
645     *
646     * @param iqRequest the IQ stanza to send (required)
647     * @param callback the callback invoked if there is result response (required)
648     * @param exceptionCallback the callback invoked if there is an Exception optional
649     * @param timeout the timeout in milliseconds to wait for a response
650     * @throws NotConnectedException
651     * @throws InterruptedException
652     * @deprecated use {@link #sendIqRequestAsync(IQ, long)} instead.
653     */
654    @Deprecated
655    // TODO: Remove in Smack 4.4.
656    void sendIqWithResponseCallback(IQ iqRequest, StanzaListener callback,
657                    @SuppressWarnings("deprecation") ExceptionCallback exceptionCallback, long timeout)
658                    throws NotConnectedException, InterruptedException;
659
660    /**
661     * Add a callback that is called exactly once and synchronously with the incoming stanza that matches the given
662     * stanza filter.
663     *
664     * @param callback the callback invoked once the stanza filter matches a stanza.
665     * @param stanzaFilter the filter to match stanzas or null to match all.
666     */
667    void addOneTimeSyncCallback(StanzaListener callback, StanzaFilter stanzaFilter);
668
669    /**
670     * Register an IQ request handler with this connection.
671     * <p>
672     * IQ request handler process incoming IQ requests, i.e. incoming IQ stanzas of type 'get' or 'set', and return a result.
673     * </p>
674     * @param iqRequestHandler the IQ request handler to register.
675     * @return the previously registered IQ request handler or null.
676     */
677    IQRequestHandler registerIQRequestHandler(IQRequestHandler iqRequestHandler);
678
679    /**
680     * Convenience method for {@link #unregisterIQRequestHandler(String, String, org.jivesoftware.smack.packet.IQ.Type)}.
681     *
682     * @param iqRequestHandler
683     * @return the previously registered IQ request handler or null.
684     */
685    IQRequestHandler unregisterIQRequestHandler(IQRequestHandler iqRequestHandler);
686
687    /**
688     * Unregister an IQ request handler with this connection.
689     *
690     * @param element the IQ element the IQ request handler is responsible for.
691     * @param namespace the IQ namespace the IQ request handler is responsible for.
692     * @param type the IQ type the IQ request handler is responsible for.
693     * @return the previously registered IQ request handler or null.
694     */
695    IQRequestHandler unregisterIQRequestHandler(String element, String namespace, IQ.Type type);
696
697    /**
698     * Returns the timestamp in milliseconds when the last stanza was received.
699     *
700     * @return the timestamp in milliseconds
701     */
702    long getLastStanzaReceived();
703
704}