[Asterisk-code-review] pjsip: Add TLS transport reload support for certificate and key. (asterisk[master])

Joshua Colp asteriskteam at digium.com
Wed Sep 7 07:55:38 CDT 2022


Joshua Colp has uploaded this change for review. ( https://gerrit.asterisk.org/c/asterisk/+/19093 )


Change subject: pjsip: Add TLS transport reload support for certificate and key.
......................................................................

pjsip: Add TLS transport reload support for certificate and key.

This change adds support using the pjsip_tls_transport_restart
function for reloading the TLS certificate and key, if the filenames
remain unchanged. This is useful for Let's Encrypt and other
situations. Note that no restart of the transport will occur if
the certificate and key remain unchanged.

ASTERISK-30186

Change-Id: I9bc95a6bf791830a9491ad9fa43c17d4010028d0
---
M configs/samples/pjsip.conf.sample
M configure
M configure.ac
A doc/CHANGES-staging/res_pjsip_tls_cert_key_reload.txt
M include/asterisk/autoconfig.h.in
M include/asterisk/res_pjsip.h
M menuselect/autoconfig.h.in
M menuselect/configure
M res/res_pjsip/config_transport.c
M res/res_pjsip/pjsip_config.xml
M third-party/pjproject/configure.m4
11 files changed, 413 insertions(+), 134 deletions(-)



  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/93/19093/1

diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample
index a74b50f..bf9f78c 100644
--- a/configs/samples/pjsip.conf.sample
+++ b/configs/samples/pjsip.conf.sample
@@ -1054,11 +1054,16 @@
                 ; and/or "asterisk_ecc.pem" are loaded (certificate, inter-
                 ; mediates, private key), to support multiple algorithms for
                 ; server authentication (RSA, DSA, ECDSA). If the chains are
-                ; different, at least OpenSSL 1.0.2 is required.
+                ; different, at least OpenSSL 1.0.2 is required. This option
+                ; can be reloaded resulting in an updated certificate if the
+                ; filename remains unchanged.
                 ; (default: "")
 ;cipher=        ; Preferred cryptography cipher names TLS ONLY (default: "")
 ;method=        ; Method of SSL transport TLS ONLY (default: "")
-;priv_key_file= ; Private key file TLS ONLY (default: "")
+;priv_key_file= ; Private key file TLS ONLY. This option can be reloaded
+                ; resulting in an updated private key if the filename remains
+                ; unchanged.
+                ; (default: "")
 ;verify_client= ; Require verification of client certificate TLS ONLY (default:
                 ; "")
 ;verify_server= ; Require verification of server certificate TLS ONLY (default:
diff --git a/configure b/configure
index 6c913f0..573f4ef 100755
--- a/configure
+++ b/configure
@@ -940,6 +940,10 @@
 POPT_DIR
 POPT_INCLUDE
 POPT_LIB
+PBX_PJSIP_TLS_TRANSPORT_RESTART
+PJSIP_TLS_TRANSPORT_RESTART_DIR
+PJSIP_TLS_TRANSPORT_RESTART_INCLUDE
+PJSIP_TLS_TRANSPORT_RESTART_LIB
 PBX_PJSIP_OAUTH_AUTHENTICATION
 PJSIP_OAUTH_AUTHENTICATION_DIR
 PJSIP_OAUTH_AUTHENTICATION_INCLUDE
@@ -10213,8 +10217,8 @@
       if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl >= 1.1.0" >&5
-printf %s "checking for openssl >= 1.1.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+printf %s "checking for OPENSSL... " >&6; }
 
 if test -n "$OPENSSL_CFLAGS"; then
     pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
@@ -10254,7 +10258,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -10275,7 +10279,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_OPENSSL=0
@@ -10304,8 +10308,8 @@
       if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl11" >&5
-printf %s "checking for openssl11... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+printf %s "checking for OPENSSL... " >&6; }
 
 if test -n "$OPENSSL_CFLAGS"; then
     pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
@@ -10345,7 +10349,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -10366,7 +10370,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_OPENSSL=0
@@ -10400,8 +10404,8 @@
       if test "x${PBX_OPENSSL}" != "x1" -a "${USE_OPENSSL}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for openssl" >&5
-printf %s "checking for openssl... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for OPENSSL" >&5
+printf %s "checking for OPENSSL... " >&6; }
 
 if test -n "$OPENSSL_CFLAGS"; then
     pkg_cv_OPENSSL_CFLAGS="$OPENSSL_CFLAGS"
@@ -10441,7 +10445,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -10462,7 +10466,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_OPENSSL=0
@@ -11087,6 +11091,9 @@
 printf "%s\n" "#define HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK 1" >>confdefs.h
 
 
+printf "%s\n" "#define HAVE_PJSIP_TLS_TRANSPORT_RESTART 1" >>confdefs.h
+
+
 
 
 
@@ -13162,6 +13169,18 @@
 
 
 
+
+PJSIP_TLS_TRANSPORT_RESTART_DESCRIP="PJSIP TLS Transport Restart Support"
+PJSIP_TLS_TRANSPORT_RESTART_OPTION=pjsip
+PJSIP_TLS_TRANSPORT_RESTART_DIR=${PJPROJECT_DIR}
+
+PBX_PJSIP_TLS_TRANSPORT_RESTART=0
+
+
+
+
+
+
 fi
 
 
@@ -14835,8 +14854,8 @@
       if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libedit" >&5
-printf %s "checking for libedit... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBEDIT" >&5
+printf %s "checking for LIBEDIT... " >&6; }
 
 if test -n "$LIBEDIT_CFLAGS"; then
     pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS"
@@ -14876,7 +14895,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -14897,7 +14916,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_LIBEDIT=0
@@ -15296,8 +15315,8 @@
       if test "x${PBX_JANSSON}" != "x1" -a "${USE_JANSSON}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for jansson >= 2.11" >&5
-printf %s "checking for jansson >= 2.11... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for JANSSON" >&5
+printf %s "checking for JANSSON... " >&6; }
 
 if test -n "$JANSSON_CFLAGS"; then
     pkg_cv_JANSSON_CFLAGS="$JANSSON_CFLAGS"
@@ -15337,7 +15356,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -15358,7 +15377,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_JANSSON=0
@@ -15614,8 +15633,8 @@
       if test "x${PBX_LIBXML2}" != "x1" -a "${USE_LIBXML2}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libxml-2.0" >&5
-printf %s "checking for libxml-2.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBXML2" >&5
+printf %s "checking for LIBXML2... " >&6; }
 
 if test -n "$LIBXML2_CFLAGS"; then
     pkg_cv_LIBXML2_CFLAGS="$LIBXML2_CFLAGS"
@@ -15655,7 +15674,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -15676,7 +15695,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_LIBXML2=0
@@ -22889,8 +22908,8 @@
       if test "x${PBX_ILBC}" != "x1" -a "${USE_ILBC}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libilbc" >&5
-printf %s "checking for libilbc... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for ILBC" >&5
+printf %s "checking for ILBC... " >&6; }
 
 if test -n "$ILBC_CFLAGS"; then
     pkg_cv_ILBC_CFLAGS="$ILBC_CFLAGS"
@@ -22930,7 +22949,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -22951,7 +22970,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_ILBC=0
@@ -25148,8 +25167,8 @@
       if test "x${PBX_NETSNMP}" != "x1" -a "${USE_NETSNMP}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for netsnmp-agent" >&5
-printf %s "checking for netsnmp-agent... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for NETSNMP" >&5
+printf %s "checking for NETSNMP... " >&6; }
 
 if test -n "$NETSNMP_CFLAGS"; then
     pkg_cv_NETSNMP_CFLAGS="$NETSNMP_CFLAGS"
@@ -25189,7 +25208,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -25210,7 +25229,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_NETSNMP=0
@@ -26575,8 +26594,8 @@
       if test "x${PBX_PJPROJECT}" != "x1" -a "${USE_PJPROJECT}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libpjproject" >&5
-printf %s "checking for libpjproject... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PJPROJECT" >&5
+printf %s "checking for PJPROJECT... " >&6; }
 
 if test -n "$PJPROJECT_CFLAGS"; then
     pkg_cv_PJPROJECT_CFLAGS="$PJPROJECT_CFLAGS"
@@ -26616,7 +26635,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -26637,7 +26656,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_PJPROJECT=0
@@ -27824,6 +27843,102 @@
 fi
 
 
+
+if test "x${PBX_PJSIP_TLS_TRANSPORT_RESTART}" != "x1" -a "${USE_PJSIP_TLS_TRANSPORT_RESTART}" != "no"; then
+   pbxlibdir=""
+   # if --with-PJSIP_TLS_TRANSPORT_RESTART=DIR has been specified, use it.
+   if test "x${PJSIP_TLS_TRANSPORT_RESTART_DIR}" != "x"; then
+      if test -d ${PJSIP_TLS_TRANSPORT_RESTART_DIR}/lib; then
+         pbxlibdir="-L${PJSIP_TLS_TRANSPORT_RESTART_DIR}/lib"
+      else
+         pbxlibdir="-L${PJSIP_TLS_TRANSPORT_RESTART_DIR}"
+      fi
+   fi
+
+      ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
+      CFLAGS="${CFLAGS} $PJPROJECT_CFLAGS"
+      { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pjsip_tls_transport_restart in -lpjsip" >&5
+printf %s "checking for pjsip_tls_transport_restart in -lpjsip... " >&6; }
+if test ${ac_cv_lib_pjsip_pjsip_tls_transport_restart+y}
+then :
+  printf %s "(cached) " >&6
+else $as_nop
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpjsip ${pbxlibdir} $PJPROJECT_LIB $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.  */
+char pjsip_tls_transport_restart ();
+int
+main (void)
+{
+return pjsip_tls_transport_restart ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"
+then :
+  ac_cv_lib_pjsip_pjsip_tls_transport_restart=yes
+else $as_nop
+  ac_cv_lib_pjsip_pjsip_tls_transport_restart=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.beam \
+    conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pjsip_pjsip_tls_transport_restart" >&5
+printf "%s\n" "$ac_cv_lib_pjsip_pjsip_tls_transport_restart" >&6; }
+if test "x$ac_cv_lib_pjsip_pjsip_tls_transport_restart" = xyes
+then :
+  AST_PJSIP_TLS_TRANSPORT_RESTART_FOUND=yes
+else $as_nop
+  AST_PJSIP_TLS_TRANSPORT_RESTART_FOUND=no
+fi
+
+      CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+
+
+   # now check for the header.
+   if test "${AST_PJSIP_TLS_TRANSPORT_RESTART_FOUND}" = "yes"; then
+      PJSIP_TLS_TRANSPORT_RESTART_LIB="${pbxlibdir} -lpjsip $PJPROJECT_LIB"
+      # if --with-PJSIP_TLS_TRANSPORT_RESTART=DIR has been specified, use it.
+      if test "x${PJSIP_TLS_TRANSPORT_RESTART_DIR}" != "x"; then
+         PJSIP_TLS_TRANSPORT_RESTART_INCLUDE="-I${PJSIP_TLS_TRANSPORT_RESTART_DIR}/include"
+      fi
+      PJSIP_TLS_TRANSPORT_RESTART_INCLUDE="${PJSIP_TLS_TRANSPORT_RESTART_INCLUDE} $PJPROJECT_CFLAGS"
+
+         # check for the header
+         ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
+         CPPFLAGS="${CPPFLAGS} ${PJSIP_TLS_TRANSPORT_RESTART_INCLUDE}"
+         ac_fn_c_check_header_compile "$LINENO" "pjsip.h" "ac_cv_header_pjsip_h" "$ac_includes_default"
+if test "x$ac_cv_header_pjsip_h" = xyes
+then :
+  PJSIP_TLS_TRANSPORT_RESTART_HEADER_FOUND=1
+else $as_nop
+  PJSIP_TLS_TRANSPORT_RESTART_HEADER_FOUND=0
+fi
+
+         CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
+
+      if test "x${PJSIP_TLS_TRANSPORT_RESTART_HEADER_FOUND}" = "x0" ; then
+         PJSIP_TLS_TRANSPORT_RESTART_LIB=""
+         PJSIP_TLS_TRANSPORT_RESTART_INCLUDE=""
+      else
+
+         PBX_PJSIP_TLS_TRANSPORT_RESTART=1
+         cat >>confdefs.h <<_ACEOF
+#define HAVE_PJSIP_TLS_TRANSPORT_RESTART 1
+_ACEOF
+
+      fi
+   fi
+fi
+
+
       fi
    fi
 
@@ -27835,8 +27950,8 @@
       if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for python-2.7" >&5
-printf %s "checking for python-2.7... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5
+printf %s "checking for PYTHONDEV... " >&6; }
 
 if test -n "$PYTHONDEV_CFLAGS"; then
     pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"
@@ -27876,7 +27991,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -27897,7 +28012,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_PYTHONDEV=0
@@ -27923,8 +28038,8 @@
       if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for python2" >&5
-printf %s "checking for python2... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5
+printf %s "checking for PYTHONDEV... " >&6; }
 
 if test -n "$PYTHONDEV_CFLAGS"; then
     pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"
@@ -27964,7 +28079,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -27985,7 +28100,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_PYTHONDEV=0
@@ -28011,8 +28126,8 @@
       if test "x${PBX_PYTHONDEV}" != "x1" -a "${USE_PYTHONDEV}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for python" >&5
-printf %s "checking for python... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PYTHONDEV" >&5
+printf %s "checking for PYTHONDEV... " >&6; }
 
 if test -n "$PYTHONDEV_CFLAGS"; then
     pkg_cv_PYTHONDEV_CFLAGS="$PYTHONDEV_CFLAGS"
@@ -28052,7 +28167,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -28073,7 +28188,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_PYTHONDEV=0
@@ -28207,8 +28322,8 @@
       if test "x${PBX_PORTAUDIO}" != "x1" -a "${USE_PORTAUDIO}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for portaudio-2.0" >&5
-printf %s "checking for portaudio-2.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for PORTAUDIO" >&5
+printf %s "checking for PORTAUDIO... " >&6; }
 
 if test -n "$PORTAUDIO_CFLAGS"; then
     pkg_cv_PORTAUDIO_CFLAGS="$PORTAUDIO_CFLAGS"
@@ -28248,7 +28363,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -28269,7 +28384,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_PORTAUDIO=0
@@ -34125,8 +34240,8 @@
       if test "x${PBX_GMIME}" != "x1" -a "${USE_GMIME}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gmime-$ver" >&5
-printf %s "checking for gmime-$ver... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GMIME" >&5
+printf %s "checking for GMIME... " >&6; }
 
 if test -n "$GMIME_CFLAGS"; then
     pkg_cv_GMIME_CFLAGS="$GMIME_CFLAGS"
@@ -34166,7 +34281,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -34187,7 +34302,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_GMIME=0
@@ -35485,8 +35600,8 @@
       if test "x${PBX_GTK2}" != "x1" -a "${USE_GTK2}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gtk+-2.0" >&5
-printf %s "checking for gtk+-2.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GTK2" >&5
+printf %s "checking for GTK2... " >&6; }
 
 if test -n "$GTK2_CFLAGS"; then
     pkg_cv_GTK2_CFLAGS="$GTK2_CFLAGS"
@@ -35526,7 +35641,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -35547,7 +35662,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_GTK2=0
@@ -35596,8 +35711,8 @@
       if test "x${PBX_SYSTEMD}" != "x1" -a "${USE_SYSTEMD}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libsystemd" >&5
-printf %s "checking for libsystemd... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for SYSTEMD" >&5
+printf %s "checking for SYSTEMD... " >&6; }
 
 if test -n "$SYSTEMD_CFLAGS"; then
     pkg_cv_SYSTEMD_CFLAGS="$SYSTEMD_CFLAGS"
@@ -35637,7 +35752,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -35658,7 +35773,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_SYSTEMD=0
diff --git a/configure.ac b/configure.ac
index b92db5d..5ee72b4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -589,6 +589,7 @@
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_ENDPOINT_COMPACT_FORM], [PJSIP Compact Form Support on Endpoint], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], [PJSIP Transport Connection Reuse Disabling], [PJPROJECT], [pjsip])
 AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_OAUTH_AUTHENTICATION], [PJSIP OAuth Authentication Support], [PJPROJECT], [pjsip])
+AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_RESTART], [PJSIP TLS Transport Restart Support], [PJPROJECT], [pjsip])
 fi
 
 AST_EXT_LIB_SETUP([POPT], [popt], [popt])
@@ -2495,6 +2496,7 @@
          AST_EXT_LIB_CHECK([PJSIP_INV_SESSION_REF], [pjsip], [pjsip_inv_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
          AST_EXT_LIB_CHECK([PJSIP_AUTH_CLT_DEINIT], [pjsip], [pjsip_auth_clt_deinit], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
          AST_EXT_LIB_CHECK([PJSIP_TSX_LAYER_FIND_TSX2], [pjsip], [pjsip_tsx_layer_find_tsx2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
+         AST_EXT_LIB_CHECK([PJSIP_TLS_TRANSPORT_RESTART], [pjsip], [pjsip_tls_transport_restart], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
       fi
    fi
 
diff --git a/doc/CHANGES-staging/res_pjsip_tls_cert_key_reload.txt b/doc/CHANGES-staging/res_pjsip_tls_cert_key_reload.txt
new file mode 100644
index 0000000..60c9dcd
--- /dev/null
+++ b/doc/CHANGES-staging/res_pjsip_tls_cert_key_reload.txt
@@ -0,0 +1,5 @@
+Subject: res_pjsip
+
+TLS transports in res_pjsip can now reload their TLS certificate
+and private key files, provided the filename of them has not
+changed.
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 40b9285..3c6b42f 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -19,19 +19,14 @@
    of a mutex to its initializer. */
 #undef CAN_COMPARE_MUTEX_TO_INIT_VALUE
 
-/* Define to 1 if the `closedir' function returns void instead of `int'. */
+/* Define to 1 if the `closedir' function returns void instead of int. */
 #undef CLOSEDIR_VOID
 
 /* Some configure tests will unexpectedly fail if configure is run by a
    non-root user. These may be able to be tested at runtime. */
 #undef CONFIGURE_RAN_AS_ROOT
 
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-   systems. This function is required for `alloca.c' support on those systems.
-   */
-#undef CRAY_STACKSEG_END
-
-/* Define to 1 if using `alloca.c'. */
+/* Define to 1 if using 'alloca.c'. */
 #undef C_ALLOCA
 
 /* Define to 1 if anonymous semaphores work. */
@@ -43,11 +38,10 @@
 /* Define to 1 if you have the `acosl' function. */
 #undef HAVE_ACOSL
 
-/* Define to 1 if you have `alloca', as a function or macro. */
+/* Define to 1 if you have 'alloca', as a function or macro. */
 #undef HAVE_ALLOCA
 
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
-   */
+/* Define to 1 if <alloca.h> works. */
 #undef HAVE_ALLOCA_H
 
 /* Define to 1 if you have the Advanced Linux Sound Architecture library. */
@@ -505,12 +499,12 @@
 /* Define to 1 if you have the `memmove' function. */
 #undef HAVE_MEMMOVE
 
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
 /* Define to 1 if you have the `memset' function. */
 #undef HAVE_MEMSET
 
+/* Define to 1 if you have the <minix/config.h> header file. */
+#undef HAVE_MINIX_CONFIG_H
+
 /* Define to 1 if you have the `mkdir' function. */
 #undef HAVE_MKDIR
 
@@ -656,6 +650,10 @@
 /* Define if your system has the PJSIP_TLS_TRANSPORT_PROTO headers. */
 #undef HAVE_PJSIP_TLS_TRANSPORT_PROTO
 
+/* Define to 1 if PJPROJECT has the PJSIP TLS Transport Restart Support
+   feature. */
+#undef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+
 /* Define if your system has the PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
    headers. */
 #undef HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE
@@ -1246,6 +1244,9 @@
 /* Define to 1 if you have the `vprintf' function. */
 #undef HAVE_VPRINTF
 
+/* Define to 1 if you have the <wchar.h> header file. */
+#undef HAVE_WCHAR_H
+
 /* Define to 1 if you have the <winsock2.h> header file. */
 #undef HAVE_WINSOCK2_H
 
@@ -1400,10 +1401,13 @@
 	STACK_DIRECTION = 0 => direction of growth unknown */
 #undef STACK_DIRECTION
 
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+   required in a freestanding environment). This macro is provided for
+   backward compatibility; new code need not use it. */
 #undef STDC_HEADERS
 
-/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. This
+   macro is obsolete. */
 #undef TIME_WITH_SYS_TIME
 
 /* Define to 1 if your <sys/time.h> declares `struct tm'. */
@@ -1416,32 +1420,93 @@
 #ifndef _ALL_SOURCE
 # undef _ALL_SOURCE
 #endif
-/* Enable GNU extensions on systems that have them.  */
-#ifndef _GNU_SOURCE
-# undef _GNU_SOURCE
-#endif
-/* Enable threading extensions on Solaris.  */
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-/* Enable extensions on HP NonStop.  */
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
+/* Enable general extensions on macOS.  */
+#ifndef _DARWIN_C_SOURCE
+# undef _DARWIN_C_SOURCE
 #endif
 /* Enable general extensions on Solaris.  */
 #ifndef __EXTENSIONS__
 # undef __EXTENSIONS__
 #endif
+/* Enable GNU extensions on systems that have them.  */
+#ifndef _GNU_SOURCE
+# undef _GNU_SOURCE
+#endif
+/* Enable X/Open compliant socket functions that do not require linking
+   with -lxnet on HP-UX 11.11.  */
+#ifndef _HPUX_ALT_XOPEN_SOCKET_API
+# undef _HPUX_ALT_XOPEN_SOCKET_API
+#endif
+/* Identify the host operating system as Minix.
+   This macro does not affect the system headers' behavior.
+   A future release of Autoconf may stop defining this macro.  */
+#ifndef _MINIX
+# undef _MINIX
+#endif
+/* Enable general extensions on NetBSD.
+   Enable NetBSD compatibility extensions on Minix.  */
+#ifndef _NETBSD_SOURCE
+# undef _NETBSD_SOURCE
+#endif
+/* Enable OpenBSD compatibility extensions on NetBSD.
+   Oddly enough, this does nothing on OpenBSD.  */
+#ifndef _OPENBSD_SOURCE
+# undef _OPENBSD_SOURCE
+#endif
+/* Define to 1 if needed for POSIX-compatible behavior.  */
+#ifndef _POSIX_SOURCE
+# undef _POSIX_SOURCE
+#endif
+/* Define to 2 if needed for POSIX-compatible behavior.  */
+#ifndef _POSIX_1_SOURCE
+# undef _POSIX_1_SOURCE
+#endif
+/* Enable POSIX-compatible threading on Solaris.  */
+#ifndef _POSIX_PTHREAD_SEMANTICS
+# undef _POSIX_PTHREAD_SEMANTICS
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-5:2014.  */
+#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-1:2014.  */
+#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
+# undef __STDC_WANT_IEC_60559_BFP_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-2:2015.  */
+#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
+# undef __STDC_WANT_IEC_60559_DFP_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-4:2015.  */
+#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
+# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TS 18661-3:2015.  */
+#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
+# undef __STDC_WANT_IEC_60559_TYPES_EXT__
+#endif
+/* Enable extensions specified by ISO/IEC TR 24731-2:2010.  */
+#ifndef __STDC_WANT_LIB_EXT2__
+# undef __STDC_WANT_LIB_EXT2__
+#endif
+/* Enable extensions specified by ISO/IEC 24747:2009.  */
+#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
+# undef __STDC_WANT_MATH_SPEC_FUNCS__
+#endif
+/* Enable extensions on HP NonStop.  */
+#ifndef _TANDEM_SOURCE
+# undef _TANDEM_SOURCE
+#endif
+/* Enable X/Open extensions.  Define to 500 only if necessary
+   to make mbstate_t available.  */
+#ifndef _XOPEN_SOURCE
+# undef _XOPEN_SOURCE
+#endif
 
 
 /* Define to 1 if running on Darwin. */
 #undef _DARWIN_UNLIMITED_SELECT
 
-/* Enable large inode numbers on Mac OS X 10.5.  */
-#ifndef _DARWIN_USE_64_BIT_INODE
-# define _DARWIN_USE_64_BIT_INODE 1
-#endif
-
 /* Number of bits in a file offset, on hosts where this is settable. */
 #undef _FILE_OFFSET_BITS
 
@@ -1459,16 +1524,6 @@
 /* Define for large files, on AIX-style hosts. */
 #undef _LARGE_FILES
 
-/* Define to 1 if on MINIX. */
-#undef _MINIX
-
-/* Define to 2 if the system does not provide POSIX.1 features except with
-   this defined. */
-#undef _POSIX_1_SOURCE
-
-/* Define to 1 if you need to in order for `stat' and other things to work. */
-#undef _POSIX_SOURCE
-
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
@@ -1490,7 +1545,7 @@
 /* Define to `long int' if <sys/types.h> does not define. */
 #undef off_t
 
-/* Define to `int' if <sys/types.h> does not define. */
+/* Define as a signed integer type capable of holding a process identifier. */
 #undef pid_t
 
 /* Define to `unsigned int' if <sys/types.h> does not define. */
diff --git a/include/asterisk/res_pjsip.h b/include/asterisk/res_pjsip.h
index b3717e7..e688494 100644
--- a/include/asterisk/res_pjsip.h
+++ b/include/asterisk/res_pjsip.h
@@ -51,6 +51,11 @@
 #include "asterisk/stasis_endpoints.h"
 #include "asterisk/stream.h"
 
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+/* Needed for knowing if the cert or priv key files changed */
+#include <sys/stat.h>
+#endif
+
 #define PJSIP_MINVERSION(m,n,p) (((m << 24) | (n << 16) | (p << 8)) >= PJ_VERSION_NUM)
 
 #ifndef PJSIP_EXPIRES_NOT_SPECIFIED
@@ -184,6 +189,16 @@
 	 * If true, fail if server certificate cannot verify (TLS only)
 	 */
 	int verify_server;
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+	/*!
+	 * The stats information for the certificate file, if configured
+	 */
+	struct stat cert_file_stat;
+	/*!
+	 * The stats information for the private key file, if configured
+	 */
+	struct stat privkey_file_stat;
+#endif
 };
 
 #define ast_sip_transport_is_nonlocal(transport_state, addr) \
diff --git a/menuselect/autoconfig.h.in b/menuselect/autoconfig.h.in
index 8047d7a..5ab0fcd 100644
--- a/menuselect/autoconfig.h.in
+++ b/menuselect/autoconfig.h.in
@@ -4,19 +4,13 @@
 #define MENUSELECT_AUTOCONFIG_H
 
 
-/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
-   systems. This function is required for `alloca.c' support on those systems.
-   */
-#undef CRAY_STACKSEG_END
-
-/* Define to 1 if using `alloca.c'. */
+/* Define to 1 if using 'alloca.c'. */
 #undef C_ALLOCA
 
-/* Define to 1 if you have `alloca', as a function or macro. */
+/* Define to 1 if you have 'alloca', as a function or macro. */
 #undef HAVE_ALLOCA
 
-/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix).
-   */
+/* Define to 1 if <alloca.h> works. */
 #undef HAVE_ALLOCA_H
 
 /* Define to 1 if you have the `asprintf' function. */
@@ -37,9 +31,6 @@
 /* Define if your system has the LIBXML2 libraries. */
 #undef HAVE_LIBXML2
 
-/* Define to 1 if you have the <memory.h> header file. */
-#undef HAVE_MEMORY_H
-
 /* Define to 1 if you have the ncurses library. */
 #undef HAVE_NCURSES
 
@@ -52,6 +43,9 @@
 /* Define to 1 if you have the <stdint.h> header file. */
 #undef HAVE_STDINT_H
 
+/* Define to 1 if you have the <stdio.h> header file. */
+#undef HAVE_STDIO_H
+
 /* Define to 1 if you have the <stdlib.h> header file. */
 #undef HAVE_STDLIB_H
 
@@ -117,7 +111,9 @@
 	STACK_DIRECTION = 0 => direction of growth unknown */
 #undef STACK_DIRECTION
 
-/* Define to 1 if you have the ANSI C header files. */
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+   required in a freestanding environment). This macro is provided for
+   backward compatibility; new code need not use it. */
 #undef STDC_HEADERS
 
 /* Define to `unsigned int' if <sys/types.h> does not define. */
diff --git a/menuselect/configure b/menuselect/configure
index c387d7f..3b35fbc 100755
--- a/menuselect/configure
+++ b/menuselect/configure
@@ -5024,8 +5024,8 @@
       if test "x${PBX_LIBXML2}" != "x1" -a "${USE_LIBXML2}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for libxml-2.0" >&5
-printf %s "checking for libxml-2.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for LIBXML2" >&5
+printf %s "checking for LIBXML2... " >&6; }
 
 if test -n "$LIBXML2_CFLAGS"; then
     pkg_cv_LIBXML2_CFLAGS="$LIBXML2_CFLAGS"
@@ -5065,7 +5065,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -5086,7 +5086,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_LIBXML2=0
@@ -5270,8 +5270,8 @@
       if test "x${PBX_GTK2}" != "x1" -a "${USE_GTK2}" != "no"; then
 
 pkg_failed=no
-{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for gtk+-2.0" >&5
-printf %s "checking for gtk+-2.0... " >&6; }
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GTK2" >&5
+printf %s "checking for GTK2... " >&6; }
 
 if test -n "$GTK2_CFLAGS"; then
     pkg_cv_GTK2_CFLAGS="$GTK2_CFLAGS"
@@ -5311,7 +5311,7 @@
 
 
 if test $pkg_failed = yes; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+   	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
 if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
@@ -5332,7 +5332,7 @@
 
 
 elif test $pkg_failed = untried; then
-        { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
+     	{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5
 printf "%s\n" "no" >&6; }
 
             PBX_GTK2=0
diff --git a/res/res_pjsip/config_transport.c b/res/res_pjsip/config_transport.c
index af0e0c9..c8655c2e 100644
--- a/res/res_pjsip/config_transport.c
+++ b/res/res_pjsip/config_transport.c
@@ -577,6 +577,22 @@
 	memcpy(&transport->external_address, &transport->state->external_signaling_address, sizeof(transport->external_signaling_address));
 }
 
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+static int file_stat_cmp(const struct stat *old_stat, const struct stat *new_stat)
+{
+	return old_stat->st_size != new_stat->st_size
+		|| old_stat->st_mtime != new_stat->st_mtime
+#if defined(HAVE_STRUCT_STAT_ST_MTIM)
+		|| old_stat->st_mtim.tv_nsec != new_stat->st_mtim.tv_nsec
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMENSEC)
+		|| old_stat->st_mtimensec != new_stat->st_mtimensec
+#elif defined(HAVE_STRUCT_STAT_ST_MTIMESPEC)
+		|| old_stat->st_mtimespec.tv_nsec != new_stat->st_mtimespec.tv_nsec
+#endif
+        ;
+}
+#endif
+
 static int has_state_changed(struct ast_sip_transport_state *a, struct ast_sip_transport_state *b)
 {
 	if (a->type != b->type) {
@@ -618,6 +634,12 @@
 		return -1;
 	}
 
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+	if (file_stat_cmp(&a->cert_file_stat, &b->cert_file_stat) || file_stat_cmp(&a->privkey_file_stat, &b->privkey_file_stat)) {
+		return -1;
+	}
+#endif
+
 	return 0;
 }
 
@@ -742,11 +764,31 @@
 		res = PJ_SUCCESS;
 	} else if (!transport->allow_reload && perm_state) {
 		/* We inherit the transport from perm state, untouched */
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+		ast_log(LOG_NOTICE, "Transport '%s' is not fully reloadable, not reloading: protocol, bind, TLS (everything but certificate and private key if filename is unchanged), TCP, ToS, or CoS options.\n", transport_id);
+		/* If this is a TLS transport and the certificate or private key has changed, then restart the transport so it uses the new one */
+		if (transport->type == AST_TRANSPORT_TLS) {
+			if (strcmp(perm_state->transport->cert_file, temp_state->transport->cert_file) ||
+				strcmp(perm_state->transport->privkey_file, temp_state->transport->privkey_file)) {
+				ast_log(LOG_ERROR, "Unable to restart TLS transport '%s' as certificate or private key filename has changed\n",
+					transport_id);
+			} else if (file_stat_cmp(&perm_state->state->cert_file_stat, &temp_state->state->cert_file_stat) ||
+				file_stat_cmp(&perm_state->state->privkey_file_stat, &temp_state->state->privkey_file_stat)) {
+				if (pjsip_tls_transport_restart(perm_state->state->factory, &perm_state->state->host, NULL) != PJ_SUCCESS) {
+					ast_log(LOG_ERROR, "Failed to restart TLS transport '%s'\n", transport_id);
+				} else {
+					sprintf(perm_state->state->factory->info, "%s", transport_id);
+				}
+			}
+		}
+#else
 		ast_log(LOG_NOTICE, "Transport '%s' is not fully reloadable, not reloading: protocol, bind, TLS, TCP, ToS, or CoS options.\n", transport_id);
+#endif
 		temp_state->state->transport = perm_state->state->transport;
 		perm_state->state->transport = NULL;
 		temp_state->state->factory = perm_state->state->factory;
 		perm_state->state->factory = NULL;
+
 		res = PJ_SUCCESS;
 	} else if (transport->type == AST_TRANSPORT_UDP) {
 
@@ -841,8 +883,12 @@
 		}
 
 		if (res == PJ_SUCCESS) {
+			/*
+			 * PJSIP uses 100 bytes to store information, and during a restart will repopulate
+			 * the field so ensure there is sufficient space - even though we'll revert it after.
+			 */
 			temp_state->state->factory->info = pj_pool_alloc(
-				temp_state->state->factory->pool, (strlen(transport_id) + 1));
+				temp_state->state->factory->pool, (MAX(MAX_OBJECT_FIELD, 100) + 1));
 			/*
 			 * Store transport id on the factory instance so it can be used
 			 * later to look up the transport state.
@@ -918,18 +964,34 @@
 		ast_string_field_set(transport, ca_list_file, var->value);
 	} else if (!strcasecmp(var->name, "ca_list_path")) {
 #ifdef HAVE_PJ_SSL_CERT_LOAD_FROM_FILES2
-		state->tls.ca_list_path = pj_str((char*)var->value);
+		state->tls.ca_list_path = pj_str((char *)var->value);
 		ast_string_field_set(transport, ca_list_path, var->value);
 #else
 		ast_log(LOG_WARNING, "Asterisk has been built against a version of pjproject that does not "
 				"support the 'ca_list_path' option. Please upgrade to version 2.4 or later.\n");
 #endif
 	} else if (!strcasecmp(var->name, "cert_file")) {
-		state->tls.cert_file = pj_str((char*)var->value);
+		state->tls.cert_file = pj_str((char *)var->value);
 		ast_string_field_set(transport, cert_file, var->value);
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+		if (stat(var->value, &state->cert_file_stat)) {
+			ast_log(LOG_ERROR, "Failed to stat certificate file '%s' for transport '%s' due to '%s'\n",
+				var->value, ast_sorcery_object_get_id(obj), strerror(errno));
+			return -1;
+		}
+		ast_sorcery_object_set_has_dynamic_contents(transport);
+#endif
 	} else if (!strcasecmp(var->name, "priv_key_file")) {
-		state->tls.privkey_file = pj_str((char*)var->value);
+		state->tls.privkey_file = pj_str((char *)var->value);
 		ast_string_field_set(transport, privkey_file, var->value);
+#ifdef HAVE_PJSIP_TLS_TRANSPORT_RESTART
+		if (stat(var->value, &state->privkey_file_stat)) {
+			ast_log(LOG_ERROR, "Failed to stat private key file '%s' for transport '%s' due to '%s'\n",
+				var->value, ast_sorcery_object_get_id(obj), strerror(errno));
+			return -1;
+		}
+		ast_sorcery_object_set_has_dynamic_contents(transport);
+#endif
 	}
 
 	return 0;
diff --git a/res/res_pjsip/pjsip_config.xml b/res/res_pjsip/pjsip_config.xml
index 63fd1a9..d78efe32 100644
--- a/res/res_pjsip/pjsip_config.xml
+++ b/res/res_pjsip/pjsip_config.xml
@@ -1657,7 +1657,8 @@
 						A path to a .crt or .pem file can be provided.  However, only
 						the certificate is read from the file, not the private key.
 						The <literal>priv_key_file</literal> option must supply a
-						matching key file.
+						matching key file. The certificate file can be reloaded if
+						the filename in configuration remains unchanged.
 					</para></description>
 				</configOption>
 				<configOption name="cipher">
@@ -1721,6 +1722,11 @@
 				</configOption>
 				<configOption name="priv_key_file">
 					<synopsis>Private key file (TLS ONLY, not WSS)</synopsis>
+					<description><para>
+						A path to a key file can be provided. The private key file
+						can be reloaded if the filename in configuration remains
+						unchanged.
+					</para></description>
 				</configOption>
 				<configOption name="protocol" default="udp">
 					<synopsis>Protocol to use for SIP traffic</synopsis>
diff --git a/third-party/pjproject/configure.m4 b/third-party/pjproject/configure.m4
index 2f26625..fb95220 100644
--- a/third-party/pjproject/configure.m4
+++ b/third-party/pjproject/configure.m4
@@ -131,6 +131,7 @@
 		AC_DEFINE([HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], 1, [Define if your system has HAVE_PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE declared])
 		AC_DEFINE([HAVE_PJSIP_OAUTH_AUTHENTICATION], 1, [Define if your system has HAVE_PJSIP_OAUTH_AUTHENTICATION declared])
 		AC_DEFINE([HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK], 1, [Define if your system has the on_valid_pair pjnath callback.])
+		AC_DEFINE([HAVE_PJSIP_TLS_TRANSPORT_RESTART], 1, [Define if your system has pjsip_tls_transport_restart support.])
 
 		AC_SUBST([PJPROJECT_BUNDLED])
 		AC_SUBST([PJPROJECT_BUNDLED_OOT])

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/19093
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: master
Gerrit-Change-Id: I9bc95a6bf791830a9491ad9fa43c17d4010028d0
Gerrit-Change-Number: 19093
Gerrit-PatchSet: 1
Gerrit-Owner: Joshua Colp <jcolp at sangoma.com>
Gerrit-MessageType: newchange
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20220907/ee1e81c0/attachment-0001.html>


More information about the asterisk-code-review mailing list