Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Serverless Messaging (XEP-174) #9

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# IntelliJ
.idea
*.iml

# Mac OS X
.DS_Store

.classpath
.project
.settings
Expand Down
3 changes: 2 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ include 'smack-core',
'smack-legacy',
'smack-jingle',
'smack-bosh',
'smack-java7'
'smack-java7',
'smack-serverless'
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@
*
* @author Henning Staib
*/
public class AbstractConnectionListener implements ConnectionListener {
public class AbstractConnectionListener <T extends XMPPConnection> implements ConnectionListener<T> {
@Override
public void connected(XMPPConnection connection) {
public void connected(T connection) {
// do nothing
}

@Override
public void authenticated(XMPPConnection connection) {
public void authenticated(T connection) {
// do nothing
}

Expand Down
4 changes: 2 additions & 2 deletions smack-core/src/main/java/org/jivesoftware/smack/Chat.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class Chat {

private ChatManager chatManager;
private String threadID;
private String participant;
protected String participant;
private final Set<MessageListener> listeners = new CopyOnWriteArraySet<MessageListener>();

/**
Expand All @@ -49,7 +49,7 @@ public class Chat {
* @param participant the user to chat with.
* @param threadID the thread ID to use.
*/
Chat(ChatManager chatManager, String participant, String threadID) {
protected Chat(ChatManager chatManager, String participant, String threadID) {
this.chatManager = chatManager;
this.participant = participant;
this.threadID = threadID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
*
* @author Alexander Wenckus
*/
public interface ChatManagerListener {
public interface ChatManagerListener<T extends Chat> {

/**
* Event fired when a new chat is created.
*
* @param chat the chat that was created.
* @param createdLocally true if the chat was created by the local user and false if it wasn't.
*/
void chatCreated(Chat chat, boolean createdLocally);
void chatCreated(T chat, boolean createdLocally);
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public class ConnectionConfiguration implements Cloneable {
* of the server. However, there are some servers like google where host would be
* talk.google.com and the serviceName would be gmail.com.
*/
private String serviceName;
protected String serviceName;

protected List<HostAddress> hostAddresses;

Expand Down Expand Up @@ -207,7 +207,7 @@ protected void init(String serviceName, ProxyInfo proxy) {
*
* @param serviceName the XMPP domain of the target server.
*/
void setServiceName(String serviceName) {
protected void setServiceName(String serviceName) {
serviceName = XmppStringUtils.parseDomain(serviceName);
this.serviceName = serviceName;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,19 @@
*
* @author Matt Tucker
*/
public interface ConnectionListener {
public interface ConnectionListener <T extends XMPPConnection> {

/**
* TODO
* @param connection
*/
public void connected(XMPPConnection connection);
public void connected(T connection);

/**
* TODO
* @param connection
*/
public void authenticated(XMPPConnection connection);
public void authenticated(T connection);

/**
* Notification that the connection was closed normally or that the reconnection
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@
/**
*
*/
public interface MessageListener {
void processMessage(Chat chat, Message message);
public interface MessageListener<T extends Chat> {
void processMessage(T chat, Message message);
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ public void cancel() {
}
}

public boolean isCanceled() {
return cancelled;
}

/**
* Returns the packet filter associated with this packet collector. The packet
* filter is used to determine what packets are queued as results.
Expand Down
27 changes: 27 additions & 0 deletions smack-core/src/main/java/org/jivesoftware/smack/util/Tuple.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
*
* Copyright 2003-2014 Jive Software.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smack.util;

public class Tuple<A,B> {
public A a;
public B b;

public Tuple(A a, B b) {
this.a = a;
this.b = b;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.jivesoftware.smackx.xdata.FormField;
import org.jivesoftware.smackx.xdata.packet.DataForm;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
Expand All @@ -56,10 +57,12 @@
import java.util.Locale;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.security.MessageDigest;
Expand All @@ -77,6 +80,7 @@ public class EntityCapsManager extends Manager {
public static final String NAMESPACE = "http://jabber.org/protocol/caps";
public static final String ELEMENT = "c";

public static final String DEFAULT_HASH = "sha-1";
private static final Map<String, MessageDigest> SUPPORTED_HASHES = new HashMap<String, MessageDigest>();
private static String DEFAULT_ENTITY_NODE = "http://www.igniterealtime.org/projects/smack";

Expand Down Expand Up @@ -106,6 +110,13 @@ public class EntityCapsManager extends Manager {
*/
private static final Cache<String, NodeVerHash> JID_TO_NODEVER_CACHE = new Cache<String, NodeVerHash>(10000, -1);

/**
* Set of listeners to be notified when the local client's
* capabilities string is updated
*/
private final static Set<CapsVerListener> capsVerListeners =
new CopyOnWriteArraySet<CapsVerListener>();

static {
XMPPConnectionRegistry.addConnectionCreationListener(new ConnectionCreationListener() {
public void connectionCreated(XMPPConnection connection) {
Expand All @@ -114,13 +125,29 @@ public void connectionCreated(XMPPConnection connection) {
});

try {
MessageDigest sha1MessageDigest = MessageDigest.getInstance("SHA-1");
SUPPORTED_HASHES.put("sha-1", sha1MessageDigest);
MessageDigest sha1MessageDigest = MessageDigest.getInstance(DEFAULT_HASH);
SUPPORTED_HASHES.put(DEFAULT_HASH, sha1MessageDigest);
} catch (NoSuchAlgorithmException e) {
// Ignore
}
}

public interface CapsVerListener {
public void capsVerUpdated(String ver);
}

public static void addCapsVerListener(CapsVerListener capsVerListener) {
capsVerListeners.add(capsVerListener);
}

public static void removeCapsVerListener(CapsVerListener capsVerListener) {
capsVerListeners.remove(capsVerListener);
}

public static Collection<CapsVerListener> getCapsVerListeners() {
return Collections.unmodifiableCollection(capsVerListeners);
}

/**
* Set the default entity node that will be used for new EntityCapsManagers
*
Expand Down Expand Up @@ -323,7 +350,7 @@ public void interceptPacket(Packet packet) {
if (!entityCapsEnabled)
return;

CapsExtension caps = new CapsExtension(entityNode, getCapsVersion(), "sha-1");
CapsExtension caps = new CapsExtension(entityNode, getCapsVersion(), DEFAULT_HASH);
packet.addExtension(caps);
}
};
Expand Down Expand Up @@ -367,6 +394,10 @@ public void setEntityNode(String entityNode) throws NotConnectedException {
updateLocalEntityCaps();
}

public String getEntityNode() {
return entityNode;
}

/**
* Remove a record telling what entity caps node a user has.
*
Expand All @@ -377,6 +408,15 @@ public void removeUserCapsNode(String user) {
JID_TO_NODEVER_CACHE.remove(user);
}

/**
* Add a record describing what enetity caps node a user has.
*
* @param user the user (Full JID)
*/
public void addUserCapsNode(String user, String node, String ver) {
JID_TO_NODEVER_CACHE.put(user, new NodeVerHash(node, ver, DEFAULT_HASH));
}

/**
* Get our own caps version. The version depends on the enabled features. A
* caps version looks like '66/0NaeaBKkwk85efJTGmU47vXI='
Expand Down Expand Up @@ -440,7 +480,7 @@ public void updateLocalEntityCaps() {
discoverInfo.setFrom(connection.getUser());
sdm.addDiscoverInfoTo(discoverInfo);

currentCapsVersion = generateVerificationString(discoverInfo, "sha-1");
currentCapsVersion = generateVerificationString(discoverInfo, DEFAULT_HASH);
addDiscoverInfoByNode(entityNode + '#' + currentCapsVersion, discoverInfo);
if (lastLocalCapsVersions.size() > 10) {
String oldCapsVersion = lastLocalCapsVersions.poll();
Expand All @@ -450,7 +490,7 @@ public void updateLocalEntityCaps() {

CAPS_CACHE.put(currentCapsVersion, discoverInfo);
if (connection != null)
JID_TO_NODEVER_CACHE.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion, "sha-1"));
JID_TO_NODEVER_CACHE.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion, DEFAULT_HASH));

final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities());
sdm.setNodeInformationProvider(entityNode + '#' + currentCapsVersion, new NodeInformationProvider() {
Expand Down Expand Up @@ -478,7 +518,7 @@ public List<PacketExtension> getNodePacketExtensions() {
}
});

// Send an empty presence, and let the packet intercepter
// Send an empty presence, and let the packet interceptor
// add a <c/> node to it.
// See http://xmpp.org/extensions/xep-0115.html#advertise
// We only send a presence packet if there was already one send
Expand All @@ -492,6 +532,10 @@ public List<PacketExtension> getNodePacketExtensions() {
LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
}
}

for (CapsVerListener listener : getCapsVerListeners()) {
listener.capsVerUpdated(currentCapsVersion);
}
}

/**
Expand Down
Loading