diff options
-rw-r--r-- | channels/chan_pjsip.c | 2 | ||||
-rw-r--r-- | codecs/codec_speex.c | 5 | ||||
-rwxr-xr-x | configure | 1004 | ||||
-rw-r--r-- | configure.ac | 40 | ||||
-rw-r--r-- | include/asterisk/_private.h | 5 | ||||
-rw-r--r-- | include/asterisk/autoconfig.h.in | 12 | ||||
-rw-r--r-- | include/asterisk/data_buffer.h | 144 | ||||
-rw-r--r-- | include/asterisk/frame.h | 2 | ||||
-rw-r--r-- | include/asterisk/paths.h | 4 | ||||
-rw-r--r-- | include/asterisk/rtp_engine.h | 26 | ||||
-rw-r--r-- | main/Makefile | 9 | ||||
-rw-r--r-- | main/asterisk.c | 420 | ||||
-rw-r--r-- | main/bridge_channel.c | 3 | ||||
-rw-r--r-- | main/channel.c | 11 | ||||
-rw-r--r-- | main/data_buffer.c | 314 | ||||
-rw-r--r-- | main/indications.c | 33 | ||||
-rw-r--r-- | main/options.c | 475 | ||||
-rw-r--r-- | makeopts.in | 18 | ||||
-rw-r--r-- | res/res_pjsip/pjsip_transport_events.c | 55 | ||||
-rw-r--r-- | res/res_rtp_asterisk.c | 70 | ||||
-rw-r--r-- | tests/test_data_buffer.c | 313 | ||||
-rw-r--r-- | third-party/pjproject/patches/0070-os_core_unix-Set-mutex-NULL-in-atomic-destroy-and-ad.patch | 114 | ||||
-rw-r--r-- | third-party/pjproject/patches/0080-timer-Clean-up-usage-of-timer-heap.patch | 434 |
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; @@ -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 + |