2017-07-21 23:05:46 +02:00
|
|
|
/**
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2017-07-27 15:18:18 +02:00
|
|
|
package org.jivesoftware.smackx.jingle.components;
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Set;
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import java.util.logging.Level;
|
|
|
|
import java.util.logging.Logger;
|
|
|
|
|
|
|
|
import org.jivesoftware.smack.SmackException;
|
|
|
|
import org.jivesoftware.smack.XMPPException;
|
|
|
|
import org.jivesoftware.smack.packet.IQ;
|
2017-07-28 00:55:44 +02:00
|
|
|
import org.jivesoftware.smack.util.Async;
|
2017-07-27 17:35:16 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.JingleDescriptionManager;
|
2017-07-21 23:05:46 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.JingleManager;
|
|
|
|
import org.jivesoftware.smackx.jingle.adapter.JingleTransportAdapter;
|
2017-07-27 17:35:16 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleAction;
|
2017-07-21 23:05:46 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContentDescriptionElement;
|
2017-07-27 17:35:16 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContentElement;
|
2017-07-21 23:05:46 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContentTransportElement;
|
2017-07-27 17:35:16 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleContentTransportInfoElement;
|
2017-07-21 23:05:46 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleElement;
|
|
|
|
import org.jivesoftware.smackx.jingle.element.JingleReasonElement;
|
|
|
|
import org.jivesoftware.smackx.jingle.exception.UnsupportedDescriptionException;
|
|
|
|
import org.jivesoftware.smackx.jingle.exception.UnsupportedSecurityException;
|
|
|
|
import org.jivesoftware.smackx.jingle.exception.UnsupportedTransportException;
|
2017-07-27 17:35:16 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.util.Role;
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
import org.jxmpp.jid.FullJid;
|
|
|
|
|
|
|
|
/**
|
2017-07-21 23:05:46 +02:00
|
|
|
* Class that represents a Jingle session.
|
2017-07-19 15:17:12 +02:00
|
|
|
*/
|
2017-07-21 23:51:06 +02:00
|
|
|
public class JingleSession {
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(JingleSession.class.getName());
|
2017-07-19 15:17:12 +02:00
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
private final ConcurrentHashMap<String, JingleContent> contents = new ConcurrentHashMap<>();
|
2017-07-19 15:17:12 +02:00
|
|
|
private final JingleManager jingleManager;
|
|
|
|
|
|
|
|
private final FullJid initiator, responder;
|
|
|
|
private final Role role;
|
|
|
|
private final String sessionId;
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
private final Map<JingleContent, PendingJingleAction> pendingJingleActions =
|
|
|
|
Collections.synchronizedMap(new HashMap<JingleContent, PendingJingleAction>());
|
2017-07-19 15:17:12 +02:00
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
public JingleSession(JingleManager manager, FullJid initiator, FullJid responder, Role role, String sessionId) {
|
2017-07-19 15:17:12 +02:00
|
|
|
this.jingleManager = manager;
|
|
|
|
this.initiator = initiator;
|
|
|
|
this.responder = responder;
|
|
|
|
this.role = role;
|
|
|
|
this.sessionId = sessionId;
|
|
|
|
}
|
|
|
|
|
2017-07-27 00:12:42 +02:00
|
|
|
public void addContent(JingleContent content) {
|
2017-07-19 15:17:12 +02:00
|
|
|
contents.put(content.getName(), content);
|
2017-07-21 17:58:57 +02:00
|
|
|
content.setParent(this);
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 00:12:42 +02:00
|
|
|
public void addContent(JingleContentElement content)
|
2017-07-19 15:17:12 +02:00
|
|
|
throws UnsupportedSecurityException, UnsupportedTransportException, UnsupportedDescriptionException {
|
2017-07-21 23:51:06 +02:00
|
|
|
addContent(JingleContent.fromElement(content));
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-27 15:58:11 +02:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
public static JingleSession fromSessionInitiate(JingleManager manager, JingleElement initiate)
|
2017-07-19 15:17:12 +02:00
|
|
|
throws UnsupportedSecurityException, UnsupportedDescriptionException, UnsupportedTransportException {
|
|
|
|
if (initiate.getAction() != JingleAction.session_initiate) {
|
|
|
|
throw new IllegalArgumentException("Jingle-Action MUST be 'session-initiate'.");
|
|
|
|
}
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
JingleSession session = new JingleSession(manager, initiate.getInitiator(), initiate.getResponder(), Role.responder, initiate.getSid());
|
2017-07-19 15:17:12 +02:00
|
|
|
List<JingleContentElement> initiateContents = initiate.getContents();
|
|
|
|
|
|
|
|
for (JingleContentElement content : initiateContents) {
|
|
|
|
session.addContent(content);
|
|
|
|
}
|
|
|
|
|
|
|
|
return session;
|
|
|
|
}
|
|
|
|
|
2017-07-27 00:12:42 +02:00
|
|
|
public JingleElement createSessionInitiate() {
|
|
|
|
if (role != Role.initiator) {
|
|
|
|
throw new IllegalStateException("Sessions role is not initiator.");
|
|
|
|
}
|
|
|
|
|
|
|
|
List<JingleContentElement> contentElements = new ArrayList<>();
|
|
|
|
for (JingleContent c : contents.values()) {
|
|
|
|
contentElements.add(c.getElement());
|
|
|
|
}
|
|
|
|
|
|
|
|
return JingleElement.createSessionInitiate(getInitiator(), getResponder(), getSessionId(), contentElements);
|
|
|
|
}
|
|
|
|
|
2017-07-19 15:17:12 +02:00
|
|
|
public IQ handleJingleRequest(JingleElement request) {
|
|
|
|
switch (request.getAction()) {
|
|
|
|
case content_accept:
|
|
|
|
return handleContentAccept(request);
|
|
|
|
case content_add:
|
|
|
|
return handleContentAdd(request);
|
|
|
|
case content_modify:
|
|
|
|
return handleContentModify(request);
|
|
|
|
case content_reject:
|
|
|
|
return handleContentReject(request);
|
|
|
|
case content_remove:
|
|
|
|
return handleContentRemove(request);
|
|
|
|
case description_info:
|
|
|
|
return handleDescriptionInfo(request);
|
|
|
|
case session_info:
|
|
|
|
return handleSessionInfo(request);
|
|
|
|
case security_info:
|
|
|
|
return handleSecurityInfo(request);
|
|
|
|
case session_accept:
|
|
|
|
return handleSessionAccept(request);
|
|
|
|
case transport_accept:
|
|
|
|
return handleTransportAccept(request);
|
|
|
|
case transport_info:
|
|
|
|
return handleTransportInfo(request);
|
|
|
|
case session_initiate:
|
|
|
|
return handleSessionInitiate(request);
|
|
|
|
case transport_reject:
|
|
|
|
return handleTransportReject(request);
|
|
|
|
case session_terminate:
|
|
|
|
return handleSessionTerminate(request);
|
|
|
|
case transport_replace:
|
|
|
|
return handleTransportReplace(request);
|
|
|
|
default:
|
|
|
|
throw new AssertionError("Unknown Jingle Action enum! " + request.getAction());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-28 00:55:44 +02:00
|
|
|
private IQ handleTransportReplace(final JingleElement request) {
|
|
|
|
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());
|
|
|
|
JingleContentTransportElement newTransport = affected.getTransport();
|
|
|
|
Set<String> blacklist = content.getTransportBlacklist();
|
|
|
|
|
|
|
|
// Proposed transport method might already be on the blacklist (eg. because of previous failures)
|
|
|
|
if (blacklist.contains(newTransport.getNamespace())) {
|
|
|
|
responses.add(JingleElement.createTransportReject(getInitiator(), getPeer(), getSessionId(),
|
|
|
|
content.getCreator(), content.getName(), newTransport));
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
try {
|
|
|
|
jingleManager.getConnection().createStanzaCollectorAndSend(response).nextResultOrThrow();
|
|
|
|
} catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | InterruptedException | SmackException.NotConnectedException e) {
|
|
|
|
LOGGER.log(Level.SEVERE, "Could not send response to transport-replace: " + e, e);
|
|
|
|
}
|
|
|
|
}
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
2017-07-28 00:55:44 +02:00
|
|
|
});
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
return IQ.createResultIQ(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleSessionTerminate(JingleElement request) {
|
|
|
|
JingleReasonElement reason = request.getReason();
|
2017-07-19 23:15:17 +02:00
|
|
|
|
2017-07-19 15:17:12 +02:00
|
|
|
if (reason == null) {
|
|
|
|
throw new AssertionError("Reason MUST not be null! (I guess)...");
|
|
|
|
}
|
2017-07-19 23:15:17 +02:00
|
|
|
|
2017-07-28 00:55:44 +02:00
|
|
|
//TODO: Inform client.
|
|
|
|
|
|
|
|
jingleManager.removeSession(this);
|
|
|
|
|
2017-07-19 15:17:12 +02:00
|
|
|
return IQ.createResultIQ(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleTransportReject(JingleElement request) {
|
2017-07-21 23:51:06 +02:00
|
|
|
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleSessionInitiate(JingleElement request) {
|
2017-07-27 23:59:26 +02:00
|
|
|
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);
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleTransportInfo(JingleElement request) {
|
2017-07-21 23:51:06 +02:00
|
|
|
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
2017-07-19 15:17:12 +02:00
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
|
|
|
JingleTransport<?> transport = entry.getValue().getTransport();
|
2017-07-19 23:15:17 +02:00
|
|
|
JingleContentTransportInfoElement info = entry.getKey().getTransport().getInfo();
|
2017-07-22 00:26:50 +02:00
|
|
|
transport.handleTransportInfo(info, request);
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return IQ.createResultIQ(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleTransportAccept(JingleElement request) {
|
2017-07-21 23:51:06 +02:00
|
|
|
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
|
|
|
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
PendingJingleAction pending = pendingJingleActions.get(entry.getValue());
|
|
|
|
if (pending == null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pending.getAction() != JingleAction.transport_replace) {
|
|
|
|
//TODO: Are multiple contents even possible here?
|
|
|
|
//TODO: How to react to partially illegal requests?
|
|
|
|
return JingleElement.createJingleErrorOutOfOrder(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
entry.getValue().setTransport(((PendingJingleAction.TransportReplace) pending).getNewTransport());
|
|
|
|
}
|
|
|
|
|
|
|
|
return IQ.createResultIQ(request);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleSessionAccept(JingleElement request) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleSecurityInfo(JingleElement request) {
|
2017-07-21 23:51:06 +02:00
|
|
|
HashMap<JingleContentElement, JingleContent> affectedContents = getAffectedContents(request);
|
2017-07-19 15:17:12 +02:00
|
|
|
List<JingleElement> responses = new ArrayList<>();
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
for (Map.Entry<JingleContentElement, JingleContent> entry : affectedContents.entrySet()) {
|
2017-07-27 00:12:42 +02:00
|
|
|
responses.add(entry.getValue().getSecurity().handleSecurityInfo(entry.getKey().getSecurity().getSecurityInfo(), request));
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
2017-07-28 00:55:44 +02:00
|
|
|
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);
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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) {
|
|
|
|
final List<JingleContentElement> proposedContents = request.getContents();
|
|
|
|
final List<JingleContentElement> acceptedContents = new ArrayList<>();
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
final HashMap<String, List<JingleContent>> contentsByDescription = new HashMap<>();
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
for (JingleContentElement p : proposedContents) {
|
|
|
|
JingleContentDescriptionElement description = p.getDescription();
|
2017-07-21 23:51:06 +02:00
|
|
|
List<JingleContent> list = contentsByDescription.get(description.getNamespace());
|
2017-07-19 15:17:12 +02:00
|
|
|
if (list == null) {
|
|
|
|
list = new ArrayList<>();
|
|
|
|
contentsByDescription.put(description.getNamespace(), list);
|
|
|
|
}
|
2017-07-21 23:51:06 +02:00
|
|
|
list.add(JingleContent.fromElement(p));
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
for (Map.Entry<String, List<JingleContent>> descriptionCategory : contentsByDescription.entrySet()) {
|
2017-07-19 23:15:17 +02:00
|
|
|
JingleDescriptionManager descriptionManager = JingleManager.getInstanceFor(getJingleManager().getConnection()).getDescriptionManager(descriptionCategory.getKey());
|
2017-07-19 15:17:12 +02:00
|
|
|
|
|
|
|
if (descriptionManager == null) {
|
|
|
|
//blabla
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
for (final JingleContent content : descriptionCategory.getValue()) {
|
2017-07-27 16:43:09 +02:00
|
|
|
descriptionManager.notifyContentAdd(content);
|
2017-07-19 15:17:12 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
private IQ handleContentAccept(JingleElement request) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
public FullJid getInitiator() {
|
|
|
|
return initiator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public FullJid getResponder() {
|
|
|
|
return responder;
|
|
|
|
}
|
|
|
|
|
|
|
|
public FullJid getPeer() {
|
|
|
|
return role == Role.initiator ? responder : initiator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public FullJid getOurJid() {
|
|
|
|
return role == Role.initiator ? initiator : responder;
|
|
|
|
}
|
|
|
|
|
2017-07-22 00:26:50 +02:00
|
|
|
public boolean isInitiator() {
|
|
|
|
return role == Role.initiator;
|
|
|
|
}
|
|
|
|
|
|
|
|
public boolean isResponder() {
|
|
|
|
return role == Role.responder;
|
|
|
|
}
|
|
|
|
|
2017-07-19 15:17:12 +02:00
|
|
|
public String getSessionId() {
|
|
|
|
return sessionId;
|
|
|
|
}
|
|
|
|
|
|
|
|
public JingleManager getJingleManager() {
|
|
|
|
return jingleManager;
|
|
|
|
}
|
|
|
|
|
2017-07-21 23:51:06 +02:00
|
|
|
private HashMap<JingleContentElement, JingleContent> getAffectedContents(JingleElement request) {
|
|
|
|
HashMap<JingleContentElement, JingleContent> map = new HashMap<>();
|
2017-07-19 15:17:12 +02:00
|
|
|
for (JingleContentElement e : request.getContents()) {
|
2017-07-21 23:51:06 +02:00
|
|
|
JingleContent c = contents.get(e.getName());
|
2017-07-19 15:17:12 +02:00
|
|
|
if (c == null) {
|
|
|
|
throw new AssertionError("Unknown content: " + e.getName());
|
|
|
|
}
|
|
|
|
map.put(e, c);
|
|
|
|
}
|
|
|
|
return map;
|
|
|
|
}
|
2017-07-27 23:31:04 +02:00
|
|
|
}
|