mirror of
https://github.com/vanitasvitae/Smack.git
synced 2025-09-11 18:19:38 +02:00
Proper(er) implementation
This commit is contained in:
parent
83cedbe00f
commit
2686fc1ccb
19 changed files with 674 additions and 469 deletions
|
@ -14,9 +14,18 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.element.Jingle;
|
||||
|
||||
/**
|
||||
* Smack's API for <a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261: Jingle In-Band Bytestreams</a>.
|
||||
* Element classes.
|
||||
* Interface with methods that JingleContentTransportManagers must implement.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle_ibb.element;
|
||||
public interface JingleContentTransportManager {
|
||||
|
||||
void acceptInputStream(Jingle jingle, JingleTransportInputStreamCallback callback);
|
||||
|
||||
OutputStream createOutputStream(Jingle jingle);
|
||||
}
|
|
@ -14,8 +14,27 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* Smack's API for <a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261: Jingle In-Band Bytestreams</a>.
|
||||
* Created by vanitas on 06.06.17.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle_ibb;
|
||||
public class JingleInputStream {
|
||||
private final InputStream inputStream;
|
||||
private final int blockSize;
|
||||
|
||||
public JingleInputStream(InputStream inputStream, int blockSize) {
|
||||
this.inputStream = inputStream;
|
||||
this.blockSize = blockSize;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
public int getBlockSize() {
|
||||
return blockSize;
|
||||
}
|
||||
}
|
|
@ -16,10 +16,11 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.jingle;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import org.jivesoftware.smack.Manager;
|
||||
|
@ -28,11 +29,13 @@ import org.jivesoftware.smack.iqrequest.AbstractIqRequestHandler;
|
|||
import org.jivesoftware.smack.iqrequest.IQRequestHandler.Mode;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.IQ.Type;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smackx.jingle.element.Jingle;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleContent;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleContentDescription;
|
||||
import org.jivesoftware.smackx.jingle_ibb.JingleInBandByteStreamManager;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleError;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleReason;
|
||||
import org.jxmpp.jid.FullJid;
|
||||
import org.jxmpp.jid.Jid;
|
||||
|
||||
|
@ -52,66 +55,75 @@ public final class JingleManager extends Manager {
|
|||
}
|
||||
|
||||
private final Map<String, JingleHandler> descriptionHandlers = new ConcurrentHashMap<>();
|
||||
private final Map<FullJidAndSessionId, JingleSession> jingleSessions = new ConcurrentHashMap<>();
|
||||
private final Map<String, JingleContentTransportManager> transportManagers = new HashMap<>();
|
||||
|
||||
private final Map<FullJidAndSessionId, JingleSessionHandler> jingleSessionHandlers = new ConcurrentHashMap<>();
|
||||
|
||||
private JingleManager(XMPPConnection connection) {
|
||||
private JingleManager(final XMPPConnection connection) {
|
||||
super(connection);
|
||||
|
||||
connection.registerIQRequestHandler(
|
||||
new AbstractIqRequestHandler(Jingle.ELEMENT, Jingle.NAMESPACE, Type.set, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
LOGGER.log(Level.INFO, "handleIQRequest");
|
||||
final Jingle jingle = (Jingle) iqRequest;
|
||||
new AbstractIqRequestHandler(Jingle.ELEMENT, Jingle.NAMESPACE, Type.set, Mode.async) {
|
||||
@Override
|
||||
public IQ handleIQRequest(IQ iqRequest) {
|
||||
final Jingle jingle = (Jingle) iqRequest;
|
||||
|
||||
if (jingle.getAction() != JingleAction.session_initiate) {
|
||||
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;
|
||||
}
|
||||
return jingleSessionHandler.handleJingleSessionRequest(jingle, sid);
|
||||
}
|
||||
if (jingle.getAction() != JingleAction.session_initiate) {
|
||||
|
||||
if (jingle.getContents().size() > 1) {
|
||||
LOGGER.severe("Jingle IQs with more then one content element are currently not supported by Smack");
|
||||
return null;
|
||||
}
|
||||
Jid from = jingle.getFrom();
|
||||
assert (from != null);
|
||||
FullJid fullFrom = from.asFullJidOrThrow();
|
||||
FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(fullFrom, jingle.getSid());
|
||||
JingleSession jingleSession = jingleSessions.get(fullJidAndSessionId);
|
||||
|
||||
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;
|
||||
}
|
||||
return jingleDescriptionHandler.handleJingleRequest(jingle);
|
||||
if (jingleSession == null) {
|
||||
// Handle unknown session (XEP-0166 §10)
|
||||
XMPPError.Builder errorBuilder = XMPPError.getBuilder();
|
||||
errorBuilder.setCondition(XMPPError.Condition.item_not_found)
|
||||
.addExtension(JingleError.UNKNOWN_SESSION);
|
||||
return IQ.createErrorResponse(jingle, errorBuilder);
|
||||
}
|
||||
});
|
||||
JingleInBandByteStreamManager.getInstanceFor(connection);
|
||||
return jingleSession.handleRequest(jingle);
|
||||
}
|
||||
|
||||
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) {
|
||||
//Unsupported Application
|
||||
Jingle.Builder builder = Jingle.getBuilder();
|
||||
builder.setAction(JingleAction.session_terminate)
|
||||
.setSessionId(jingle.getSid())
|
||||
.setReason(JingleReason.Reason.unsupported_applications);
|
||||
Jingle response = builder.build();
|
||||
response.setTo(jingle.getFrom());
|
||||
response.setFrom(connection.getUser());
|
||||
return response;
|
||||
}
|
||||
|
||||
return jingleDescriptionHandler.handleJingleRequest(jingle);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void registerJingleSession(JingleSession session) {
|
||||
FullJidAndSessionId jidAndSid = new FullJidAndSessionId(session.getRemote(), session.getSid());
|
||||
jingleSessions.put(jidAndSid, session);
|
||||
}
|
||||
|
||||
public void unregisterJingleSession(JingleSession session) {
|
||||
jingleSessions.values().removeAll(Collections.singleton(session));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public JingleSessionHandler unregisterJingleSessionHandler(FullJid otherJid, String sessionId, JingleSessionHandler sessionHandler) {
|
||||
FullJidAndSessionId fullJidAndSessionId = new FullJidAndSessionId(otherJid, sessionId);
|
||||
return jingleSessionHandlers.remove(fullJidAndSessionId);
|
||||
}
|
||||
|
||||
private static final class FullJidAndSessionId {
|
||||
final FullJid fullJid;
|
||||
final String sessionId;
|
||||
|
@ -135,7 +147,7 @@ public final class JingleManager extends Manager {
|
|||
}
|
||||
FullJidAndSessionId otherFullJidAndSessionId = (FullJidAndSessionId) other;
|
||||
return fullJid.equals(otherFullJidAndSessionId.fullJid)
|
||||
&& sessionId.equals(otherFullJidAndSessionId.sessionId);
|
||||
&& sessionId.equals(otherFullJidAndSessionId.sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Florian Schmaus
|
||||
* Copyright 2017 Paul Schaub
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -16,80 +16,232 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.jingle;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.packet.IQ;
|
||||
import org.jivesoftware.smack.packet.XMPPError;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smackx.jingle.element.Jingle;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleContent;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleError;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleReason;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.jxmpp.jid.FullJid;
|
||||
|
||||
// TODO: Is this class still required? If not, then remove it.
|
||||
public class JingleSession {
|
||||
/**
|
||||
* JingleSession.
|
||||
*/
|
||||
public abstract class JingleSession {
|
||||
|
||||
public enum State {
|
||||
fresh,
|
||||
pending,
|
||||
active,
|
||||
;
|
||||
accepted,
|
||||
terminated,
|
||||
}
|
||||
|
||||
private final Jid initiator;
|
||||
protected final XMPPConnection connection;
|
||||
protected final FullJid initiator;
|
||||
protected final FullJid responder;
|
||||
protected final FullJid ourJid;
|
||||
protected final FullJid remote;
|
||||
protected final String sid;
|
||||
protected State sessionState;
|
||||
protected List<JingleContent> contents;
|
||||
|
||||
private final Jid responder;
|
||||
|
||||
private final String sid;
|
||||
|
||||
private State state = State.pending;
|
||||
|
||||
public JingleSession(Jid initiator, Jid responder, String sid) {
|
||||
public JingleSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder, String sid) {
|
||||
this.connection = connection;
|
||||
this.ourJid = connection.getUser();
|
||||
this.remote = remote;
|
||||
this.initiator = initiator;
|
||||
this.responder = responder;
|
||||
this.sid = sid;
|
||||
this.sessionState = State.fresh;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 31 + initiator.hashCode();
|
||||
hashCode = 31 * hashCode + responder.hashCode();
|
||||
hashCode = 31 * hashCode + sid.hashCode();
|
||||
return hashCode;
|
||||
public JingleSession(XMPPConnection connection, FullJid remote, FullJid initiator, FullJid responder) {
|
||||
this(connection, remote, initiator, responder, StringUtils.randomString(24));
|
||||
}
|
||||
|
||||
public JingleSession(XMPPConnection connection, Jingle initiate) {
|
||||
if (initiate.getAction() != JingleAction.session_initiate) {
|
||||
throw new AssertionError("Session cannot be created without session-initiate");
|
||||
}
|
||||
this.connection = connection;
|
||||
this.ourJid = connection.getUser();
|
||||
this.remote = initiate.getFrom().asFullJidIfPossible();
|
||||
this.initiator = initiate.getInitiator();
|
||||
this.responder = initiate.getResponder();
|
||||
this.sid = initiate.getSid();
|
||||
this.sessionState = State.fresh;
|
||||
}
|
||||
|
||||
public FullJid getInitiator() {
|
||||
return initiator;
|
||||
}
|
||||
|
||||
public FullJid getResponder() {
|
||||
return responder;
|
||||
}
|
||||
|
||||
public FullJid getRemote() {
|
||||
return remote;
|
||||
}
|
||||
|
||||
public FullJid getOurJid() {
|
||||
return ourJid;
|
||||
}
|
||||
|
||||
public String getSid() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public Jid getInitiator() {
|
||||
return initiator;
|
||||
public State getSessionState() {
|
||||
return sessionState;
|
||||
}
|
||||
|
||||
public Jid getResponder() {
|
||||
return responder;
|
||||
public IQ handleRequest(Jingle jingle) {
|
||||
switch (jingle.getAction()) {
|
||||
case session_initiate:
|
||||
// Did we already get another session-initiate?
|
||||
if (sessionState != State.fresh) {
|
||||
return outOfOrder(jingle);
|
||||
}
|
||||
|
||||
//Keep local copy of contents
|
||||
contents = jingle.getContents();
|
||||
|
||||
onSessionInitiate(jingle);
|
||||
|
||||
return IQ.createResultIQ(jingle);
|
||||
|
||||
case session_accept:
|
||||
if (sessionState != State.pending) {
|
||||
return outOfOrder(jingle);
|
||||
}
|
||||
|
||||
onAccept(jingle);
|
||||
|
||||
return IQ.createResultIQ(jingle);
|
||||
|
||||
case session_terminate:
|
||||
|
||||
onTerminate(jingle);
|
||||
|
||||
return IQ.createResultIQ(jingle);
|
||||
|
||||
case content_add:
|
||||
//TODO: Inform listeners
|
||||
return IQ.createResultIQ(jingle);
|
||||
|
||||
default: return IQ.createResultIQ(jingle);
|
||||
}
|
||||
}
|
||||
|
||||
public void setState(State state) {
|
||||
this.state = state;
|
||||
}
|
||||
public abstract void onSessionInitiate(Jingle jingle);
|
||||
|
||||
public State getState() {
|
||||
return state;
|
||||
}
|
||||
public abstract void onAccept(Jingle jingle);
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof JingleSession)) {
|
||||
return false;
|
||||
public abstract void onTerminate(Jingle jingle);
|
||||
|
||||
public IQ initiate(List<JingleContent> contents) {
|
||||
Jingle.Builder b = Jingle.getBuilder();
|
||||
b.setInitiator(initiator)
|
||||
.setAction(JingleAction.session_initiate)
|
||||
.setSessionId(sid);
|
||||
for (JingleContent c : contents) {
|
||||
b.addJingleContent(c);
|
||||
}
|
||||
|
||||
JingleSession otherJingleSession = (JingleSession) other;
|
||||
return initiator.equals(otherJingleSession.initiator) && responder.equals(otherJingleSession.responder)
|
||||
&& sid.equals(otherJingleSession.sid);
|
||||
Jingle j = b.build();
|
||||
j.setTo(remote);
|
||||
j.setFrom(ourJid);
|
||||
this.sessionState = State.pending;
|
||||
return j;
|
||||
}
|
||||
|
||||
IQ terminateSuccessfully() {
|
||||
Jingle.Builder builder = Jingle.getBuilder();
|
||||
builder.setAction(JingleAction.session_terminate);
|
||||
builder.setSessionId(getSid());
|
||||
builder.setReason(JingleReason.Reason.success);
|
||||
public IQ accept(Jingle jingle) {
|
||||
Jingle.Builder b = Jingle.getBuilder();
|
||||
b.setResponder(ourJid)
|
||||
.setAction(JingleAction.session_accept)
|
||||
.setSessionId(sid);
|
||||
for (JingleContent c : jingle.getContents()) {
|
||||
b.addJingleContent(c);
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
Jingle j = b.build();
|
||||
j.setTo(remote);
|
||||
j.setFrom(ourJid);
|
||||
this.sessionState = State.accepted;
|
||||
return j;
|
||||
}
|
||||
|
||||
public IQ terminate(JingleReason.Reason reason) {
|
||||
Jingle.Builder b = Jingle.getBuilder();
|
||||
b.setAction(JingleAction.session_terminate)
|
||||
.setSessionId(sid)
|
||||
.setReason(reason);
|
||||
Jingle j = b.build();
|
||||
j.setTo(remote);
|
||||
j.setFrom(ourJid);
|
||||
this.sessionState = State.terminated;
|
||||
return b.build();
|
||||
}
|
||||
|
||||
public IQ terminateFormally() {
|
||||
return terminate(JingleReason.Reason.decline);
|
||||
}
|
||||
|
||||
//TODO Fix
|
||||
public IQ terminateAlternativeSession(String alternative) {
|
||||
Jingle.Builder b = Jingle.getBuilder();
|
||||
b.setAction(JingleAction.session_terminate)
|
||||
.setSessionId(sid)
|
||||
.setReason(JingleReason.Reason.alternative_session); //Set alt. sessionId
|
||||
Jingle j = b.build();
|
||||
j.setTo(remote);
|
||||
j.setFrom(ourJid);
|
||||
this.sessionState = State.terminated;
|
||||
return j;
|
||||
}
|
||||
|
||||
public IQ terminateSuccessfully() {
|
||||
return terminate(JingleReason.Reason.success);
|
||||
}
|
||||
|
||||
public IQ terminateBusy() {
|
||||
return terminate(JingleReason.Reason.busy);
|
||||
}
|
||||
|
||||
public IQ terminateUnsupportedTransports() {
|
||||
return terminate(JingleReason.Reason.unsupported_transports);
|
||||
}
|
||||
|
||||
public IQ terminateFailedTransport() {
|
||||
return terminate(JingleReason.Reason.failed_transport);
|
||||
}
|
||||
|
||||
public IQ terminateUnsupportedApplications() {
|
||||
return terminate(JingleReason.Reason.unsupported_applications);
|
||||
}
|
||||
|
||||
public IQ terminateFailedApplication() {
|
||||
return terminate(JingleReason.Reason.failed_application);
|
||||
}
|
||||
|
||||
public IQ terminateIncompatibleParameters() {
|
||||
return terminate(JingleReason.Reason.incompatible_parameters);
|
||||
}
|
||||
|
||||
public IQ unknownInitiator(Jingle jingle) {
|
||||
return IQ.createErrorResponse(jingle, XMPPError.Condition.service_unavailable);
|
||||
}
|
||||
|
||||
public IQ outOfOrder(Jingle jingle) {
|
||||
XMPPError.Builder b = XMPPError.getBuilder();
|
||||
b.setCondition(XMPPError.Condition.unexpected_request);
|
||||
b.addExtension(JingleError.OUT_OF_ORDER);
|
||||
return IQ.createErrorResponse(jingle, b);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle;
|
||||
|
||||
/**
|
||||
* Smack's API for <a href="https://xmpp.org/extensions/xep-0261.html">XEP-0261: Jingle In-Band Bytestreams</a>.
|
||||
* Provider classes.
|
||||
* Created by vanitas on 06.06.17.
|
||||
*/
|
||||
package org.jivesoftware.smackx.jingle_ibb.provider;
|
||||
public interface JingleTransportInputStreamCallback {
|
||||
|
||||
void onInputStream(JingleInputStream inputStream);
|
||||
}
|
|
@ -16,12 +16,12 @@
|
|||
*/
|
||||
package org.jivesoftware.smackx.jingle.element;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.jivesoftware.smack.packet.ExtensionElement;
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
|
||||
/**
|
||||
* A jingle transport extension.
|
||||
*
|
||||
|
@ -71,5 +71,4 @@ public abstract class JingleContentTransport implements ExtensionElement {
|
|||
|
||||
return xml;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Paul Schaub
|
||||
*
|
||||
* 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_ibb;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import org.jivesoftware.smack.Manager;
|
||||
import org.jivesoftware.smack.XMPPConnection;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.jivesoftware.smackx.disco.ServiceDiscoveryManager;
|
||||
import org.jivesoftware.smackx.jingle.provider.JingleContentProviderManager;
|
||||
import org.jivesoftware.smackx.jingle_ibb.provider.JingleInBandByteStreamTransportProvider;
|
||||
|
||||
/**
|
||||
* Manager for Jingle In-Band-ByteStreams.
|
||||
*/
|
||||
public final class JingleInBandByteStreamManager extends Manager {
|
||||
|
||||
public static final String NAMESPACE_V1 = "urn:xmpp:jingle:transports:ibb:1";
|
||||
|
||||
private static final WeakHashMap<XMPPConnection, JingleInBandByteStreamManager> INSTANCES = new WeakHashMap<>();
|
||||
|
||||
private JingleInBandByteStreamManager(XMPPConnection connection) {
|
||||
super(connection);
|
||||
JingleContentProviderManager.addJingleContentTransportProvider(NAMESPACE_V1, new JingleInBandByteStreamTransportProvider());
|
||||
ServiceDiscoveryManager.getInstanceFor(connection).addFeature(NAMESPACE_V1);
|
||||
}
|
||||
|
||||
public static JingleInBandByteStreamManager getInstanceFor(XMPPConnection connection) {
|
||||
JingleInBandByteStreamManager manager = INSTANCES.get(connection);
|
||||
if (manager == null) {
|
||||
manager = new JingleInBandByteStreamManager(connection);
|
||||
INSTANCES.put(connection, manager);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random session id.
|
||||
* @return
|
||||
*/
|
||||
public static String generateSessionId() {
|
||||
return StringUtils.randomString(24);
|
||||
}
|
||||
}
|
|
@ -1,85 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Paul Schaub
|
||||
*
|
||||
* 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_ibb.element;
|
||||
|
||||
import org.jivesoftware.smack.util.XmlStringBuilder;
|
||||
import org.jivesoftware.smackx.jingle.element.JingleContentTransport;
|
||||
import org.jivesoftware.smackx.jingle_ibb.JingleInBandByteStreamManager;
|
||||
|
||||
/**
|
||||
* Jingle In-Band-ByteStream transport.
|
||||
*/
|
||||
public class JingleInBandByteStreamTransport extends JingleContentTransport {
|
||||
|
||||
public static final String ATTR_BLOCK_SIZE = "block-size";
|
||||
public static final String ATTR_SID = "sid";
|
||||
public static final short DEFAULT_BLOCK_SIZE = 4096;
|
||||
|
||||
private final short blockSize;
|
||||
private final String sid;
|
||||
|
||||
public JingleInBandByteStreamTransport() {
|
||||
this(DEFAULT_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
public JingleInBandByteStreamTransport(short blockSize) {
|
||||
this(blockSize, JingleInBandByteStreamManager.generateSessionId());
|
||||
}
|
||||
|
||||
public JingleInBandByteStreamTransport(short blockSize, String sid) {
|
||||
super(null);
|
||||
if (blockSize > 0) {
|
||||
this.blockSize = blockSize;
|
||||
} else {
|
||||
this.blockSize = DEFAULT_BLOCK_SIZE;
|
||||
}
|
||||
this.sid = sid;
|
||||
}
|
||||
|
||||
public String getSessionId() {
|
||||
return sid;
|
||||
}
|
||||
|
||||
public short getBlockSize() {
|
||||
return blockSize;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addExtraAttributes(XmlStringBuilder xml) {
|
||||
xml.attribute(ATTR_BLOCK_SIZE, blockSize);
|
||||
xml.attribute(ATTR_SID, sid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return JingleInBandByteStreamManager.NAMESPACE_V1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (other == null || !(other instanceof JingleInBandByteStreamTransport)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.hashCode() == other.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.toXML().toString().hashCode();
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Paul Schaub
|
||||
*
|
||||
* 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_ibb.provider;
|
||||
|
||||
import org.jivesoftware.smackx.jingle.provider.JingleContentTransportProvider;
|
||||
import org.jivesoftware.smackx.jingle_ibb.element.JingleInBandByteStreamTransport;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
|
||||
/**
|
||||
* Parse JingleByteStreamTransport elements.
|
||||
*/
|
||||
public class JingleInBandByteStreamTransportProvider extends JingleContentTransportProvider<JingleInBandByteStreamTransport> {
|
||||
@Override
|
||||
public JingleInBandByteStreamTransport parse(XmlPullParser parser, int initialDepth) throws Exception {
|
||||
String blockSizeString = parser.getAttributeValue(null, JingleInBandByteStreamTransport.ATTR_BLOCK_SIZE);
|
||||
String sid = parser.getAttributeValue(null, JingleInBandByteStreamTransport.ATTR_SID);
|
||||
|
||||
short blockSize = -1;
|
||||
if (blockSizeString != null) {
|
||||
blockSize = Short.valueOf(blockSizeString);
|
||||
}
|
||||
|
||||
return new JingleInBandByteStreamTransport(blockSize, sid);
|
||||
}
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright 2017 Paul Schaub
|
||||
*
|
||||
* 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;
|
||||
|
||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||
import org.jivesoftware.smack.util.StringUtils;
|
||||
import org.junit.Test;
|
||||
import org.jxmpp.jid.Jid;
|
||||
import org.jxmpp.jid.impl.JidCreate;
|
||||
import org.jxmpp.stringprep.XmppStringprepException;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static junit.framework.TestCase.assertNotSame;
|
||||
|
||||
/**
|
||||
* Test JingleSession class.
|
||||
*/
|
||||
public class JingleSessionTest extends SmackTestSuite {
|
||||
|
||||
@Test
|
||||
public void sessionTest() throws XmppStringprepException {
|
||||
Jid romeo = JidCreate.from("romeo@montague.lit");
|
||||
Jid juliet = JidCreate.from("juliet@capulet.lit");
|
||||
String sid = StringUtils.randomString(24);
|
||||
|
||||
JingleSession s1 = new JingleSession(romeo, juliet, sid);
|
||||
JingleSession s2 = new JingleSession(juliet, romeo, sid);
|
||||
JingleSession s3 = new JingleSession(romeo, juliet, StringUtils.randomString(23));
|
||||
JingleSession s4 = new JingleSession(juliet, romeo, sid);
|
||||
|
||||
assertNotSame(s1, s2);
|
||||
assertNotSame(s1, s3);
|
||||
assertNotSame(s2, s3);
|
||||
assertEquals(s2, s4);
|
||||
assertEquals(s2.hashCode(), s4.hashCode());
|
||||
}
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* Copyright © 2017 Paul Schaub
|
||||
*
|
||||
* 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_ibb;
|
||||
|
||||
import org.jivesoftware.smack.test.util.SmackTestSuite;
|
||||
import org.jivesoftware.smack.test.util.TestUtils;
|
||||
import org.jivesoftware.smackx.jingle_ibb.element.JingleInBandByteStreamTransport;
|
||||
import org.jivesoftware.smackx.jingle_ibb.provider.JingleInBandByteStreamTransportProvider;
|
||||
import org.junit.Test;
|
||||
|
||||
import static junit.framework.TestCase.assertEquals;
|
||||
import static junit.framework.TestCase.assertFalse;
|
||||
import static junit.framework.TestCase.assertNotSame;
|
||||
import static junit.framework.TestCase.assertTrue;
|
||||
|
||||
/**
|
||||
* Test JingleInBandByteStreamTransport provider and element.
|
||||
*/
|
||||
public class JingleInBandByteStreamTransportTest extends SmackTestSuite {
|
||||
|
||||
@Test
|
||||
public void parserTest() throws Exception {
|
||||
String sid = JingleInBandByteStreamManager.generateSessionId();
|
||||
short size = 8192;
|
||||
|
||||
String xml = "<transport xmlns='urn:xmpp:jingle:transports:ibb:1' block-size='8192' sid='" + sid + "'/>";
|
||||
|
||||
JingleInBandByteStreamTransport transport = new JingleInBandByteStreamTransport(size, sid);
|
||||
assertEquals(xml, transport.toXML().toString());
|
||||
assertEquals(size, transport.getBlockSize());
|
||||
assertEquals(sid, transport.getSessionId());
|
||||
|
||||
JingleInBandByteStreamTransport parsed = new JingleInBandByteStreamTransportProvider()
|
||||
.parse(TestUtils.getParser(xml));
|
||||
assertEquals(transport, parsed);
|
||||
assertTrue(transport.equals(parsed));
|
||||
assertEquals(xml, parsed.toXML().toString());
|
||||
|
||||
JingleInBandByteStreamTransport transport1 = new JingleInBandByteStreamTransport((short) 1024);
|
||||
assertEquals((short) 1024, transport1.getBlockSize());
|
||||
assertNotSame(transport, transport1);
|
||||
assertNotSame(transport.getSessionId(), transport1.getSessionId());
|
||||
|
||||
assertFalse(transport.equals(null));
|
||||
|
||||
JingleInBandByteStreamTransport transport2 = new JingleInBandByteStreamTransport();
|
||||
assertEquals(JingleInBandByteStreamTransport.DEFAULT_BLOCK_SIZE, transport2.getBlockSize());
|
||||
assertFalse(transport1.equals(transport2));
|
||||
|
||||
JingleInBandByteStreamTransport transport3 = new JingleInBandByteStreamTransport((short) -1024);
|
||||
assertEquals(JingleInBandByteStreamTransport.DEFAULT_BLOCK_SIZE, transport3.getBlockSize());
|
||||
|
||||
assertEquals(transport3.getNamespace(), JingleInBandByteStreamManager.NAMESPACE_V1);
|
||||
assertEquals(transport3.getElementName(), "transport");
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue