diff --git a/configs/samples/rtp.conf.sample b/configs/samples/rtp.conf.sample
index a2664e41a1160c93bb4d16169533ec8748535636..a94707e59698db5dc3704ea75a81e807d49ffd01 100644
--- a/configs/samples/rtp.conf.sample
+++ b/configs/samples/rtp.conf.sample
@@ -102,6 +102,10 @@ rtpend=20000
 ;
 ; ice_blacklist =
 ;
+; The MTU to use for DTLS packet fragmentation. This option is set to 1200
+; by default. The minimum MTU is 256.
+; dtls_mtu = 1200
+;
 [ice_host_candidates]
 ;
 ; When Asterisk is behind a static one-to-one NAT and ICE is in use, ICE will
diff --git a/configure b/configure
index 2a704b544e78f517b954327ba7373f76caf08275..92143a47b510f5073499bcbb11bfe43bdbd2da94 100755
--- a/configure
+++ b/configure
@@ -1152,6 +1152,10 @@ PBX_DAHDI
 DAHDI_DIR
 DAHDI_INCLUDE
 DAHDI_LIB
+PBX_OPENSSL_BIO_METHOD
+OPENSSL_BIO_METHOD_DIR
+OPENSSL_BIO_METHOD_INCLUDE
+OPENSSL_BIO_METHOD_LIB
 PBX_OPENSSL_SRTP
 OPENSSL_SRTP_DIR
 OPENSSL_SRTP_INCLUDE
@@ -9827,6 +9831,18 @@ PBX_OPENSSL_SRTP=0
 
 
 
+OPENSSL_BIO_METHOD_DESCRIP="OpenSSL BIO Method Support"
+OPENSSL_BIO_METHOD_OPTION=crypto
+OPENSSL_BIO_METHOD_DIR=${CRYPTO_DIR}
+
+PBX_OPENSSL_BIO_METHOD=0
+
+
+
+
+
+
+
     DAHDI_DESCRIP="DAHDI"
     DAHDI_OPTION="dahdi"
     PBX_DAHDI=0
@@ -31149,6 +31165,102 @@ _ACEOF
 fi
 
 
+
+if test "x${PBX_OPENSSL_BIO_METHOD}" != "x1" -a "${USE_OPENSSL_BIO_METHOD}" != "no"; then
+   pbxlibdir=""
+   # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it.
+   if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then
+      if test -d ${OPENSSL_BIO_METHOD_DIR}/lib; then
+         pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}/lib"
+      else
+         pbxlibdir="-L${OPENSSL_BIO_METHOD_DIR}"
+      fi
+   fi
+
+      ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${CFLAGS} "
+      { $as_echo "$as_me:${as_lineno-$LINENO}: checking for BIO_meth_new in -lssl" >&5
+$as_echo_n "checking for BIO_meth_new in -lssl... " >&6; }
+if ${ac_cv_lib_ssl_BIO_meth_new+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lssl ${pbxlibdir} -lcrypto $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char BIO_meth_new ();
+int
+main ()
+{
+return BIO_meth_new ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  ac_cv_lib_ssl_BIO_meth_new=yes
+else
+  ac_cv_lib_ssl_BIO_meth_new=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ssl_BIO_meth_new" >&5
+$as_echo "$ac_cv_lib_ssl_BIO_meth_new" >&6; }
+if test "x$ac_cv_lib_ssl_BIO_meth_new" = xyes; then :
+  AST_OPENSSL_BIO_METHOD_FOUND=yes
+else
+  AST_OPENSSL_BIO_METHOD_FOUND=no
+fi
+
+      CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+
+
+   # now check for the header.
+   if test "${AST_OPENSSL_BIO_METHOD_FOUND}" = "yes"; then
+      OPENSSL_BIO_METHOD_LIB="${pbxlibdir} -lssl -lcrypto"
+      # if --with-OPENSSL_BIO_METHOD=DIR has been specified, use it.
+      if test "x${OPENSSL_BIO_METHOD_DIR}" != "x"; then
+         OPENSSL_BIO_METHOD_INCLUDE="-I${OPENSSL_BIO_METHOD_DIR}/include"
+      fi
+      OPENSSL_BIO_METHOD_INCLUDE="${OPENSSL_BIO_METHOD_INCLUDE} "
+
+         # check for the header
+         ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${OPENSSL_BIO_METHOD_INCLUDE}"
+         ac_fn_c_check_header_mongrel "$LINENO" "openssl/ssl.h" "ac_cv_header_openssl_ssl_h" "$ac_includes_default"
+if test "x$ac_cv_header_openssl_ssl_h" = xyes; then :
+  OPENSSL_BIO_METHOD_HEADER_FOUND=1
+else
+  OPENSSL_BIO_METHOD_HEADER_FOUND=0
+fi
+
+
+         CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+
+      if test "x${OPENSSL_BIO_METHOD_HEADER_FOUND}" = "x0" ; then
+         OPENSSL_BIO_METHOD_LIB=""
+         OPENSSL_BIO_METHOD_INCLUDE=""
+      else
+
+         PBX_OPENSSL_BIO_METHOD=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_OPENSSL_BIO_METHOD 1
+_ACEOF
+
+      fi
+   fi
+fi
+
+
 fi
 
 if test "$PBX_OPENSSL" = "1";
diff --git a/configure.ac b/configure.ac
index e65f1598030371f90c3fc7fb8f6d15a5331a4b44..b2fcb853084a67597117dc32ff73b6195d47fb00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -480,6 +480,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([COROSYNC_CFG_STATE_TRACK], [A callback only in coros
 AST_EXT_LIB_SETUP([CRYPT], [password and data encryption], [crypt])
 AST_EXT_LIB_SETUP([CRYPTO], [OpenSSL Cryptography], [crypto])
 AST_EXT_LIB_SETUP_OPTIONAL([OPENSSL_SRTP], [OpenSSL SRTP Extension Support], [CRYPTO], [crypto])
+AST_EXT_LIB_SETUP_OPTIONAL([OPENSSL_BIO_METHOD], [OpenSSL BIO Method Support], [CRYPTO], [crypto])
 AST_EXT_LIB_SETUP([DAHDI], [DAHDI], [dahdi])
 AST_EXT_LIB_SETUP([FFMPEG], [Ffmpeg and avcodec], [avcodec])
 AST_EXT_LIB_SETUP([GSM], [External GSM], [gsm], [, use 'internal' GSM otherwise])
@@ -2588,6 +2589,7 @@ AST_EXT_LIB_CHECK([CRYPTO], [crypto], [AES_encrypt], [openssl/aes.h])
 if test "$PBX_CRYPTO" = "1";
 then
 	AST_EXT_LIB_CHECK([OPENSSL], [ssl], [SSL_connect], [openssl/ssl.h], [-lcrypto])
+	AST_EXT_LIB_CHECK([OPENSSL_BIO_METHOD], [ssl], [BIO_meth_new], [openssl/ssl.h], [-lcrypto])
 fi
 
 if test "$PBX_OPENSSL" = "1";
diff --git a/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt b/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dfc5984d6fcef12b64d3ead6a89ae299c8a1caba
--- /dev/null
+++ b/doc/CHANGES-staging/res_rtp_asterisk_dtls_fragmentation.txt
@@ -0,0 +1,5 @@
+Subject: res_rtp_asterisk
+
+DTLS packets will now be fragmented according to the MTU as set in rtp.conf. This
+allows larger certificates to be used for the DTLS negotiation. By default this value
+is 1200.
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 71df798c1208a7e1b445fd4d8c42cb7d8e5768d8..8f7aaa13602024902ff6137cf8380bf2df27b7a1 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -582,6 +582,9 @@
 /* Define to 1 if you have the OpenSSL Secure Sockets Layer library. */
 #undef HAVE_OPENSSL
 
+/* Define to 1 if CRYPTO has the OpenSSL BIO Method Support feature. */
+#undef HAVE_OPENSSL_BIO_METHOD
+
 /* Define to 1 if CRYPTO has the OpenSSL SRTP Extension Support feature. */
 #undef HAVE_OPENSSL_SRTP
 
diff --git a/menuselect/configure b/menuselect/configure
index 8efb6372e82920e98f39891d12b5d635668c224a..fd7d24b87be6a9675003ce103857f453872c588b 100755
--- a/menuselect/configure
+++ b/menuselect/configure
@@ -692,6 +692,7 @@ infodir
 docdir
 oldincludedir
 includedir
+runstatedir
 localstatedir
 sharedstatedir
 sysconfdir
@@ -772,6 +773,7 @@ datadir='${datarootdir}'
 sysconfdir='${prefix}/etc'
 sharedstatedir='${prefix}/com'
 localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
 includedir='${prefix}/include'
 oldincludedir='/usr/include'
 docdir='${datarootdir}/doc/${PACKAGE}'
@@ -1024,6 +1026,15 @@ do
   | -silent | --silent | --silen | --sile | --sil)
     silent=yes ;;
 
+  -runstatedir | --runstatedir | --runstatedi | --runstated \
+  | --runstate | --runstat | --runsta | --runst | --runs \
+  | --run | --ru | --r)
+    ac_prev=runstatedir ;;
+  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+  | --run=* | --ru=* | --r=*)
+    runstatedir=$ac_optarg ;;
+
   -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
     ac_prev=sbindir ;;
   -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
@@ -1161,7 +1172,7 @@ fi
 for ac_var in	exec_prefix prefix bindir sbindir libexecdir datarootdir \
 		datadir sysconfdir sharedstatedir localstatedir includedir \
 		oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
-		libdir localedir mandir
+		libdir localedir mandir runstatedir
 do
   eval ac_val=\$$ac_var
   # Remove trailing slashes.
@@ -1314,6 +1325,7 @@ Fine tuning of the installation directories:
   --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]
   --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]
   --localstatedir=DIR     modifiable single-machine data [PREFIX/var]
+  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]
   --libdir=DIR            object code libraries [EPREFIX/lib]
   --includedir=DIR        C header files [PREFIX/include]
   --oldincludedir=DIR     C header files for non-gcc [/usr/include]
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index 335a329c69561703fb59bdc8909de55c0ba7b6b0..b55a7d511e51a4a394e92bc9d31f7dd3c3d103a1 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -174,6 +174,7 @@ enum strict_rtp_mode {
 
 #define DEFAULT_STRICT_RTP STRICT_RTP_YES	/*!< Enabled by default */
 #define DEFAULT_ICESUPPORT 1
+#define DEFAULT_DTLS_MTU 1200
 
 extern struct ast_srtp_res *res_srtp;
 extern struct ast_srtp_policy_res *res_srtp_policy;
@@ -203,6 +204,9 @@ static pj_str_t turnaddr;
 static int turnport = DEFAULT_TURN_PORT;
 static pj_str_t turnusername;
 static pj_str_t turnpassword;
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+static int dtls_mtu = DEFAULT_DTLS_MTU;
+#endif
 
 static struct ast_ha *ice_blacklist = NULL;    /*!< Blacklisted ICE networks */
 static ast_rwlock_t ice_blacklist_lock = AST_RWLOCK_INIT_VALUE;
@@ -593,13 +597,101 @@ static int ast_rtp_bundle(struct ast_rtp_instance *child, struct ast_rtp_instanc
 
 #if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
 static int ast_rtp_activate(struct ast_rtp_instance *instance);
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
 static void dtls_srtp_start_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
 static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp);
+static int dtls_bio_write(BIO *bio, const char *buf, int len);
+static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2);
+static int dtls_bio_new(BIO *bio);
+static int dtls_bio_free(BIO *bio);
+
+#ifndef HAVE_OPENSSL_BIO_METHOD
+static BIO_METHOD dtls_bio_methods = {
+	.type = BIO_TYPE_BIO,
+	.name = "rtp write",
+	.bwrite = dtls_bio_write,
+	.ctrl = dtls_bio_ctrl,
+	.create = dtls_bio_new,
+	.destroy = dtls_bio_free,
+};
+#else
+static BIO_METHOD *dtls_bio_methods;
+#endif
 #endif
 
 static int __rtp_sendto(struct ast_rtp_instance *instance, void *buf, size_t size, int flags, struct ast_sockaddr *sa, int rtcp, int *via_ice, int use_srtp);
 
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+static int dtls_bio_new(BIO *bio)
+{
+#ifdef HAVE_OPENSSL_BIO_METHOD
+	BIO_set_init(bio, 1);
+	BIO_set_data(bio, NULL);
+	BIO_set_shutdown(bio, 0);
+#else
+	bio->init = 1;
+	bio->ptr = NULL;
+	bio->flags = 0;
+#endif
+	return 1;
+}
+
+static int dtls_bio_free(BIO *bio)
+{
+	/* The pointer on the BIO is that of the RTP instance. It is not reference counted as the BIO
+	 * lifetime is tied to the instance, and actions on the BIO are taken by the thread handling
+	 * the RTP instance - not another thread.
+	 */
+#ifdef HAVE_OPENSSL_BIO_METHOD
+	BIO_set_data(bio, NULL);
+#else
+	bio->ptr = NULL;
+#endif
+	return 1;
+}
+
+static int dtls_bio_write(BIO *bio, const char *buf, int len)
+{
+#ifdef HAVE_OPENSSL_BIO_METHOD
+	struct ast_rtp_instance *instance = BIO_get_data(bio);
+#else
+	struct ast_rtp_instance *instance = bio->ptr;
+#endif
+	struct ast_rtp *rtp = ast_rtp_instance_get_data(instance);
+	int rtcp = 0;
+	struct ast_sockaddr remote_address = { {0, } };
+	int ice;
+
+	if (rtp->rtcp && rtp->rtcp->dtls.write_bio == bio) {
+		rtcp = 1;
+		ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
+	} else {
+		ast_rtp_instance_get_remote_address(instance, &remote_address);
+	}
+
+	if (ast_sockaddr_isnull(&remote_address)) {
+		return 0;
+	}
+
+	return __rtp_sendto(instance, (char *)buf, len, 0, &remote_address, rtcp, &ice, 0);
+}
+
+static long dtls_bio_ctrl(BIO *bio, int cmd, long arg1, void *arg2)
+{
+	switch (cmd) {
+	case BIO_CTRL_FLUSH:
+		return 1;
+	case BIO_CTRL_DGRAM_QUERY_MTU:
+		return dtls_mtu;
+	case BIO_CTRL_WPENDING:
+	case BIO_CTRL_PENDING:
+		return 0L;
+	default:
+		return 0;
+	}
+}
+
+#endif
+
 #ifdef HAVE_PJPROJECT
 /*! \brief Helper function which clears the ICE host candidate mapping */
 static void host_candidate_overrides_clear(void)
@@ -1630,7 +1722,7 @@ static int dtls_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
 }
 
 static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx,
-	enum ast_rtp_dtls_setup setup)
+	enum ast_rtp_dtls_setup setup, struct ast_rtp_instance *instance)
 {
 	dtls->dtls_setup = setup;
 
@@ -1645,12 +1737,20 @@ static int dtls_details_initialize(struct dtls_details *dtls, SSL_CTX *ssl_ctx,
 	}
 	BIO_set_mem_eof_return(dtls->read_bio, -1);
 
-	if (!(dtls->write_bio = BIO_new(BIO_s_mem()))) {
+#ifdef HAVE_OPENSSL_BIO_METHOD
+	if (!(dtls->write_bio = BIO_new(dtls_bio_methods))) {
 		ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n");
 		goto error;
 	}
-	BIO_set_mem_eof_return(dtls->write_bio, -1);
 
+	BIO_set_data(dtls->write_bio, instance);
+#else
+	if (!(dtls->write_bio = BIO_new(&dtls_bio_methods))) {
+		ast_log(LOG_ERROR, "Failed to allocate memory for outbound SSL traffic\n");
+		goto error;
+	}
+	dtls->write_bio->ptr = instance;
+#endif
 	SSL_set_bio(dtls->ssl, dtls->read_bio, dtls->write_bio);
 
 	if (dtls->dtls_setup == AST_RTP_DTLS_SETUP_PASSIVE) {
@@ -1688,7 +1788,7 @@ static int dtls_setup_rtcp(struct ast_rtp_instance *instance)
 		return 0;
 	}
 
-	return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup);
+	return dtls_details_initialize(&rtp->rtcp->dtls, rtp->ssl_ctx, rtp->dtls.dtls_setup, instance);
 }
 
 static const SSL_METHOD *get_dtls_method(void)
@@ -2081,7 +2181,7 @@ static int ast_rtp_dtls_set_configuration(struct ast_rtp_instance *instance, con
 	rtp->rekey = dtls_cfg->rekey;
 	rtp->suite = dtls_cfg->suite;
 
-	res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup);
+	res = dtls_details_initialize(&rtp->dtls, rtp->ssl_ctx, dtls_cfg->default_setup, instance);
 	if (!res) {
 		dtls_setup_rtcp(instance);
 	}
@@ -2337,12 +2437,6 @@ static void dtls_perform_handshake(struct ast_rtp_instance *instance, struct dtl
 	 * timer before we have a chance to even start it.
 	 */
 	dtls_srtp_start_timeout_timer(instance, rtp, rtcp);
-
-	/*
-	 * We must call dtls_srtp_check_pending() after starting the timer.
-	 * Otherwise we won't prevent the race condition.
-	 */
-	dtls_srtp_check_pending(instance, rtp, rtcp);
 }
 #endif
 
@@ -2533,7 +2627,6 @@ static int dtls_srtp_handle_timeout(struct ast_rtp_instance *instance, int rtcp)
 	struct timeval dtls_timeout;
 
 	DTLSv1_handle_timeout(dtls->ssl);
-	dtls_srtp_check_pending(instance, rtp, rtcp);
 
 	/* If a timeout can't be retrieved then this recurring scheduled item must stop */
 	if (!DTLSv1_get_timeout(dtls->ssl, &dtls_timeout)) {
@@ -2604,40 +2697,6 @@ static void dtls_srtp_stop_timeout_timer(struct ast_rtp_instance *instance, stru
 	AST_SCHED_DEL_UNREF(rtp->sched, dtls->timeout_timer, ao2_ref(instance, -1));
 }
 
-/*! \pre instance is locked */
-static void dtls_srtp_check_pending(struct ast_rtp_instance *instance, struct ast_rtp *rtp, int rtcp)
-{
-	struct dtls_details *dtls = !rtcp ? &rtp->dtls : &rtp->rtcp->dtls;
-	size_t pending;
-
-	if (!dtls->ssl || !dtls->write_bio) {
-		return;
-	}
-
-	pending = BIO_ctrl_pending(dtls->write_bio);
-
-	if (pending > 0) {
-		char outgoing[pending];
-		size_t out;
-		struct ast_sockaddr remote_address = { {0, } };
-		int ice;
-
-		if (!rtcp) {
-			ast_rtp_instance_get_remote_address(instance, &remote_address);
-		} else {
-			ast_sockaddr_copy(&remote_address, &rtp->rtcp->them);
-		}
-
-		/* If we do not yet know an address to send this to defer it until we do */
-		if (ast_sockaddr_isnull(&remote_address)) {
-			return;
-		}
-
-		out = BIO_read(dtls->write_bio, outgoing, sizeof(outgoing));
-		__rtp_sendto(instance, outgoing, out, 0, &remote_address, rtcp, &ice, 0);
-	}
-}
-
 /* Scheduler callback */
 static int dtls_srtp_renegotiate(const void *data)
 {
@@ -2648,12 +2707,10 @@ static int dtls_srtp_renegotiate(const void *data)
 
 	SSL_renegotiate(rtp->dtls.ssl);
 	SSL_do_handshake(rtp->dtls.ssl);
-	dtls_srtp_check_pending(instance, rtp, 0);
 
 	if (rtp->rtcp && rtp->rtcp->dtls.ssl && rtp->rtcp->dtls.ssl != rtp->dtls.ssl) {
 		SSL_renegotiate(rtp->rtcp->dtls.ssl);
 		SSL_do_handshake(rtp->rtcp->dtls.ssl);
-		dtls_srtp_check_pending(instance, rtp, 1);
 	}
 
 	rtp->rekeyid = -1;
@@ -2904,8 +2961,6 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
 			SSL_set_accept_state(dtls->ssl);
 		}
 
-		dtls_srtp_check_pending(instance, rtp, rtcp);
-
 		BIO_write(dtls->read_bio, buf, len);
 
 		len = SSL_read(dtls->ssl, buf, len);
@@ -2917,8 +2972,6 @@ static int __rtp_recvfrom(struct ast_rtp_instance *instance, void *buf, size_t s
 			return -1;
 		}
 
-		dtls_srtp_check_pending(instance, rtp, rtcp);
-
 		if (SSL_is_init_finished(dtls->ssl)) {
 			/* Any further connections will be existing since this is now established */
 			dtls->connection = AST_RTP_DTLS_CONNECTION_EXISTING;
@@ -8559,6 +8612,10 @@ static int rtp_reload(int reload)
 	blacklist_clear(&stun_blacklist_lock, &stun_blacklist);
 #endif
 
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+	dtls_mtu = DEFAULT_DTLS_MTU;
+#endif
+
 	if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
 		rtpstart = atoi(s);
 		if (rtpstart < MINIMUM_RTP_PORT)
@@ -8692,6 +8749,15 @@ static int rtp_reload(int reload)
 	/* Read STUN blacklist configuration lines */
 	blacklist_config_load(cfg, "stun_blacklist", &stun_blacklist_lock, &stun_blacklist);
 #endif
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP)
+	if ((s = ast_variable_retrieve(cfg, "general", "dtls_mtu"))) {
+		if ((sscanf(s, "%d", &dtls_mtu) != 1) || dtls_mtu < 256) {
+			ast_log(LOG_WARNING, "Value for 'dtls_mtu' could not be read, using default of '%d' instead\n",
+				DEFAULT_DTLS_MTU);
+			dtls_mtu = DEFAULT_DTLS_MTU;
+		}
+	}
+#endif
 
 	ast_config_destroy(cfg);
 
@@ -8769,7 +8835,24 @@ static int load_module(void)
 
 #endif
 
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+	dtls_bio_methods = BIO_meth_new(BIO_TYPE_BIO, "rtp write");
+	if (!dtls_bio_methods) {
+#ifdef HAVE_PJPROJECT
+		rtp_terminate_pjproject();
+#endif
+		return AST_MODULE_LOAD_DECLINE;
+	}
+	BIO_meth_set_write(dtls_bio_methods, dtls_bio_write);
+	BIO_meth_set_ctrl(dtls_bio_methods, dtls_bio_ctrl);
+	BIO_meth_set_create(dtls_bio_methods, dtls_bio_new);
+	BIO_meth_set_destroy(dtls_bio_methods, dtls_bio_free);
+#endif
+
 	if (ast_rtp_engine_register(&asterisk_rtp_engine)) {
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+		BIO_meth_free(dtls_bio_methods);
+#endif
 #ifdef HAVE_PJPROJECT
 		rtp_terminate_pjproject();
 #endif
@@ -8777,6 +8860,9 @@ static int load_module(void)
 	}
 
 	if (ast_cli_register_multiple(cli_rtp, ARRAY_LEN(cli_rtp))) {
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+		BIO_meth_free(dtls_bio_methods);
+#endif
 #ifdef HAVE_PJPROJECT
 		ast_rtp_engine_unregister(&asterisk_rtp_engine);
 		rtp_terminate_pjproject();
@@ -8794,6 +8880,12 @@ static int unload_module(void)
 	ast_rtp_engine_unregister(&asterisk_rtp_engine);
 	ast_cli_unregister_multiple(cli_rtp, ARRAY_LEN(cli_rtp));
 
+#if defined(HAVE_OPENSSL) && (OPENSSL_VERSION_NUMBER >= 0x10001000L) && !defined(OPENSSL_NO_SRTP) && defined(HAVE_OPENSSL_BIO_METHOD)
+	if (dtls_bio_methods) {
+		BIO_meth_free(dtls_bio_methods);
+	}
+#endif
+
 #ifdef HAVE_PJPROJECT
 	host_candidate_overrides_clear();
 	pj_thread_register_check();