diff options
55 files changed, 596 insertions, 146 deletions
@@ -209,7 +209,9 @@ ifeq ($(AST_DEVMODE),yes) ifeq ($(AST_DEVMODE_STRICT),yes) _ASTCFLAGS+=-Wshadow endif - ADDL_TARGETS+=validate-docs + ifneq ($(DISABLE_XMLDOC),yes) + ADDL_TARGETS+=validate-docs + endif endif ifneq ($(findstring BSD,$(OSARCH)),) @@ -247,6 +249,14 @@ ifneq ($(wildcard .svn),) ASTERISKVERSIONNUM:=999999 endif +ifneq ($(DISABLE_XMLDOC),yes) + CORE_XMLDOC=doc/core-en_US.xml + FULL_XMLDOC=doc/full-en_US.xml +else + CORE_XMLDOC= + FULL_XMLDOC= +endif + _ASTCFLAGS+=$(OPTIONS) MOD_SUBDIRS:=third-party channels pbx apps codecs formats cdr cel bridges funcs tests main res addons $(LOCAL_MOD_SUBDIRS) @@ -327,9 +337,9 @@ full: _full @echo " +-------------------------------------------+" -_all: makeopts $(SUBDIRS) doc/core-en_US.xml $(ADDL_TARGETS) +_all: makeopts $(SUBDIRS) $(CORE_XMLDOC) $(ADDL_TARGETS) -_full: makeopts $(SUBDIRS) doc/full-en_US.xml $(ADDL_TARGETS) +_full: makeopts $(SUBDIRS) $(FULL_XMLDOC) $(ADDL_TARGETS) makeopts: configure @echo "****" @@ -424,7 +434,7 @@ distclean: $(SUBDIRS_DIST_CLEAN) _clean rm -f doc/asterisk-ng-doxygen rm -f build_tools/menuselect-deps -datafiles: _all doc/core-en_US.xml +datafiles: _all $(CORE_XMLDOC) CFLAGS="$(_ASTCFLAGS) $(ASTCFLAGS)" build_tools/mkpkgconfig "$(DESTDIR)$(libdir)/pkgconfig"; # # Recursively install contents of the static-http directory, in case @@ -436,8 +446,10 @@ datafiles: _all doc/core-en_US.xml $(INSTALL) -m 644 $$x "$(DESTDIR)$(ASTDATADIR)/$$x" ; \ fi \ done +ifneq ($(DISABLE_XMLDOC),yes) $(INSTALL) -m 644 doc/core-en_US.xml "$(DESTDIR)$(ASTDATADIR)/static-http"; $(INSTALL) -m 644 doc/appdocsxml.xslt "$(DESTDIR)$(ASTDATADIR)/static-http"; +endif if [ -d doc/tex/asterisk ] ; then \ $(INSTALL) -d "$(DESTDIR)$(ASTDATADIR)/static-http/docs" ; \ for n in doc/tex/asterisk/* ; do \ @@ -566,9 +578,11 @@ bininstall: _all installdirs $(SUBDIRS_INSTALL) main-bininstall for h in $(OLDHEADERS); do rm -f "$(DESTDIR)$(ASTHEADERDIR)/$$h"; done \ fi +ifneq ($(DISABLE_XMLDOC),yes) $(INSTALL) -m 644 doc/core-*.xml "$(DESTDIR)$(ASTDATADIR)/documentation" $(INSTALL) -m 644 doc/appdocsxml.xslt "$(DESTDIR)$(ASTDATADIR)/documentation" $(INSTALL) -m 644 doc/appdocsxml.dtd "$(DESTDIR)$(ASTDATADIR)/documentation" +endif $(INSTALL) -m 644 doc/asterisk.8 "$(DESTDIR)$(ASTMANDIR)/man8" $(INSTALL) -m 644 doc/astdb*.8 "$(DESTDIR)$(ASTMANDIR)/man8" $(INSTALL) -m 644 contrib/scripts/astgenkey.8 "$(DESTDIR)$(ASTMANDIR)/man8" diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index d218d0f2e..73dff8634 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -2386,21 +2386,12 @@ static int confbridge_exec(struct ast_channel *chan, const char *data) user.tech_args.drop_silence = 1; } - if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER)) { - char *func_jb; - if ((func_jb = ast_module_helper("", "func_jitterbuffer", 0, 0, 0, 0))) { - ast_free(func_jb); - ast_func_write(chan, "JITTERBUFFER(adaptive)", "default"); - } + if (ast_test_flag(&user.u_profile, USER_OPT_JITTERBUFFER) && ast_module_check("func_jitterbuffer.so")) { + ast_func_write(chan, "JITTERBUFFER(adaptive)", "default"); } - if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE)) { - char *mod_speex; - /* Reduce background noise from each participant */ - if ((mod_speex = ast_module_helper("", "codec_speex", 0, 0, 0, 0))) { - ast_free(mod_speex); - ast_func_write(chan, "DENOISE(rx)", "on"); - } + if (ast_test_flag(&user.u_profile, USER_OPT_DENOISE) && ast_module_check("codec_speex.so")) { + ast_func_write(chan, "DENOISE(rx)", "on"); } /* if this user has a intro, play it before entering */ diff --git a/apps/app_meetme.c b/apps/app_meetme.c index 7ca9ba39f..5567fe036 100644 --- a/apps/app_meetme.c +++ b/apps/app_meetme.c @@ -3198,7 +3198,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc struct timeval now; struct ast_dsp *dsp = NULL; struct ast_app *agi_app; - char *agifile, *mod_speex; + char *agifile; const char *agifiledefault = "conf-background.agi", *tmpvar; char meetmesecs[30] = ""; char exitcontext[AST_MAX_CONTEXT] = ""; @@ -3588,9 +3588,7 @@ static int conf_run(struct ast_channel *chan, struct ast_conference *conf, struc } /* Reduce background noise from each participant */ - if (!ast_test_flag64(confflags, CONFFLAG_DONT_DENOISE) && - (mod_speex = ast_module_helper("", "func_speex", 0, 0, 0, 0))) { - ast_free(mod_speex); + if (!ast_test_flag64(confflags, CONFFLAG_DONT_DENOISE) && ast_module_check("func_speex.so")) { ast_func_write(chan, "DENOISE(rx)", "on"); } diff --git a/apps/app_mixmonitor.c b/apps/app_mixmonitor.c index ac4564205..2922e0cd3 100644 --- a/apps/app_mixmonitor.c +++ b/apps/app_mixmonitor.c @@ -34,6 +34,7 @@ */ /*** MODULEINFO + <use type="module">func_periodic_hook</use> <support_level>core</support_level> ***/ diff --git a/bridges/bridge_builtin_features.c b/bridges/bridge_builtin_features.c index 332857347..e6cacbf7e 100644 --- a/bridges/bridge_builtin_features.c +++ b/bridges/bridge_builtin_features.c @@ -26,6 +26,7 @@ */ /*** MODULEINFO + <use type="module">res_monitor</use> <support_level>core</support_level> ***/ diff --git a/build_tools/menuselect-deps.in b/build_tools/menuselect-deps.in index ec70be0da..9becdb62e 100644 --- a/build_tools/menuselect-deps.in +++ b/build_tools/menuselect-deps.in @@ -45,6 +45,7 @@ NEON29=@PBX_NEON29@ OGG=@PBX_OGG@ OPENH323=@PBX_OPENH323@ OPUS=@PBX_OPUS@ +OPUSFILE=@PBX_OPUSFILE@ OSPTK=@PBX_OSPTK@ OSS=@PBX_OSS@ PGSQL=@PBX_PGSQL@ diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c index 04aa228bf..69261f35a 100644 --- a/channels/chan_iax2.c +++ b/channels/chan_iax2.c @@ -52,7 +52,7 @@ */ /*** MODULEINFO - <use type="external">crypto</use> + <use type="module">res_crypto</use> <support_level>core</support_level> ***/ diff --git a/channels/chan_rtp.c b/channels/chan_rtp.c index e1c29a2ac..0a59e330e 100644 --- a/channels/chan_rtp.c +++ b/channels/chan_rtp.c @@ -28,6 +28,7 @@ */ /*** MODULEINFO + <depend>res_rtp_multicast</depend> <support_level>core</support_level> ***/ @@ -718,6 +718,7 @@ PBX_DYNAMIC_LIST POW_LIB PBX_WORKING_FORK LIBOBJS +DISABLE_XMLDOC CONFIG_LIBXML2 UUID_LIB UUID_INCLUDE @@ -1007,6 +1008,10 @@ PBX_OSPTK OSPTK_DIR OSPTK_INCLUDE OSPTK_LIB +PBX_OPUSFILE +OPUSFILE_DIR +OPUSFILE_INCLUDE +OPUSFILE_LIB PBX_OPUS OPUS_DIR OPUS_INCLUDE @@ -1434,6 +1439,7 @@ with_newt with_ogg with_openr2 with_opus +with_opusfile with_osptk with_oss with_postgres @@ -2190,6 +2196,7 @@ Optional Packages: --with-ogg=PATH use OGG files in PATH --with-openr2=PATH use MFR2 files in PATH --with-opus=PATH use Opus files in PATH + --with-opusfile=PATH use Opusfile files in PATH --with-osptk=PATH use OSP Toolkit files in PATH --with-oss=PATH use Open Sound System files in PATH --with-postgres=PATH use PostgreSQL files in PATH @@ -11356,6 +11363,38 @@ fi + OPUSFILE_DESCRIP="Opusfile" + OPUSFILE_OPTION="opusfile" + PBX_OPUSFILE=0 + +# Check whether --with-opusfile was given. +if test "${with_opusfile+set}" = set; then : + withval=$with_opusfile; + case ${withval} in + n|no) + USE_OPUSFILE=no + # -1 is a magic value used by menuselect to know that the package + # was disabled, other than 'not found' + PBX_OPUSFILE=-1 + ;; + y|ye|yes) + ac_mandatory_list="${ac_mandatory_list} OPUSFILE" + ;; + *) + OPUSFILE_DIR="${withval}" + ac_mandatory_list="${ac_mandatory_list} OPUSFILE" + ;; + esac + +fi + + + + + + + + OSPTK_DESCRIP="OSP Toolkit" OSPTK_OPTION="osptk" PBX_OSPTK=0 @@ -14660,16 +14699,20 @@ fi # Check whether --enable-xmldoc was given. if test "${enable_xmldoc+set}" = set; then : enableval=$enable_xmldoc; case "${enableval}" in - y|ye|yes) disable_xmldoc=no ;; - n|no) disable_xmldoc=yes ;; + y|ye|yes) DISABLE_XMLDOC=no ;; + n|no) DISABLE_XMLDOC=yes ;; *) as_fn_error $? "bad value ${enableval} for --disable-xmldoc" "$LINENO" 5 ;; esac else - disable_xmldoc=no + DISABLE_XMLDOC=no fi -if test "${disable_xmldoc}" != "yes"; then + +if test "${DISABLE_XMLDOC}" != "yes"; then + +$as_echo "#define AST_XML_DOCS 1" >>confdefs.h + if test "x${PBX_LIBXSLT}" != "x1" -a "${USE_LIBXSLT}" != "no"; then pbxlibdir="" @@ -30421,6 +30464,116 @@ _ACEOF fi +# opusfile.h includes <opus_multistream.h> so we need to make sure that +# either $OPUS_INCLUDE or /usr/include/opus is added to the search path. +__opus_include=${OPUS_INCLUDE} +if test -z "$__opus_include" -o x"$__opus_include" = x" " ; then + __opus_include=-I/usr/include/opus +fi + +if test "x${PBX_OPUSFILE}" != "x1" -a "${USE_OPUSFILE}" != "no"; then + pbxlibdir="" + # if --with-OPUSFILE=DIR has been specified, use it. + if test "x${OPUSFILE_DIR}" != "x"; then + if test -d ${OPUSFILE_DIR}/lib; then + pbxlibdir="-L${OPUSFILE_DIR}/lib" + else + pbxlibdir="-L${OPUSFILE_DIR}" + fi + fi + pbxfuncname="op_open_callbacks" + if test "x${pbxfuncname}" = "x" ; then # empty lib, assume only headers + AST_OPUSFILE_FOUND=yes + else + ast_ext_lib_check_save_CFLAGS="${CFLAGS}" + CFLAGS="${CFLAGS} $__opus_include" + as_ac_Lib=`$as_echo "ac_cv_lib_opusfile_${pbxfuncname}" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${pbxfuncname} in -lopusfile" >&5 +$as_echo_n "checking for ${pbxfuncname} in -lopusfile... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lopusfile ${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 ${pbxfuncname} (); +int +main () +{ +return ${pbxfuncname} (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + AST_OPUSFILE_FOUND=yes +else + AST_OPUSFILE_FOUND=no +fi + + CFLAGS="${ast_ext_lib_check_save_CFLAGS}" + fi + + # now check for the header. + if test "${AST_OPUSFILE_FOUND}" = "yes"; then + OPUSFILE_LIB="${pbxlibdir} -lopusfile " + # if --with-OPUSFILE=DIR has been specified, use it. + if test "x${OPUSFILE_DIR}" != "x"; then + OPUSFILE_INCLUDE="-I${OPUSFILE_DIR}/include" + fi + OPUSFILE_INCLUDE="${OPUSFILE_INCLUDE} $__opus_include" + if test "xopus/opusfile.h" = "x" ; then # no header, assume found + OPUSFILE_HEADER_FOUND="1" + else # check for the header + ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${CPPFLAGS} ${OPUSFILE_INCLUDE}" + ac_fn_c_check_header_mongrel "$LINENO" "opus/opusfile.h" "ac_cv_header_opus_opusfile_h" "$ac_includes_default" +if test "x$ac_cv_header_opus_opusfile_h" = xyes; then : + OPUSFILE_HEADER_FOUND=1 +else + OPUSFILE_HEADER_FOUND=0 +fi + + + CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}" + fi + if test "x${OPUSFILE_HEADER_FOUND}" = "x0" ; then + OPUSFILE_LIB="" + OPUSFILE_INCLUDE="" + else + if test "x${pbxfuncname}" = "x" ; then # only checking headers -> no library + OPUSFILE_LIB="" + fi + PBX_OPUSFILE=1 + cat >>confdefs.h <<_ACEOF +#define HAVE_OPUSFILE 1 +_ACEOF + + fi + fi +fi + + if test "${USE_PWLIB}" != "no"; then if test -n "${PWLIB_DIR}"; then diff --git a/configure.ac b/configure.ac index c729b94ab..23ff5265a 100644 --- a/configure.ac +++ b/configure.ac @@ -503,6 +503,7 @@ AST_EXT_LIB_SETUP([NEWT], [newt], [newt]) AST_EXT_LIB_SETUP([OGG], [OGG], [ogg]) AST_EXT_LIB_SETUP([OPENR2], [MFR2], [openr2]) AST_EXT_LIB_SETUP([OPUS], [Opus], [opus]) +AST_EXT_LIB_SETUP([OPUSFILE], [Opusfile], [opusfile]) AST_EXT_LIB_SETUP([OSPTK], [OSP Toolkit], [osptk]) AST_EXT_LIB_SETUP([OSS], [Open Sound System], [oss]) AST_EXT_LIB_SETUP([PGSQL], [PostgreSQL], [postgres]) @@ -690,12 +691,14 @@ AC_ARG_ENABLE([xmldoc], [AS_HELP_STRING([--disable-xmldoc], [Explicitly disable XML documentation])], [case "${enableval}" in - y|ye|yes) disable_xmldoc=no ;; - n|no) disable_xmldoc=yes ;; + y|ye|yes) DISABLE_XMLDOC=no ;; + n|no) DISABLE_XMLDOC=yes ;; *) AC_MSG_ERROR(bad value ${enableval} for --disable-xmldoc) ;; - esac], [disable_xmldoc=no]) + esac], [DISABLE_XMLDOC=no]) -if test "${disable_xmldoc}" != "yes"; then +AC_SUBST([DISABLE_XMLDOC]) +if test "${DISABLE_XMLDOC}" != "yes"; then + AC_DEFINE([AST_XML_DOCS], 1, [Define to enable XML documentation.]) AST_EXT_LIB_CHECK([LIBXSLT], [xslt], [xsltLoadStylesheetPI], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}]) AST_EXT_LIB_CHECK([LIBXSLT_CLEANUP], [xslt], [xsltCleanupGlobals], [libxslt/xsltInternals.h], [${LIBXML2_LIB}], [${LIBXML2_INCLUDE}]) @@ -2348,6 +2351,13 @@ AST_EXT_LIB_CHECK([SS7], [ss7], [ss7_set_isup_timer], [libss7.h]) AST_EXT_LIB_CHECK([OPENR2], [openr2], [openr2_chan_new], [openr2.h]) AST_EXT_LIB_CHECK([OPUS], [opus], [opus_encoder_create], [opus/opus.h]) +# opusfile.h includes <opus_multistream.h> so we need to make sure that +# either $OPUS_INCLUDE or /usr/include/opus is added to the search path. +__opus_include=${OPUS_INCLUDE} +if test -z "$__opus_include" -o x"$__opus_include" = x" " ; then + __opus_include=-I/usr/include/opus +fi +AST_EXT_LIB_CHECK([OPUSFILE], [opusfile], [op_open_callbacks], [opus/opusfile.h], [], [$__opus_include]) if test "${USE_PWLIB}" != "no"; then if test -n "${PWLIB_DIR}"; then diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper index e5fc44eb3..9b01a4239 100755 --- a/contrib/scripts/ast_coredumper +++ b/contrib/scripts/ast_coredumper @@ -17,6 +17,7 @@ SYNOPSIS [ --tarball-results ] [ --delete-results-after ] [ --tarball-uniqueid="<uniqueid>" ] [ --no-default-search ] [ --append-coredumps ] + [ --asterisk-bin="path" ] [ <coredump> | <pattern> ... ] DESCRIPTION @@ -102,6 +103,10 @@ DESCRIPTION Append any coredumps specified on the command line to the config file specified ones instead of overriding them. + --asterisk-binary + Path to the asterisk binary. Default: look for asterisk + in the PATH. + <coredump> | <pattern> A list of coredumps or coredump search patterns. Unless --append-coredumps was specified, these entries will override @@ -267,6 +272,9 @@ for a in "$@" ; do --tarball-uniqueid=*) tarball_uniqueid=${a#*=} ;; + --asterisk-bin=*) + asterisk_bin=${a#*=} + ;; --help|-*) print_help ;; @@ -368,7 +376,10 @@ tail -n +${ss} $0 >/tmp/.ast_coredumper.gdbinit for i in ${!COREDUMPS[@]} ; do cf=${COREDUMPS[$i]} echo "Processing $cf" - ${GDB} -n --batch -q --ex "source /tmp/.ast_coredumper.gdbinit" $(which asterisk) "$cf" 2>/dev/null | ( + if [ -z "$asterisk_bin" ]; then + asterisk_bin=$(which asterisk) + fi + ${GDB} -n --batch -q --ex "source /tmp/.ast_coredumper.gdbinit" "$asterisk_bin" "$cf" 2>/dev/null | ( of=/dev/null while IFS= read line ; do if [[ "$line" =~ !@!@!@!\ ([^\ ]+)\ !@!@!@! ]] ; then diff --git a/contrib/scripts/install_prereq b/contrib/scripts/install_prereq index d69f5527a..c4b91f6f8 100755 --- a/contrib/scripts/install_prereq +++ b/contrib/scripts/install_prereq @@ -165,22 +165,18 @@ install_unpackaged() { /sbin/ldconfig fi - # Only install libsrtp if it wasn't installed via package + # Only install libsrtp2 if it wasn't installed via package if ! test -f /usr/include/srtp/srtp.h; then - echo "*** Installing libsrtp ***" - if [ ! -d libsrtp ]; then - git clone https://github.com/cisco/libsrtp.git - cd libsrtp - else - cd libsrtp - git pull + if ! test -f /usr/include/srtp2/srtp.h; then + echo "*** Installing libsrtp2 ***" + wget -O - http://github.com/cisco/libsrtp/archive/v2.tar.gz | zcat | tar -xf - + cd libsrtp-2 + ./configure --enable-openssl + make shared_library uninstall install + cd .. + echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local.conf + /sbin/ldconfig fi - git checkout "1_5_x_throttle" - ./configure --disable-debug --disable-stdout --enable-openssl - make shared_library uninstall install - cd .. - echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local.conf - /sbin/ldconfig fi # Only install pjproject if it wasn't installed via package diff --git a/funcs/func_aes.c b/funcs/func_aes.c index 9392a1c7d..7208cd4c8 100644 --- a/funcs/func_aes.c +++ b/funcs/func_aes.c @@ -23,7 +23,7 @@ */ /*** MODULEINFO - <use type="external">crypto</use> + <use type="module">res_crypto</use> <support_level>core</support_level> ***/ diff --git a/funcs/func_periodic_hook.c b/funcs/func_periodic_hook.c index f8e79b326..0ab3d6b8b 100644 --- a/funcs/func_periodic_hook.c +++ b/funcs/func_periodic_hook.c @@ -488,6 +488,11 @@ static int load_module(void) res = ast_custom_function_register_escalating(&hook_function, AST_CFE_BOTH); + if (!res) { + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + } + return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS; } diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index f85ad8d07..cfa260b21 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -9,6 +9,9 @@ /* Define to 1 if internal poll should be used. */ #undef AST_POLL_COMPAT +/* Define to enable XML documentation. */ +#undef AST_XML_DOCS + /* Define to 1 if your system's implementation of mutexes supports comparison of a mutex to its initializer. */ #undef CAN_COMPARE_MUTEX_TO_INIT_VALUE @@ -585,6 +588,9 @@ /* Define to 1 if you have the Opus library. */ #undef HAVE_OPUS +/* Define to 1 if you have the Opusfile library. */ +#undef HAVE_OPUSFILE + /* Define this to indicate the ${OSPTK_DESCRIP} library */ #undef HAVE_OSPTK diff --git a/include/asterisk/module.h b/include/asterisk/module.h index e614a726f..6c60429c9 100644 --- a/include/asterisk/module.h +++ b/include/asterisk/module.h @@ -94,6 +94,20 @@ enum ast_module_support_level { AST_MODULE_SUPPORT_DEPRECATED, }; +/*! Used to specify which modules should be returned by ast_module_helper. */ +enum ast_module_helper_type { + /*! Modules that are loaded by dlopen. */ + AST_MODULE_HELPER_LOADED = 0, + /*! Running modules that include a reload callback. */ + AST_MODULE_HELPER_RELOAD = 1, + /*! Modules that can be loaded or started. */ + AST_MODULE_HELPER_LOAD, + /*! Modules that can be unloaded. */ + AST_MODULE_HELPER_UNLOAD, + /*! Running modules */ + AST_MODULE_HELPER_RUNNING, +}; + /*! * \brief Load a module. * \param resource_name The name of the module to load. @@ -237,14 +251,13 @@ int ast_loader_unregister(int (*updater)(void)); * \param state The possible match to return. * \param rpos The position we should be matching. This should be the same as * pos. - * \param needsreload This should be 1 if we need to reload this module and 0 - * otherwise. This function will only return modules that are reloadble - * if this is 1. + * \param type The type of action that will be performed by CLI. + * This argument accepts values of enum ast_module_helper_type. * * \retval A possible completion of the partial match. * \retval NULL if no matches were found. */ -char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload); +char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int type); /* Opaque type for module handles generated by the loader */ diff --git a/include/asterisk/res_pjsip_session.h b/include/asterisk/res_pjsip_session.h index 70f94682e..de6589abd 100644 --- a/include/asterisk/res_pjsip_session.h +++ b/include/asterisk/res_pjsip_session.h @@ -111,6 +111,8 @@ struct ast_sip_session_media { char label[AST_UUID_STR_LEN]; /*! \brief The underlying session has been changed in some fashion */ unsigned int changed; + /*! \brief Remote media stream label */ + char *remote_mslabel; }; /*! diff --git a/include/asterisk/stream.h b/include/asterisk/stream.h index 4027231ed..bbde73d1a 100644 --- a/include/asterisk/stream.h +++ b/include/asterisk/stream.h @@ -465,4 +465,25 @@ struct ast_stream *ast_stream_topology_get_first_stream_by_type( void ast_stream_topology_map(const struct ast_stream_topology *topology, struct ast_vector_int *types, struct ast_vector_int *v0, struct ast_vector_int *v1); +/*! + * \brief Get the stream group that a stream is part of + * + * \param stream The stream + * + * \return the numerical stream group (-1 if not in a group) + * + * \since 15.2.0 + */ +int ast_stream_get_group(const struct ast_stream *stream); + +/*! + * \brief Set the stream group for a stream + * + * \param stream The stream + * \param group The group the stream is part of + * + * \since 15.2.0 + */ +void ast_stream_set_group(struct ast_stream *stream, int group); + #endif /* _AST_STREAM_H */ diff --git a/include/asterisk/xml.h b/include/asterisk/xml.h index 063e8c0b3..ab7b630a2 100644 --- a/include/asterisk/xml.h +++ b/include/asterisk/xml.h @@ -246,10 +246,5 @@ struct ast_xml_node *ast_xml_xpath_get_first_result(struct ast_xml_xpath_results */ struct ast_xml_xpath_results *ast_xml_query(struct ast_xml_doc *doc, const char *xpath_str); -/* Features using ast_xml_ */ -#ifdef HAVE_LIBXML2 -#define AST_XML_DOCS -#endif - #endif /* _ASTERISK_XML_H */ diff --git a/main/Makefile b/main/Makefile index 968f74658..08d1f6558 100644 --- a/main/Makefile +++ b/main/Makefile @@ -149,7 +149,7 @@ endif db.o: _ASTCFLAGS+=$(SQLITE3_INCLUDE) asterisk.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE) -cli.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE) +loader.o: _ASTCFLAGS+=$(LIBEDIT_INCLUDE) json.o: _ASTCFLAGS+=$(JANSSON_INCLUDE) bucket.o: _ASTCFLAGS+=$(URIPARSER_INCLUDE) crypt.o: _ASTCFLAGS+=$(CRYPT_INCLUDE) diff --git a/main/aoc.c b/main/aoc.c index d4b74ec92..451b21973 100644 --- a/main/aoc.c +++ b/main/aoc.c @@ -1713,7 +1713,7 @@ static struct ast_json *s_to_json(const struct ast_aoc_decoded *decoded) } for (i = 0; i < decoded->aoc_s_count; ++i) { - struct ast_json *rate = ast_json_object_create(); + struct ast_json *rate; RAII_VAR(struct ast_json *, type, NULL, ast_json_unref); RAII_VAR(struct ast_json *, currency, NULL, ast_json_unref); const char *charge_item = aoc_charged_item_str( diff --git a/main/channel.c b/main/channel.c index 7d6e5db07..7eb40d195 100644 --- a/main/channel.c +++ b/main/channel.c @@ -5054,7 +5054,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame case AST_FRAME_VIDEO: /* XXX Handle translation of video codecs one day XXX */ if (ast_channel_tech(chan)->write_stream) { - res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr); + if (stream) { + res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr); + } else { + res = 0; + } } else if ((stream == default_stream) && ast_channel_tech(chan)->write_video) { res = ast_channel_tech(chan)->write_video(chan, fr); } else { @@ -5063,7 +5067,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame break; case AST_FRAME_MODEM: if (ast_channel_tech(chan)->write_stream) { - res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr); + if (stream) { + res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), fr); + } else { + res = 0; + } } else if ((stream == default_stream) && ast_channel_tech(chan)->write) { res = ast_channel_tech(chan)->write(chan, fr); } else { @@ -5251,7 +5259,11 @@ int ast_write_stream(struct ast_channel *chan, int stream_num, struct ast_frame f = NULL; } else { if (ast_channel_tech(chan)->write_stream) { - res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), f); + if (stream) { + res = ast_channel_tech(chan)->write_stream(chan, ast_stream_get_position(stream), f); + } else { + res = 0; + } } else if ((stream == default_stream) && ast_channel_tech(chan)->write) { res = ast_channel_tech(chan)->write(chan, f); } else { diff --git a/main/cli.c b/main/cli.c index ef86e256a..0896181b0 100644 --- a/main/cli.c +++ b/main/cli.c @@ -45,7 +45,6 @@ #include <regex.h> #include <pwd.h> #include <grp.h> -#include <editline/readline.h> #include "asterisk/cli.h" #include "asterisk/linkedlists.h" @@ -224,28 +223,6 @@ static int cli_has_permissions(int uid, int gid, const char *command) static AST_RWLIST_HEAD_STATIC(helpers, ast_cli_entry); -static char *complete_fn(const char *word, int state) -{ - char *c, *d; - char filename[PATH_MAX]; - - if (word[0] == '/') - ast_copy_string(filename, word, sizeof(filename)); - else - snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_MODULE_DIR, word); - - c = d = filename_completion_function(filename, state); - - if (c && word[0] != '/') - c += (strlen(ast_config_AST_MODULE_DIR) + 1); - if (c) - c = ast_strdup(c); - - ast_std_free(d); - - return c; -} - static char *handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { /* "module load <mod>" */ @@ -258,12 +235,14 @@ static char *handle_load(struct ast_cli_entry *e, int cmd, struct ast_cli_args * return NULL; case CLI_GENERATE: - if (a->pos != e->args) + if (a->pos != e->args) { return NULL; - return complete_fn(a->word, a->n); + } + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOAD); } - if (a->argc != e->args + 1) + if (a->argc != e->args + 1) { return CLI_SHOWUSAGE; + } if (ast_load_resource(a->argv[e->args])) { ast_cli(a->fd, "Unable to load module %s\n", a->argv[e->args]); return CLI_FAILURE; @@ -286,7 +265,7 @@ static char *handle_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args return NULL; case CLI_GENERATE: - return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 1); + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RELOAD); } if (a->argc == e->args) { ast_module_reload(NULL); @@ -482,7 +461,7 @@ static char *handle_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args } } else if ((a->pos == 4 && !atleast && strcasecmp(argv3, "off") && strcasecmp(argv3, "channel")) || (a->pos == 5 && atleast)) { - return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0); + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_RUNNING); } return NULL; } @@ -733,7 +712,7 @@ static char *handle_unload(struct ast_cli_entry *e, int cmd, struct ast_cli_args return NULL; case CLI_GENERATE: - return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0); + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_UNLOAD); } if (a->argc < e->args + 1) return CLI_SHOWUSAGE; @@ -889,10 +868,11 @@ static char *handle_modlist(struct ast_cli_entry *e, int cmd, struct ast_cli_arg return NULL; case CLI_GENERATE: - if (a->pos == e->args) - return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, 0); - else + if (a->pos == e->args) { + return ast_module_helper(a->line, a->word, a->pos, a->n, a->pos, AST_MODULE_HELPER_LOADED); + } else { return NULL; + } } /* all the above return, so we proceed with the handler. * we are guaranteed to have argc >= e->args @@ -1690,10 +1670,12 @@ static char *handle_showchan(struct ast_cli_entry *e, int cmd, struct ast_cli_ar "Name: %s\n" " Type: %s\n" " State: %s\n" + " Group: %d\n" " Formats: %s\n", ast_stream_get_name(stream), ast_codec_media_type2str(ast_stream_get_type(stream)), ast_stream_state2str(ast_stream_get_state(stream)), + ast_stream_get_group(stream), ast_format_cap_get_names(ast_stream_get_formats(stream), &codec_buf) ); } diff --git a/main/config_options.c b/main/config_options.c index 8eacbda35..3c0959ea3 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -80,7 +80,6 @@ struct aco_option { #ifdef AST_XML_DOCS static struct ao2_container *xmldocs; -#endif /* AST_XML_DOCS */ /*! \brief Value of the aco_option_type enum as strings */ static char *aco_option_type_string[] = { @@ -98,6 +97,7 @@ static char *aco_option_type_string[] = { "Unsigned Integer", /* OPT_UINT_T, */ "Boolean", /* OPT_YESNO_T, */ }; +#endif /* AST_XML_DOCS */ void *aco_pending_config(struct aco_info *info) { diff --git a/main/features.c b/main/features.c index 61d9e511f..516c64a4a 100644 --- a/main/features.c +++ b/main/features.c @@ -196,7 +196,6 @@ <value name="FAILURE" /> <value name="LOOP" /> <value name="NONEXISTENT" /> - <value name="INCOMPATIBLE" /> </variable> </variablelist> </description> @@ -1006,6 +1005,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data) const char *extension; int priority; int bridge_add_failed; + int res = -1; struct ast_bridge_features chan_features; struct ast_bridge_features *peer_features; struct ast_bridge *bridge; @@ -1032,6 +1032,7 @@ static int bridge_exec(struct ast_channel *chan, const char *data) if (!current_dest_chan) { ast_log(LOG_WARNING, "Bridge failed because channel %s does not exist\n", args.dest_chan); + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "NONEXISTENT"); return 0; } @@ -1039,13 +1040,13 @@ static int bridge_exec(struct ast_channel *chan, const char *data) if (chan == current_dest_chan) { ast_channel_unref(current_dest_chan); ast_log(LOG_WARNING, "Unable to bridge channel %s with itself\n", ast_channel_name(chan)); + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "LOOP"); return 0; } if (ast_test_flag(&opts, OPT_DURATION_LIMIT) && !ast_strlen_zero(opt_args[OPT_ARG_DURATION_LIMIT]) && ast_bridge_timelimit(chan, &bconfig, opt_args[OPT_ARG_DURATION_LIMIT], &calldurationlimit)) { - pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE"); goto done; } @@ -1124,14 +1125,18 @@ static int bridge_exec(struct ast_channel *chan, const char *data) /* Don't keep the channel ref in case it was not already in a bridge. */ current_dest_chan = ast_channel_unref(current_dest_chan); - ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, + res = ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, AST_BRIDGE_JOIN_PASS_REFERENCE); ast_bridge_features_cleanup(&chan_features); - /* The bridge has ended, set BRIDGERESULT to SUCCESS. */ - pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS"); done: + if (res == -1) { + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "FAILURE"); + } else { + pbx_builtin_setvar_helper(chan, "BRIDGERESULT", "SUCCESS"); + } + ast_free((char *) bconfig.warning_sound); ast_free((char *) bconfig.end_sound); ast_free((char *) bconfig.start_sound); diff --git a/main/loader.c b/main/loader.c index d5500076b..fc3e9a374 100644 --- a/main/loader.c +++ b/main/loader.c @@ -36,6 +36,7 @@ #include "asterisk/_private.h" #include "asterisk/paths.h" /* use ast_config_AST_MODULE_DIR */ #include <dirent.h> +#include <editline/readline.h> #include "asterisk/dlinkedlists.h" #include "asterisk/module.h" @@ -702,32 +703,121 @@ int ast_unload_resource(const char *resource_name, enum ast_module_unload_mode f return res; } -char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int needsreload) +static int module_matches_helper_type(struct ast_module *mod, enum ast_module_helper_type type) { - struct ast_module *cur; - int i, which=0, l = strlen(word); + switch (type) { + case AST_MODULE_HELPER_UNLOAD: + return !mod->usecount && mod->flags.running && !mod->flags.declined; + + case AST_MODULE_HELPER_RELOAD: + return mod->flags.running && mod->info->reload; + + case AST_MODULE_HELPER_RUNNING: + return mod->flags.running; + + case AST_MODULE_HELPER_LOADED: + /* if we have a 'struct ast_module' then we're loaded. */ + return 1; + default: + /* This function is not called for AST_MODULE_HELPER_LOAD. */ + /* Unknown ast_module_helper_type. Assume it doesn't match. */ + ast_assert(0); + + return 0; + } +} + +static char *module_load_helper(const char *word, int state) +{ + struct ast_module *mod; + int which = 0; + char *name; char *ret = NULL; + char *editline_ret; + char fullpath[PATH_MAX]; + int idx = 0; + /* This is needed to avoid listing modules that are already running. */ + AST_VECTOR(, char *) running_modules; - if (pos != rpos) - return NULL; + AST_VECTOR_INIT(&running_modules, 200); AST_DLLIST_LOCK(&module_list); - AST_DLLIST_TRAVERSE(&module_list, cur, entry) { - if (!strncasecmp(word, cur->resource, l) && - (cur->info->reload || !needsreload) && - ++which > state) { - ret = ast_strdup(cur->resource); - break; + AST_DLLIST_TRAVERSE(&module_list, mod, entry) { + if (mod->flags.running) { + AST_VECTOR_APPEND(&running_modules, mod->resource); } } + + if (word[0] == '/') { + /* BUGBUG: we should not support this. */ + ast_copy_string(fullpath, word, sizeof(fullpath)); + } else { + snprintf(fullpath, sizeof(fullpath), "%s/%s", ast_config_AST_MODULE_DIR, word); + } + + /* + * This is ugly that we keep calling filename_completion_function. + * The only way to avoid this would be to make a copy of the function + * that skips matches found in the running_modules vector. + */ + while (!ret && (name = editline_ret = filename_completion_function(fullpath, idx++))) { + if (word[0] != '/') { + name += (strlen(ast_config_AST_MODULE_DIR) + 1); + } + + /* Don't list files that are already loaded! */ + if (!AST_VECTOR_GET_CMP(&running_modules, name, !strcasecmp) && ++which > state) { + ret = ast_strdup(name); + } + + ast_std_free(editline_ret); + } + + /* Do not clean-up the elements, they belong to module_list. */ + AST_VECTOR_FREE(&running_modules); AST_DLLIST_UNLOCK(&module_list); - if (!ret) { - for (i=0; !ret && reload_classes[i].name; i++) { - if (!strncasecmp(word, reload_classes[i].name, l) && ++which > state) - ret = ast_strdup(reload_classes[i].name); + return ret; +} + +char *ast_module_helper(const char *line, const char *word, int pos, int state, int rpos, int _type) +{ + enum ast_module_helper_type type = _type; + struct ast_module *mod; + int which = 0; + int wordlen = strlen(word); + char *ret = NULL; + + if (pos != rpos) { + return NULL; + } + + if (type == AST_MODULE_HELPER_LOAD) { + return module_load_helper(word, state); + } + + if (type == AST_MODULE_HELPER_RELOAD) { + int idx; + + for (idx = 0; reload_classes[idx].name; idx++) { + if (!strncasecmp(word, reload_classes[idx].name, wordlen) && ++which > state) { + return ast_strdup(reload_classes[idx].name); + } + } + } + + AST_DLLIST_LOCK(&module_list); + AST_DLLIST_TRAVERSE(&module_list, mod, entry) { + if (!module_matches_helper_type(mod, type)) { + continue; + } + + if (!strncasecmp(word, mod->resource, wordlen) && ++which > state) { + ret = ast_strdup(mod->resource); + break; } } + AST_DLLIST_UNLOCK(&module_list); return ret; } diff --git a/main/manager.c b/main/manager.c index 5c0b318b9..079dab77f 100644 --- a/main/manager.c +++ b/main/manager.c @@ -1653,8 +1653,10 @@ static AST_RWLIST_HEAD_STATIC(actions, manager_action); /*! \brief list of hooks registered */ static AST_RWLIST_HEAD_STATIC(manager_hooks, manager_custom_hook); +#ifdef AST_XML_DOCS /*! \brief A container of event documentation nodes */ static AO2_GLOBAL_OBJ_STATIC(event_docs); +#endif static int __attribute__((format(printf, 9, 0))) __manager_event_sessions( struct ao2_container *sessions, @@ -2305,7 +2307,9 @@ static int manager_displayconnects(struct mansession_session *session) return ret; } +#ifdef AST_XML_DOCS static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item *instance); +#endif static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) { diff --git a/main/sorcery.c b/main/sorcery.c index 61628fbf4..5ff1d106c 100644 --- a/main/sorcery.c +++ b/main/sorcery.c @@ -1633,6 +1633,7 @@ struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sor int res = 0; if (!object_type || !json) { + ast_json_unref(json); return NULL; } diff --git a/main/stream.c b/main/stream.c index 093cd5450..72d859954 100644 --- a/main/stream.c +++ b/main/stream.c @@ -67,6 +67,11 @@ struct ast_stream { ast_stream_data_free_fn data_free_fn[AST_STREAM_DATA_SLOT_MAX]; /*! + * \brief The group that the stream is part of + */ + int group; + + /*! * \brief Name for the stream within the context of the channel it is on */ char name[0]; @@ -90,6 +95,7 @@ struct ast_stream *ast_stream_alloc(const char *name, enum ast_media_type type) stream->type = type; stream->state = AST_STREAM_STATE_INACTIVE; + stream->group = -1; strcpy(stream->name, S_OR(name, "")); /* Safe */ return stream; @@ -115,6 +121,7 @@ struct ast_stream *ast_stream_clone(const struct ast_stream *stream, const char memcpy(new_stream, stream, sizeof(*new_stream)); strcpy(new_stream->name, stream_name); /* Safe */ + new_stream->group = -1; if (new_stream->formats) { ao2_ref(new_stream->formats, +1); } @@ -271,14 +278,16 @@ struct ast_stream_topology *ast_stream_topology_clone( } for (i = 0; i < AST_VECTOR_SIZE(&topology->streams); i++) { - struct ast_stream *stream = - ast_stream_clone(AST_VECTOR_GET(&topology->streams, i), NULL); + struct ast_stream *existing = AST_VECTOR_GET(&topology->streams, i); + struct ast_stream *stream = ast_stream_clone(existing, NULL); if (!stream || AST_VECTOR_APPEND(&new_topology->streams, stream)) { ast_stream_free(stream); ast_stream_topology_free(new_topology); return NULL; } + + ast_stream_set_group(stream, ast_stream_get_group(existing)); } return new_topology; @@ -563,3 +572,17 @@ void ast_stream_topology_map(const struct ast_stream_topology *topology, AST_VECTOR_REPLACE(v1, index, i); } } + +int ast_stream_get_group(const struct ast_stream *stream) +{ + ast_assert(stream != NULL); + + return stream->group; +} + +void ast_stream_set_group(struct ast_stream *stream, int group) +{ + ast_assert(stream != NULL); + + stream->group = group; +} diff --git a/makeopts.in b/makeopts.in index 7d0347ddc..e25b614e0 100644 --- a/makeopts.in +++ b/makeopts.in @@ -108,6 +108,7 @@ ASTVARRUNDIR = @astvarrundir@ AST_DEVMODE=@AST_DEVMODE@ AST_DEVMODE_STRICT=@AST_DEVMODE_STRICT@ +DISABLE_XMLDOC=@DISABLE_XMLDOC@ NOISY_BUILD=@NOISY_BUILD@ AST_CODE_COVERAGE=@AST_CODE_COVERAGE@ @@ -231,6 +232,9 @@ OGG_LIB=@OGG_LIB@ OPUS_INCLUDE=@OPUS_INCLUDE@ OPUS_LIB=@OPUS_LIB@ +OPUSFILE_INCLUDE=@OPUSFILE_INCLUDE@ +OPUSFILE_LIB=@OPUSFILE_LIB@ + OSPTK_INCLUDE=@OSPTK_INCLUDE@ OSPTK_LIB=@OSPTK_LIB@ diff --git a/pbx/pbx_dundi.c b/pbx/pbx_dundi.c index 58086aa81..b39cd7b2d 100644 --- a/pbx/pbx_dundi.c +++ b/pbx/pbx_dundi.c @@ -32,7 +32,7 @@ /*** MODULEINFO <depend>zlib</depend> - <use type="external">crypto</use> + <use type="module">res_crypto</use> <support_level>extended</support_level> ***/ diff --git a/res/ari/resource_asterisk.c b/res/ari/resource_asterisk.c index e76eb02bc..5c6a35af6 100644 --- a/res/ari/resource_asterisk.c +++ b/res/ari/resource_asterisk.c @@ -433,6 +433,10 @@ void ast_ari_asterisk_list_modules(struct ast_variable *headers, struct ast_json *json; json = ast_json_array_create(); + if (!json) { + ast_ari_response_alloc_failed(response); + return; + } ast_update_module_list_data(&process_module_list, NULL, json); ast_ari_response_ok(response, json); @@ -505,6 +509,7 @@ void ast_ari_asterisk_get_module(struct ast_variable *headers, ast_ari_response_error( response, 409, "Conflict", "Module information could not be retrieved"); + ast_json_unref(json); return; } @@ -667,10 +672,12 @@ void ast_ari_asterisk_list_log_channels(struct ast_variable *headers, if (res == AST_LOGGER_FAILURE) { ast_ari_response_error(response, 500, "Internal Server Error", "Response body is not valid"); + ast_json_unref(json); return; } else if (res == AST_LOGGER_ALLOC_ERROR) { ast_ari_response_error(response, 500, "Internal Server Error", "Allocation Failed"); + ast_json_unref(json); return; } diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h index e75d8e028..a3b6430ac 100644 --- a/res/ari/resource_bridges.h +++ b/res/ari/resource_bridges.h @@ -52,7 +52,7 @@ struct ast_ari_bridges_list_args { void ast_ari_bridges_list(struct ast_variable *headers, struct ast_ari_bridges_list_args *args, struct ast_ari_response *response); /*! Argument struct for ast_ari_bridges_create() */ struct ast_ari_bridges_create_args { - /*! Comma separated list of bridge type attributes (mixing, holding, dtmf_events, proxy_media). */ + /*! Comma separated list of bridge type attributes (mixing, holding, dtmf_events, proxy_media, video_sfu). */ const char *type; /*! Unique ID to give to the bridge being created. */ const char *bridge_id; @@ -82,7 +82,7 @@ int ast_ari_bridges_create_parse_body( void ast_ari_bridges_create(struct ast_variable *headers, struct ast_ari_bridges_create_args *args, struct ast_ari_response *response); /*! Argument struct for ast_ari_bridges_create_with_id() */ struct ast_ari_bridges_create_with_id_args { - /*! Comma separated list of bridge type attributes (mixing, holding, dtmf_events, proxy_media) to set. */ + /*! Comma separated list of bridge type attributes (mixing, holding, dtmf_events, proxy_media, video_sfu) to set. */ const char *type; /*! Unique ID to give to the bridge being created. */ const char *bridge_id; diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index 6027a8059..6b4f26c25 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -99,9 +99,13 @@ static int channel_state_invalid(struct stasis_app_control *control, || snapshot->state == AST_STATE_RINGING) { ast_ari_response_error(response, 412, "Precondition Failed", "Channel in invalid state"); + ao2_ref(snapshot, -1); + return -1; } + ao2_ref(snapshot, -1); + return 0; } diff --git a/res/ari/resource_events.c b/res/ari/resource_events.c index ed936f732..4be5d0223 100644 --- a/res/ari/resource_events.c +++ b/res/ari/resource_events.c @@ -23,6 +23,11 @@ * \author David M. Lee, II <dlee@digium.com> */ +/*** MODULEINFO + <depend type="module">res_http_websocket</depend> + <support_level>core</support_level> + ***/ + #include "asterisk.h" #include "resource_events.h" diff --git a/res/ari/resource_sounds.c b/res/ari/resource_sounds.c index 59ace5d81..2cb35b620 100644 --- a/res/ari/resource_sounds.c +++ b/res/ari/resource_sounds.c @@ -202,6 +202,7 @@ void ast_ari_sounds_list(struct ast_variable *headers, if (!ast_json_array_size(sounds_blob)) { ast_ari_response_error(response, 404, "Not Found", "No sounds found that matched the query"); + ast_json_unref(sounds_blob); return; } diff --git a/res/res_agi.c b/res/res_agi.c index 466063557..13af48f49 100644 --- a/res/res_agi.c +++ b/res/res_agi.c @@ -25,6 +25,7 @@ */ /*** MODULEINFO + <depend>res_speech</depend> <support_level>core</support_level> ***/ @@ -4713,6 +4714,10 @@ static int load_module(void) unload_module(); return AST_MODULE_LOAD_DECLINE; } + + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return AST_MODULE_LOAD_SUCCESS; } diff --git a/res/res_ari.c b/res/res_ari.c index 5145499be..9104eded3 100644 --- a/res/res_ari.c +++ b/res/res_ari.c @@ -73,6 +73,7 @@ /*** MODULEINFO <depend type="module">res_http_websocket</depend> + <depend type="module">res_stasis</depend> <support_level>core</support_level> ***/ @@ -984,9 +985,11 @@ static int ast_ari_callback(struct ast_tcptls_session_instance *ser, struct ast_str *buf = ast_str_create(512); char *str = ast_json_dump_string_format(body, ast_ari_json_format()); - if (!buf) { + if (!buf || !str) { ast_http_request_close_on_completion(ser); ast_http_error(ser, 500, "Server Error", "Out of memory"); + ast_json_free(str); + ast_free(buf); goto request_failed; } diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c index 60332f591..8e9aae9dd 100644 --- a/res/res_http_websocket.c +++ b/res/res_http_websocket.c @@ -1446,6 +1446,9 @@ static int load_module(void) ast_http_uri_link(&websocketuri); websocket_add_protocol_internal("echo", websocket_echo_callback); + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return 0; } diff --git a/res/res_monitor.c b/res/res_monitor.c index 3e3611b36..3ac6e455f 100644 --- a/res/res_monitor.c +++ b/res/res_monitor.c @@ -24,6 +24,7 @@ */ /*** MODULEINFO + <use type="module">func_periodic_hook</use> <support_level>core</support_level> ***/ @@ -984,6 +985,9 @@ static int load_module(void) ast_manager_register_xml("PauseMonitor", EVENT_FLAG_CALL, pause_monitor_action); ast_manager_register_xml("UnpauseMonitor", EVENT_FLAG_CALL, unpause_monitor_action); + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return AST_MODULE_LOAD_SUCCESS; } diff --git a/res/res_pjsip.c b/res/res_pjsip.c index 2c65c3c37..f0959d6b2 100644 --- a/res/res_pjsip.c +++ b/res/res_pjsip.c @@ -51,6 +51,7 @@ <depend>res_sorcery_config</depend> <depend>res_sorcery_memory</depend> <depend>res_sorcery_astdb</depend> + <use type="module">res_statsd</use> <support_level>core</support_level> ***/ diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c index 2b6a2bb2a..a6afe5e53 100644 --- a/res/res_pjsip/pjsip_configuration.c +++ b/res/res_pjsip/pjsip_configuration.c @@ -1147,11 +1147,11 @@ static int from_user_handler(const struct aco_option *opt, { struct ast_sip_endpoint *endpoint = obj; /* Valid non-alphanumeric characters for URI */ - char *valid_uri_marks = "-_.!~*`()"; + char *valid_uri_marks = "-._~%!$&'()*+,;=:"; const char *val; for (val = var->value; *val; val++) { - if (!strchr(valid_uri_marks, *val) && !isdigit(*val) && !isalpha(*val)) { + if (!isalpha(*val) && !isdigit(*val) && !strchr(valid_uri_marks, *val)) { ast_log(LOG_ERROR, "Error configuring endpoint '%s' - '%s' field " "contains invalid character '%c'\n", ast_sorcery_object_get_id(endpoint), var->name, *val); diff --git a/res/res_pjsip/pjsip_message_filter.c b/res/res_pjsip/pjsip_message_filter.c index 978aeb070..085d9787e 100644 --- a/res/res_pjsip/pjsip_message_filter.c +++ b/res/res_pjsip/pjsip_message_filter.c @@ -236,7 +236,7 @@ static pj_status_t filter_on_tx_message(pjsip_tx_data *tdata) pjsip_tpmgr_fla2_param_default(&prm); prm.tp_type = tdata->tp_info.transport->key.type; pj_strset2(&prm.dst_host, tdata->tp_info.dst_name); - prm.local_if = PJ_TRUE; + prm.local_if = is_bound_any(tdata->tp_info.transport); /* If we can't get the local address use best effort and let it pass */ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) { diff --git a/res/res_pjsip_outbound_publish.c b/res/res_pjsip_outbound_publish.c index 0fac8adf6..f1f49d510 100644 --- a/res/res_pjsip_outbound_publish.c +++ b/res/res_pjsip_outbound_publish.c @@ -18,6 +18,7 @@ /*** MODULEINFO <depend>pjproject</depend> + <depend>res_pjproject</depend> <depend>res_pjsip</depend> <support_level>core</support_level> ***/ diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c index 4697e5cf7..7fa6e2c10 100644 --- a/res/res_pjsip_outbound_registration.c +++ b/res/res_pjsip_outbound_registration.c @@ -19,6 +19,7 @@ /*** MODULEINFO <depend>pjproject</depend> <depend>res_pjsip</depend> + <use type="module">res_statsd</use> <support_level>core</support_level> ***/ diff --git a/res/res_pjsip_publish_asterisk.c b/res/res_pjsip_publish_asterisk.c index fa5e4ced7..72e1e4d7e 100644 --- a/res/res_pjsip_publish_asterisk.c +++ b/res/res_pjsip_publish_asterisk.c @@ -20,6 +20,7 @@ <depend>pjproject</depend> <depend>res_pjsip</depend> <depend>res_pjsip_outbound_publish</depend> + <depend>res_pjsip_pubsub</depend> <support_level>core</support_level> ***/ diff --git a/res/res_pjsip_sdp_rtp.c b/res/res_pjsip_sdp_rtp.c index 604fd421e..a87758267 100644 --- a/res/res_pjsip_sdp_rtp.c +++ b/res/res_pjsip_sdp_rtp.c @@ -1052,20 +1052,11 @@ static void add_msid_to_stream(struct ast_sip_session *session, } if (ast_strlen_zero(session_media->mslabel)) { - if (ast_sip_session_is_pending_stream_default(session, stream)) { - int index; - - /* If this is a default stream we group them together under the same stream, but as different tracks */ - for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) { - struct ast_sip_session_media *other_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index); - - if (session_media == other_session_media) { - continue; - } + /* If this stream is grouped with another then use its media stream label if possible */ + if (ast_stream_get_group(stream) != -1) { + struct ast_sip_session_media *group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, ast_stream_get_group(stream)); - ast_copy_string(session_media->mslabel, other_session_media->mslabel, sizeof(session_media->mslabel)); - break; - } + ast_copy_string(session_media->mslabel, group_session_media->mslabel, sizeof(session_media->mslabel)); } if (ast_strlen_zero(session_media->mslabel)) { diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c index 37ff53105..4724d46ce 100644 --- a/res/res_pjsip_session.c +++ b/res/res_pjsip_session.c @@ -399,6 +399,7 @@ static void session_media_dtor(void *obj) } ast_free(session_media->mid); + ast_free(session_media->remote_mslabel); } struct ast_sip_session_media *ast_sip_session_media_state_add(struct ast_sip_session *session, @@ -553,6 +554,70 @@ static int set_mid_and_bundle_group(struct ast_sip_session *session, return 0; } +static void set_remote_mslabel_and_stream_group(struct ast_sip_session *session, + struct ast_sip_session_media *session_media, + const pjmedia_sdp_session *sdp, + const struct pjmedia_sdp_media *stream, + struct ast_stream *asterisk_stream) +{ + int index; + + ast_free(session_media->remote_mslabel); + session_media->remote_mslabel = NULL; + + for (index = 0; index < stream->attr_count; ++index) { + pjmedia_sdp_attr *attr = stream->attr[index]; + char attr_value[pj_strlen(&attr->value) + 1]; + char *ssrc_attribute_name, *ssrc_attribute_value = NULL; + char *msid, *tmp = attr_value; + static const pj_str_t STR_msid = { "msid", 4 }; + static const pj_str_t STR_ssrc = { "ssrc", 4 }; + + if (!pj_strcmp(&attr->name, &STR_msid)) { + ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value)); + msid = strsep(&tmp, " "); + session_media->remote_mslabel = ast_strdup(msid); + break; + } else if (!pj_strcmp(&attr->name, &STR_ssrc)) { + ast_copy_pj_str(attr_value, &attr->value, sizeof(attr_value)); + + if ((ssrc_attribute_name = strchr(attr_value, ' '))) { + /* This has an actual attribute */ + *ssrc_attribute_name++ = '\0'; + ssrc_attribute_value = strchr(ssrc_attribute_name, ':'); + if (ssrc_attribute_value) { + /* Values are actually optional according to the spec */ + *ssrc_attribute_value++ = '\0'; + } + + if (!strcasecmp(ssrc_attribute_name, "mslabel") && !ast_strlen_zero(ssrc_attribute_value)) { + session_media->remote_mslabel = ast_strdup(ssrc_attribute_value); + break; + } + } + } + } + + if (ast_strlen_zero(session_media->remote_mslabel)) { + return; + } + + /* Iterate through the existing streams looking for a match and if so then group this with it */ + for (index = 0; index < AST_VECTOR_SIZE(&session->pending_media_state->sessions); ++index) { + struct ast_sip_session_media *group_session_media; + + group_session_media = AST_VECTOR_GET(&session->pending_media_state->sessions, index); + + if (ast_strlen_zero(group_session_media->remote_mslabel) || + strcmp(group_session_media->remote_mslabel, session_media->remote_mslabel)) { + continue; + } + + ast_stream_set_group(asterisk_stream, index); + break; + } +} + static void remove_stream_from_bundle(struct ast_sip_session_media *session_media, struct ast_stream *stream) { @@ -630,6 +695,7 @@ static int handle_incoming_sdp(struct ast_sip_session *session, const pjmedia_sd } set_mid_and_bundle_group(session, session_media, sdp, remote_stream); + set_remote_mslabel_and_stream_group(session, session_media, sdp, remote_stream, stream); if (session_media->handler) { handler = session_media->handler; @@ -730,6 +796,7 @@ static int handle_negotiated_sdp_session_media(struct ast_sip_session_media *ses ast_copy_pj_str(media, &local->media[index]->desc.media, sizeof(media)); set_mid_and_bundle_group(session, session_media, remote, remote->media[index]); + set_remote_mslabel_and_stream_group(session, session_media, remote, remote->media[index], asterisk_stream); handler = session_media->handler; if (handler) { diff --git a/res/res_pktccops.c b/res/res_pktccops.c index 4f6944875..e8d266cda 100644 --- a/res/res_pktccops.c +++ b/res/res_pktccops.c @@ -1472,6 +1472,10 @@ static int load_module(void) } ast_cli_register_multiple(cli_pktccops, sizeof(cli_pktccops) / sizeof(struct ast_cli_entry)); restart_pktc_thread(); + + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return 0; } diff --git a/res/res_smdi.c b/res/res_smdi.c index 4d7240104..0edabb83c 100644 --- a/res/res_smdi.c +++ b/res/res_smdi.c @@ -1405,6 +1405,10 @@ static int _unload_module(int fromload) } smdi_loaded = 0; + + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return 0; } diff --git a/res/res_stasis_device_state.c b/res/res_stasis_device_state.c index 276a98b93..6527af4a6 100644 --- a/res/res_stasis_device_state.c +++ b/res/res_stasis_device_state.c @@ -168,22 +168,22 @@ struct ast_json *stasis_app_device_state_to_json( struct ast_json *stasis_app_device_states_to_json(void) { struct ast_json *array = ast_json_array_create(); - RAII_VAR(struct ast_db_entry *, tree, - ast_db_gettree(DEVICE_STATE_FAMILY, NULL), ast_db_freetree); + struct ast_db_entry *tree; struct ast_db_entry *entry; + tree = ast_db_gettree(DEVICE_STATE_FAMILY, NULL); for (entry = tree; entry; entry = entry->next) { const char *name = strrchr(entry->key, '/'); + if (!ast_strlen_zero(name)) { - struct ast_str *device = ast_str_alloca(DEVICE_STATE_SIZE); - ast_str_set(&device, 0, "%s%s", - DEVICE_STATE_SCHEME_STASIS, ++name); - ast_json_array_append( - array, stasis_app_device_state_to_json( - ast_str_buffer(device), - ast_device_state(ast_str_buffer(device)))); + char device[DEVICE_STATE_SIZE]; + + snprintf(device, sizeof(device), "%s%s", DEVICE_STATE_SCHEME_STASIS, ++name); + ast_json_array_append(array, + stasis_app_device_state_to_json(device, ast_device_state(device))); } } + ast_db_freetree(tree); return array; } @@ -291,7 +291,7 @@ static void populate_cache(void) static enum ast_device_state stasis_device_state_cb(const char *data) { - char buf[DEVICE_STATE_SIZE] = ""; + char buf[DEVICE_STATE_SIZE]; ast_db_get(DEVICE_STATE_FAMILY, data, buf, sizeof(buf)); diff --git a/res/res_stasis_mailbox.c b/res/res_stasis_mailbox.c index 4522adc10..5ed061de2 100644 --- a/res/res_stasis_mailbox.c +++ b/res/res_stasis_mailbox.c @@ -93,6 +93,7 @@ struct ast_json *stasis_app_mailboxes_to_json() } } ao2_iterator_destroy(&iter); + ao2_ref(mailboxes, -1); return array; } diff --git a/res/res_statsd.c b/res/res_statsd.c index 3d7dd1684..aee0bcd5a 100644 --- a/res/res_statsd.c +++ b/res/res_statsd.c @@ -353,6 +353,9 @@ static int load_module(void) return AST_MODULE_LOAD_DECLINE; } + /* For Optional API. */ + ast_module_shutdown_ref(AST_MODULE_SELF); + return AST_MODULE_LOAD_SUCCESS; } diff --git a/res/stasis/messaging.c b/res/stasis/messaging.c index 8dfd99608..d398bb6d4 100644 --- a/res/stasis/messaging.c +++ b/res/stasis/messaging.c @@ -264,6 +264,7 @@ static struct ast_json *msg_to_json(struct ast_msg *msg) json_vars = ast_json_array_create(); if (!json_vars) { + ast_msg_var_iterator_destroy(it_vars); return NULL; } @@ -272,7 +273,8 @@ static struct ast_json *msg_to_json(struct ast_msg *msg) json_tuple = ast_json_pack("{s: s}", name, value); if (!json_tuple) { - ast_json_free(json_vars); + ast_json_unref(json_vars); + ast_msg_var_iterator_destroy(it_vars); return NULL; } diff --git a/tests/test_utils.c b/tests/test_utils.c index d8915ba28..072cf0a39 100644 --- a/tests/test_utils.c +++ b/tests/test_utils.c @@ -27,6 +27,8 @@ /*** MODULEINFO <depend>TEST_FRAMEWORK</depend> + <use type="module">res_agi</use> + <use type="module">res_crypto</use> <support_level>core</support_level> ***/ |