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