1
0
Fork 0
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:
Florian Schmaus 2015-05-21 22:04:26 +02:00
parent c120bc1cbc
commit 385798f9ba
3 changed files with 44 additions and 12 deletions

View file

@ -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

View file

@ -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.
* *

View file

@ -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);