diff --git a/src/org/jitsi/impl/neomedia/MediaServiceImpl.java b/src/org/jitsi/impl/neomedia/MediaServiceImpl.java
index defaeb487538225d1f7f1fec6f93028f9a1f6934..0e2d714bb1a2d6b290df4dd26eecb9b238423c39 100755
--- a/src/org/jitsi/impl/neomedia/MediaServiceImpl.java
+++ b/src/org/jitsi/impl/neomedia/MediaServiceImpl.java
@@ -306,6 +306,16 @@ public MediaStream createMediaStream(
         return createMediaStream(connector, device, null);
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaType mediaType)
+    {
+        return createMediaStream(connector, mediaType, null);
+    }
+
     /**
      * Creates a new <tt>MediaStream</tt> instance which will use the specified
      * <tt>MediaDevice</tt> for both capture and playback of media exchanged
@@ -330,6 +340,17 @@ public MediaStream createMediaStream(
         return createMediaStream(null, connector, device, srtpControl);
     }
 
+    /**
+     * {@inheritDocs}
+     */
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaType mediaType,
+            SrtpControl srtpControl)
+    {
+        return createMediaStream(mediaType, connector, null, srtpControl);
+    }
+
     /**
      * Initializes a new <tt>MediaStream</tt> instance. The method is the actual
      * implementation to which the public <tt>createMediaStream</tt> methods of
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java b/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
index 77b2220f0b0f44ec1d328aa23d77a9b6e36a7cb8..6e4e868cb47a6086a28371f735770a5c14dc1119 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
@@ -239,15 +239,23 @@ public int receive(byte[] buf, int off, int len, int waitMillis)
                     }
                 }
 
-                if (receiveQ.isEmpty() && (timeout >= 0))
+                if (receiveQ.isEmpty())
                 {
-                    try
+                    if (timeout >= 0)
                     {
-                        receiveQ.wait(timeout);
+                        try
+                        {
+                            receiveQ.wait(timeout);
+                        }
+                        catch (InterruptedException ie)
+                        {
+                            interrupted = true;
+                        }
                     }
-                    catch (InterruptedException ie)
+                    else
                     {
-                        interrupted = true;
+                        // The specified waitMillis has been exceeded.
+                        break;
                     }
                 }
             }
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
index f9d7768fbdf45a575f024580d9e25b6949dd502c..e28209e88c2d1021e6102069fe4283116f988730 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
@@ -566,7 +566,7 @@ private static String toHex(byte[] fingerprint)
      * and validate against the fingerprints presented by the remote endpoint
      * via the signaling path
      */
-    void verifyAndValidateCertificate(
+    private void verifyAndValidateCertificate(
             org.bouncycastle.asn1.x509.Certificate certificate)
         throws Exception
     {
@@ -592,11 +592,32 @@ void verifyAndValidateCertificate(
         synchronized (this)
         {
             if (disposed)
+            {
                 throw new IllegalStateException("disposed");
+            }
             else
-                remoteFingerprint = remoteFingerprints.get(hashFunction);
+            {
+                Map<String,String> remoteFingerprints = this.remoteFingerprints;
+
+                if (remoteFingerprints == null)
+                {
+                    throw new IOException(
+                            "No fingerprints declared over the signaling"
+                                + " path!");
+                }
+                else
+                {
+                    remoteFingerprint = remoteFingerprints.get(hashFunction);
+                }
+            }
         }
-        if (!remoteFingerprint.equals(fingerprint))
+        if (remoteFingerprint == null)
+        {
+            throw new IOException(
+                    "No fingerprint declared over the signaling path with"
+                        + " hash function: " + hashFunction + "!");
+        }
+        else if (!remoteFingerprint.equals(fingerprint))
         {
             throw new IOException(
                     "Fingerprint " + remoteFingerprint
@@ -611,24 +632,61 @@ void verifyAndValidateCertificate(
      *
      * @param certificate the certificate to be verified and validated against
      * the fingerprints presented by the remote endpoint via the signaling path
+     * @return <tt>true</tt> if the specified <tt>certificate</tt> was
+     * successfully verified and validated against the fingerprints presented by
+     * the remote endpoint over the signaling path
      * @throws Exception if the specified <tt>certificate</tt> failed to verify
      * and validate against the fingerprints presented by the remote endpoint
-     * via the signaling path
+     * over the signaling path
      */
-    void verifyAndValidateCertificate(
+    boolean verifyAndValidateCertificate(
             org.bouncycastle.crypto.tls.Certificate certificate)
         throws Exception
     {
-        org.bouncycastle.asn1.x509.Certificate[] certificateList
-            = certificate.getCertificateList();
+        boolean b = false;
 
-        if (certificateList.length == 0)
-            throw new IllegalArgumentException("certificate.certificateList");
+        try
+        {
+            org.bouncycastle.asn1.x509.Certificate[] certificateList
+                = certificate.getCertificateList();
 
-        for (org.bouncycastle.asn1.x509.Certificate x509Certificate
-                : certificateList)
+            if (certificateList.length == 0)
+            {
+                throw new IllegalArgumentException(
+                        "certificate.certificateList");
+            }
+            else
+            {
+                for (org.bouncycastle.asn1.x509.Certificate x509Certificate
+                        : certificateList)
+                {
+                    verifyAndValidateCertificate(x509Certificate);
+                }
+                b = true;
+            }
+        }
+        catch (Exception e)
         {
-            verifyAndValidateCertificate(x509Certificate);
+            /*
+             * XXX Contrary to RFC 5763 "Framework for Establishing a Secure
+             * Real-time Transport Protocol (SRTP) Security Context Using
+             * Datagram Transport Layer Security (DTLS)", we do NOT want to tear
+             * down the media session if the fingerprint does not match the
+             * hashed certificate. We want to notify the user via the
+             * SrtpListener.
+             */
+            // TODO Auto-generated method stub
+            String message
+                = "Failed to verify and/or validate a certificate offered over"
+                    + " the media path against fingerprints declared over the"
+                    + " signaling path!";
+            String throwableMessage = e.getMessage();
+
+            if ((throwableMessage == null) || (throwableMessage.length() == 0))
+                logger.warn(message, e);
+            else
+                logger.warn(message + " " + throwableMessage);
         }
+        return b;
     }
 }
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
index 2b66d7e6182f04cd91b4eaea9972b0ebaf4ef62c..47f5758805657e2c0b5c92bf0b81e817bba36a60 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
@@ -477,6 +477,10 @@ else if (delta < 0)
                             if (delta > 0)
                                 pkt.shrink(delta);
 
+                            /*
+                             * In DTLS-SRTP no application data is transmitted
+                             * over the DTLS channel.
+                             */
                             pkt = null;
                         }
                     }
@@ -491,7 +495,7 @@ else if (delta < 0)
             {
                 /*
                  * The specified pkt looks like a DTLS record but it is
-                 * unexpected in the current state of the secure channels
+                 * unexpected in the current state of the secure channel
                  * represented by this PacketTransformer.
                  */
                 pkt = null;
@@ -499,11 +503,15 @@ else if (delta < 0)
         }
         else
         {
+            /*
+             * XXX If DTLS-SRTP has not been initialized yet or has failed to
+             * initialize, it is our explicit policy to let the received packet
+             * pass through and rely on the SrtpListener to notify the user that
+             * the session is not secured.
+             */
             PacketTransformer srtpTransformer = this.srtpTransformer;
 
-            if (srtpTransformer == null)
-                pkt = null;
-            else
+            if (srtpTransformer != null)
                 pkt = srtpTransformer.reverseTransform(pkt);
         }
         return pkt;
@@ -522,8 +530,8 @@ private void runInConnectThread(
             DatagramTransport datagramTransport)
     {
         DTLSTransport dtlsTransport = null;
-        int srtpProtectionProfile;
-        TlsContext tlsContext;
+        int srtpProtectionProfile = 0;
+        TlsContext tlsContext = null;
 
         if (dtlsProtocol instanceof DTLSClientProtocol)
         {
@@ -544,8 +552,11 @@ private void runInConnectThread(
                         "Failed to connect this DTLS client to a DTLS server!",
                         ioe);
             }
-            srtpProtectionProfile = tlsClient.getChosenProtectionProfile();
-            tlsContext = tlsClient.getContext();
+            if (dtlsTransport != null)
+            {
+                srtpProtectionProfile = tlsClient.getChosenProtectionProfile();
+                tlsContext = tlsClient.getContext();
+            }
         }
         else if (dtlsProtocol instanceof DTLSServerProtocol)
         {
@@ -566,14 +577,19 @@ else if (dtlsProtocol instanceof DTLSServerProtocol)
                         "Failed to accept a connection from a DTLS client!",
                         ioe);
             }
-            srtpProtectionProfile = tlsServer.getChosenProtectionProfile();
-            tlsContext = tlsServer.getContext();
+            if (dtlsTransport != null)
+            {
+                srtpProtectionProfile = tlsServer.getChosenProtectionProfile();
+                tlsContext = tlsServer.getContext();
+            }
         }
         else
             throw new IllegalStateException("dtlsProtocol");
 
         PacketTransformer srtpTransformer
-            = initializeSRTPTransformer(srtpProtectionProfile, tlsContext);
+            = (dtlsTransport == null)
+                ? null
+                : initializeSRTPTransformer(srtpProtectionProfile, tlsContext);
         boolean closeSRTPTransformer;
 
         synchronized (this)
@@ -588,7 +604,7 @@ else if (dtlsProtocol instanceof DTLSServerProtocol)
             closeSRTPTransformer
                 = (this.srtpTransformer != srtpTransformer);
         }
-        if (closeSRTPTransformer)
+        if (closeSRTPTransformer && (srtpTransformer != null))
             srtpTransformer.close();
     }
 
@@ -799,11 +815,15 @@ public RawPacket transform(RawPacket pkt)
          */
         if (!isDtlsRecord(buf, off, len))
         {
+            /*
+             * XXX If DTLS-SRTP has not been initialized yet or has failed to
+             * initialize, it is our explicit policy to let the received packet
+             * pass through and rely on the SrtpListener to notify the user that
+             * the session is not secured.
+             */
             PacketTransformer srtpTransformer = this.srtpTransformer;
 
-            if (srtpTransformer == null)
-                pkt = null;
-            else
+            if (srtpTransformer != null)
                 pkt = srtpTransformer.transform(pkt);
         }
         return pkt;
diff --git a/src/org/jitsi/impl/neomedia/transform/zrtp/ZrtpRawPacket.java b/src/org/jitsi/impl/neomedia/transform/zrtp/ZrtpRawPacket.java
index 65cf9f4f3f494fd3610d1be30e6e238a34853a10..cc421119f2a8dc94ded4ab577475b6d436397df2 100644
--- a/src/org/jitsi/impl/neomedia/transform/zrtp/ZrtpRawPacket.java
+++ b/src/org/jitsi/impl/neomedia/transform/zrtp/ZrtpRawPacket.java
@@ -22,17 +22,10 @@
 public class ZrtpRawPacket extends RawPacket
 {
     /**
-     * Each ZRTP packet contains this magic number.
+     * Each ZRTP packet contains this magic number/cookie.
      */
-    public static byte[] zrtpMagic;
-
-    static {
-        zrtpMagic = new byte[4];
-        zrtpMagic[0]= 0x5a;
-        zrtpMagic[1]= 0x52;
-        zrtpMagic[2]= 0x54;
-        zrtpMagic[3]= 0x50;
-    }
+    public static final byte[] ZRTP_MAGIC
+        = new byte[] { 0x5a, 0x52, 0x54, 0x50 };
 
     /**
      * Construct an input ZrtpRawPacket using a received RTP raw packet.
@@ -41,7 +34,7 @@ public class ZrtpRawPacket extends RawPacket
      */
     public ZrtpRawPacket(RawPacket pkt)
     {
-        super (pkt.getBuffer(), pkt.getOffset(), pkt.getLength());
+        super(pkt.getBuffer(), pkt.getOffset(), pkt.getLength());
     }
 
     /**
@@ -61,10 +54,10 @@ public ZrtpRawPacket(byte[] buf, int off, int len)
         writeByte(1, (byte)0);
 
         int at = 4;
-        writeByte(at++, zrtpMagic[0]);
-        writeByte(at++, zrtpMagic[1]);
-        writeByte(at++, zrtpMagic[2]);
-        writeByte(at, zrtpMagic[3]);
+        writeByte(at++, ZRTP_MAGIC[0]);
+        writeByte(at++, ZRTP_MAGIC[1]);
+        writeByte(at++, ZRTP_MAGIC[2]);
+        writeByte(at, ZRTP_MAGIC[3]);
     }
 
     /**
@@ -88,13 +81,8 @@ protected boolean isZrtpPacket()
      */
     static boolean isZrtpData(RawPacket pkt)
     {
-        if(!pkt.getExtensionBit())
-            return false;
-
-        if(pkt.getHeaderExtensionType() == 0x505a)
-            return true;
-
-        return false;
+        return
+            pkt.getExtensionBit() && (pkt.getHeaderExtensionType() == 0x505a);
     }
 
     /**
@@ -108,10 +96,10 @@ static boolean isZrtpData(RawPacket pkt)
     protected boolean hasMagic()
     {
         return
-            (readByte(4) == zrtpMagic[0])
-                && (readByte(5) == zrtpMagic[1])
-                && (readByte(6) == zrtpMagic[2])
-                && (readByte(7) == zrtpMagic[3]);
+            (readByte(4) == ZRTP_MAGIC[0])
+                && (readByte(5) == ZRTP_MAGIC[1])
+                && (readByte(6) == ZRTP_MAGIC[2])
+                && (readByte(7) == ZRTP_MAGIC[3]);
     }
 
     /**
diff --git a/src/org/jitsi/service/neomedia/MediaService.java b/src/org/jitsi/service/neomedia/MediaService.java
index dcd441e5d4007748d2fdec836c7e97d10bc32632..e44b3071d6460bed6b5d4b2a305e1a8ec5a99f1f 100644
--- a/src/org/jitsi/service/neomedia/MediaService.java
+++ b/src/org/jitsi/service/neomedia/MediaService.java
@@ -102,8 +102,27 @@ public interface MediaService
      *
      * @return the newly created <tt>MediaStream</tt>.
      */
-    public MediaStream createMediaStream(StreamConnector connector,
-                                         MediaDevice     device);
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaDevice device);
+
+    /**
+     * Initializes a new <tt>MediaStream</tt> instance which is to exchange
+     * media of a specific <tt>MediaType</tt> via a specific
+     * <tt>StreamConnector</tt>.
+     *
+     * @param connector the <tt>StreamConnector</tt> the stream should use for
+     * sending and receiving media or <tt>null</tt> if the stream is to not have
+     * a <tt>StreamConnector</tt> configured at initialization time and a
+     * <tt>StreamConnector</tt> is to be specified later on
+     * @param mediaType the <tt>MediaType</tt> of the media to be exchanged by
+     * the new instance via the specified <tt>connector</tt>
+     * @return a new <tt>MediaStream</tt> instance which is to exchange media of
+     * the specified <tt>mediaType</tt> via the specified <tt>connector</tt>
+     */
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaType mediaType);
 
     /**
      * Creates a <tt>MediaStream</tt> that will be using the specified
@@ -116,14 +135,37 @@ public MediaStream createMediaStream(StreamConnector connector,
      * <tt>StreamConnector</tt> is to be specified later on
      * @param device the device to be used for both capture and playback of
      * media exchanged via the specified <tt>StreamConnector</tt>
-     * @param zrtpControl a control which is already created, used to control
+     * @param srtpControl a control which is already created, used to control
      * the ZRTP operations.
      *
      * @return the newly created <tt>MediaStream</tt>.
      */
-    public MediaStream createMediaStream(StreamConnector connector,
-                                         MediaDevice     device,
-                                         SrtpControl zrtpControl);
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaDevice device,
+            SrtpControl srtpControl);
+
+    /**
+     * Initializes a new <tt>MediaStream</tt> instance which is to exchange
+     * media of a specific <tt>MediaType</tt> via a specific
+     * <tt>StreamConnector</tt>. The security of the media exchange is to be
+     * controlled by a specific <tt>SrtpControl</tt>.
+     *
+     * @param connector the <tt>StreamConnector</tt> the stream should use for
+     * sending and receiving media or <tt>null</tt> if the stream is to not have
+     * a <tt>StreamConnector</tt> configured at initialization time and a
+     * <tt>StreamConnector</tt> is to be specified later on
+     * @param mediaType the <tt>MediaType</tt> of the media to be exchanged by
+     * the new instance via the specified <tt>connector</tt>
+     * @param srtpControl the <tt>SrtpControl</tt> to control the security of
+     * the media exchange
+     * @return a new <tt>MediaStream</tt> instance which is to exchange media of
+     * the specified <tt>mediaType</tt> via the specified <tt>connector</tt>
+     */
+    public MediaStream createMediaStream(
+            StreamConnector connector,
+            MediaType mediaType,
+            SrtpControl srtpControl);
 
     /**
      * Creates a new <tt>MediaDevice</tt> which uses a specific