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

DRAFT/WIP: Serverless Messaging v2 (XEP-174) #25

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
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
3 changes: 2 additions & 1 deletion settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@ include 'smack-core',
'smack-bosh',
'smack-android',
'smack-android-extensions',
'smack-java7'
'smack-java7',
'smack-serverless'
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,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
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@ public String getElementName() {

@Override
public XmlStringBuilder toXML() {
XmlStringBuilder xml = getBasicStreamOpen();
xml.rightAngleBracket();
return xml;
}

protected final XmlStringBuilder getBasicStreamOpen() {
XmlStringBuilder xml = new XmlStringBuilder(this);
xml.attribute("to", service);
xml.attribute("xmlns:stream", "http://etherx.jabber.org/streams");
xml.attribute("version", VERSION);
xml.rightAngleBracket();
return xml;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -55,10 +55,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 Down Expand Up @@ -111,6 +113,13 @@ public class EntityCapsManager extends Manager {
*/
private static final LruCache<String, NodeVerHash> JID_TO_NODEVER_CACHE = new LruCache<String, NodeVerHash>(10000);

/**
* 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 @@ -126,6 +135,18 @@ public void connectionCreated(XMPPConnection connection) {
}
}

public interface CapsVerListener {
public void capsVerUpdated(CapsVersionAndHash capsVersionAndHash);
}

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

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

/**
* Set the default entity node that will be used for new EntityCapsManagers
*
Expand Down Expand Up @@ -244,7 +265,7 @@ public static void clearMemoryCache() {
CAPS_CACHE.clear();
}

private static void addCapsExtensionInfo(String from, CapsExtension capsExtension) {
protected static void addCapsExtensionInfo(String from, CapsExtension capsExtension) {
String capsExtensionHash = capsExtension.getHash();
String hashInUppercase = capsExtensionHash.toUpperCase(Locale.US);
// SUPPORTED_HASHES uses the format of MessageDigest, which is uppercase, e.g. "SHA-1" instead of "sha-1"
Expand All @@ -271,6 +292,11 @@ private static void addCapsExtensionInfo(String from, CapsExtension capsExtensio
*/
private String entityNode = DEFAULT_ENTITY_NODE;

protected EntityCapsManager() {
super(null);
throw new UnsupportedOperationException();
}

private EntityCapsManager(XMPPConnection connection) {
super(connection);
this.sdm = ServiceDiscoveryManager.getInstanceFor(connection);
Expand Down Expand Up @@ -401,6 +427,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 @@ -411,6 +441,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 @@ -517,6 +556,10 @@ public List<PacketExtension> getNodePacketExtensions() {
LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e);
}
}

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

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public class ServiceDiscoveryManager extends Manager {
private Set<DiscoverInfo.Identity> identities = new HashSet<DiscoverInfo.Identity>();
private DiscoverInfo.Identity identity = defaultIdentity;

private EntityCapsManager capsManager;
protected EntityCapsManager capsManager;

private static Map<XMPPConnection, ServiceDiscoveryManager> instances =
Collections.synchronizedMap(new WeakHashMap<XMPPConnection, ServiceDiscoveryManager>());
Expand Down Expand Up @@ -116,7 +116,7 @@ public static void setDefaultIdentity(DiscoverInfo.Identity identity) {
*
* @param connection the connection to which a ServiceDiscoveryManager is going to be created.
*/
private ServiceDiscoveryManager(XMPPConnection connection) {
protected ServiceDiscoveryManager(XMPPConnection connection) {
super(connection);

addFeature(DiscoverInfo.NAMESPACE);
Expand Down Expand Up @@ -759,7 +759,7 @@ public void setEntityCapsManager(EntityCapsManager manager) {
/**
* Updates the Entity Capabilities Verification String if EntityCaps is enabled.
*/
private void renewEntityCapsVersion() {
protected void renewEntityCapsVersion() {
if (capsManager != null && capsManager.entityCapsEnabled())
capsManager.updateLocalEntityCaps();
}
Expand Down
8 changes: 8 additions & 0 deletions smack-serverless/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
description = """\
XEP-0174 Serverless Messaging."""

dependencies {
compile 'javax.jmdns:jmdns:3.4.1'
compile project(':smack-core')
compile project(':smack-extensions')
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
/**
*
* Copyright 2009 Jonas Ådahl.
*
* 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.serverless;


import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.serverless.LLPresence;

import javax.net.SocketFactory;
import java.net.Socket;

/**
* Link-local connection configuration settings. Two general cases exists,
* one where the we want to connect to a remote peer, and one when o remote
* peer has connected to us.
*/
public class LLConnectionConfiguration extends ConnectionConfiguration implements Cloneable {
private static final String SERVICE_NAME = "locallink";
private LLPresence remotePresence;
private LLPresence localPresence;
private Socket socket;

/**
* Holds the socket factory that is used to generate the socket in the connection
*/
private SocketFactory socketFactory;

/**
* Configuration used for connecting to remote peer.
* @param local LLPresence for the local user
* @param remote LLPresence for the remote user
*/
// public LLConnectionConfiguration(LLPresence local, LLPresence remote) {
//// super(remote.getServiceName());
// this.localPresence = local;
// this.remotePresence = remote;
// }

/**
* Instantiate a link-local configuration when the connection is acting as
* the host.
*
* @param local the local link-local presence class.
* @param remoteSocket the socket which the new connection is assigned to.
*/
public LLConnectionConfiguration(LLPresence local, Socket remoteSocket) {
super(null);
this.localPresence = local;
this.socket = remoteSocket;
}

// @Override
// public void setServiceName(String serviceName) {
// // ConnectionConfiguration#setServiceName extracts the domain from the serviceName
// // e.g "david@guardian" -> "guardian"
// // This is not the behavior we want for XEP-0174 clients
// this.serviceName = serviceName;
// }

/**
* Tells if the connection is the initiating one.
* @return true if this configuration is for the connecting connection.
*/
public boolean isInitiator() {
return socket == null;
}

/**
* Return the service name of the remote peer.
* @return the remote peer's service name.
*/
public String getRemoteServiceName() {
return remotePresence.getServiceName();
}

/**
* Return the service name of this client.
* @return this clients service name.
*/
public String getLocalServiceName() {
return localPresence.getServiceName();
}

/**
* Return this clients link-local presence information.
* @return this clients link-local presence information.
*/
public LLPresence getLocalPresence() {
return localPresence;
}

/**
* Return the remote client's link-local presence information.
* @return the remote client's link-local presence information.
*/
public LLPresence getRemotePresence() {
return remotePresence;
}

/**
* Return the socket which has been established when the
* remote client connected.
* @return the socket established when the remote client connected.
*/
public Socket getSocket() {
return socket;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
*
* Copyright 2014 Florian Schmaus
*
* 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.serverless;

import org.jivesoftware.smackx.caps.EntityCapsManager;
import org.jivesoftware.smackx.caps.packet.CapsExtension;
import org.jivesoftware.smackx.disco.packet.DiscoverInfo;

public class LLEntityCapsManager extends EntityCapsManager {
private LLEntityCapsManager() {
throw new UnsupportedOperationException();
}

static void addDiscoverInfo(String jid, DiscoverInfo discoverInfo) {
CapsExtension capsExtension = CapsExtension.from(discoverInfo);
if (capsExtension == null) {
return;
}
addCapsExtensionInfo(jid, capsExtension);
}
}
Loading