mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-29 15:32:06 +01:00
Only add Entity Capabilities extension to available presences
Also don't override eventually send presences on updateLocalEntityCaps(), instead save the last sent Presence stanza and re-send that stanza. SMACK-669.
This commit is contained in:
parent
c120bc1cbc
commit
385798f9ba
3 changed files with 44 additions and 12 deletions
|
@ -19,6 +19,7 @@ package org.jivesoftware.smack.packet;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.packet.id.StanzaIdUtil;
|
||||||
import org.jivesoftware.smack.util.Objects;
|
import org.jivesoftware.smack.util.Objects;
|
||||||
import org.jivesoftware.smack.util.TypedCloneable;
|
import org.jivesoftware.smack.util.TypedCloneable;
|
||||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||||
|
@ -259,6 +260,18 @@ public final class Presence extends Stanza implements TypedCloneable<Presence> {
|
||||||
return new Presence(this);
|
return new Presence(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clone this presence and set a newly generated stanza ID as the clone's ID.
|
||||||
|
*
|
||||||
|
* @return a "clone" of this presence with a different stanza ID.
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public Presence cloneWithNewId() {
|
||||||
|
Presence clone = clone();
|
||||||
|
clone.setStanzaId(StanzaIdUtil.newStanzaId());
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An enum to represent the presence type. Note that presence type is often confused
|
* An enum to represent the presence type. Note that presence type is often confused
|
||||||
* with presence mode. Generally, if a user is signed in to a server, they have a presence
|
* with presence mode. Generally, if a user is signed in to a server, they have a presence
|
||||||
|
|
|
@ -316,6 +316,23 @@ public abstract class Stanza implements TopLevelStreamElement, Packet {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given extension and override eventually existing extensions with the same name and
|
||||||
|
* namespace.
|
||||||
|
*
|
||||||
|
* @param extension the extension element to add.
|
||||||
|
* @return one of the removed extensions or <code>null</code> if there are none.
|
||||||
|
* @since 4.1.2
|
||||||
|
*/
|
||||||
|
public ExtensionElement overrideExtension(ExtensionElement extension) {
|
||||||
|
if (extension == null) return null;
|
||||||
|
synchronized (packetExtensions) {
|
||||||
|
ExtensionElement removedExtension = removeExtension(extension);
|
||||||
|
addExtension(extension);
|
||||||
|
return removedExtension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a collection of stanza(/packet) extensions to the packet. Does nothing if extensions is null.
|
* Adds a collection of stanza(/packet) extensions to the packet. Does nothing if extensions is null.
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.Stanza;
|
||||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||||
import org.jivesoftware.smack.packet.Presence;
|
import org.jivesoftware.smack.packet.Presence;
|
||||||
import org.jivesoftware.smack.filter.NotFilter;
|
import org.jivesoftware.smack.filter.NotFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PresenceTypeFilter;
|
||||||
import org.jivesoftware.smack.filter.StanzaFilter;
|
import org.jivesoftware.smack.filter.StanzaFilter;
|
||||||
import org.jivesoftware.smack.filter.AndFilter;
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
import org.jivesoftware.smack.filter.StanzaTypeFilter;
|
import org.jivesoftware.smack.filter.StanzaTypeFilter;
|
||||||
|
@ -94,7 +95,6 @@ public class EntityCapsManager extends Manager {
|
||||||
ELEMENT, NAMESPACE));
|
ELEMENT, NAMESPACE));
|
||||||
private static final StanzaFilter PRESENCES_WITHOUT_CAPS = new AndFilter(new StanzaTypeFilter(Presence.class), new NotFilter(new StanzaExtensionFilter(
|
private static final StanzaFilter PRESENCES_WITHOUT_CAPS = new AndFilter(new StanzaTypeFilter(Presence.class), new NotFilter(new StanzaExtensionFilter(
|
||||||
ELEMENT, NAMESPACE)));
|
ELEMENT, NAMESPACE)));
|
||||||
private static final StanzaFilter PRESENCES = StanzaTypeFilter.PRESENCE;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of "node + '#' + hash" to DiscoverInfo data
|
* Map of "node + '#' + hash" to DiscoverInfo data
|
||||||
|
@ -262,7 +262,7 @@ public class EntityCapsManager extends Manager {
|
||||||
|
|
||||||
private boolean entityCapsEnabled;
|
private boolean entityCapsEnabled;
|
||||||
private CapsVersionAndHash currentCapsVersion;
|
private CapsVersionAndHash currentCapsVersion;
|
||||||
private boolean presenceSend = false;
|
private volatile Presence presenceSend;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The entity node String used by this EntityCapsManager instance.
|
* The entity node String used by this EntityCapsManager instance.
|
||||||
|
@ -291,7 +291,7 @@ public class EntityCapsManager extends Manager {
|
||||||
|
|
||||||
// Reset presenceSend when the connection was not resumed
|
// Reset presenceSend when the connection was not resumed
|
||||||
if (!resumed) {
|
if (!resumed) {
|
||||||
presenceSend = false;
|
presenceSend = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) {
|
private void processCapsStreamFeatureIfAvailable(XMPPConnection connection) {
|
||||||
|
@ -339,23 +339,26 @@ public class EntityCapsManager extends Manager {
|
||||||
connection.addPacketSendingListener(new StanzaListener() {
|
connection.addPacketSendingListener(new StanzaListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Stanza packet) {
|
public void processPacket(Stanza packet) {
|
||||||
presenceSend = true;
|
presenceSend = (Presence) packet;
|
||||||
}
|
}
|
||||||
}, PRESENCES);
|
}, PresenceTypeFilter.AVAILABLE);
|
||||||
|
|
||||||
// Intercept presence packages and add caps data when intended.
|
// Intercept presence packages and add caps data when intended.
|
||||||
// XEP-0115 specifies that a client SHOULD include entity capabilities
|
// XEP-0115 specifies that a client SHOULD include entity capabilities
|
||||||
// with every presence notification it sends.
|
// with every presence notification it sends.
|
||||||
StanzaListener packetInterceptor = new StanzaListener() {
|
StanzaListener packetInterceptor = new StanzaListener() {
|
||||||
public void processPacket(Stanza packet) {
|
public void processPacket(Stanza packet) {
|
||||||
if (!entityCapsEnabled)
|
if (!entityCapsEnabled) {
|
||||||
|
// Be sure to not send stanzas with the caps extension if it's not enabled
|
||||||
|
packet.removeExtension(CapsExtension.ELEMENT, CapsExtension.NAMESPACE);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash();
|
CapsVersionAndHash capsVersionAndHash = getCapsVersionAndHash();
|
||||||
CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash);
|
CapsExtension caps = new CapsExtension(entityNode, capsVersionAndHash.version, capsVersionAndHash.hash);
|
||||||
packet.addExtension(caps);
|
packet.overrideExtension(caps);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
connection.addPacketInterceptor(packetInterceptor, PRESENCES);
|
connection.addPacketInterceptor(packetInterceptor, PresenceTypeFilter.AVAILABLE);
|
||||||
// It's important to do this as last action. Since it changes the
|
// It's important to do this as last action. Since it changes the
|
||||||
// behavior of the SDM in some ways
|
// behavior of the SDM in some ways
|
||||||
sdm.setEntityCapsManager(this);
|
sdm.setEntityCapsManager(this);
|
||||||
|
@ -502,15 +505,14 @@ public class EntityCapsManager extends Manager {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send an empty presence, and let the packet interceptor
|
// Re-send the last sent presence, and let the stanza interceptor
|
||||||
// add a <c/> node to it.
|
// add a <c/> node to it.
|
||||||
// See http://xmpp.org/extensions/xep-0115.html#advertise
|
// See http://xmpp.org/extensions/xep-0115.html#advertise
|
||||||
// We only send a presence packet if there was already one send
|
// We only send a presence packet if there was already one send
|
||||||
// to respect ConnectionConfiguration.isSendPresence()
|
// to respect ConnectionConfiguration.isSendPresence()
|
||||||
if (connection != null && connection.isAuthenticated() && presenceSend) {
|
if (connection != null && connection.isAuthenticated() && presenceSend != null) {
|
||||||
Presence presence = new Presence(Presence.Type.available);
|
|
||||||
try {
|
try {
|
||||||
connection.sendStanza(presence);
|
connection.sendStanza(presenceSend.cloneWithNewId());
|
||||||
}
|
}
|
||||||
catch (NotConnectedException e) {
|
catch (NotConnectedException e) {
|
||||||
LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
|
LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
|
||||||
|
|
Loading…
Reference in a new issue