summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_pjsip.c2
-rw-r--r--codecs/codec_speex.c5
-rwxr-xr-xconfigure1004
-rw-r--r--configure.ac40
-rw-r--r--include/asterisk/_private.h5
-rw-r--r--include/asterisk/autoconfig.h.in12
-rw-r--r--include/asterisk/data_buffer.h144
-rw-r--r--include/asterisk/frame.h2
-rw-r--r--include/asterisk/paths.h4
-rw-r--r--include/asterisk/rtp_engine.h26
-rw-r--r--main/Makefile9
-rw-r--r--main/asterisk.c420
-rw-r--r--main/bridge_channel.c3
-rw-r--r--main/channel.c11
-rw-r--r--main/data_buffer.c314
-rw-r--r--main/indications.c33
-rw-r--r--main/options.c475
-rw-r--r--makeopts.in18
-rw-r--r--res/res_pjsip/pjsip_transport_events.c55
-rw-r--r--res/res_rtp_asterisk.c70
-rw-r--r--tests/test_data_buffer.c313
-rw-r--r--third-party/pjproject/patches/0070-os_core_unix-Set-mutex-NULL-in-atomic-destroy-and-ad.patch114
-rw-r--r--third-party/pjproject/patches/0080-timer-Clean-up-usage-of-timer-heap.patch434
23 files changed, 2227 insertions, 1286 deletions
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 2c111feeb..5cb52a5b2 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -965,6 +965,8 @@ static int chan_pjsip_write_stream(struct ast_channel *ast, int stream_num, stru
break;
case AST_FRAME_CNG:
break;
+ case AST_FRAME_RTCP:
+ break;
default:
ast_log(LOG_WARNING, "Can't send %u type frames with PJSIP\n", frame->frametype);
break;
diff --git a/codecs/codec_speex.c b/codecs/codec_speex.c
index 0a9359620..591fce9de 100644
--- a/codecs/codec_speex.c
+++ b/codecs/codec_speex.c
@@ -372,6 +372,11 @@ static void lintospeex_feedback(struct ast_trans_pvt *pvt, struct ast_frame *fee
if(!exp_rtcp_fb)
return;
+ /* We only accept feedback information in the form of SR and RR reports */
+ if (feedback->subclass.integer != AST_RTP_RTCP_SR && feedback->subclass.integer != AST_RTP_RTCP_RR) {
+ return;
+ }
+
rtcp_report = (struct ast_rtp_rtcp_report *)feedback->data.ptr;
if (rtcp_report->reception_report_count == 0)
return;
diff --git a/configure b/configure
index 9245063da..3a8c5051a 100755
--- a/configure
+++ b/configure
@@ -672,16 +672,11 @@ CONFIG_NEON
CONFIG_MYSQLCLIENT
PBX_MISDN_FAC_ERROR
PBX_MISDN_FAC_RESULT
-LIBEDIT_LIBS
-LIBEDIT_CFLAGS
ILBC_LIBS
ILBC_CFLAGS
ILBC_INTERNAL
GSM_INTERNAL
PBX_DAHDI_HALF_FULL
-PKG_CONFIG_LIBDIR
-PKG_CONFIG_PATH
-PKG_CONFIG
PBX_DLADDR
PBX_IP_MTU_DISCOVER
PBX_RTLD_NOLOAD
@@ -712,7 +707,11 @@ DISABLE_XMLDOC
CONFIG_LIBXML2
UUID_LIB
UUID_INCLUDE
-EDITLINE_LIB
+LIBEDIT_LIBS
+LIBEDIT_CFLAGS
+PKG_CONFIG_LIBDIR
+PKG_CONFIG_PATH
+PKG_CONFIG
ALLOCA
PBX_ZLIB
ZLIB_DIR
@@ -742,18 +741,10 @@ PBX_TONEZONE
TONEZONE_DIR
TONEZONE_INCLUDE
TONEZONE_LIB
-PBX_TINFO
-TINFO_DIR
-TINFO_INCLUDE
-TINFO_LIB
PBX_TIMERFD
TIMERFD_DIR
TIMERFD_INCLUDE
TIMERFD_LIB
-PBX_TERMCAP
-TERMCAP_DIR
-TERMCAP_INCLUDE
-TERMCAP_LIB
PBX_FREETDS
FREETDS_DIR
FREETDS_INCLUDE
@@ -1026,10 +1017,6 @@ PBX_NEON
NEON_DIR
NEON_INCLUDE
NEON_LIB
-PBX_NCURSES
-NCURSES_DIR
-NCURSES_INCLUDE
-NCURSES_LIB
PBX_NBS
NBS_DIR
NBS_INCLUDE
@@ -1162,10 +1149,6 @@ PBX_CRYPT
CRYPT_DIR
CRYPT_INCLUDE
CRYPT_LIB
-PBX_CURSES
-CURSES_DIR
-CURSES_INCLUDE
-CURSES_LIB
PBX_COROSYNC_CFG_STATE_TRACK
COROSYNC_CFG_STATE_TRACK_DIR
COROSYNC_CFG_STATE_TRACK_INCLUDE
@@ -1378,7 +1361,6 @@ with_bluetooth
with_cap
with_codec2
with_cpg
-with_curses
with_crypt
with_crypto
with_dahdi
@@ -1408,7 +1390,6 @@ with_lua
with_misdn
with_mysqlclient
with_nbs
-with_ncurses
with_neon
with_neon29
with_netsnmp
@@ -1441,9 +1422,7 @@ with_srtp
with_ssl
with_suppserv
with_tds
-with_termcap
with_timerfd
-with_tinfo
with_tonezone
with_unbound
with_unixodbc
@@ -1474,10 +1453,10 @@ PJPROJECT_CONFIGURE_OPTS
PKG_CONFIG
PKG_CONFIG_PATH
PKG_CONFIG_LIBDIR
-ILBC_CFLAGS
-ILBC_LIBS
LIBEDIT_CFLAGS
LIBEDIT_LIBS
+ILBC_CFLAGS
+ILBC_LIBS
PJPROJECT_CFLAGS
PJPROJECT_LIBS
PYTHONDEV_CFLAGS
@@ -2131,7 +2110,6 @@ Optional Packages:
--with-cap=PATH use POSIX 1.e capabilities files in PATH
--with-codec2=PATH use Codec 2 Audio Decoder/Encoder files in PATH
--with-cpg=PATH use Corosync files in PATH
- --with-curses=PATH use curses files in PATH
--with-crypt=PATH use password and data encryption files in PATH
--with-crypto=PATH use OpenSSL Cryptography files in PATH
--with-dahdi=PATH use DAHDI files in PATH
@@ -2164,7 +2142,6 @@ Optional Packages:
--with-misdn=PATH use mISDN user files in PATH
--with-mysqlclient=PATH use MySQL client files in PATH
--with-nbs=PATH use Network Broadcast Sound files in PATH
- --with-ncurses=PATH use ncurses files in PATH
--with-neon=PATH use neon files in PATH
--with-neon29=PATH use neon29 files in PATH
--with-netsnmp=PATH use Net-SNMP files in PATH
@@ -2198,9 +2175,7 @@ Optional Packages:
--with-ssl=PATH use OpenSSL Secure Sockets Layer files in PATH
--with-suppserv=PATH use mISDN Supplemental Services files in PATH
--with-tds=PATH use FreeTDS files in PATH
- --with-termcap=PATH use Termcap files in PATH
--with-timerfd=PATH use timerfd files in PATH
- --with-tinfo=PATH use Term Info files in PATH
--with-tonezone=PATH use tonezone files in PATH
--with-unbound=PATH use unbound files in PATH
--with-unixodbc=PATH use unixODBC files in PATH
@@ -2228,12 +2203,12 @@ Some influential environment variables:
directories to add to pkg-config's search path
PKG_CONFIG_LIBDIR
path overriding pkg-config's built-in search path
- ILBC_CFLAGS C compiler flags for ILBC, overriding pkg-config
- ILBC_LIBS linker flags for ILBC, overriding pkg-config
LIBEDIT_CFLAGS
C compiler flags for LIBEDIT, overriding pkg-config
LIBEDIT_LIBS
linker flags for LIBEDIT, overriding pkg-config
+ ILBC_CFLAGS C compiler flags for ILBC, overriding pkg-config
+ ILBC_LIBS linker flags for ILBC, overriding pkg-config
PJPROJECT_CFLAGS
C compiler flags for PJPROJECT, overriding pkg-config
PJPROJECT_LIBS
@@ -9565,38 +9540,6 @@ PBX_COROSYNC_CFG_STATE_TRACK=0
- CURSES_DESCRIP="curses"
- CURSES_OPTION="curses"
- PBX_CURSES=0
-
-# Check whether --with-curses was given.
-if test "${with_curses+set}" = set; then :
- withval=$with_curses;
- case ${withval} in
- n|no)
- USE_CURSES=no
- # -1 is a magic value used by menuselect to know that the package
- # was disabled, other than 'not found'
- PBX_CURSES=-1
- ;;
- y|ye|yes)
- ac_mandatory_list="${ac_mandatory_list} CURSES"
- ;;
- *)
- CURSES_DIR="${withval}"
- ac_mandatory_list="${ac_mandatory_list} CURSES"
- ;;
- esac
-
-fi
-
-
-
-
-
-
-
-
CRYPT_DESCRIP="password and data encryption"
CRYPT_OPTION="crypt"
PBX_CRYPT=0
@@ -10928,38 +10871,6 @@ fi
- NCURSES_DESCRIP="ncurses"
- NCURSES_OPTION="ncurses"
- PBX_NCURSES=0
-
-# Check whether --with-ncurses was given.
-if test "${with_ncurses+set}" = set; then :
- withval=$with_ncurses;
- case ${withval} in
- n|no)
- USE_NCURSES=no
- # -1 is a magic value used by menuselect to know that the package
- # was disabled, other than 'not found'
- PBX_NCURSES=-1
- ;;
- y|ye|yes)
- ac_mandatory_list="${ac_mandatory_list} NCURSES"
- ;;
- *)
- NCURSES_DIR="${withval}"
- ac_mandatory_list="${ac_mandatory_list} NCURSES"
- ;;
- esac
-
-fi
-
-
-
-
-
-
-
-
NEON_DESCRIP="neon"
NEON_OPTION="neon"
PBX_NEON=0
@@ -12467,38 +12378,6 @@ fi
- TERMCAP_DESCRIP="Termcap"
- TERMCAP_OPTION="termcap"
- PBX_TERMCAP=0
-
-# Check whether --with-termcap was given.
-if test "${with_termcap+set}" = set; then :
- withval=$with_termcap;
- case ${withval} in
- n|no)
- USE_TERMCAP=no
- # -1 is a magic value used by menuselect to know that the package
- # was disabled, other than 'not found'
- PBX_TERMCAP=-1
- ;;
- y|ye|yes)
- ac_mandatory_list="${ac_mandatory_list} TERMCAP"
- ;;
- *)
- TERMCAP_DIR="${withval}"
- ac_mandatory_list="${ac_mandatory_list} TERMCAP"
- ;;
- esac
-
-fi
-
-
-
-
-
-
-
-
TIMERFD_DESCRIP="timerfd"
TIMERFD_OPTION="timerfd"
PBX_TIMERFD=0
@@ -12531,38 +12410,6 @@ fi
- TINFO_DESCRIP="Term Info"
- TINFO_OPTION="tinfo"
- PBX_TINFO=0
-
-# Check whether --with-tinfo was given.
-if test "${with_tinfo+set}" = set; then :
- withval=$with_tinfo;
- case ${withval} in
- n|no)
- USE_TINFO=no
- # -1 is a magic value used by menuselect to know that the package
- # was disabled, other than 'not found'
- PBX_TINFO=-1
- ;;
- y|ye|yes)
- ac_mandatory_list="${ac_mandatory_list} TINFO"
- ;;
- *)
- TINFO_DIR="${withval}"
- ac_mandatory_list="${ac_mandatory_list} TINFO"
- ;;
- esac
-
-fi
-
-
-
-
-
-
-
-
TONEZONE_DESCRIP="tonezone"
TONEZONE_OPTION="tonezone"
PBX_TONEZONE=0
@@ -13381,200 +13228,237 @@ fi
done
-# Any one of these packages support a mandatory requirement, so we want to check on them as early as possible.
+# Find required NetBSD Editline library (libedit).
-if test "x${PBX_TERMCAP}" != "x1" -a "${USE_TERMCAP}" != "no"; then
- pbxlibdir=""
- # if --with-TERMCAP=DIR has been specified, use it.
- if test "x${TERMCAP_DIR}" != "x"; then
- if test -d ${TERMCAP_DIR}/lib; then
- pbxlibdir="-L${TERMCAP_DIR}/lib"
- else
- pbxlibdir="-L${TERMCAP_DIR}"
- fi
- fi
- ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
- CFLAGS="${CFLAGS} "
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltermcap" >&5
-$as_echo_n "checking for tgetent in -ltermcap... " >&6; }
-if ${ac_cv_lib_termcap_tgetent+:} false; then :
+
+
+
+
+
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args.
+set dummy ${ac_tool_prefix}pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_PKG_CONFIG+:} false; then :
$as_echo_n "(cached) " >&6
else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ltermcap ${pbxlibdir} $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
+ case $PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
-/* 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 tgetent ();
-int
-main ()
-{
-return tgetent ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_termcap_tgetent=yes
-else
- ac_cv_lib_termcap_tgetent=no
-fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+ ;;
+esac
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_termcap_tgetent" >&5
-$as_echo "$ac_cv_lib_termcap_tgetent" >&6; }
-if test "x$ac_cv_lib_termcap_tgetent" = xyes; then :
- AST_TERMCAP_FOUND=yes
+PKG_CONFIG=$ac_cv_path_PKG_CONFIG
+if test -n "$PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5
+$as_echo "$PKG_CONFIG" >&6; }
else
- AST_TERMCAP_FOUND=no
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
fi
- CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
-
-
- # now check for the header.
- if test "${AST_TERMCAP_FOUND}" = "yes"; then
- TERMCAP_LIB="${pbxlibdir} -ltermcap "
- # if --with-TERMCAP=DIR has been specified, use it.
- if test "x${TERMCAP_DIR}" != "x"; then
- TERMCAP_INCLUDE="-I${TERMCAP_DIR}/include"
- fi
- TERMCAP_INCLUDE="${TERMCAP_INCLUDE} "
-
- # no header, assume found
- TERMCAP_HEADER_FOUND="1"
- if test "x${TERMCAP_HEADER_FOUND}" = "x0" ; then
- TERMCAP_LIB=""
- TERMCAP_INCLUDE=""
- else
+fi
+if test -z "$ac_cv_path_PKG_CONFIG"; then
+ ac_pt_PKG_CONFIG=$PKG_CONFIG
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ac_pt_PKG_CONFIG in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
- PBX_TERMCAP=1
- cat >>confdefs.h <<_ACEOF
-#define HAVE_TERMCAP 1
-_ACEOF
+ ;;
+esac
+fi
+ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG
+if test -n "$ac_pt_PKG_CONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5
+$as_echo "$ac_pt_PKG_CONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
- fi
- fi
+ if test "x$ac_pt_PKG_CONFIG" = x; then
+ PKG_CONFIG=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ PKG_CONFIG=$ac_pt_PKG_CONFIG
+ fi
+else
+ PKG_CONFIG="$ac_cv_path_PKG_CONFIG"
fi
+fi
+if test -n "$PKG_CONFIG"; then
+ _pkg_min_version=0.9.0
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5
+$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; }
+ if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ PKG_CONFIG=""
+ fi
+fi
+ if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then
-if test "x${PBX_TINFO}" != "x1" -a "${USE_TINFO}" != "no"; then
- pbxlibdir=""
- # if --with-TINFO=DIR has been specified, use it.
- if test "x${TINFO_DIR}" != "x"; then
- if test -d ${TINFO_DIR}/lib; then
- pbxlibdir="-L${TINFO_DIR}/lib"
- else
- pbxlibdir="-L${TINFO_DIR}"
- fi
- fi
+pkg_failed=no
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEDIT" >&5
+$as_echo_n "checking for LIBEDIT... " >&6; }
- ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
- CFLAGS="${CFLAGS} "
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for tgetent in -ltinfo" >&5
-$as_echo_n "checking for tgetent in -ltinfo... " >&6; }
-if ${ac_cv_lib_tinfo_tgetent+:} false; then :
- $as_echo_n "(cached) " >&6
+if test -n "$LIBEDIT_CFLAGS"; then
+ pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libedit") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBEDIT_CFLAGS=`$PKG_CONFIG --cflags "libedit" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ltinfo ${pbxlibdir} $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 tgetent ();
-int
-main ()
-{
-return tgetent ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_tinfo_tgetent=yes
+ pkg_failed=yes
+fi
+ else
+ pkg_failed=untried
+fi
+if test -n "$LIBEDIT_LIBS"; then
+ pkg_cv_LIBEDIT_LIBS="$LIBEDIT_LIBS"
+ elif test -n "$PKG_CONFIG"; then
+ if test -n "$PKG_CONFIG" && \
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5
+ ($PKG_CONFIG --exists --print-errors "libedit") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ pkg_cv_LIBEDIT_LIBS=`$PKG_CONFIG --libs "libedit" 2>/dev/null`
+ test "x$?" != "x0" && pkg_failed=yes
else
- ac_cv_lib_tinfo_tgetent=no
+ pkg_failed=yes
fi
-rm -f core conftest.err conftest.$ac_objext \
- conftest$ac_exeext conftest.$ac_ext
-LIBS=$ac_check_lib_save_LIBS
+ else
+ pkg_failed=untried
fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_tinfo_tgetent" >&5
-$as_echo "$ac_cv_lib_tinfo_tgetent" >&6; }
-if test "x$ac_cv_lib_tinfo_tgetent" = xyes; then :
- AST_TINFO_FOUND=yes
+
+
+
+if test $pkg_failed = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+ _pkg_short_errors_supported=yes
else
- AST_TINFO_FOUND=no
+ _pkg_short_errors_supported=no
fi
+ if test $_pkg_short_errors_supported = yes; then
+ LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libedit" 2>&1`
+ else
+ LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libedit" 2>&1`
+ fi
+ # Put the nasty error message in config.log where it belongs
+ echo "$LIBEDIT_PKG_ERRORS" >&5
- CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+ PBX_LIBEDIT=0
- # now check for the header.
- if test "${AST_TINFO_FOUND}" = "yes"; then
- TINFO_LIB="${pbxlibdir} -ltinfo "
- # if --with-TINFO=DIR has been specified, use it.
- if test "x${TINFO_DIR}" != "x"; then
- TINFO_INCLUDE="-I${TINFO_DIR}/include"
- fi
- TINFO_INCLUDE="${TINFO_INCLUDE} "
- # no header, assume found
- TINFO_HEADER_FOUND="1"
+elif test $pkg_failed = untried; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
- if test "x${TINFO_HEADER_FOUND}" = "x0" ; then
- TINFO_LIB=""
- TINFO_INCLUDE=""
- else
+ PBX_LIBEDIT=0
- PBX_TINFO=1
- cat >>confdefs.h <<_ACEOF
-#define HAVE_TINFO 1
-_ACEOF
- fi
- fi
-fi
+else
+ LIBEDIT_CFLAGS=$pkg_cv_LIBEDIT_CFLAGS
+ LIBEDIT_LIBS=$pkg_cv_LIBEDIT_LIBS
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ PBX_LIBEDIT=1
+ LIBEDIT_INCLUDE="$LIBEDIT_CFLAGS"
+ LIBEDIT_LIB="$LIBEDIT_LIBS"
+$as_echo "#define HAVE_LIBEDIT 1" >>confdefs.h
+
+
+fi
+ fi
+# some platforms do not list libedit via pkg-config, for example OpenBSD 6.2
-if test "x${PBX_CURSES}" != "x1" -a "${USE_CURSES}" != "no"; then
+if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then
pbxlibdir=""
- # if --with-CURSES=DIR has been specified, use it.
- if test "x${CURSES_DIR}" != "x"; then
- if test -d ${CURSES_DIR}/lib; then
- pbxlibdir="-L${CURSES_DIR}/lib"
+ # if --with-LIBEDIT=DIR has been specified, use it.
+ if test "x${LIBEDIT_DIR}" != "x"; then
+ if test -d ${LIBEDIT_DIR}/lib; then
+ pbxlibdir="-L${LIBEDIT_DIR}/lib"
else
- pbxlibdir="-L${CURSES_DIR}"
+ pbxlibdir="-L${LIBEDIT_DIR}"
fi
fi
ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} "
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lcurses" >&5
-$as_echo_n "checking for initscr in -lcurses... " >&6; }
-if ${ac_cv_lib_curses_initscr+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for history_init in -ledit" >&5
+$as_echo_n "checking for history_init in -ledit... " >&6; }
+if ${ac_cv_lib_edit_history_init+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
-LIBS="-lcurses ${pbxlibdir} $LIBS"
+LIBS="-ledit ${pbxlibdir} -ltermcap $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -13584,65 +13468,65 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#ifdef __cplusplus
extern "C"
#endif
-char initscr ();
+char history_init ();
int
main ()
{
-return initscr ();
+return history_init ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_curses_initscr=yes
+ ac_cv_lib_edit_history_init=yes
else
- ac_cv_lib_curses_initscr=no
+ ac_cv_lib_edit_history_init=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_curses_initscr" >&5
-$as_echo "$ac_cv_lib_curses_initscr" >&6; }
-if test "x$ac_cv_lib_curses_initscr" = xyes; then :
- AST_CURSES_FOUND=yes
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_edit_history_init" >&5
+$as_echo "$ac_cv_lib_edit_history_init" >&6; }
+if test "x$ac_cv_lib_edit_history_init" = xyes; then :
+ AST_LIBEDIT_FOUND=yes
else
- AST_CURSES_FOUND=no
+ AST_LIBEDIT_FOUND=no
fi
CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
# now check for the header.
- if test "${AST_CURSES_FOUND}" = "yes"; then
- CURSES_LIB="${pbxlibdir} -lcurses "
- # if --with-CURSES=DIR has been specified, use it.
- if test "x${CURSES_DIR}" != "x"; then
- CURSES_INCLUDE="-I${CURSES_DIR}/include"
+ if test "${AST_LIBEDIT_FOUND}" = "yes"; then
+ LIBEDIT_LIB="${pbxlibdir} -ledit -ltermcap"
+ # if --with-LIBEDIT=DIR has been specified, use it.
+ if test "x${LIBEDIT_DIR}" != "x"; then
+ LIBEDIT_INCLUDE="-I${LIBEDIT_DIR}/include"
fi
- CURSES_INCLUDE="${CURSES_INCLUDE} "
+ LIBEDIT_INCLUDE="${LIBEDIT_INCLUDE} "
# check for the header
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
- CPPFLAGS="${CPPFLAGS} ${CURSES_INCLUDE}"
- ac_fn_c_check_header_mongrel "$LINENO" "curses.h" "ac_cv_header_curses_h" "$ac_includes_default"
-if test "x$ac_cv_header_curses_h" = xyes; then :
- CURSES_HEADER_FOUND=1
+ CPPFLAGS="${CPPFLAGS} ${LIBEDIT_INCLUDE}"
+ ac_fn_c_check_header_mongrel "$LINENO" "histedit.h" "ac_cv_header_histedit_h" "$ac_includes_default"
+if test "x$ac_cv_header_histedit_h" = xyes; then :
+ LIBEDIT_HEADER_FOUND=1
else
- CURSES_HEADER_FOUND=0
+ LIBEDIT_HEADER_FOUND=0
fi
CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
- if test "x${CURSES_HEADER_FOUND}" = "x0" ; then
- CURSES_LIB=""
- CURSES_INCLUDE=""
+ if test "x${LIBEDIT_HEADER_FOUND}" = "x0" ; then
+ LIBEDIT_LIB=""
+ LIBEDIT_INCLUDE=""
else
- PBX_CURSES=1
+ PBX_LIBEDIT=1
cat >>confdefs.h <<_ACEOF
-#define HAVE_CURSES 1
+#define HAVE_LIBEDIT 1
_ACEOF
fi
@@ -13650,115 +13534,49 @@ _ACEOF
fi
+if test "${PBX_LIBEDIT}" != 1; then
+ as_fn_error $? "*** Please install the 'libedit' development package." "$LINENO" 5
+ exit 1
+fi
-if test "x${PBX_NCURSES}" != "x1" -a "${USE_NCURSES}" != "no"; then
- pbxlibdir=""
- # if --with-NCURSES=DIR has been specified, use it.
- if test "x${NCURSES_DIR}" != "x"; then
- if test -d ${NCURSES_DIR}/lib; then
- pbxlibdir="-L${NCURSES_DIR}/lib"
- else
- pbxlibdir="-L${NCURSES_DIR}"
- fi
- fi
+ if test "x${PBX_LIBEDIT_IS_UNICODE}" != "x1" -a "${USE_LIBEDIT_IS_UNICODE}" != "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Testing for libedit unicode support" >&5
+$as_echo_n "checking for Testing for libedit unicode support... " >&6; }
+ saved_cppflags="${CPPFLAGS}"
+ if test "x${LIBEDIT_IS_UNICODE_DIR}" != "x"; then
+ LIBEDIT_IS_UNICODE_INCLUDE="-I${LIBEDIT_IS_UNICODE_DIR}/include"
+ fi
+ CPPFLAGS="${CPPFLAGS} ${LIBEDIT_IS_UNICODE_INCLUDE}"
- ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
- CFLAGS="${CFLAGS} "
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for initscr in -lncurses" >&5
-$as_echo_n "checking for initscr in -lncurses... " >&6; }
-if ${ac_cv_lib_ncurses_initscr+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-lncurses ${pbxlibdir} $LIBS"
-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ 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 initscr ();
+ #include <histedit.h>
int
main ()
{
-return initscr ();
+ el_rfunc_t *callback;;
+
;
return 0;
}
_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_ncurses_initscr=yes
-else
- ac_cv_lib_ncurses_initscr=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_ncurses_initscr" >&5
-$as_echo "$ac_cv_lib_ncurses_initscr" >&6; }
-if test "x$ac_cv_lib_ncurses_initscr" = xyes; then :
- AST_NCURSES_FOUND=yes
-else
- AST_NCURSES_FOUND=no
-fi
+if ac_fn_c_try_compile "$LINENO"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ PBX_LIBEDIT_IS_UNICODE=1
- CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
+$as_echo "#define HAVE_LIBEDIT_IS_UNICODE 1" >>confdefs.h
- # now check for the header.
- if test "${AST_NCURSES_FOUND}" = "yes"; then
- NCURSES_LIB="${pbxlibdir} -lncurses "
- # if --with-NCURSES=DIR has been specified, use it.
- if test "x${NCURSES_DIR}" != "x"; then
- NCURSES_INCLUDE="-I${NCURSES_DIR}/include"
- fi
- NCURSES_INCLUDE="${NCURSES_INCLUDE} "
- # check for the header
- ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
- CPPFLAGS="${CPPFLAGS} ${NCURSES_INCLUDE}"
- ac_fn_c_check_header_mongrel "$LINENO" "curses.h" "ac_cv_header_curses_h" "$ac_includes_default"
-if test "x$ac_cv_header_curses_h" = xyes; then :
- NCURSES_HEADER_FOUND=1
else
- NCURSES_HEADER_FOUND=0
-fi
-
-
- CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
-
- if test "x${NCURSES_HEADER_FOUND}" = "x0" ; then
- NCURSES_LIB=""
- NCURSES_INCLUDE=""
- else
-
- PBX_NCURSES=1
- cat >>confdefs.h <<_ACEOF
-#define HAVE_NCURSES 1
-_ACEOF
-
- fi
- fi
-fi
-
-
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
-EDITLINE_LIB=""
-if test "x$TERMCAP_LIB" != "x" ; then
- EDITLINE_LIB="$TERMCAP_LIB"
-elif test "x$TINFO_LIB" != "x" ; then
- EDITLINE_LIB="$TINFO_LIB"
-elif test "x$CURSES_LIB" != "x" ; then
- EDITLINE_LIB="$CURSES_LIB"
-elif test "x$NCURSES_LIB" != "x" ; then
- EDITLINE_LIB="$NCURSES_LIB"
-else
- as_fn_error $? "*** termcap support not found (on modern systems, this typically means the ncurses development package is missing)" "$LINENO" 5
fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CPPFLAGS="${saved_cppflags}"
+ fi
# Find required UUID support.
@@ -20695,236 +20513,6 @@ fi
fi
- if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then
-
-pkg_failed=no
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for LIBEDIT" >&5
-$as_echo_n "checking for LIBEDIT... " >&6; }
-
-if test -n "$LIBEDIT_CFLAGS"; then
- pkg_cv_LIBEDIT_CFLAGS="$LIBEDIT_CFLAGS"
- elif test -n "$PKG_CONFIG"; then
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libedit") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_LIBEDIT_CFLAGS=`$PKG_CONFIG --cflags "libedit" 2>/dev/null`
- test "x$?" != "x0" && pkg_failed=yes
-else
- pkg_failed=yes
-fi
- else
- pkg_failed=untried
-fi
-if test -n "$LIBEDIT_LIBS"; then
- pkg_cv_LIBEDIT_LIBS="$LIBEDIT_LIBS"
- elif test -n "$PKG_CONFIG"; then
- if test -n "$PKG_CONFIG" && \
- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libedit\""; } >&5
- ($PKG_CONFIG --exists --print-errors "libedit") 2>&5
- ac_status=$?
- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
- test $ac_status = 0; }; then
- pkg_cv_LIBEDIT_LIBS=`$PKG_CONFIG --libs "libedit" 2>/dev/null`
- test "x$?" != "x0" && pkg_failed=yes
-else
- pkg_failed=yes
-fi
- else
- pkg_failed=untried
-fi
-
-
-
-if test $pkg_failed = yes; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
- _pkg_short_errors_supported=yes
-else
- _pkg_short_errors_supported=no
-fi
- if test $_pkg_short_errors_supported = yes; then
- LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libedit" 2>&1`
- else
- LIBEDIT_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libedit" 2>&1`
- fi
- # Put the nasty error message in config.log where it belongs
- echo "$LIBEDIT_PKG_ERRORS" >&5
-
-
- PBX_LIBEDIT=0
-
-
-elif test $pkg_failed = untried; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
- PBX_LIBEDIT=0
-
-
-else
- LIBEDIT_CFLAGS=$pkg_cv_LIBEDIT_CFLAGS
- LIBEDIT_LIBS=$pkg_cv_LIBEDIT_LIBS
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
-
- PBX_LIBEDIT=1
- LIBEDIT_INCLUDE="$LIBEDIT_CFLAGS"
- LIBEDIT_LIB="$LIBEDIT_LIBS"
-
-$as_echo "#define HAVE_LIBEDIT 1" >>confdefs.h
-
-
-fi
- fi
-
-# some platforms do not list libedit via pkg-config, for example OpenBSD 6.2
-
-if test "x${PBX_LIBEDIT}" != "x1" -a "${USE_LIBEDIT}" != "no"; then
- pbxlibdir=""
- # if --with-LIBEDIT=DIR has been specified, use it.
- if test "x${LIBEDIT_DIR}" != "x"; then
- if test -d ${LIBEDIT_DIR}/lib; then
- pbxlibdir="-L${LIBEDIT_DIR}/lib"
- else
- pbxlibdir="-L${LIBEDIT_DIR}"
- fi
- fi
-
- ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
- CFLAGS="${CFLAGS} "
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for history_init in -ledit" >&5
-$as_echo_n "checking for history_init in -ledit... " >&6; }
-if ${ac_cv_lib_edit_history_init+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- ac_check_lib_save_LIBS=$LIBS
-LIBS="-ledit ${pbxlibdir} -ltermcap $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 history_init ();
-int
-main ()
-{
-return history_init ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_edit_history_init=yes
-else
- ac_cv_lib_edit_history_init=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_edit_history_init" >&5
-$as_echo "$ac_cv_lib_edit_history_init" >&6; }
-if test "x$ac_cv_lib_edit_history_init" = xyes; then :
- AST_LIBEDIT_FOUND=yes
-else
- AST_LIBEDIT_FOUND=no
-fi
-
- CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
-
-
- # now check for the header.
- if test "${AST_LIBEDIT_FOUND}" = "yes"; then
- LIBEDIT_LIB="${pbxlibdir} -ledit -ltermcap"
- # if --with-LIBEDIT=DIR has been specified, use it.
- if test "x${LIBEDIT_DIR}" != "x"; then
- LIBEDIT_INCLUDE="-I${LIBEDIT_DIR}/include"
- fi
- LIBEDIT_INCLUDE="${LIBEDIT_INCLUDE} "
-
- # check for the header
- ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
- CPPFLAGS="${CPPFLAGS} ${LIBEDIT_INCLUDE}"
- ac_fn_c_check_header_mongrel "$LINENO" "histedit.h" "ac_cv_header_histedit_h" "$ac_includes_default"
-if test "x$ac_cv_header_histedit_h" = xyes; then :
- LIBEDIT_HEADER_FOUND=1
-else
- LIBEDIT_HEADER_FOUND=0
-fi
-
-
- CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
-
- if test "x${LIBEDIT_HEADER_FOUND}" = "x0" ; then
- LIBEDIT_LIB=""
- LIBEDIT_INCLUDE=""
- else
-
- PBX_LIBEDIT=1
- cat >>confdefs.h <<_ACEOF
-#define HAVE_LIBEDIT 1
-_ACEOF
-
- fi
- fi
-fi
-
-
-if test "${PBX_LIBEDIT}" != 1; then
- as_fn_error $? "*** Please install the 'libedit' development package." "$LINENO" 5
- exit 1
-fi
-
- if test "x${PBX_LIBEDIT_IS_UNICODE}" != "x1" -a "${USE_LIBEDIT_IS_UNICODE}" != "no"; then
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Testing for libedit unicode support" >&5
-$as_echo_n "checking for Testing for libedit unicode support... " >&6; }
- saved_cppflags="${CPPFLAGS}"
- if test "x${LIBEDIT_IS_UNICODE_DIR}" != "x"; then
- LIBEDIT_IS_UNICODE_INCLUDE="-I${LIBEDIT_IS_UNICODE_DIR}/include"
- fi
- CPPFLAGS="${CPPFLAGS} ${LIBEDIT_IS_UNICODE_INCLUDE}"
-
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
- #include <histedit.h>
-int
-main ()
-{
- el_rfunc_t *callback;;
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
-$as_echo "yes" >&6; }
- PBX_LIBEDIT_IS_UNICODE=1
-
-$as_echo "#define HAVE_LIBEDIT_IS_UNICODE 1" >>confdefs.h
-
-
-
-else
- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
-$as_echo "no" >&6; }
-
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CPPFLAGS="${saved_cppflags}"
- fi
-
-
-
if test "x${PBX_ICONV}" != "x1" -a "${USE_ICONV}" != "no"; then
pbxlibdir=""
# if --with-ICONV=DIR has been specified, use it.
@@ -25886,102 +25474,6 @@ fi
-if test "x${PBX_PJSIP_EVSUB_SET_UAS_TIMEOUT}" != "x1" -a "${USE_PJSIP_EVSUB_SET_UAS_TIMEOUT}" != "no"; then
- pbxlibdir=""
- # if --with-PJSIP_EVSUB_SET_UAS_TIMEOUT=DIR has been specified, use it.
- if test "x${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}" != "x"; then
- if test -d ${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}/lib; then
- pbxlibdir="-L${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}/lib"
- else
- pbxlibdir="-L${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}"
- fi
- fi
-
- ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
- CFLAGS="${CFLAGS} $PJPROJECT_CFLAGS"
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pjsip_evsub_set_uas_timeout in -lpjsip" >&5
-$as_echo_n "checking for pjsip_evsub_set_uas_timeout in -lpjsip... " >&6; }
-if ${ac_cv_lib_pjsip_pjsip_evsub_set_uas_timeout+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- 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. */
-#ifdef __cplusplus
-extern "C"
-#endif
-char pjsip_evsub_set_uas_timeout ();
-int
-main ()
-{
-return pjsip_evsub_set_uas_timeout ();
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_link "$LINENO"; then :
- ac_cv_lib_pjsip_pjsip_evsub_set_uas_timeout=yes
-else
- ac_cv_lib_pjsip_pjsip_evsub_set_uas_timeout=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_pjsip_pjsip_evsub_set_uas_timeout" >&5
-$as_echo "$ac_cv_lib_pjsip_pjsip_evsub_set_uas_timeout" >&6; }
-if test "x$ac_cv_lib_pjsip_pjsip_evsub_set_uas_timeout" = xyes; then :
- AST_PJSIP_EVSUB_SET_UAS_TIMEOUT_FOUND=yes
-else
- AST_PJSIP_EVSUB_SET_UAS_TIMEOUT_FOUND=no
-fi
-
- CFLAGS="${ast_ext_lib_check_save_CFLAGS}"
-
-
- # now check for the header.
- if test "${AST_PJSIP_EVSUB_SET_UAS_TIMEOUT_FOUND}" = "yes"; then
- PJSIP_EVSUB_SET_UAS_TIMEOUT_LIB="${pbxlibdir} -lpjsip $PJPROJECT_LIB"
- # if --with-PJSIP_EVSUB_SET_UAS_TIMEOUT=DIR has been specified, use it.
- if test "x${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}" != "x"; then
- PJSIP_EVSUB_SET_UAS_TIMEOUT_INCLUDE="-I${PJSIP_EVSUB_SET_UAS_TIMEOUT_DIR}/include"
- fi
- PJSIP_EVSUB_SET_UAS_TIMEOUT_INCLUDE="${PJSIP_EVSUB_SET_UAS_TIMEOUT_INCLUDE} $PJPROJECT_CFLAGS"
-
- # check for the header
- ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
- CPPFLAGS="${CPPFLAGS} ${PJSIP_EVSUB_SET_UAS_TIMEOUT_INCLUDE}"
- ac_fn_c_check_header_mongrel "$LINENO" "pjsip.h" "ac_cv_header_pjsip_h" "$ac_includes_default"
-if test "x$ac_cv_header_pjsip_h" = xyes; then :
- PJSIP_EVSUB_SET_UAS_TIMEOUT_HEADER_FOUND=1
-else
- PJSIP_EVSUB_SET_UAS_TIMEOUT_HEADER_FOUND=0
-fi
-
-
- CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"
-
- if test "x${PJSIP_EVSUB_SET_UAS_TIMEOUT_HEADER_FOUND}" = "x0" ; then
- PJSIP_EVSUB_SET_UAS_TIMEOUT_LIB=""
- PJSIP_EVSUB_SET_UAS_TIMEOUT_INCLUDE=""
- else
-
- PBX_PJSIP_EVSUB_SET_UAS_TIMEOUT=1
- cat >>confdefs.h <<_ACEOF
-#define HAVE_PJSIP_EVSUB_SET_UAS_TIMEOUT 1
-_ACEOF
-
- fi
- fi
-fi
-
-
-
if test "x${PBX_PJSIP_TSX_LAYER_FIND_TSX2}" != "x1" -a "${USE_PJSIP_TSX_LAYER_FIND_TSX2}" != "no"; then
pbxlibdir=""
# if --with-PJSIP_TSX_LAYER_FIND_TSX2=DIR has been specified, use it.
diff --git a/configure.ac b/configure.ac
index 219f85d0c..702ff4f97 100644
--- a/configure.ac
+++ b/configure.ac
@@ -458,7 +458,6 @@ AST_EXT_LIB_SETUP([CAP], [POSIX 1.e capabilities], [cap])
AST_EXT_LIB_SETUP([CODEC2], [Codec 2 Audio Decoder/Encoder], [codec2])
AST_EXT_LIB_SETUP([COROSYNC], [Corosync], [cpg])
AST_EXT_LIB_SETUP_OPTIONAL([COROSYNC_CFG_STATE_TRACK], [A callback only in corosync 1.x], [COROSYNC], [cfg])
-AST_EXT_LIB_SETUP([CURSES], [curses], [curses])
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])
@@ -492,7 +491,6 @@ AST_EXT_LIB_SETUP([LUA], [Lua], [lua])
AST_EXT_LIB_SETUP([MISDN], [mISDN user], [misdn])
AST_EXT_LIB_SETUP([MYSQLCLIENT], [MySQL client], [mysqlclient])
AST_EXT_LIB_SETUP([NBS], [Network Broadcast Sound], [nbs])
-AST_EXT_LIB_SETUP([NCURSES], [ncurses], [ncurses])
AST_EXT_LIB_SETUP([NEON], [neon], [neon])
AST_EXT_LIB_SETUP([NEON29], [neon29], [neon29])
AST_EXT_LIB_SETUP([NETSNMP], [Net-SNMP], [netsnmp])
@@ -571,9 +569,7 @@ AST_EXT_LIB_SETUP([OPENSSL], [OpenSSL Secure Sockets Layer], [ssl])
AST_EXT_LIB_SETUP_OPTIONAL([RT], [Realtime functions], [rt])
AST_EXT_LIB_SETUP([SUPPSERV], [mISDN Supplemental Services], [suppserv])
AST_EXT_LIB_SETUP([FREETDS], [FreeTDS], [tds])
-AST_EXT_LIB_SETUP([TERMCAP], [Termcap], [termcap])
AST_EXT_LIB_SETUP([TIMERFD], [timerfd], [timerfd])
-AST_EXT_LIB_SETUP([TINFO], [Term Info], [tinfo])
AST_EXT_LIB_SETUP([TONEZONE], [tonezone], [tonezone])
AST_EXT_LIB_SETUP([UNBOUND], [unbound], [unbound])
AST_EXT_LIB_SETUP([UNIXODBC], [unixODBC], [unixodbc])
@@ -621,25 +617,15 @@ AC_CHECK_HEADERS([ \
AC_CHECK_HEADERS([arpa/inet.h libintl.h malloc.h netdb.h stddef.h strings.h sys/event.h utime.h])
-# Any one of these packages support a mandatory requirement, so we want to check on them as early as possible.
-AST_EXT_LIB_CHECK([TERMCAP], [termcap], [tgetent], [])
-AST_EXT_LIB_CHECK([TINFO], [tinfo], [tgetent], [])
-AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
-AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [curses.h])
-
-EDITLINE_LIB=""
-if test "x$TERMCAP_LIB" != "x" ; then
- EDITLINE_LIB="$TERMCAP_LIB"
-elif test "x$TINFO_LIB" != "x" ; then
- EDITLINE_LIB="$TINFO_LIB"
-elif test "x$CURSES_LIB" != "x" ; then
- EDITLINE_LIB="$CURSES_LIB"
-elif test "x$NCURSES_LIB" != "x" ; then
- EDITLINE_LIB="$NCURSES_LIB"
-else
- AC_MSG_ERROR([*** termcap support not found (on modern systems, this typically means the ncurses development package is missing)])
+# Find required NetBSD Editline library (libedit).
+AST_PKG_CONFIG_CHECK(LIBEDIT, libedit)
+# some platforms do not list libedit via pkg-config, for example OpenBSD 6.2
+AST_EXT_LIB_CHECK([LIBEDIT], [edit], [history_init], [histedit.h], [-ltermcap])
+if test "${PBX_LIBEDIT}" != 1; then
+ AC_MSG_ERROR(*** Please install the 'libedit' development package.)
+ exit 1
fi
-AC_SUBST(EDITLINE_LIB)
+AST_C_COMPILE_CHECK([LIBEDIT_IS_UNICODE], [el_rfunc_t *callback;], [histedit.h], [], [Testing for libedit unicode support])
# Find required UUID support.
# * -luuid on Linux
@@ -1599,15 +1585,6 @@ if test "${USE_ILBC}" != "no"; then
fi
fi
-AST_PKG_CONFIG_CHECK(LIBEDIT, libedit)
-# some platforms do not list libedit via pkg-config, for example OpenBSD 6.2
-AST_EXT_LIB_CHECK([LIBEDIT], [edit], [history_init], [histedit.h], [-ltermcap])
-if test "${PBX_LIBEDIT}" != 1; then
- AC_MSG_ERROR(*** Please install the 'libedit' development package.)
- exit 1
-fi
-AST_C_COMPILE_CHECK([LIBEDIT_IS_UNICODE], [el_rfunc_t *callback;], [histedit.h], [], [Testing for libedit unicode support])
-
AST_EXT_LIB_CHECK([ICONV], [iconv], [iconv_open], [iconv.h])
# GNU libiconv #define's iconv_open to libiconv_open, so we need to search for that symbol
AST_EXT_LIB_CHECK([ICONV], [iconv], [libiconv_open], [iconv.h])
@@ -2303,7 +2280,6 @@ if test "$USE_PJPROJECT" != "no" ; then
AST_EXT_LIB_CHECK([PJSIP_EVSUB_GRP_LOCK], [pjsip], [pjsip_evsub_add_ref], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
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_EVSUB_SET_UAS_TIMEOUT], [pjsip], [pjsip_evsub_set_uas_timeout], [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])
fi
fi
diff --git a/include/asterisk/_private.h b/include/asterisk/_private.h
index 431f96108..d19c58967 100644
--- a/include/asterisk/_private.h
+++ b/include/asterisk/_private.h
@@ -15,6 +15,11 @@
#ifndef _ASTERISK__PRIVATE_H
#define _ASTERISK__PRIVATE_H
+/* Load settings from asterisk.conf, provided by options.c */
+void load_asterisk_conf(void);
+void set_asterisk_conf_path(const char *path);
+void set_socket_path(const char *path);
+
int load_modules(unsigned int); /*!< Provided by loader.c */
int modules_shutdown(void); /*!< Provided by loader.c */
int load_pbx(void); /*!< Provided by pbx.c */
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index 5e9ba6011..4d1624ee3 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -185,9 +185,6 @@
/* Define to 1 if you have a functional curl library. */
#undef HAVE_CURL
-/* Define to 1 if you have the curses library. */
-#undef HAVE_CURSES
-
/* Define to 1 if your C compiler provides __atomic operations. */
#undef HAVE_C_ATOMICS
@@ -534,9 +531,6 @@
/* Define to 1 if you have the Network Broadcast Sound library. */
#undef HAVE_NBS
-/* Define to 1 if you have the ncurses library. */
-#undef HAVE_NCURSES
-
/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */
#undef HAVE_NDIR_H
@@ -1155,9 +1149,6 @@
/* Define to 1 if you have the `tanl' function. */
#undef HAVE_TANL
-/* Define to 1 if you have the Termcap library. */
-#undef HAVE_TERMCAP
-
/* Define to 1 if you have the <termios.h> header file. */
#undef HAVE_TERMIOS_H
@@ -1170,9 +1161,6 @@
/* Define to 1 if you have the <time.h> header file. */
#undef HAVE_TIME_H
-/* Define to 1 if you have the Term Info library. */
-#undef HAVE_TINFO
-
/* Define to 1 if you have the tonezone library. */
#undef HAVE_TONEZONE
diff --git a/include/asterisk/data_buffer.h b/include/asterisk/data_buffer.h
new file mode 100644
index 000000000..dacbaa5e4
--- /dev/null
+++ b/include/asterisk/data_buffer.h
@@ -0,0 +1,144 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2018, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ * Ben Ford <bford@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Data Buffer API
+ *
+ * A data buffer acts as a ring buffer of data. It is given a fixed
+ * number of data packets to store (which may be dynamically changed).
+ * Given a number it will store a data packet at that position relative
+ * to the others. Given a number it will retrieve the given data packet
+ * if it is present. This is purposely a storage of arbitrary things so
+ * that it can be used for multiple things.
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ * \author Ben Ford <bford@digium.com>
+ */
+
+#ifndef _AST_DATA_BUFFER_H_
+#define _AST_DATA_BUFFER_H_
+
+/*!
+ * \brief A buffer of data payloads.
+ */
+struct ast_data_buffer;
+
+/*!
+ * \brief A callback function to free a data payload in a data buffer
+ *
+ * \param The data payload
+ */
+typedef void (*ast_data_buffer_free_callback)(void *data);
+
+/*!
+ * \brief Allocate a data buffer
+ *
+ * \param free_fn Callback function to free a data payload
+ * \param size The maximum number of data payloads to contain in the data buffer
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note free_fn can be NULL. It is up to the consumer of this API to ensure that memory is
+ * managed appropriately.
+ *
+ * \since 15.4.0
+ */
+struct ast_data_buffer *ast_data_buffer_alloc(ast_data_buffer_free_callback free_fn, size_t size);
+
+/*!
+ * \brief Resize a data buffer
+ *
+ * \param buffer The data buffer
+ * \param size The new maximum size of the data buffer
+ *
+ * \note If the data buffer is shrunk any old data payloads will be freed using the configured callback.
+ * The data buffer is flexible and can be used for multiple purposes. Therefore it is up to the
+ * caller of the function to know whether or not a buffer should have its size changed. Increasing
+ * the size of the buffer may make sense in some scenarios, but shrinking should always be handled
+ * with caution since data can be lost.
+ *
+ * \since 15.4.0
+ */
+void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size);
+
+/*!
+ * \brief Place a data payload at a position in the data buffer
+ *
+ * \param buffer The data buffer
+ * \param pos The position of the data payload
+ * \param payload The data payload
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \note It is up to the consumer of this API to ensure proper memory management of data payloads
+ *
+ * \since 15.4.0
+ */
+int ast_data_buffer_put(struct ast_data_buffer *buffer, size_t pos, void *payload);
+
+/*!
+ * \brief Retrieve a data payload from the data buffer
+ *
+ * \param buffer The data buffer
+ * \param pos The position of the data payload
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \note This does not remove the data payload from the data buffer. It will be removed when it is displaced.
+ *
+ * \since 15.4.0
+ */
+void *ast_data_buffer_get(const struct ast_data_buffer *buffer, size_t pos);
+
+/*!
+ * \brief Free a data buffer (and all held data payloads)
+ *
+ * \param buffer The data buffer
+ *
+ * \since 15.4.0
+ */
+void ast_data_buffer_free(struct ast_data_buffer *buffer);
+
+/*!
+ * \brief Return the number of payloads in a data buffer
+ *
+ * \param buffer The data buffer
+ *
+ * \retval the number of data payloads
+ *
+ * \since 15.4.0
+ */
+size_t ast_data_buffer_count(const struct ast_data_buffer *buffer);
+
+/*!
+ * \brief Return the maximum number of payloads a data buffer can hold
+ *
+ * \param buffer The data buffer
+ *
+ * \retval the maximum number of data payloads
+ *
+ * \since 15.4.0
+ */
+size_t ast_data_buffer_max(const struct ast_data_buffer *buffer);
+
+#endif /* _AST_DATA_BUFFER_H */
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index eb6a6479a..c3c0f8817 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -127,7 +127,7 @@ enum ast_frame_type {
* directly into bridges.
*/
AST_FRAME_BRIDGE_ACTION_SYNC,
- /*! RTCP feedback */
+ /*! RTCP feedback (the subclass will contain the payload type) */
AST_FRAME_RTCP,
};
#define AST_FRAME_DTMF AST_FRAME_DTMF_END
diff --git a/include/asterisk/paths.h b/include/asterisk/paths.h
index 3e3b8eae0..de28c7575 100644
--- a/include/asterisk/paths.h
+++ b/include/asterisk/paths.h
@@ -37,5 +37,9 @@ extern const char *ast_config_AST_RUN_GROUP;
extern const char *ast_config_AST_RUN_USER;
extern const char *ast_config_AST_SYSTEM_NAME;
extern const char *ast_config_AST_SBIN_DIR;
+extern const char *ast_config_AST_CTL_PERMISSIONS;
+extern const char *ast_config_AST_CTL_OWNER;
+extern const char *ast_config_AST_CTL_GROUP;
+extern const char *ast_config_AST_CTL;
#endif /* _ASTERISK_PATHS_H */
diff --git a/include/asterisk/rtp_engine.h b/include/asterisk/rtp_engine.h
index 4e32d6b32..b552948d2 100644
--- a/include/asterisk/rtp_engine.h
+++ b/include/asterisk/rtp_engine.h
@@ -292,6 +292,14 @@ struct ast_rtp_payload_type {
#define AST_RTP_RTCP_SR 200
/*! Receiver Report */
#define AST_RTP_RTCP_RR 201
+/*! Payload Specific Feed Back (From RFC4585 also RFC5104) */
+#define AST_RTP_RTCP_PSFB 206
+
+/* Common RTCP feedback message types */
+/*! Full INTRA-frame Request (From RFC5104) */
+#define AST_RTP_RTCP_FMT_FIR 4
+/*! REMB Information (From draft-alvestrand-rmcat-remb-03) */
+#define AST_RTP_RTCP_FMT_REMB 15
/*!
* \since 12
@@ -327,6 +335,24 @@ struct ast_rtp_rtcp_report {
struct ast_rtp_rtcp_report_block *report_block[0];
};
+/*!
+ * \since 15.4.0
+ * \brief A REMB feedback message (see draft-alvestrand-rmcat-remb-03 for details) */
+struct ast_rtp_rtcp_feedback_remb {
+ unsigned int br_exp; /*!< Exponential scaling of the mantissa for the maximum total media bit rate value */
+ unsigned int br_mantissa; /*!< The mantissa of the maximum total media bit rate */
+};
+
+/*!
+ * \since 15.4.0
+ * \brief An object that represents data received in a feedback report */
+struct ast_rtp_rtcp_feedback {
+ unsigned int fmt; /*!< The feedback message type */
+ union {
+ struct ast_rtp_rtcp_feedback_remb remb; /*!< REMB feedback information */
+ };
+};
+
/*! Structure that represents statistics from an RTP instance */
struct ast_rtp_instance_stats {
/*! Number of packets transmitted */
diff --git a/main/Makefile b/main/Makefile
index fb985b9b8..bef70e966 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -57,9 +57,9 @@ ifneq ($(findstring $(OSARCH), linux-gnu uclinux linux-uclibc linux-musl kfreebs
ifneq (x$(CAP_LIB),x)
AST_LIBS+=$(CAP_LIB)
endif
- AST_LIBS+=-lpthread $(EDITLINE_LIB) -lm -lresolv
+ AST_LIBS+=-lpthread -lm -lresolv
else
- AST_LIBS+=$(EDITLINE_LIB) -lm
+ AST_LIBS+=-lm
endif
ifneq ($(findstring BETTER_BACKTRACES,$(MENUSELECT_CFLAGS)),)
@@ -90,11 +90,11 @@ ifneq ($(findstring $(OSARCH), mingw32 cygwin ),)
ASTLINK+=-shared -Wl,--out-implib,libasterisk.a
endif
ifeq ($(OSARCH),NetBSD)
- AST_LIBS+=-lpthread -lcrypto -lm -L/usr/pkg/lib $(EDITLINE_LIB)
+ AST_LIBS+=-lpthread -lcrypto -lm -L/usr/pkg/lib
endif
ifeq ($(OSARCH),OpenBSD)
- AST_LIBS+=-lcrypto -lpthread -lm $(EDITLINE_LIB)
+ AST_LIBS+=-lcrypto -lpthread -lm
endif
ifeq ($(OSARCH),SunOS)
@@ -354,7 +354,6 @@ endif
rm -f .libasteriskpj*
rm -f asterisk.exports libasteriskssl.exports libasteriskpj.exports
- @if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
@$(MAKE) -C stdtime clean
rm -f libresample/src/*.o
rm -f *.tmp
diff --git a/main/asterisk.c b/main/asterisk.c
index 6d838d0a0..665b4be84 100644
--- a/main/asterisk.c
+++ b/main/asterisk.c
@@ -294,10 +294,6 @@ int daemon(int, int); /* defined in libresolv of all places */
#define AST_MAX_CONNECTS 128
#define NUM_MSGS 64
-/*! Default minimum DTMF digit length - 80ms */
-#define AST_MIN_DTMF_DURATION 80
-
-
/*! \brief Welcome message when starting a CLI interface */
#define WELCOME_MESSAGE \
ast_verbose("Asterisk %s, Copyright (C) 1999 - 2018, Digium, Inc. and others.\n" \
@@ -308,40 +304,6 @@ int daemon(int, int); /* defined in libresolv of all places */
"certain conditions. Type 'core show license' for details.\n" \
"=========================================================================\n", ast_get_version()) \
-/*! \defgroup main_options Main Configuration Options
- * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
- * \arg \ref Config_ast "asterisk.conf"
- * \note Some of them can be changed in the CLI
- */
-/*! @{ */
-
-struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
-
-/*! Maximum active system verbosity level. */
-int ast_verb_sys_level;
-
-int option_verbose; /*!< Verbosity level */
-int option_debug; /*!< Debug level */
-int ast_pjproject_max_log_level = -1;/* Default to -1 to know if we have read the level from pjproject yet. */
-int ast_option_pjproject_log_level;
-int ast_option_pjproject_cache_pools;
-double ast_option_maxload; /*!< Max load avg on system */
-int ast_option_maxcalls; /*!< Max number of active calls */
-int ast_option_maxfiles; /*!< Max number of open file handles (files, sockets) */
-unsigned int option_dtmfminduration; /*!< Minimum duration of DTMF. */
-#if defined(HAVE_SYSINFO)
-long option_minmemfree; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
-#endif
-int ast_option_rtpusedynamic;
-unsigned int ast_option_rtpptdynamic;
-
-/*! @} */
-
-struct ast_eid ast_eid_default;
-
-/* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
-char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
-
static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
static int ast_socket_is_sd = 0; /*!< Is socket activation responsible for ast_socket? */
static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
@@ -375,8 +337,6 @@ static char *remotehostname;
struct console consoles[AST_MAX_CONNECTS];
-char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
-
static int ast_el_add_history(const char *);
static int ast_el_read_history(const char *);
static int ast_el_write_history(const char *);
@@ -386,62 +346,6 @@ static void ast_el_write_default_histfile(void);
static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
-#define DEFAULT_MONITOR_DIR DEFAULT_SPOOL_DIR "/monitor"
-#define DEFAULT_RECORDING_DIR DEFAULT_SPOOL_DIR "/recording"
-
-struct _cfg_paths {
- char config_dir[PATH_MAX];
- char module_dir[PATH_MAX];
- char spool_dir[PATH_MAX];
- char monitor_dir[PATH_MAX];
- char recording_dir[PATH_MAX];
- char var_dir[PATH_MAX];
- char data_dir[PATH_MAX];
- char log_dir[PATH_MAX];
- char agi_dir[PATH_MAX];
- char run_dir[PATH_MAX];
- char key_dir[PATH_MAX];
-
- char config_file[PATH_MAX];
- char db_path[PATH_MAX];
- char sbin_dir[PATH_MAX];
- char pid_path[PATH_MAX];
- char socket_path[PATH_MAX];
- char run_user[PATH_MAX];
- char run_group[PATH_MAX];
- char system_name[128];
-};
-
-static struct _cfg_paths cfg_paths;
-
-const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
-const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
-const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
-const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
-const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
-const char *ast_config_AST_RECORDING_DIR = cfg_paths.recording_dir;
-const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
-const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
-const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
-const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
-const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
-const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
-const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
-
-const char *ast_config_AST_DB = cfg_paths.db_path;
-const char *ast_config_AST_PID = cfg_paths.pid_path;
-const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
-const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
-const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
-const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
-
-static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
-static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
-static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
-static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
-
-extern unsigned int ast_FD_SETSIZE;
-
static char *_argv[256];
typedef enum {
@@ -1803,29 +1707,6 @@ static struct sigaction child_handler = {
.sa_flags = SA_RESTART,
};
-/*! \brief Set maximum open files */
-static void set_ulimit(int value)
-{
- struct rlimit l = {0, 0};
-
- if (value <= 0) {
- ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
- return;
- }
-
- l.rlim_cur = value;
- l.rlim_max = value;
-
- if (setrlimit(RLIMIT_NOFILE, &l)) {
- ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
- return;
- }
-
- ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
-
- return;
-}
-
/*! \brief Set an X-term or screen title */
static void set_title(char *text)
{
@@ -3441,296 +3322,6 @@ static int show_cli_help(void)
return 0;
}
-static void ast_readconfig(void)
-{
- struct ast_config *cfg;
- struct ast_variable *v;
- char hostname[MAXHOSTNAMELEN] = "";
- struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
- struct {
- unsigned int dbdir:1;
- unsigned int keydir:1;
- } found = { 0, 0 };
- /* Default to false for security */
- int live_dangerously = 0;
- int option_debug_new = 0;
- int option_verbose_new = 0;
-
- /* Set default value */
- option_dtmfminduration = AST_MIN_DTMF_DURATION;
- ast_option_rtpusedynamic = 1;
- ast_option_rtpptdynamic = 35;
-
- /* init with buildtime config */
- ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
- ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
- ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
- ast_copy_string(cfg_paths.monitor_dir, DEFAULT_MONITOR_DIR, sizeof(cfg_paths.monitor_dir));
- ast_copy_string(cfg_paths.recording_dir, DEFAULT_RECORDING_DIR, sizeof(cfg_paths.recording_dir));
- ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
- ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
- ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
- ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
- ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
- ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
- ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
- ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
- ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
- ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
-
-#ifdef REF_DEBUG
- /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
- * Support for debugging reference counts is always compiled in. */
- ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
-#endif
-
- ast_set_default_eid(&ast_eid_default);
-
- cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
-
- /* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
- * Using #exec from other configs requires that it be enabled from asterisk.conf. */
- ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
-
- /* no asterisk.conf? no problem, use buildtime config! */
- if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
- fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
- return;
- }
-
- for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
- if (!strcasecmp(v->name, "astctlpermissions"))
- ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
- else if (!strcasecmp(v->name, "astctlowner"))
- ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
- else if (!strcasecmp(v->name, "astctlgroup"))
- ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
- else if (!strcasecmp(v->name, "astctl"))
- ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
- }
-
- for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
- if (!strcasecmp(v->name, "astetcdir")) {
- ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
- } else if (!strcasecmp(v->name, "astspooldir")) {
- ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
- snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
- snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
- } else if (!strcasecmp(v->name, "astvarlibdir")) {
- ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
- if (!found.dbdir)
- snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
- } else if (!strcasecmp(v->name, "astdbdir")) {
- snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
- found.dbdir = 1;
- } else if (!strcasecmp(v->name, "astdatadir")) {
- ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
- if (!found.keydir)
- snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
- } else if (!strcasecmp(v->name, "astkeydir")) {
- snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
- found.keydir = 1;
- } else if (!strcasecmp(v->name, "astlogdir")) {
- ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
- } else if (!strcasecmp(v->name, "astagidir")) {
- ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
- } else if (!strcasecmp(v->name, "astrundir")) {
- snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
- ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
- } else if (!strcasecmp(v->name, "astmoddir")) {
- ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
- } else if (!strcasecmp(v->name, "astsbindir")) {
- ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
- }
- }
-
- /* Combine astrundir and astctl settings. */
- snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s",
- ast_config_AST_RUN_DIR, ast_config_AST_CTL);
-
- for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
- /* verbose level (-v at startup) */
- if (!strcasecmp(v->name, "verbose")) {
- option_verbose_new = atoi(v->value);
- /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
- } else if (!strcasecmp(v->name, "timestamp")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
- /* whether or not to support #exec in config files */
- } else if (!strcasecmp(v->name, "execincludes")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
- /* debug level (-d at startup) */
- } else if (!strcasecmp(v->name, "debug")) {
- option_debug_new = 0;
- if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
- option_debug_new = ast_true(v->value) ? 1 : 0;
- }
- } else if (!strcasecmp(v->name, "refdebug")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
-#if HAVE_WORKING_FORK
- /* Disable forking (-f at startup) */
- } else if (!strcasecmp(v->name, "nofork")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
- /* Always fork, even if verbose or debug are enabled (-F at startup) */
- } else if (!strcasecmp(v->name, "alwaysfork")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
-#endif
- /* Run quietly (-q at startup ) */
- } else if (!strcasecmp(v->name, "quiet")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
- /* Run as console (-c at startup, implies nofork) */
- } else if (!strcasecmp(v->name, "console")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
- /* Run with high priority if the O/S permits (-p at startup) */
- } else if (!strcasecmp(v->name, "highpriority")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
- /* Initialize RSA auth keys (IAX2) (-i at startup) */
- } else if (!strcasecmp(v->name, "initcrypto")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
- /* Disable ANSI colors for console (-c at startup) */
- } else if (!strcasecmp(v->name, "nocolor")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
- /* Disable some usage warnings for picky people :p */
- } else if (!strcasecmp(v->name, "dontwarn")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
- /* Dump core in case of crash (-g) */
- } else if (!strcasecmp(v->name, "dumpcore")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
- /* Cache recorded sound files to another directory during recording */
- } else if (!strcasecmp(v->name, "cache_record_files")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
-#if !defined(LOW_MEMORY)
- /* Cache media frames for performance */
- } else if (!strcasecmp(v->name, "cache_media_frames")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);
-#endif
- /* Specify cache directory */
- } else if (!strcasecmp(v->name, "record_cache_dir")) {
- ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
- /* Build transcode paths via SLINEAR, instead of directly */
- } else if (!strcasecmp(v->name, "transcode_via_sln")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
- /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
- } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
- /* Enable internal timing */
- } else if (!strcasecmp(v->name, "internal_timing")) {
- if (!ast_opt_remote) {
- fprintf(stderr,
- "NOTICE: The internal_timing option is no longer needed.\n"
- " It will always be enabled if you have a timing module loaded.\n");
- }
- } else if (!strcasecmp(v->name, "mindtmfduration")) {
- if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
- option_dtmfminduration = AST_MIN_DTMF_DURATION;
- }
- } else if (!strcasecmp(v->name, "rtp_use_dynamic")) {
- ast_option_rtpusedynamic = ast_true(v->value);
- /* http://www.iana.org/assignments/rtp-parameters
- * RTP dynamic payload types start at 96 normally; extend down to 0 */
- } else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
- ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
- &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
- } else if (!strcasecmp(v->name, "maxcalls")) {
- if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
- ast_option_maxcalls = 0;
- }
- } else if (!strcasecmp(v->name, "maxload")) {
- double test[1];
-
- if (getloadavg(test, 1) == -1) {
- ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
- ast_option_maxload = 0.0;
- } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
- ast_option_maxload = 0.0;
- }
- /* Set the maximum amount of open files */
- } else if (!strcasecmp(v->name, "maxfiles")) {
- ast_option_maxfiles = atoi(v->value);
- if (!ast_opt_remote) {
- set_ulimit(ast_option_maxfiles);
- }
- /* What user to run as */
- } else if (!strcasecmp(v->name, "runuser")) {
- ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
- /* What group to run as */
- } else if (!strcasecmp(v->name, "rungroup")) {
- ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
- } else if (!strcasecmp(v->name, "systemname")) {
- ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
- } else if (!strcasecmp(v->name, "autosystemname")) {
- if (ast_true(v->value)) {
- if (!gethostname(hostname, sizeof(hostname) - 1))
- ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
- else {
- if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
- ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
- }
- ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
- }
- }
- } else if (!strcasecmp(v->name, "languageprefix")) {
- ast_language_is_prefix = ast_true(v->value);
- } else if (!strcasecmp(v->name, "defaultlanguage")) {
- ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
- } else if (!strcasecmp(v->name, "lockmode")) {
- if (!strcasecmp(v->value, "lockfile")) {
- ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
- } else if (!strcasecmp(v->value, "flock")) {
- ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
- } else {
- ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
- "defaulting to 'lockfile'\n", v->value);
- ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
- }
-#if defined(HAVE_SYSINFO)
- } else if (!strcasecmp(v->name, "minmemfree")) {
- /* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
- * if the amount of free memory falls below this watermark */
- if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
- option_minmemfree = 0;
- }
-#endif
- } else if (!strcasecmp(v->name, "entityid")) {
- struct ast_eid tmp_eid;
- if (!ast_str_to_eid(&tmp_eid, v->value)) {
- ast_eid_default = tmp_eid;
- } else {
- ast_log(LOG_WARNING, "Invalid Entity ID '%s' provided\n", v->value);
- }
- } else if (!strcasecmp(v->name, "lightbackground")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
- } else if (!strcasecmp(v->name, "forceblackbackground")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
- } else if (!strcasecmp(v->name, "hideconnect")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
- } else if (!strcasecmp(v->name, "lockconfdir")) {
- ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
- } else if (!strcasecmp(v->name, "stdexten")) {
- /* Choose how to invoke the extensions.conf stdexten */
- if (!strcasecmp(v->value, "gosub")) {
- ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
- } else if (!strcasecmp(v->value, "macro")) {
- ast_set_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
- } else {
- ast_log(LOG_WARNING,
- "'%s' is not a valid setting for the stdexten option, defaulting to 'gosub'\n",
- v->value);
- ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
- }
- } else if (!strcasecmp(v->name, "live_dangerously")) {
- live_dangerously = ast_true(v->value);
- }
- }
- if (!ast_opt_remote) {
- pbx_live_dangerously(live_dangerously);
- }
-
- option_debug += option_debug_new;
- option_verbose += option_verbose_new;
-
- ast_config_destroy(cfg);
-}
-
static void read_pjproject_startup_options(void)
{
struct ast_config *cfg;
@@ -3915,9 +3506,6 @@ int main(int argc, char *argv[])
}
ast_mainpid = getpid();
- /* Set config file to default before checking arguments for override. */
- ast_copy_string(cfg_paths.config_file, DEFAULT_CONFIG_FILE, sizeof(cfg_paths.config_file));
-
/* Process command-line options that effect asterisk.conf load. */
while ((c = getopt(argc, argv, getopt_settings)) != -1) {
switch (c) {
@@ -3925,7 +3513,7 @@ int main(int argc, char *argv[])
ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
break;
case 'C':
- ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
+ set_asterisk_conf_path(optarg);
break;
case 'd':
option_debug++;
@@ -3954,7 +3542,7 @@ int main(int argc, char *argv[])
/* Initialize env so it is available if #exec is used in asterisk.conf. */
env_init();
- ast_readconfig();
+ load_asterisk_conf();
/* Update env to include any systemname that was set. */
env_init();
@@ -3963,7 +3551,7 @@ int main(int argc, char *argv[])
*
* \todo Document these options
*/
- optind = 0;
+ optind = 1;
while ((c = getopt(argc, argv, getopt_settings)) != -1) {
/*!\note Please keep the ordering here to alphabetical, capital letters
* first. This will make it easier in the future to select unused
@@ -4047,7 +3635,7 @@ int main(int argc, char *argv[])
break;
case 's':
if (ast_opt_remote) {
- ast_copy_string((char *) cfg_paths.socket_path, optarg, sizeof(cfg_paths.socket_path));
+ set_socket_path(optarg);
}
break;
case 'T':
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index 89e55713f..3aac5eb25 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -653,7 +653,8 @@ static int bridge_channel_write_frame(struct ast_bridge_channel *bridge_channel,
case AST_FRAME_VIDEO:
case AST_FRAME_TEXT:
case AST_FRAME_IMAGE:
- /* Media frames need to be mapped to an appropriate write stream */
+ case AST_FRAME_RTCP:
+ /* These frames need to be mapped to an appropriate write stream */
if (frame->stream_num < 0) {
/* Map to default stream */
frame->stream_num = -1;
diff --git a/main/channel.c b/main/channel.c
index 869b29f5e..815d5dbfe 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -4123,8 +4123,7 @@ static struct ast_frame *__ast_read(struct ast_channel *chan, int dropaudio, int
if (ast_channel_writetrans(chan)) {
ast_translate(ast_channel_writetrans(chan), f, 0);
}
- ast_frfree(f);
- f = &ast_null_frame;
+ break;
default:
/* Just pass it on! */
break;
@@ -5267,6 +5266,14 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame
/* Ignore these */
res = 0;
break;
+ case AST_FRAME_RTCP:
+ /* RTCP information is on a per-stream basis and only available on multistream capable channels */
+ if (ast_channel_tech(chan)->write_stream && stream) {
+ res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr);
+ } else {
+ res = 0;
+ }
+ break;
default:
/* At this point, fr is the incoming frame and f is NULL. Channels do
* not expect to get NULL as a frame pointer and will segfault. Hence,
diff --git a/main/data_buffer.c b/main/data_buffer.c
new file mode 100644
index 000000000..ccbffd22d
--- /dev/null
+++ b/main/data_buffer.c
@@ -0,0 +1,314 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2018, Digium, Inc.
+ *
+ * Joshua Colp <jcolp@digium.com>
+ * Ben Ford <bford@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Data Buffer API
+ *
+ * \author Joshua Colp <jcolp@digium.com>
+ * \author Ben Ford <bford@digium.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/logger.h"
+#include "asterisk/strings.h"
+#include "asterisk/data_buffer.h"
+#include "asterisk/linkedlists.h"
+
+/*!
+ * \brief The number of payloads to increment the cache by
+ */
+#define CACHED_PAYLOAD_MAX 5
+
+/*!
+ * \brief Payload entry placed inside of the data buffer list
+ */
+struct data_buffer_payload_entry {
+ /*! \brief The payload for this position */
+ void *payload;
+ /*! \brief The provided position for this */
+ size_t pos;
+ /*! \brief Linked list information */
+ AST_LIST_ENTRY(data_buffer_payload_entry) list;
+};
+
+/*!
+ * \brief Data buffer containing fixed number of data payloads
+ */
+struct ast_data_buffer {
+ /*! \brief Callback function to free a data payload */
+ ast_data_buffer_free_callback free_fn;
+ /*! \brief A linked list of data payloads */
+ AST_LIST_HEAD_NOLOCK(, data_buffer_payload_entry) payloads;
+ /*! \brief A linked list of unused cached data payloads */
+ AST_LIST_HEAD_NOLOCK(, data_buffer_payload_entry) cached_payloads;
+ /*! \brief The current number of data payloads in the buffer */
+ size_t count;
+ /*! \brief Maximum number of data payloads in the buffer */
+ size_t max;
+ /*! \brief The current number of data payloads in the cache */
+ size_t cache_count;
+};
+
+static void free_fn_do_nothing(void *data)
+{
+ return;
+}
+
+/*!
+ * \brief Helper function to allocate a data payload
+ */
+static struct data_buffer_payload_entry *data_buffer_payload_alloc(void *payload, size_t pos)
+{
+ struct data_buffer_payload_entry *data_payload;
+
+ data_payload = ast_calloc(1, sizeof(*data_payload));
+ if (!data_payload) {
+ return NULL;
+ }
+
+ data_payload->payload = payload;
+ data_payload->pos = pos;
+
+ return data_payload;
+}
+
+/*!
+ * \brief Helper function that sets the cache to its maximum number of payloads
+ */
+static void ast_data_buffer_cache_adjust(struct ast_data_buffer *buffer)
+{
+ int buffer_space;
+
+ ast_assert(buffer != NULL);
+
+ buffer_space = buffer->max - buffer->count;
+
+ if (buffer->cache_count == buffer_space) {
+ return;
+ }
+
+ if (buffer->cache_count < buffer_space) {
+ /* Add payloads to the cache, if able */
+ while (buffer->cache_count < CACHED_PAYLOAD_MAX && buffer->cache_count < buffer_space) {
+ struct data_buffer_payload_entry *buffer_payload;
+
+ buffer_payload = data_buffer_payload_alloc(NULL, -1);
+ if (buffer_payload) {
+ AST_LIST_INSERT_TAIL(&buffer->cached_payloads, buffer_payload, list);
+ buffer->cache_count++;
+ continue;
+ }
+
+ ast_log(LOG_ERROR, "Failed to allocate memory to the cache.");
+ break;
+ }
+ } else if (buffer->cache_count > buffer_space) {
+ /* Remove payloads from the cache */
+ while (buffer->cache_count > buffer_space) {
+ struct data_buffer_payload_entry *buffer_payload;
+
+ buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->cached_payloads, list);
+ if (buffer_payload) {
+ ast_free(buffer_payload);
+ buffer->cache_count--;
+ continue;
+ }
+
+ ast_log(LOG_ERROR, "Failed to remove memory from the cache.");
+ break;
+ }
+ }
+}
+
+struct ast_data_buffer *ast_data_buffer_alloc(ast_data_buffer_free_callback free_fn, size_t size)
+{
+ struct ast_data_buffer *buffer;
+
+ ast_assert(size != 0);
+
+ buffer = ast_calloc(1, sizeof(*buffer));
+ if (!buffer) {
+ return NULL;
+ }
+
+ AST_LIST_HEAD_INIT_NOLOCK(&buffer->payloads);
+ AST_LIST_HEAD_INIT_NOLOCK(&buffer->cached_payloads);
+
+ /* If free_fn is NULL, just use free_fn_do_nothing as a default */
+ buffer->free_fn = free_fn ? free_fn : free_fn_do_nothing;
+ buffer->max = size;
+
+ ast_data_buffer_cache_adjust(buffer);
+
+ return buffer;
+}
+
+void ast_data_buffer_resize(struct ast_data_buffer *buffer, size_t size)
+{
+ struct data_buffer_payload_entry *existing_payload;
+
+ ast_assert(buffer != NULL);
+
+ /* The buffer must have at least a size of 1 */
+ ast_assert(size > 0);
+
+ if (buffer->max == size) {
+ return;
+ }
+
+ /* If the size is decreasing, some payloads will need to be freed */
+ if (buffer->max > size) {
+ int remove = buffer->max - size;
+
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&buffer->payloads, existing_payload, list) {
+ if (remove) {
+ AST_LIST_REMOVE_HEAD(&buffer->payloads, list);
+ buffer->free_fn(existing_payload->payload);
+ ast_free(existing_payload);
+ buffer->count--;
+ remove--;
+ continue;
+ }
+ break;
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ }
+
+ buffer->max = size;
+ ast_data_buffer_cache_adjust(buffer);
+}
+
+int ast_data_buffer_put(struct ast_data_buffer *buffer, size_t pos, void *payload)
+{
+ struct data_buffer_payload_entry *buffer_payload = NULL;
+ struct data_buffer_payload_entry *existing_payload;
+ int inserted = 0;
+
+ ast_assert(buffer != NULL);
+ ast_assert(payload != NULL);
+
+ /* If the data buffer has reached its maximum size then the head goes away and
+ * we will reuse its buffer payload
+ */
+ if (buffer->count == buffer->max) {
+ buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->payloads, list);
+ buffer->free_fn(buffer_payload->payload);
+ buffer->count--;
+
+ /* Update this buffer payload with its new information */
+ buffer_payload->payload = payload;
+ buffer_payload->pos = pos;
+ }
+ if (!buffer_payload) {
+ if (!buffer->cache_count) {
+ ast_data_buffer_cache_adjust(buffer);
+ }
+ buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->cached_payloads, list);
+ buffer->cache_count--;
+
+ /* Update the payload from the cache with its new information */
+ buffer_payload->payload = payload;
+ buffer_payload->pos = pos;
+ }
+ if (!buffer_payload) {
+ return -1;
+ }
+
+ /* Given the position find its ideal spot within the buffer */
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&buffer->payloads, existing_payload, list) {
+ /* If it's already in the buffer, drop it */
+ if (existing_payload->pos == pos) {
+ ast_debug(3, "Packet with position %zu is already in buffer. Not inserting.\n", pos);
+ inserted = -1;
+ break;
+ }
+
+ if (existing_payload->pos > pos) {
+ AST_LIST_INSERT_BEFORE_CURRENT(buffer_payload, list);
+ inserted = 1;
+ break;
+ }
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+
+ if (inserted == -1) {
+ return 0;
+ }
+
+ if (!inserted) {
+ AST_LIST_INSERT_TAIL(&buffer->payloads, buffer_payload, list);
+ }
+
+ buffer->count++;
+
+ return 0;
+}
+
+void *ast_data_buffer_get(const struct ast_data_buffer *buffer, size_t pos)
+{
+ struct data_buffer_payload_entry *buffer_payload;
+
+ ast_assert(buffer != NULL);
+
+ AST_LIST_TRAVERSE(&buffer->payloads, buffer_payload, list) {
+ if (buffer_payload->pos == pos) {
+ return buffer_payload->payload;
+ }
+ }
+
+ return NULL;
+}
+
+void ast_data_buffer_free(struct ast_data_buffer *buffer)
+{
+ struct data_buffer_payload_entry *buffer_payload;
+
+ ast_assert(buffer != NULL);
+
+ while ((buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->payloads, list))) {
+ buffer->free_fn(buffer_payload->payload);
+ ast_free(buffer_payload);
+ }
+
+ while ((buffer_payload = AST_LIST_REMOVE_HEAD(&buffer->cached_payloads, list))) {
+ ast_free(buffer_payload);
+ }
+
+ ast_free(buffer);
+}
+
+size_t ast_data_buffer_count(const struct ast_data_buffer *buffer)
+{
+ ast_assert(buffer != NULL);
+
+ return buffer->count;
+}
+
+size_t ast_data_buffer_max(const struct ast_data_buffer *buffer)
+{
+ ast_assert(buffer != NULL);
+
+ return buffer->max;
+}
diff --git a/main/indications.c b/main/indications.c
index 9b0976809..c9f02416f 100644
--- a/main/indications.c
+++ b/main/indications.c
@@ -632,9 +632,7 @@ static struct ast_tone_zone *ast_tone_zone_alloc(void)
static char *complete_country(struct ast_cli_args *a)
{
- char *res = NULL;
struct ao2_iterator i;
- int which = 0;
size_t wordlen;
struct ast_tone_zone *tz;
@@ -642,17 +640,17 @@ static char *complete_country(struct ast_cli_args *a)
i = ao2_iterator_init(ast_tone_zones, 0);
while ((tz = ao2_iterator_next(&i))) {
- if (!strncasecmp(a->word, tz->country, wordlen) && ++which > a->n) {
- res = ast_strdup(tz->country);
- }
- tz = ast_tone_zone_unref(tz);
- if (res) {
- break;
+ if (!strncasecmp(a->word, tz->country, wordlen)) {
+ if (ast_cli_completion_add(ast_strdup(tz->country))) {
+ ast_tone_zone_unref(tz);
+ break;
+ }
}
+ ast_tone_zone_unref(tz);
}
ao2_iterator_destroy(&i);
- return res;
+ return NULL;
}
static char *handle_cli_indication_add(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
@@ -718,17 +716,17 @@ static char *handle_cli_indication_add(struct ast_cli_entry *e, int cmd, struct
static char *complete_indications(struct ast_cli_args *a)
{
- char *res = NULL;
- int which = 0;
size_t wordlen;
struct ast_tone_zone_sound *ts;
- struct ast_tone_zone *tz, tmp_tz = {
+ struct ast_tone_zone *tz;
+ struct ast_tone_zone tmp_tz = {
.nrringcadence = 0,
};
ast_copy_string(tmp_tz.country, a->argv[a->pos - 1], sizeof(tmp_tz.country));
- if (!(tz = ao2_find(ast_tone_zones, &tmp_tz, OBJ_POINTER))) {
+ tz = ao2_find(ast_tone_zones, &tmp_tz, OBJ_POINTER);
+ if (!tz) {
return NULL;
}
@@ -736,16 +734,17 @@ static char *complete_indications(struct ast_cli_args *a)
ast_tone_zone_lock(tz);
AST_LIST_TRAVERSE(&tz->tones, ts, entry) {
- if (!strncasecmp(a->word, ts->name, wordlen) && ++which > a->n) {
- res = ast_strdup(ts->name);
- break;
+ if (!strncasecmp(a->word, ts->name, wordlen)) {
+ if (ast_cli_completion_add(ast_strdup(ts->name))) {
+ break;
+ }
}
}
ast_tone_zone_unlock(tz);
tz = ast_tone_zone_unref(tz);
- return res;
+ return NULL;
}
static char *handle_cli_indication_remove(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
diff --git a/main/options.c b/main/options.c
new file mode 100644
index 000000000..f6a4e8fd0
--- /dev/null
+++ b/main/options.c
@@ -0,0 +1,475 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2018, CFWare, LLC
+ *
+ * Corey Farrell <git@cfware.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Symbols related to asterisk.conf options and paths.
+ *
+ * \author Corey Farrell <git@cfware.com>
+ */
+
+/*** MODULEINFO
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+#include "asterisk/_private.h"
+#include "asterisk/app.h"
+#include "asterisk/config.h"
+#include "asterisk/logger.h"
+#include "asterisk/options.h"
+#include "asterisk/paths.h"
+#include "asterisk/pbx.h"
+#include "asterisk/rtp_engine.h"
+#include "asterisk/strings.h"
+#include "asterisk/utils.h"
+
+#include "../defaults.h"
+
+#include <sys/time.h>
+#include <sys/resource.h>
+
+
+/*! Default minimum DTMF digit length - 80ms */
+#define AST_MIN_DTMF_DURATION 80
+
+#define DEFAULT_MONITOR_DIR DEFAULT_SPOOL_DIR "/monitor"
+#define DEFAULT_RECORDING_DIR DEFAULT_SPOOL_DIR "/recording"
+
+/*! \defgroup main_options Main Configuration Options
+ * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
+ * \arg \ref Config_ast "asterisk.conf"
+ * \note Some of them can be changed in the CLI
+ */
+/*! @{ */
+
+struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
+
+/*! Maximum active system verbosity level. */
+int ast_verb_sys_level;
+
+/*! Verbosity level */
+int option_verbose;
+/*! Debug level */
+int option_debug;
+/*! Default to -1 to know if we have read the level from pjproject yet. */
+int ast_pjproject_max_log_level = -1;
+int ast_option_pjproject_log_level;
+int ast_option_pjproject_cache_pools;
+/*! Max load avg on system */
+double ast_option_maxload;
+/*! Max number of active calls */
+int ast_option_maxcalls;
+/*! Max number of open file handles (files, sockets) */
+int ast_option_maxfiles;
+/*! Minimum duration of DTMF. */
+unsigned int option_dtmfminduration = AST_MIN_DTMF_DURATION;
+#if defined(HAVE_SYSINFO)
+/*! Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
+long option_minmemfree;
+#endif
+int ast_option_rtpusedynamic = 1;
+unsigned int ast_option_rtpptdynamic = 35;
+
+/*! @} */
+
+struct ast_eid ast_eid_default;
+
+/* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
+char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
+
+char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
+
+struct _cfg_paths {
+ char config_dir[PATH_MAX];
+ char module_dir[PATH_MAX];
+ char spool_dir[PATH_MAX];
+ char monitor_dir[PATH_MAX];
+ char recording_dir[PATH_MAX];
+ char var_dir[PATH_MAX];
+ char data_dir[PATH_MAX];
+ char log_dir[PATH_MAX];
+ char agi_dir[PATH_MAX];
+ char run_dir[PATH_MAX];
+ char key_dir[PATH_MAX];
+
+ char config_file[PATH_MAX];
+ char db_path[PATH_MAX];
+ char sbin_dir[PATH_MAX];
+ char pid_path[PATH_MAX];
+ char socket_path[PATH_MAX];
+ char run_user[PATH_MAX];
+ char run_group[PATH_MAX];
+ char system_name[128];
+ char ctl_perms[PATH_MAX];
+ char ctl_owner[PATH_MAX];
+ char ctl_group[PATH_MAX];
+ char ctl_file[PATH_MAX];
+};
+
+static struct _cfg_paths cfg_paths = {
+ .config_dir = DEFAULT_CONFIG_DIR,
+ .module_dir = DEFAULT_MODULE_DIR,
+ .spool_dir = DEFAULT_SPOOL_DIR,
+ .monitor_dir = DEFAULT_MONITOR_DIR,
+ .recording_dir = DEFAULT_RECORDING_DIR,
+ .var_dir = DEFAULT_VAR_DIR,
+ .data_dir = DEFAULT_DATA_DIR,
+ .log_dir = DEFAULT_LOG_DIR,
+ .agi_dir = DEFAULT_AGI_DIR,
+ .run_dir = DEFAULT_RUN_DIR,
+ .key_dir = DEFAULT_KEY_DIR,
+
+ .config_file = DEFAULT_CONFIG_FILE,
+ .db_path = DEFAULT_DB,
+ .sbin_dir = DEFAULT_SBIN_DIR,
+ .pid_path = DEFAULT_PID,
+ .socket_path = DEFAULT_SOCKET,
+ .ctl_file = "asterisk.ctl",
+};
+
+const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
+const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
+const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
+const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
+const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
+const char *ast_config_AST_RECORDING_DIR = cfg_paths.recording_dir;
+const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
+const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
+const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
+const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
+const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
+const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
+const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
+
+const char *ast_config_AST_DB = cfg_paths.db_path;
+const char *ast_config_AST_PID = cfg_paths.pid_path;
+const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
+const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
+const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
+const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
+
+const char *ast_config_AST_CTL_PERMISSIONS = cfg_paths.ctl_perms;
+const char *ast_config_AST_CTL_OWNER = cfg_paths.ctl_owner;
+const char *ast_config_AST_CTL_GROUP = cfg_paths.ctl_group;
+const char *ast_config_AST_CTL = cfg_paths.ctl_file;
+
+/*! \brief Set maximum open files */
+static void set_ulimit(int value)
+{
+ struct rlimit l = {0, 0};
+
+ if (value <= 0) {
+ ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
+ return;
+ }
+
+ l.rlim_cur = value;
+ l.rlim_max = value;
+
+ if (setrlimit(RLIMIT_NOFILE, &l)) {
+ ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
+ return;
+ }
+
+ ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
+
+ return;
+}
+
+void set_asterisk_conf_path(const char *path)
+{
+ ast_copy_string(cfg_paths.config_file, path, sizeof(cfg_paths.config_file));
+}
+
+void set_socket_path(const char *path)
+{
+ ast_copy_string(cfg_paths.socket_path, path, sizeof(cfg_paths.socket_path));
+}
+
+void load_asterisk_conf(void)
+{
+ struct ast_config *cfg;
+ struct ast_variable *v;
+ char hostname[MAXHOSTNAMELEN] = "";
+ struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
+ struct {
+ unsigned int dbdir:1;
+ unsigned int keydir:1;
+ } found = { 0, 0 };
+ /* Default to false for security */
+ int live_dangerously = 0;
+ int option_debug_new = 0;
+ int option_verbose_new = 0;
+
+ /* init with buildtime config */
+#ifdef REF_DEBUG
+ /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
+ * Support for debugging reference counts is always compiled in. */
+ ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
+#endif
+
+ ast_set_default_eid(&ast_eid_default);
+
+ cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
+
+ /* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
+ * Using #exec from other configs requires that it be enabled from asterisk.conf. */
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
+
+ /* no asterisk.conf? no problem, use buildtime config! */
+ if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
+ fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
+ return;
+ }
+
+ for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
+ if (!strcasecmp(v->name, "astctlpermissions")) {
+ ast_copy_string(cfg_paths.ctl_perms, v->value, sizeof(cfg_paths.ctl_perms));
+ } else if (!strcasecmp(v->name, "astctlowner")) {
+ ast_copy_string(cfg_paths.ctl_owner, v->value, sizeof(cfg_paths.ctl_owner));
+ } else if (!strcasecmp(v->name, "astctlgroup")) {
+ ast_copy_string(cfg_paths.ctl_group, v->value, sizeof(cfg_paths.ctl_group));
+ } else if (!strcasecmp(v->name, "astctl")) {
+ ast_copy_string(cfg_paths.ctl_file, v->value, sizeof(cfg_paths.ctl_file));
+ }
+ }
+
+ for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
+ if (!strcasecmp(v->name, "astetcdir")) {
+ ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
+ } else if (!strcasecmp(v->name, "astspooldir")) {
+ ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
+ snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
+ snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
+ } else if (!strcasecmp(v->name, "astvarlibdir")) {
+ ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
+ if (!found.dbdir) {
+ snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
+ }
+ } else if (!strcasecmp(v->name, "astdbdir")) {
+ snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
+ found.dbdir = 1;
+ } else if (!strcasecmp(v->name, "astdatadir")) {
+ ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
+ if (!found.keydir) {
+ snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
+ }
+ } else if (!strcasecmp(v->name, "astkeydir")) {
+ snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
+ found.keydir = 1;
+ } else if (!strcasecmp(v->name, "astlogdir")) {
+ ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
+ } else if (!strcasecmp(v->name, "astagidir")) {
+ ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
+ } else if (!strcasecmp(v->name, "astrundir")) {
+ snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
+ ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
+ } else if (!strcasecmp(v->name, "astmoddir")) {
+ ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
+ } else if (!strcasecmp(v->name, "astsbindir")) {
+ ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
+ }
+ }
+
+ /* Combine astrundir and astctl settings. */
+ snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s",
+ ast_config_AST_RUN_DIR, ast_config_AST_CTL);
+
+ for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
+ /* verbose level (-v at startup) */
+ if (!strcasecmp(v->name, "verbose")) {
+ option_verbose_new = atoi(v->value);
+ /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
+ } else if (!strcasecmp(v->name, "timestamp")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
+ /* whether or not to support #exec in config files */
+ } else if (!strcasecmp(v->name, "execincludes")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
+ /* debug level (-d at startup) */
+ } else if (!strcasecmp(v->name, "debug")) {
+ option_debug_new = 0;
+ if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
+ option_debug_new = ast_true(v->value) ? 1 : 0;
+ }
+ } else if (!strcasecmp(v->name, "refdebug")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
+#if HAVE_WORKING_FORK
+ /* Disable forking (-f at startup) */
+ } else if (!strcasecmp(v->name, "nofork")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
+ /* Always fork, even if verbose or debug are enabled (-F at startup) */
+ } else if (!strcasecmp(v->name, "alwaysfork")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
+#endif
+ /* Run quietly (-q at startup ) */
+ } else if (!strcasecmp(v->name, "quiet")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
+ /* Run as console (-c at startup, implies nofork) */
+ } else if (!strcasecmp(v->name, "console")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
+ /* Run with high priority if the O/S permits (-p at startup) */
+ } else if (!strcasecmp(v->name, "highpriority")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
+ /* Initialize RSA auth keys (IAX2) (-i at startup) */
+ } else if (!strcasecmp(v->name, "initcrypto")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
+ /* Disable ANSI colors for console (-c at startup) */
+ } else if (!strcasecmp(v->name, "nocolor")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
+ /* Disable some usage warnings for picky people :p */
+ } else if (!strcasecmp(v->name, "dontwarn")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
+ /* Dump core in case of crash (-g) */
+ } else if (!strcasecmp(v->name, "dumpcore")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
+ /* Cache recorded sound files to another directory during recording */
+ } else if (!strcasecmp(v->name, "cache_record_files")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
+#if !defined(LOW_MEMORY)
+ /* Cache media frames for performance */
+ } else if (!strcasecmp(v->name, "cache_media_frames")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);
+#endif
+ /* Specify cache directory */
+ } else if (!strcasecmp(v->name, "record_cache_dir")) {
+ ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
+ /* Build transcode paths via SLINEAR, instead of directly */
+ } else if (!strcasecmp(v->name, "transcode_via_sln")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
+ /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
+ } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
+ /* Enable internal timing */
+ } else if (!strcasecmp(v->name, "internal_timing")) {
+ if (!ast_opt_remote) {
+ fprintf(stderr,
+ "NOTICE: The internal_timing option is no longer needed.\n"
+ " It will always be enabled if you have a timing module loaded.\n");
+ }
+ } else if (!strcasecmp(v->name, "mindtmfduration")) {
+ if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
+ option_dtmfminduration = AST_MIN_DTMF_DURATION;
+ }
+ } else if (!strcasecmp(v->name, "rtp_use_dynamic")) {
+ ast_option_rtpusedynamic = ast_true(v->value);
+ /* http://www.iana.org/assignments/rtp-parameters
+ * RTP dynamic payload types start at 96 normally; extend down to 0 */
+ } else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
+ ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
+ &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
+ } else if (!strcasecmp(v->name, "maxcalls")) {
+ if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
+ ast_option_maxcalls = 0;
+ }
+ } else if (!strcasecmp(v->name, "maxload")) {
+ double test[1];
+
+ if (getloadavg(test, 1) == -1) {
+ ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
+ ast_option_maxload = 0.0;
+ } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
+ ast_option_maxload = 0.0;
+ }
+ /* Set the maximum amount of open files */
+ } else if (!strcasecmp(v->name, "maxfiles")) {
+ ast_option_maxfiles = atoi(v->value);
+ if (!ast_opt_remote) {
+ set_ulimit(ast_option_maxfiles);
+ }
+ /* What user to run as */
+ } else if (!strcasecmp(v->name, "runuser")) {
+ ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
+ /* What group to run as */
+ } else if (!strcasecmp(v->name, "rungroup")) {
+ ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
+ } else if (!strcasecmp(v->name, "systemname")) {
+ ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
+ } else if (!strcasecmp(v->name, "autosystemname")) {
+ if (ast_true(v->value)) {
+ if (!gethostname(hostname, sizeof(hostname) - 1)) {
+ ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
+ } else {
+ if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
+ ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
+ }
+ ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
+ }
+ }
+ } else if (!strcasecmp(v->name, "languageprefix")) {
+ ast_language_is_prefix = ast_true(v->value);
+ } else if (!strcasecmp(v->name, "defaultlanguage")) {
+ ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
+ } else if (!strcasecmp(v->name, "lockmode")) {
+ if (!strcasecmp(v->value, "lockfile")) {
+ ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
+ } else if (!strcasecmp(v->value, "flock")) {
+ ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
+ } else {
+ ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
+ "defaulting to 'lockfile'\n", v->value);
+ ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
+ }
+#if defined(HAVE_SYSINFO)
+ } else if (!strcasecmp(v->name, "minmemfree")) {
+ /* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
+ * if the amount of free memory falls below this watermark */
+ if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
+ option_minmemfree = 0;
+ }
+#endif
+ } else if (!strcasecmp(v->name, "entityid")) {
+ struct ast_eid tmp_eid;
+ if (!ast_str_to_eid(&tmp_eid, v->value)) {
+ ast_eid_default = tmp_eid;
+ } else {
+ ast_log(LOG_WARNING, "Invalid Entity ID '%s' provided\n", v->value);
+ }
+ } else if (!strcasecmp(v->name, "lightbackground")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
+ } else if (!strcasecmp(v->name, "forceblackbackground")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
+ } else if (!strcasecmp(v->name, "hideconnect")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
+ } else if (!strcasecmp(v->name, "lockconfdir")) {
+ ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
+ } else if (!strcasecmp(v->name, "stdexten")) {
+ /* Choose how to invoke the extensions.conf stdexten */
+ if (!strcasecmp(v->value, "gosub")) {
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
+ } else if (!strcasecmp(v->value, "macro")) {
+ ast_set_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
+ } else {
+ ast_log(LOG_WARNING,
+ "'%s' is not a valid setting for the stdexten option, defaulting to 'gosub'\n",
+ v->value);
+ ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
+ }
+ } else if (!strcasecmp(v->name, "live_dangerously")) {
+ live_dangerously = ast_true(v->value);
+ }
+ }
+ if (!ast_opt_remote) {
+ pbx_live_dangerously(live_dangerously);
+ }
+
+ option_debug += option_debug_new;
+ option_verbose += option_verbose_new;
+
+ ast_config_destroy(cfg);
+}
diff --git a/makeopts.in b/makeopts.in
index 4d3cc5db6..1063316dd 100644
--- a/makeopts.in
+++ b/makeopts.in
@@ -143,12 +143,6 @@ CODEC2_LIB=@CODEC2_LIB@
CURL_INCLUDE=@CURL_INCLUDE@
CURL_LIB=@CURL_LIB@
-CURSES_INCLUDE=@CURSES_INCLUDE@
-CURSES_LIB=@CURSES_LIB@
-CURSES_DIR=@CURSES_DIR@
-
-EDITLINE_LIB=@EDITLINE_LIB@
-
FREETDS_INCLUDE=@FREETDS_INCLUDE@
FREETDS_LIB=@FREETDS_LIB@
@@ -210,10 +204,6 @@ MYSQLCLIENT_LIB=@MYSQLCLIENT_LIB@
NBS_INCLUDE=@NBS_INCLUDE@
NBS_LIB=@NBS_LIB@
-NCURSES_INCLUDE=@NCURSES_INCLUDE@
-NCURSES_LIB=@NCURSES_LIB@
-NCURSES_DIR=@NCURSES_DIR@
-
NEON_INCLUDE=@NEON_INCLUDE@
NEON_LIB=@NEON_LIB@
NEON29_INCLUDE=@NEON_INCLUDE@
@@ -364,20 +354,12 @@ CAP_INCLUDE=@CAP_INCLUDE@
BKTR_INCLUDE=@BKTR_INCLUDE@
BKTR_LIB=@BKTR_LIB@
-TERMCAP_INCLUDE=@TERMCAP_INCLUDE@
-TERMCAP_LIB=@TERMCAP_LIB@
-TERMCAP_DIR=@TERMCAP_DIR@
-
LIBXML2_INCLUDE=@LIBXML2_INCLUDE@
LIBXML2_LIB=@LIBXML2_LIB@
LIBXSLT_INCLUDE=@LIBXSLT_INCLUDE@
LIBXSLT_LIB=@LIBXSLT_LIB@
-TINFO_INCLUDE=@TINFO_INCLUDE@
-TINFO_LIB=@TINFO_LIB@
-TINFO_DIR=@TINFO_DIR@
-
# if poll is not present, let the makefile know.
POLL_AVAILABLE=@HAS_POLL@
TIMERFD_INCLUDE=@TIMERFD_INCLUDE@
diff --git a/res/res_pjsip/pjsip_transport_events.c b/res/res_pjsip/pjsip_transport_events.c
index c701b8411..cc7b7c077 100644
--- a/res/res_pjsip/pjsip_transport_events.c
+++ b/res/res_pjsip/pjsip_transport_events.c
@@ -114,6 +114,36 @@ static void transport_monitor_dtor(void *vdoomed)
AST_VECTOR_FREE(&monitored->monitors);
}
+/*!
+ * \internal
+ * \brief Do registered callbacks for the transport.
+ * \since 13.21.0
+ *
+ * \param transports Active transports container
+ * \param transport Which transport to do callbacks for.
+ *
+ * \return Nothing
+ */
+static void transport_state_do_reg_callbacks(struct ao2_container *transports, pjsip_transport *transport)
+{
+ struct transport_monitor *monitored;
+
+ monitored = ao2_find(transports, transport->obj_name, OBJ_SEARCH_KEY | OBJ_UNLINK);
+ if (monitored) {
+ int idx;
+
+ for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
+ struct transport_monitor_notifier *notifier;
+
+ notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
+ ast_debug(3, "running callback %p(%p) for transport %s\n",
+ notifier->cb, notifier->data, transport->obj_name);
+ notifier->cb(notifier->data);
+ }
+ ao2_ref(monitored, -1);
+ }
+}
+
/*! \brief Callback invoked when transport state changes occur */
static void transport_state_callback(pjsip_transport *transport,
pjsip_transport_state state, const pjsip_transport_state_info *info)
@@ -147,6 +177,7 @@ static void transport_state_callback(pjsip_transport *transport,
if (!transport->is_shutdown) {
pjsip_transport_shutdown(transport);
}
+ transport_state_do_reg_callbacks(transports, transport);
break;
case PJSIP_TP_STATE_SHUTDOWN:
/*
@@ -157,23 +188,17 @@ static void transport_state_callback(pjsip_transport *transport,
*/
transport->is_shutdown = PJ_TRUE;
- monitored = ao2_find(transports, transport->obj_name,
- OBJ_SEARCH_KEY | OBJ_UNLINK);
- if (monitored) {
- int idx;
-
- for (idx = AST_VECTOR_SIZE(&monitored->monitors); idx--;) {
- struct transport_monitor_notifier *notifier;
-
- notifier = AST_VECTOR_GET_ADDR(&monitored->monitors, idx);
- ast_debug(3, "running callback %p(%p) for transport %s\n",
- notifier->cb, notifier->data, transport->obj_name);
- notifier->cb(notifier->data);
- }
- ao2_ref(monitored, -1);
- }
+ transport_state_do_reg_callbacks(transports, transport);
+ break;
+ case PJSIP_TP_STATE_DESTROY:
+ transport_state_do_reg_callbacks(transports, transport);
break;
default:
+ /*
+ * We have to have a default case because the enum is
+ * defined by a third-party library.
+ */
+ ast_assert(0);
break;
}
diff --git a/res/res_rtp_asterisk.c b/res/res_rtp_asterisk.c
index d0e482405..b010f6c51 100644
--- a/res/res_rtp_asterisk.c
+++ b/res/res_rtp_asterisk.c
@@ -106,7 +106,7 @@
#define RTCP_PT_APP 204
/* VP8: RTCP Feedback */
/*! Payload Specific Feed Back (From RFC4585 also RFC5104) */
-#define RTCP_PT_PSFB 206
+#define RTCP_PT_PSFB AST_RTP_RTCP_PSFB
#define RTP_MTU 1200
#define DTMF_SAMPLE_RATE_MS 8 /*!< DTMF samples per millisecond */
@@ -5185,6 +5185,7 @@ static const char *rtcp_payload_type2str(unsigned int pt)
#define RTCP_SR_BLOCK_WORD_LENGTH 5
#define RTCP_RR_BLOCK_WORD_LENGTH 6
#define RTCP_HEADER_SSRC_LENGTH 2
+#define RTCP_FB_REMB_BLOCK_WORD_LENGTH 5
static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, const unsigned char *rtcpdata, size_t size, struct ast_sockaddr *addr)
{
@@ -5266,6 +5267,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
RAII_VAR(struct ast_rtp_rtcp_report *, rtcp_report, NULL, ao2_cleanup);
struct ast_rtp_instance *child;
struct ast_rtp *rtp;
+ struct ast_rtp_rtcp_feedback *feedback;
i = position;
first_word = ntohl(rtcpheader[i]);
@@ -5284,7 +5286,15 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
min_length += (rc * RTCP_RR_BLOCK_WORD_LENGTH);
break;
case RTCP_PT_FUR:
+ break;
case RTCP_PT_PSFB:
+ switch (rc) {
+ case AST_RTP_RTCP_FMT_REMB:
+ min_length += RTCP_FB_REMB_BLOCK_WORD_LENGTH;
+ break;
+ default:
+ break;
+ }
break;
case RTCP_PT_SDES:
case RTCP_PT_BYE:
@@ -5493,6 +5503,7 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
/* Return an AST_FRAME_RTCP frame with the ast_rtp_rtcp_report
* object as a its data */
transport_rtp->f.frametype = AST_FRAME_RTCP;
+ transport_rtp->f.subclass.integer = pt;
transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
memcpy(transport_rtp->f.data.ptr, rtcp_report, sizeof(struct ast_rtp_rtcp_report));
transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_report);
@@ -5514,18 +5525,55 @@ static struct ast_frame *ast_rtcp_interpret(struct ast_rtp_instance *instance, c
f = &transport_rtp->f;
break;
case RTCP_PT_FUR:
- /* Handle RTCP FIR as FUR */
+ /* Handle RTCP FUR as FIR by setting the format to 4 */
+ rc = AST_RTP_RTCP_FMT_FIR;
case RTCP_PT_PSFB:
- if (rtcp_debug_test_addr(addr)) {
- ast_verbose("Received an RTCP Fast Update Request\n");
+ switch (rc) {
+ case AST_RTP_RTCP_FMT_FIR:
+ if (rtcp_debug_test_addr(addr)) {
+ ast_verbose("Received an RTCP Fast Update Request\n");
+ }
+ transport_rtp->f.frametype = AST_FRAME_CONTROL;
+ transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
+ transport_rtp->f.datalen = 0;
+ transport_rtp->f.samples = 0;
+ transport_rtp->f.mallocd = 0;
+ transport_rtp->f.src = "RTP";
+ f = &transport_rtp->f;
+ break;
+ case AST_RTP_RTCP_FMT_REMB:
+ /* If REMB support is not enabled ignore this message */
+ if (!ast_rtp_instance_get_prop(instance, AST_RTP_PROPERTY_REMB)) {
+ break;
+ }
+
+ if (rtcp_debug_test_addr(addr)) {
+ ast_verbose("Received REMB report\n");
+ }
+ transport_rtp->f.frametype = AST_FRAME_RTCP;
+ transport_rtp->f.subclass.integer = pt;
+ transport_rtp->f.stream_num = rtp->stream_num;
+ transport_rtp->f.data.ptr = rtp->rtcp->frame_buf + AST_FRIENDLY_OFFSET;
+ feedback = transport_rtp->f.data.ptr;
+ feedback->fmt = rc;
+
+ /* We don't actually care about the SSRC information in the feedback message */
+ first_word = ntohl(rtcpheader[i + 2]);
+ feedback->remb.br_exp = (first_word >> 18) & ((1 << 6) - 1);
+ feedback->remb.br_mantissa = first_word & ((1 << 18) - 1);
+
+ transport_rtp->f.datalen = sizeof(struct ast_rtp_rtcp_feedback);
+ transport_rtp->f.offset = AST_FRIENDLY_OFFSET;
+ transport_rtp->f.samples = 0;
+ transport_rtp->f.mallocd = 0;
+ transport_rtp->f.delivery.tv_sec = 0;
+ transport_rtp->f.delivery.tv_usec = 0;
+ transport_rtp->f.src = "RTP";
+ f = &transport_rtp->f;
+ break;
+ default:
+ break;
}
- transport_rtp->f.frametype = AST_FRAME_CONTROL;
- transport_rtp->f.subclass.integer = AST_CONTROL_VIDUPDATE;
- transport_rtp->f.datalen = 0;
- transport_rtp->f.samples = 0;
- transport_rtp->f.mallocd = 0;
- transport_rtp->f.src = "RTP";
- f = &transport_rtp->f;
break;
case RTCP_PT_SDES:
if (rtcp_debug_test_addr(addr)) {
diff --git a/tests/test_data_buffer.c b/tests/test_data_buffer.c
new file mode 100644
index 000000000..11fdc7b6f
--- /dev/null
+++ b/tests/test_data_buffer.c
@@ -0,0 +1,313 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2018, Digium, Inc.
+ *
+ * Ben Ford <bford@digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*!
+ * \file
+ * \brief Media Stream API Unit Tests
+ *
+ * \author Ben Ford <bford@digium.com>
+ *
+ */
+
+/*** MODULEINFO
+ <depend>TEST_FRAMEWORK</depend>
+ <support_level>core</support_level>
+ ***/
+
+#include "asterisk.h"
+
+#include "asterisk/module.h"
+#include "asterisk/test.h"
+#include "asterisk/data_buffer.h"
+
+#define BUFFER_MAX_NOMINAL 10
+
+struct mock_payload
+{
+ int id;
+};
+
+/* Ensures that RAII_VAR will not trip ast_assert(buffer != NULL) in the callback */
+static void ast_data_buffer_free_wrapper(struct ast_data_buffer *buffer)
+{
+ if (!buffer) {
+ return;
+ }
+
+ ast_data_buffer_free(buffer);
+}
+
+AST_TEST_DEFINE(buffer_create)
+{
+ RAII_VAR(struct ast_data_buffer *, buffer, NULL, ast_data_buffer_free_wrapper);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "buffer_create";
+ info->category = "/main/data_buffer/";
+ info->summary = "buffer create unit test";
+ info->description =
+ "Test that creating a data buffer results in a buffer with the expected values";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ buffer = ast_data_buffer_alloc(ast_free_ptr, BUFFER_MAX_NOMINAL);
+
+ ast_test_validate(test, buffer != NULL,
+ "Failed to create buffer with valid arguments");
+ ast_test_validate(test, ast_data_buffer_count(buffer) == 0,
+ "Newly created buffer does not have the expected payload count");
+ ast_test_validate(test, ast_data_buffer_max(buffer) == BUFFER_MAX_NOMINAL,
+ "Newly created buffer does not have the expected max size");
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(buffer_put)
+{
+ RAII_VAR(struct ast_data_buffer *, buffer, NULL, ast_data_buffer_free_wrapper);
+ struct mock_payload *payload;
+ struct mock_payload *fetched_payload;
+ int ret;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "buffer_put";
+ info->category = "/main/data_buffer/";
+ info->summary = "buffer put unit test";
+ info->description =
+ "Test that putting payloads in the buffer yields the expected results";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ buffer = ast_data_buffer_alloc(ast_free_ptr, 2);
+
+ ast_test_validate(test, buffer != NULL,
+ "Failed to create buffer with valid arguments");
+ ast_test_validate(test, ast_data_buffer_count(buffer) == 0,
+ "Newly created buffer is not empty");
+
+ payload = ast_calloc(1, sizeof(*payload));
+
+ ast_test_validate(test, payload != NULL,
+ "Failed to allocate memory for first payload");
+
+ payload->id = 2;
+ ret = ast_data_buffer_put(buffer, 2, payload);
+
+ ast_test_validate(test, ret == 0,
+ "Adding a payload to an empty buffer did not return the expected value");
+ ast_test_validate(test, ast_data_buffer_count(buffer) == 1,
+ "Adding a payload to an empty buffer did not update count to the expected value");
+
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, 2);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get only payload from buffer given valid arguments");
+
+ ast_data_buffer_put(buffer, 2, payload);
+
+ ast_test_validate(test, ast_data_buffer_count(buffer) == 1,
+ "Adding a payload that is already in the buffer should not do anything");
+
+ payload = ast_calloc(1, sizeof(*payload));
+
+ ast_test_validate(test, payload != NULL,
+ "Failed to allocate memory for second payload");
+
+ payload->id = 1;
+ ast_data_buffer_put(buffer, 1, payload);
+ fetched_payload = ast_data_buffer_get(buffer, 1);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get a payload from buffer given valid arguments");
+ ast_test_validate(test, ast_data_buffer_count(buffer) == 2,
+ "Buffer does not have the expected count after removing a payload");
+ ast_test_validate(test, fetched_payload->id == 1,
+ "Did not get the expected payload from the buffer");
+
+ payload = ast_calloc(1, sizeof(*payload));
+
+ ast_test_validate(test, payload != NULL,
+ "Failed to allocate memory for third payload");
+
+ payload->id = 3;
+ ret = ast_data_buffer_put(buffer, 3, payload);
+
+ ast_test_validate(test, ret == 0,
+ "Failed to replace a payload in the buffer");
+ ast_test_validate(test, ast_data_buffer_count(buffer) <= 2,
+ "Buffer count exceeded the max");
+
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, 3);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get a payload from buffer at position 3 given valid arguments");
+ ast_test_validate(test, fetched_payload->id == 3,
+ "Did not get the expected payload at position 3 from the buffer");
+
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, 2);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get a payload from buffer at position 2 given valid arguments");
+ ast_test_validate(test, fetched_payload->id == 2,
+ "Did not get the expected payload at position 2 from the buffer");
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(buffer_resize)
+{
+ RAII_VAR(struct ast_data_buffer *, buffer, NULL, ast_data_buffer_free_wrapper);
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "buffer_resize";
+ info->category = "/main/data_buffer/";
+ info->summary = "buffer resize unit test";
+ info->description =
+ "Tests resizing a data buffer to make sure it has the expected outcome";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ buffer = ast_data_buffer_alloc(ast_free_ptr, BUFFER_MAX_NOMINAL);
+
+ ast_test_validate(test, buffer != NULL,
+ "Failed to create buffer with valid arguments");
+
+ ast_data_buffer_resize(buffer, BUFFER_MAX_NOMINAL);
+
+ ast_test_validate(test, ast_data_buffer_max(buffer) == BUFFER_MAX_NOMINAL,
+ "Trying to resize buffer to same size should not change its max size");
+
+ ast_data_buffer_resize(buffer, BUFFER_MAX_NOMINAL + 2);
+
+ ast_test_validate(test, ast_data_buffer_max(buffer) == BUFFER_MAX_NOMINAL + 2,
+ "Increasing buffer size did not return the expected max");
+
+ ast_data_buffer_resize(buffer, 1);
+
+ ast_test_validate(test, ast_data_buffer_max(buffer) == 1,
+ "Decreasing buffer size did not return the expected max");
+
+ return AST_TEST_PASS;
+}
+
+AST_TEST_DEFINE(buffer_nominal)
+{
+ RAII_VAR(struct ast_data_buffer *, buffer, NULL, ast_data_buffer_free_wrapper);
+ struct mock_payload *payload;
+ struct mock_payload *fetched_payload;
+ int ret;
+ int i;
+
+ switch (cmd) {
+ case TEST_INIT:
+ info->name = "buffer_nominal";
+ info->category = "/main/data_buffer/";
+ info->summary = "buffer nominal unit test";
+ info->description =
+ "Tests the normal usage of a data buffer to ensure the expected payloads "
+ "are present after multiple insertions";
+ return AST_TEST_NOT_RUN;
+ case TEST_EXECUTE:
+ break;
+ }
+
+ buffer = ast_data_buffer_alloc(ast_free_ptr, BUFFER_MAX_NOMINAL);
+
+ ast_test_validate(test, buffer != NULL,
+ "Failed to create buffer with valid arguments");
+
+ for (i = 1; i <= BUFFER_MAX_NOMINAL; i++) {
+ payload = ast_calloc(1, sizeof(*payload));
+
+ ast_test_validate(test, payload != NULL,
+ "Failed to allocate memory for payload %d", i);
+
+ ret = ast_data_buffer_put(buffer, i, payload);
+
+ ast_test_validate(test, ret == 0,
+ "Failed to add payload %d to buffer", i);
+ }
+
+ ast_test_validate(test, ast_data_buffer_count(buffer) == BUFFER_MAX_NOMINAL,
+ "Buffer does not have the expected count after adding payloads");
+
+ for (i = 1; i <= BUFFER_MAX_NOMINAL; i++) {
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, i);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get payload at position %d during first loop", i);
+ }
+
+ for (i = 1; i <= BUFFER_MAX_NOMINAL; i++) {
+ payload = ast_calloc(1, sizeof(*payload));
+
+ ast_test_validate(test, payload != NULL,
+ "Failed to allocate memory for payload %d", i + BUFFER_MAX_NOMINAL);
+
+ ret = ast_data_buffer_put(buffer, i + BUFFER_MAX_NOMINAL, payload);
+
+ ast_test_validate(test, ret == 0,
+ "Failed to add payload %d to buffer", i + BUFFER_MAX_NOMINAL);
+ }
+
+ ast_test_validate(test, ast_data_buffer_count(buffer) == BUFFER_MAX_NOMINAL,
+ "Buffer does not have the expected count after replacing payloads");
+
+ for (i = 1; i <= BUFFER_MAX_NOMINAL; i++) {
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, i);
+
+ ast_test_validate(test, fetched_payload == NULL,
+ "Got an unexpected payload at position %d", i);
+
+ fetched_payload = (struct mock_payload *)ast_data_buffer_get(buffer, i + BUFFER_MAX_NOMINAL);
+
+ ast_test_validate(test, fetched_payload != NULL,
+ "Failed to get payload at position %d during second loop", i + BUFFER_MAX_NOMINAL);
+ }
+
+ return AST_TEST_PASS;
+}
+
+static int unload_module(void)
+{
+ AST_TEST_UNREGISTER(buffer_create);
+ AST_TEST_UNREGISTER(buffer_put);
+ AST_TEST_UNREGISTER(buffer_resize);
+ AST_TEST_UNREGISTER(buffer_nominal);
+ return 0;
+}
+
+static int load_module(void)
+{
+ AST_TEST_REGISTER(buffer_create);
+ AST_TEST_REGISTER(buffer_put);
+ AST_TEST_REGISTER(buffer_resize);
+ AST_TEST_REGISTER(buffer_nominal);
+ return AST_MODULE_LOAD_SUCCESS;
+}
+
+AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Data buffer API test module");
diff --git a/third-party/pjproject/patches/0070-os_core_unix-Set-mutex-NULL-in-atomic-destroy-and-ad.patch b/third-party/pjproject/patches/0070-os_core_unix-Set-mutex-NULL-in-atomic-destroy-and-ad.patch
new file mode 100644
index 000000000..3aafd69e8
--- /dev/null
+++ b/third-party/pjproject/patches/0070-os_core_unix-Set-mutex-NULL-in-atomic-destroy-and-ad.patch
@@ -0,0 +1,114 @@
+From 67485f3a6c711f67a40ff46288cb6be1658023bd Mon Sep 17 00:00:00 2001
+From: nanang <nanang@localhost>
+Date: Mon, 26 Mar 2018 10:33:50 +0000
+Subject: [PATCH] Close #2101: - set atomic's mutex to NULL in atomic destroy
+ - added few sanity checks to the atomic functions.
+
+---
+ pjlib/src/pj/os_core_unix.c | 20 ++++++++++++++++++--
+ pjlib/src/pj/os_core_win32.c | 4 ++++
+ 2 files changed, 22 insertions(+), 2 deletions(-)
+
+diff --git a/pjlib/src/pj/os_core_unix.c b/pjlib/src/pj/os_core_unix.c
+index ebfe84348..c17ad4ef0 100644
+--- a/pjlib/src/pj/os_core_unix.c
++++ b/pjlib/src/pj/os_core_unix.c
+@@ -879,9 +879,16 @@ PJ_DEF(pj_status_t) pj_atomic_create( pj_pool_t *pool,
+ */
+ PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var )
+ {
++ pj_status_t status;
++
+ PJ_ASSERT_RETURN(atomic_var, PJ_EINVAL);
++
+ #if PJ_HAS_THREADS
+- return pj_mutex_destroy( atomic_var->mutex );
++ status = pj_mutex_destroy( atomic_var->mutex );
++ if (status == PJ_SUCCESS) {
++ atomic_var->mutex = NULL;
++ }
++ return status;
+ #else
+ return 0;
+ #endif
+@@ -892,10 +899,16 @@ PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *atomic_var )
+ */
+ PJ_DEF(void) pj_atomic_set(pj_atomic_t *atomic_var, pj_atomic_value_t value)
+ {
++ pj_status_t status;
++
+ PJ_CHECK_STACK();
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+
+ #if PJ_HAS_THREADS
+- pj_mutex_lock( atomic_var->mutex );
++ status = pj_mutex_lock( atomic_var->mutex );
++ if (status != PJ_SUCCESS) {
++ return;
++ }
+ #endif
+ atomic_var->value = value;
+ #if PJ_HAS_THREADS
+@@ -946,6 +959,7 @@ PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
+ */
+ PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ pj_atomic_inc_and_get(atomic_var);
+ }
+
+@@ -974,6 +988,7 @@ PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
+ */
+ PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ pj_atomic_dec_and_get(atomic_var);
+ }
+
+@@ -1005,6 +1020,7 @@ PJ_DEF(pj_atomic_value_t) pj_atomic_add_and_get( pj_atomic_t *atomic_var,
+ PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value )
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ pj_atomic_add_and_get(atomic_var, value);
+ }
+
+diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c
+index 1cb6004d3..8c934b34d 100644
+--- a/pjlib/src/pj/os_core_win32.c
++++ b/pjlib/src/pj/os_core_win32.c
+@@ -750,6 +750,7 @@ PJ_DEF(pj_status_t) pj_atomic_destroy( pj_atomic_t *var )
+ PJ_DEF(void) pj_atomic_set( pj_atomic_t *atomic_var, pj_atomic_value_t value)
+ {
+ PJ_CHECK_STACK();
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+
+ InterlockedExchange(&atomic_var->value, value);
+ }
+@@ -784,6 +785,7 @@ PJ_DEF(pj_atomic_value_t) pj_atomic_inc_and_get(pj_atomic_t *atomic_var)
+ */
+ PJ_DEF(void) pj_atomic_inc(pj_atomic_t *atomic_var)
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ pj_atomic_inc_and_get(atomic_var);
+ }
+
+@@ -806,6 +808,7 @@ PJ_DEF(pj_atomic_value_t) pj_atomic_dec_and_get(pj_atomic_t *atomic_var)
+ */
+ PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ pj_atomic_dec_and_get(atomic_var);
+ }
+
+@@ -815,6 +818,7 @@ PJ_DEF(void) pj_atomic_dec(pj_atomic_t *atomic_var)
+ PJ_DEF(void) pj_atomic_add( pj_atomic_t *atomic_var,
+ pj_atomic_value_t value )
+ {
++ PJ_ASSERT_ON_FAIL(atomic_var, return);
+ #if defined(PJ_WIN32_WINNT) && PJ_WIN32_WINNT >= 0x0400
+ InterlockedExchangeAdd( &atomic_var->value, value );
+ #else
+--
+2.14.3
+
diff --git a/third-party/pjproject/patches/0080-timer-Clean-up-usage-of-timer-heap.patch b/third-party/pjproject/patches/0080-timer-Clean-up-usage-of-timer-heap.patch
new file mode 100644
index 000000000..6c139ba18
--- /dev/null
+++ b/third-party/pjproject/patches/0080-timer-Clean-up-usage-of-timer-heap.patch
@@ -0,0 +1,434 @@
+From 853005378de2ffecee7774e095d8cbfbfa0ab706 Mon Sep 17 00:00:00 2001
+From: George Joseph <gjoseph@digium.com>
+Date: Tue, 2 Jan 2018 06:36:46 -0700
+Subject: [PATCH] timer: Clean up usage of timer heap
+
+Added a new pj_timer_entry_reset function that resets a timer_entry
+for re-use.
+
+Changed direct settings of timer_entry fields to use
+pj_timer_entry_init and pj_timer_entry_reset.
+
+Fixed issues where timers were being rescheduled incorrectly.
+---
+ pjlib/include/pj/timer.h | 14 ++++++++++++++
+ pjlib/src/pj/ssl_sock_ossl.c | 8 +++++---
+ pjlib/src/pj/timer.c | 12 ++++++++++++
+ pjnath/src/pjnath/ice_session.c | 9 ++++++++-
+ pjnath/src/pjnath/nat_detect.c | 2 ++
+ pjnath/src/pjnath/stun_sock.c | 2 +-
+ pjnath/src/pjnath/stun_transaction.c | 10 +++++-----
+ pjnath/src/pjnath/turn_session.c | 3 +++
+ pjnath/src/pjnath/turn_sock.c | 1 +
+ pjnath/src/pjturn-srv/allocation.c | 4 ++--
+ pjnath/src/pjturn-srv/listener_tcp.c | 2 +-
+ pjsip/src/pjsip-simple/evsub.c | 6 +++---
+ pjsip/src/pjsip/sip_endpoint.c | 4 +++-
+ pjsip/src/pjsip/sip_transaction.c | 9 +++------
+ pjsip/src/pjsip/sip_transport.c | 3 +--
+ 15 files changed, 64 insertions(+), 25 deletions(-)
+
+diff --git a/pjlib/include/pj/timer.h b/pjlib/include/pj/timer.h
+index df6155a81..90fc8ac85 100644
+--- a/pjlib/include/pj/timer.h
++++ b/pjlib/include/pj/timer.h
+@@ -212,6 +212,20 @@ PJ_DECL(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,
+ void *user_data,
+ pj_timer_heap_callback *cb );
+
++/**
++ * Reset a timer entry. Application should call this function before reusing
++ * the timer entry.
++ *
++ * @param entry The timer entry to be initialized.
++ * @param id Arbitrary ID assigned by the user/owner of this entry.
++ * Applications can use this ID to distinguish multiple
++ * timer entries that share the same callback and user_data.
++ *
++ * @return The timer entry itself.
++ */
++PJ_DECL(pj_timer_entry*) pj_timer_entry_reset( pj_timer_entry *entry,
++ int id);
++
+ /**
+ * Queries whether a timer entry is currently running.
+ *
+diff --git a/pjlib/src/pj/ssl_sock_ossl.c b/pjlib/src/pj/ssl_sock_ossl.c
+index 969cc1420..ead1a8fbb 100644
+--- a/pjlib/src/pj/ssl_sock_ossl.c
++++ b/pjlib/src/pj/ssl_sock_ossl.c
+@@ -291,6 +291,7 @@ struct pj_ssl_cert_t
+ static write_data_t* alloc_send_data(pj_ssl_sock_t *ssock, pj_size_t len);
+ static void free_send_data(pj_ssl_sock_t *ssock, write_data_t *wdata);
+ static pj_status_t flush_delayed_send(pj_ssl_sock_t *ssock);
++static void on_timer(pj_timer_heap_t *th, struct pj_timer_entry *te);
+
+ /*
+ *******************************************************************
+@@ -1621,7 +1622,8 @@ static pj_bool_t on_handshake_complete(pj_ssl_sock_t *ssock,
+ pj_timer_heap_cancel(ssock->param.timer_heap,
+ &ssock->timer);
+ }
+- ssock->timer.id = TIMER_CLOSE;
++
++ pj_timer_entry_reset(&ssock->timer, TIMER_CLOSE);
+ pj_time_val_normalize(&interval);
+ if (pj_timer_heap_schedule(ssock->param.timer_heap,
+ &ssock->timer, &interval) != 0)
+@@ -2387,7 +2389,7 @@ static pj_bool_t asock_on_accept_complete (pj_activesock_t *asock,
+ ssock->param.timeout.msec != 0))
+ {
+ pj_assert(ssock->timer.id == TIMER_NONE);
+- ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
++ pj_timer_entry_reset(&ssock->timer, TIMER_HANDSHAKE_TIMEOUT);
+ status = pj_timer_heap_schedule(ssock->param.timer_heap,
+ &ssock->timer,
+ &ssock->param.timeout);
+@@ -3405,7 +3407,7 @@ PJ_DEF(pj_status_t) pj_ssl_sock_start_connect( pj_ssl_sock_t *ssock,
+ ssock->param.timeout.msec != 0))
+ {
+ pj_assert(ssock->timer.id == TIMER_NONE);
+- ssock->timer.id = TIMER_HANDSHAKE_TIMEOUT;
++ pj_timer_entry_reset(&ssock->timer, TIMER_HANDSHAKE_TIMEOUT);
+ status = pj_timer_heap_schedule(ssock->param.timer_heap,
+ &ssock->timer,
+ &ssock->param.timeout);
+diff --git a/pjlib/src/pj/timer.c b/pjlib/src/pj/timer.c
+index 90a95e37b..13126116f 100644
+--- a/pjlib/src/pj/timer.c
++++ b/pjlib/src/pj/timer.c
+@@ -472,6 +472,18 @@ PJ_DEF(pj_timer_entry*) pj_timer_entry_init( pj_timer_entry *entry,
+ return entry;
+ }
+
++PJ_DEF(pj_timer_entry*) pj_timer_entry_reset( pj_timer_entry *entry,
++ int id)
++{
++ entry->id = id;
++ entry->_grp_lock = NULL;
++ entry->_timer_id = -1;
++ entry->_timer_value = (pj_time_val){0, 0};
++
++ return entry;
++}
++
++
+ PJ_DEF(pj_bool_t) pj_timer_entry_running( pj_timer_entry *entry )
+ {
+ return (entry->_timer_id >= 1);
+diff --git a/pjnath/src/pjnath/ice_session.c b/pjnath/src/pjnath/ice_session.c
+index 63a0d1c9c..6d0e6abc9 100644
+--- a/pjnath/src/pjnath/ice_session.c
++++ b/pjnath/src/pjnath/ice_session.c
+@@ -1246,6 +1246,7 @@ done:
+ ice->comp_cnt;
+ pj_time_val_normalize(&delay);
+
++ pj_timer_entry_reset(&ice->timer, TIMER_KEEP_ALIVE);
+ pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap,
+ &ice->timer, &delay,
+ TIMER_KEEP_ALIVE,
+@@ -1276,7 +1277,7 @@ static void on_ice_complete(pj_ice_sess *ice, pj_status_t status)
+ /* Call callback */
+ if (ice->cb.on_ice_complete) {
+ pj_time_val delay = {0, 0};
+-
++ pj_timer_entry_reset(&ice->timer, TIMER_COMPLETION_CALLBACK);
+ pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap,
+ &ice->timer, &delay,
+ TIMER_COMPLETION_CALLBACK,
+@@ -1507,6 +1508,7 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
+ delay.sec = 0;
+ delay.msec = ice->opt.controlled_agent_want_nom_timeout;
+ pj_time_val_normalize(&delay);
++ pj_timer_entry_reset(&ice->timer, TIMER_CONTROLLED_WAIT_NOM);
+
+ pj_timer_heap_schedule_w_grp_lock(
+ ice->stun_cfg.timer_heap,
+@@ -1597,6 +1599,7 @@ static pj_bool_t on_check_complete(pj_ice_sess *ice,
+ delay.sec = 0;
+ delay.msec = ice->opt.nominated_check_delay;
+ pj_time_val_normalize(&delay);
++ pj_timer_entry_reset(&ice->timer, TIMER_START_NOMINATED_CHECK);
+
+ pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap,
+ &ice->timer, &delay,
+@@ -1929,6 +1932,8 @@ static pj_status_t start_periodic_check(pj_timer_heap_t *th,
+ pj_time_val timeout = {0, PJ_ICE_TA_VAL};
+
+ pj_time_val_normalize(&timeout);
++ pj_timer_entry_reset(&ice->timer, PJ_TRUE);
++
+ pj_timer_heap_schedule_w_grp_lock(th, te, &timeout, PJ_TRUE,
+ ice->grp_lock);
+ }
+@@ -1986,6 +1991,7 @@ static void start_nominated_check(pj_ice_sess *ice)
+ &ice->clist.timer, PJ_FALSE);
+
+ delay.sec = delay.msec = 0;
++ pj_timer_entry_reset(&ice->timer, PJ_TRUE);
+ status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap,
+ &ice->clist.timer, &delay,
+ PJ_TRUE,
+@@ -2125,6 +2131,7 @@ PJ_DEF(pj_status_t) pj_ice_sess_start_check(pj_ice_sess *ice)
+ * return start_periodic_check(ice->stun_cfg.timer_heap, &clist->timer);
+ */
+ delay.sec = delay.msec = 0;
++ pj_timer_entry_reset(&ice->timer, PJ_TRUE);
+ status = pj_timer_heap_schedule_w_grp_lock(ice->stun_cfg.timer_heap,
+ &clist->timer, &delay,
+ PJ_TRUE, ice->grp_lock);
+diff --git a/pjnath/src/pjnath/nat_detect.c b/pjnath/src/pjnath/nat_detect.c
+index 8a2408374..7bb364798 100644
+--- a/pjnath/src/pjnath/nat_detect.c
++++ b/pjnath/src/pjnath/nat_detect.c
+@@ -414,6 +414,7 @@ static void end_session(nat_detect_session *sess,
+ delay.msec = 0;
+
+ sess->timer.id = TIMER_DESTROY;
++ pj_timer_entry_init(&sess->timer, TIMER_DESTROY, sess, &on_sess_timer);
+ pj_timer_heap_schedule(sess->timer_heap, &sess->timer, &delay);
+ }
+
+@@ -933,6 +934,7 @@ static void on_sess_timer(pj_timer_heap_t *th,
+
+ if (next_timer) {
+ pj_time_val delay = {0, TEST_INTERVAL};
++ pj_timer_entry_reset(te, TIMER_TEST);
+ pj_timer_heap_schedule(th, te, &delay);
+ } else {
+ te->id = 0;
+diff --git a/pjnath/src/pjnath/stun_sock.c b/pjnath/src/pjnath/stun_sock.c
+index 6028e0c47..3aab27a1d 100644
+--- a/pjnath/src/pjnath/stun_sock.c
++++ b/pjnath/src/pjnath/stun_sock.c
+@@ -864,7 +864,7 @@ static void start_ka_timer(pj_stun_sock *stun_sock)
+
+ delay.sec = stun_sock->ka_interval;
+ delay.msec = 0;
+-
++ pj_timer_entry_reset(&stun_sock->ka_timer, PJ_TRUE);
+ pj_timer_heap_schedule_w_grp_lock(stun_sock->stun_cfg.timer_heap,
+ &stun_sock->ka_timer,
+ &delay, PJ_TRUE,
+diff --git a/pjnath/src/pjnath/stun_transaction.c b/pjnath/src/pjnath/stun_transaction.c
+index 28f623005..ad87b7b6c 100644
+--- a/pjnath/src/pjnath/stun_transaction.c
++++ b/pjnath/src/pjnath/stun_transaction.c
+@@ -86,11 +86,8 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_create(pj_stun_config *cfg,
+ tsx->grp_lock = grp_lock;
+ pj_memcpy(&tsx->cb, cb, sizeof(*cb));
+
+- tsx->retransmit_timer.cb = &retransmit_timer_callback;
+- tsx->retransmit_timer.user_data = tsx;
+-
+- tsx->destroy_timer.cb = &destroy_timer_callback;
+- tsx->destroy_timer.user_data = tsx;
++ pj_timer_entry_init(&tsx->retransmit_timer, 0, tsx, &retransmit_timer_callback);
++ pj_timer_entry_init(&tsx->destroy_timer, 0, tsx, &destroy_timer_callback);
+
+ pj_ansi_snprintf(tsx->obj_name, sizeof(tsx->obj_name), "utsx%p", tsx);
+
+@@ -120,6 +117,7 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_schedule_destroy(
+ pj_timer_heap_cancel_if_active(tsx->timer_heap, &tsx->retransmit_timer,
+ TIMER_INACTIVE);
+
++ pj_timer_entry_reset(&tsx->destroy_timer, TIMER_ACTIVE);
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->destroy_timer, delay,
+ TIMER_ACTIVE, tsx->grp_lock);
+@@ -237,6 +235,7 @@ static pj_status_t tsx_transmit_msg(pj_stun_client_tsx *tsx,
+ * cancel it (as opposed to when schedule_timer() failed we cannot
+ * cancel transmission).
+ */;
++ pj_timer_entry_reset(&tsx->retransmit_timer, TIMER_ACTIVE);
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ &tsx->retransmit_time,
+@@ -315,6 +314,7 @@ PJ_DEF(pj_status_t) pj_stun_client_tsx_send_msg(pj_stun_client_tsx *tsx,
+ * cancel it (as opposed to when schedule_timer() failed we cannot
+ * cancel transmission).
+ */;
++ pj_timer_entry_reset(&tsx->retransmit_timer, TIMER_ACTIVE);
+ status = pj_timer_heap_schedule_w_grp_lock(tsx->timer_heap,
+ &tsx->retransmit_timer,
+ &tsx->retransmit_time,
+diff --git a/pjnath/src/pjnath/turn_session.c b/pjnath/src/pjnath/turn_session.c
+index bbea027f3..e4685e625 100644
+--- a/pjnath/src/pjnath/turn_session.c
++++ b/pjnath/src/pjnath/turn_session.c
+@@ -431,6 +431,7 @@ static void sess_shutdown(pj_turn_session *sess,
+
+ pj_timer_heap_cancel_if_active(sess->timer_heap, &sess->timer,
+ TIMER_NONE);
++ pj_timer_entry_reset(&sess->timer, TIMER_DESTROY);
+ pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer,
+ &delay, TIMER_DESTROY,
+ sess->grp_lock);
+@@ -1434,6 +1435,7 @@ static void on_allocate_success(pj_turn_session *sess,
+ timeout.sec = sess->ka_interval;
+ timeout.msec = 0;
+
++ pj_timer_entry_reset(&sess->timer, TIMER_KEEP_ALIVE);
+ pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer,
+ &timeout, TIMER_KEEP_ALIVE,
+ sess->grp_lock);
+@@ -2080,6 +2082,7 @@ static void on_timer_event(pj_timer_heap_t *th, pj_timer_entry *e)
+ delay.sec = sess->ka_interval;
+ delay.msec = 0;
+
++ pj_timer_entry_reset(&sess->timer, TIMER_KEEP_ALIVE);
+ pj_timer_heap_schedule_w_grp_lock(sess->timer_heap, &sess->timer,
+ &delay, TIMER_KEEP_ALIVE,
+ sess->grp_lock);
+diff --git a/pjnath/src/pjnath/turn_sock.c b/pjnath/src/pjnath/turn_sock.c
+index a30ab5153..507858048 100644
+--- a/pjnath/src/pjnath/turn_sock.c
++++ b/pjnath/src/pjnath/turn_sock.c
+@@ -928,6 +928,7 @@ static void turn_on_state(pj_turn_session *sess,
+
+ pj_timer_heap_cancel_if_active(turn_sock->cfg.timer_heap,
+ &turn_sock->timer, 0);
++ pj_timer_entry_reset(&turn_sock->timer, TIMER_DESTROY);
+ pj_timer_heap_schedule_w_grp_lock(turn_sock->cfg.timer_heap,
+ &turn_sock->timer,
+ &delay, TIMER_DESTROY,
+diff --git a/pjnath/src/pjturn-srv/allocation.c b/pjnath/src/pjturn-srv/allocation.c
+index 6c9c9ce11..88533926b 100644
+--- a/pjnath/src/pjturn-srv/allocation.c
++++ b/pjnath/src/pjturn-srv/allocation.c
+@@ -513,7 +513,7 @@ static void alloc_shutdown(pj_turn_allocation *alloc)
+ */
+
+ /* Schedule destroy timer */
+- alloc->relay.timer.id = TIMER_ID_DESTROY;
++ pj_timer_entry_reset(&alloc->relay.timer, TIMER_ID_DESTROY);
+ pj_timer_heap_schedule(alloc->server->core.timer_heap,
+ &alloc->relay.timer, &destroy_delay);
+ }
+@@ -538,7 +538,7 @@ static pj_status_t resched_timeout(pj_turn_allocation *alloc)
+ delay.sec = alloc->relay.lifetime;
+ delay.msec = 0;
+
+- alloc->relay.timer.id = TIMER_ID_TIMEOUT;
++ pj_timer_entry_reset(&alloc->relay.timer, TIMER_ID_TIMEOUT);
+ status = pj_timer_heap_schedule(alloc->server->core.timer_heap,
+ &alloc->relay.timer, &delay);
+ if (status != PJ_SUCCESS) {
+diff --git a/pjnath/src/pjturn-srv/listener_tcp.c b/pjnath/src/pjturn-srv/listener_tcp.c
+index 796ed471b..4a9550c2e 100644
+--- a/pjnath/src/pjturn-srv/listener_tcp.c
++++ b/pjnath/src/pjturn-srv/listener_tcp.c
+@@ -475,7 +475,7 @@ static void tcp_dec_ref(pj_turn_transport *tp,
+
+ if (tcp->ref_cnt == 0 && tcp->timer.id == TIMER_NONE) {
+ pj_time_val delay = { SHUTDOWN_DELAY, 0 };
+- tcp->timer.id = TIMER_DESTROY;
++ pj_timer_entry_reset(&tcp->timer, TIMER_DESTROY);
+ pj_timer_heap_schedule(tcp->base.listener->server->core.timer_heap,
+ &tcp->timer, &delay);
+ }
+diff --git a/pjsip/src/pjsip-simple/evsub.c b/pjsip/src/pjsip-simple/evsub.c
+index eb666654f..7748853d2 100644
+--- a/pjsip/src/pjsip-simple/evsub.c
++++ b/pjsip/src/pjsip-simple/evsub.c
+@@ -518,6 +518,7 @@ static void set_timer( pjsip_evsub *sub, int timer_id,
+ timeout.sec = seconds;
+ timeout.msec = 0;
+
++ pj_timer_entry_reset(&sub->timer, timer_id);
+ pj_timer_heap_schedule_w_grp_lock(
+ pjsip_endpt_get_timer_heap(sub->endpt),
+ &sub->timer, &timeout, timer_id, sub->grp_lock);
+@@ -655,7 +656,7 @@ static void on_timer( pj_timer_heap_t *timer_heap,
+ /* If this timer entry has just been rescheduled or cancelled
+ * while waiting for dialog mutex, just return (see #1885 scenario 1).
+ */
+- if (pj_timer_entry_running(entry) || entry->id == TIMER_TYPE_NONE) {
++ if (entry->id == TIMER_TYPE_NONE) {
+ pjsip_dlg_dec_lock(sub->dlg);
+ return;
+ }
+@@ -786,8 +787,7 @@ static pj_status_t evsub_create( pjsip_dialog *dlg,
+ pjsip_hdr_clone(sub->pool, pkg->pkg_accept);
+ pj_list_init(&sub->sub_hdr_list);
+
+- sub->timer.user_data = sub;
+- sub->timer.cb = &on_timer;
++ pj_timer_entry_init(&sub->timer, 0, sub, &on_timer);
+
+ /* Set name. */
+ pj_ansi_snprintf(sub->obj_name, PJ_ARRAY_SIZE(sub->obj_name),
+diff --git a/pjsip/src/pjsip/sip_endpoint.c b/pjsip/src/pjsip/sip_endpoint.c
+index d810781d5..5c98a5bf6 100644
+--- a/pjsip/src/pjsip/sip_endpoint.c
++++ b/pjsip/src/pjsip/sip_endpoint.c
+@@ -788,6 +788,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer_dbg(pjsip_endpoint *endpt,
+ {
+ PJ_LOG(6, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
+ entry, delay->sec, delay->msec));
++ pj_timer_entry_reset(entry, entry->id);
+ return pj_timer_heap_schedule_dbg(endpt->timer_heap, entry, delay,
+ src_file, src_line);
+ }
+@@ -798,6 +799,7 @@ PJ_DEF(pj_status_t) pjsip_endpt_schedule_timer( pjsip_endpoint *endpt,
+ {
+ PJ_LOG(6, (THIS_FILE, "pjsip_endpt_schedule_timer(entry=%p, delay=%u.%u)",
+ entry, delay->sec, delay->msec));
++ pj_timer_entry_reset(entry, entry->id);
+ return pj_timer_heap_schedule( endpt->timer_heap, entry, delay );
+ }
+ #endif
+@@ -809,7 +811,7 @@ PJ_DEF(void) pjsip_endpt_cancel_timer( pjsip_endpoint *endpt,
+ pj_timer_entry *entry )
+ {
+ PJ_LOG(6, (THIS_FILE, "pjsip_endpt_cancel_timer(entry=%p)", entry));
+- pj_timer_heap_cancel( endpt->timer_heap, entry );
++ pj_timer_heap_cancel_if_active( endpt->timer_heap, entry, 0 );
+ }
+
+ /*
+diff --git a/pjsip/src/pjsip/sip_transaction.c b/pjsip/src/pjsip/sip_transaction.c
+index d52b12a72..5236e63f7 100644
+--- a/pjsip/src/pjsip/sip_transaction.c
++++ b/pjsip/src/pjsip/sip_transaction.c
+@@ -978,6 +978,7 @@ static pj_status_t tsx_schedule_timer(pjsip_transaction *tsx,
+ pj_status_t status;
+
+ pj_assert(active_id != 0);
++ pj_timer_entry_reset(entry, active_id);
+ status = pj_timer_heap_schedule_w_grp_lock(timer_heap, entry,
+ delay, active_id,
+ tsx->grp_lock);
+@@ -1019,12 +1020,8 @@ static pj_status_t tsx_create( pjsip_module *tsx_user,
+ pj_memcpy(pool->obj_name, tsx->obj_name, sizeof(pool->obj_name));
+
+ tsx->handle_200resp = 1;
+- tsx->retransmit_timer.id = TIMER_INACTIVE;
+- tsx->retransmit_timer.user_data = tsx;
+- tsx->retransmit_timer.cb = &tsx_timer_callback;
+- tsx->timeout_timer.id = TIMER_INACTIVE;
+- tsx->timeout_timer.user_data = tsx;
+- tsx->timeout_timer.cb = &tsx_timer_callback;
++ pj_timer_entry_init(&tsx->retransmit_timer, TIMER_INACTIVE, tsx, &tsx_timer_callback);
++ pj_timer_entry_init(&tsx->timeout_timer, TIMER_INACTIVE, tsx, &tsx_timer_callback);
+
+ if (grp_lock) {
+ tsx->grp_lock = grp_lock;
+diff --git a/pjsip/src/pjsip/sip_transport.c b/pjsip/src/pjsip/sip_transport.c
+index 3d27d5d71..834babeae 100644
+--- a/pjsip/src/pjsip/sip_transport.c
++++ b/pjsip/src/pjsip/sip_transport.c
+@@ -1092,8 +1092,7 @@ PJ_DEF(pj_status_t) pjsip_transport_register( pjsip_tpmgr *mgr,
+ /* Init. */
+ tp->tpmgr = mgr;
+ pj_bzero(&tp->idle_timer, sizeof(tp->idle_timer));
+- tp->idle_timer.user_data = tp;
+- tp->idle_timer.cb = &transport_idle_callback;
++ pj_timer_entry_init(&tp->idle_timer, 0, tp, &transport_idle_callback);
+
+ /*
+ * Register to hash table (see Trac ticket #42).
+--
+2.14.3
+