2017-05-30 08:45:27 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* Copyright 2017 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.smackx.jingle;
|
|
|
|
|
2017-06-04 17:18:40 +02:00
|
|
|
import java.util.Map;
|
|
|
|
import java.util.WeakHashMap;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
2017-06-04 20:33:44 +02:00
|
|
|
import java.util.logging.Level;
|
2017-06-04 17:18:40 +02:00
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
2017-05-30 08:45:27 +02:00
|
|
|
import org.jivesoftware.smack.Manager;
|
|
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
|
|
import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
2017-06-03 23:30:37 +02:00
|
|
|
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
2017-05-30 08:45:27 +02:00
|
|
|
import org.jivesoftware.smack.packet.IQ;
|
|
|
|
import org.jivesoftware.smack.packet.IQ.Type;
|
|
|
|
import org.jivesoftware.smackx.jingle.element.Jingle;
|
2017-06-04 17:18:40 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
2017-05-30 08:45:27 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContent;
|
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContentDescription;
|
2017-06-04 20:33:44 +02:00
|
|
|
import org.jivesoftware.smackx.jingle_ibb.JingleInBandByteStreamManager;
|
2017-05-30 08:45:27 +02:00
|
|
|
import org.jxmpp.jid.FullJid;
|
|
|
|
import org.jxmpp.jid.Jid;
|
|
|
|
|
|
|
|
public final class JingleManager extends Manager {
|
|
|
|
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(JingleManager.class.getName());
|
|
|
|
|
|
|
|
private static final Map<XMPPConnection, JingleManager> INSTANCES = new WeakHashMap<>();
|
|
|
|
|
|
|
|
public static synchronized JingleManager getInstanceFor(XMPPConnection connection) {
|
|
|
|
JingleManager jingleManager = INSTANCES.get(connection);
|
|
|
|
if (jingleManager == null) {
|
|
|
|
jingleManager = new JingleManager(connection);
|
|
|
|
INSTANCES.put(connection, jingleManager);
|
|
|
|
}
|
|
|
|
return jingleManager;
|
|
|
|
}
|
|
|
|
|
|
|
|
private final Map<String, JingleHandler> descriptionHandlers = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
|
private final Map<FullJidAndSessionId, JingleSessionHandler> jingleSessionHandlers = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
|
private JingleManager(XMPPConnection connection) {
|
|
|
|
super(connection);
|
|
|
|
|
|
|
|
connection.registerIQRequestHandler(
|
|
|
|
new AbstractIqRequestHandler(Jingle.ELEMENT, Jingle.NAMESPACE, Type.set, Mode.async) {
|
|
|
|
@Override
|
|
|
|
public IQ handleIQRequest(IQ iqRequest) {
|
2017-06-04 20:33:44 +02:00
|
|
|
LOGGER.log(Level.INFO, "handleIQRequest");
|
2017-05-30 08:45:27 +02:00
|
|
|
final Jingle jingle = (Jingle) iqRequest;
|
|
|
|
|
2017-06-04 17:18:40 +02:00
|
|
|
if (jingle.getAction() != JingleAction.session_initiate) {
|
2017-05-30 08:45:27 +02:00
|
|
|
Jid from = jingle.getFrom();
|
|
|
|
assert (from != null);
|
|
|
|
FullJid fullFrom = from.asFullJidOrThrow();
|
|
|
|
String sid = jingle.getSid();
|
|
|
|
FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(fullFrom, sid);
|
|
|
|
JingleSessionHandler jingleSessionHandler = jingleSessionHandlers.get(fullJidAndSessionId);
|
|
|
|
if (jingleSessionHandler == null) {
|
|
|
|
// TODO handle non existing jingle session handler.
|
|
|
|
return null;
|
|
|
|
}
|
2017-06-04 15:49:06 +02:00
|
|
|
return jingleSessionHandler.handleJingleSessionRequest(jingle, sid);
|
2017-05-30 08:45:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (jingle.getContents().size() > 1) {
|
|
|
|
LOGGER.severe("Jingle IQs with more then one content element are currently not supported by Smack");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
JingleContent content = jingle.getContents().get(0);
|
|
|
|
JingleContentDescription description = content.getDescription();
|
|
|
|
JingleHandler jingleDescriptionHandler = descriptionHandlers.get(
|
|
|
|
description.getNamespace());
|
|
|
|
if (jingleDescriptionHandler == null) {
|
|
|
|
// TODO handle non existing content description handler.
|
|
|
|
return null;
|
|
|
|
}
|
2017-06-04 15:49:06 +02:00
|
|
|
return jingleDescriptionHandler.handleJingleRequest(jingle);
|
2017-05-30 08:45:27 +02:00
|
|
|
}
|
|
|
|
});
|
2017-06-04 20:33:44 +02:00
|
|
|
JingleInBandByteStreamManager.getInstanceFor(connection);
|
2017-05-30 08:45:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
public JingleHandler registerDescriptionHandler(String namespace, JingleHandler handler) {
|
|
|
|
return descriptionHandlers.put(namespace, handler);
|
|
|
|
}
|
|
|
|
|
|
|
|
public JingleSessionHandler registerJingleSessionHandler(FullJid otherJid, String sessionId, JingleSessionHandler sessionHandler) {
|
|
|
|
FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(otherJid, sessionId);
|
|
|
|
return jingleSessionHandlers.put(fullJidAndSessionId, sessionHandler);
|
|
|
|
}
|
|
|
|
|
2017-06-03 23:30:37 +02:00
|
|
|
public JingleSessionHandler unregisterJingleSessionHandler(FullJid otherJid, String sessionId, JingleSessionHandler sessionHandler) {
|
2017-05-30 08:45:27 +02:00
|
|
|
FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(otherJid, sessionId);
|
|
|
|
return jingleSessionHandlers.remove(fullJidAndSessionId);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final class FullJidAndSessionId {
|
|
|
|
final FullJid fullJid;
|
|
|
|
final String sessionId;
|
|
|
|
|
|
|
|
private FullJidAndSessionId(FullJid fullJid, String sessionId) {
|
|
|
|
this.fullJid = fullJid;
|
|
|
|
this.sessionId = sessionId;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
|
|
|
int hashCode = 31 * fullJid.hashCode();
|
|
|
|
hashCode = 31 * hashCode + sessionId.hashCode();
|
|
|
|
return hashCode;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object other) {
|
|
|
|
if (!(other instanceof FullJidAndSessionId)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
FullJidAndSessionId otherFullJidAndSessionId = (FullJidAndSessionId) other;
|
|
|
|
return fullJid.equals(otherFullJidAndSessionId.fullJid)
|
|
|
|
&& sessionId.equals(otherFullJidAndSessionId.sessionId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|