diff -urN asterisk-11.9.0/channels/chan_sip.c asterisk-11.9.0-dtls/channels/chan_sip.c
--- asterisk-11.9.0/channels/chan_sip.c	2014-04-21 22:56:05.000000000 +0200
+++ asterisk-11.9.0-dtls/channels/chan_sip.c	2014-06-03 10:45:52.142802279 +0200
@@ -1401,7 +1401,7 @@
 static int process_sdp_a_text(const char *a, struct sip_pvt *p, struct ast_rtp_codecs *newtextrtp, char *red_fmtp, int *red_num_gen, int *red_data_pt, int *last_rtpmap_codec);
 static int process_sdp_a_image(const char *a, struct sip_pvt *p);
 static void add_ice_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
-static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf);
+static void add_dtls_to_sdp(struct ast_rtp_instance *instance, const struct sip_pvt *dialog, struct ast_str **a_buf);
 static void start_ice(struct ast_rtp_instance *instance);
 static void add_codec_to_sdp(const struct sip_pvt *p, struct ast_format *codec,
 			     struct ast_str **m_buf, struct ast_str **a_buf,
@@ -5891,10 +5891,6 @@
 		ice->stop(dialog->rtp);
 	}
 
-	if (dialog_initialize_dtls_srtp(dialog, dialog->rtp, &dialog->srtp)) {
-		return -1;
-	}
-
 	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT_ALWAYS) ||
 			(ast_test_flag(&dialog->flags[1], SIP_PAGE2_VIDEOSUPPORT) && (ast_format_cap_has_type(dialog->caps, AST_FORMAT_TYPE_VIDEO)))) {
 		if (!(dialog->vrtp = ast_rtp_instance_new(dialog->engine, sched, &bindaddr_tmp, NULL))) {
@@ -5905,16 +5901,17 @@
 			ice->stop(dialog->vrtp);
 		}
 
-		if (dialog_initialize_dtls_srtp(dialog, dialog->vrtp, &dialog->vsrtp)) {
-			return -1;
-		}
-
 		ast_rtp_instance_set_timeout(dialog->vrtp, dialog->rtptimeout);
 		ast_rtp_instance_set_hold_timeout(dialog->vrtp, dialog->rtpholdtimeout);
 		ast_rtp_instance_set_keepalive(dialog->vrtp, dialog->rtpkeepalive);
 
 		ast_rtp_instance_set_prop(dialog->vrtp, AST_RTP_PROPERTY_RTCP, 1);
 		ast_rtp_instance_set_qos(dialog->vrtp, global_tos_video, global_cos_video, "SIP VIDEO");
+		
+		/*SRTP_DTLS */
+		if (dialog_initialize_dtls_srtp(dialog, dialog->vrtp, &dialog->vsrtp)) {
+			return -1;
+		}
 	}
 
 	if (ast_test_flag(&dialog->flags[1], SIP_PAGE2_TEXTSUPPORT)) {
@@ -5926,14 +5923,15 @@
 			ice->stop(dialog->trtp);
 		}
 
-		if (dialog_initialize_dtls_srtp(dialog, dialog->trtp, &dialog->tsrtp)) {
-			return -1;
-		}
-
 		/* Do not timeout text as its not constant*/
 		ast_rtp_instance_set_keepalive(dialog->trtp, dialog->rtpkeepalive);
 
 		ast_rtp_instance_set_prop(dialog->trtp, AST_RTP_PROPERTY_RTCP, 1);
+		
+		/*SRTP_DTLS */
+		if (dialog_initialize_dtls_srtp(dialog, dialog->trtp, &dialog->tsrtp)) {
+			return -1;
+		}
 	}
 
 	ast_rtp_instance_set_timeout(dialog->rtp, dialog->rtptimeout);
@@ -5943,6 +5941,11 @@
 	ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_RTCP, 1);
 	ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF, ast_test_flag(&dialog->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833);
 	ast_rtp_instance_set_prop(dialog->rtp, AST_RTP_PROPERTY_DTMF_COMPENSATE, ast_test_flag(&dialog->flags[1], SIP_PAGE2_RFC2833_COMPENSATE));
+ 
+	/*SRTP_DTLS */
+	if (dialog_initialize_dtls_srtp(dialog, dialog->rtp, &dialog->srtp)) {
+		return -1;
+	}
 
 	ast_rtp_instance_set_qos(dialog->rtp, global_tos_audio, global_cos_audio, "SIP RTP");
 
@@ -9955,6 +9958,9 @@
 	/* SRTP */
 	int secure_audio = FALSE;
 	int secure_video = FALSE;
+/** SRTP_DTLS **/
+	int processed_dtls = FALSE;
+	/** SRTP_DTLS **/
 
 	/* Others */
 	int sendonly = -1;
@@ -10047,12 +10053,15 @@
 			}
 
 			if (process_sdp_a_dtls(value, p, p->rtp)) {
+				processed_dtls = TRUE;
 				processed = TRUE;
 			}
 			if (process_sdp_a_dtls(value, p, p->vrtp)) {
+				processed_dtls = TRUE;
 				processed = TRUE;
 			}
 			if (process_sdp_a_dtls(value, p, p->trtp)) {
+				processed_dtls = TRUE;
 				processed = TRUE;
 			}
 
@@ -10145,7 +10154,6 @@
 					}
 				} else if (!strcmp(protocol, "UDP/TLS/RTP/SAVP") || !strcmp(protocol, "UDP/TLS/RTP/SAVPF")) {
 					secure_audio = 1;
-
 					if (p->srtp) {
 						ast_set_flag(p->srtp, SRTP_CRYPTO_OFFER_OK);
 					}
@@ -10460,6 +10468,7 @@
 						processed = TRUE;
 					} else if (process_sdp_a_dtls(value, p, p->rtp)) {
 						processed = TRUE;
+						processed_dtls = TRUE;
 					} else if (process_sdp_a_sendonly(value, &sendonly)) {
 						processed = TRUE;
 					} else if (!processed_crypto && process_crypto(p, p->rtp, &p->srtp, value)) {
@@ -10475,6 +10484,7 @@
 						processed = TRUE;
 					} else if (process_sdp_a_dtls(value, p, p->vrtp)) {
 						processed = TRUE;
+						processed_dtls = TRUE;
 					} else if (!processed_crypto && process_crypto(p, p->vrtp, &p->vsrtp, value)) {
 						processed_crypto = TRUE;
 						processed = TRUE;
@@ -10508,10 +10518,11 @@
 		}
 
 		/* Ensure crypto lines are provided where necessary */
-		if (audio && secure_audio && !processed_crypto) {
+			ast_log(LOG_WARNING, "Processed DTLS [%s] \n", processed_dtls?"TRUE":"FALSE");
+			if (audio && secure_audio && !(processed_crypto || processed_dtls)) {
 			ast_log(LOG_WARNING, "Rejecting secure audio stream without encryption details: %s\n", m);
 			return -1;
-		} else if (video && secure_video && !processed_crypto) {
+			} else if (video && secure_video && !(processed_crypto || processed_dtls)) {
 			ast_log(LOG_WARNING, "Rejecting secure video stream without encryption details: %s\n", m);
 			return -1;
 		}
@@ -10533,6 +10544,9 @@
 		goto process_sdp_cleanup;
 	}
 
+	if(processed_dtls && p->srtp) {
+		ast_set_flag(p->srtp, SRTP_CRYPTO_OFFER_OK);
+	}
 	if (secure_audio && !(p->srtp && (ast_test_flag(p->srtp, SRTP_CRYPTO_OFFER_OK)))) {
 		ast_log(LOG_WARNING, "Can't provide secure audio requested in SDP offer\n");
 		res = -1;
@@ -11018,6 +11032,7 @@
 {
 	struct ast_rtp_engine_dtls *dtls;
 	int found = FALSE;
+	int found_setup = FALSE;
 	char value[256], hash[6];
 
 	if (!instance || !p->dtls_cfg.enabled || !(dtls = ast_rtp_instance_get_dtls(instance))) {
@@ -11026,7 +11041,7 @@
 
 	if (sscanf(a, "setup: %255s", value) == 1) {
 		found = TRUE;
-
+		found_setup = TRUE;
 		if (!strcasecmp(value, "active")) {
 			dtls->set_setup(instance, AST_RTP_DTLS_SETUP_ACTIVE);
 		} else if (!strcasecmp(value, "passive")) {
@@ -11050,17 +11065,26 @@
 			ast_log(LOG_WARNING, "Unsupported connection attribute value '%s' received on dialog '%s'\n",
 				value, p->callid);
 		}
-	} else if (sscanf(a, "fingerprint: %5s %255s", hash, value) == 2) {
+	} else if (sscanf(a, "fingerprint: %s %255s", hash, value) == 2) {
 		found = TRUE;
 
+		ast_log(LOG_WARNING, "Remote hash: %s\n", hash);
 		if (!strcasecmp(hash, "sha-1")) {
+			ast_log(LOG_WARNING, "  -- Setting remote SHA-1 fingerprint: %s\n", value);
 			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1, value);
+		} else if (!strcasecmp(hash, "sha-256")) {
+			ast_log(LOG_WARNING, "  -- Setting remote SHA-256 fingerprint: %s\n", value);
+			dtls->set_fingerprint(instance, AST_RTP_DTLS_HASH_SHA256, value);
 		} else {
 			ast_log(LOG_WARNING, "Unsupported fingerprint hash type '%s' received on dialog '%s'\n",
 				hash, p->callid);
 		}
 	}
-
+	if (found && !found_setup)
+	{
+		/* No setup line provided by WebRTC peer */
+		dtls->set_setup(instance, AST_RTP_DTLS_SETUP_PASSIVE);
+	}
 	return found;
 }
 
@@ -12706,11 +12730,14 @@
 }
 
 /*! \brief Add DTLS attributes to SDP */
-static void add_dtls_to_sdp(struct ast_rtp_instance *instance, struct ast_str **a_buf)
+static void add_dtls_to_sdp(struct ast_rtp_instance *instance, const struct sip_pvt *dialog, struct ast_str **a_buf)
 {
 	struct ast_rtp_engine_dtls *dtls;
 	const char *fingerprint;
+	/*SRTP_DTLS */
+	dtls = ast_rtp_instance_get_dtls(instance);
 
+	/*SRTP_DTLS */
 	if (!instance || !(dtls = ast_rtp_instance_get_dtls(instance)) || !dtls->active(instance)) {
 		return;
 	}
@@ -12743,9 +12770,17 @@
 		break;
 	}
 
-	if ((fingerprint = dtls->get_fingerprint(instance, AST_RTP_DTLS_HASH_SHA1))) {
+	if ((fingerprint = dtls->get_fingerprint(instance, &dialog->dtls_cfg, AST_RTP_DTLS_HASH_SHA256))) {
+			ast_str_append(a_buf, 0, "a=fingerprint:SHA-256 %s\r\n", fingerprint);
+	}
+	else if ((fingerprint = dtls->get_fingerprint(instance, &dialog->dtls_cfg, AST_RTP_DTLS_HASH_SHA1)))
+	{
 		ast_str_append(a_buf, 0, "a=fingerprint:SHA-1 %s\r\n", fingerprint);
 	}
+	else 
+	{
+		ast_log(LOG_ERROR, "Can't add fingerprint....");
+	}
 }
 
 /*! \brief Add codec offer to SDP offer/answer body in INVITE or 200 OK */
@@ -13052,7 +13087,9 @@
 	struct ast_rtp_engine_dtls *dtls;
 
 	if ((dtls = ast_rtp_instance_get_dtls(instance)) && dtls->active(instance)) {
-		return ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF) ? "UDP/TLS/RTP/SAVPF" : "UDP/TLS/RTP/SAVP";
+				/*SRTP_DTLS */
+		return ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF) ? "RTP/SAVPF" : "RTP/SAVP";
+		/*SRTP_DTLS */
 	} else {
 		if (ast_test_flag(&p->flags[2], SIP_PAGE3_USE_AVPF)) {
 			return secure ? "RTP/SAVPF" : "RTP/AVPF";
@@ -13231,12 +13268,15 @@
 				ast_verbose("Video is at %s\n", ast_sockaddr_stringify(&vdest));
 			}
 
+			/* Meetecho: add a=rtcp attribute */
+			ast_str_append(&a_video, 0, "a=rtcp:%d\r\n", ast_sockaddr_port(&vdest)+1);
+
 			if (!doing_directmedia) {
 				if (ast_test_flag(&p->flags[2], SIP_PAGE3_ICE_SUPPORT)) {
 					add_ice_to_sdp(p->vrtp, &a_video);
 				}
 
-				add_dtls_to_sdp(p->vrtp, &a_video);
+				add_dtls_to_sdp(p->vrtp, p, &a_video);
 			}
 		}
 
@@ -13257,7 +13297,7 @@
 					add_ice_to_sdp(p->trtp, &a_text);
 				}
 
-				add_dtls_to_sdp(p->trtp, &a_text);
+				add_dtls_to_sdp(p->trtp, p, &a_text);
 			}
 		}
 
@@ -13314,6 +13354,9 @@
 			ast_format_cap_add(alreadysent, &tmp_fmt);
 		}
 
+		/* Meetecho: add a=rtcp attribute */
+		ast_str_append(&a_audio, 0, "a=rtcp:%d\r\n", ast_sockaddr_port(&dest)+1);
+
 		/* Now send any other common audio and video codecs, and non-codec formats: */
 		ast_format_cap_iter_start(tmpcap);
 		while (!(ast_format_cap_iter_next(tmpcap, &tmp_fmt))) {
@@ -13359,7 +13402,7 @@
 				add_ice_to_sdp(p->rtp, &a_audio);
 			}
 
-			add_dtls_to_sdp(p->rtp, &a_audio);
+			add_dtls_to_sdp(p->rtp, p, &a_audio);
 		}
 	}
 
@@ -31279,26 +31322,21 @@
 		peer->socket.port = htons(((peer->socket.type & SIP_TRANSPORT_TLS) ? STANDARD_TLS_PORT : STANDARD_SIP_PORT));
 	}
 
-	if (realtime) {
-		int enablepoke = 1;
-
-		if (!sip_cfg.ignore_regexpire && peer->host_dynamic) {
-			time_t nowtime = time(NULL);
+	if (!sip_cfg.ignore_regexpire && peer->host_dynamic && realtime) {
+		time_t nowtime = time(NULL);
 
-			if ((nowtime - regseconds) > 0) {
-				destroy_association(peer);
-				memset(&peer->addr, 0, sizeof(peer->addr));
-				peer->lastms = -1;
-				enablepoke = 0;
-				ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
-			}
+		if ((nowtime - regseconds) > 0) {
+			destroy_association(peer);
+			memset(&peer->addr, 0, sizeof(peer->addr));
+			peer->lastms = -1;
+			ast_debug(1, "Bah, we're expired (%d/%d/%d)!\n", (int)(nowtime - regseconds), (int)regseconds, (int)nowtime);
 		}
+	}
 
-		/* Startup regular pokes */
-		if (!devstate_only && enablepoke) {
-			sip_ref_peer(peer, "schedule qualify");
-			sip_poke_peer(peer, 0);
-		}
+	/* Startup regular pokes */
+	if (!devstate_only && realtime && peer->lastms > 0) {
+		sip_ref_peer(peer, "schedule qualify");
+		sip_poke_peer(peer, 0);
 	}
 
 	if (ast_test_flag(&peer->flags[1], SIP_PAGE2_ALLOWSUBSCRIBE)) {
@@ -33334,11 +33372,6 @@
 
 	ast_set_flag(*srtp, SRTP_CRYPTO_OFFER_OK);
 
-	if ((dtls = ast_rtp_instance_get_dtls(rtp))) {
-		dtls->stop(rtp);
-		p->dtls_cfg.enabled = 0;
-	}
-
 	return TRUE;
 }
 
diff -urN asterisk-11.9.0/include/asterisk/rtp_engine.h asterisk-11.9.0-dtls/include/asterisk/rtp_engine.h
--- asterisk-11.9.0/include/asterisk/rtp_engine.h	2014-02-27 13:47:29.000000000 +0100
+++ asterisk-11.9.0-dtls/include/asterisk/rtp_engine.h	2014-06-03 10:41:21.393722582 +0200
@@ -375,7 +375,11 @@
 
 /*! \brief DTLS fingerprint hashes */
 enum ast_rtp_dtls_hash {
+	AST_RTP_DTLS_HASH_NONE, /* Uninitialized */
 	AST_RTP_DTLS_HASH_SHA1, /*!< SHA-1 fingerprint hash */
+	/*SRTP_DTLS */
+	AST_RTP_DTLS_HASH_SHA256, /*!< SHA-256 fingerprint hash */
+	/*SRTP_DTLS */
 };
 
 /*! \brief DTLS configuration structure */
@@ -411,7 +415,7 @@
 	/*! Set the remote fingerprint */
 	void (*set_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint);
 	/*! Get the local fingerprint */
-	const char *(*get_fingerprint)(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash);
+	const char *(*get_fingerprint)(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg, enum ast_rtp_dtls_hash hash);
 };
 
 /*! Structure that represents an RTP stack (engine) */
diff -urN asterisk-11.9.0/res/res_rtp_asterisk.c asterisk-11.9.0-dtls/res/res_rtp_asterisk.c
--- asterisk-11.9.0/res/res_rtp_asterisk.c	2014-03-04 17:40:39.000000000 +0100
+++ asterisk-11.9.0-dtls/res/res_rtp_asterisk.c	2014-06-03 10:42:56.759475326 +0200
@@ -128,6 +128,8 @@
 static int rtpdebug;			/*!< Are we debugging? */
 static int rtcpdebug;			/*!< Are we debugging RTCP? */
 static int rtcpstats;			/*!< Are we debugging RTCP? */
+/* SRTP_DTLS */
+static int dtlsdebug;
 static int rtcpinterval = RTCP_DEFAULT_INTERVALMS; /*!< Time between rtcp reports in millisecs */
 static struct ast_sockaddr rtpdebugaddr;	/*!< Debug packets to/from this host */
 static struct ast_sockaddr rtcpdebugaddr;	/*!< Debug RTCP packets to/from this host */
@@ -268,6 +270,13 @@
 	ast_cond_t cond;            /*!< Condition for signaling */
 	unsigned int passthrough:1; /*!< Bit to indicate that the received packet should be passed through */
 	unsigned int ice_port;      /*!< Port that ICE was started with if it was previously started */
+	/* SRTP_DTLS */
+	unsigned int icecomplete:1; /*!< Bit to indicate ICE connectivity checks have completed */
+	unsigned int icedone:1; /*!< Bit to indicate ICE connectivity checks have completed (go on with RTP or DTLS) */
+	unsigned int dtlsinit:1; /*!< Bit to indicate DTLS-SRTP setup has been started (whether to start DTLS or not) */
+	unsigned int dtlsdone:1; /*!< Bit to indicate DTLS-SRTP setup has been completed (go on with RTP or DTLS) */
+	struct ast_rtp_instance *instance;
+	/* SRTP_DTLS */
 
 	char remote_ufrag[256];  /*!< The remote ICE username */
 	char remote_passwd[256]; /*!< The remote ICE password */
@@ -289,11 +298,14 @@
 	enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
 	enum ast_srtp_suite suite;   /*!< SRTP crypto suite */
 	char local_fingerprint[160]; /*!< Fingerprint of our certificate */
+	enum ast_rtp_dtls_hash local_fingerprint_type; /*!< Local fingerprint type */
 	unsigned char remote_fingerprint[EVP_MAX_MD_SIZE]; /*!< Fingerprint of the peer certificate */
+	enum ast_rtp_dtls_hash remote_fingerprint_type; /*!< Remote fingerprint type */
 	enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
 	unsigned int dtls_failure:1; /*!< Failure occurred during DTLS negotiation */
 	unsigned int rekey; /*!< Interval at which to renegotiate and rekey */
 	int rekeyid; /*!< Scheduled item id for rekeying */
+	int dtlstimerid; /*!< Scheduled item id for DTLS retransmission for RTP */
 #endif
 };
 
@@ -356,6 +368,28 @@
 	double normdevrtt;
 	double stdevrtt;
 	unsigned int rtt_count;
+	/* VP8: sequence number for the RTCP FIR FCI */
+ 	int firseq;
+	/* SRTP_DTLS */
+        unsigned int icecomplete:1; /*!< Bit to indicate ICE connectivity checks have completed */
+        unsigned int icedone:1; /*!< Bit to indicate ICE connectivity checks have completed (go on with RTCP or DTLS) */
+        unsigned int dtlsdone:1; /*!< Bit to indicate DTLS-SRTP setup has been completed (go on with RTCP or DTLS) */
+#ifdef HAVE_OPENSSL_SRTP
+        SSL_CTX *ssl_ctx; /*!< SSL context */
+        SSL *ssl;         /*!< SSL session */
+        BIO *read_bio;    /*!< Memory buffer for reading */
+        BIO *write_bio;   /*!< Memory buffer for writing */
+        enum ast_rtp_dtls_setup dtls_setup; /*!< Current setup state */
+        enum ast_srtp_suite suite;   /*!< SRTP crypto suite */
+        char local_fingerprint[160]; /*!< Fingerprint of our certificate */
+        unsigned char remote_fingerprint[EVP_MAX_MD_SIZE]; /*!< Fingerprint of the peer certificate */
+        enum ast_rtp_dtls_connection connection; /*!< Whether this is a new or existing connection */
+        unsigned int dtls_failure:1; /*!< Failure occurred during DTLS negotiation */
+        unsigned int rekey; /*!< Interval at which to renegotiate and rekey */
+        int rekeyid; /*!< Scheduled item id for rekeying */
+#endif
+	/* SRTP_DTLS */
+
 };
 
 struct rtp_red {
@@ -403,6 +437,9 @@
 
 #ifdef HAVE_OPENSSL_SRTP
 static int ast_rtp_activate(struct ast_rtp_instance *instance);
+/* SRTP_DTLS DTLS certificate verification callback */
+static int dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx);
+/* SRTP_DTLS */
 #endif
 
 static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *ice, int use_srtp);
@@ -788,6 +825,10 @@
 	if (!(where & SSL_CB_ALERT)) {
 		return;
 	}
+	/* SRTP_DTLS */
+	ast_verbose(VERBOSE_PREFIX_3 "dtls_info_callback: %s, where=%d, ret=%d\n", (where & SSL_CB_READ)?"read":"write", where, ret);
+	ast_verbose(VERBOSE_PREFIX_3 "  >> %s, %s, %s\n", SSL_state_string(ssl), SSL_alert_type_string(ret), SSL_alert_desc_string(ret));
+	/* SRTP_DTLS */
 
 	rtp->dtls_failure = 1;
 }
@@ -808,7 +849,9 @@
 		return -1;
 	}
 
-	SSL_CTX_set_verify(rtp->ssl_ctx, dtls_cfg->verify ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, NULL);
+	/* SRTP_DTLS */
+	SSL_CTX_set_verify(rtp->ssl_ctx, dtls_cfg->verify ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, dtls_verify_callback);
+	/* SRTP_DTLS */
 
 	if (dtls_cfg->suite == AST_AES_CM_128_HMAC_SHA1_80) {
 		SSL_CTX_set_tlsext_use_srtp(rtp->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
@@ -848,14 +891,17 @@
 
 		if (!BIO_read_filename(certbio, dtls_cfg->certfile) ||
 		    !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL)) ||
-		    !X509_digest(cert, EVP_sha1(), fingerprint, &size) ||
+		    !X509_digest(cert, EVP_sha256(), fingerprint, &size) ||
 		    !size) {
 			ast_log(LOG_ERROR, "Could not produce fingerprint from certificate '%s' for RTP instance '%p'\n",
 				dtls_cfg->certfile, instance);
 			BIO_free_all(certbio);
 			goto error;
 		}
-
+		else
+		{
+			rtp->local_fingerprint_type = AST_RTP_DTLS_HASH_SHA256;
+		}
 		for (i = 0; i < size; i++) {
 			sprintf(local_fingerprint, "%.2X:", fingerprint[i]);
 			local_fingerprint += 3;
@@ -919,6 +965,112 @@
 
 	rtp->connection = AST_RTP_DTLS_CONNECTION_NEW;
 
+	        /* SRTP_DTLS: do the same with RTCP */
+        if (!(rtp->rtcp->ssl_ctx = SSL_CTX_new(DTLSv1_method()))) {
+               return -1;
+        }
+        SSL_CTX_set_verify(rtp->rtcp->ssl_ctx, dtls_cfg->verify ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE, NULL);
+        if (dtls_cfg->suite == AST_AES_CM_128_HMAC_SHA1_80) {
+                SSL_CTX_set_tlsext_use_srtp(rtp->rtcp->ssl_ctx, "SRTP_AES128_CM_SHA1_80");
+        } else if (dtls_cfg->suite == AST_AES_CM_128_HMAC_SHA1_32) {
+                SSL_CTX_set_tlsext_use_srtp(rtp->rtcp->ssl_ctx, "SRTP_AES128_CM_SHA1_32");
+        } else {
+                ast_log(LOG_ERROR, "Unsupported suite specified for DTLS-SRTP on RTCP instance '%p'\n", instance);
+                goto error;
+        }
+        if (!ast_strlen_zero(dtls_cfg->certfile)) {
+                char *private = ast_strlen_zero(dtls_cfg->pvtfile) ? dtls_cfg->certfile : dtls_cfg->pvtfile;
+                BIO *certbio;
+                X509 *cert;
+                unsigned int size, i;
+                unsigned char fingerprint[EVP_MAX_MD_SIZE];
+                char *local_fingerprint = rtp->rtcp->local_fingerprint;
+                if (!SSL_CTX_use_certificate_file(rtp->rtcp->ssl_ctx, dtls_cfg->certfile, SSL_FILETYPE_PEM)) {
+                        ast_log(LOG_ERROR, "Specified certificate file '%s' for RTCP instance '%p' could not be used\n",
+                                dtls_cfg->certfile, instance);
+                        goto error;
+                }
+                if (!SSL_CTX_use_PrivateKey_file(rtp->rtcp->ssl_ctx, private, SSL_FILETYPE_PEM) ||
+                    !SSL_CTX_check_private_key(rtp->rtcp->ssl_ctx)) {
+                        ast_log(LOG_ERROR, "Specified private key file '%s' for RTCP instance '%p' could not be used\n",
+                                private, instance);
+                        goto error;
+                }
+                if (!(certbio = BIO_new(BIO_s_file()))) {
+                        ast_log(LOG_ERROR, "Failed to allocate memory for certificate fingerprinting on RTCP instance '%p'\n",
+                                instance);
+                        goto error;
+                }
+		if (!(certbio = BIO_new(BIO_s_file()))) {
+			ast_log(LOG_ERROR, "Failed to allocate memory for certificate fingerprinting on RTCP instance '%p'\n",
+				instance);
+			goto error;
+		}
+		if (!BIO_read_filename(certbio, dtls_cfg->certfile) ||
+		    !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL)) ||
+		    /* SRTP_DTLS: use SHA256 for DTLS-SRTP Fingerprint */
+		    !X509_digest(cert, EVP_sha256(), fingerprint, &size) ||
+		    !size) {
+			ast_log(LOG_ERROR, "Could not produce fingerprint from certificate '%s' for RTCP instance '%p'\n",
+				dtls_cfg->certfile, instance);
+			BIO_free_all(certbio);
+			goto error;
+		}
+		for (i = 0; i < size; i++) {
+			sprintf(local_fingerprint, "%.2X:", fingerprint[i]);
+			local_fingerprint += 3;
+		}
+  	*(local_fingerprint-1) = 0;
+ 	BIO_free_all(certbio);
+	}
+
+        if (!ast_strlen_zero(dtls_cfg->cipher)) {
+                if (!SSL_CTX_set_cipher_list(rtp->rtcp->ssl_ctx, dtls_cfg->cipher)) {
+                        ast_log(LOG_ERROR, "Invalid cipher specified in cipher list '%s' for RTCP instance '%p'\n",
+                                dtls_cfg->cipher, instance);
+                        goto error;
+                }
+        }
+        if (!ast_strlen_zero(dtls_cfg->cafile) || !ast_strlen_zero(dtls_cfg->capath)) {
+                if (!SSL_CTX_load_verify_locations(rtp->rtcp->ssl_ctx, S_OR(dtls_cfg->cafile, NULL), S_OR(dtls_cfg->capath, NULL))) {
+                        ast_log(LOG_ERROR, "Invalid certificate authority file '%s' or path '%s' specified for RTCP instance '%p'\n",
+                                S_OR(dtls_cfg->cafile, ""), S_OR(dtls_cfg->capath, ""), instance);
+                        goto error;
+                }
+        }
+
+	rtp->rtcp->rekey = dtls_cfg->rekey;
+        rtp->rtcp->dtls_setup = dtls_cfg->default_setup;
+        rtp->rtcp->suite = dtls_cfg->suite;
+        if (!(rtp->rtcp->ssl = SSL_new(rtp->rtcp->ssl_ctx))) {
+                ast_log(LOG_ERROR, "Failed to allocate memory for SSL context on RTCP instance '%p'\n",
+                        instance);
+                goto error;
+        }
+        SSL_set_ex_data(rtp->rtcp->ssl, 0, rtp);
+        SSL_set_info_callback(rtp->rtcp->ssl, dtls_info_callback);
+        if (!(rtp->rtcp->read_bio = BIO_new(BIO_s_mem()))) {
+                ast_log(LOG_ERROR, "Failed to allocate memory for inbound SSL traffic on RTCP instance '%p'\n",
+                        instance);
+                goto error;
+        }
+        BIO_set_mem_eof_return(rtp->rtcp->read_bio, -1);
+        if (!(rtp->rtcp->write_bio = BIO_new(BIO_s_mem()))) {
+                ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic on RTCP instance '%p'\n",
+                        instance);
+                goto error;
+        }
+        BIO_set_mem_eof_return(rtp->rtcp->write_bio, -1);
+
+	SSL_set_bio(rtp->rtcp->ssl, rtp->rtcp->read_bio, rtp->rtcp->write_bio);
+        if (rtp->rtcp->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+                SSL_set_accept_state(rtp->rtcp->ssl);
+        } else {
+                SSL_set_connect_state(rtp->rtcp->ssl);
+        }
+        rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+
+	
 	return 0;
 
 error:
@@ -939,6 +1091,21 @@
 
 	SSL_CTX_free(rtp->ssl_ctx);
 	rtp->ssl_ctx = NULL;
+	/* SRTP_DTLS: do the same with RTCP */
+	if (rtp->rtcp->read_bio) {
+		BIO_free(rtp->rtcp->read_bio);
+		rtp->rtcp->read_bio = NULL;
+	}
+	if (rtp->rtcp->write_bio) {
+		BIO_free(rtp->rtcp->write_bio);
+		rtp->rtcp->write_bio = NULL;
+	}
+	if (rtp->rtcp->ssl) {
+		SSL_free(rtp->rtcp->ssl);
+		rtp->rtcp->ssl = NULL;
+	}
+	SSL_CTX_free(rtp->rtcp->ssl_ctx);
+	rtp->rtcp->ssl_ctx = NULL;
 
 	return -1;
 }
@@ -946,7 +1113,6 @@
 static int ast_rtp_dtls_active(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-
 	return !rtp->ssl_ctx ? 0 : 1;
 }
 
@@ -954,6 +1120,8 @@
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 
+		ast_verbose(VERBOSE_PREFIX_3 "Stopping DTLS...\n");
+
 	if (rtp->ssl_ctx) {
 		SSL_CTX_free(rtp->ssl_ctx);
 		rtp->ssl_ctx = NULL;
@@ -963,6 +1131,16 @@
 		SSL_free(rtp->ssl);
 		rtp->ssl = NULL;
 	}
+	
+	/* SRTP_DTLS: do the same with RTCP */
+	if (rtp->rtcp->ssl_ctx) {
+		SSL_CTX_free(rtp->rtcp->ssl_ctx);
+		rtp->rtcp->ssl_ctx = NULL;
+	}
+	if (rtp->rtcp->ssl) {
+		SSL_free(rtp->rtcp->ssl);
+		rtp->rtcp->ssl = NULL;
+	}
 }
 
 static void ast_rtp_dtls_reset(struct ast_rtp_instance *instance)
@@ -976,6 +1154,13 @@
 
 	SSL_shutdown(rtp->ssl);
 	rtp->connection = AST_RTP_DTLS_CONNECTION_NEW;
+	
+	/* SRTP_DTLS: do the same with RTCP */
+	if (!SSL_is_init_finished(rtp->rtcp->ssl)) {
+		return;
+	}
+	SSL_shutdown(rtp->rtcp->ssl);
+	rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_NEW;
 }
 
 static enum ast_rtp_dtls_connection ast_rtp_dtls_get_connection(struct ast_rtp_instance *instance)
@@ -1035,32 +1220,138 @@
 	} else {
 		return;
 	}
+	
+	/* SRTP_DTLS: do the same with RTCP */
+	rtp->rtcp->dtls_setup = rtp->dtls_setup;
+	if (rtp->rtcp->dtls_setup == AST_RTP_DTLS_SETUP_ACTIVE) {
+		SSL_set_connect_state(rtp->rtcp->ssl);
+	} else if (rtp->rtcp->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
+		SSL_set_accept_state(rtp->rtcp->ssl);
+	} else {
+		return;
+	}
 }
 
 static void ast_rtp_dtls_set_fingerprint(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash, const char *fingerprint)
 {
+	ast_log(LOG_WARNING, "Remote fingerprint of type %d: %s\n", hash, fingerprint);
 	char *tmp = ast_strdupa(fingerprint), *value;
 	int pos = 0;
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 
-	if (hash != AST_RTP_DTLS_HASH_SHA1) {
-		return;
+	if (hash == AST_RTP_DTLS_HASH_SHA1)
+	{
+		rtp->remote_fingerprint_type = AST_RTP_DTLS_HASH_SHA1;
+	}
+	else if(hash == AST_RTP_DTLS_HASH_SHA256)
+	{
+		rtp->remote_fingerprint_type = AST_RTP_DTLS_HASH_SHA256;
 	}
 
 	while ((value = strsep(&tmp, ":")) && (pos != (EVP_MAX_MD_SIZE - 1))) {
 		sscanf(value, "%02x", (unsigned int*)&rtp->remote_fingerprint[pos++]);
 	}
+	ast_log(LOG_ERROR,"remote fingerprint (RTP) set\n"); 
+	
+	/* SRTP_DTLS: do the same with RTCP */
+	while ((value = strsep(&tmp, ":")) && (pos != (EVP_MAX_MD_SIZE - 1))) {
+		sscanf(value, "%02x", (unsigned int*)&rtp->rtcp->remote_fingerprint[pos++]);
+	}
+	ast_log(LOG_ERROR,"remote fingerprint (RTCP) set\n"); 
 }
 
-static const char *ast_rtp_dtls_get_fingerprint(struct ast_rtp_instance *instance, enum ast_rtp_dtls_hash hash)
+static const char *ast_rtp_dtls_get_fingerprint(struct ast_rtp_instance *instance, const struct ast_rtp_dtls_cfg *dtls_cfg, enum ast_rtp_dtls_hash fingerprint_type)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
 
-	if (hash != AST_RTP_DTLS_HASH_SHA1) {
+    ast_debug(2, "SRTP_DTLS--Inside ast_rtp_dtls_get_fingerprint\n");
+	if (rtp->remote_fingerprint_type > 0 && rtp->remote_fingerprint_type != fingerprint_type)
+	{
+		ast_log(LOG_WARNING, "Not the fingerprint type we're interested in (%d != %d)\n", rtp->remote_fingerprint_type, fingerprint_type);
 		return NULL;
 	}
 
-	return rtp->local_fingerprint;
+	if (rtp->remote_fingerprint_type == 0)
+	{
+		ast_log(LOG_WARNING, "No remote fingerprint type, we're offering...\n");
+		if (rtp->local_fingerprint_type == AST_RTP_DTLS_HASH_SHA256)
+		{
+			ast_log(LOG_WARNING, "  -- Returning local fingerprint of type %d: %s\n", fingerprint_type, rtp->local_fingerprint ? rtp->local_fingerprint : "NULL");
+			return rtp->local_fingerprint;
+		}
+		ast_log(LOG_WARNING, "  -- Skipping SHA-1\n");
+		return NULL;
+	}
+	if (rtp->local_fingerprint_type == rtp->remote_fingerprint_type)
+	{
+		ast_log(LOG_WARNING, "Returning local fingerprint of type %d: %s\n", fingerprint_type, rtp->local_fingerprint ? rtp->local_fingerprint : "NULL");
+		return rtp->local_fingerprint;
+	}
+	else
+	{
+		ast_log(LOG_WARNING, "Recalculating local fingerprint of type %d\n", fingerprint_type);
+		/* Remote fingerprint type is different from local fingerprint type
+		   recaclulate the local fingerprint */
+		if (dtls_cfg != NULL && dtls_cfg->certfile != NULL)
+		{
+			BIO *certbio;
+			unsigned char fingerprint[EVP_MAX_MD_SIZE];
+			char *local_fingerprint = rtp->local_fingerprint;
+			unsigned int size = 0;
+			unsigned int i = 0;
+			X509 *cert;
+			unsigned int failed = 0;
+			if (!(certbio = BIO_new(BIO_s_file()))) {
+				ast_log(LOG_ERROR, "Failed to allocate memory for certificate fingerprinting on RTP instance '%p'\n",
+				instance);
+				return NULL;
+			}
+
+			if (rtp->remote_fingerprint_type == AST_RTP_DTLS_HASH_SHA256)
+			{
+				if (!BIO_read_filename(certbio, dtls_cfg->certfile) ||
+		                  !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL)) ||
+		                  !X509_digest(cert, EVP_sha256(), fingerprint, &size) ||
+		                  !size) {
+					failed = 1;
+					ast_log(LOG_ERROR, "Could not produce fingerprint from certificate '%s' for RTP instance '%p'\n",
+					        dtls_cfg->certfile, instance);
+				}
+			}
+			else if (rtp->remote_fingerprint_type == AST_RTP_DTLS_HASH_SHA1)
+			{
+				if (!BIO_read_filename(certbio, dtls_cfg->certfile) ||
+		                  !(cert = PEM_read_bio_X509(certbio, NULL, 0, NULL)) ||
+		                  !X509_digest(cert, EVP_sha1(), fingerprint, &size) ||
+		                  !size) {
+					failed = 1;
+					ast_log(LOG_ERROR, "Could not produce fingerprint from certificate '%s' for RTP instance '%p'\n",
+					        dtls_cfg->certfile, instance);
+				}
+			}
+			BIO_free_all(certbio);
+			if (!failed)
+			{
+			    for (i = 0; i < size; i++) {
+			    	sprintf(local_fingerprint, "%.2X:", fingerprint[i]);
+		     	    	local_fingerprint += 3;
+			    }
+			    *(local_fingerprint-1) = 0;
+			    rtp->local_fingerprint_type = rtp->remote_fingerprint_type;
+				ast_log(LOG_WARNING, "  -- Returning recalculated local fingerprint of type %d: %s\n", fingerprint_type, rtp->local_fingerprint ? rtp->local_fingerprint : "NULL");
+			    return rtp->local_fingerprint;
+			}
+			else
+			{
+			    return NULL;
+			}
+		}
+		else
+		{
+			ast_log(LOG_ERROR, "  -- Missing DTLS configuration?\n");
+			return NULL;
+		}
+	}
 }
 
 /* DTLS RTP Engine interface declaration */
@@ -1117,18 +1408,11 @@
 static void rtp_learning_seq_init(struct rtp_learning_info *info, uint16_t seq);
 
 #ifdef USE_PJPROJECT
-static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status)
-{
-	struct ast_rtp *rtp = ice->user_data;
-
-	if (!strictrtp) {
-		return;
-	}
-
-	rtp->strict_rtp_state = STRICT_RTP_LEARN;
-	rtp_learning_seq_init(&rtp->rtp_source_learn, (uint16_t)rtp->seqno);
-}
-
+/* SRTP_DTLS: callback to known when ICE is complete */
+#ifdef HAVE_OPENSSL_SRTP
+static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp);
+#endif
+/*SRTP_DTLS */
 static void ast_rtp_on_ice_rx_data(pj_ice_sess *ice, unsigned comp_id, unsigned transport_id, void *pkt, pj_size_t size, const pj_sockaddr_t *src_addr, unsigned src_addr_len)
 {
 	struct ast_rtp *rtp = ice->user_data;
@@ -1146,6 +1430,16 @@
 
 	if (transport_id == TRANSPORT_SOCKET_RTP) {
 		/* Traffic is destined to go right out the RTP socket we already have */
+				/* SRTP_DTLS : are we sending DTLS? */
+		if(dtlsdebug > 1)
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP] ast_rtp_on_ice_tx_pkt (%zu)\n", size);
+		const char *out = pkt;
+		if ((*out >= 20) && (*out <= 64)) {
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP] Sending DTLS data (%zu)\n", size);
+			}
+		}
 		status = pj_sock_sendto(rtp->s, pkt, &_size, 0, dst_addr, dst_addr_len);
 		/* sendto on a connectionless socket should send all the data, or none at all */
 		ast_assert(_size == size || status != PJ_SUCCESS);
@@ -1173,6 +1467,48 @@
 	return status;
 }
 
+static void ast_rtp_on_ice_complete(pj_ice_sess *ice, pj_status_t status) {
+	struct ast_rtp *rtp = ice->user_data;
+	ast_verbose(VERBOSE_PREFIX_3 "ICE is now complete\n");
+	rtp->icecomplete = 1;
+	/* SRTP_DTLS: do the same with RTCP (FIXME is this true??) */
+	rtp->rtcp->icecomplete = 1;
+	/* SRTP_DTLS: since ICE has been completed, we can do the DTLS handshake */
+	if(rtp->icecomplete) {
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP] ICE has been completed, yay!\n");
+		}
+		rtp->icecomplete = 0;
+		rtp->icedone = 1;
+		if (rtp->ssl) {
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP]    >> Doing DTLS handshake as well...\n");
+			}
+			SSL_do_handshake(rtp->ssl);
+			dtls_srtp_check_pending(rtp->instance, rtp);
+		}
+	}
+	/* SRTP_DTLS: do the same with RTCP */
+	if(rtp->rtcp->icecomplete) {
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTCP] ICE has been completed, yay!\n");
+		}
+		rtp->rtcp->icecomplete = 0;
+		rtp->rtcp->icedone = 1;
+		if (rtp->rtcp->ssl) {
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> Doing DTLS handshake as well...\n");
+			}
+			SSL_do_handshake(rtp->rtcp->ssl);
+			dtls_srtp_check_pending(rtp->instance, rtp);
+		}
+	}
+}
+
 /* ICE Session interface declaration */
 static pj_ice_sess_cb ast_rtp_ice_sess_cb = {
 	.on_ice_complete = ast_rtp_on_ice_complete,
@@ -1319,9 +1655,41 @@
 }
 
 #ifdef HAVE_OPENSSL_SRTP
+/* SRTP_DTLS: DTLS certificate verification callback */
+static int dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
+	/* We just use the verify_callback to request a certificate from the client */
+	return 1;
+}
+
+static int dtls_srtp_handle_timeout(const void *data)
+{
+	struct ast_rtp_instance *instance = (struct ast_rtp_instance *)data;
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+
+	rtp->dtlstimerid = -1;
+
+	if (rtp && rtp->ssl)
+	{
+		DTLSv1_handle_timeout(rtp->ssl);
+	}
+
+	if (rtp->rtcp && rtp->rtcp->ssl)
+	{
+		DTLSv1_handle_timeout(rtp->rtcp->ssl);
+	}
+
+	dtls_srtp_check_pending(instance, rtp);
+
+	ao2_ref(instance, -1);
+
+	return 0;
+}
+
+/*SRTP_DTLS */
 static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp)
 {
 	size_t pending = BIO_ctrl_pending(rtp->write_bio);
+	struct timeval dtls_timeout; /* timeout on DTLS  */
 
 	if (pending > 0) {
 		char outgoing[pending];
@@ -1329,6 +1697,30 @@
 		struct ast_sockaddr remote_address = { {0, } };
 		int ice;
 
+		/*SRTP_DTLS */
+		/* Stop existing DTLS timer if running */
+		if (rtp->dtlstimerid > -1)
+		{
+			AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1));
+			rtp->dtlstimerid = -1;
+		}
+
+		if (DTLSv1_get_timeout(rtp->ssl, &dtls_timeout))
+		{
+			int timeout = dtls_timeout.tv_sec * 1000 + dtls_timeout.tv_usec/1000;
+			ao2_ref(instance, +1);
+			if ((rtp->dtlstimerid = ast_sched_add(rtp->sched, timeout, dtls_srtp_handle_timeout, instance)) < 0)
+			{
+				ao2_ref(instance, -1);
+				ast_log(LOG_WARNING, "scheduling DTLS retransmission for RTP instance [%p] failed.\n", instance);
+			}
+		}
+
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> Going to send DTLS data: %zu bytes\n", pending);
+		}
+		/*SRTP_DTLS */
 		ast_rtp_instance_get_remote_address(instance, &remote_address);
 
 		/* If we do not yet know an address to send this to defer it until we do */
@@ -1337,9 +1729,51 @@
 		}
 
 		out = BIO_read(rtp->write_bio, outgoing, sizeof(outgoing));
+		/*SRTP_DTLS */
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> >> Read %zu bytes from the write_BIO...\n", pending);
+		}
+		/*SRTP_DTLS */
 
 		__rtp_sendto(instance, outgoing, out, 0, &remote_address, 0, &ice, 0);
+				/*SRTP_DTLS */
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> >> Called __rtp_sendto! (%zu)\n", pending);
+		}
+		/*SRTP_DTLS */
+	}
+
+	/* SRTP_DTLS: do the same with RTCP */
+	pending = BIO_ctrl_pending(rtp->rtcp->write_bio);
+	if (pending > 0) {
+		if(dtlsdebug)
+		ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> Going to send DTLS data: %zu bytes\n", pending);
+		char outgoing[pending];
+		size_t out;
+		struct ast_sockaddr remote_address = { {0, } };
+		int ice;
+		//~ ast_rtp_instance_get_remote_address(instance, &remote_address);
+		if (ast_sockaddr_isnull(&rtp->rtcp->them)) {
+			return;
+		}
+		ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
+		if (ast_sockaddr_isnull(&remote_address)) {
+			return;
+		}
+		out = BIO_read(rtp->rtcp->write_bio, outgoing, sizeof(outgoing));
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> >> Read %zu bytes from the write_BIO...\n", pending);
+		}
+		__rtp_sendto(instance, outgoing, out, 0, &remote_address, 1, &ice, 0);
+		if(dtlsdebug)
+		{
+			ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> >> Called __rtp_sendto! (%zu)\n", pending);
+		}
 	}
+	/* SRTP_DTLS: */
 }
 
 static int dtls_srtp_renegotiate(const void *data)
@@ -1349,6 +1783,9 @@
 
 	SSL_renegotiate(rtp->ssl);
 	SSL_do_handshake(rtp->ssl);
+		/* SRTP_DTLS: do the same with RTCP */
+	SSL_do_handshake(rtp->rtcp->ssl);
+	/*SRTP_DTLS */
 	dtls_srtp_check_pending(instance, rtp);
 
 	rtp->rekeyid = -1;
@@ -1357,6 +1794,7 @@
 	return 0;
 }
 
+
 static int dtls_srtp_setup(struct ast_rtp *rtp, struct ast_srtp *srtp, struct ast_rtp_instance *instance)
 {
 	unsigned char material[SRTP_MASTER_LEN * 2];
@@ -1378,25 +1816,40 @@
 			unsigned char fingerprint[EVP_MAX_MD_SIZE];
 			unsigned int size;
 
-			if (!X509_digest(certificate, EVP_sha1(), fingerprint, &size) ||
-			    !size ||
-			    memcmp(fingerprint, rtp->remote_fingerprint, size)) {
-				X509_free(certificate);
-				ast_log(LOG_WARNING, "Fingerprint provided by remote party does not match that of peer certificate on RTP instance '%p'\n",
+			if (rtp->remote_fingerprint_type == AST_RTP_DTLS_HASH_SHA1)
+			{
+				if (!X509_digest(certificate, EVP_sha1(), fingerprint, &size) ||
+			    	   !size ||
+			    	   memcmp(fingerprint, rtp->remote_fingerprint, size)) {
+					X509_free(certificate);
+					ast_log(LOG_WARNING, "Fingerprint provided by remote party does not match that of peer certificate on RTP instance '%p'\n",
 					instance);
-				return -1;
+					return -1;
+				}
+			}
+			else if (rtp->remote_fingerprint_type == AST_RTP_DTLS_HASH_SHA256 )
+			{
+				if (!X509_digest(certificate, EVP_sha256(), fingerprint, &size) ||
+			    	   !size ||
+			    	   memcmp(fingerprint, rtp->remote_fingerprint, size)) {
+					X509_free(certificate);
+					ast_log(LOG_WARNING, "Fingerprint provided by remote party does not match that of peer certificate on RTP instance '%p'\n",
+					instance);
+				   return -1;
+
+				}
 			}
 		}
 
 		X509_free(certificate);
 	}
 
-	/* Ensure that certificate verification was successful */
-	if (SSL_get_verify_result(rtp->ssl) != X509_V_OK) {
-		ast_log(LOG_WARNING, "Peer certificate on RTP instance '%p' failed verification test\n",
-			instance);
-		return -1;
-	}
+	/* SRTP_DTLS */
+	if(dtlsdebug)
+	{
+		ast_verbose(VERBOSE_PREFIX_3 "Verification was ok :-)\n");
+ 	}
+	/* SRTP_DTLS */
 
 	/* Produce key information and set up SRTP */
 	if (!SSL_export_keying_material(rtp->ssl, material, SRTP_MASTER_LEN * 2, "EXTRACTOR-dtls_srtp", 19, NULL, 0, 0)) {
@@ -1466,6 +1919,10 @@
 			goto error;
 		}
 	}
+	/* SRTP_DTLS: done with DTLS-SRTP */
+	ast_verbose(VERBOSE_PREFIX_3 "Looks like SRTP setup was completed...\n");
+	rtp->dtlsdone = 1;
+	/* SRTP_DTLS */
 
 	return 0;
 
@@ -1497,6 +1954,12 @@
 
 		/* If this is an SSL packet pass it to OpenSSL for processing */
 		if ((*in >= 20) && (*in <= 64)) {
+					/* SRTP_DTLS */
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP] Received a DTLS message\n");
+			}
+			/* SRTP_DTLS */
 			int res = 0;
 
 			/* If no SSL session actually exists terminate things */
@@ -1514,10 +1977,27 @@
 
 			dtls_srtp_check_pending(instance, rtp);
 
-			BIO_write(rtp->read_bio, buf, len);
+			/* SRTP_DTLS */
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> >> writing %d bytes on read_BIO (to have it read later)\n", len);
+			}
+			int written = BIO_write(rtp->read_bio, buf, len);
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> >> >> actually wrote %d bytes (%s)\n", written, BIO_should_retry(rtp->read_bio) ? "should retry" : "should NOT retry");
+			}
+			/* SRTP_DTLS */
 
 			len = SSL_read(rtp->ssl, buf, len);
 
+						/* SRTP_DTLS */
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP]  >> >> read %d bytes from SSL\n", len);
+			}
+			/* SRTP_DTLS */
+
 			dtls_srtp_check_pending(instance, rtp);
 
 			if (rtp->dtls_failure) {
@@ -1528,6 +2008,7 @@
 
 			if (SSL_is_init_finished(rtp->ssl)) {
 				/* Any further connections will be existing since this is now established */
+				ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> DTLS established, yay!\n");
 				rtp->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
 
 				/* Use the keying material to set up key/salt information */
@@ -1536,6 +2017,70 @@
 
 			return res;
 		}
+	} /* SRTP_DTLS -- since we don't do RTCP mux, we need DTLS for RTCP as well */
+	else
+	{
+		char *in = buf;
+
+		dtls_srtp_check_pending(instance, rtp);
+
+		/* If this is an SSL packet pass it to OpenSSL for processing */
+		if ((*in >= 20) && (*in <= 64)) {
+			if(dtlsdebug)
+			ast_verbose(VERBOSE_PREFIX_3 "[RTCP] Received a DTLS message\n");
+			int res = 0;
+
+			/* If no SSL session actually exists terminate things */
+			if (!rtp->rtcp->ssl) {
+				ast_log(LOG_ERROR, "Received SSL traffic on RTP instance '%p' without an SSL session\n",
+					instance);
+				return -1;
+			}
+
+			/* If we don't yet know if we are active or passive and we receive a packet... we are obviously passive */
+			if (rtp->rtcp->dtls_setup == AST_RTP_DTLS_SETUP_ACTPASS) {
+				rtp->rtcp->dtls_setup = AST_RTP_DTLS_SETUP_PASSIVE;
+				SSL_set_accept_state(rtp->rtcp->ssl);
+			}
+
+			dtls_srtp_check_pending(instance, rtp);
+
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> >> writing %d bytes on read_BIO (to have it read later)\n", len);
+			}
+			int written = BIO_write(rtp->rtcp->read_bio, buf, len);
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> >> >> actually wrote %d bytes (%s)\n", written, BIO_should_retry(rtp->rtcp->read_bio) ? "should retry" : "should NOT retry");
+			}
+
+			len = SSL_read(rtp->rtcp->ssl, buf, len);
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]  >> >> read %d bytes from SSL\n", len);
+			}
+
+			dtls_srtp_check_pending(instance, rtp);
+
+			if (rtp->rtcp->dtls_failure) {
+				ast_log(LOG_ERROR, "DTLS failure occurred on RTCP instance '%p', terminating\n",
+					instance);
+				return -1;
+			}
+
+			if (SSL_is_init_finished(rtp->rtcp->ssl)) {
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> DTLS established, yay!\n");
+				/* Any further connections will be existing since this is now established */
+				rtp->rtcp->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
+
+				/* Use the keying material to set up key/salt information */
+				//~ res = dtls_srtp_setup(rtp, srtp, instance);
+				rtp->rtcp->dtlsdone = 1;
+			}
+
+			return res;
+		}
 	}
 #endif
 
@@ -1613,11 +2158,44 @@
 
 static int rtcp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 {
+	/* SRTP_DTLS: don't send RTCP until ICE completed (FIXME useless? pjnath already does this?) */
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	if(rtp->rtcp->ssl && !rtp->rtcp->dtlsdone) {
+		const char *out = buf;
+		if ((*out >= 20) && (*out <= 64)) {
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP] Sending DTLS data (%zu)\n", size);
+			}
+		} else if(rtp->rtcp->connection == AST_RTP_DTLS_CONNECTION_NEW) {
+			if(dtlsdebug)
+			{
+				ast_verbose(VERBOSE_PREFIX_3 "[RTCP]   >> Still waiting for the DTLS handshake to complete, discarding packet (%zu)\n", size);
+			}
+			return 0;
+		}
+	}
+	/* SRTP_DTLS */
 	return __rtp_sendto(instance, buf, size, flags, sa, 1, ice, 1);
 }
 
 static int rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int *ice)
 {
+	/*SRTP_DTLS */
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	/* don't send RTP until DTLS handshake has been completed */
+	if(rtp->ssl && !rtp->dtlsdone) {
+		const char *out = buf;
+		if ((*out >= 20) && (*out <= 64)) {
+			if(dtlsdebug)
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP] Sending DTLS data (%zu)\n", size);
+		} else if(rtp->connection == AST_RTP_DTLS_CONNECTION_NEW) {
+			if(dtlsdebug)
+			ast_verbose(VERBOSE_PREFIX_3 "[RTP]   >> Still waiting for the DTLS handshake to complete, discarding packet (%zu)\n", size);
+			return 0;
+		}
+	}
+	/*SRTP_DTLS */
 	return __rtp_sendto(instance, buf, size, flags, sa, 0, ice, 1);
 }
 
@@ -1861,7 +2439,7 @@
 	passwd = pj_str(rtp->local_passwd);
 
 	/* Create an ICE session for ICE negotiation */
-	if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_UNKNOWN, 2,
+	if (pj_ice_sess_create(&stun_config, NULL, PJ_ICE_SESS_ROLE_CONTROLLING, 2,
 			&ast_rtp_ice_sess_cb, &ufrag, &passwd, &rtp->ice) == PJ_SUCCESS) {
 		/* Make this available for the callbacks */
 		rtp->ice->user_data = rtp;
@@ -1973,7 +2551,14 @@
 
 #ifdef HAVE_OPENSSL_SRTP
 	rtp->rekeyid = -1;
+	rtp->dtlstimerid = -1;
+	rtp->local_fingerprint_type = AST_RTP_DTLS_HASH_NONE;
+	rtp->remote_fingerprint_type = AST_RTP_DTLS_HASH_NONE;
+
 #endif
+	/* SRTP_DTLS: make rtp aware of instance as well... */
+	rtp->instance = instance;
+	/*SRTP_DTLS */
 
 	return 0;
 }
@@ -4295,6 +4880,7 @@
 
 #ifdef HAVE_OPENSSL_SRTP
 	AST_SCHED_DEL_UNREF(rtp->sched, rtp->rekeyid, ao2_ref(instance, -1));
+	AST_SCHED_DEL_UNREF(rtp->sched, rtp->dtlstimerid, ao2_ref(instance, -1));
 #endif
 
 	if (rtp->rtcp && rtp->rtcp->schedid > 0) {
@@ -4383,14 +4969,19 @@
 static int ast_rtp_activate(struct ast_rtp_instance *instance)
 {
 	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
-
 	if (!rtp->ssl) {
 		return 0;
 	}
 
-	SSL_do_handshake(rtp->ssl);
-
-	dtls_srtp_check_pending(instance, rtp);
+	/* SRTP_DTLS: only do the DTLS handshake right now if there's no ICE or if it has completed */
+	if(!rtp->ice || rtp->icedone) {
+		ast_verbose(VERBOSE_PREFIX_3 "  >> Doing DTLS handshake as well...\n");
+		SSL_do_handshake(rtp->ssl);
+		/* Meetecho: do the same with RTCP */
+		SSL_do_handshake(rtp->rtcp->ssl);
+		ast_verbose(VERBOSE_PREFIX_3 "  >> [activate] check pending...\n");
+		dtls_srtp_check_pending(instance, rtp);
+	}
 
 	return 0;
 }
@@ -4522,11 +5113,49 @@
 	ast_cli(a->fd, "RTCP Stats %s\n", rtcpstats ? "Enabled" : "Disabled");
 	return CLI_SUCCESS;
 }
+/* SRTP_DTLS: add DTLS debugging */
+static char *handle_cli_dtls_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "dtls set debug";
+		e->usage =
+			"Usage: dtls set debug {status|none|normal|huge}\n"
+			"       Enable/Disable DTLS debugging: normal only debugs setup and errors, huge debugs every single packet\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc != 4)
+		return CLI_SHOWUSAGE;
+
+	if (!strncasecmp(a->argv[a->argc-1], "status", 6)) {
+		ast_cli(a->fd, "DTLS debugging %s\n", dtlsdebug > 1 ? "huge" : dtlsdebug > 0 ? "normal" : "none");
+		return CLI_SUCCESS;
+	}
+	if (!strncasecmp(a->argv[a->argc-1], "huge", 4))
+		dtlsdebug = 2;
+	else if (!strncasecmp(a->argv[a->argc-1], "normal", 6))
+		dtlsdebug = 1;
+	else if (!strncasecmp(a->argv[a->argc-1], "none", 4))
+		dtlsdebug = 0;
+	else
+		return CLI_SHOWUSAGE;
+
+	ast_cli(a->fd, "DTLS debugging %s\n", dtlsdebug > 1 ? "huge" : dtlsdebug > 0 ? "normal" : "none");
+	return CLI_SUCCESS;
+}
+/*SRTP_DTLS */
+
 
 static struct ast_cli_entry cli_rtp[] = {
 	AST_CLI_DEFINE(handle_cli_rtp_set_debug,  "Enable/Disable RTP debugging"),
 	AST_CLI_DEFINE(handle_cli_rtcp_set_debug, "Enable/Disable RTCP debugging"),
 	AST_CLI_DEFINE(handle_cli_rtcp_set_stats, "Enable/Disable RTCP stats"),
+	/* SRTP_DTLS: add DTLS debugging */
+	AST_CLI_DEFINE(handle_cli_dtls_set_debug, "Enable/Disable DTLS debugging"),
+	/*SRTP_DTLS */
 };
 
 static int rtp_reload(int reload)
