diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
index 7c5c69024..832dda2e9 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/AbstractCallPeerMediaHandlerJabberGTalkImpl.java
@@ -6,8 +6,6 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
-import ch.imvs.sdes4j.srtp.*;
-
import java.util.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
@@ -18,11 +16,14 @@
import org.jitsi.service.neomedia.*;
import org.jivesoftware.smack.packet.*;
+import ch.imvs.sdes4j.srtp.*;
+
/**
* An implementation of the CallPeerMediaHandler abstract class for the
* common part of Jabber and Gtalk protocols.
*
* @author Vincent Lucas
+ * @author Lyubomir Marinov
*/
public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
>
@@ -84,7 +85,7 @@ public void setLocalInputEvtAware(boolean enable)
* contains the PAYLOAD-TYPE and (more important here) the ENCRYPTION.
* @param mediaType The type of media (AUDIO or VIDEO).
*/
- protected void addZRTPAdvertisedEncryptions(
+ protected void addZrtpAdvertisedEncryptions(
boolean isInitiator,
RtpDescriptionPacketExtension description,
MediaType mediaType)
@@ -131,7 +132,7 @@ && getPeer().getCall().isSipZrtpAttribute())
* contains the PAYLOAD-TYPE and (more important here) the ENCRYPTION.
* @param mediaType The type of media (AUDIO or VIDEO).
*/
- protected void addSDESAdvertisedEncryptions(
+ protected void addSDesAdvertisedEncryptions(
boolean isInitiator,
RtpDescriptionPacketExtension description,
MediaType mediaType)
@@ -380,7 +381,7 @@ protected boolean setSDesEncryptionToDescription(
= accountID.getAccountPropertyString(
ProtocolProviderFactory.SDES_CIPHER_SUITES);
- if (ciphers == null)
+ if (ciphers == null)
{
ciphers =
JabberActivator.getResources().getSettingsString(
@@ -475,8 +476,8 @@ protected boolean setSDesEncryptionToDescription(
* @param localDescription The element containing the media DESCRIPTION and
* its encryption.
* @param remoteDescription The element containing the media DESCRIPTION and
- * its encryption for the remote peer. Null, if the local peer is the
- * initiator of the call.
+ * its encryption for the remote peer; null if the local peer is
+ * the initiator of the call.
*/
protected void setAndAddPreferredEncryptionProtocol(
MediaType mediaType,
@@ -497,41 +498,71 @@ protected void setAndAddPreferredEncryptionProtocol(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL.length()
+ 1);
- // SDES
- if(SDesControl.PROTO_NAME.equals(protoName))
+ if (setAndAddPreferredEncryptionProtocol(
+ protoName,
+ mediaType,
+ localDescription,
+ remoteDescription))
+ {
+ // Stop once an encryption advertisement has been chosen.
+ return;
+ }
+ }
+ }
+
+ /**
+ * Selects a specific encryption protocol if it is the preferred (only used
+ * by the callee).
+ *
+ * @param protoName the name of the encryption protocol which is to be
+ * selected
+ * @param mediaType The type of media (AUDIO or VIDEO).
+ * @param localDescription The element containing the media DESCRIPTION and
+ * its encryption.
+ * @param remoteDescription The element containing the media DESCRIPTION and
+ * its encryption for the remote peer; null if the local peer is
+ * the initiator of the call.
+ * @return true if the specified encryption protocol has been
+ * selected; false, otherwise
+ */
+ protected boolean setAndAddPreferredEncryptionProtocol(
+ String protoName,
+ MediaType mediaType,
+ RtpDescriptionPacketExtension localDescription,
+ RtpDescriptionPacketExtension remoteDescription)
+ {
+ // SDES
+ if(SDesControl.PROTO_NAME.equals(protoName))
+ {
+ addSDesAdvertisedEncryptions(
+ false,
+ remoteDescription,
+ mediaType);
+ if(setSDesEncryptionToDescription(
+ mediaType,
+ localDescription,
+ remoteDescription))
+ {
+ // Stop once an encryption advertisement has been chosen.
+ return true;
+ }
+ }
+ // ZRTP
+ else if(ZrtpControl.PROTO_NAME.equals(protoName))
+ {
+ if(setZrtpEncryptionToDescription(
+ mediaType,
+ localDescription,
+ remoteDescription))
{
- addSDESAdvertisedEncryptions(
+ addZrtpAdvertisedEncryptions(
false,
remoteDescription,
mediaType);
- if(setSDesEncryptionToDescription(
- mediaType,
- localDescription,
- remoteDescription))
- {
- // Stop once an encryption advertisement has been chosen.
- return;
- }
- }
- // ZRTP
- else if(ZrtpControl.PROTO_NAME.equals(protoName))
- {
- boolean isZRTPAddedToDescription
- = setZrtpEncryptionToDescription(
- mediaType,
- localDescription,
- remoteDescription);
-
- if(isZRTPAddedToDescription)
- {
- addZRTPAdvertisedEncryptions(
- false,
- remoteDescription,
- mediaType);
- // Stop once an encryption advertisement has been chosen.
- return;
- }
+ // Stop once an encryption advertisement has been chosen.
+ return true;
}
}
+ return false;
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
index b15f0fb23..726d12fe9 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerJabberImpl.java
@@ -979,7 +979,7 @@ public void processTransportInfo(JingleIQ jingleIQ)
}
getMediaHandler().processTransportInfo(
- jingleIQ.getContentList());
+ jingleIQ.getContentList());
}
catch (OperationFailedException ofe)
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerGTalkImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerGTalkImpl.java
index 6c4e190d3..1007f9784 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerGTalkImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerGTalkImpl.java
@@ -362,8 +362,8 @@ public void processAnswer(RtpDescriptionPacketExtension answer)
if(format == null)
continue;
- addZRTPAdvertisedEncryptions(true, answer, mediaType);
- addSDESAdvertisedEncryptions(true, answer, mediaType);
+ addZrtpAdvertisedEncryptions(true, answer, mediaType);
+ addSDesAdvertisedEncryptions(true, answer, mediaType);
// stream connector
StreamConnector connector
@@ -521,7 +521,6 @@ public RtpDescriptionPacketExtension createDescription()
mediaType,
description,
null);
-
//ZRTP
setZrtpEncryptionToDescription(
mediaType,
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
index 727b735bf..31d0e4b7f 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
@@ -267,6 +267,8 @@ && isRTPTranslationEnabled(mediaType)))
RtpDescriptionPacketExtension description
= JingleUtils.getRtpDescription(content);
+ // DTLS-SRTP
+ setDtlsEncryptionToContent(mediaType, content, null);
//SDES
// It is important to set SDES before ZRTP in order to make GTALK
// application able to work with SDES.
@@ -320,13 +322,13 @@ private ContentPacketExtension createContentForOffer(
{
ContentPacketExtension content
= JingleUtils.createDescription(
- ContentPacketExtension.CreatorEnum.initiator,
- supportedFormats.get(0).getMediaType().toString(),
- JingleUtils.getSenders(direction, !getPeer().isInitiator()),
- supportedFormats,
- supportedExtensions,
- getDynamicPayloadTypes(),
- getRtpExtensionsRegistry());
+ ContentPacketExtension.CreatorEnum.initiator,
+ supportedFormats.get(0).getMediaType().toString(),
+ JingleUtils.getSenders(direction, !getPeer().isInitiator()),
+ supportedFormats,
+ supportedExtensions,
+ getDynamicPayloadTypes(),
+ getRtpExtensionsRegistry());
this.localContentMap.put(content.getName(), content);
return content;
@@ -390,6 +392,8 @@ && isRTPTranslationEnabled(mediaType)))
RtpDescriptionPacketExtension description
= JingleUtils.getRtpDescription(content);
+ // DTLS-SRTP
+ setDtlsEncryptionToContent(mediaType, content, null);
//SDES
// It is important to set SDES before ZRTP in order to make
// GTALK application able to work with SDES.
@@ -542,11 +546,10 @@ public Iterable generateSessionAccept()
//user answered an incoming call so we go through whatever content
//entries we are initializing and init their corresponding streams
- // First parse content so we know how may streams,
- // and what type of content we have
- Map contents
- = new HashMap();
+ // First parse content so we know how many streams and what type of
+ // content we have
+ Map contents
+ = new HashMap();
for(ContentPacketExtension ourContent : sessAccept)
{
@@ -1065,7 +1068,6 @@ private List harvestCandidates(
throws OperationFailedException
{
long startCandidateHarvestTime = System.currentTimeMillis();
-
TransportManagerJabberImpl transportManager = getTransportManager();
if (remote == null)
@@ -1090,11 +1092,19 @@ private List harvestCandidates(
}
long stopCandidateHarvestTime = System.currentTimeMillis();
- long candidateHarvestTime
- = stopCandidateHarvestTime - startCandidateHarvestTime;
+
if (logger.isInfoEnabled())
- logger.info("End candidate harvest within "
- + candidateHarvestTime + " ms");
+ {
+ long candidateHarvestTime
+ = stopCandidateHarvestTime - startCandidateHarvestTime;
+
+ logger.info(
+ "End candidate harvest within " + candidateHarvestTime
+ + " ms");
+ }
+
+ setDtlsEncryptionToTransports(local);
+
/*
* TODO Ideally, we wouldn't wrap up that quickly. We need to revisit
* this.
@@ -1220,7 +1230,7 @@ public void processAnswer(List answer)
RtpDescriptionPacketExtension description
= JingleUtils.getRtpDescription(content);
MediaType mediaType
- = MediaType.parseString( description.getMedia() );
+ = MediaType.parseString(description.getMedia());
if(answer.size() > 1)
{
@@ -1408,8 +1418,9 @@ private void processContent(
logger);
}
- addZRTPAdvertisedEncryptions(true, description, mediaType);
- addSDESAdvertisedEncryptions(true, description, mediaType);
+ addZrtpAdvertisedEncryptions(true, description, mediaType);
+ addSDesAdvertisedEncryptions(true, description, mediaType);
+ addDtlsAdvertisedEncryptions(true, content, mediaType);
StreamConnector connector
= transportManager.getStreamConnector(mediaType);
@@ -1573,7 +1584,9 @@ public void processOffer(List offer)
// intersect the MediaFormats of our device with remote ones
List mutuallySupportedFormats
- = intersectFormats(remoteFormats, getLocallySupportedFormats(dev));
+ = intersectFormats(
+ remoteFormats,
+ getLocallySupportedFormats(dev));
// check whether we will be exchanging any RTP extensions.
List offeredRTPExtensions
@@ -1649,14 +1662,14 @@ public void processOffer(List offer)
getDynamicPayloadTypes(),
getRtpExtensionsRegistry());
- RtpDescriptionPacketExtension localDescription =
- JingleUtils.getRtpDescription(ourContent);
-
- // Sets ZRTP or SDES, depending on the preferences for this account.
+ /*
+ * Sets ZRTP, SDES or DTLS-SRTP depending on the preferences for
+ * this account.
+ */
setAndAddPreferredEncryptionProtocol(
mediaType,
- localDescription,
- description);
+ ourContent,
+ content);
// Got a content which has inputevt. It means that the peer requests
// a desktop sharing session so tell it we support inputevt.
@@ -2163,4 +2176,343 @@ public void setLocallyOnHold(boolean locallyOnHold)
}
}
+ /**
+ * Detects and adds DTLS-SRTP available encryption method present in the
+ * content (description) given in parameter.
+ *
+ * @param isInitiator true if the local call instance is the
+ * initiator of the call; false, otherwise.
+ * @param content The CONTENT element of the JINGLE element which contains
+ * the TRANSPORT element
+ * @param mediaType The type of media (AUDIO or VIDEO).
+ */
+ private boolean addDtlsAdvertisedEncryptions(
+ boolean isInitiator,
+ ContentPacketExtension content,
+ MediaType mediaType)
+ {
+ IceUdpTransportPacketExtension remoteTransport
+ = content.getFirstChildOfType(IceUdpTransportPacketExtension.class);
+ SrtpControls srtpControls = getSrtpControls();
+ boolean b = false;
+
+ if (remoteTransport != null)
+ {
+ List remoteFingerpintPEs
+ = remoteTransport.getChildExtensionsOfType(
+ DtlsFingerprintPacketExtension.class);
+
+ if (!remoteFingerpintPEs.isEmpty())
+ {
+ AccountID accountID
+ = getPeer().getProtocolProvider().getAccountID();
+
+ if (accountID.getAccountPropertyBoolean(
+ ProtocolProviderFactory.DEFAULT_ENCRYPTION,
+ true)
+ && accountID.isEncryptionProtocolEnabled(
+ DtlsControl.PROTO_NAME))
+ {
+ Map remoteFingerprints
+ = new LinkedHashMap();
+
+ for (DtlsFingerprintPacketExtension remoteFingerprintPE
+ : remoteFingerpintPEs)
+ {
+ String remoteFingerprint
+ = remoteFingerprintPE.getFingerprint();
+ String remoteHash = remoteFingerprintPE.getHash();
+
+ remoteFingerprints.put(
+ remoteHash,
+ remoteFingerprint);
+ }
+
+ DtlsControl dtlsControl;
+ int dtlsProtocol;
+
+ if (isInitiator)
+ {
+ dtlsControl
+ = (DtlsControl)
+ srtpControls.get(
+ mediaType,
+ SrtpControlType.DTLS_SRTP);
+ dtlsProtocol = DtlsControl.DTLS_SERVER_PROTOCOL;
+ }
+ else
+ {
+ dtlsControl
+ = (DtlsControl)
+ srtpControls.getOrCreate(
+ mediaType,
+ SrtpControlType.DTLS_SRTP);
+ dtlsProtocol = DtlsControl.DTLS_CLIENT_PROTOCOL;
+ }
+ if (dtlsControl != null)
+ {
+ dtlsControl.setDtlsProtocol(dtlsProtocol);
+ dtlsControl.setRemoteFingerprints(remoteFingerprints);
+ removeAndCleanupOtherSrtpControls(
+ mediaType,
+ SrtpControlType.DTLS_SRTP);
+ addAdvertisedEncryptionMethod(
+ SrtpControlType.DTLS_SRTP);
+ b = true;
+ }
+ }
+ }
+ }
+ /*
+ * If they haven't advertised DTLS-SRTP in their (media) description,
+ * then DTLS-SRTP shouldn't be functioning as far as we're concerned.
+ */
+ if (!b)
+ {
+ SrtpControl dtlsControl
+ = srtpControls.get(mediaType, SrtpControlType.DTLS_SRTP);
+
+ if (dtlsControl != null)
+ {
+ srtpControls.remove(mediaType, SrtpControlType.DTLS_SRTP);
+ dtlsControl.cleanup();
+ }
+ }
+ return b;
+ }
+
+ /**
+ * Selects the preferred encryption protocol (only used by the callee).
+ *
+ * @param mediaType The type of media (AUDIO or VIDEO).
+ * @param localContent The element containing the media DESCRIPTION and
+ * its encryption.
+ * @param remoteContent The element containing the media DESCRIPTION and
+ * its encryption for the remote peer; null if the local peer is
+ * the initiator of the call.
+ */
+ private void setAndAddPreferredEncryptionProtocol(
+ MediaType mediaType,
+ ContentPacketExtension localContent,
+ ContentPacketExtension remoteContent)
+ {
+ List preferredEncryptionProtocols
+ = getPeer()
+ .getProtocolProvider()
+ .getAccountID()
+ .getSortedEnabledEncryptionProtocolList();
+
+ for (String preferredEncryptionProtocol : preferredEncryptionProtocols)
+ {
+ String protoName
+ = preferredEncryptionProtocol.substring(
+ ProtocolProviderFactory.ENCRYPTION_PROTOCOL.length()
+ + 1);
+
+ // DTLS-SRTP
+ if (DtlsControl.PROTO_NAME.equals(protoName))
+ {
+ addDtlsAdvertisedEncryptions(
+ false,
+ remoteContent,
+ mediaType);
+ if (setDtlsEncryptionToContent(
+ mediaType,
+ localContent,
+ remoteContent))
+ {
+ // Stop once an encryption advertisement has been chosen.
+ return;
+ }
+ }
+ else
+ {
+ RtpDescriptionPacketExtension localDescription
+ = (localContent == null)
+ ? null
+ : JingleUtils.getRtpDescription(localContent);
+ RtpDescriptionPacketExtension remoteDescription
+ = (remoteContent == null)
+ ? null
+ : JingleUtils.getRtpDescription(remoteContent);
+
+ if (setAndAddPreferredEncryptionProtocol(
+ protoName,
+ mediaType,
+ localDescription,
+ remoteDescription))
+ {
+ // Stop once an encryption advertisement has been chosen.
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets DTLS-SRTP element(s) to the TRANSPORT element of the CONTENT for a
+ * given media.
+ *
+ * @param mediaType The type of media we are modifying the CONTENT to
+ * integrate the DTLS-SRTP element(s).
+ * @param localContent The element containing the media CONTENT and its
+ * TRANSPORT.
+ * @param remoteContent The element containing the media CONTENT and its
+ * TRANSPORT for the remote peer. Null, if the local peer is the initiator
+ * of the call.
+ * @return true if any DTLS-SRTP element has been added to the
+ * specified localContent; false, otherwise.
+ */
+ private boolean setDtlsEncryptionToContent(
+ MediaType mediaType,
+ ContentPacketExtension localContent,
+ ContentPacketExtension remoteContent)
+ {
+ CallPeerJabberImpl peer = getPeer();
+ ProtocolProviderServiceJabberImpl protocolProvider
+ = peer.getProtocolProvider();
+ AccountID accountID = protocolProvider.getAccountID();
+ SrtpControls srtpControls = getSrtpControls();
+ boolean b = false;
+
+ if (accountID.getAccountPropertyBoolean(
+ ProtocolProviderFactory.DEFAULT_ENCRYPTION,
+ true)
+ && accountID.isEncryptionProtocolEnabled(
+ DtlsControl.PROTO_NAME))
+ {
+ boolean addFingerprintToLocalTransport;
+
+ if (remoteContent == null) // initiator
+ {
+ addFingerprintToLocalTransport
+ = protocolProvider.isFeatureSupported(
+ peer.getAddress(),
+ ProtocolProviderServiceJabberImpl
+ .URN_XMPP_JINGLE_DTLS_SRTP);
+ }
+ else // responder
+ {
+ addFingerprintToLocalTransport
+ = addDtlsAdvertisedEncryptions(
+ false,
+ remoteContent,
+ mediaType);
+ }
+ if (addFingerprintToLocalTransport)
+ {
+ DtlsControl dtlsControl
+ = (DtlsControl)
+ srtpControls.getOrCreate(
+ mediaType,
+ SrtpControlType.DTLS_SRTP);
+
+ if (dtlsControl != null)
+ {
+ int dtlsProtocol
+ = (remoteContent == null)
+ ? DtlsControl.DTLS_SERVER_PROTOCOL
+ : DtlsControl.DTLS_CLIENT_PROTOCOL;
+
+ dtlsControl.setDtlsProtocol(dtlsProtocol);
+ b = true;
+
+ setDtlsEncryptionToTransport(mediaType, localContent);
+ }
+ }
+ }
+ /*
+ * If we haven't advertised DTLS-SRTP in our (media) description, then
+ * DTLS-SRTP shouldn't be functioning as far as we're concerned.
+ */
+ if (!b)
+ {
+ SrtpControl dtlsControl
+ = srtpControls.get(mediaType, SrtpControlType.DTLS_SRTP);
+
+ if (dtlsControl != null)
+ {
+ srtpControls.remove(mediaType, SrtpControlType.DTLS_SRTP);
+ dtlsControl.cleanup();
+ }
+ }
+ return b;
+ }
+
+ /**
+ * Sets DTLS-SRTP element(s) to the TRANSPORT element of the CONTENT for a
+ * given media.
+ *
+ * @param mediaType The type of media we are modifying the CONTENT to
+ * integrate the DTLS-SRTP element(s).
+ * @param localContent The element containing the media CONTENT and its
+ * TRANSPORT.
+ */
+ private void setDtlsEncryptionToTransport(
+ MediaType mediaType,
+ ContentPacketExtension localContent)
+ {
+ SrtpControls srtpControls = getSrtpControls();
+ DtlsControl dtlsControl
+ = (DtlsControl)
+ srtpControls.get(
+ mediaType,
+ SrtpControlType.DTLS_SRTP);
+
+ if (dtlsControl != null)
+ {
+ IceUdpTransportPacketExtension localTransport
+ = localContent.getFirstChildOfType(
+ IceUdpTransportPacketExtension.class);
+
+ if (localTransport != null)
+ {
+ String localFingerprint = dtlsControl.getLocalFingerprint();
+ String localFingerprintHashFunction
+ = dtlsControl.getLocalFingerprintHashFunction();
+
+ {
+ DtlsFingerprintPacketExtension localFingerprintPE
+ = localTransport.getFirstChildOfType(
+ DtlsFingerprintPacketExtension.class);
+
+ if (localFingerprintPE == null)
+ {
+ localFingerprintPE
+ = new DtlsFingerprintPacketExtension();
+ localTransport.addChildExtension(
+ localFingerprintPE);
+ }
+ localFingerprintPE.setFingerprint(localFingerprint);
+ localFingerprintPE.setHash(
+ localFingerprintHashFunction);
+ }
+ }
+ }
+ }
+
+ /**
+ * Sets DTLS-SRTP element(s) to the TRANSPORT element of a specified list of
+ * CONTENT elements.
+ *
+ * @param localContents The elements containing the media CONTENT elements
+ * and their respective TRANSPORT elements.
+ */
+ private void setDtlsEncryptionToTransports(
+ List localContents)
+ {
+ for (ContentPacketExtension localContent : localContents)
+ {
+ RtpDescriptionPacketExtension description
+ = JingleUtils.getRtpDescription(localContent);
+
+ if (description != null)
+ {
+ MediaType mediaType = JingleUtils.getMediaType(localContent);
+
+ if (mediaType != null)
+ setDtlsEncryptionToTransport(mediaType, localContent);
+ }
+ }
+ }
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
index afe59a2a6..96cf9daec 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ContactJabberImpl.java
@@ -14,8 +14,6 @@
import net.java.sip.communicator.service.protocol.jabberconstants.*;
import org.jivesoftware.smack.*;
-import org.jivesoftware.smack.packet.*;
-import org.jivesoftware.smack.util.*;
/**
* The Jabber implementation of the service.protocol.Contact interface.
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
index 2e70e4879..024d7f23e 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/IceUdpTransportManager.java
@@ -583,17 +583,18 @@ public void startCandidateHarvest(
transportInfoContent.addChildExtension(
createTransport(stream));
- /* We send each media content in separate transport-info.
- * It is absolutely not mandatory (we can simply send all
- * content in one transport-info) but the XMPP Jingle client
- * Empathy (via telepathy-gabble), which is present on many
- * Linux distributions and N900 mobile phone, has a bug when
- * it receives more than one content in transport-info.
+ /*
+ * We send each media content in separate transport-info. It is
+ * absolutely not mandatory (we can simply send all content in
+ * one transport-info) but the XMPP Jingle client Empathy (via
+ * telepathy-gabble), which is present on many Linux
+ * distributions and N900 mobile phone, has a bug when it
+ * receives more than one content in transport-info.
*
- * The related bug has been fixed in mainstream but the
- * Linux distributions have not updated their packages yet.
- * That's why we made this modification to be fully
- * interoperable with Empathy right now.
+ * The related bug has been fixed in mainstream but the Linux
+ * distributions have not updated their packages yet. That's why
+ * we made this modification to be fully interoperable with
+ * Empathy right now.
*
* In the future, we will get back to the original behavior:
* sending all content in one transport-info.
@@ -1160,7 +1161,8 @@ public void propertyChange(PropertyChangeEvent evt)
transport.removeCandidate(candidate);
Collection> childExtensions
- = transport.getChildExtensions();
+ = transport.getChildExtensionsOfType(
+ CandidatePacketExtension.class);
if ((childExtensions == null) || childExtensions.isEmpty())
{
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
index a43e44fb1..bd8dd88b7 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/ProtocolProviderServiceJabberImpl.java
@@ -33,9 +33,10 @@
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.service.protocol.jabberconstants.*;
import net.java.sip.communicator.util.*;
-
import net.java.sip.communicator.util.Logger;
+
import org.jitsi.service.configuration.*;
+import org.jitsi.service.neomedia.*;
import org.jitsi.util.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.*;
@@ -124,6 +125,13 @@ public class ProtocolProviderServiceJabberImpl
*/
public static final String URN_XMPP_JINGLE_COIN = "urn:xmpp:coin";
+ /**
+ * Jingle's Discovery Info URN for "XEP-0320: Use of DTLS-SRTP in
+ * Jingle Sessions".
+ */
+ public static final String URN_XMPP_JINGLE_DTLS_SRTP
+ = "urn:xmpp:jingle:apps:dtls:0";
+
/**
* Discovery Info URN for classic RFC3264-style Offer/Answer negotiation
* with no support for Trickle ICE and low tolerance to transport/payload
@@ -1889,6 +1897,16 @@ private void addJingleFeatures()
// XEP-0251: Jingle Session Transfer
supportedFeatures.add(URN_XMPP_JINGLE_TRANSFER_0);
+
+ // XEP-0320: Use of DTLS-SRTP in Jingle Sessions
+ if (accountID.getAccountPropertyBoolean(
+ ProtocolProviderFactory.DEFAULT_ENCRYPTION,
+ true)
+ && accountID.isEncryptionProtocolEnabled(
+ DtlsControl.PROTO_NAME))
+ {
+ supportedFeatures.add(URN_XMPP_JINGLE_DTLS_SRTP);
+ }
}
/**
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java
index 2f76151ff..4577c3a9f 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/AbstractPacketExtension.java
@@ -51,7 +51,7 @@ public abstract class AbstractPacketExtension
/**
* A list of extensions registered with this element.
*/
- private List childExtensions
+ private final List childExtensions
= new ArrayList();
/**
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 73fa1d62b..f09fcaf7d 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
@@ -18,7 +18,8 @@
* @author Emil Ivov
* @author Lyubomir Marinov
*/
-public class IceUdpTransportPacketExtension extends AbstractPacketExtension
+public class IceUdpTransportPacketExtension
+ extends AbstractPacketExtension
{
/**
* The name of the "transport" element.
@@ -128,24 +129,22 @@ public String getUfrag()
@Override
public List extends PacketExtension> getChildExtensions()
{
+ List childExtensions
+ = new ArrayList();
+ List extends PacketExtension> superChildExtensions
+ = super.getChildExtensions();
+
+ childExtensions.addAll(superChildExtensions);
+
synchronized (candidateList)
{
- if(candidateList.size() > 0)
- {
- return candidateList;
- }
+ if (candidateList.size() > 0)
+ childExtensions.addAll(candidateList);
else if (remoteCandidate != null)
- {
- List list
- = new ArrayList();
- list.add(remoteCandidate);
-
- return list;
- }
+ childExtensions.add(remoteCandidate);
}
- //there are apparently no child elements.
- return null;
+ return childExtensions;
}
/**
@@ -191,7 +190,7 @@ public List getCandidateList()
{
synchronized(candidateList)
{
- return new ArrayList(this.candidateList);
+ return new ArrayList(candidateList);
}
}
@@ -221,7 +220,7 @@ public RemoteCandidatePacketExtension getRemoteCandidate()
* CandidatePacketExtension}, a {@link RemoteCandidatePacketExtension} or
* something else and then adds it as such.
*
- * @param childExtension the extension we'd like to add here.
+ * @param childExtension the extension we'd like to add here.
*/
@Override
public void addChildExtension(PacketExtension childExtension)
@@ -232,5 +231,8 @@ public void addChildExtension(PacketExtension childExtension)
else if(childExtension instanceof CandidatePacketExtension)
addCandidate((CandidatePacketExtension) childExtension);
+
+ else if (childExtension instanceof DtlsFingerprintPacketExtension)
+ super.addChildExtension(childExtension);
}
}
diff --git a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RawUdpTransportPacketExtension.java b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RawUdpTransportPacketExtension.java
index 0fd8e7594..8ee3e7760 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RawUdpTransportPacketExtension.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/extensions/jingle/RawUdpTransportPacketExtension.java
@@ -47,6 +47,7 @@ public RawUdpTransportPacketExtension()
@Override
public List extends PacketExtension> getChildExtensions()
{
- return getCandidateList();
+ // TODO Auto-generated method stub
+ return super.getChildExtensions();
}
}
diff --git a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
index 9780393c5..b256fe8be 100644
--- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
@@ -1443,6 +1443,17 @@ public boolean processKeyFrameRequest()
return mediaHandler.processKeyFrameRequest(this);
}
+ /**
+ * Removes from this instance and cleans up the SrtpControl which
+ * are not of a specific SrtpControlType.
+ *
+ * @param mediaType the MediaType of the SrtpControl to be
+ * examined
+ * @param srtpControlType the SrtpControlType of the
+ * SrtpControls to not be removed from this instance and cleaned
+ * up. If null, all SrtpControls are removed from this
+ * instance and cleaned up
+ */
protected void removeAndCleanupOtherSrtpControls(
MediaType mediaType,
SrtpControlType srtpControlType)