mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-22 22:32:06 +01:00
Make EntityCapsManager's node version configurable
Also some cleanup of caps code.
This commit is contained in:
parent
4fb5b85806
commit
bd6828db38
2 changed files with 51 additions and 60 deletions
|
@ -16,9 +16,9 @@
|
||||||
*/
|
*/
|
||||||
package org.jivesoftware.smackx.caps;
|
package org.jivesoftware.smackx.caps;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.AbstractConnectionListener;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
import org.jivesoftware.smack.ConnectionCreationListener;
|
||||||
import org.jivesoftware.smack.ConnectionListener;
|
|
||||||
import org.jivesoftware.smack.Manager;
|
import org.jivesoftware.smack.Manager;
|
||||||
import org.jivesoftware.smack.PacketInterceptor;
|
import org.jivesoftware.smack.PacketInterceptor;
|
||||||
import org.jivesoftware.smack.PacketListener;
|
import org.jivesoftware.smack.PacketListener;
|
||||||
|
@ -66,14 +66,15 @@ import java.security.NoSuchAlgorithmException;
|
||||||
* Keeps track of entity capabilities.
|
* Keeps track of entity capabilities.
|
||||||
*
|
*
|
||||||
* @author Florian Schmaus
|
* @author Florian Schmaus
|
||||||
|
* @see <a href="http://www.xmpp.org/extensions/xep-0115.html">XEP-0115: Entity Capabilities</a>
|
||||||
*/
|
*/
|
||||||
public class EntityCapsManager extends Manager {
|
public class EntityCapsManager extends Manager {
|
||||||
|
|
||||||
public static final String NAMESPACE = "http://jabber.org/protocol/caps";
|
public static final String NAMESPACE = "http://jabber.org/protocol/caps";
|
||||||
public static final String ELEMENT = "c";
|
public static final String ELEMENT = "c";
|
||||||
|
|
||||||
private static final String ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";
|
|
||||||
private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>();
|
private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>();
|
||||||
|
private static String DEFAULT_ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";
|
||||||
|
|
||||||
protected static EntityCapsPersistentCache persistentCache;
|
protected static EntityCapsPersistentCache persistentCache;
|
||||||
|
|
||||||
|
@ -82,6 +83,12 @@ public class EntityCapsManager extends Manager {
|
||||||
private static Map<XMPPConnection, EntityCapsManager> instances = Collections
|
private static Map<XMPPConnection, EntityCapsManager> instances = Collections
|
||||||
.synchronizedMap(new WeakHashMap<XMPPConnection, EntityCapsManager>());
|
.synchronizedMap(new WeakHashMap<XMPPConnection, EntityCapsManager>());
|
||||||
|
|
||||||
|
private static final PacketFilter PRESENCES_WITH_CAPS = new AndFilter(new PacketTypeFilter(Presence.class), new PacketExtensionFilter(
|
||||||
|
ELEMENT, NAMESPACE));
|
||||||
|
private static final PacketFilter PRESENCES_WITHOUT_CAPS = new AndFilter(new PacketTypeFilter(Presence.class), new NotFilter(new PacketExtensionFilter(
|
||||||
|
ELEMENT, NAMESPACE)));
|
||||||
|
private static final PacketFilter PRESENCES = new PacketTypeFilter(Presence.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map of (node + '#" + hash algorithm) to DiscoverInfo data
|
* Map of (node + '#" + hash algorithm) to DiscoverInfo data
|
||||||
*/
|
*/
|
||||||
|
@ -110,11 +117,14 @@ public class EntityCapsManager extends Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServiceDiscoveryManager sdm;
|
/**
|
||||||
private boolean entityCapsEnabled;
|
* Set the default entity node that will be used for new EntityCapsManagers
|
||||||
private String currentCapsVersion;
|
*
|
||||||
private boolean presenceSend = false;
|
* @param entityNode
|
||||||
private Queue<String> lastLocalCapsVersions = new ConcurrentLinkedQueue<String>();
|
*/
|
||||||
|
public static void setDefaultEntityNode(String entityNode) {
|
||||||
|
DEFAULT_ENTITY_NODE = entityNode;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add DiscoverInfo to the database.
|
* Add DiscoverInfo to the database.
|
||||||
|
@ -219,31 +229,31 @@ public class EntityCapsManager extends Manager {
|
||||||
((Cache) caps).setMaxCacheSize(maxCacheSize);
|
((Cache) caps).setMaxCacheSize(maxCacheSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ServiceDiscoveryManager sdm;
|
||||||
|
private boolean entityCapsEnabled;
|
||||||
|
private String currentCapsVersion;
|
||||||
|
private boolean presenceSend = false;
|
||||||
|
private Queue<String> lastLocalCapsVersions = new ConcurrentLinkedQueue<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity node String used by this EntityCapsManager instance.
|
||||||
|
*/
|
||||||
|
private String entityNode = DEFAULT_ENTITY_NODE;
|
||||||
|
|
||||||
private EntityCapsManager(XMPPConnection connection) {
|
private EntityCapsManager(XMPPConnection connection) {
|
||||||
super(connection);
|
super(connection);
|
||||||
this.sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
this.sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
instances.put(connection, this);
|
instances.put(connection, this);
|
||||||
|
|
||||||
connection.addConnectionListener(new ConnectionListener() {
|
connection.addConnectionListener(new AbstractConnectionListener() {
|
||||||
|
@Override
|
||||||
public void connectionClosed() {
|
public void connectionClosed() {
|
||||||
presenceSend = false;
|
presenceSend = false;
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public void connectionClosedOnError(Exception e) {
|
public void connectionClosedOnError(Exception e) {
|
||||||
presenceSend = false;
|
presenceSend = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reconnectionFailed(Exception e) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reconnectingIn(int seconds) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reconnectionSuccessful() {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// This calculates the local entity caps version
|
// This calculates the local entity caps version
|
||||||
|
@ -252,8 +262,6 @@ public class EntityCapsManager extends Manager {
|
||||||
if (autoEnableEntityCaps)
|
if (autoEnableEntityCaps)
|
||||||
enableEntityCaps();
|
enableEntityCaps();
|
||||||
|
|
||||||
PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), new PacketExtensionFilter(
|
|
||||||
ELEMENT, NAMESPACE));
|
|
||||||
connection.addPacketListener(new PacketListener() {
|
connection.addPacketListener(new PacketListener() {
|
||||||
// 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
|
||||||
|
@ -276,10 +284,8 @@ public class EntityCapsManager extends Manager {
|
||||||
jidCaps.put(from, new NodeVerHash(node, ver, hash));
|
jidCaps.put(from, new NodeVerHash(node, ver, hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
}, packetFilter);
|
}, PRESENCES_WITH_CAPS);
|
||||||
|
|
||||||
packetFilter = new AndFilter(new PacketTypeFilter(Presence.class), new NotFilter(new PacketExtensionFilter(
|
|
||||||
ELEMENT, NAMESPACE)));
|
|
||||||
connection.addPacketListener(new PacketListener() {
|
connection.addPacketListener(new PacketListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Packet packet) {
|
public void processPacket(Packet packet) {
|
||||||
|
@ -288,30 +294,28 @@ public class EntityCapsManager extends Manager {
|
||||||
String from = packet.getFrom();
|
String from = packet.getFrom();
|
||||||
jidCaps.remove(from);
|
jidCaps.remove(from);
|
||||||
}
|
}
|
||||||
}, packetFilter);
|
}, PRESENCES_WITHOUT_CAPS);
|
||||||
|
|
||||||
packetFilter = new PacketTypeFilter(Presence.class);
|
|
||||||
connection.addPacketSendingListener(new PacketListener() {
|
connection.addPacketSendingListener(new PacketListener() {
|
||||||
@Override
|
@Override
|
||||||
public void processPacket(Packet packet) {
|
public void processPacket(Packet packet) {
|
||||||
presenceSend = true;
|
presenceSend = true;
|
||||||
}
|
}
|
||||||
}, packetFilter);
|
}, PRESENCES);
|
||||||
|
|
||||||
// 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.
|
||||||
PacketFilter capsPacketFilter = new PacketTypeFilter(Presence.class);
|
|
||||||
PacketInterceptor packetInterceptor = new PacketInterceptor() {
|
PacketInterceptor packetInterceptor = new PacketInterceptor() {
|
||||||
public void interceptPacket(Packet packet) {
|
public void interceptPacket(Packet packet) {
|
||||||
if (!entityCapsEnabled)
|
if (!entityCapsEnabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CapsExtension caps = new CapsExtension(ENTITY_NODE, getCapsVersion(), "sha-1");
|
CapsExtension caps = new CapsExtension(entityNode, getCapsVersion(), "sha-1");
|
||||||
packet.addExtension(caps);
|
packet.addExtension(caps);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
connection.addPacketInterceptor(packetInterceptor, capsPacketFilter);
|
connection.addPacketInterceptor(packetInterceptor, PRESENCES);
|
||||||
// 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);
|
||||||
|
@ -330,14 +334,14 @@ public class EntityCapsManager extends Manager {
|
||||||
return entityCapsManager;
|
return entityCapsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void enableEntityCaps() {
|
public synchronized void enableEntityCaps() {
|
||||||
// Add Entity Capabilities (XEP-0115) feature node.
|
// Add Entity Capabilities (XEP-0115) feature node.
|
||||||
sdm.addFeature(NAMESPACE);
|
sdm.addFeature(NAMESPACE);
|
||||||
updateLocalEntityCaps();
|
updateLocalEntityCaps();
|
||||||
entityCapsEnabled = true;
|
entityCapsEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void disableEntityCaps() {
|
public synchronized void disableEntityCaps() {
|
||||||
entityCapsEnabled = false;
|
entityCapsEnabled = false;
|
||||||
sdm.removeFeature(NAMESPACE);
|
sdm.removeFeature(NAMESPACE);
|
||||||
}
|
}
|
||||||
|
@ -346,6 +350,11 @@ public class EntityCapsManager extends Manager {
|
||||||
return entityCapsEnabled;
|
return entityCapsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setEntityNode(String entityNode) {
|
||||||
|
this.entityNode = entityNode;
|
||||||
|
updateLocalEntityCaps();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a record telling what entity caps node a user has.
|
* Remove a record telling what entity caps node a user has.
|
||||||
*
|
*
|
||||||
|
@ -374,7 +383,7 @@ public class EntityCapsManager extends Manager {
|
||||||
* @return the local NodeVer
|
* @return the local NodeVer
|
||||||
*/
|
*/
|
||||||
public String getLocalNodeVer() {
|
public String getLocalNodeVer() {
|
||||||
return ENTITY_NODE + '#' + getCapsVersion();
|
return entityNode + '#' + getCapsVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -414,19 +423,19 @@ public class EntityCapsManager extends Manager {
|
||||||
sdm.addDiscoverInfoTo(discoverInfo);
|
sdm.addDiscoverInfoTo(discoverInfo);
|
||||||
|
|
||||||
currentCapsVersion = generateVerificationString(discoverInfo, "sha-1");
|
currentCapsVersion = generateVerificationString(discoverInfo, "sha-1");
|
||||||
addDiscoverInfoByNode(ENTITY_NODE + '#' + currentCapsVersion, discoverInfo);
|
addDiscoverInfoByNode(entityNode + '#' + currentCapsVersion, discoverInfo);
|
||||||
if (lastLocalCapsVersions.size() > 10) {
|
if (lastLocalCapsVersions.size() > 10) {
|
||||||
String oldCapsVersion = lastLocalCapsVersions.poll();
|
String oldCapsVersion = lastLocalCapsVersions.poll();
|
||||||
sdm.removeNodeInformationProvider(ENTITY_NODE + '#' + oldCapsVersion);
|
sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion);
|
||||||
}
|
}
|
||||||
lastLocalCapsVersions.add(currentCapsVersion);
|
lastLocalCapsVersions.add(currentCapsVersion);
|
||||||
|
|
||||||
caps.put(currentCapsVersion, discoverInfo);
|
caps.put(currentCapsVersion, discoverInfo);
|
||||||
if (connection != null)
|
if (connection != null)
|
||||||
jidCaps.put(connection.getUser(), new NodeVerHash(ENTITY_NODE, currentCapsVersion, "sha-1"));
|
jidCaps.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion, "sha-1"));
|
||||||
|
|
||||||
final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities());
|
final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities());
|
||||||
sdm.setNodeInformationProvider(ENTITY_NODE + '#' + currentCapsVersion, new NodeInformationProvider() {
|
sdm.setNodeInformationProvider(entityNode + '#' + currentCapsVersion, new NodeInformationProvider() {
|
||||||
List<String> features = sdm.getFeaturesList();
|
List<String> features = sdm.getFeaturesList();
|
||||||
List<PacketExtension> packetExtensions = sdm.getExtendedInfoAsList();
|
List<PacketExtension> packetExtensions = sdm.getExtendedInfoAsList();
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Copyright © 2009 Jonas Ådahl, 2011-2013 Florian Schmaus
|
* Copyright © 2009 Jonas Ådahl, 2011-2014 Florian Schmaus
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,7 +14,6 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jivesoftware.smackx.caps.packet;
|
package org.jivesoftware.smackx.caps.packet;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
import org.jivesoftware.smack.packet.PacketExtension;
|
||||||
|
@ -22,10 +21,7 @@ import org.jivesoftware.smackx.caps.EntityCapsManager;
|
||||||
|
|
||||||
public class CapsExtension implements PacketExtension {
|
public class CapsExtension implements PacketExtension {
|
||||||
|
|
||||||
private String node, ver, hash;
|
private final String node, ver, hash;
|
||||||
|
|
||||||
public CapsExtension() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public CapsExtension(String node, String version, String hash) {
|
public CapsExtension(String node, String version, String hash) {
|
||||||
this.node = node;
|
this.node = node;
|
||||||
|
@ -45,26 +41,14 @@ public class CapsExtension implements PacketExtension {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNode(String node) {
|
|
||||||
this.node = node;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getVer() {
|
public String getVer() {
|
||||||
return ver;
|
return ver;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setVer(String ver) {
|
|
||||||
this.ver = ver;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getHash() {
|
public String getHash() {
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setHash(String hash) {
|
|
||||||
this.hash = hash;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* <c xmlns='http://jabber.org/protocol/caps'
|
* <c xmlns='http://jabber.org/protocol/caps'
|
||||||
* hash='sha-1'
|
* hash='sha-1'
|
||||||
|
@ -73,11 +57,9 @@ public class CapsExtension implements PacketExtension {
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public String toXML() {
|
public String toXML() {
|
||||||
String xml = "<" + EntityCapsManager.ELEMENT + " xmlns=\"" + EntityCapsManager.NAMESPACE + "\" " +
|
return "<" + EntityCapsManager.ELEMENT + " xmlns=\"" + EntityCapsManager.NAMESPACE + "\" " +
|
||||||
"hash=\"" + hash + "\" " +
|
"hash=\"" + hash + "\" " +
|
||||||
"node=\"" + node + "\" " +
|
"node=\"" + node + "\" " +
|
||||||
"ver=\"" + ver + "\"/>";
|
"ver=\"" + ver + "\"/>";
|
||||||
|
|
||||||
return xml;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue