mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-11-23 20:42:06 +01:00
Pass events down to contents
This commit is contained in:
parent
185d569b89
commit
af069ffc49
9 changed files with 423 additions and 251 deletions
|
@ -166,7 +166,7 @@ public final class JingleFileTransferManager extends Manager implements JingleDe
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyContentAdd(JingleContent content) {
|
public void notifyContentAdd(JingleSession session, JingleContent content) {
|
||||||
notifyTransfer((JingleFileTransfer) content.getDescription());
|
notifyTransfer((JingleFileTransfer) content.getDescription());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Smack's API for <a href="https://xmpp.org/extensions/xep-0234.html">XEP-0234: Jingle File Transfer</a>.
|
||||||
|
* Adapters.
|
||||||
|
*/
|
||||||
|
package org.jivesoftware.smackx.jft.adapter;
|
|
@ -19,9 +19,13 @@ package org.jivesoftware.smackx.jft.controller;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by vanitas on 27.07.17.
|
* Created by vanitas on 27.07.17.
|
||||||
*/
|
*/
|
||||||
public interface IncomingFileOfferController extends JingleFileTransferController {
|
public interface IncomingFileOfferController extends JingleFileTransferController {
|
||||||
Future<Void> accept(File target);
|
Future<Void> accept(XMPPConnection connection, File target) throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, SmackException.NoResponseException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@ import java.util.concurrent.Future;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
||||||
import org.jivesoftware.smackx.jft.controller.IncomingFileOfferController;
|
import org.jivesoftware.smackx.jft.controller.IncomingFileOfferController;
|
||||||
import org.jivesoftware.smackx.jft.element.JingleFileTransferChildElement;
|
import org.jivesoftware.smackx.jft.element.JingleFileTransferChildElement;
|
||||||
|
@ -69,10 +72,12 @@ public class JingleIncomingFileOffer extends AbstractJingleFileOffer<RemoteFile>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<Void> accept(File target) {
|
public Future<Void> accept(XMPPConnection connection, File target)
|
||||||
|
throws InterruptedException, XMPPException.XMPPErrorException, SmackException.NotConnectedException,
|
||||||
|
SmackException.NoResponseException {
|
||||||
JingleSession session = getParent().getParent();
|
JingleSession session = getParent().getParent();
|
||||||
if (session.getSessionState() == JingleSession.SessionState.pending) {
|
if (session.getSessionState() == JingleSession.SessionState.pending) {
|
||||||
//session.accept();
|
session.accept(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -28,5 +28,5 @@ public interface JingleDescriptionManager {
|
||||||
|
|
||||||
void notifySessionInitiate(JingleSession session);
|
void notifySessionInitiate(JingleSession session);
|
||||||
|
|
||||||
void notifyContentAdd(JingleContent content);
|
void notifyContentAdd(JingleSession session, JingleContent content);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ import java.util.logging.Logger;
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.util.StringUtils;
|
import org.jivesoftware.smack.util.StringUtils;
|
||||||
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
import org.jivesoftware.smackx.bytestreams.BytestreamSession;
|
||||||
import org.jivesoftware.smackx.jingle.Callback;
|
import org.jivesoftware.smackx.jingle.Callback;
|
||||||
|
@ -62,6 +63,69 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
private final List<Callback> callbacks = Collections.synchronizedList(new ArrayList<Callback>());
|
private final List<Callback> callbacks = Collections.synchronizedList(new ArrayList<Callback>());
|
||||||
private final Set<String> transportBlacklist = Collections.synchronizedSet(new HashSet<String>());
|
private final Set<String> transportBlacklist = Collections.synchronizedSet(new HashSet<String>());
|
||||||
|
|
||||||
|
public IQ handleJingleRequest(JingleElement request, XMPPConnection connection) {
|
||||||
|
switch (request.getAction()) {
|
||||||
|
case content_modify:
|
||||||
|
return handleContentModify(request, connection);
|
||||||
|
case description_info:
|
||||||
|
return handleDescriptionInfo(request, connection);
|
||||||
|
case security_info:
|
||||||
|
return handleSecurityInfo(request, connection);
|
||||||
|
case session_info:
|
||||||
|
return handleSessionInfo(request, connection);
|
||||||
|
case transport_accept:
|
||||||
|
return handleTransportAccept(request, connection);
|
||||||
|
case transport_info:
|
||||||
|
return handleTransportInfo(request, connection);
|
||||||
|
case transport_reject:
|
||||||
|
return handleTransportReject(request, connection);
|
||||||
|
case transport_replace:
|
||||||
|
return handleTransportReplace(request, connection);
|
||||||
|
default:
|
||||||
|
throw new AssertionError("Illegal jingle action: " + request.getAction() + " is not allowed here.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleSessionAccept(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleContentModify(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleDescriptionInfo(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleContentRemove(JingleSession session, XMPPConnection connection) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleSecurityInfo(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleSessionInfo(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleTransportAccept(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleTransportInfo(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleTransportReject(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IQ handleTransportReplace(JingleElement request, XMPPConnection connection) {
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
public enum STATE {
|
public enum STATE {
|
||||||
pending_accept,
|
pending_accept,
|
||||||
pending_transmission_start,
|
pending_transmission_start,
|
||||||
|
@ -77,9 +141,9 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public JingleContent(JingleDescription<?> description, JingleTransport<?> transport, JingleSecurity<?> security, String name, String disposition, JingleContentElement.Creator creator, JingleContentElement.Senders senders) {
|
public JingleContent(JingleDescription<?> description, JingleTransport<?> transport, JingleSecurity<?> security, String name, String disposition, JingleContentElement.Creator creator, JingleContentElement.Senders senders) {
|
||||||
this.description = description;
|
setDescription(description);
|
||||||
this.transport = transport;
|
setTransport(transport);
|
||||||
this.security = security;
|
setSecurity(security);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.disposition = disposition;
|
this.disposition = disposition;
|
||||||
this.creator = creator;
|
this.creator = creator;
|
||||||
|
@ -178,7 +242,7 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDescription(JingleDescription<?> description) {
|
public void setDescription(JingleDescription<?> description) {
|
||||||
if (this.description != description) {
|
if (description != null && this.description != description) {
|
||||||
this.description = description;
|
this.description = description;
|
||||||
description.setParent(this);
|
description.setParent(this);
|
||||||
}
|
}
|
||||||
|
@ -189,7 +253,7 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTransport(JingleTransport<?> transport) {
|
public void setTransport(JingleTransport<?> transport) {
|
||||||
if (this.transport != transport) {
|
if (transport != null && this.transport != transport) {
|
||||||
this.transport = transport;
|
this.transport = transport;
|
||||||
transport.setParent(this);
|
transport.setParent(this);
|
||||||
}
|
}
|
||||||
|
@ -200,7 +264,7 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSecurity(JingleSecurity<?> security) {
|
public void setSecurity(JingleSecurity<?> security) {
|
||||||
if (this.security != security) {
|
if (security != null && this.security != security) {
|
||||||
this.security = security;
|
this.security = security;
|
||||||
security.setParent(this);
|
security.setParent(this);
|
||||||
}
|
}
|
||||||
|
@ -266,13 +330,16 @@ public class JingleContent implements JingleTransportCallback {
|
||||||
connection.createStanzaCollectorAndSend(transportReplace).nextResultOrThrow();
|
connection.createStanzaCollectorAndSend(transportReplace).nextResultOrThrow();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onContentAccept(XMPPConnection connection)
|
public void handleContentAccept(JingleElement request, XMPPConnection connection) {
|
||||||
throws SmackException.NotConnectedException, InterruptedException {
|
|
||||||
//Establish transport
|
//Establish transport
|
||||||
if (isReceiving()) {
|
try {
|
||||||
getTransport().establishIncomingBytestreamSession(connection, this, getParent());
|
if (isReceiving()) {
|
||||||
} else if (isSending()) {
|
getTransport().establishIncomingBytestreamSession(connection, this, getParent());
|
||||||
getTransport().establishOutgoingBytestreamSession(connection, this, getParent());
|
} else if (isSending()) {
|
||||||
|
getTransport().establishOutgoingBytestreamSession(connection, this, getParent());
|
||||||
|
}
|
||||||
|
} catch (SmackException.NotConnectedException | InterruptedException e) {
|
||||||
|
LOGGER.log(Level.SEVERE, "Error establishing connection: " + e, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -33,12 +32,8 @@ import org.jivesoftware.smack.packet.IQ;
|
||||||
import org.jivesoftware.smack.util.Async;
|
import org.jivesoftware.smack.util.Async;
|
||||||
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
|
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
|
||||||
import org.jivesoftware.smackx.jingle.JingleManager;
|
import org.jivesoftware.smackx.jingle.JingleManager;
|
||||||
import org.jivesoftware.smackx.jingle.adapter.JingleTransportAdapter;
|
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
|
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
|
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement;
|
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
|
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleElement;
|
import org.jivesoftware.smackx.jingle.element.JingleElement;
|
||||||
import org.jivesoftware.smackx.jingle.element.JingleReasonElement;
|
import org.jivesoftware.smackx.jingle.element.JingleReasonElement;
|
||||||
import org.jivesoftware.smackx.jingle.exception.UnsupportedDescriptionException;
|
import org.jivesoftware.smackx.jingle.exception.UnsupportedDescriptionException;
|
||||||
|
@ -55,6 +50,7 @@ public class JingleSession {
|
||||||
private static final Logger LOGGER = Logger.getLogger(JingleSession.class.getName());
|
private static final Logger LOGGER = Logger.getLogger(JingleSession.class.getName());
|
||||||
|
|
||||||
private final ConcurrentHashMap<String, JingleContent> contents = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, JingleContent> contents = new ConcurrentHashMap<>();
|
||||||
|
private final ConcurrentHashMap<String, JingleContent> proposedContents = new ConcurrentHashMap<>();
|
||||||
private final JingleManager jingleManager;
|
private final JingleManager jingleManager;
|
||||||
|
|
||||||
private final FullJid initiator, responder;
|
private final FullJid initiator, responder;
|
||||||
|
@ -82,36 +78,6 @@ public class JingleSession {
|
||||||
this.sessionState = SessionState.fresh;
|
this.sessionState = SessionState.fresh;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addContent(JingleContent content) {
|
|
||||||
contents.put(content.getName(), content);
|
|
||||||
content.setParent(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addContent(JingleContentElement content)
|
|
||||||
throws UnsupportedSecurityException, UnsupportedTransportException, UnsupportedDescriptionException {
|
|
||||||
addContent(JingleContent.fromElement(content));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<String, JingleContent> getContents() {
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
public JingleContent getContent(String name) {
|
|
||||||
return contents.get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
public JingleContent getSoleContentOrThrow() {
|
|
||||||
if (contents.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contents.size() > 1) {
|
|
||||||
throw new IllegalStateException();
|
|
||||||
}
|
|
||||||
|
|
||||||
return contents.values().iterator().next();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static JingleSession fromSessionInitiate(JingleManager manager, JingleElement initiate)
|
public static JingleSession fromSessionInitiate(JingleManager manager, JingleElement initiate)
|
||||||
throws UnsupportedSecurityException, UnsupportedDescriptionException, UnsupportedTransportException {
|
throws UnsupportedSecurityException, UnsupportedDescriptionException, UnsupportedTransportException {
|
||||||
if (initiate.getAction() != JingleAction.session_initiate) {
|
if (initiate.getAction() != JingleAction.session_initiate) {
|
||||||
|
@ -131,10 +97,23 @@ public class JingleSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initiate(XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
|
public void initiate(XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
|
||||||
|
if (this.sessionState != SessionState.fresh) {
|
||||||
|
throw new IllegalStateException("Session is not in fresh state.");
|
||||||
|
}
|
||||||
|
|
||||||
connection.createStanzaCollectorAndSend(createSessionInitiate()).nextResultOrThrow();
|
connection.createStanzaCollectorAndSend(createSessionInitiate()).nextResultOrThrow();
|
||||||
this.sessionState = SessionState.pending;
|
this.sessionState = SessionState.pending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void accept(XMPPConnection connection) throws SmackException.NotConnectedException, InterruptedException, XMPPException.XMPPErrorException, SmackException.NoResponseException {
|
||||||
|
if (this.sessionState != SessionState.pending) {
|
||||||
|
throw new IllegalStateException("Session is not in pending state.");
|
||||||
|
}
|
||||||
|
|
||||||
|
connection.createStanzaCollectorAndSend(createSessionAccept()).nextResultOrThrow();
|
||||||
|
this.sessionState = SessionState.active;
|
||||||
|
}
|
||||||
|
|
||||||
public JingleElement createSessionInitiate() {
|
public JingleElement createSessionInitiate() {
|
||||||
if (role != Role.initiator) {
|
if (role != Role.initiator) {
|
||||||
throw new IllegalStateException("Sessions role is not initiator.");
|
throw new IllegalStateException("Sessions role is not initiator.");
|
||||||
|
@ -148,87 +127,81 @@ public class JingleSession {
|
||||||
return JingleElement.createSessionInitiate(getInitiator(), getResponder(), getSessionId(), contentElements);
|
return JingleElement.createSessionInitiate(getInitiator(), getResponder(), getSessionId(), contentElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JingleElement createSessionAccept() {
|
||||||
|
if (role != Role.responder) {
|
||||||
|
throw new IllegalStateException("Sessions role is not responder.");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<JingleContentElement> contentElements = new ArrayList<>();
|
||||||
|
for (JingleContent c : contents.values()) {
|
||||||
|
contentElements.add(c.getElement());
|
||||||
|
}
|
||||||
|
|
||||||
|
return JingleElement.createSessionAccept(getInitiator(), getResponder(), getSessionId(), contentElements);
|
||||||
|
}
|
||||||
|
|
||||||
public IQ handleJingleRequest(JingleElement request) {
|
public IQ handleJingleRequest(JingleElement request) {
|
||||||
switch (request.getAction()) {
|
switch (request.getAction()) {
|
||||||
|
case content_modify:
|
||||||
|
case description_info:
|
||||||
|
case security_info:
|
||||||
|
case session_info:
|
||||||
|
case transport_accept:
|
||||||
|
case transport_info:
|
||||||
|
case transport_reject:
|
||||||
|
case transport_replace:
|
||||||
|
return getSoleAffectedContentOrThrow(request).handleJingleRequest(request, jingleManager.getConnection());
|
||||||
case content_accept:
|
case content_accept:
|
||||||
return handleContentAccept(request);
|
return handleContentAccept(request);
|
||||||
case content_add:
|
case content_add:
|
||||||
return handleContentAdd(request);
|
return handleContentAdd(request);
|
||||||
case content_modify:
|
|
||||||
return handleContentModify(request);
|
|
||||||
case content_reject:
|
case content_reject:
|
||||||
return handleContentReject(request);
|
return handleContentReject(request);
|
||||||
case content_remove:
|
case content_remove:
|
||||||
return handleContentRemove(request);
|
return handleContentRemove(request);
|
||||||
case description_info:
|
|
||||||
return handleDescriptionInfo(request);
|
|
||||||
case session_info:
|
|
||||||
return handleSessionInfo(request);
|
|
||||||
case security_info:
|
|
||||||
return handleSecurityInfo(request);
|
|
||||||
case session_accept:
|
case session_accept:
|
||||||
return handleSessionAccept(request);
|
return handleSessionAccept(request);
|
||||||
case transport_accept:
|
|
||||||
return handleTransportAccept(request);
|
|
||||||
case transport_info:
|
|
||||||
return handleTransportInfo(request);
|
|
||||||
case session_initiate:
|
case session_initiate:
|
||||||
return handleSessionInitiate(request);
|
return handleSessionInitiate(request);
|
||||||
case transport_reject:
|
|
||||||
return handleTransportReject(request);
|
|
||||||
case session_terminate:
|
case session_terminate:
|
||||||
return handleSessionTerminate(request);
|
return handleSessionTerminate(request);
|
||||||
case transport_replace:
|
|
||||||
return handleTransportReplace(request);
|
|
||||||
default:
|
default:
|
||||||
throw new AssertionError("Unknown Jingle Action enum! " + request.getAction());
|
throw new AssertionError("Illegal jingle action: " + request.getAction());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQ handleTransportReplace(final JingleElement request) {
|
/* ############## Processed in this class ############## */
|
||||||
Async.go(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
List<JingleContentElement> affectedContents = request.getContents();
|
|
||||||
List<JingleElement> responses = new ArrayList<>();
|
|
||||||
|
|
||||||
for (JingleContentElement affected : affectedContents) {
|
/**
|
||||||
JingleContent content = contents.get(affected.getName());
|
* Handle incoming session-accept stanza.
|
||||||
JingleContentTransportElement newTransport = affected.getTransport();
|
* @param request session-accept stanza.
|
||||||
Set<String> blacklist = content.getTransportBlacklist();
|
* @return result.
|
||||||
|
*/
|
||||||
|
private IQ handleSessionAccept(final JingleElement request) {
|
||||||
|
this.sessionState = SessionState.active;
|
||||||
|
|
||||||
// Proposed transport method might already be on the blacklist (eg. because of previous failures)
|
for (final JingleContent content : contents.values()) {
|
||||||
if (blacklist.contains(newTransport.getNamespace())) {
|
Async.go(new Runnable() {
|
||||||
responses.add(JingleElement.createTransportReject(getInitiator(), getPeer(), getSessionId(),
|
@Override
|
||||||
content.getCreator(), content.getName(), newTransport));
|
public void run() {
|
||||||
continue;
|
content.handleSessionAccept(request, jingleManager.getConnection());
|
||||||
}
|
|
||||||
|
|
||||||
JingleTransportAdapter<?> transportAdapter = JingleManager.getJingleTransportAdapter(
|
|
||||||
newTransport.getNamespace());
|
|
||||||
// This might be an unknown transport.
|
|
||||||
if (transportAdapter == null) {
|
|
||||||
responses.add(JingleElement.createTransportReject(getInitiator(), getPeer(), getSessionId(),
|
|
||||||
content.getCreator(), content.getName(), newTransport));
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Otherwise, when all went well so far, accept the transport-replace
|
|
||||||
content.setTransport(JingleManager.getJingleTransportAdapter(newTransport.getNamespace())
|
|
||||||
.transportFromElement(newTransport));
|
|
||||||
responses.add(JingleElement.createTransportAccept(getInitiator(), getPeer(), getSessionId(),
|
|
||||||
content.getCreator(), content.getName(), newTransport));
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
for (JingleElement response : responses) {
|
return IQ.createResultIQ(request);
|
||||||
try {
|
}
|
||||||
jingleManager.getConnection().createStanzaCollectorAndSend(response).nextResultOrThrow();
|
|
||||||
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) {
|
private IQ handleSessionInitiate(JingleElement request) {
|
||||||
LOGGER.log(Level.SEVERE, "Could not send response to transport-replace: " + e, e);
|
JingleDescription<?> description = getSoleContentOrThrow().getDescription();
|
||||||
}
|
JingleDescriptionManager descriptionManager = jingleManager.getDescriptionManager(description.getNamespace());
|
||||||
}
|
|
||||||
}
|
if (descriptionManager == null) {
|
||||||
});
|
LOGGER.log(Level.WARNING, "Unsupported description type: " + description.getNamespace());
|
||||||
|
return JingleElement.createSessionTerminate(getPeer(), getSessionId(), JingleReasonElement.Reason.unsupported_applications);
|
||||||
|
}
|
||||||
|
|
||||||
|
descriptionManager.notifySessionInitiate(this);
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
return IQ.createResultIQ(request);
|
||||||
}
|
}
|
||||||
|
@ -247,168 +220,193 @@ public class JingleSession {
|
||||||
return IQ.createResultIQ(request);
|
return IQ.createResultIQ(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQ handleTransportReject(JingleElement request) {
|
private IQ handleContentAccept(final JingleElement request) {
|
||||||
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
for (JingleContentElement a : request.getContents()) {
|
||||||
for (JingleContent c : affectedContents.values()) {
|
final JingleContent accepted = proposedContents.get(a.getName());
|
||||||
|
|
||||||
}
|
if (accepted == null) {
|
||||||
return null;
|
throw new AssertionError("Illegal content name!");
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleSessionInitiate(JingleElement request) {
|
|
||||||
JingleDescription<?> description = getSoleContentOrThrow().getDescription();
|
|
||||||
JingleDescriptionManager descriptionManager = jingleManager.getDescriptionManager(description.getNamespace());
|
|
||||||
|
|
||||||
if (descriptionManager == null) {
|
|
||||||
LOGGER.log(Level.WARNING, "Unsupported description type: " + description.getNamespace());
|
|
||||||
return JingleElement.createSessionTerminate(getPeer(), getSessionId(), JingleReasonElement.Reason.unsupported_applications);
|
|
||||||
}
|
|
||||||
|
|
||||||
descriptionManager.notifySessionInitiate(this);
|
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleTransportInfo(JingleElement request) {
|
|
||||||
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
|
||||||
|
|
||||||
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
|
||||||
JingleTransport<?> transport = entry.getValue().getTransport();
|
|
||||||
JingleContentTransportInfoElement info = entry.getKey().getTransport().getInfo();
|
|
||||||
transport.handleTransportInfo(info, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleTransportAccept(JingleElement request) {
|
|
||||||
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
|
||||||
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
|
||||||
|
|
||||||
PendingJingleAction pending = pendingJingleActions.get(entry.getValue());
|
|
||||||
if (pending == null) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending.getAction() != JingleAction.transport_replace) {
|
proposedContents.remove(accepted.getName());
|
||||||
//TODO: Are multiple contents even possible here?
|
contents.put(accepted.getName(), accepted);
|
||||||
//TODO: How to react to partially illegal requests?
|
|
||||||
return JingleElement.createJingleErrorOutOfOrder(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
entry.getValue().setTransport(((PendingJingleAction.TransportReplace) pending).getNewTransport());
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
accepted.handleContentAccept(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
return IQ.createResultIQ(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQ handleSessionAccept(JingleElement request) {
|
|
||||||
this.sessionState = SessionState.active;
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleSecurityInfo(JingleElement request) {
|
|
||||||
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
|
||||||
List<JingleElement> responses = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
|
||||||
responses.add(entry.getValue().getSecurity().handleSecurityInfo(entry.getKey().getSecurity().getSecurityInfo(), request));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JingleElement response : responses) {
|
|
||||||
try {
|
|
||||||
getJingleManager().getConnection().createStanzaCollectorAndSend(response).nextResultOrThrow();
|
|
||||||
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException e) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Could not send response to security-info: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleSessionInfo(JingleElement request) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleDescriptionInfo(JingleElement request) {
|
|
||||||
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
|
||||||
List<JingleElement> responses = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
|
||||||
responses.add(entry.getValue().getDescription().handleDescriptionInfo(entry.getKey().getDescription().getDescriptionInfo()));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (JingleElement response : responses) {
|
|
||||||
try {
|
|
||||||
getJingleManager().getConnection().createStanzaCollectorAndSend(response).nextResultOrThrow();
|
|
||||||
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException e) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Could not send response to description-info: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleContentRemove(JingleElement request) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleContentReject(JingleElement request) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleContentModify(JingleElement request) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ handleContentAdd(JingleElement request) {
|
private IQ handleContentAdd(JingleElement request) {
|
||||||
final List<JingleContentElement> proposedContents = request.getContents();
|
final JingleContent proposed = getSoleProposedContentOrThrow(request);
|
||||||
final List<JingleContentElement> acceptedContents = new ArrayList<>();
|
|
||||||
|
|
||||||
final HashMap<String, List<JingleContent>> contentsByDescription = new HashMap<>();
|
final JingleDescriptionManager descriptionManager = jingleManager.getDescriptionManager(proposed.getDescription().getNamespace());
|
||||||
|
|
||||||
for (JingleContentElement p : proposedContents) {
|
if (descriptionManager == null) {
|
||||||
JingleContentDescriptionElement description = p.getDescription();
|
throw new AssertionError("DescriptionManager is null: " + proposed.getDescription().getNamespace());
|
||||||
List<JingleContent> list = contentsByDescription.get(description.getNamespace());
|
|
||||||
if (list == null) {
|
|
||||||
list = new ArrayList<>();
|
|
||||||
contentsByDescription.put(description.getNamespace(), list);
|
|
||||||
}
|
|
||||||
list.add(JingleContent.fromElement(p));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<String, List<JingleContent>> descriptionCategory : contentsByDescription.entrySet()) {
|
Async.go(new Runnable() {
|
||||||
JingleDescriptionManager descriptionManager = JingleManager.getInstanceFor(getJingleManager().getConnection()).getDescriptionManager(descriptionCategory.getKey());
|
@Override
|
||||||
|
public void run() {
|
||||||
if (descriptionManager == null) {
|
descriptionManager.notifyContentAdd(JingleSession.this, proposed);
|
||||||
//blabla
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
for (final JingleContent content : descriptionCategory.getValue()) {
|
|
||||||
descriptionManager.notifyContentAdd(content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (acceptedContents.size() > 0) {
|
|
||||||
JingleElement accept = JingleElement.createContentAccept(getPeer(), getSessionId(), acceptedContents);
|
|
||||||
try {
|
|
||||||
getJingleManager().getConnection().createStanzaCollectorAndSend(accept).nextResultOrThrow();
|
|
||||||
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) {
|
|
||||||
LOGGER.log(Level.SEVERE, "Could not send response to content-add: " + e, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//TODO: send content-reject for rejected contents!
|
|
||||||
|
|
||||||
return IQ.createResultIQ(request);
|
return IQ.createResultIQ(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IQ handleContentAccept(JingleElement request) {
|
private IQ handleContentReject(JingleElement request) {
|
||||||
return null;
|
for (JingleContentElement r : request.getContents()) {
|
||||||
|
final JingleContent rejected = proposedContents.get(r.getName());
|
||||||
|
|
||||||
|
if (rejected == null) {
|
||||||
|
throw new AssertionError("Illegal content name!");
|
||||||
|
}
|
||||||
|
|
||||||
|
proposedContents.remove(rejected.getName());
|
||||||
|
|
||||||
|
/*
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
rejected.handleContentReject(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IQ handleContentRemove(final JingleElement request) {
|
||||||
|
for (JingleContentElement r : request.getContents()) {
|
||||||
|
final JingleContent removed = contents.get(r.getName());
|
||||||
|
|
||||||
|
if (removed == null) {
|
||||||
|
throw new AssertionError("Illegal content name!");
|
||||||
|
}
|
||||||
|
|
||||||
|
contents.remove(removed.getName());
|
||||||
|
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
removed.handleContentRemove(JingleSession.this, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ############## Processed further down ############## */
|
||||||
|
|
||||||
|
private IQ handleContentModify(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleContentModify(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleDescriptionInfo(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleDescriptionInfo(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleSecurityInfo(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleSecurityInfo(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleSessionInfo(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleSessionInfo(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleTransportAccept(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleTransportAccept(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleTransportInfo(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleTransportInfo(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleTransportReject(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleTransportReject(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IQ handleTransportReplace(final JingleElement request) {
|
||||||
|
final JingleContent content = getSoleAffectedContentOrThrow(request);
|
||||||
|
Async.go(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
content.handleTransportReplace(request, jingleManager.getConnection());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return IQ.createResultIQ(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ################ Other getters and setters ############### */
|
||||||
|
|
||||||
public FullJid getInitiator() {
|
public FullJid getInitiator() {
|
||||||
return initiator;
|
return initiator;
|
||||||
}
|
}
|
||||||
|
@ -453,6 +451,57 @@ public class JingleSession {
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private JingleContent getSoleAffectedContentOrThrow(JingleElement request) {
|
||||||
|
if (request.getContents().size() != 1) {
|
||||||
|
throw new AssertionError("More/less than 1 content in request!");
|
||||||
|
}
|
||||||
|
|
||||||
|
JingleContent content = contents.get(request.getContents().get(0).getName());
|
||||||
|
if (content == null) {
|
||||||
|
throw new AssertionError("Illegal content name!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JingleContent getSoleProposedContentOrThrow(JingleElement request) {
|
||||||
|
if (request.getContents().size() != 1) {
|
||||||
|
throw new AssertionError("More/less than 1 content in request!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return JingleContent.fromElement(request.getContents().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContent(JingleContent content) {
|
||||||
|
contents.put(content.getName(), content);
|
||||||
|
content.setParent(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addContent(JingleContentElement content)
|
||||||
|
throws UnsupportedSecurityException, UnsupportedTransportException, UnsupportedDescriptionException {
|
||||||
|
addContent(JingleContent.fromElement(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConcurrentHashMap<String, JingleContent> getContents() {
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JingleContent getContent(String name) {
|
||||||
|
return contents.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JingleContent getSoleContentOrThrow() {
|
||||||
|
if (contents.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contents.size() > 1) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents.values().iterator().next();
|
||||||
|
}
|
||||||
|
|
||||||
public SessionState getSessionState() {
|
public SessionState getSessionState() {
|
||||||
return sessionState;
|
return sessionState;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 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.element;
|
package org.jivesoftware.smackx.jingle.element;
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.NamedElement;
|
import org.jivesoftware.smack.packet.NamedElement;
|
||||||
|
|
|
@ -27,6 +27,8 @@ import java.util.ArrayList;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.SmackException;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
|
import org.jivesoftware.smackx.bytestreams.socks5.Socks5Proxy;
|
||||||
import org.jivesoftware.smackx.jft.controller.IncomingFileOfferController;
|
import org.jivesoftware.smackx.jft.controller.IncomingFileOfferController;
|
||||||
import org.jivesoftware.smackx.jft.controller.OutgoingFileOfferController;
|
import org.jivesoftware.smackx.jft.controller.OutgoingFileOfferController;
|
||||||
|
@ -86,6 +88,7 @@ public class JingleFileTransferTest extends AbstractSmackIntegrationTest {
|
||||||
@Override
|
@Override
|
||||||
public void onIncomingFileOffer(IncomingFileOfferController offer) {
|
public void onIncomingFileOffer(IncomingFileOfferController offer) {
|
||||||
LOGGER.log(Level.INFO, "INCOMING FILE TRANSFER!");
|
LOGGER.log(Level.INFO, "INCOMING FILE TRANSFER!");
|
||||||
|
|
||||||
offer.addProgressListener(new ProgressListener() {
|
offer.addProgressListener(new ProgressListener() {
|
||||||
@Override
|
@Override
|
||||||
public void started() {
|
public void started() {
|
||||||
|
@ -102,11 +105,17 @@ public class JingleFileTransferTest extends AbstractSmackIntegrationTest {
|
||||||
resultSyncPoint2.signal();
|
resultSyncPoint2.signal();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
receiveFuture.add(offer.accept(target));
|
|
||||||
|
try {
|
||||||
|
receiveFuture.add(offer.accept(conTwo, target));
|
||||||
|
} catch (InterruptedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
|
||||||
|
fail(e.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
OutgoingFileOfferController sending = aftm.sendFile(source, bob);
|
OutgoingFileOfferController sending = aftm.sendFile(source, bob);
|
||||||
|
|
||||||
sending.addProgressListener(new ProgressListener() {
|
sending.addProgressListener(new ProgressListener() {
|
||||||
@Override
|
@Override
|
||||||
public void started() {
|
public void started() {
|
||||||
|
|
Loading…
Reference in a new issue