1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-12-25 12:08:00 +01:00

Merge pull request #572 from Flowdalic/sync-entity-caps

[caps] Use a synchronous listener for incoming presence stanzas
This commit is contained in:
Florian Schmaus 2023-11-25 13:26:12 +01:00 committed by GitHub
commit 2e8f83c579
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 20 additions and 13 deletions

View file

@ -83,23 +83,24 @@ import org.jxmpp.jid.EntityFullJid;
* <h2>Incoming Stanza Listeners</h2> * <h2>Incoming Stanza Listeners</h2>
* Most callbacks (listeners, handlers, ) than you can add to a connection come in three different variants: * Most callbacks (listeners, handlers, ) than you can add to a connection come in three different variants:
* <ul> * <ul>
* <li>standard</li> * <li>asynchronous - e.g., {@link #addAsyncStanzaListener(StanzaListener, StanzaFilter)}</li>
* <li>async (asynchronous)</li> * <li>synchronous - e.g., {@link #addSyncStanzaListener(StanzaListener, StanzaFilter)}</li>
* <li>sync (synchronous)</li> * <li>other - e.g., {@link #addStanzaListener(StanzaListener, StanzaFilter)}</li>
* </ul> * </ul>
* <p> * <p>
* Standard callbacks are invoked concurrently, but it is ensured that the same callback is never run concurrently.
* The callback's identity is used as key for that. The events delivered to the callback preserve the order of the
* causing events of the connection.
* </p>
* <p>
* Asynchronous callbacks are run decoupled from the connections main event loop. Hence a callback triggered by * Asynchronous callbacks are run decoupled from the connections main event loop. Hence a callback triggered by
* stanza B may (appear to) invoked before a callback triggered by stanza A, even though stanza A arrived before B. * stanza B may (appear to) invoked before a callback triggered by stanza A, even though stanza A arrived before B.
* </p> * </p>
* <p> * <p>
* Synchronous callbacks are run synchronous to the main event loop of a connection. Hence they are invoked in the * Synchronous callbacks are invoked concurrently, but it is ensured that the same callback is never run concurrently
* exact order of how events happen there, most importantly the arrival order of incoming stanzas. You should only * and that they are executed in order. That is, if both stanza A and B trigger the same callback, and A arrives before
* use synchronous callbacks in rare situations. * B, then the callback will be invoked with A first, and then B. Furthermore, those callbacks are not executed within
* the main loop. However it is still advisable that those callbacks do not block or only block briefly.
* </p>
* <p>
* Other callbacks are run synchronous to the main event loop of a connection and are executed within the main loop.
* <b>This means that if such a callback blocks, the main event loop also blocks, which can easily cause deadlocks.
* Therefore, you should avoid using those callbacks unless you know what you are doing.</b>
* </p> * </p>
* *
* @author Matt Tucker * @author Matt Tucker
@ -370,7 +371,7 @@ public interface XMPPConnection {
boolean removeStanzaListener(StanzaListener stanzaListener); boolean removeStanzaListener(StanzaListener stanzaListener);
/** /**
* Registers a <b>synchronous</b> stanza listener with this connection. A stanza listener will be invoked only when * Registers a <b>synchronous</b> stanza listener with this connection. A stanza listener will be invoked only when
* an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If * an incoming stanza is received. A stanza filter determines which stanzas will be delivered to the listener. If
* the same stanza listener is added again with a different filter, only the new filter will be used. * the same stanza listener is added again with a different filter, only the new filter will be used.
* <p> * <p>

View file

@ -174,7 +174,10 @@ public final class ChatMarkersManager extends Manager {
* @throws XMPPErrorException in case an error response was received. * @throws XMPPErrorException in case an error response was received.
* @throws NoResponseException if no response was received. * @throws NoResponseException if no response was received.
* @throws InterruptedException if the connection is interrupted. * @throws InterruptedException if the connection is interrupted.
* @deprecated This method serves no purpose, as servers do not announce this feature.
*/ */
// TODO: Remove in Smack 4.6.
@Deprecated
public boolean isSupportedByServer() public boolean isSupportedByServer()
throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException { throws NoResponseException, XMPPErrorException, NotConnectedException, InterruptedException {
return ServiceDiscoveryManager.getInstanceFor(connection()) return ServiceDiscoveryManager.getInstanceFor(connection())

View file

@ -354,7 +354,10 @@ public final class EntityCapsManager extends Manager {
if (autoEnableEntityCaps) if (autoEnableEntityCaps)
enableEntityCaps(); enableEntityCaps();
connection.addAsyncStanzaListener(new StanzaListener() { // Note that this is a *synchronous* stanza listener to avoid unnecessary feature lookups. If this were to be an
// asynchronous listener, then it would be possible that the entity caps information was not processed when the
// features of entity are looked up. See SMACK-937.
connection.addStanzaListener(new StanzaListener() {
// Listen for remote presence stanzas with the caps extension // Listen for remote presence stanzas with the caps extension
// If we receive such a stanza, record the JID and nodeVer // If we receive such a stanza, record the JID and nodeVer
@Override @Override