2007-01-04 18:25:30 +01:00
|
|
|
/**
|
|
|
|
*
|
2007-02-12 01:59:05 +01:00
|
|
|
* Copyright 2003-2007 Jive Software.
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
|
|
|
* All rights reserved. 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.packet;
|
|
|
|
|
|
|
|
import org.jivesoftware.smack.packet.IQ;
|
2008-05-20 00:54:19 +02:00
|
|
|
import org.jivesoftware.smackx.jingle.JingleActionEnum;
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An Jingle sub-packet, which is used by XMPP clients to exchange info like
|
|
|
|
* descriptions and transports. <p/> The following link summarizes the
|
|
|
|
* requirements of Jingle IM: <a
|
|
|
|
* href="http://www.jabber.org/jeps/jep-0166.html">Valid tags</a>.
|
|
|
|
* <p/>
|
|
|
|
* <p/> Warning: this is an non-standard protocol documented by <a
|
|
|
|
* href="http://www.jabber.org/jeps/jep-0166.html">JEP-166</a>. Because this is
|
|
|
|
* a non-standard protocol, it is subject to change.
|
|
|
|
*
|
|
|
|
* @author Alvaro Saurin
|
|
|
|
*/
|
|
|
|
public class Jingle extends IQ {
|
|
|
|
|
|
|
|
// static
|
|
|
|
|
2008-10-30 22:20:29 +01:00
|
|
|
public static final String NAMESPACE = "urn:xmpp:tmp:jingle";
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
public static final String NODENAME = "jingle";
|
|
|
|
|
|
|
|
// non-static
|
|
|
|
|
|
|
|
private String sid; // The session id
|
|
|
|
|
2008-05-20 00:54:19 +02:00
|
|
|
private JingleActionEnum action; // The action associated to the Jingle
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
private String initiator; // The initiator as a "user@host/resource"
|
|
|
|
|
|
|
|
private String responder; // The responder
|
|
|
|
|
|
|
|
// Sub-elements of a Jingle object.
|
2008-05-20 00:54:19 +02:00
|
|
|
|
|
|
|
private final List<JingleContent> contents = new ArrayList<JingleContent>();
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
private JingleContentInfo contentInfo;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A constructor where the main components can be initialized.
|
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public Jingle(final List<JingleContent> contents, final JingleContentInfo mi,
|
2007-01-04 18:25:30 +01:00
|
|
|
final String sid) {
|
|
|
|
super();
|
|
|
|
|
2008-05-20 00:54:19 +02:00
|
|
|
if (contents != null) {
|
|
|
|
contents.addAll(contents);
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
setContentInfo(mi);
|
|
|
|
setSid(sid);
|
|
|
|
|
|
|
|
// Set null all other fields in the packet
|
|
|
|
initiator = null;
|
|
|
|
responder = null;
|
|
|
|
action = null;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-05-20 00:54:19 +02:00
|
|
|
* Constructor with a contents.
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
2008-05-20 00:54:19 +02:00
|
|
|
* @param content a content
|
2007-01-04 18:25:30 +01:00
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public Jingle(final JingleContent content) {
|
2007-01-04 18:25:30 +01:00
|
|
|
super();
|
|
|
|
|
2008-05-20 00:54:19 +02:00
|
|
|
addContent(content);
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
// Set null all other fields in the packet
|
|
|
|
initiator = null;
|
|
|
|
responder = null;
|
|
|
|
|
|
|
|
// Some default values for the most common situation...
|
2008-05-20 00:54:19 +02:00
|
|
|
action = JingleActionEnum.UNKNOWN;
|
2007-01-04 18:25:30 +01:00
|
|
|
this.setType(IQ.Type.SET);
|
|
|
|
}
|
|
|
|
|
2008-05-20 00:54:19 +02:00
|
|
|
/**
|
2007-01-04 18:25:30 +01:00
|
|
|
* Constructor with a content info.
|
|
|
|
*
|
|
|
|
* @param info The content info
|
|
|
|
*/
|
|
|
|
public Jingle(final JingleContentInfo info) {
|
|
|
|
super();
|
|
|
|
|
|
|
|
setContentInfo(info);
|
|
|
|
|
|
|
|
// Set null all other fields in the packet
|
|
|
|
initiator = null;
|
|
|
|
responder = null;
|
|
|
|
|
|
|
|
// Some default values for the most common situation...
|
2008-05-20 00:54:19 +02:00
|
|
|
action = JingleActionEnum.UNKNOWN;
|
2007-01-04 18:25:30 +01:00
|
|
|
this.setType(IQ.Type.SET);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A constructor where the action can be specified.
|
|
|
|
*
|
|
|
|
* @param action The action.
|
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public Jingle(final JingleActionEnum action) {
|
|
|
|
this(null, null, null);
|
2007-01-04 18:25:30 +01:00
|
|
|
this.action = action;
|
|
|
|
|
|
|
|
// In general, a Jingle with an action is used in a SET packet...
|
|
|
|
this.setType(IQ.Type.SET);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A constructor where the session ID can be specified.
|
|
|
|
*
|
|
|
|
* @param sid The session ID related to the negotiation.
|
|
|
|
* @see #setSid(String)
|
|
|
|
*/
|
|
|
|
public Jingle(final String sid) {
|
2008-05-20 00:54:19 +02:00
|
|
|
this(null, null, sid);
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The default constructor
|
|
|
|
*/
|
|
|
|
public Jingle() {
|
|
|
|
super();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the session ID related to this session. The session ID is a unique
|
|
|
|
* identifier generated by the initiator. This should match the XML Nmtoken
|
|
|
|
* production so that XML character escaping is not needed for characters
|
|
|
|
* such as &.
|
|
|
|
*
|
|
|
|
* @param sid the session ID
|
|
|
|
*/
|
|
|
|
public final void setSid(final String sid) {
|
|
|
|
this.sid = sid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the session ID related to the session. The session ID is a unique
|
|
|
|
* identifier generated by the initiator. This should match the XML Nmtoken
|
|
|
|
* production so that XML character escaping is not needed for characters
|
|
|
|
* such as &.
|
|
|
|
*
|
|
|
|
* @return Returns the session ID related to the session.
|
|
|
|
* @see #setSid(String)
|
|
|
|
*/
|
|
|
|
public String getSid() {
|
|
|
|
|
|
|
|
return sid;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the XML element name of the extension sub-packet root element.
|
|
|
|
* Always returns "jingle"
|
|
|
|
*
|
|
|
|
* @return the XML element name of the packet extension.
|
|
|
|
*/
|
|
|
|
public static String getElementName() {
|
|
|
|
return NODENAME;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns the XML namespace of the extension sub-packet root element.
|
|
|
|
*
|
|
|
|
* @return the XML namespace of the packet extension.
|
|
|
|
*/
|
|
|
|
public static String getNamespace() {
|
|
|
|
return NAMESPACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @return the audioInfo
|
|
|
|
*/
|
|
|
|
public JingleContentInfo getContentInfo() {
|
|
|
|
return contentInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param contentInfo the audioInfo to set
|
|
|
|
*/
|
|
|
|
public void setContentInfo(final JingleContentInfo contentInfo) {
|
|
|
|
this.contentInfo = contentInfo;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-05-20 00:54:19 +02:00
|
|
|
* Get an iterator for the contents
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
2008-05-20 00:54:19 +02:00
|
|
|
* @return the contents
|
2007-01-04 18:25:30 +01:00
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public Iterator<JingleContent> getContents() {
|
|
|
|
synchronized (contents) {
|
2012-10-26 12:47:55 +02:00
|
|
|
return Collections.unmodifiableList(new ArrayList<JingleContent>(contents)).iterator();
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-05-20 00:54:19 +02:00
|
|
|
* Get an iterator for the content
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
2008-05-20 00:54:19 +02:00
|
|
|
* @return the contents
|
2007-01-04 18:25:30 +01:00
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public List<JingleContent> getContentsList() {
|
|
|
|
synchronized (contents) {
|
|
|
|
return new ArrayList<JingleContent>(contents);
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-05-20 00:54:19 +02:00
|
|
|
* Add a new content.
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
2008-05-20 00:54:19 +02:00
|
|
|
* @param content the content to add
|
2007-01-04 18:25:30 +01:00
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public void addContent(final JingleContent content) {
|
|
|
|
if (content != null) {
|
|
|
|
synchronized (contents) {
|
|
|
|
contents.add(content);
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2008-05-20 00:54:19 +02:00
|
|
|
* Add a list of JingleContent elements
|
2007-01-04 18:25:30 +01:00
|
|
|
*
|
2008-05-20 00:54:19 +02:00
|
|
|
* @param contentList the list of contents to add
|
2007-01-04 18:25:30 +01:00
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public void addContents(final List<JingleContent> contentList) {
|
|
|
|
if (contentList != null) {
|
|
|
|
synchronized (contents) {
|
|
|
|
contents.addAll(contentList);
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-05-20 00:54:19 +02:00
|
|
|
/**
|
2007-01-04 18:25:30 +01:00
|
|
|
* Get the action specified in the packet
|
|
|
|
*
|
|
|
|
* @return the action
|
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public JingleActionEnum getAction() {
|
2007-01-04 18:25:30 +01:00
|
|
|
return action;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the action in the packet
|
|
|
|
*
|
|
|
|
* @param action the action to set
|
|
|
|
*/
|
2008-05-20 00:54:19 +02:00
|
|
|
public void setAction(final JingleActionEnum action) {
|
2007-01-04 18:25:30 +01:00
|
|
|
this.action = action;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the initiator. The initiator will be the full JID of the entity that
|
|
|
|
* has initiated the flow (which may be different to the "from" address in
|
|
|
|
* the IQ)
|
|
|
|
*
|
|
|
|
* @return the initiator
|
|
|
|
*/
|
|
|
|
public String getInitiator() {
|
|
|
|
return initiator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the initiator. The initiator must be the full JID of the entity that
|
|
|
|
* has initiated the flow (which may be different to the "from" address in
|
|
|
|
* the IQ)
|
|
|
|
*
|
|
|
|
* @param initiator the initiator to set
|
|
|
|
*/
|
|
|
|
public void setInitiator(final String initiator) {
|
|
|
|
this.initiator = initiator;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the responder. The responder is the full JID of the entity that has
|
|
|
|
* replied to the initiation (which may be different to the "to" addresss in
|
|
|
|
* the IQ).
|
|
|
|
*
|
|
|
|
* @return the responder
|
|
|
|
*/
|
|
|
|
public String getResponder() {
|
|
|
|
return responder;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Set the responder. The responder must be the full JID of the entity that
|
|
|
|
* has replied to the initiation (which may be different to the "to"
|
|
|
|
* addresss in the IQ).
|
|
|
|
*
|
|
|
|
* @param resp the responder to set
|
|
|
|
*/
|
|
|
|
public void setResponder(final String resp) {
|
|
|
|
responder = resp;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a hash key for the session this packet belongs to.
|
|
|
|
*
|
|
|
|
* @param sid The session id
|
|
|
|
* @param initiator The initiator
|
|
|
|
* @return A hash key
|
|
|
|
*/
|
|
|
|
public static int getSessionHash(final String sid, final String initiator) {
|
|
|
|
final int PRIME = 31;
|
|
|
|
int result = 1;
|
|
|
|
result = PRIME * result + (initiator == null ? 0 : initiator.hashCode());
|
|
|
|
result = PRIME * result + (sid == null ? 0 : sid.hashCode());
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the XML representation of the packet.
|
|
|
|
*
|
|
|
|
* @return the XML string
|
|
|
|
*/
|
|
|
|
public String getChildElementXML() {
|
|
|
|
StringBuilder buf = new StringBuilder();
|
|
|
|
|
|
|
|
buf.append("<").append(getElementName());
|
|
|
|
buf.append(" xmlns=\"").append(getNamespace()).append("\"");
|
|
|
|
if (getInitiator() != null) {
|
|
|
|
buf.append(" initiator=\"").append(getInitiator()).append("\"");
|
|
|
|
}
|
|
|
|
if (getResponder() != null) {
|
|
|
|
buf.append(" responder=\"").append(getResponder()).append("\"");
|
|
|
|
}
|
|
|
|
if (getAction() != null) {
|
|
|
|
buf.append(" action=\"").append(getAction()).append("\"");
|
|
|
|
}
|
|
|
|
if (getSid() != null) {
|
|
|
|
buf.append(" sid=\"").append(getSid()).append("\"");
|
|
|
|
}
|
|
|
|
buf.append(">");
|
2008-05-20 00:54:19 +02:00
|
|
|
|
|
|
|
synchronized (contents) {
|
|
|
|
for (JingleContent content : contents) {
|
|
|
|
buf.append(content.toXML());
|
2007-01-04 18:25:30 +01:00
|
|
|
}
|
2008-05-20 00:54:19 +02:00
|
|
|
}
|
2007-01-04 18:25:30 +01:00
|
|
|
|
|
|
|
// and the same for audio jmf info
|
|
|
|
if (contentInfo != null) {
|
|
|
|
buf.append(contentInfo.toXML());
|
|
|
|
}
|
|
|
|
|
|
|
|
buf.append("</").append(getElementName()).append(">");
|
|
|
|
return buf.toString();
|
|
|
|
}
|
|
|
|
}
|