aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/java/sip/communicator/impl/protocol/jabber/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/java/sip/communicator/impl/protocol/jabber/extensions')
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java11
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java113
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java10
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java629
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java69
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java131
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java144
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java134
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java (renamed from src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java)21
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java94
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java413
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java112
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java121
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java126
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java93
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java878
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java12
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java21
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java25
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java196
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java135
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java15
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java70
23 files changed, 2677 insertions, 896 deletions
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java
index 1285581..778d086 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/DefaultPacketExtensionProvider.java
@@ -19,6 +19,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions;
import java.util.logging.*;
+import net.java.sip.communicator.service.protocol.jabber.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import org.xmlpull.v1.*;
@@ -41,6 +42,13 @@ public class DefaultPacketExtensionProvider<C extends AbstractPacketExtension>
.getLogger(DefaultPacketExtensionProvider.class.getName());
/**
+ * The <tt>AbstractSmackInteroperabilityLayer</tt> instance implementing
+ * necessary methods
+ */
+ private AbstractSmackInteroperabilityLayer smackInteroperabilityLayer =
+ AbstractSmackInteroperabilityLayer.getInstance();
+
+ /**
* The {@link Class} that the packets we will be parsing here belong to.
*/
private final Class<C> packetClass;
@@ -100,8 +108,7 @@ public class DefaultPacketExtensionProvider<C extends AbstractPacketExtension>
if (eventType == XmlPullParser.START_TAG)
{
- PacketExtensionProvider provider
- = (PacketExtensionProvider)ProviderManager.getInstance()
+ PacketExtensionProvider provider = smackInteroperabilityLayer
.getExtensionProvider( elementName, namespace );
if(provider == null)
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
index ebdcbb0..97d9ff8 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/EntityCapsManager.java
@@ -243,6 +243,7 @@ public class EntityCapsManager
if ((user != null) && (node != null) && (hash != null) && (ver != null))
{
Caps caps = userCaps.get(user);
+ String bareJid=StringUtils.parseBareAddress(user);
if ((caps == null)
|| !caps.node.equals(node)
@@ -270,7 +271,9 @@ public class EntityCapsManager
String nodeVer = caps.getNodeVer();
for (UserCapsNodeListener listener : listeners)
- listener.userCapsNodeAdded(user, nodeVer, online);
+ listener.userCapsNodeAdded(user,
+ getFullJidsByBareJid(bareJid),
+ nodeVer, online);
}
}
}
@@ -305,6 +308,8 @@ public class EntityCapsManager
{
Caps caps = null;
String lastRemovedJid = null;
+ String bareJid=StringUtils.parseBareAddress(
+ contact.getAddress());
Iterator<String> iter = userCaps.keySet().iterator();
while(iter.hasNext())
@@ -337,7 +342,9 @@ public class EntityCapsManager
for (UserCapsNodeListener listener : listeners)
listener.userCapsNodeRemoved(
- lastRemovedJid, nodeVer, false);
+ lastRemovedJid,
+ getFullJidsByBareJid(bareJid),
+ nodeVer, false);
}
}
}
@@ -350,6 +357,7 @@ public class EntityCapsManager
public void removeUserCapsNode(String user)
{
Caps caps = userCaps.remove(user);
+ String bareJid=StringUtils.parseBareAddress(user);
// Fire userCapsNodeRemoved.
if (caps != null)
@@ -367,7 +375,9 @@ public class EntityCapsManager
String nodeVer = caps.getNodeVer();
for (UserCapsNodeListener listener : listeners)
- listener.userCapsNodeRemoved(user, nodeVer, false);
+ listener.userCapsNodeRemoved(user,
+ getFullJidsByBareJid(bareJid),
+ nodeVer, false);
}
}
}
@@ -404,6 +414,24 @@ public class EntityCapsManager
{
return userCaps.get(user);
}
+
+ /**
+ * Gets the full Jids (with resources) as Strings.
+ *
+ * @param the bare Jid
+ * @return the full Jids as an ArrayList <tt>user</tt>
+ */
+ public ArrayList<String> getFullJidsByBareJid(String bareJid)
+ {
+ ArrayList<String> jids = new ArrayList<String>();
+ for(String jid: userCaps.keySet())
+ {
+ if(bareJid.equals(StringUtils.parseBareAddress(jid))){
+ jids.add(jid);
+ }
+ }
+ return jids;
+ }
/**
* Get the discover info given a user name. The discover info is returned if
@@ -605,14 +633,9 @@ public class EntityCapsManager
* @param connection the connection that we'd like this manager to register
* with.
*/
- public void addPacketListener(XMPPConnection connection)
+ public void addPacketListener(Connection connection)
{
- PacketFilter filter
- = new AndFilter(
- new PacketTypeFilter(Presence.class),
- new PacketExtensionFilter(
- CapsPacketExtension.ELEMENT_NAME,
- CapsPacketExtension.NAMESPACE));
+ PacketFilter filter = new PacketTypeFilter(Presence.class);
connection.addPacketListener(new CapsPacketListener(), filter);
}
@@ -913,48 +936,48 @@ public class EntityCapsManager
*/
public void processPacket(Packet packet)
{
+ // Check it the packet indicates that the user is online. We
+ // will use this information to decide if we're going to send
+ // the discover info request.
+ boolean online
+ = (packet instanceof Presence)
+ && ((Presence) packet).isAvailable();
+
CapsPacketExtension ext
= (CapsPacketExtension)
packet.getExtension(
CapsPacketExtension.ELEMENT_NAME,
CapsPacketExtension.NAMESPACE);
- /*
- * Before Version 1.4 of XEP-0115: Entity Capabilities, the 'ver'
- * attribute was generated differently and the 'hash' attribute was
- * absent. The 'ver' attribute in Version 1.3 represents the
- * specific version of the client and thus does not provide a way to
- * validate the DiscoverInfo sent by the client. If
- * EntityCapsManager receives no 'hash' attribute, it will assume
- * the legacy format and will not cache it because the DiscoverInfo
- * to be received from the client later on will not be trustworthy.
- */
- String hash = ext.getHash();
-
- /* Google Talk web does not set hash but we need it to be cached */
- if(hash == null)
- hash = "";
-
- if (hash != null)
+ if(ext != null && online)
{
- // Check it the packet indicates that the user is online. We
- // will use this information to decide if we're going to send
- // the discover info request.
- boolean online
- = (packet instanceof Presence)
- && ((Presence) packet).isAvailable();
-
- if(online)
- {
- addUserCapsNode(
- packet.getFrom(),
- ext.getNode(), hash, ext.getVersion(),
- ext.getExtensions(), online);
- }
- else
- {
- removeUserCapsNode(packet.getFrom());
- }
+ /*
+ * Before Version 1.4 of XEP-0115: Entity Capabilities,
+ * the 'ver' attribute was generated differently and the 'hash'
+ * attribute was absent. The 'ver' attribute in Version 1.3
+ * represents the specific version of the client and thus does
+ * not provide a way to validate the DiscoverInfo sent by
+ * the client. If EntityCapsManager receives no 'hash'
+ * attribute, it will assume the legacy format and will not
+ * cache it because the DiscoverInfo to be received from
+ * the client later on will not be trustworthy.
+ */
+ String hash = ext.getHash();
+
+ /* Google Talk web does not set hash, but we need it to
+ * be cached
+ */
+ if (hash == null)
+ hash = "";
+
+ addUserCapsNode(
+ packet.getFrom(),
+ ext.getNode(), hash, ext.getVersion(),
+ ext.getExtensions(), online);
+ }
+ else if (!online)
+ {
+ removeUserCapsNode(packet.getFrom());
}
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java
index 5ee38b0..eda921f 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/caps/UserCapsNodeListener.java
@@ -17,6 +17,8 @@
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.caps;
+import java.util.ArrayList;
+
/**
* Represents a listener of events notifying about changes in the list of user
* caps nodes of <tt>EntityCapsManager</tt>.
@@ -30,18 +32,22 @@ public interface UserCapsNodeListener
* record for a specific user about the caps node the user has.
*
* @param user the user (full JID)
+ * @param fullJids a list of all resources of the user (full JIDs)
* @param node the entity caps node#ver
* @param online indicates if the user for which we're notified is online
*/
- public void userCapsNodeAdded(String user, String node, boolean online);
+ public void userCapsNodeAdded(String user, ArrayList<String> fullJids,
+ String node, boolean online);
/**
* Notifies this listener that an <tt>EntityCapsManager</tt> has removed a
* record for a specific user about the caps node the user has.
*
* @param user the user (full JID)
+ * @param fullJids a list of all resources of the user (full JIDs)
* @param node the entity caps node#ver
* @param online indicates if the user for which we're notified is online
*/
- public void userCapsNodeRemoved(String user, String node, boolean online);
+ public void userCapsNodeRemoved(String user, ArrayList<String> fullJids,
+ String node, boolean online);
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
index 547ebe8..48207c2 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriBuilder.java
@@ -37,9 +37,9 @@ import java.util.*;
* Add one or multiple requests of the same type by calling
* {@link #addAllocateChannelsReq(boolean, String, boolean, java.util.List)}}
* or {@link #addExpireChannelsReq(ColibriConferenceIQ)}
- * or {@link #addTransportUpdateReq(boolean, java.util.Map, ColibriConferenceIQ)}
- * or {@link #addBundleTransportUpdateReq(
- * boolean, IceUdpTransportPacketExtension, ColibriConferenceIQ)}.
+ * or {@link #addRtpDescription(Map, ColibriConferenceIQ)}
+ * and {@link #addSSSRCGroupsInfo(Map, ColibriConferenceIQ)}
+ * and {@link #addSSSRCInfo(Map, ColibriConferenceIQ)}.
* </li>
* <li>
* Compile the request by calling {@link #getRequest(String)}. Then send it to
@@ -119,6 +119,20 @@ public class ColibriBuilder
private SimulcastMode simulcastMode;
/**
+ * Specifies the audio packet delay that will be set on all created audio
+ * channels. When set to <tt>null</tt> the builder will clear the attribute
+ * which stands for 'undefined'.
+ **/
+ private Integer audioPacketDelay;
+
+ /**
+ * Channel 'rtp-level-relay-type' option that will be used with all created
+ * audio channel. Possible values: mixer or translator (default).
+ *
+ */
+ private RTPLevelRelayType rtpLevelRelayType;
+
+ /**
* Creates new instance of {@link ColibriBuilder} for given
* <tt>conferenceState</tt>.
*
@@ -161,18 +175,26 @@ public class ColibriBuilder
* @param contents the list of {@link ContentPacketExtension} describing
* channels media.
*
- * @return this instance fo calls chaining purpose.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
*/
- public ColibriBuilder addAllocateChannelsReq(
- boolean useBundle,
- String endpointName,
- boolean peerIsInitiator,
+ public boolean addAllocateChannelsReq(
+ boolean useBundle,
+ String endpointName,
+ boolean peerIsInitiator,
List<ContentPacketExtension> contents)
{
+ Objects.requireNonNull(endpointName, "endpointName");
+ Objects.requireNonNull(contents, "contents");
+
assertRequestType(RequestType.ALLOCATE_CHANNELS);
request.setType(IQ.Type.GET);
+ boolean hasAnyChanges = false;
+
for (ContentPacketExtension cpe : contents)
{
MediaType mediaType = JingleUtils.getMediaType(cpe);
@@ -193,7 +215,7 @@ public class ColibriBuilder
remoteChannelRequest.setChannelBundleId(endpointName);
}
- if (mediaType != MediaType.DATA)
+ if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel)
{
RtpDescriptionPacketExtension rdpe
= cpe.getFirstChildOfType(
@@ -213,6 +235,13 @@ public class ColibriBuilder
remoteRtpChannelRequest.setAdaptiveLastN(adaptiveLastN);
remoteRtpChannelRequest.setAdaptiveSimulcast(adaptiveSimulcast);
remoteRtpChannelRequest.setSimulcastMode(simulcastMode);
+ if (MediaType.AUDIO.equals(mediaType))
+ {
+ // When audioPacketDelay is null it will clear the attribute
+ remoteRtpChannelRequest.setPacketDelay(audioPacketDelay);
+ // Set rtp packet relay type for this channel
+ remoteRtpChannelRequest.setRTPLevelRelayType(rtpLevelRelayType);
+ }
}
// Copy transport
@@ -221,13 +250,17 @@ public class ColibriBuilder
copyTransportOnChannel(cpe, remoteChannelRequest);
}
- if (mediaType != MediaType.DATA)
+ if (remoteChannelRequest instanceof ColibriConferenceIQ.Channel)
{
+ hasAnyChanges = true;
+
contentRequest.addChannel(
(ColibriConferenceIQ.Channel) remoteChannelRequest);
}
else
{
+ hasAnyChanges = true;
+
contentRequest.addSctpConnection(
(ColibriConferenceIQ.SctpConnection) remoteChannelRequest);
}
@@ -246,6 +279,8 @@ public class ColibriBuilder
IceUdpTransportPacketExtension.class);
if (transport != null)
{
+ hasAnyChanges = true;
+
bundle.setTransport(
IceUdpTransportPacketExtension
.cloneTransportAndCandidates(transport, true));
@@ -254,106 +289,38 @@ public class ColibriBuilder
request.addChannelBundle(bundle);
}
- return this;
- }
-
- /**
- * Adds next ICE transport update request to
- * {@link RequestType#TRANSPORT_UPDATE} query currently being built.
- *
- * @param initiator the value that will be set in 'initiator'
- * attribute({@link ColibriConferenceIQ.Channel#initiator}).
- * @param map the map of content name to transport extensions. Maps
- * transport to media types.
- * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
- * Colibri channels to be updated.
- *
- * @return this instance fo calls chaining purpose.
- */
- public ColibriBuilder addTransportUpdateReq(
- boolean initiator,
- Map<String, IceUdpTransportPacketExtension> map,
- ColibriConferenceIQ localChannelsInfo)
- {
- if (conferenceState == null
- || StringUtils.isNullOrEmpty(conferenceState.getID()))
- {
- // We are not initialized yet
- return null;
- }
-
- assertRequestType(RequestType.TRANSPORT_UPDATE);
-
- request.setType(IQ.Type.SET);
-
- for (Map.Entry<String,IceUdpTransportPacketExtension> e
- : map.entrySet())
- {
- String contentName = e.getKey();
- ColibriConferenceIQ.ChannelCommon channel
- = getColibriChannel(localChannelsInfo, contentName);
-
- if (channel != null)
- {
- IceUdpTransportPacketExtension transport
- = IceUdpTransportPacketExtension
- .cloneTransportAndCandidates(e.getValue(), true);
-
- ColibriConferenceIQ.ChannelCommon channelRequest
- = channel instanceof ColibriConferenceIQ.Channel
- ? new ColibriConferenceIQ.Channel()
- : new ColibriConferenceIQ.SctpConnection();
-
- channelRequest.setID(channel.getID());
- channelRequest.setEndpoint(channel.getEndpoint());
- channelRequest.setInitiator(initiator);
- channelRequest.setTransport(transport);
-
- if (channelRequest instanceof ColibriConferenceIQ.Channel)
- {
- request.getOrCreateContent(contentName)
- .addChannel(
- (ColibriConferenceIQ.Channel) channelRequest);
- }
- else
- {
- request.getOrCreateContent(contentName)
- .addSctpConnection(
- (ColibriConferenceIQ.SctpConnection) channelRequest);
- }
- }
- }
- return this;
+ return hasAnyChanges;
}
/**
- * Adds next request to {@link RequestType#BUNDLE_TRANSPORT_UPDATE} query.
- * @param initiator the value that will be set in 'initiator'
- * attribute({@link ColibriConferenceIQ.Channel#initiator}).
+ * Adds next request to {@link RequestType#CHANNEL_INFO_UPDATE} query.
* @param localChannelsInfo the {@link ColibriConferenceIQ} instance that
* describes the channel for which bundle transport will be updated.
* It should contain the description of only one "channel bundle".
* If it contains more than one then the first one will be used.
- * @return this instance for calls chaining purpose.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
* @throws IllegalArgumentException if <tt>localChannelsInfo</tt> does not
* describe any channel bundles.
*/
- public ColibriBuilder addBundleTransportUpdateReq(
- boolean initiator,
- IceUdpTransportPacketExtension transport,
- ColibriConferenceIQ localChannelsInfo)
+ public boolean addBundleTransportUpdateReq(
+ IceUdpTransportPacketExtension transport,
+ ColibriConferenceIQ localChannelsInfo)
throws IllegalArgumentException
{
- // FIXME:'initiator' not used on bundle transport update ?
+ Objects.requireNonNull(transport, "transport");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
if (conferenceState == null
|| StringUtils.isNullOrEmpty(conferenceState.getID()))
{
// We are not initialized yet
- return null;
+ return false;
}
- assertRequestType(RequestType.BUNDLE_TRANSPORT_UPDATE);
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
request.setType(IQ.Type.SET);
@@ -371,7 +338,7 @@ public class ColibriBuilder
else
{
throw new IllegalArgumentException(
- "Expected ChannelBundle as not found");
+ "Expected ChannelBundle as not found");
}
ColibriConferenceIQ.ChannelBundle bundleUpdate
@@ -387,7 +354,7 @@ public class ColibriBuilder
request.addChannelBundle(bundleUpdate);
- return this;
+ return true;
}
/**
@@ -395,15 +362,20 @@ public class ColibriBuilder
* {@link RequestType#EXPIRE_CHANNELS} query currently being built.
* @param channelInfo the {@link ColibriConferenceIQ} instance that contains
* info about the channels to be expired.
- * @return this instance for the purpose of calls chaining.
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
*/
- public ColibriBuilder addExpireChannelsReq(ColibriConferenceIQ channelInfo)
+ public boolean addExpireChannelsReq(ColibriConferenceIQ channelInfo)
{
+ Objects.requireNonNull(channelInfo, "channelInfo");
+
// Formulate the ColibriConferenceIQ request which is to be sent.
if (conferenceState == null
|| StringUtils.isNullOrEmpty(conferenceState.getID()))
{
- return null;
+ return false;
}
assertRequestType(RequestType.EXPIRE_CHANNELS);
@@ -411,7 +383,7 @@ public class ColibriBuilder
request.setType(IQ.Type.SET);
for (ColibriConferenceIQ.Content expiredContent
- : channelInfo.getContents())
+ : channelInfo.getContents())
{
ColibriConferenceIQ.Content stateContent
= conferenceState.getContent(expiredContent.getName());
@@ -420,7 +392,7 @@ public class ColibriBuilder
{
ColibriConferenceIQ.Content requestContent
= request.getOrCreateContent(
- stateContent.getName());
+ stateContent.getName());
for (ColibriConferenceIQ.Channel expiredChannel
: expiredContent.getChannels())
@@ -490,7 +462,7 @@ public class ColibriBuilder
*/
/*if (stateContent.getChannelCount() == 1)
{
- stateChannel = stateContent.getChannel(0);
+ stateChannel = stateContent.getRtpChannel(0);
ColibriConferenceIQ.Channel channelRequest
= new ColibriConferenceIQ.Channel();
@@ -537,7 +509,294 @@ public class ColibriBuilder
}
}
- return this;
+ return hasAnyChannelsToExpire;
+ }
+
+ /**
+ * Adds next payload type information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param map the map of content name to RTP description packet extension.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addRtpDescription(
+ Map<String, RtpDescriptionPacketExtension> map,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(map, "map");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ for (Map.Entry<String, RtpDescriptionPacketExtension> e
+ : map.entrySet())
+ {
+ String contentName = e.getKey();
+ ColibriConferenceIQ.ChannelCommon channel
+ = getColibriChannel(localChannelsInfo, contentName);
+
+ if (channel != null
+ && channel instanceof ColibriConferenceIQ.Channel)
+ {
+ RtpDescriptionPacketExtension rtpPE = e.getValue();
+ if (rtpPE == null)
+ {
+ continue;
+ }
+
+ List<PayloadTypePacketExtension> pts = rtpPE.getPayloadTypes();
+ if (pts == null || pts.isEmpty())
+ {
+ continue;
+ }
+
+ anyUpdates = true;
+
+ ColibriConferenceIQ.Channel channelRequest
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName),
+ channel);
+ if (channelRequest == null)
+ {
+ channelRequest = new ColibriConferenceIQ.Channel();
+ channelRequest.setID(channel.getID());
+ }
+
+ for (PayloadTypePacketExtension ptPE : pts)
+ {
+ channelRequest.addPayloadType(ptPE);
+ }
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next SSRC information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param ssrcMap the map of content name to the list of
+ * <tt>SourcePacketExtension</tt>.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addSSSRCInfo(
+ Map<String, List<SourcePacketExtension>> ssrcMap,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(ssrcMap, "ssrcMap");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ // Go over SSRCs
+ for (String contentName : ssrcMap.keySet())
+ {
+ // Get channel from local channel info
+ ColibriConferenceIQ.ChannelCommon rtpChanel
+ = getRtpChannel(localChannelsInfo, contentName);
+ if (rtpChanel == null)
+ {
+ // There's no channel for this content name in localChannelsInfo
+ continue;
+ }
+
+ anyUpdates = true;
+
+ // Ok we have channel for this content, let's add SSRCs
+ ColibriConferenceIQ.Channel reqChannel
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName), rtpChanel);
+
+ for (SourcePacketExtension ssrc : ssrcMap.get(contentName))
+ {
+ reqChannel.addSource(ssrc.copy());
+ }
+
+ if (reqChannel.getSources() == null
+ || reqChannel.getSources().isEmpty())
+ {
+ // Put an empty source to remove all sources
+ SourcePacketExtension emptySource = new SourcePacketExtension();
+ emptySource.setSSRC(-1L);
+ reqChannel.addSource(emptySource);
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next SSRC group information update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param ssrcGroupMap the map of content name to the list of
+ * <tt>SourceGroupPacketExtension</tt>.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addSSSRCGroupsInfo(
+ Map<String, List<SourceGroupPacketExtension>> ssrcGroupMap,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(ssrcGroupMap, "ssrcGroupMap");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ boolean anyUpdates = false;
+
+ // Go over SSRC groups
+ for (String contentName : ssrcGroupMap.keySet())
+ {
+ // Get channel from local channel info
+ ColibriConferenceIQ.Channel rtpChannel
+ = getRtpChannel(localChannelsInfo, contentName);
+ if (rtpChannel == null)
+ {
+ // There's no channel for this content name in localChannelsInfo
+ continue;
+ }
+
+ List<SourceGroupPacketExtension> groups
+ = ssrcGroupMap.get(contentName);
+
+ // Ok we have channel for this content, let's add SSRCs
+ ColibriConferenceIQ.Channel reqChannel
+ = (ColibriConferenceIQ.Channel) getRequestChannel(
+ request.getOrCreateContent(contentName), rtpChannel);
+
+ if (groups.isEmpty() && "video".equalsIgnoreCase(contentName))
+ {
+ anyUpdates = true;
+
+ // Put empty source group to turn off simulcast layers
+ reqChannel.addSourceGroup(
+ SourceGroupPacketExtension.createSimulcastGroup());
+ }
+
+ for (SourceGroupPacketExtension group : groups)
+ {
+ anyUpdates = true;
+
+ reqChannel.addSourceGroup(group);
+ }
+ }
+
+ return anyUpdates;
+ }
+
+ /**
+ * Adds next ICE transport update request to
+ * {@link RequestType#CHANNEL_INFO_UPDATE} query currently being built.
+ *
+ * @param map the map of content name to transport extensions. Maps
+ * transport to media types.
+ * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
+ * Colibri channels to be updated.
+ *
+ * @return <tt>true</tt> if the request yields any changes in Colibri
+ * channels state on the bridge or <tt>false</tt> otherwise.
+ * In general when <tt>false</tt> is returned for all
+ * combined requests it makes no sense to send it.
+ */
+ public boolean addTransportUpdateReq(
+ Map<String, IceUdpTransportPacketExtension> map,
+ ColibriConferenceIQ localChannelsInfo)
+ {
+ Objects.requireNonNull(map, "map");
+ Objects.requireNonNull(localChannelsInfo, "localChannelsInfo");
+
+ if (conferenceState == null
+ || StringUtils.isNullOrEmpty(conferenceState.getID()))
+ {
+ // We are not initialized yet
+ return false;
+ }
+
+ boolean hasAnyChanges = false;
+
+ assertRequestType(RequestType.CHANNEL_INFO_UPDATE);
+
+ request.setType(IQ.Type.SET);
+
+ for (Map.Entry<String,IceUdpTransportPacketExtension> e
+ : map.entrySet())
+ {
+ String contentName = e.getKey();
+ ColibriConferenceIQ.ChannelCommon channel
+ = getColibriChannel(localChannelsInfo, contentName);
+
+ if (channel != null)
+ {
+ IceUdpTransportPacketExtension transport
+ = IceUdpTransportPacketExtension
+ .cloneTransportAndCandidates(e.getValue(), true);
+
+ ColibriConferenceIQ.ChannelCommon channelRequest
+ = channel instanceof ColibriConferenceIQ.Channel
+ ? new ColibriConferenceIQ.Channel()
+ : new ColibriConferenceIQ.SctpConnection();
+
+ channelRequest.setID(channel.getID());
+ channelRequest.setEndpoint(channel.getEndpoint());
+ channelRequest.setTransport(transport);
+
+ request.getOrCreateContent(contentName)
+ .addChannelCommon(channelRequest);
+
+ hasAnyChanges = true;
+ }
+ }
+ return hasAnyChanges;
}
/**
@@ -583,10 +842,12 @@ public class ColibriBuilder
request.setTo(videobridge);
- if (requestType == RequestType.EXPIRE_CHANNELS
- && !hasAnyChannelsToExpire)
+ if (requestType == RequestType.EXPIRE_CHANNELS)
{
- return null;
+ if (!hasAnyChannelsToExpire)
+ return null;
+
+ hasAnyChannelsToExpire = false;
}
return request;
@@ -720,6 +981,28 @@ public class ColibriBuilder
}
/**
+ * Returns an <tt>Integer</tt> which stands for the audio packet delay
+ * that will be set on all created audio channels or <tt>null</tt> if
+ * the builder should leave not include the XML attribute at all.
+ */
+ public Integer getAudioPacketDelay()
+ {
+ return audioPacketDelay;
+ }
+
+ /**
+ * Configures audio channels packet delay.
+ * @param audioPacketDelay an <tt>Integer</tt> value which stands for
+ * the audio packet delay that will be set on all created audio channels or
+ * <tt>null</tt> if the builder should not set that channel property to any
+ * value.
+ */
+ public void setAudioPacketDelay(Integer audioPacketDelay)
+ {
+ this.audioPacketDelay = audioPacketDelay;
+ }
+
+ /**
* Sets channel 'simulcast-mode' option that will be added to the
* request when channels are created.
* @param simulcastMode a <tt>SimulcastMode</tt> value to specify
@@ -732,69 +1015,64 @@ public class ColibriBuilder
}
/**
- * Adds next payload type information update request to
- * {@link RequestType#RTP_DESCRIPTION_UPDATE} query currently being built.
+ * Creates a new instance of <tt>localChannelInfo</tt> and initializes only
+ * the fields required to identify particular Colibri channel on the bridge.
+ * This instance is meant to be used in Colibri
+ * {@link RequestType#CHANNEL_INFO_UPDATE} requests. This instance is also
+ * added to given <tt>requestContent</tt> which used to construct current
+ * request.
*
- * @param map the map of content name to RTP description packet extension.
- * @param localChannelsInfo {@link ColibriConferenceIQ} holding info about
- * Colibri channels to be updated.
+ * @param requestContent <tt>Content</tt> of Colibri update request to which
+ * new instance wil be automatically added after has been created.
+ * @param localChannelInfo the original channel for which "update request"
+ * equivalent is to be created with this call.
*
- * @return this instance for calls chaining purpose.
+ * @return new instance of <tt>localChannelInfo</tt> and initialized with
+ * only those fields required to identify particular Colibri channel on
+ * the bridge.
*/
- public ColibriBuilder addRtpDescription(
- Map<String, RtpDescriptionPacketExtension> map,
- ColibriConferenceIQ localChannelsInfo) {
-
- if (conferenceState == null
- || StringUtils.isNullOrEmpty(conferenceState.getID()))
- {
- // We are not initialized yet
- return null;
- }
-
- assertRequestType(RequestType.RTP_DESCRIPTION_UPDATE);
-
- request.setType(IQ.Type.SET);
-
- for (Map.Entry<String, RtpDescriptionPacketExtension> e
- : map.entrySet())
+ private ColibriConferenceIQ.ChannelCommon getRequestChannel(
+ ColibriConferenceIQ.Content requestContent,
+ ColibriConferenceIQ.ChannelCommon localChannelInfo)
+ {
+ ColibriConferenceIQ.ChannelCommon reqChannel
+ = requestContent.getChannel(localChannelInfo.getID());
+ if (reqChannel == null)
{
- String contentName = e.getKey();
- ColibriConferenceIQ.ChannelCommon channel
- = getColibriChannel(localChannelsInfo, contentName);
-
- if (channel != null
- && channel instanceof ColibriConferenceIQ.Channel)
+ if (localChannelInfo instanceof ColibriConferenceIQ.Channel)
{
- RtpDescriptionPacketExtension rtpPE = e.getValue();
- if (rtpPE == null)
- {
- continue;
- }
-
- List<PayloadTypePacketExtension> pts = rtpPE.getPayloadTypes();
- if (pts == null || pts.isEmpty())
- {
- continue;
- }
-
- ColibriConferenceIQ.Channel channelRequest
- = new ColibriConferenceIQ.Channel();
+ reqChannel = new ColibriConferenceIQ.Channel();
+ }
+ else if (
+ localChannelInfo instanceof ColibriConferenceIQ.SctpConnection)
+ {
+ reqChannel = new ColibriConferenceIQ.SctpConnection();
+ }
+ else
+ {
+ throw new RuntimeException(
+ "Unsupported ChannelCommon class: "
+ + localChannelInfo.getClass());
+ }
- channelRequest.setID(channel.getID());
+ reqChannel.setID(localChannelInfo.getID());
- for (PayloadTypePacketExtension ptPE : rtpPE.getPayloadTypes())
- {
- channelRequest.addPayloadType(ptPE);
- }
+ requestContent.addChannelCommon(reqChannel);
+ }
+ return reqChannel;
+ }
- request.getOrCreateContent(contentName)
- .addChannel(channelRequest);
- }
+ private ColibriConferenceIQ.Channel getRtpChannel(
+ ColibriConferenceIQ localChannelsInfo,
+ String contentName)
+ {
+ ColibriConferenceIQ.Content content
+ = localChannelsInfo.getContent(contentName);
- }
+ if (content == null)
+ return null;
- return this;
+ return content.getChannelCount() > 0 ? content.getChannel(0) : null;
}
/**
@@ -808,19 +1086,10 @@ public class ColibriBuilder
ALLOCATE_CHANNELS,
/**
- * Updates transport information for channels that use RTP bundle.
- */
- BUNDLE_TRANSPORT_UPDATE,
-
- /**
- * Updates channel transport information(ICE transport candidates).
+ * An update request which is meant to modify some values of existing
+ * Colibri channels on the bridge.
*/
- TRANSPORT_UPDATE,
-
- /**
- * Updates the RTP description of a channel (payload types).
- */
- RTP_DESCRIPTION_UPDATE,
+ CHANNEL_INFO_UPDATE,
/**
* Expires specified Colibri channels.
@@ -833,4 +1102,28 @@ public class ColibriBuilder
*/
UNDEFINED;
}
+
+ /**
+ * Configures RTP-level relay (RFC 3550, section 2.3).
+ * @param rtpLevelRelayType an <tt>RTPLevelRelayType</tt> value which
+ * stands for the rtp level relay type that will be set on all created
+ * audio channels.
+ */
+ public void setRTPLevelRelayType(RTPLevelRelayType rtpLevelRelayType)
+ {
+ this.rtpLevelRelayType = rtpLevelRelayType;
+ }
+
+ /**
+ * Configures RTP-level relay (RFC 3550, section 2.3).
+ * @param rtpLevelRelayType a <tt>String</tt> value which
+ * stands for the rtp level relay type that will be set on all created
+ * audio channels.
+ */
+ public void setRTPLevelRelayType(String rtpLevelRelayType)
+ {
+ setRTPLevelRelayType
+ (RTPLevelRelayType.parseRTPLevelRelayType(rtpLevelRelayType));
+ }
+
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
index 52368bf..d5cf175 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriConferenceIQ.java
@@ -161,7 +161,7 @@ public class ColibriConferenceIQ
throw new NullPointerException("channelBundle");
return
- channelBundles.contains(channelBundles)
+ channelBundles.contains(channelBundle)
? false
: channelBundles.add(channelBundle);
}
@@ -543,6 +543,14 @@ public class ColibriConferenceIQ
= "receive-simulcast-layer";
/**
+ * The XML name of the <tt>packet-delay</tt> attribute of
+ * a <tt>channel</tt> of a <tt>content</tt> of a <tt>conference</tt> IQ
+ * which represents the value of the {@link #packetDelay} property of
+ * <tt>ColibriConferenceIQ.Channel</tt>.
+ */
+ public static final String PACKET_DELAY_ATTR_NAME = "packet-delay";
+
+ /**
* The XML name of the <tt>rtcpport</tt> attribute of a <tt>channel</tt>
* of a <tt>content</tt> of a <tt>conference</tt> IQ which represents
* the value of the <tt>rtcpPort</tt> property of
@@ -613,6 +621,11 @@ public class ColibriConferenceIQ
private SimulcastMode simulcastMode;
/**
+ * The amount of delay added to the RTP stream in a number of packets.
+ */
+ private Integer packetDelay;
+
+ /**
* The <tt>payload-type</tt> elements defined by XEP-0167: Jingle RTP
* Sessions associated with this <tt>channel</tt>.
*/
@@ -893,6 +906,18 @@ public class ColibriConferenceIQ
}
/**
+ * Returns an <tt>Integer</tt> which stands for the amount of delay
+ * added to the RTP stream in a number of packets.
+ *
+ * @return <tt>Integer</tt> with the value or <tt>null</tt> if
+ * unspecified.
+ */
+ public Integer getPacketDelay()
+ {
+ return packetDelay;
+ }
+
+ /**
* Gets a list of <tt>payload-type</tt> elements defined by XEP-0167:
* Jingle RTP Sessions added to this <tt>channel</tt>.
*
@@ -1077,8 +1102,16 @@ public class ColibriConferenceIQ
if (adaptiveSimulcast != null)
{
- xml.append(' ').append(adaptiveSimulcast).append("='")
- .append(adaptiveSimulcast).append('\'');
+ xml.append(' ').append(ADAPTIVE_SIMULCAST_ATTR_NAME)
+ .append("='").append(adaptiveSimulcast).append('\'');
+ }
+
+ // packet-delay
+ Integer packetDelay = getPacketDelay();
+ if (packetDelay != null)
+ {
+ xml.append(' ').append(PACKET_DELAY_ATTR_NAME).append("='")
+ .append(packetDelay).append('\'');
}
// simulcastMode
@@ -1314,6 +1347,17 @@ public class ColibriConferenceIQ
}
/**
+ * Configures channel's packet delay which tells by how many packets
+ * the RTP streams will be delayed.
+ * @param packetDelay an <tt>Integer</tt> value which stands for
+ * the packet delay that will be set or <tt>null</tt> to leave undefined
+ */
+ public void setPacketDelay(Integer packetDelay)
+ {
+ this.packetDelay = packetDelay;
+ }
+
+ /**
* Sets the value of the 'simulcast-mode' flag.
* @param simulcastMode the value to set.
*/
@@ -1925,6 +1969,25 @@ public class ColibriConferenceIQ
}
/**
+ * Adds <tt>ChannelCommon</tt> to this <tt>Content</tt>.
+ * @param channelCommon {@link ChannelCommon} instance to be added to
+ * this content.
+ * @return <tt>true</tt> if given <tt>channelCommon</tt> has been
+ * actually added to this <tt>Content</tt> instance.
+ */
+ public boolean addChannelCommon(ChannelCommon channelCommon)
+ {
+ if (channelCommon instanceof Channel)
+ {
+ return addChannel((Channel) channelCommon);
+ }
+ else
+ {
+ return addSctpConnection((SctpConnection) channelCommon);
+ }
+ }
+
+ /**
* Adds a specific <tt>SctpConnection</tt> to the list of
* <tt>SctpConnection</tt>s included into this <tt>Content</tt>.
*
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
index 39e299f..ce676ef 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriIQProvider.java
@@ -20,6 +20,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
+import net.java.sip.communicator.service.protocol.jabber.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.util.*;
import org.jivesoftware.smack.packet.*;
@@ -36,89 +37,101 @@ import org.xmlpull.v1.*;
public class ColibriIQProvider
implements IQProvider
{
+
+ /**
+ * Smack interoperation layer
+ */
+ private AbstractSmackInteroperabilityLayer smackInteroperabilityLayer =
+ AbstractSmackInteroperabilityLayer.getInstance();
+
/** Initializes a new <tt>ColibriIQProvider</tt> instance. */
public ColibriIQProvider()
{
- ProviderManager providerManager = ProviderManager.getInstance();
-
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
PayloadTypePacketExtension.ELEMENT_NAME,
ColibriConferenceIQ.NAMESPACE,
new DefaultPacketExtensionProvider<PayloadTypePacketExtension>(
PayloadTypePacketExtension.class));
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
RtcpFbPacketExtension.ELEMENT_NAME,
RtcpFbPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<RtcpFbPacketExtension>(
RtcpFbPacketExtension.class));
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
RTPHdrExtPacketExtension.ELEMENT_NAME,
ColibriConferenceIQ.NAMESPACE,
new DefaultPacketExtensionProvider<RTPHdrExtPacketExtension>(
RTPHdrExtPacketExtension.class));
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
SourcePacketExtension.ELEMENT_NAME,
SourcePacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<SourcePacketExtension>(
SourcePacketExtension.class));
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
SourceGroupPacketExtension.ELEMENT_NAME,
SourceGroupPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<SourceGroupPacketExtension>(
SourceGroupPacketExtension.class));
PacketExtensionProvider parameterProvider
- = new DefaultPacketExtensionProvider<ParameterPacketExtension>(
- ParameterPacketExtension.class);
+ = new DefaultPacketExtensionProvider<ParameterPacketExtension>(
+ ParameterPacketExtension.class);
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
ParameterPacketExtension.ELEMENT_NAME,
ColibriConferenceIQ.NAMESPACE,
parameterProvider);
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
ParameterPacketExtension.ELEMENT_NAME,
SourcePacketExtension.NAMESPACE,
parameterProvider);
// Shutdown IQ
- providerManager.addIQProvider(
- GracefulShutdownIQ.ELEMENT_NAME,
- GracefulShutdownIQ.NAMESPACE,
+ smackInteroperabilityLayer.addIQProvider(
+ ShutdownIQ.GRACEFUL_ELEMENT_NAME,
+ ShutdownIQ.NAMESPACE,
+ this);
+ smackInteroperabilityLayer.addIQProvider(
+ ShutdownIQ.FORCE_ELEMENT_NAME,
+ ShutdownIQ.NAMESPACE,
this);
// Shutdown extension
PacketExtensionProvider shutdownProvider
- = new DefaultPacketExtensionProvider
- <ColibriConferenceIQ.GracefulShutdown>(
- ColibriConferenceIQ.GracefulShutdown.class);
+ = new DefaultPacketExtensionProvider
+ <ColibriConferenceIQ.GracefulShutdown>(
+ ColibriConferenceIQ.GracefulShutdown.class);
- providerManager.addExtensionProvider(
- ColibriConferenceIQ.GracefulShutdown.ELEMENT_NAME,
- ColibriConferenceIQ.GracefulShutdown.NAMESPACE,
- shutdownProvider);
+ smackInteroperabilityLayer.addExtensionProvider(
+ ColibriConferenceIQ.GracefulShutdown.ELEMENT_NAME,
+ ColibriConferenceIQ.GracefulShutdown.NAMESPACE,
+ shutdownProvider);
// ColibriStatsIQ
- providerManager.addIQProvider(
- ColibriStatsIQ.ELEMENT_NAME,
- ColibriStatsIQ.NAMESPACE,
- this);
+ smackInteroperabilityLayer.addIQProvider(
+ ColibriStatsIQ.ELEMENT_NAME,
+ ColibriStatsIQ.NAMESPACE,
+ this);
// ColibriStatsExtension
PacketExtensionProvider statsProvider
- = new DefaultPacketExtensionProvider<ColibriStatsExtension>(
- ColibriStatsExtension.class);
+ = new DefaultPacketExtensionProvider<ColibriStatsExtension>(
+ ColibriStatsExtension.class);
- providerManager.addExtensionProvider(
- ColibriStatsExtension.ELEMENT_NAME,
- ColibriStatsExtension.NAMESPACE,
- statsProvider);
+ smackInteroperabilityLayer.addExtensionProvider(
+ ColibriStatsExtension.ELEMENT_NAME,
+ ColibriStatsExtension.NAMESPACE,
+ statsProvider);
// ColibriStatsExtension.Stat
PacketExtensionProvider statProvider
- = new DefaultPacketExtensionProvider<ColibriStatsExtension.Stat>(
- ColibriStatsExtension.Stat.class);
-
- providerManager.addExtensionProvider(
- ColibriStatsExtension.Stat.ELEMENT_NAME,
- ColibriStatsExtension.NAMESPACE,
- statProvider);
+ = new DefaultPacketExtensionProvider
+ <ColibriStatsExtension.Stat>(
+ ColibriStatsExtension.Stat.class);
+
+ smackInteroperabilityLayer.addExtensionProvider(
+ ColibriStatsExtension.Stat.ELEMENT_NAME,
+ ColibriStatsExtension.NAMESPACE,
+ statProvider);
+
+
}
private void addChildExtension(
@@ -199,8 +212,7 @@ public class ColibriIQProvider
throws Exception
{
PacketExtensionProvider extensionProvider
- = (PacketExtensionProvider)
- ProviderManager.getInstance().getExtensionProvider(
+ = smackInteroperabilityLayer.getExtensionProvider(
name,
namespace);
PacketExtension extension;
@@ -416,6 +428,15 @@ public class ColibriIQProvider
if ((expire != null) && (expire.length() != 0))
channel.setExpire(Integer.parseInt(expire));
+ String packetDelay
+ = parser.getAttributeValue(
+ "",
+ ColibriConferenceIQ.Channel
+ .PACKET_DELAY_ATTR_NAME);
+ if (!StringUtils.isNullOrEmpty(packetDelay))
+ channel.setPacketDelay(
+ Integer.parseInt(packetDelay));
+
// host
String host
= parser.getAttributeValue(
@@ -464,6 +485,18 @@ public class ColibriIQProvider
channel.setAdaptiveLastN(
Boolean.parseBoolean(adaptiveLastN));
+ String adaptiveSimulcast
+ = parser.getAttributeValue(
+ "",
+ ColibriConferenceIQ.Channel
+ .ADAPTIVE_SIMULCAST_ATTR_NAME);
+
+ if (!StringUtils.isNullOrEmpty(adaptiveSimulcast))
+ {
+ channel.setAdaptiveSimulcast(
+ Boolean.parseBoolean(adaptiveSimulcast));
+ }
+
// simulcastMode
String simulcastMode
= parser.getAttributeValue(
@@ -802,12 +835,12 @@ public class ColibriIQProvider
iq = conference;
}
- else if (GracefulShutdownIQ.ELEMENT_NAME.equals(parser.getName())
- && GracefulShutdownIQ.NAMESPACE.equals(namespace))
+ else if (ShutdownIQ.NAMESPACE.equals(namespace) &&
+ ShutdownIQ.isValidElementName(parser.getName()))
{
String rootElement = parser.getName();
- iq = new GracefulShutdownIQ();
+ iq = ShutdownIQ.createShutdownIQ(rootElement);
boolean done = false;
@@ -825,12 +858,6 @@ public class ColibriIQProvider
}
break;
}
-
- case XmlPullParser.TEXT:
- {
- // Parse some text here
- break;
- }
}
}
}
@@ -891,12 +918,6 @@ public class ColibriIQProvider
}
break;
}
-
- case XmlPullParser.TEXT:
- {
- // Parse some text here
- break;
- }
}
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java
index d5a6ce1..ef80392 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ColibriStreamConnector.java
@@ -1,4 +1,4 @@
-/*
+/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
@@ -15,74 +15,74 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri;
-
-import org.jitsi.service.neomedia.*;
-
-/**
- * Implements a <tt>StreamConnector</tt> which allows sharing a specific
- * <tt>StreamConnector</tt> instance among multiple <tt>TransportManager</tt>s
- * for the purposes of the Jitsi Videobridge.
- *
- * @author Lyubomir Marinov
- */
-public class ColibriStreamConnector
- extends StreamConnectorDelegate<StreamConnector>
-{
- /**
- * Initializes a new <tt>ColibriStreamConnector</tt> instance which is to
- * share a specific <tt>StreamConnector</tt> instance among multiple
- * <tt>TransportManager</tt>s for the purposes of the Jitsi Videobridge.
- *
- * @param streamConnector the <tt>StreamConnector</tt> instance to be shared
- * by the new instance among multiple <tt>TransportManager</tt>s for the
- * purposes of the Jitsi Videobridge
- */
- public ColibriStreamConnector(StreamConnector streamConnector)
- {
- super(streamConnector);
- }
-
- /**
- * {@inheritDoc}
- *
- * Overrides {@link StreamConnectorDelegate#close()} in order to prevent the
- * closing of the <tt>StreamConnector</tt> wrapped by this instance because
- * the latter is shared and it is not clear whether no
- * <tt>TransportManager</tt> is using it.
- */
- @Override
- public void close()
- {
- /*
- * Do not close the shared StreamConnector because it is not clear
- * whether no TransportManager is using it.
- */
- }
-
- /**
- * {@inheritDoc}
- *
- * Invokes {@link #close()} on this instance when it is clear that no
- * <tt>TransportManager</tt> is using it in order to release the resources
- * allocated by this instance throughout its life time (that need explicit
- * disposal).
- */
- @Override
- protected void finalize()
- throws Throwable
- {
- try
- {
- /*
- * Close the shared StreamConnector because it is clear that no
- * TrasportManager is using it.
- */
- super.close();
- }
- finally
- {
- super.finalize();
- }
- }
-}
+package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri;
+
+import org.jitsi.service.neomedia.*;
+
+/**
+ * Implements a <tt>StreamConnector</tt> which allows sharing a specific
+ * <tt>StreamConnector</tt> instance among multiple <tt>TransportManager</tt>s
+ * for the purposes of the Jitsi Videobridge.
+ *
+ * @author Lyubomir Marinov
+ */
+public class ColibriStreamConnector
+ extends StreamConnectorDelegate<StreamConnector>
+{
+ /**
+ * Initializes a new <tt>ColibriStreamConnector</tt> instance which is to
+ * share a specific <tt>StreamConnector</tt> instance among multiple
+ * <tt>TransportManager</tt>s for the purposes of the Jitsi Videobridge.
+ *
+ * @param streamConnector the <tt>StreamConnector</tt> instance to be shared
+ * by the new instance among multiple <tt>TransportManager</tt>s for the
+ * purposes of the Jitsi Videobridge
+ */
+ public ColibriStreamConnector(StreamConnector streamConnector)
+ {
+ super(streamConnector);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Overrides {@link StreamConnectorDelegate#close()} in order to prevent the
+ * closing of the <tt>StreamConnector</tt> wrapped by this instance because
+ * the latter is shared and it is not clear whether no
+ * <tt>TransportManager</tt> is using it.
+ */
+ @Override
+ public void close()
+ {
+ /*
+ * Do not close the shared StreamConnector because it is not clear
+ * whether no TransportManager is using it.
+ */
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * Invokes {@link #close()} on this instance when it is clear that no
+ * <tt>TransportManager</tt> is using it in order to release the resources
+ * allocated by this instance throughout its life time (that need explicit
+ * disposal).
+ */
+ @Override
+ protected void finalize()
+ throws Throwable
+ {
+ try
+ {
+ /*
+ * Close the shared StreamConnector because it is clear that no
+ * TrasportManager is using it.
+ */
+ super.close();
+ }
+ finally
+ {
+ super.finalize();
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java
new file mode 100644
index 0000000..4df251b
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/ShutdownIQ.java
@@ -0,0 +1,134 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.colibri;
+
+import org.jivesoftware.smack.packet.*;
+
+/**
+ * The IQ used to trigger the graceful shutdown mode of the videobridge or force
+ * shutdown the one which receives the stanza(given that source JID is
+ * authorized to do so).
+ *
+ * @author Pawel Domas
+ */
+public class ShutdownIQ
+ extends IQ
+{
+ /**
+ * XML namespace name for shutdown IQs.
+ */
+ final static public String NAMESPACE = ColibriConferenceIQ.NAMESPACE;
+
+ /**
+ * Force shutdown IQ element name.
+ */
+ final static public String FORCE_ELEMENT_NAME = "force-shutdown";
+
+ /**
+ * Graceful shutdown IQ element name.
+ */
+ final static public String GRACEFUL_ELEMENT_NAME = "graceful-shutdown";
+
+ /**
+ * The element name of this IQ. Either {@link #FORCE_ELEMENT_NAME} or
+ * {@link #GRACEFUL_ELEMENT_NAME}.
+ */
+ private final String elementName;
+
+ /**
+ * Checks if given element is a valid one for <tt>ShutdownIQ</tt>.
+ *
+ * @param elementName the name if XML element name inside of the IQ.
+ *
+ * @return <tt>true</tt> if given <tt>elementName</tt> is correct for
+ * <tt>ShutdownIQ</tt>.
+ */
+ public static boolean isValidElementName(String elementName)
+ {
+ return GRACEFUL_ELEMENT_NAME.equals(elementName)
+ || FORCE_ELEMENT_NAME.equals(elementName);
+ }
+
+ /**
+ * Creates shutdown IQ for given element name.
+ *
+ * @param elementName can be {@link #FORCE_ELEMENT_NAME} or
+ * {@link #GRACEFUL_ELEMENT_NAME}
+ *
+ * @return new <tt>ShutdownIQ</tt> instance for given element name.
+ *
+ * @throws IllegalArgumentException if given element name is neither
+ * {@link #FORCE_ELEMENT_NAME} nor {@link #GRACEFUL_ELEMENT_NAME}.
+ */
+ public static ShutdownIQ createShutdownIQ(String elementName)
+ {
+ if (!isValidElementName(elementName))
+ {
+ throw new IllegalArgumentException(
+ "Invalid element name: " + elementName);
+ }
+
+ if (GRACEFUL_ELEMENT_NAME.equals(elementName))
+ {
+ return createGracefulShutdownIQ();
+ }
+ else
+ {
+ return createForceShutdownIQ();
+ }
+ }
+
+ /**
+ * Creates and returns new instance of graceful shutdown IQ.
+ */
+ public static ShutdownIQ createGracefulShutdownIQ()
+ {
+ return new ShutdownIQ(GRACEFUL_ELEMENT_NAME);
+ }
+
+ /**
+ * Creates and returns new instance of force shutdown IQ.
+ */
+ public static ShutdownIQ createForceShutdownIQ()
+ {
+ return new ShutdownIQ(FORCE_ELEMENT_NAME);
+ }
+
+ private ShutdownIQ(String elementName)
+ {
+ this.elementName = elementName;
+ }
+
+ /**
+ * Returns <tt>true</tt> if this IQ instance is a "graceful shutdown" one.
+ * Otherwise it is a force shutdown IQ.
+ */
+ public boolean isGracefulShutdown()
+ {
+ return elementName.equals(GRACEFUL_ELEMENT_NAME);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getChildElementXML()
+ {
+ return "<" + elementName + " xmlns='" + NAMESPACE + "' />";
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java
index 9808b11..661bb1b 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/colibri/GracefulShutdownIQ.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQ.java
@@ -15,23 +15,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package net.java.sip.communicator.impl.protocol.jabber.extensions.colibri;
+package net.java.sip.communicator.impl.protocol.jabber.extensions.health;
import org.jivesoftware.smack.packet.*;
/**
- * The IQ used to trigger the graceful shutdown mode of the videobridge which
- * receives the stanza(given that source JID is authorized to start it).
+ * The health check IQ used to trigger health checks on the Jitsi Videobridge.
*
* @author Pawel Domas
*/
-public class GracefulShutdownIQ
+public class HealthCheckIQ
extends IQ
{
- public static final String NAMESPACE = ColibriConferenceIQ.NAMESPACE;
+ /**
+ * Health check IQ element name.
+ */
+ final static public String ELEMENT_NAME = "healthcheck";
- public static final String ELEMENT_NAME = "graceful-shutdown";
+ /**
+ * XML namespace name for health check IQs.
+ */
+ final static public String NAMESPACE
+ = "http://jitsi.org/protocol/healthcheck";
+ /**
+ * {@inheritDoc}
+ */
@Override
public String getChildElementXML()
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java
new file mode 100644
index 0000000..9c2903d
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/health/HealthCheckIQProvider.java
@@ -0,0 +1,94 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.health;
+
+import net.java.sip.communicator.service.protocol.jabber.*;
+
+import org.jivesoftware.smack.packet.*;
+import org.jivesoftware.smack.provider.*;
+
+import org.xmlpull.v1.*;
+
+/**
+ * The <tt>IQProvider</tt> for {@link HealthCheckIQ}.
+ *
+ * @author Pawel Domas
+ */
+public class HealthCheckIQProvider
+ implements IQProvider
+{
+ /**
+ * Registers <tt>HealthCheckIQProvider</tt> as an <tt>IQProvider</tt>
+ * in {@link AbstractSmackInteroperabilityLayer}.
+ */
+ public static void registerIQProvider()
+ {
+ AbstractSmackInteroperabilityLayer smackInteropLayer =
+ AbstractSmackInteroperabilityLayer.getInstance();
+
+ // ColibriStatsIQ
+ smackInteropLayer.addIQProvider(
+ HealthCheckIQ.ELEMENT_NAME,
+ HealthCheckIQ.NAMESPACE,
+ new HealthCheckIQProvider());
+ }
+
+ /**
+ * Parses <tt>HealthCheckIQ</tt>.
+ *
+ * {@inheritDoc}
+ */
+ @Override
+ public IQ parseIQ(XmlPullParser parser)
+ throws Exception
+ {
+ String namespace = parser.getNamespace();
+ IQ iq;
+
+ if (HealthCheckIQ.ELEMENT_NAME.equals(parser.getName())
+ && HealthCheckIQ.NAMESPACE.equals(namespace))
+ {
+ String rootElement = parser.getName();
+
+ iq = new HealthCheckIQ();
+
+ boolean done = false;
+
+ while (!done)
+ {
+ switch (parser.next())
+ {
+ case XmlPullParser.END_TAG:
+ {
+ String name = parser.getName();
+
+ if (rootElement.equals(name))
+ {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+ }
+ else
+ iq = null;
+
+ return iq;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java
new file mode 100644
index 0000000..8b964af
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIq.java
@@ -0,0 +1,413 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * The IQ used to control conference recording with Jibri component.
+ *
+ * Start the recording:
+ *
+ * 1. Send Jibri IQ with {@link Action#START} to Jibri.
+ * 2. Jibri replies with RESULT and status {@link Status#PENDING}.
+ * 3. Jibri sends SET IQ with status {@link Status#ON} once recording actually
+ * starts.
+ *
+ * Stop the recording:
+ *
+ * 1. Send Jibri IQ with {@link Action#STOP} to Jibri.
+ * 2. Jibri replies with {@link Status#OFF} immediately if the recording has
+ * been stopped already or sends separate Jibri SET IQ later on if it takes
+ * more time.
+ *
+ * @author lishunyang
+ * @author Pawel Domas
+ */
+public class JibriIq
+ extends IQ
+{
+ /**
+ * Attribute name of "action".
+ */
+ public static final String ACTION_ATTR_NAME = "action";
+
+ /**
+ * XML element name of the Jibri IQ.
+ */
+ public static final String ELEMENT_NAME = "jibri";
+
+ /**
+ * XML namespace of the Jibri IQ.
+ */
+ public static final String NAMESPACE = "http://jitsi.org/protocol/jibri";
+
+ /**
+ * The name of XML attribute which stores the recording status.
+ */
+ static final String STATUS_ATTR_NAME = "status";
+
+ /**
+ * The name of XML attribute which stores the stream id.
+ */
+ static final String STREAM_ID_ATTR_NAME = "streamid";
+
+ /**
+ * The name of XML attribute which stores the name of the conference room to
+ * be recorded.
+ */
+ static final String ROOM_ATTR_NAME = "room";
+
+ /**
+ * Holds the action.
+ */
+ private Action action = Action.UNDEFINED;
+
+ /**
+ * XMPPError stores error details for {@link Status#FAILED}.
+ */
+ private XMPPError error;
+
+ /**
+ * Holds recording status.
+ */
+ private Status status = Status.UNDEFINED;
+
+ /**
+ * The ID of the stream which will be used to record the conference. The
+ * value depends on recording service provider.
+ */
+ private String streamId = null;
+
+ /**
+ * The name of the conference room to be recorded.
+ */
+ private String room = null;
+
+ /**
+ * Returns the value of {@link #STREAM_ID_ATTR_NAME} attribute.
+ * @return a <tt>String</tt> which contains the value of "stream id"
+ * attribute or <tt>null</tt> if empty.
+ */
+ public String getStreamId()
+ {
+ return streamId;
+ }
+
+ /**
+ * Sets the value for {@link #STREAM_ID_ATTR_NAME} attribute.
+ * @param streamId a <tt>String</tt> for the stream id attribute or
+ * <tt>null</tt> to remove it from XML element.
+ */
+ public void setStreamId(String streamId)
+ {
+ this.streamId = streamId;
+ }
+
+ /**
+ * Returns the value of {@link #ROOM_ATTR_NAME} attribute.
+ * @return a <tt>String</tt> which contains the value of the room attribute
+ * or <tt>null</tt> if empty.
+ * @see #room
+ */
+ public String getRoom()
+ {
+ return room;
+ }
+
+ /**
+ * Sets the value for {@link #ROOM_ATTR_NAME} attribute.
+ * @param room a <tt>String</tt> for the room attribute or <tt>null</tt> to
+ * remove it from XML element.
+ * @see #room
+ */
+ public void setRoom(String room)
+ {
+ this.room = room;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getChildElementXML()
+ {
+ StringBuilder xml = new StringBuilder();
+
+ xml.append('<').append(ELEMENT_NAME);
+ xml.append(" xmlns='").append(NAMESPACE).append("' ");
+
+ if (action != Action.UNDEFINED)
+ {
+ printStringAttribute(xml, ACTION_ATTR_NAME, action.toString());
+ }
+
+ if (status != Status.UNDEFINED)
+ {
+ printStringAttribute(xml, STATUS_ATTR_NAME, status.toString());
+ }
+
+ if (room != null)
+ {
+ printStringAttribute(xml, ROOM_ATTR_NAME, room);
+ }
+
+ if (streamId != null)
+ {
+ printStringAttribute(xml, STREAM_ID_ATTR_NAME, streamId);
+ }
+
+ Collection<PacketExtension> extensions = getExtensions();
+ if (extensions.size() > 0)
+ {
+ xml.append(">");
+ for (PacketExtension extension : extensions)
+ {
+ xml.append(extension.toXML());
+ }
+ xml.append("</").append(ELEMENT_NAME).append(">");
+ }
+ else
+ {
+ xml.append("/>");
+ }
+
+ return xml.toString();
+ }
+
+ private void printStringAttribute(
+ StringBuilder xml, String attrName, String attr)
+ {
+ if (!StringUtils.isNullOrEmpty(attr))
+ {
+ attr = org.jivesoftware.smack.util.StringUtils.escapeForXML(attr);
+ xml.append(attrName).append("='")
+ .append(attr).append("' ");
+ }
+ }
+
+ /**
+ * Sets the value of 'action' attribute.
+ *
+ * @param action the value to be set as 'action' attribute of this IQ.
+ */
+ public void setAction(Action action)
+ {
+ this.action = action;
+ }
+
+ /**
+ * Returns the value of 'action' attribute.
+ */
+ public Action getAction()
+ {
+ return action;
+ }
+
+ /**
+ * Sets the value of 'status' attribute.
+ */
+ public void setStatus(Status status)
+ {
+ this.status = status;
+ }
+
+ /**
+ * Returns the value of 'status' attribute.
+ */
+ public Status getStatus()
+ {
+ return status;
+ }
+
+ /**
+ * Sets the <tt>XMPPError</tt> which will provide details about Jibri
+ * failure. It is expected to be set when this IQ's status value is
+ * {@link Status#FAILED}.
+ *
+ * @param error <tt>XMPPError</tt> to be set on this <tt>JibriIq</tt>
+ * instance.
+ */
+ public void setXMPPError(XMPPError error)
+ {
+ this.error = error;
+ }
+
+ /**
+ * Returns {@link XMPPError} with Jibri error details when the status is
+ * {@link Status#FAILED}.
+ */
+ public XMPPError getError()
+ {
+ return error;
+ }
+
+ /**
+ * Enumerative value of attribute "action" in recording extension.
+ *
+ * @author lishunyang
+ * @author Pawel Domas
+ *
+ */
+ public enum Action
+ {
+ /**
+ * Start the recording.
+ */
+ START("start"),
+ /**
+ * Stop the recording.
+ */
+ STOP("stop"),
+ /**
+ * Unknown/uninitialized
+ */
+ UNDEFINED("undefined");
+
+ private String name;
+
+ Action(String name)
+ {
+ this.name = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Action</tt> from given string.
+ *
+ * @param action the string representation of <tt>Action</tt>.
+ *
+ * @return <tt>Action</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Action parse(String action)
+ {
+ if (StringUtils.isNullOrEmpty(action))
+ return UNDEFINED;
+
+ try
+ {
+ return Action.valueOf(action.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+
+ /**
+ * The enumeration of recording status values.
+ */
+ public enum Status
+ {
+ /**
+ * Recording is in progress.
+ */
+ ON("on"),
+
+ /**
+ * Recording stopped.
+ */
+ OFF("off"),
+
+ /**
+ * Starting the recording process.
+ */
+ PENDING("pending"),
+
+ /**
+ * The recorder has failed and the service is retrying on another
+ * instance.
+ */
+ RETRYING("retrying"),
+
+ /**
+ * An error occurred any point during startup, recording or shutdown.
+ */
+ FAILED("failed"),
+
+ /**
+ * There are Jibri instances connected to the system, but all of them
+ * are currently busy.
+ */
+ BUSY("busy"),
+
+ /**
+ * Unknown/uninitialized.
+ */
+ UNDEFINED("undefined");
+
+ /**
+ * Status name holder.
+ */
+ private String name;
+
+ /**
+ * Creates new {@link Status} instance.
+ * @param name a string corresponding to one of {@link Status} values.
+ */
+ Status(String name)
+ {
+ this.name = name;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Status</tt> from given string.
+ *
+ * @param status the string representation of <tt>Status</tt>.
+ *
+ * @return <tt>Status</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Status parse(String status)
+ {
+ if (StringUtils.isNullOrEmpty(status))
+ return UNDEFINED;
+
+ try
+ {
+ return Status.valueOf(status.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java
new file mode 100644
index 0000000..155853c
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriIqProvider.java
@@ -0,0 +1,112 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.packet.*;
+import org.jivesoftware.smack.provider.*;
+import org.jivesoftware.smack.util.PacketParserUtils;
+
+import org.xmlpull.v1.*;
+
+/**
+ * Parses {@link JibriIq}.
+ */
+public class JibriIqProvider
+ implements IQProvider
+{
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public IQ parseIQ(XmlPullParser parser)
+ throws Exception
+ {
+ String namespace = parser.getNamespace();
+
+ // Check the namespace
+ if (!JibriIq.NAMESPACE.equals(namespace))
+ {
+ return null;
+ }
+
+ String rootElement = parser.getName();
+
+ JibriIq iq;
+
+ if (JibriIq.ELEMENT_NAME.equals(rootElement))
+ {
+ iq = new JibriIq();
+
+ String action
+ = parser.getAttributeValue("", JibriIq.ACTION_ATTR_NAME);
+ iq.setAction(JibriIq.Action.parse(action));
+
+ String status
+ = parser.getAttributeValue("", JibriIq.STATUS_ATTR_NAME);
+ iq.setStatus(JibriIq.Status.parse(status));
+
+ String room
+ = parser.getAttributeValue("", JibriIq.ROOM_ATTR_NAME);
+ if (!StringUtils.isNullOrEmpty(room))
+ iq.setRoom(room);
+
+ String streamId
+ = parser.getAttributeValue("", JibriIq.STREAM_ID_ATTR_NAME);
+ if (!StringUtils.isNullOrEmpty(streamId))
+ iq.setStreamId(streamId);
+ }
+ else
+ {
+ return null;
+ }
+
+ boolean done = false;
+
+ while (!done)
+ {
+ switch (parser.next())
+ {
+ case XmlPullParser.START_TAG:
+ {
+ String name = parser.getName();
+
+ if ("error".equals(name))
+ {
+ XMPPError error = PacketParserUtils.parseError(parser);
+ iq.setXMPPError(error);
+ }
+ break;
+ }
+ case XmlPullParser.END_TAG:
+ {
+ String name = parser.getName();
+
+ if (rootElement.equals(name))
+ {
+ done = true;
+ }
+ break;
+ }
+ }
+ }
+
+ return iq;
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java
new file mode 100644
index 0000000..e046b68
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/JibriStatusPacketExt.java
@@ -0,0 +1,121 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+import org.jitsi.util.*;
+
+import org.jivesoftware.smack.provider.*;
+
+/**
+ * Status extension included in MUC presence by Jibri to indicate it's status.
+ * One of:
+ * <li>idle</li> - the instance is idle and can be used for recording
+ * <li>busy</li> - the instance is currently recording or doing something very
+ * important and should not be disturbed
+ *
+ *
+ */
+public class JibriStatusPacketExt
+ extends AbstractPacketExtension
+{
+ /**
+ * The namespace of this packet extension.
+ */
+ public static final String NAMESPACE = JibriIq.NAMESPACE;
+
+ /**
+ * XML element name of this packet extension.
+ */
+ public static final String ELEMENT_NAME = "jibri-status";
+
+ private static final String STATUS_ATTRIBUTE = "status";
+
+ /**
+ * Creates new instance of <tt>VideoMutedExtension</tt>.
+ */
+ public JibriStatusPacketExt()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ static public void registerExtensionProvider()
+ {
+ ProviderManager.getInstance().addExtensionProvider(
+ ELEMENT_NAME,
+ NAMESPACE,
+ new DefaultPacketExtensionProvider<JibriStatusPacketExt>(
+ JibriStatusPacketExt.class)
+ );
+ }
+
+ public Status getStatus()
+ {
+ return Status.parse(getAttributeAsString(STATUS_ATTRIBUTE));
+ }
+
+ public void setStatus(Status status)
+ {
+ setAttribute(STATUS_ATTRIBUTE, String.valueOf(status));
+ }
+
+ public enum Status
+ {
+ IDLE("idle"),
+ BUSY("busy"),
+ UNDEFINED("undefined");
+
+ private String name;
+
+ Status(String name)
+ {
+ this.name = name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+
+ /**
+ * Parses <tt>Status</tt> from given string.
+ *
+ * @param status the string representation of <tt>Status</tt>.
+ *
+ * @return <tt>Status</tt> value for given string or
+ * {@link #UNDEFINED} if given string does not
+ * reflect any of valid values.
+ */
+ public static Status parse(String status)
+ {
+ if (StringUtils.isNullOrEmpty(status))
+ return UNDEFINED;
+
+ try
+ {
+ return Status.valueOf(status.toUpperCase());
+ }
+ catch(IllegalArgumentException e)
+ {
+ return UNDEFINED;
+ }
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java
new file mode 100644
index 0000000..13177cf
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/RecordingStatus.java
@@ -0,0 +1,126 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * The packet extension added to Jicofo MUC presence to broadcast current
+ * recording status to all conference participants.
+ *
+ * Status meaning:
+ * <tt>{@link JibriIq.Status#UNDEFINED}</tt> - recording not available
+ * <tt>{@link JibriIq.Status#OFF}</tt> - recording stopped(available to start)
+ * <tt>{@link JibriIq.Status#PENDING}</tt> - starting recording
+ * <tt>{@link JibriIq.Status#ON}</tt> - recording in progress
+ */
+public class RecordingStatus
+ extends AbstractPacketExtension
+{
+ /**
+ * The namespace of this packet extension.
+ */
+ public static final String NAMESPACE = JibriIq.NAMESPACE;
+
+ /**
+ * XML element name of this packet extension.
+ */
+ public static final String ELEMENT_NAME = "jibri-recording-status";
+
+ /**
+ * The name of XML attribute which holds the recording status.
+ */
+ private static final String STATUS_ATTRIBUTE = "status";
+
+ public RecordingStatus()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Returns the value of current recording status stored in it's attribute.
+ * @return one of {@link JibriIq.Status}
+ */
+ public JibriIq.Status getStatus()
+ {
+ String statusAttr = getAttributeAsString(STATUS_ATTRIBUTE);
+
+ return JibriIq.Status.parse(statusAttr);
+ }
+
+ /**
+ * Sets new value for the recording status.
+ * @param status one of {@link JibriIq.Status}
+ */
+ public void setStatus(JibriIq.Status status)
+ {
+ setAttribute(STATUS_ATTRIBUTE, String.valueOf(status));
+ }
+
+ /**
+ * Returns <tt>XMPPError</tt> associated with current
+ * {@link RecordingStatus}.
+ */
+ public XMPPError getError()
+ {
+ XMPPErrorPE errorPe = getErrorPE();
+ return errorPe != null ? errorPe.getError() : null;
+ }
+
+ /**
+ * Gets <tt>{@link XMPPErrorPE}</tt> from the list of child packet
+ * extensions.
+ * @return {@link XMPPErrorPE} or <tt>null</tt> if not found.
+ */
+ private XMPPErrorPE getErrorPE()
+ {
+ List<? extends PacketExtension> errorPe
+ = getChildExtensionsOfType(XMPPErrorPE.class);
+
+ return (XMPPErrorPE) (!errorPe.isEmpty() ? errorPe.get(0) : null);
+ }
+
+ /**
+ * Sets <tt>XMPPError</tt> on this <tt>RecordingStatus</tt>.
+ * @param error <tt>XMPPError</tt> to add error details to this
+ * <tt>RecordingStatus</tt> instance or <tt>null</tt> to have it removed.
+ */
+ public void setError(XMPPError error)
+ {
+ if (error != null)
+ {
+ // Wrap and add XMPPError as packet extension
+ XMPPErrorPE errorPe = getErrorPE();
+ if (errorPe == null)
+ {
+ errorPe = new XMPPErrorPE(error);
+ addChildExtension(errorPe);
+ }
+ errorPe.setError(error);
+ }
+ else
+ {
+ // Remove error PE
+ getChildExtensions().remove(getErrorPE());
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java
new file mode 100644
index 0000000..a72f310
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jibri/XMPPErrorPE.java
@@ -0,0 +1,93 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jibri;
+
+import org.jivesoftware.smack.packet.*;
+
+import java.util.*;
+
+/**
+ * Wraps Smack's <tt>XMPPError</tt> into <tt>PacketExtension</tt>, so that it
+ * can be easily inserted into {@link RecordingStatus}.
+ */
+public class XMPPErrorPE
+ implements PacketExtension
+{
+ /**
+ * <tt>XMPPError</tt> wrapped into this <tt>XMPPErrorPE</tt>.
+ */
+ private XMPPError error;
+
+ /**
+ * Creates new instance of <tt>XMPPErrorPE</tt>.
+ * @param xmppError the instance of <tt>XMPPError</tt> that will be wrapped
+ * by the newly created <tt>XMPPErrorPE</tt>.
+ */
+ public XMPPErrorPE(XMPPError xmppError)
+ {
+ setError(xmppError);
+ }
+
+ /**
+ * Returns the underlying instance of <tt>XMPPError</tt>.
+ */
+ public XMPPError getError()
+ {
+ return error;
+ }
+
+ /**
+ * Sets new instance of <tt>XMPPError</tt> to be wrapped by this
+ * <tt>XMPPErrorPE</tt>.
+ * @param error <tt>XMPPError</tt> that will be wrapped by this
+ * <TT>XMPPErrorPE</TT>.
+ */
+ public void setError(XMPPError error)
+ {
+ Objects.requireNonNull(error, "error");
+
+ this.error = error;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getElementName()
+ {
+ return "error";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getNamespace()
+ {
+ return "";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toXML()
+ {
+ return error.toXML();
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java
index 0c5b190..46b1e77 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CandidatePacketExtension.java
@@ -1,4 +1,4 @@
-/*
+/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
@@ -15,441 +15,441 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle;
-
-import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
-import org.ice4j.ice.*;
-
-/**
- * @author Emil Ivov
- */
-public class CandidatePacketExtension extends AbstractPacketExtension
- implements Comparable<CandidatePacketExtension>
-{
- /**
- * The name of the "candidate" element.
- */
- public static final String ELEMENT_NAME = "candidate";
-
- /**
- * The name of the "component" element.
- */
- public static final String COMPONENT_ATTR_NAME = "component";
-
- /**
- * The "component" ID for RTP components.
- */
- public static final int RTP_COMPONENT_ID = 1;
-
- /**
- * The "component" ID for RTCP components.
- */
- public static final int RTCP_COMPONENT_ID = 2;
-
- /**
- * The name of the "foundation" element.
- */
- public static final String FOUNDATION_ATTR_NAME = "foundation";
-
- /**
- * The name of the "generation" element.
- */
- public static final String GENERATION_ATTR_NAME = "generation";
-
- /**
- * The name of the "id" element.
- */
- public static final String ID_ATTR_NAME = "id";
-
- /**
- * The name of the "ip" element.
- */
- public static final String IP_ATTR_NAME = "ip";
-
- /**
- * The name of the "network" element.
- */
- public static final String NETWORK_ATTR_NAME = "network";
-
- /**
- * The name of the "port" element.
- */
- public static final String PORT_ATTR_NAME = "port";
-
- /**
- * The name of the "priority" element.
- */
- public static final String PRIORITY_ATTR_NAME = "priority";
-
- /**
- * The name of the "protocol" element.
- */
- public static final String PROTOCOL_ATTR_NAME = "protocol";
-
- /**
- * The name of the "rel-addr" element.
- */
- public static final String REL_ADDR_ATTR_NAME = "rel-addr";
-
- /**
- * The name of the "rel-port" element.
- */
- public static final String REL_PORT_ATTR_NAME = "rel-port";
-
- /**
- * The name of the "type" element.
- */
- public static final String TYPE_ATTR_NAME = "type";
-
- /**
- * The name of the "tcptype" element.
- */
- public static final String TCPTYPE_ATTR_NAME = "tcptype";
-
- /**
- * Creates a new {@link CandidatePacketExtension}
- */
- public CandidatePacketExtension()
- {
- super(null, ELEMENT_NAME);
- }
-
- /**
- * Creates a new {@link CandidatePacketExtension} with the specified
- * <tt>elementName</tt> so that this class would be usable as a
- * <tt>RemoteCandidatePacketExtension</tt> parent.
- *
- * @param elementName the element name that this instance should be using.
- */
- protected CandidatePacketExtension(String elementName)
- {
- super(null, elementName);
- }
-
- /**
- * Sets a component ID as defined in ICE-CORE.
- *
- * @param component a component ID as defined in ICE-CORE.
- */
- public void setComponent(int component)
- {
- super.setAttribute(COMPONENT_ATTR_NAME, component);
- }
-
- /**
- * Returns a component ID as defined in ICE-CORE.
- *
- * @return a component ID as defined in ICE-CORE.
- */
- public int getComponent()
- {
- return super.getAttributeAsInt(COMPONENT_ATTR_NAME);
- }
-
- /**
- * Sets the candidate foundation as defined in ICE-CORE.
- *
- * @param foundation the candidate foundation as defined in ICE-CORE.
- */
- public void setFoundation(String foundation)
- {
- super.setAttribute(FOUNDATION_ATTR_NAME, foundation);
- }
-
- /**
- * Returns the candidate foundation as defined in ICE-CORE.
- *
- * @return the candidate foundation as defined in ICE-CORE.
- */
- public String getFoundation()
- {
- return super.getAttributeAsString(FOUNDATION_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's generation index. A generation is an index,
- * starting at 0, that enables the parties to keep track of updates to the
- * candidate throughout the life of the session. For details, see the ICE
- * Restarts section of XEP-0176.
- *
- * @param generation this candidate's generation index.
- */
- public void setGeneration(int generation)
- {
- super.setAttribute(GENERATION_ATTR_NAME, generation);
- }
-
- /**
- * Returns this candidate's generation. A generation is an index, starting at
- * 0, that enables the parties to keep track of updates to the candidate
- * throughout the life of the session. For details, see the ICE Restarts
- * section of XEP-0176.
- *
- * @return this candidate's generation index.
- */
- public int getGeneration()
- {
- return super.getAttributeAsInt(GENERATION_ATTR_NAME);
- }
-
- /**
- * Sets this candidates's unique identifier <tt>String</tt>.
- *
- * @param id this candidates's unique identifier <tt>String</tt>
- */
- public void setID(String id)
- {
- super.setAttribute(ID_ATTR_NAME, id);
- }
-
- /**
- * Returns this candidates's unique identifier <tt>String</tt>.
- *
- * @return this candidates's unique identifier <tt>String</tt>
- */
- public String getID()
- {
- return super.getAttributeAsString(ID_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's Internet Protocol (IP) address; this can be either
- * an IPv4 address or an IPv6 address.
- *
- * @param ip this candidate's IPv4 or IPv6 address.
- */
- public void setIP(String ip)
- {
- super.setAttribute(IP_ATTR_NAME, ip);
- }
-
- /**
- * Returns this candidate's Internet Protocol (IP) address; this can be
- * either an IPv4 address or an IPv6 address.
- *
- * @return this candidate's IPv4 or IPv6 address.
- */
- public String getIP()
- {
- return super.getAttributeAsString(IP_ATTR_NAME);
- }
-
- /**
- * The network index indicating the interface that the candidate belongs to.
- * The network ID is used for diagnostic purposes only in cases where the
- * calling hardware has more than one Network Interface Card.
- *
- * @param network the network index indicating the interface that the
- * candidate belongs to.
- */
- public void setNetwork(int network)
- {
- super.setAttribute(NETWORK_ATTR_NAME, network);
- }
-
- /**
- * Returns the network index indicating the interface that the candidate
- * belongs to. The network ID is used for diagnostic purposes only in cases
- * where the calling hardware has more than one Network Interface Card.
- *
- * @return the network index indicating the interface that the candidate
- * belongs to.
- */
- public int getNetwork()
- {
- return super.getAttributeAsInt(NETWORK_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's port number.
- *
- * @param port this candidate's port number.
- */
- public void setPort(int port)
- {
- super.setAttribute(PORT_ATTR_NAME, port);
- }
-
- /**
- * Returns this candidate's port number.
- *
- * @return this candidate's port number.
- */
- public int getPort()
- {
- return super.getAttributeAsInt(PORT_ATTR_NAME);
- }
-
- /**
- * This candidate's priority as defined in ICE's RFC 5245
- *
- * @param priority this candidate's priority
- */
- public void setPriority(long priority)
- {
- super.setAttribute(PRIORITY_ATTR_NAME, priority);
- }
-
- /**
- * This candidate's priority as defined in ICE's RFC 5245
- *
- * @return this candidate's priority
- */
- public int getPriority()
- {
- return super.getAttributeAsInt(PRIORITY_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's transport protocol.
- *
- * @param protocol this candidate's transport protocol.
- */
- public void setProtocol(String protocol)
- {
- super.setAttribute(PROTOCOL_ATTR_NAME, protocol);
- }
-
- /**
- * Sets this candidate's transport protocol.
- *
- * @return this candidate's transport protocol.
- */
- public String getProtocol()
- {
- return super.getAttributeAsString(PROTOCOL_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's related address as described by ICE's RFC 5245.
- *
- * @param relAddr this candidate's related address as described by ICE's
- * RFC 5245.
- */
- public void setRelAddr(String relAddr)
- {
- super.setAttribute(REL_ADDR_ATTR_NAME, relAddr);
- }
-
- /**
- * Returns this candidate's related address as described by ICE's RFC 5245.
- *
- * @return this candidate's related address as described by ICE's RFC 5245.
- */
- public String getRelAddr()
- {
- return super.getAttributeAsString(REL_ADDR_ATTR_NAME);
- }
-
- /**
- * Sets this candidate's related port as described by ICE's RFC 5245.
- *
- * @param relPort this candidate's related port as described by ICE's
- * RFC 5245.
- */
- public void setRelPort(int relPort)
- {
- super.setAttribute(REL_PORT_ATTR_NAME, relPort);
- }
-
- /**
- * Returns this candidate's related port as described by ICE's RFC 5245.
- *
- * @return this candidate's related port as described by ICE's RFC 5245.
- */
- public int getRelPort()
- {
- return super.getAttributeAsInt(REL_PORT_ATTR_NAME);
- }
-
- /**
- * Sets a Candidate Type as defined in ICE-CORE. The allowable values are
- * "host" for host candidates, "prflx" for peer reflexive candidates,
- * "relay" for relayed candidates, and "srflx" for server reflexive
- * candidates. All allowable values are enumerated in the {@link
- * CandidateType} enum.
- *
- * @param type this candidates' type as per ICE's RFC 5245.
- */
- public void setType(CandidateType type)
- {
- super.setAttribute(TYPE_ATTR_NAME, type);
- }
-
- /**
- * Returns a Candidate Type as defined in ICE-CORE. The allowable values are
- * "host" for host candidates, "prflx" for peer reflexive candidates,
- * "relay" for relayed candidates, and "srflx" for server reflexive
- * candidates. All allowable values are enumerated in the {@link
- * CandidateType} enum.
- *
- * @return this candidates' type as per ICE's RFC 5245.
- */
- public CandidateType getType()
- {
- return CandidateType.valueOf(getAttributeAsString(TYPE_ATTR_NAME));
- }
-
- /**
- * Compares this instance with another CandidatePacketExtension by
- * preference of type: host < local < prflx < srflx < stun < relay.
- *
- * @return 0 if the type are equal. -1 if this instance type is preferred.
- * Otherwise 1.
- */
- public int compareTo(CandidatePacketExtension candidatePacketExtension)
- {
- // If the types are different.
- if(this.getType() != candidatePacketExtension.getType())
- {
- CandidateType[] types = {
- CandidateType.host,
- CandidateType.local,
- CandidateType.prflx,
- CandidateType.srflx,
- CandidateType.stun,
- CandidateType.relay
- };
- for(int i = 0; i < types.length; ++i)
- {
- // this object is preferred.
- if(types[i] == this.getType())
- {
- return -1;
- }
- // the candidatePacketExtension is preferred.
- else if(types[i] == candidatePacketExtension.getType())
- {
- return 1;
- }
- }
- }
- // If the types are equal.
- return 0;
- }
-
- /**
- * Gets the TCP type for this <tt>CandidatePacketExtension</tt>.
- */
- public CandidateTcpType getTcpType()
- {
- String tcpTypeString = getAttributeAsString(TCPTYPE_ATTR_NAME);
- try
- {
- return CandidateTcpType.parse(tcpTypeString);
- }
- catch (IllegalArgumentException iae)
- {
- return null;
- }
- }
-
- /**
- * Sets the TCP type for this <tt>CandidatePacketExtension</tt>.
- * @param tcpType
- */
- public void setTcpType(CandidateTcpType tcpType)
- {
- setAttribute(TCPTYPE_ATTR_NAME, tcpType.toString());
- }
-}
+package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+import org.ice4j.ice.*;
+
+/**
+ * @author Emil Ivov
+ */
+public class CandidatePacketExtension extends AbstractPacketExtension
+ implements Comparable<CandidatePacketExtension>
+{
+ /**
+ * The name of the "candidate" element.
+ */
+ public static final String ELEMENT_NAME = "candidate";
+
+ /**
+ * The name of the "component" element.
+ */
+ public static final String COMPONENT_ATTR_NAME = "component";
+
+ /**
+ * The "component" ID for RTP components.
+ */
+ public static final int RTP_COMPONENT_ID = 1;
+
+ /**
+ * The "component" ID for RTCP components.
+ */
+ public static final int RTCP_COMPONENT_ID = 2;
+
+ /**
+ * The name of the "foundation" element.
+ */
+ public static final String FOUNDATION_ATTR_NAME = "foundation";
+
+ /**
+ * The name of the "generation" element.
+ */
+ public static final String GENERATION_ATTR_NAME = "generation";
+
+ /**
+ * The name of the "id" element.
+ */
+ public static final String ID_ATTR_NAME = "id";
+
+ /**
+ * The name of the "ip" element.
+ */
+ public static final String IP_ATTR_NAME = "ip";
+
+ /**
+ * The name of the "network" element.
+ */
+ public static final String NETWORK_ATTR_NAME = "network";
+
+ /**
+ * The name of the "port" element.
+ */
+ public static final String PORT_ATTR_NAME = "port";
+
+ /**
+ * The name of the "priority" element.
+ */
+ public static final String PRIORITY_ATTR_NAME = "priority";
+
+ /**
+ * The name of the "protocol" element.
+ */
+ public static final String PROTOCOL_ATTR_NAME = "protocol";
+
+ /**
+ * The name of the "rel-addr" element.
+ */
+ public static final String REL_ADDR_ATTR_NAME = "rel-addr";
+
+ /**
+ * The name of the "rel-port" element.
+ */
+ public static final String REL_PORT_ATTR_NAME = "rel-port";
+
+ /**
+ * The name of the "type" element.
+ */
+ public static final String TYPE_ATTR_NAME = "type";
+
+ /**
+ * The name of the "tcptype" element.
+ */
+ public static final String TCPTYPE_ATTR_NAME = "tcptype";
+
+ /**
+ * Creates a new {@link CandidatePacketExtension}
+ */
+ public CandidatePacketExtension()
+ {
+ super(null, ELEMENT_NAME);
+ }
+
+ /**
+ * Creates a new {@link CandidatePacketExtension} with the specified
+ * <tt>elementName</tt> so that this class would be usable as a
+ * <tt>RemoteCandidatePacketExtension</tt> parent.
+ *
+ * @param elementName the element name that this instance should be using.
+ */
+ protected CandidatePacketExtension(String elementName)
+ {
+ super(null, elementName);
+ }
+
+ /**
+ * Sets a component ID as defined in ICE-CORE.
+ *
+ * @param component a component ID as defined in ICE-CORE.
+ */
+ public void setComponent(int component)
+ {
+ super.setAttribute(COMPONENT_ATTR_NAME, component);
+ }
+
+ /**
+ * Returns a component ID as defined in ICE-CORE.
+ *
+ * @return a component ID as defined in ICE-CORE.
+ */
+ public int getComponent()
+ {
+ return super.getAttributeAsInt(COMPONENT_ATTR_NAME);
+ }
+
+ /**
+ * Sets the candidate foundation as defined in ICE-CORE.
+ *
+ * @param foundation the candidate foundation as defined in ICE-CORE.
+ */
+ public void setFoundation(String foundation)
+ {
+ super.setAttribute(FOUNDATION_ATTR_NAME, foundation);
+ }
+
+ /**
+ * Returns the candidate foundation as defined in ICE-CORE.
+ *
+ * @return the candidate foundation as defined in ICE-CORE.
+ */
+ public String getFoundation()
+ {
+ return super.getAttributeAsString(FOUNDATION_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's generation index. A generation is an index,
+ * starting at 0, that enables the parties to keep track of updates to the
+ * candidate throughout the life of the session. For details, see the ICE
+ * Restarts section of XEP-0176.
+ *
+ * @param generation this candidate's generation index.
+ */
+ public void setGeneration(int generation)
+ {
+ super.setAttribute(GENERATION_ATTR_NAME, generation);
+ }
+
+ /**
+ * Returns this candidate's generation. A generation is an index, starting at
+ * 0, that enables the parties to keep track of updates to the candidate
+ * throughout the life of the session. For details, see the ICE Restarts
+ * section of XEP-0176.
+ *
+ * @return this candidate's generation index.
+ */
+ public int getGeneration()
+ {
+ return super.getAttributeAsInt(GENERATION_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidates's unique identifier <tt>String</tt>.
+ *
+ * @param id this candidates's unique identifier <tt>String</tt>
+ */
+ public void setID(String id)
+ {
+ super.setAttribute(ID_ATTR_NAME, id);
+ }
+
+ /**
+ * Returns this candidates's unique identifier <tt>String</tt>.
+ *
+ * @return this candidates's unique identifier <tt>String</tt>
+ */
+ public String getID()
+ {
+ return super.getAttributeAsString(ID_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's Internet Protocol (IP) address; this can be either
+ * an IPv4 address or an IPv6 address.
+ *
+ * @param ip this candidate's IPv4 or IPv6 address.
+ */
+ public void setIP(String ip)
+ {
+ super.setAttribute(IP_ATTR_NAME, ip);
+ }
+
+ /**
+ * Returns this candidate's Internet Protocol (IP) address; this can be
+ * either an IPv4 address or an IPv6 address.
+ *
+ * @return this candidate's IPv4 or IPv6 address.
+ */
+ public String getIP()
+ {
+ return super.getAttributeAsString(IP_ATTR_NAME);
+ }
+
+ /**
+ * The network index indicating the interface that the candidate belongs to.
+ * The network ID is used for diagnostic purposes only in cases where the
+ * calling hardware has more than one Network Interface Card.
+ *
+ * @param network the network index indicating the interface that the
+ * candidate belongs to.
+ */
+ public void setNetwork(int network)
+ {
+ super.setAttribute(NETWORK_ATTR_NAME, network);
+ }
+
+ /**
+ * Returns the network index indicating the interface that the candidate
+ * belongs to. The network ID is used for diagnostic purposes only in cases
+ * where the calling hardware has more than one Network Interface Card.
+ *
+ * @return the network index indicating the interface that the candidate
+ * belongs to.
+ */
+ public int getNetwork()
+ {
+ return super.getAttributeAsInt(NETWORK_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's port number.
+ *
+ * @param port this candidate's port number.
+ */
+ public void setPort(int port)
+ {
+ super.setAttribute(PORT_ATTR_NAME, port);
+ }
+
+ /**
+ * Returns this candidate's port number.
+ *
+ * @return this candidate's port number.
+ */
+ public int getPort()
+ {
+ return super.getAttributeAsInt(PORT_ATTR_NAME);
+ }
+
+ /**
+ * This candidate's priority as defined in ICE's RFC 5245
+ *
+ * @param priority this candidate's priority
+ */
+ public void setPriority(long priority)
+ {
+ super.setAttribute(PRIORITY_ATTR_NAME, priority);
+ }
+
+ /**
+ * This candidate's priority as defined in ICE's RFC 5245
+ *
+ * @return this candidate's priority
+ */
+ public int getPriority()
+ {
+ return super.getAttributeAsInt(PRIORITY_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's transport protocol.
+ *
+ * @param protocol this candidate's transport protocol.
+ */
+ public void setProtocol(String protocol)
+ {
+ super.setAttribute(PROTOCOL_ATTR_NAME, protocol);
+ }
+
+ /**
+ * Sets this candidate's transport protocol.
+ *
+ * @return this candidate's transport protocol.
+ */
+ public String getProtocol()
+ {
+ return super.getAttributeAsString(PROTOCOL_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's related address as described by ICE's RFC 5245.
+ *
+ * @param relAddr this candidate's related address as described by ICE's
+ * RFC 5245.
+ */
+ public void setRelAddr(String relAddr)
+ {
+ super.setAttribute(REL_ADDR_ATTR_NAME, relAddr);
+ }
+
+ /**
+ * Returns this candidate's related address as described by ICE's RFC 5245.
+ *
+ * @return this candidate's related address as described by ICE's RFC 5245.
+ */
+ public String getRelAddr()
+ {
+ return super.getAttributeAsString(REL_ADDR_ATTR_NAME);
+ }
+
+ /**
+ * Sets this candidate's related port as described by ICE's RFC 5245.
+ *
+ * @param relPort this candidate's related port as described by ICE's
+ * RFC 5245.
+ */
+ public void setRelPort(int relPort)
+ {
+ super.setAttribute(REL_PORT_ATTR_NAME, relPort);
+ }
+
+ /**
+ * Returns this candidate's related port as described by ICE's RFC 5245.
+ *
+ * @return this candidate's related port as described by ICE's RFC 5245.
+ */
+ public int getRelPort()
+ {
+ return super.getAttributeAsInt(REL_PORT_ATTR_NAME);
+ }
+
+ /**
+ * Sets a Candidate Type as defined in ICE-CORE. The allowable values are
+ * "host" for host candidates, "prflx" for peer reflexive candidates,
+ * "relay" for relayed candidates, and "srflx" for server reflexive
+ * candidates. All allowable values are enumerated in the {@link
+ * CandidateType} enum.
+ *
+ * @param type this candidates' type as per ICE's RFC 5245.
+ */
+ public void setType(CandidateType type)
+ {
+ super.setAttribute(TYPE_ATTR_NAME, type);
+ }
+
+ /**
+ * Returns a Candidate Type as defined in ICE-CORE. The allowable values are
+ * "host" for host candidates, "prflx" for peer reflexive candidates,
+ * "relay" for relayed candidates, and "srflx" for server reflexive
+ * candidates. All allowable values are enumerated in the {@link
+ * CandidateType} enum.
+ *
+ * @return this candidates' type as per ICE's RFC 5245.
+ */
+ public CandidateType getType()
+ {
+ return CandidateType.valueOf(getAttributeAsString(TYPE_ATTR_NAME));
+ }
+
+ /**
+ * Compares this instance with another CandidatePacketExtension by
+ * preference of type: host < local < prflx < srflx < stun < relay.
+ *
+ * @return 0 if the type are equal. -1 if this instance type is preferred.
+ * Otherwise 1.
+ */
+ public int compareTo(CandidatePacketExtension candidatePacketExtension)
+ {
+ // If the types are different.
+ if(this.getType() != candidatePacketExtension.getType())
+ {
+ CandidateType[] types = {
+ CandidateType.host,
+ CandidateType.local,
+ CandidateType.prflx,
+ CandidateType.srflx,
+ CandidateType.stun,
+ CandidateType.relay
+ };
+ for(int i = 0; i < types.length; ++i)
+ {
+ // this object is preferred.
+ if(types[i] == this.getType())
+ {
+ return -1;
+ }
+ // the candidatePacketExtension is preferred.
+ else if(types[i] == candidatePacketExtension.getType())
+ {
+ return 1;
+ }
+ }
+ }
+ // If the types are equal.
+ return 0;
+ }
+
+ /**
+ * Gets the TCP type for this <tt>CandidatePacketExtension</tt>.
+ */
+ public CandidateTcpType getTcpType()
+ {
+ String tcpTypeString = getAttributeAsString(TCPTYPE_ATTR_NAME);
+ try
+ {
+ return CandidateTcpType.parse(tcpTypeString);
+ }
+ catch (IllegalArgumentException iae)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Sets the TCP type for this <tt>CandidatePacketExtension</tt>.
+ * @param tcpType
+ */
+ public void setTcpType(CandidateTcpType tcpType)
+ {
+ setAttribute(TCPTYPE_ATTR_NAME, tcpType.toString());
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java
index 69b2e47..3ccbd72 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/CryptoPacketExtension.java
@@ -17,6 +17,8 @@
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle;
+import java.util.Objects;
+
import ch.imvs.sdes4j.srtp.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
@@ -332,4 +334,14 @@ public class CryptoPacketExtension
}
return false;
}
+
+ @Override
+ public int hashCode()
+ {
+ return Objects.hash(
+ getCryptoSuite(),
+ getKeyParams(),
+ getSessionParams(),
+ getTag());
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java
index 1112c8c..173701f 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/IceUdpTransportPacketExtension.java
@@ -191,6 +191,27 @@ public class IceUdpTransportPacketExtension
}
/**
+ * Removes given <tt>PacketExtension</tt> from the list of child packet
+ * extensions. <tt>CandidatePacketExtension</tt> are not taken into account
+ * in this method and {@link #removeCandidate(CandidatePacketExtension)}
+ * should be used instead.
+ *
+ * @param childExtension <tt>PacketExtension</tt> instance to be removed
+ * from child packet extensions list.
+ *
+ * @return <tt>true</tt> if given <tt>childExtension</tt> has been in the
+ * list and was removed or <tt>false</tt> otherwise.
+ */
+ public boolean removeChildExtension(PacketExtension childExtension)
+ {
+ List<? extends PacketExtension> childExtensions
+ = super.getChildExtensions();
+
+ return childExtensions != null
+ && childExtensions.remove(childExtension);
+ }
+
+ /**
* Returns the list of {@link CandidatePacketExtension}s currently
* registered with this transport.
*
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java
index 9183fa0..65b0849 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQ.java
@@ -21,6 +21,7 @@ import java.math.*;
import java.security.*;
import java.util.*;
+import net.java.sip.communicator.service.protocol.jabber.*;
import org.jivesoftware.smack.packet.*;
/**
@@ -62,7 +63,8 @@ public class JingleIQ extends IQ
* The name of the argument that contains the session id.
*/
public static final String SID_ATTR_NAME = "sid";
-
+
+
/**
* The <tt>JingleAction</tt> that describes the purpose of this
* <tt>jingle</tt> element.
@@ -104,8 +106,8 @@ public class JingleIQ extends IQ
* The list of "content" elements included in this IQ.
*/
private final List<ContentPacketExtension> contentList
- = new ArrayList<ContentPacketExtension>();
-
+ = new ArrayList<ContentPacketExtension>();
+
/**
* Returns the XML string of this Jingle IQ's "section" sub-element.
*
@@ -124,17 +126,18 @@ public class JingleIQ extends IQ
if( initiator != null)
bldr.append(" " + INITIATOR_ATTR_NAME
- + "='" + getInitiator() + "'");
+ + "='" + getInitiator() + "'");
if( responder != null)
bldr.append(" " + RESPONDER_ATTR_NAME
- + "='" + getResponder() + "'");
+ + "='" + getResponder() + "'");
bldr.append(" " + SID_ATTR_NAME
- + "='" + getSID() + "'");
-
- String extensionsXML = getExtensionsXML();
+ + "='" + getSID() + "'");
+ CharSequence extensionsXMLSeq = getExtensionsXML();
+ String extensionsXML = extensionsXMLSeq.toString();
+
if ((contentList.size() == 0)
&& (reason == null)
&& (sessionInfo == null)
@@ -348,7 +351,7 @@ public class JingleIQ extends IQ
* otherwise.
*/
public boolean containsContentChildOfType(
- Class<? extends PacketExtension> contentType)
+ Class<? extends PacketExtension> contentType)
{
if(getContentForType(contentType) != null)
return true;
@@ -369,14 +372,14 @@ public class JingleIQ extends IQ
* found.
*/
public ContentPacketExtension getContentForType(
- Class<? extends PacketExtension> contentType)
+ Class<? extends PacketExtension> contentType)
{
synchronized(contentList)
{
for(ContentPacketExtension content : contentList)
{
PacketExtension child
- = content.getFirstChildOfType(contentType);
+ = content.getFirstChildOfType(contentType);
if(child != null)
return content;
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
index 11f909a..49934e5 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/JingleIQProvider.java
@@ -20,6 +20,7 @@ package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet.*;
+import net.java.sip.communicator.service.protocol.jabber.*;
import org.jivesoftware.smack.provider.*;
import org.xmlpull.v1.*;
@@ -37,174 +38,187 @@ public class JingleIQProvider implements IQProvider
*/
public JingleIQProvider()
{
- ProviderManager providerManager = ProviderManager.getInstance();
+
+ AbstractSmackInteroperabilityLayer smackInteroperabilityLayer =
+ AbstractSmackInteroperabilityLayer.getInstance();
//<description/> provider
- providerManager.addExtensionProvider(
- RtpDescriptionPacketExtension.ELEMENT_NAME,
- RtpDescriptionPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <RtpDescriptionPacketExtension>(
- RtpDescriptionPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ RtpDescriptionPacketExtension.ELEMENT_NAME,
+ RtpDescriptionPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <RtpDescriptionPacketExtension>(
+ RtpDescriptionPacketExtension.class));
//<payload-type/> provider
- providerManager.addExtensionProvider(
- PayloadTypePacketExtension.ELEMENT_NAME,
- RtpDescriptionPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <PayloadTypePacketExtension>(
- PayloadTypePacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ PayloadTypePacketExtension.ELEMENT_NAME,
+ RtpDescriptionPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <PayloadTypePacketExtension>(
+ PayloadTypePacketExtension.class));
//<parameter/> provider
- providerManager.addExtensionProvider(
- ParameterPacketExtension.ELEMENT_NAME,
- RtpDescriptionPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <ParameterPacketExtension>(ParameterPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ ParameterPacketExtension.ELEMENT_NAME,
+ RtpDescriptionPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <ParameterPacketExtension>
+ (ParameterPacketExtension.class));
//<rtp-hdrext/> provider
- providerManager.addExtensionProvider(
- RTPHdrExtPacketExtension.ELEMENT_NAME,
- RTPHdrExtPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <RTPHdrExtPacketExtension>(RTPHdrExtPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ RTPHdrExtPacketExtension.ELEMENT_NAME,
+ RTPHdrExtPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <RTPHdrExtPacketExtension>
+ (RTPHdrExtPacketExtension.class));
// <sctpmap/> provider
- providerManager.addExtensionProvider(
- SctpMapExtension.ELEMENT_NAME,
- SctpMapExtension.NAMESPACE,
- new SctpMapExtensionProvider());
+ smackInteroperabilityLayer.addExtensionProvider(
+ SctpMapExtension.ELEMENT_NAME,
+ SctpMapExtension.NAMESPACE,
+ new SctpMapExtensionProvider());
//<encryption/> provider
- providerManager.addExtensionProvider(
- EncryptionPacketExtension.ELEMENT_NAME,
- RtpDescriptionPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <EncryptionPacketExtension>(EncryptionPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ EncryptionPacketExtension.ELEMENT_NAME,
+ RtpDescriptionPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <EncryptionPacketExtension>
+ (EncryptionPacketExtension.class));
//<zrtp-hash/> provider
- providerManager.addExtensionProvider(
- ZrtpHashPacketExtension.ELEMENT_NAME,
- ZrtpHashPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <ZrtpHashPacketExtension>(ZrtpHashPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ ZrtpHashPacketExtension.ELEMENT_NAME,
+ ZrtpHashPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <ZrtpHashPacketExtension>
+ (ZrtpHashPacketExtension.class));
//<crypto/> provider
- providerManager.addExtensionProvider(
- CryptoPacketExtension.ELEMENT_NAME,
- RtpDescriptionPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <CryptoPacketExtension>(CryptoPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ CryptoPacketExtension.ELEMENT_NAME,
+ RtpDescriptionPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <CryptoPacketExtension>
+ (CryptoPacketExtension.class));
// <bundle/> provider
- providerManager.addExtensionProvider(
- BundlePacketExtension.ELEMENT_NAME,
- BundlePacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <BundlePacketExtension>(BundlePacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ BundlePacketExtension.ELEMENT_NAME,
+ BundlePacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <BundlePacketExtension>
+ (BundlePacketExtension.class));
// <group/> provider
- providerManager.addExtensionProvider(
- GroupPacketExtension.ELEMENT_NAME,
- GroupPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider
- <GroupPacketExtension>(GroupPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ GroupPacketExtension.ELEMENT_NAME,
+ GroupPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <GroupPacketExtension>(GroupPacketExtension.class));
//ice-udp transport
- providerManager.addExtensionProvider(
- IceUdpTransportPacketExtension.ELEMENT_NAME,
- IceUdpTransportPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<IceUdpTransportPacketExtension>(
- IceUdpTransportPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ IceUdpTransportPacketExtension.ELEMENT_NAME,
+ IceUdpTransportPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <IceUdpTransportPacketExtension>(
+ IceUdpTransportPacketExtension.class));
//<raw-udp/> provider
- providerManager.addExtensionProvider(
- RawUdpTransportPacketExtension.ELEMENT_NAME,
- RawUdpTransportPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<RawUdpTransportPacketExtension>(
- RawUdpTransportPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ RawUdpTransportPacketExtension.ELEMENT_NAME,
+ RawUdpTransportPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <RawUdpTransportPacketExtension>(
+ RawUdpTransportPacketExtension.class));
//ice-udp <candidate/> provider
- providerManager.addExtensionProvider(
- CandidatePacketExtension.ELEMENT_NAME,
- IceUdpTransportPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<CandidatePacketExtension>(
- CandidatePacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ CandidatePacketExtension.ELEMENT_NAME,
+ IceUdpTransportPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <CandidatePacketExtension>(
+ CandidatePacketExtension.class));
//raw-udp <candidate/> provider
- providerManager.addExtensionProvider(
- CandidatePacketExtension.ELEMENT_NAME,
- RawUdpTransportPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<CandidatePacketExtension>(
- CandidatePacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ CandidatePacketExtension.ELEMENT_NAME,
+ RawUdpTransportPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <CandidatePacketExtension>(
+ CandidatePacketExtension.class));
//ice-udp <remote-candidate/> provider
- providerManager.addExtensionProvider(
- RemoteCandidatePacketExtension.ELEMENT_NAME,
- IceUdpTransportPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<RemoteCandidatePacketExtension>(
- RemoteCandidatePacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ RemoteCandidatePacketExtension.ELEMENT_NAME,
+ IceUdpTransportPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider
+ <RemoteCandidatePacketExtension>(
+ RemoteCandidatePacketExtension.class));
//inputevt <inputevt/> provider
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
InputEvtPacketExtension.ELEMENT_NAME,
InputEvtPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<InputEvtPacketExtension>(
InputEvtPacketExtension.class));
//coin <conference-info/> provider
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
CoinPacketExtension.ELEMENT_NAME,
CoinPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<CoinPacketExtension>(
CoinPacketExtension.class));
// DTLS-SRTP
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
DtlsFingerprintPacketExtension.ELEMENT_NAME,
DtlsFingerprintPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider
- <DtlsFingerprintPacketExtension>(
+ <DtlsFingerprintPacketExtension>(
DtlsFingerprintPacketExtension.class));
/*
* XEP-0251: Jingle Session Transfer <transfer/> and <transferred>
* providers
*/
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
TransferPacketExtension.ELEMENT_NAME,
TransferPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<TransferPacketExtension>(
TransferPacketExtension.class));
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
TransferredPacketExtension.ELEMENT_NAME,
TransferredPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<TransferredPacketExtension>(
TransferredPacketExtension.class));
//conference description <callid/> provider
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
ConferenceDescriptionPacketExtension.CALLID_ELEM_NAME,
ConferenceDescriptionPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<CallIdPacketExtension>(
CallIdPacketExtension.class));
//rtcp-fb
- providerManager.addExtensionProvider(
- RtcpFbPacketExtension.ELEMENT_NAME,
- RtcpFbPacketExtension.NAMESPACE,
- new DefaultPacketExtensionProvider<RtcpFbPacketExtension>(
- RtcpFbPacketExtension.class));
+ smackInteroperabilityLayer.addExtensionProvider(
+ RtcpFbPacketExtension.ELEMENT_NAME,
+ RtcpFbPacketExtension.NAMESPACE,
+ new DefaultPacketExtensionProvider<RtcpFbPacketExtension>(
+ RtcpFbPacketExtension.class));
//rtcp-mux
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
RtcpmuxPacketExtension.ELEMENT_NAME,
IceUdpTransportPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<RtcpmuxPacketExtension>(
RtcpmuxPacketExtension.class));
//ssrcInfo
- providerManager.addExtensionProvider(
+ smackInteroperabilityLayer.addExtensionProvider(
SSRCInfoPacketExtension.ELEMENT_NAME,
SSRCInfoPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider<SSRCInfoPacketExtension>(
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java
new file mode 100644
index 0000000..bcc3397
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/ComponentVersionsExtension.java
@@ -0,0 +1,135 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+/**
+ * The packet extension is used by Jicofo to broadcast versions of all video
+ * conferencing system components. This packets extension is added to jicofo's
+ * MUC presence. It will contain {@link Component} children which carry each
+ * component's name and version.
+ *
+ * @author Pawel Domas
+ */
+public class ComponentVersionsExtension
+ extends AbstractPacketExtension
+{
+ /**
+ * The XML element name of {@link ComponentVersionsExtension}.
+ */
+ public static final String ELEMENT_NAME = "versions";
+
+ /**
+ * The name of XML sub-elements which carry the info about particular
+ * component's version.
+ */
+ public static final String COMPONENT_ELEMENT_NAME = "component";
+
+ /**
+ * Constant for {@link Component} name used to signal the version of
+ * conference focus.
+ */
+ public static final String COMPONENT_FOCUS = "focus";
+
+ /**
+ * Constant for {@link Component} name used to signal the version of
+ * XMPP server.
+ */
+ public static final String COMPONENT_XMPP_SERVER = "xmpp";
+
+ /**
+ * Constant for {@link Component} name used to signal the version of
+ * the videobridge.
+ */
+ public static final String COMPONENT_VIDEOBRIDGE = "videobridge";
+
+ /**
+ * The XML element namespace of {@link ComponentVersionsExtension}.
+ */
+ public static final String NAMESPACE = "http://jitsi.org/jitmeet";
+
+ /**
+ * Creates an {@link AbstractPacketExtension} instance for the specified
+ * <tt>namespace</tt> and <tt>elementName</tt>.
+ */
+ public ComponentVersionsExtension()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Adds component's version to this extension.
+ *
+ * @param componentName the name of the component for which
+ * child {@link Component} extension will be added.
+ * @param versionStr human readable string that describes component's
+ * version.
+ */
+ public void addComponentVersion(String componentName, String versionStr)
+ {
+ Component v = new Component();
+
+ v.setName(componentName);
+ v.setText(versionStr);
+
+ addChildExtension(v);
+ }
+
+ /**
+ * Component child element of {@link ComponentVersionsExtension}. The name
+ * of the component is carried in name attribute and the version string is
+ * the text value.
+ */
+ public class Component
+ extends AbstractPacketExtension
+ {
+ /**
+ * The name of that attribute that carries component's name.
+ */
+ private final String NAME_ATTR_NAME = "name";
+
+ /**
+ * Creates new instance of {@link Component} packet extension.
+ */
+ public Component()
+ {
+ super(NAMESPACE, COMPONENT_ELEMENT_NAME);
+ }
+
+ /**
+ * Returns the value of the name attribute.
+ * @return <tt>String</tt> which describes the name of video
+ * conferencing system component.
+ */
+ public String getName()
+ {
+ return getAttributeAsString(NAME_ATTR_NAME);
+ }
+
+ /**
+ * Sets new value for the component's name attribute.
+ * @param name a <tt>String</tt> which describes the name of video
+ * conferencing system component.
+ */
+ public void setName(String name)
+ {
+ setAttribute(NAME_ATTR_NAME, name);
+ }
+ }
+}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java
index 239c708..7384c9e 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/SSRCInfoPacketExtension.java
@@ -1,8 +1,19 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
- * Distributable under LGPL license.
- * See terms of license at gnu.org.
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet;
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java
new file mode 100644
index 0000000..cf76d89
--- /dev/null
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jitsimeet/VideoMutedExtension.java
@@ -0,0 +1,70 @@
+/*
+ * Jitsi, the OpenSource Java VoIP and Instant Messaging client.
+ *
+ * Copyright @ 2015 Atlassian Pty Ltd
+ *
+ * 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 net.java.sip.communicator.impl.protocol.jabber.extensions.jitsimeet;
+
+import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
+
+/**
+ * Video muted extension that is included in users presence in Jitsi-meet
+ * conferences. It does carry the info about user's video muted status.
+ *
+ * @author Pawel Domas
+ */
+public class VideoMutedExtension
+ extends AbstractPacketExtension
+{
+ /**
+ * The namespace of this packet extension.
+ */
+ public static final String NAMESPACE = "http://jitsi.org/jitmeet/video";
+
+ /**
+ * XML element name of this packet extension.
+ */
+ public static final String ELEMENT_NAME = "videomuted";
+
+ /**
+ * Creates new instance of <tt>VideoMutedExtension</tt>.
+ */
+ public VideoMutedExtension()
+ {
+ super(NAMESPACE, ELEMENT_NAME);
+ }
+
+ /**
+ * Check whether or not user's video is in muted status.
+ * @return <tt>true</tt> if muted, <tt>false</tt> if unmuted or
+ * <tt>null</tt> if no valid info found in the extension body.
+ */
+ public Boolean isVideoMuted()
+ {
+ return Boolean.valueOf(getText());
+ }
+
+ /**
+ * Sets user's video muted status.
+ *
+ * @param videoMuted <tt>true</tt> or <tt>false</tt> which indicates video
+ * muted status of the user.
+ */
+ public void setVideoMuted(Boolean videoMuted)
+ {
+ setText(
+ String.valueOf(videoMuted));
+ }
+}