aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Bauersachs <ingo@jitsi.org>2011-10-04 12:27:40 +0000
committerIngo Bauersachs <ingo@jitsi.org>2011-10-04 12:27:40 +0000
commit81d63ab6722ec556f0ff65f82d53e1de31cc05ce (patch)
tree8f838c00616c9b414e589e92b714c0458c98fd6d
parentb0ad56ad8277eb51dc42a247d757cafb6cc58c7c (diff)
downloadjitsi-81d63ab6722ec556f0ff65f82d53e1de31cc05ce.zip
jitsi-81d63ab6722ec556f0ff65f82d53e1de31cc05ce.tar.gz
jitsi-81d63ab6722ec556f0ff65f82d53e1de31cc05ce.tar.bz2
SDES Integration: Enable fallback to ZRTP, add Javadoc, more renames
-rw-r--r--resources/config/defaults.properties2
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java37
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java71
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java2
-rw-r--r--src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java60
-rw-r--r--src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java27
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java268
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java39
-rw-r--r--src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java7
-rw-r--r--src/net/java/sip/communicator/service/neomedia/MediaStream.java2
-rw-r--r--src/net/java/sip/communicator/service/neomedia/MediaTypeSrtpControl.java65
-rw-r--r--src/net/java/sip/communicator/service/neomedia/SDesControl.java65
-rw-r--r--src/net/java/sip/communicator/service/neomedia/SrtpControl.java22
-rw-r--r--src/net/java/sip/communicator/service/neomedia/SrtpControlType.java25
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java73
-rw-r--r--src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java2
16 files changed, 578 insertions, 189 deletions
diff --git a/resources/config/defaults.properties b/resources/config/defaults.properties
index b2b9764..6e0adae 100644
--- a/resources/config/defaults.properties
+++ b/resources/config/defaults.properties
@@ -80,3 +80,5 @@ plugin.provisioning.EXIT_ON_FAIL=false
net.java.sip.communicator.util.dns.BACKUP_RESOLVER_FALLBACK_IP=8.8.8.8
plugin.jabberaccregwizz.NEW_ACCOUNT_DEFAULT_SERVER=jit.si
+
+net.java.sip.communicator.service.neomedia.SDES_CIPHER_SUITES=AES_CM_128_HMAC_SHA1_80,AES_CM_128_HMAC_SHA1_32
diff --git a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
index af7a864..5fcdbda 100644
--- a/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/MediaStreamImpl.java
@@ -196,9 +196,9 @@ public class MediaStreamImpl
new Hashtable<String, String>();
/**
- * The current <tt>ZrtpControl</tt>.
+ * The current <tt>SrtpControl</tt>.
*/
- private final SrtpControl zrtpControl;
+ private final SrtpControl srtpControl;
/**
* Needed when restarting zrtp control.
@@ -256,14 +256,14 @@ public class MediaStreamImpl
* @param device the <tt>MediaDevice</tt> the new instance is to use for
* both capture and playback of media exchanged via the specified
* <tt>StreamConnector</tt>
- * @param zrtpControl an existing control instance to control the ZRTP
+ * @param srtpControl an existing control instance to control the ZRTP
* operations or <tt>null</tt> if a new control instance is to be created by
* the new <tt>MediaStreamImpl</tt>
*/
public MediaStreamImpl(
StreamConnector connector,
MediaDevice device,
- SrtpControl zrtpControl)
+ SrtpControl srtpControl)
{
/*
* XXX Set the device early in order to make sure that it is of the
@@ -271,8 +271,9 @@ public class MediaStreamImpl
*/
setDevice(device);
- this.zrtpControl
- = (zrtpControl == null) ? new ZrtpControlImpl() : zrtpControl;
+ //TODO add option to disable ZRTP, e.g. by implementing a NullControl
+ this.srtpControl
+ = (srtpControl == null) ? new ZrtpControlImpl() : srtpControl;
if (connector != null)
setConnector(connector);
@@ -351,8 +352,8 @@ public class MediaStreamImpl
if (dtmfEngine != null)
engineChain.add(dtmfEngine);
- // ZRTP
- engineChain.add(zrtpControl.getTransformEngine());
+ // SRTP
+ engineChain.add(srtpControl.getTransformEngine());
// RTCP Statistics
if(statisticsEngine == null)
@@ -506,7 +507,7 @@ public class MediaStreamImpl
stop();
closeSendStreams();
- zrtpControl.cleanup();
+ srtpControl.cleanup();
zrtpRestarted = false;
if(csrcEngine != null)
@@ -646,7 +647,7 @@ public class MediaStreamImpl
// If a ZRTP engine is available then set the SSRC of this
// stream
// currently ZRTP supports only one SSRC per engine
- TransformEngine engine = zrtpControl.getTransformEngine();
+ TransformEngine engine = srtpControl.getTransformEngine();
if (engine != null && engine instanceof ZRTPTransformEngine)
((ZRTPTransformEngine)engine)
@@ -1096,13 +1097,13 @@ public class MediaStreamImpl
}
/**
- * Gets the <tt>ZrtpControl</tt> which controls the ZRTP of this stream.
+ * Gets the <tt>SrtpControl</tt> which controls the SRTP of this stream.
*
- * @return the <tt>ZrtpControl</tt> which controls the ZRTP of this stream
+ * @return the <tt>SrtpControl</tt> which controls the SRTP of this stream
*/
- public SrtpControl getZrtpControl()
+ public SrtpControl getSrtpControl()
{
- return zrtpControl;
+ return srtpControl;
}
/**
@@ -1115,10 +1116,10 @@ public class MediaStreamImpl
* If there is no current secure communication, we don't need to do
* that.
*/
- if(!zrtpControl.getSecureCommunicationStatus())
+ if(!srtpControl.getSecureCommunicationStatus())
return;
- zrtpControl.cleanup();
+ srtpControl.cleanup();
/*
* As we are recreating this stream and it was obviously secured, it may
@@ -1134,7 +1135,7 @@ public class MediaStreamImpl
AbstractRTPConnector rtpConnector = getRTPConnector();
- zrtpControl.setConnector(rtpConnector);
+ srtpControl.setConnector(rtpConnector);
if(rtpConnector instanceof RTPTransformUDPConnector)
((RTPTransformUDPConnector)rtpConnector)
.setEngine(createTransformEngineChain());
@@ -1250,7 +1251,7 @@ public class MediaStreamImpl
AbstractRTPConnector oldValue,
AbstractRTPConnector newValue)
{
- zrtpControl.setConnector(newValue);
+ srtpControl.setConnector(newValue);
if (newValue != null)
{
diff --git a/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java
index e105f7a..4ea5e63 100644
--- a/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/SDesControlImpl.java
@@ -1,42 +1,68 @@
package net.java.sip.communicator.impl.neomedia;
+import java.util.*;
+
import ch.imvs.sdes4j.srtp.*;
import net.java.sip.communicator.impl.neomedia.transform.*;
import net.java.sip.communicator.impl.neomedia.transform.sdes.*;
import net.java.sip.communicator.service.neomedia.*;
import net.java.sip.communicator.service.neomedia.event.*;
+import net.java.sip.communicator.service.protocol.event.CallPeerSecurityStatusEvent;
+/**
+ * Default implementation of {@link SDesControl}.
+ *
+ * @author Ingo Bauersachs
+ */
public class SDesControlImpl
implements SDesControl
{
- private String[] supportedCryptoSuites = new String[]
- {
- SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80,
- //SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32,
- //SrtpCryptoSuite.F8_128_HMAC_SHA1_80
- };
+ private List<String> enabledCryptoSuites = new ArrayList<String>(3)
+ {{
+ add(SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80);
+ add(SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32);
+ add(SrtpCryptoSuite.F8_128_HMAC_SHA1_80);
+ }};
+
+ private final List<String> supportedCryptoSuites = new ArrayList<String>(3)
+ {{
+ add(SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_80);
+ add(SrtpCryptoSuite.AES_CM_128_HMAC_SHA1_32);
+ add(SrtpCryptoSuite.F8_128_HMAC_SHA1_80);
+ }};
+
private SrtpSDesFactory sdesFactory = new SrtpSDesFactory();
private SrtpCryptoAttribute[] attributes;
private SDesTransformEngine engine;
private SrtpCryptoAttribute selectedInAttribute;
private SrtpCryptoAttribute selectedOutAttribute;
+ private SrtpListener srtpListener;
- public SDesControlImpl()
+ public void setEnabledCiphers(Iterable<String> ciphers)
{
+ enabledCryptoSuites.clear();
+ for(String c : ciphers)
+ enabledCryptoSuites.add(c);
+ }
+
+ public Iterable<String> getSupportedCryptoSuites()
+ {
+ return Collections.unmodifiableList(supportedCryptoSuites);
}
public void cleanup()
{
}
- public void setZrtpListener(SrtpListener zrtpListener)
+ public void setSrtpListener(SrtpListener srtpListener)
{
+ this.srtpListener = srtpListener;
}
public SrtpListener getSrtpListener()
{
- return null;
+ return srtpListener;
}
public boolean getSecureCommunicationStatus()
@@ -50,6 +76,11 @@ public class SDesControlImpl
public void start(boolean masterSession)
{
+ srtpListener.securityTurnedOn(
+ masterSession ?
+ CallPeerSecurityStatusEvent.AUDIO_SESSION :
+ CallPeerSecurityStatusEvent.VIDEO_SESSION,
+ selectedInAttribute.getCryptoSuite().encode(), null, true, null);
}
public void setMultistream(byte[] multiStreamData)
@@ -65,12 +96,15 @@ public class SDesControlImpl
public String[] getInitiatorCryptoAttributes()
{
- attributes = new SrtpCryptoAttribute[supportedCryptoSuites.length];
- for (int i = 0; i < attributes.length; i++)
+ if(attributes == null)
{
- attributes[i] =
- sdesFactory.createCryptoAttribute(i + 1,
- supportedCryptoSuites[i]);
+ attributes = new SrtpCryptoAttribute[enabledCryptoSuites.size()];
+ for (int i = 0; i < attributes.length; i++)
+ {
+ attributes[i] =
+ sdesFactory.createCryptoAttribute(i + 1,
+ enabledCryptoSuites.get(i));
+ }
}
String[] result = new String[attributes.length];
for(int i = 0; i < attributes.length; i++)
@@ -78,9 +112,9 @@ public class SDesControlImpl
return result;
}
- public String responderSelectAttribute(String[] peerAttributes)
+ public String responderSelectAttribute(Iterable<String> peerAttributes)
{
- for (String suite : supportedCryptoSuites)
+ for (String suite : enabledCryptoSuites)
{
for (String ea : peerAttributes)
{
@@ -97,7 +131,7 @@ public class SDesControlImpl
return null;
}
- public void initiatorSelectAttribute(String[] peerAttributes)
+ public boolean initiatorSelectAttribute(Iterable<String> peerAttributes)
{
for (SrtpCryptoAttribute localCA : attributes)
{
@@ -108,10 +142,11 @@ public class SDesControlImpl
{
selectedInAttribute = peerCA;
selectedOutAttribute = localCA;
- return;
+ return true;
}
}
}
+ return false;
}
public SrtpCryptoAttribute getInAttribute()
diff --git a/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java b/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java
index bafe48b..ae1d8e4 100644
--- a/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java
+++ b/src/net/java/sip/communicator/impl/neomedia/ZrtpControlImpl.java
@@ -78,7 +78,7 @@ public class ZrtpControlImpl
*
* @param zrtpListener the <tt>ZrtpListener</tt> to set
*/
- public void setZrtpListener(SrtpListener zrtpListener)
+ public void setSrtpListener(SrtpListener zrtpListener)
{
this.zrtpListener = zrtpListener;
}
diff --git a/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java b/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java
index 92412d6..dba4af1 100644
--- a/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java
+++ b/src/net/java/sip/communicator/impl/neomedia/transform/sdes/SDesTransformEngine.java
@@ -6,6 +6,11 @@ import net.java.sip.communicator.impl.neomedia.*;
import net.java.sip.communicator.impl.neomedia.transform.*;
import net.java.sip.communicator.impl.neomedia.transform.srtp.*;
+/**
+ * PacketTransformer for SDES based SRTP encryption.
+ *
+ * @author Ingo Bauersachs
+ */
public class SDesTransformEngine
implements TransformEngine, PacketTransformer
{
@@ -14,6 +19,10 @@ public class SDesTransformEngine
private SrtpCryptoAttribute inAttribute;
private SrtpCryptoAttribute outAttribute;
+ /**
+ * Creates a new instance of this class.
+ * @param sDesControl The control that supplies the key material.
+ */
public SDesTransformEngine(SDesControlImpl sDesControl)
{
inAttribute = sDesControl.getInAttribute();
@@ -53,11 +62,23 @@ public class SDesTransformEngine
return salt;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.java.sip.communicator.impl.neomedia.transform.TransformEngine#
+ * getRTPTransformer()
+ */
public PacketTransformer getRTPTransformer()
{
return this;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.java.sip.communicator.impl.neomedia.transform.TransformEngine#
+ * getRTCPTransformer()
+ */
public PacketTransformer getRTCPTransformer()
{
return null;
@@ -70,23 +91,23 @@ public class SDesTransformEngine
SrtpCryptoSuite cs = attribute.getCryptoSuite();
switch (cs.getEncryptionAlgorithm())
{
- case SrtpCryptoSuite.ENCRYPTION_AES128_CM:
- encType = SRTPPolicy.AESCM_ENCRYPTION;
- break;
- case SrtpCryptoSuite.ENCRYPTION_AES128_F8:
- encType = SRTPPolicy.AESF8_ENCRYPTION;
- break;
- default:
- throw new IllegalArgumentException("Unsupported cipher");
+ case SrtpCryptoSuite.ENCRYPTION_AES128_CM:
+ encType = SRTPPolicy.AESCM_ENCRYPTION;
+ break;
+ case SrtpCryptoSuite.ENCRYPTION_AES128_F8:
+ encType = SRTPPolicy.AESF8_ENCRYPTION;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported cipher");
}
int authType;
switch (cs.getHashAlgorithm())
{
- case SrtpCryptoSuite.HASH_HMAC_SHA1:
- authType = SRTPPolicy.HMACSHA1_AUTHENTICATION;
- break;
- default:
- throw new IllegalArgumentException("Unsupported hash");
+ case SrtpCryptoSuite.HASH_HMAC_SHA1:
+ authType = SRTPPolicy.HMACSHA1_AUTHENTICATION;
+ break;
+ default:
+ throw new IllegalArgumentException("Unsupported hash");
}
SRTPPolicy policy =
new SRTPPolicy(
@@ -103,6 +124,13 @@ public class SDesTransformEngine
);
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * net.java.sip.communicator.impl.neomedia.transform.PacketTransformer
+ * #transform(net.java.sip.communicator.impl.neomedia.RawPacket)
+ */
public RawPacket transform(RawPacket pkt)
{
if (outContext == null)
@@ -115,6 +143,12 @@ public class SDesTransformEngine
return pkt;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see net.java.sip.communicator.impl.neomedia.transform.PacketTransformer#
+ * reverseTransform(net.java.sip.communicator.impl.neomedia.RawPacket)
+ */
public RawPacket reverseTransform(RawPacket pkt)
{
long ssrc = pkt.getSSRC();
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 2293e41..28ca62f 100644
--- a/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/jabber/CallPeerMediaHandlerJabberImpl.java
@@ -343,12 +343,14 @@ public class CallPeerMediaHandlerJabberImpl
// ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
{
- SrtpControl control = getZrtpControls().get(mediaType);
- if(control == null || !(control instanceof ZrtpControl))
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(mediaType, SrtpControlType.ZRTP);
+ SrtpControl control = getSrtpControls().get(key);
+ if(control == null)
{
control = JabberActivator.getMediaService()
.createZrtpControl();
- getZrtpControls().put(mediaType, control);
+ getSrtpControls().put(key, control);
}
String helloHash[] = ((ZrtpControl)control).getHelloHashSep();
@@ -550,13 +552,15 @@ public class CallPeerMediaHandlerJabberImpl
//ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
{
- SrtpControl control = getZrtpControls().get(dev.getMediaType());
-
- if(control == null || !(control instanceof ZrtpControl))
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(dev.getMediaType(),
+ SrtpControlType.ZRTP);
+ SrtpControl control = getSrtpControls().get(key);
+ if(control == null)
{
control
= JabberActivator.getMediaService().createZrtpControl();
- getZrtpControls().put(dev.getMediaType(), control);
+ getSrtpControls().put(key, control);
}
String helloHash[] = ((ZrtpControl)control).getHelloHashSep();
@@ -689,12 +693,15 @@ public class CallPeerMediaHandlerJabberImpl
//ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
{
- SrtpControl control = getZrtpControls().get(mediaType);
- if(control == null || !(control instanceof ZrtpControl))
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(mediaType,
+ SrtpControlType.ZRTP);
+ SrtpControl control = getSrtpControls().get(key);
+ if(control == null)
{
control = JabberActivator.getMediaService()
.createZrtpControl();
- getZrtpControls().put(mediaType, control);
+ getSrtpControls().put(key, control);
}
String helloHash[] =
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
index 0798cef..d20a497 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/CallPeerMediaHandlerSipImpl.java
@@ -47,12 +47,6 @@ public class CallPeerMediaHandlerSipImpl
private SessionDescription localSess = null;
/**
- * The last ( and maybe only ) session description that we received from
- * the remote party.
- */
- private SessionDescription remoteSess = null;
-
- /**
* A <tt>URL</tt> pointing to a location with call information or a call
* control web interface related to the <tt>CallPeer</tt> that we are
* associated with.
@@ -179,19 +173,23 @@ public class CallPeerMediaHandlerSipImpl
{
MediaDevice dev = getDefaultDevice(mediaType);
- if (dev != null)
- {
- MediaDirection direction = dev.getDirection().and(
- getDirectionUserPreference(mediaType));
+ if (dev == null)
+ continue;
- if(isLocallyOnHold())
- direction = direction.and(MediaDirection.SENDONLY);
+ MediaDirection direction = dev.getDirection().and(
+ getDirectionUserPreference(mediaType));
- if(direction != MediaDirection.INACTIVE)
+ if(isLocallyOnHold())
+ direction = direction.and(MediaDirection.SENDONLY);
+
+ if(direction != MediaDirection.INACTIVE)
+ {
+ boolean hadSavp = false;
+ for (String profileName : getRtpTransports())
{
MediaDescription md =
createMediaDescription(
- true, //TODO base on settings
+ profileName,
dev.getSupportedFormats(
sendQualityPreset,
receiveQualityPreset),
@@ -216,10 +214,16 @@ public class CallPeerMediaHandlerSipImpl
// do nothing in case of error.
}
- //updateMediaDescriptionForZrtp(mediaType, md); //TODO: base on setting
- updateMediaDescriptionForSDes(mediaType, md, null);
+ if(!hadSavp)
+ {
+ updateMediaDescriptionForZrtp(mediaType, md);
+ updateMediaDescriptionForSDes(mediaType, md, null);
+ }
mediaDescs.add(md);
+
+ if(!hadSavp && profileName.contains("SAVP"))
+ hadSavp = true;
}
}
}
@@ -321,8 +325,6 @@ public class CallPeerMediaHandlerSipImpl
throws OperationFailedException,
IllegalArgumentException
{
- this.remoteSess = offer;
-
Vector<MediaDescription> answerDescriptions
= createMediaDescriptionsForAnswer(offer);
@@ -358,8 +360,6 @@ public class CallPeerMediaHandlerSipImpl
throws OperationFailedException,
IllegalArgumentException
{
- this.remoteSess = newOffer;
-
Vector<MediaDescription> answerDescriptions
= createMediaDescriptionsForAnswer(newOffer);
@@ -403,12 +403,17 @@ public class CallPeerMediaHandlerSipImpl
boolean atLeastOneValidDescription = false;
+ List<MediaType> seenMediaTypes = new ArrayList<MediaType>();
for (MediaDescription mediaDescription : remoteDescriptions)
{
MediaType mediaType = null;
try
{
mediaType = SdpUtils.getMediaType(mediaDescription);
+ //don't process a second media of the same type
+ if(seenMediaTypes.contains(mediaType))
+ continue;
+ seenMediaTypes.add(mediaType);
}
catch (IllegalArgumentException iae)
{
@@ -524,11 +529,23 @@ public class CallPeerMediaHandlerSipImpl
}
}
- MediaDescription md = createMediaDescription(true, //TODO base on settings
- mutuallySupportedFormats, connector, direction, rtpExtensions);
+ MediaDescription md;
+ try
+ {
+ md =
+ createMediaDescription(mediaDescription.getMedia()
+ .getProtocol(), mutuallySupportedFormats, connector,
+ direction, rtpExtensions);
+ }
+ catch (SdpParseException e)
+ {
+ throw new OperationFailedException(
+ "unable to create the media description",
+ OperationFailedException.ILLEGAL_ARGUMENT, e);
+ }
- //updateMediaDescriptionForZrtp(mediaType, md); //TODO base on setting
- updateMediaDescriptionForSDes(mediaType, md, mediaDescription);
+ if(!updateMediaDescriptionForSDes(mediaType, md, mediaDescription))
+ updateMediaDescriptionForZrtp(mediaType, md);
// create the corresponding stream...
MediaFormat fmt = findMediaFormat(remoteFormats,
@@ -562,12 +579,14 @@ public class CallPeerMediaHandlerSipImpl
{
try
{
- SrtpControl scontrol = getZrtpControls().get(mediaType);
- if(scontrol == null || !(scontrol instanceof ZrtpControl))
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(mediaType, SrtpControlType.ZRTP);
+ SrtpControl scontrol = getSrtpControls().get(key);
+ if(scontrol == null)
{
scontrol = SipActivator.getMediaService()
.createZrtpControl();
- getZrtpControls().put(mediaType, scontrol);
+ getSrtpControls().put(key, scontrol);
}
ZrtpControl zcontrol = (ZrtpControl) scontrol;
@@ -587,72 +606,139 @@ public class CallPeerMediaHandlerSipImpl
* Updates the supplied description with SDES attributes if necessary.
*
* @param mediaType the media type.
- * @param localMd the description to be updated.
- * @param peerMd
- * @throws OperationFailedException
+ * @param localMd the description of the local peer.
+ * @param peerMd the description of the remote peer.
*/
@SuppressWarnings("unchecked") //jain-sip legacy
- private void updateMediaDescriptionForSDes(
+ private boolean updateMediaDescriptionForSDes(
MediaType mediaType, MediaDescription localMd, MediaDescription peerMd)
- throws OperationFailedException
{
- //if(getPeer().getCall().isSipZrtpAttribute()) //TODO: check SDES config
+ //check if SDES is enabled at all
+ if (!getPeer()
+ .getProtocolProvider()
+ .getAccountID()
+ .getAccountPropertyBoolean(
+ ProtocolProviderServiceSipImpl.SDES_ENABLED, true))
+ {
+ return false;
+ }
+
+ // get or create the control
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(mediaType, SrtpControlType.SDES);
+ SrtpControl scontrol = getSrtpControls().get(key);
+ if (scontrol == null)
+ {
+ scontrol = SipActivator.getMediaService().createSDesControl();
+ getSrtpControls().put(key, scontrol);
+ }
+
+ // set the enabled ciphers suites
+ SDesControl sdcontrol = (SDesControl) scontrol;
+ String ciphers =
+ getPeer()
+ .getProtocolProvider()
+ .getAccountID()
+ .getAccountPropertyString(
+ ProtocolProviderServiceSipImpl.SDES_CIPHER_SUITES);
+ if (ciphers == null)
{
- SrtpControl scontrol = getZrtpControls().get(mediaType);
- if (scontrol == null || !(scontrol instanceof SDesControl))
+ ciphers =
+ SipActivator.getResources().getSettingsString(
+ SDesControl.SDES_CIPHER_SUITES);
+ }
+ sdcontrol.setEnabledCiphers(Arrays.asList(ciphers.split(",")));
+
+ // act as initiator
+ if (peerMd == null)
+ {
+ Vector<Attribute> atts = localMd.getAttributes(true);
+ for (String ca : sdcontrol.getInitiatorCryptoAttributes())
{
- scontrol = SipActivator.getMediaService().createSDesControl();
- getZrtpControls().put(mediaType, scontrol);
+ Attribute a = SdpUtils.createAttribute("crypto", ca);
+ atts.add(a);
}
- SDesControl sdcontrol = (SDesControl) scontrol;
- if (peerMd == null)
+ return true;
+ }
+ // act as responder
+ else
+ {
+ Vector<Attribute> atts = peerMd.getAttributes(true);
+ List<String> peerAttributes = new LinkedList<String>();
+ for (Attribute a : atts)
{
- Vector<Attribute> atts = localMd.getAttributes(true);
- for (String ca : sdcontrol.getInitiatorCryptoAttributes())
+ try
+ {
+ if (a.getName().equals("crypto"))
+ {
+ peerAttributes.add(a.getValue());
+ }
+ }
+ catch (SdpParseException e)
{
- Attribute a = SdpUtils.createAttribute("crypto", ca);
- atts.add(a);
+ logger.error("received an uparsable sdp attribute", e);
}
}
- else
+ if (peerAttributes.size() > 0)
{
- Vector<Attribute> atts = peerMd.getAttributes(true);
- List<String> peerAttributes = new LinkedList<String>();
- for (Attribute a : atts)
+ String localAttr =
+ sdcontrol.responderSelectAttribute(peerAttributes);
+ if (localAttr != null)
{
try
{
- if (a.getName().equals("crypto"))
- {
- peerAttributes.add(a.getValue());
- }
+ localMd.setAttribute("crypto", localAttr);
+ return true;
}
- catch (SdpParseException e)
+ catch (SdpException e)
{
- logger.error("received an uparsable sdp attribute", e);
+ logger.error("unable to add crypto to answer", e);
}
}
- if (peerAttributes.size() > 0)
+ else
{
- String localAttr =
- sdcontrol.responderSelectAttribute(peerAttributes
- .toArray(new String[peerAttributes.size()]));
- if(localAttr != null)
- {
- try
- {
- localMd.setAttribute("crypto", localAttr);
- }
- catch (SdpException e)
- {
- logger.error("unable to add crypto to answer", e);
- }
- }
+ // none of the offered suites match, destroy the sdes
+ // control
+ getSrtpControls().remove(key);
+ logger.warn("Received unsupported sdes crypto attribute "
+ + peerAttributes.toString());
}
}
+ else
+ {
+ // peer doesn't offer any SDES attribute, destroy the sdes
+ // control
+ getSrtpControls().remove(key);
+ }
+ return false;
}
}
+ private List<String> getRtpTransports() throws OperationFailedException
+ {
+ List<String> result = new ArrayList<String>(2);
+ int savpOption =
+ getPeer()
+ .getProtocolProvider()
+ .getAccountID()
+ .getAccountPropertyInt(
+ ProtocolProviderServiceSipImpl.SAVP_OPTION,
+ ProtocolProviderServiceSipImpl.SAVP_OFF);
+ if(savpOption == ProtocolProviderServiceSipImpl.SAVP_MANDATORY)
+ result.add("RTP/SAVP");
+ else if(savpOption == ProtocolProviderServiceSipImpl.SAVP_OFF)
+ result.add(SdpConstants.RTP_AVP);
+ else if(savpOption == ProtocolProviderServiceSipImpl.SAVP_OPTIONAL)
+ {
+ result.add("RTP/SAVP");
+ result.add(SdpConstants.RTP_AVP);
+ }
+ else
+ throw new OperationFailedException("invalid value for SAVP_OPTION",
+ OperationFailedException.GENERAL_ERROR);
+ return result;
+ }
+
/**
* Handles the specified <tt>answer</tt> by creating and initializing the
* corresponding <tt>MediaStream</tt>s.
@@ -690,19 +776,22 @@ public class CallPeerMediaHandlerSipImpl
throws OperationFailedException,
IllegalArgumentException
{
- this.remoteSess = answer;
-
List<MediaDescription> remoteDescriptions
= SdpUtils.extractMediaDescriptions(answer);
this.setCallInfoURL(SdpUtils.getCallInfoURL(answer));
- for ( MediaDescription mediaDescription : remoteDescriptions)
+ List<MediaType> seenMediaTypes = new ArrayList<MediaType>();
+ for (MediaDescription mediaDescription : remoteDescriptions)
{
MediaType mediaType;
try
{
mediaType = SdpUtils.getMediaType(mediaDescription);
+ //don't process a second media of the same type
+ if(seenMediaTypes.contains(mediaType))
+ continue;
+ seenMediaTypes.add(mediaType);
}
catch(IllegalArgumentException iae)
{
@@ -787,8 +876,10 @@ public class CallPeerMediaHandlerSipImpl
}
// select the crypto key the peer has chosen from our proposal
- SrtpControl scontrol = getZrtpControls().get(mediaType);
- if(scontrol != null && scontrol instanceof SDesControl)
+ MediaTypeSrtpControl key =
+ new MediaTypeSrtpControl(mediaType, SrtpControlType.SDES);
+ SrtpControl scontrol = getSrtpControls().get(key);
+ if(scontrol != null)
{
List<String> peerAttributes = new LinkedList<String>();
@SuppressWarnings("unchecked")
@@ -807,9 +898,28 @@ public class CallPeerMediaHandlerSipImpl
logger.error("received an uparsable sdp attribute", e);
}
}
- ((SDesControl) scontrol)
- .initiatorSelectAttribute(peerAttributes
- .toArray(new String[peerAttributes.size()]));
+ if(!((SDesControl) scontrol)
+ .initiatorSelectAttribute(peerAttributes))
+ {
+ getSrtpControls().remove(key);
+ if(peerAttributes.size() > 0)
+ logger
+ .warn("Received unsupported sdes crypto attribute: "
+ + peerAttributes);
+ }
+ else
+ {
+ //found an SDES answer, remove all other controls
+ Iterator<MediaTypeSrtpControl> it =
+ getSrtpControls().keySet().iterator();
+ while (it.hasNext())
+ {
+ MediaTypeSrtpControl mtc = it.next();
+ if (mtc.mediaType == mediaType
+ && mtc.srtpControlType != SrtpControlType.SDES)
+ it.remove();
+ }
+ }
}
// create the corresponding stream...
@@ -835,7 +945,7 @@ public class CallPeerMediaHandlerSipImpl
* taking account the local streaming preference for the corresponding
* media type.
*
- * @param secure when true, the profile is RTP/SAVP instead of RTP/AVP
+ * @param transport the profile name (RTP/SAVP or RTP/AVP)
* @param formats the list of <tt>MediaFormats</tt> that we'd like to
* advertise.
* @param connector the <tt>StreamConnector</tt> that we will be using
@@ -852,14 +962,14 @@ public class CallPeerMediaHandlerSipImpl
* <tt>MediaDescription</tt> fails for some reason.
*/
private MediaDescription createMediaDescription(
- boolean secure,
+ String transport,
List<MediaFormat> formats,
StreamConnector connector,
MediaDirection direction,
List<RTPExtension> extensions )
throws OperationFailedException
{
- return SdpUtils.createMediaDescription(secure, formats, connector,
+ return SdpUtils.createMediaDescription(transport, formats, connector,
direction, extensions,
getDynamicPayloadTypes(), getRtpExtensionsRegistry());
}
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
index 940d3a1..dca666f 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/ProtocolProviderServiceSipImpl.java
@@ -159,7 +159,7 @@ public class ProtocolProviderServiceSipImpl
/**
* The name of the property under which the user may specify whether to use
- * original sip creadetials for the XCAP.
+ * original sip credentials for the XCAP.
*/
public static final String XCAP_USE_SIP_CREDETIALS =
"XCAP_USE_SIP_CREDETIALS";
@@ -182,6 +182,43 @@ public class ProtocolProviderServiceSipImpl
public static final String XCAP_PASSWORD = "XCAP_PASSWORD";
/**
+ * The name of the property that indicates if SDES is enabled for this
+ * account.
+ */
+ public static final String SDES_ENABLED = "SDES_ENABLED";
+
+ /**
+ * The name of the property that defines the enabled SDES cipher suites.
+ * Enabled suites are listed as CSV by their RFC name.
+ */
+ public static final String SDES_CIPHER_SUITES = "SDES_CIPHER_SUITES";
+
+ /**
+ * The name of the property that indicates the AVP type.
+ * <ul>
+ * <li>{@link #SAVP_OPTION_AVP}</li>
+ * <li>{@link #SAVP_OPTION_SAVP}</li>
+ * <li>{@link #SAVP_OPTION_AVP_OR_SAVP}</li>
+ * </ul>
+ */
+ public static final String SAVP_OPTION = "SAVP_OPTION";
+
+ /**
+ * Always use RTP/AVP
+ */
+ public static final int SAVP_OFF = 0;
+
+ /**
+ * Always use RTP/SAVP
+ */
+ public static final int SAVP_MANDATORY = 1;
+
+ /**
+ * Sends two media description, with RTP/SAVP being first.
+ */
+ public static final int SAVP_OPTIONAL = 2;
+
+ /**
* Presence content for image.
*/
public static final String PRES_CONTENT_IMAGE_NAME = "sip_communicator";
diff --git a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
index a3f8c77..7796b1c 100644
--- a/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
+++ b/src/net/java/sip/communicator/impl/protocol/sip/sdp/SdpUtils.java
@@ -1284,7 +1284,7 @@ public class SdpUtils
* description is determined via from the type of the first
* <tt>MediaFormat</tt> in the <tt>formats</tt> list.
*
- * @param secure when true, the profile is RTP/SAVP instead of RTP/AVP
+ * @param transport the profile name (RTP/SAVP or RTP/AVP)
* @param formats the list of formats that should be advertised in the newly
* created <tt>MediaDescription</tt>.
* @param connector the socket couple that will be used for the media stream
@@ -1307,7 +1307,7 @@ public class SdpUtils
* some other reason.
*/
public static MediaDescription createMediaDescription(
- boolean secure,
+ String transport,
List<MediaFormat> formats,
StreamConnector connector,
MediaDirection direction,
@@ -1437,8 +1437,7 @@ public class SdpUtils
{
mediaDesc = sdpFactory.createMediaDescription(mediaType.toString(),
connector.getDataSocket().getLocalPort(), 1,
- secure ? "RTP/SAVP" : SdpConstants.RTP_AVP,
- payloadTypesArray);
+ transport, payloadTypesArray);
// add all the attributes we have created above
mediaDesc.setAttributes(mediaAttributes);
diff --git a/src/net/java/sip/communicator/service/neomedia/MediaStream.java b/src/net/java/sip/communicator/service/neomedia/MediaStream.java
index 2487a71..5c9b65a 100644
--- a/src/net/java/sip/communicator/service/neomedia/MediaStream.java
+++ b/src/net/java/sip/communicator/service/neomedia/MediaStream.java
@@ -319,5 +319,5 @@ public interface MediaStream
*
* @return the <tt>ZrtpControl</tt> which controls the ZRTP for this stream
*/
- public SrtpControl getZrtpControl();
+ public SrtpControl getSrtpControl();
}
diff --git a/src/net/java/sip/communicator/service/neomedia/MediaTypeSrtpControl.java b/src/net/java/sip/communicator/service/neomedia/MediaTypeSrtpControl.java
new file mode 100644
index 0000000..b4c6bbe
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/MediaTypeSrtpControl.java
@@ -0,0 +1,65 @@
+package net.java.sip.communicator.service.neomedia;
+
+public class MediaTypeSrtpControl implements Comparable<MediaTypeSrtpControl>
+{
+ public MediaType mediaType;
+ public SrtpControlType srtpControlType;
+
+ public MediaTypeSrtpControl(MediaType mt, SrtpControlType sct)
+ {
+ mediaType = mt;
+ srtpControlType = sct;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if(obj == null || obj.getClass() != MediaTypeSrtpControl.class)
+ return false;
+
+ MediaTypeSrtpControl other = (MediaTypeSrtpControl)obj;
+ return mediaType == other.mediaType && srtpControlType == other.srtpControlType;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return mediaType.hashCode() ^ srtpControlType.hashCode();
+ }
+
+ public int compareTo(MediaTypeSrtpControl o)
+ {
+ return getWeight() == o.getWeight() ?
+ 0 :
+ getWeight() < o.getWeight() ?
+ -1 : 1;
+ }
+
+ private int getWeight()
+ {
+ int mtWeight = 0;
+ switch(mediaType)
+ {
+ case AUDIO:
+ mtWeight = 1;
+ break;
+ case VIDEO:
+ mtWeight = 2;
+ break;
+ }
+ int stWeight = 0;
+ switch(srtpControlType)
+ {
+ case ZRTP:
+ stWeight = 1;
+ break;
+ case MIKEY:
+ stWeight = 2;
+ break;
+ case SDES:
+ stWeight = 3;
+ break;
+ }
+ return mtWeight * 10 + stWeight;
+ }
+}
diff --git a/src/net/java/sip/communicator/service/neomedia/SDesControl.java b/src/net/java/sip/communicator/service/neomedia/SDesControl.java
index 6f7e285..d7e6b2c 100644
--- a/src/net/java/sip/communicator/service/neomedia/SDesControl.java
+++ b/src/net/java/sip/communicator/service/neomedia/SDesControl.java
@@ -2,12 +2,73 @@ package net.java.sip.communicator.service.neomedia;
import ch.imvs.sdes4j.srtp.SrtpCryptoAttribute;
+/**
+ * SDES based SRTP MediaStream encryption control.
+ *
+ * @author Ingo Bauersachs
+ */
public interface SDesControl
extends SrtpControl
{
+ /**
+ * Name of the config setting that supplies the default enabled cipher
+ * suites. Cipher suites are comma-separated.
+ */
+ public static final String SDES_CIPHER_SUITES =
+ "net.java.sip.communicator.service.neomedia.SDES_CIPHER_SUITES";
+
+ /**
+ * Set the enabled SDES ciphers.
+ *
+ * @param ciphers The list of enabled ciphers.
+ */
+ public void setEnabledCiphers(Iterable<String> ciphers);
+
+ /**
+ * Gets all supported cipher suites.
+ *
+ * @return all supported cipher suites.
+ */
+ public Iterable<String> getSupportedCryptoSuites();
+
+ /**
+ * Gets the encoded SDES crypto-attributes for all enabled ciphers when the
+ * control is used as the initiator.
+ *
+ * @return the encoded SDES crypto-attributes for all enabled ciphers.
+ */
public String[] getInitiatorCryptoAttributes();
- public String responderSelectAttribute(String[] peerAttributes);
- public void initiatorSelectAttribute(String[] peerAttributes);
+
+ /**
+ * Chooses a supported crypto attribute from the peer's list of supplied
+ * attributes and creates the local crypto attribute. Used when the control
+ * is running in the role as responder.
+ *
+ * @param peerAttributes The peer's crypto attribute offering.
+ * @return The local crypto attribute for the answer of the offer or null if
+ * no matching cipher suite could be found.
+ */
+ public String responderSelectAttribute(Iterable<String> peerAttributes);
+
+ /**
+ * Select the local crypto attribute from the initial offering (@see
+ * {@link #getInitiatorCryptoAttributes()}) based on the peer's first
+ * matching cipher suite.
+ *
+ * @param peerAttributes The peer's crypto offers.
+ * @return True when a matching cipher suite was found, false otherwise.
+ */
+ public boolean initiatorSelectAttribute(Iterable<String> peerAttributes);
+
+ /**
+ * Gets the crypto attribute of the incoming MediaStream.
+ * @return the crypto attribute of the incoming MediaStream.
+ */
public SrtpCryptoAttribute getInAttribute();
+
+ /**
+ * Gets the crypto attribute of the outgoing MediaStream.
+ * @return the crypto attribute of the outgoing MediaStream.
+ */
public SrtpCryptoAttribute getOutAttribute();
}
diff --git a/src/net/java/sip/communicator/service/neomedia/SrtpControl.java b/src/net/java/sip/communicator/service/neomedia/SrtpControl.java
index 3df982b..64503a3 100644
--- a/src/net/java/sip/communicator/service/neomedia/SrtpControl.java
+++ b/src/net/java/sip/communicator/service/neomedia/SrtpControl.java
@@ -11,29 +11,29 @@ import net.java.sip.communicator.impl.neomedia.transform.TransformEngine;
import net.java.sip.communicator.service.neomedia.event.*;
/**
- * Controls zrtp in the MediaStream.
+ * Controls SRTP encryption in the MediaStream.
*
* @author Damian Minkov
*/
public interface SrtpControl
{
/**
- * Cleans up the current zrtp control and its engine.
+ * Cleans up the current SRTP control and its engine.
*/
public void cleanup();
/**
- * Sets a <tt>ZrtpListener</tt> that will listen for
- * zrtp security events.
+ * Sets a <tt>SrtpListener</tt> that will listen for
+ * srtp security events.
*
- * @param zrtpListener the <tt>ZrtpListener</tt> to set
+ * @param srtpListener the <tt>SrtpListener</tt> to set
*/
- public void setZrtpListener(SrtpListener zrtpListener);
+ public void setSrtpListener(SrtpListener srtpListener);
/**
- * Returns the <tt>ZrtpListener</tt> which listens for security events.
+ * Returns the <tt>SrtpListener</tt> which listens for security events.
*
- * @return the <tt>ZrtpListener</tt> which listens for security events
+ * @return the <tt>SrtpListener</tt> which listens for security events
*/
public SrtpListener getSrtpListener();
@@ -76,5 +76,11 @@ public interface SrtpControl
*/
public TransformEngine getTransformEngine();
+ /**
+ * Sets the <tt>RTPConnector</tt> which is to use or uses this SRTP engine.
+ *
+ * @param connector the <tt>RTPConnector</tt> which is to use or uses this
+ * SRTP engine
+ */
public void setConnector(AbstractRTPConnector newValue);
}
diff --git a/src/net/java/sip/communicator/service/neomedia/SrtpControlType.java b/src/net/java/sip/communicator/service/neomedia/SrtpControlType.java
new file mode 100644
index 0000000..dbaa70c
--- /dev/null
+++ b/src/net/java/sip/communicator/service/neomedia/SrtpControlType.java
@@ -0,0 +1,25 @@
+package net.java.sip.communicator.service.neomedia;
+
+/**
+ * The <tt>SrtpControlType</tt> enumeration contains all currently known
+ * <tt>SrtpControl</tt> implementations.
+ *
+ * @author Ingo Bauersachs
+ */
+public enum SrtpControlType
+{
+ /**
+ * Session Description Protocol (SDP) Security Descriptions for Media Streams (RFC 4568)
+ */
+ SDES,
+
+ /**
+ * ZRTP: Media Path Key Agreement for Unicast Secure RTP (RFC 6189)
+ */
+ ZRTP,
+
+ /**
+ * Multimedia Internet KEYing (RFC 3830)
+ */
+ MIKEY
+}
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 f67b6f0..7d29b8d 100644
--- a/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
+++ b/src/net/java/sip/communicator/service/protocol/media/CallPeerMediaHandler.java
@@ -94,10 +94,10 @@ public abstract class CallPeerMediaHandler<
private final T peer;
/**
- * A reference to the object that would be responsible for ZRTP control
+ * A reference to the object that would be responsible for SRTP control
* and which most often would be the peer itself.
*/
- public final SrtpListener zrtpController;
+ public final SrtpListener srtpListener;
/**
* The RTP stream that this media handler uses to send audio.
@@ -191,10 +191,10 @@ public abstract class CallPeerMediaHandler<
= new DynamicRTPExtensionsRegistry();
/**
- * Holds the ZRTP controls used for the current call.
+ * Holds the SRTP controls used for the current call.
*/
- private Map<MediaType, SrtpControl> srtpControls =
- new Hashtable<MediaType, SrtpControl>();
+ private SortedMap<MediaTypeSrtpControl, SrtpControl> srtpControls =
+ new TreeMap<MediaTypeSrtpControl, SrtpControl>();
/**
* The <tt>KeyFrameControl</tt> currently known to this
@@ -330,14 +330,13 @@ public abstract class CallPeerMediaHandler<
*
* @param peer that <tt>CallPeer</tt> instance that we will be managing
* media for.
- * @param zrtpController the object that would be responsible for
- * controlling zrtp, and which most often would be the peer itself.
+ * @param srtpListener the object that receives SRTP security events.
*/
public CallPeerMediaHandler(T peer,
- SrtpListener zrtpController)
+ SrtpListener srtpListener)
{
this.peer = peer;
- this.zrtpController = zrtpController;
+ this.srtpListener = srtpListener;
}
/**
@@ -415,20 +414,23 @@ public abstract class CallPeerMediaHandler<
*/
protected void closeStream(MediaType type)
{
- if( type == MediaType.AUDIO)
+ if (type == MediaType.AUDIO)
setAudioStream(null);
else
setVideoStream(null);
getTransportManager().closeStreamConnector(type);
- // Clear the ZRTP controls used for the associated Call.
- SrtpControl zrtpCtrl = srtpControls.get(type);
-
- if (zrtpCtrl != null)
+ // Clear the SRTP controls used for the associated Call.
+ Iterator<MediaTypeSrtpControl> it = srtpControls.keySet().iterator();
+ while (it.hasNext())
{
- zrtpCtrl.cleanup();
- srtpControls.remove(type);
+ MediaTypeSrtpControl mct = it.next();
+ if (mct.mediaType == type)
+ {
+ srtpControls.get(mct).cleanup();
+ it.remove();
+ }
}
}
@@ -675,10 +677,10 @@ public abstract class CallPeerMediaHandler<
public void setSasVerified(boolean isVerified )
{
if(audioStream != null)
- audioStream.getZrtpControl().setSASVerification(isVerified);
+ audioStream.getSrtpControl().setSASVerification(isVerified);
if(videoStream != null)
- videoStream.getZrtpControl().setSASVerification(isVerified);
+ videoStream.getSrtpControl().setSASVerification(isVerified);
}
/**
@@ -694,14 +696,14 @@ public abstract class CallPeerMediaHandler<
*/
boolean isAudioSecured
= (audioStream == null)
- || audioStream.getZrtpControl().getSecureCommunicationStatus();
+ || audioStream.getSrtpControl().getSecureCommunicationStatus();
if (!isAudioSecured)
return false;
boolean isVideoSecured
= (videoStream == null)
- || videoStream.getZrtpControl().getSecureCommunicationStatus();
+ || videoStream.getSrtpControl().getSecureCommunicationStatus();
if (!isVideoSecured)
return false;
@@ -711,16 +713,16 @@ public abstract class CallPeerMediaHandler<
/**
* Passes <tt>multiStreamData</tt> to the video stream that we are using
- * in this media handler (if any) so that the underlying ZRTP lib could
+ * in this media handler (if any) so that the underlying SRTP lib could
* properly handle stream security.
*
* @param multiStreamData the data that we are supposed to pass to our
* video stream.
*/
- public void startZrtpMultistream(byte[] multiStreamData)
+ public void startSrtpMultistream(byte[] multiStreamData)
{
if(videoStream != null)
- videoStream.getZrtpControl().setMultistream(multiStreamData);
+ videoStream.getSrtpControl().setMultistream(multiStreamData);
}
/**
@@ -1157,11 +1159,11 @@ public abstract class CallPeerMediaHandler<
}
/**
- * Returns the currently valid <tt>ZrtpControls</tt> map.
+ * Returns the currently valid <tt>SrtpControls</tt> map.
*
- * @return the currently valid <tt>ZrtpControls</tt> map.
+ * @return the currently valid <tt>SrtpControls</tt> map.
*/
- protected Map<MediaType, SrtpControl> getZrtpControls()
+ protected Map<MediaTypeSrtpControl, SrtpControl> getSrtpControls()
{
return this.srtpControls;
}
@@ -1206,16 +1208,21 @@ public abstract class CallPeerMediaHandler<
logger.trace("The media types of device and format differ.");
// check whether a control already exists
- SrtpControl control = srtpControls.get(mediaType);
MediaService mediaService
= ProtocolMediaActivator.getMediaService();
+ SrtpControl control = srtpControls.size() > 0 ?
+ srtpControls.get(new MediaTypeSrtpControl(mediaType,
+ srtpControls.firstKey().srtpControlType)) : null;
if(control == null)
+ {
+ // this creates the default control, currently ZRTP without
+ // the hello-hash
stream = mediaService.createMediaStream(connector, device);
+ }
else
{
- stream
- = mediaService.createMediaStream(
+ stream = mediaService.createMediaStream(
connector, device, control);
}
}
@@ -1281,11 +1288,11 @@ public abstract class CallPeerMediaHandler<
if(peer.getCall().isDefaultEncrypted())
{
// we use the audio stream for master stream
- // when using ZRTP multistreams.
- SrtpControl zrtpControl = stream.getZrtpControl();
+ // when using SRTP multistreams.
+ SrtpControl srtpControl = stream.getSrtpControl();
- zrtpControl.setZrtpListener(zrtpController);
- zrtpControl.start(stream instanceof AudioMediaStream);
+ srtpControl.setSrtpListener(srtpListener);
+ srtpControl.start(stream instanceof AudioMediaStream);
}
return stream;
diff --git a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
index 9f7b9c0..33d25e6 100644
--- a/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
+++ b/src/net/java/sip/communicator/service/protocol/media/MediaAwareCallPeer.java
@@ -730,7 +730,7 @@ public abstract class MediaAwareCallPeer
{
if(multiStreamData != null)
{
- getMediaHandler().startZrtpMultistream(multiStreamData);
+ getMediaHandler().startSrtpMultistream(multiStreamData);
}
fireCallPeerSecurityOnEvent(