diff options
31 files changed, 515 insertions, 182 deletions
@@ -40,6 +40,12 @@ cdr_odbc * Added a new configuration option, "newcdrcolumns", which enables use of the post-1.8 CDR columns 'peeraccount', 'linkedid', and 'sequence'. +------------------ +cdr_csv +------------------ + * Added a new configuration option, "newcdrcolumns", which enables use of the + post-1.8 CDR columns 'peeraccount', 'linkedid', and 'sequence'. + Channel Drivers ------------------ @@ -48,6 +54,9 @@ chan_dahdi ------------------ * The CALLERID(ani2) value for incoming calls is now populated in featdmf signaling mode. The information was previously discarded. + * Added the force_restart_unavailable_chans compatibility option. When + enabled it causes Asterisk to restart the ISDN B channel if an outgoing + call receives cause 44 (Requested channel not available). chan_iax2 ------------------ diff --git a/Makefile.moddir_rules b/Makefile.moddir_rules index 3d3e6ad67..d2964e374 100644 --- a/Makefile.moddir_rules +++ b/Makefile.moddir_rules @@ -66,7 +66,9 @@ define MOD_ADD_SOURCE $$(if $$(filter $(1),$$(EMBEDDED_MODS)),modules.link,$(1).so): $$(subst $(3),$(5),$(2)) $$(subst $(3),$(5),$(2)): _ASTCFLAGS+=$$(call MOD_ASTCFLAGS,$(1)) .$(1).moduleinfo: MODULEINFO_EXTRA_OUTPUT=" $$(addprefix $$(SUBDIR)/,$$(subst $(3),$(5),$(2)) $$(subst $(3),$(4),$(2)))" -.$(1).moduleinfo: $(2) +# The use of wildcard ensures that 'make menuselect' will not fail for modules that +# require additional source downloads. +.$(1).moduleinfo: $(wildcard $(2)) clean:: clean-$(1)$(3) diff --git a/Makefile.rules b/Makefile.rules index a24cc72b7..a274c9572 100644 --- a/Makefile.rules +++ b/Makefile.rules @@ -65,6 +65,11 @@ endif CC_CFLAGS=$(PTHREAD_CFLAGS) $(_ASTCFLAGS) $(ASTCFLAGS) CXX_CFLAGS=$(PTHREAD_CFLAGS) $(filter-out -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations $(AST_DECLARATION_AFTER_STATEMENT),$(_ASTCFLAGS) $(ASTCFLAGS)) +# Clang -Werror warning suppressions +ifeq ($(C_COMPILER_FAMILY),clang) + CC_CFLAGS+=-Wno-unused-value -Wno-parentheses-equality +endif + ifeq ($(GNU_LD),1) SO_SUPPRESS_SYMBOLS=-Wl,--version-script,$(subst .so,.exports,$@),--warn-common ifneq ($(wildcard $(subst .so,.dynamics,$@)),) diff --git a/autoconf/ast_check_raii.m4 b/autoconf/ast_check_raii.m4 new file mode 100644 index 000000000..e39a43d2e --- /dev/null +++ b/autoconf/ast_check_raii.m4 @@ -0,0 +1,56 @@ +dnl check RAII requirements +dnl +dnl gcc / llvm-gcc: -fnested-functions +dnl clang : -fblocks / -fblocks and -lBlocksRuntime" +AC_DEFUN([AST_CHECK_RAII], [ + AC_MSG_CHECKING([for RAII support]) + AST_C_COMPILER_FAMILY="" + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([], [ + int main() { + #if defined(__clang__) + choke + #endif + return 0; + } + ]) + ],[ + dnl Nested functions required for RAII implementation + AC_MSG_CHECKING(for gcc -fnested-functions) + AC_COMPILE_IFELSE( + dnl Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 + [ + AC_LANG_PROGRAM([], [auto void foo(void); void foo(void) {}]) + ],[ + AST_NESTED_FUNCTIONS="" + AC_MSG_RESULT(no) + ],[ + AST_NESTED_FUNCTIONS="-fnested-functions" + AC_MSG_RESULT(yes) + ] + ) + AC_SUBST(AST_NESTED_FUNCTIONS) + AST_C_COMPILER_FAMILY="gcc" + ],[ + AC_MSG_CHECKING(for clang -fblocks) + if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then + AST_CLANG_BLOCKS_LIBS="" + AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks" + AC_MSG_RESULT(yes) + elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then + AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime" + AST_CLANG_BLOCKS="-fblocks" + AC_MSG_RESULT(yes) + else + AC_MSG_ERROR([BlocksRuntime is required for clang, please install libblocksruntime]) + fi + AC_SUBST(AST_CLANG_BLOCKS_LIBS) + AC_SUBST(AST_CLANG_BLOCKS) + AST_C_COMPILER_FAMILY="clang" + ] + ) + if test -z "${AST_C_COMPILER_FAMILY}"; then + AC_MSG_ERROR([Compiler ${CC} not supported. Mminimum required gcc-4.3 / llvm-gcc-4.3 / clang-3.3 + libblocksruntime-dev]) + fi + AC_SUBST(AST_C_COMPILER_FAMILY) +]) diff --git a/autoconf/ast_check_strsep_array_bounds.m4 b/autoconf/ast_check_strsep_array_bounds.m4 new file mode 100644 index 000000000..47a41e58a --- /dev/null +++ b/autoconf/ast_check_strsep_array_bounds.m4 @@ -0,0 +1,81 @@ +dnl macro AST_CHECK_STRSEP_ARRAY_BOUNDS0 +dnl +dnl The optimized strcmp and strsep macro's in +dnl /usr/include/xxx-linux-gnu/bits/string2.h produce a warning (-Warray-bounds) +dnl when compiled with clang (+ -O1), when the delimiter parameter is +dnl passed in as a char *, instead of the expected char[] +dnl +dnl Instead of replacing all occurrences of strsep and strcmp, looking like: +dnl xxx_name = strsep(&rest, ","); +dnl +dnl with: +dnl char delimiters[] = ","; +dnl xxx_name = strsep(&rest, delimiters); +dnl +dnl to get around this warning, without having to suppress the warning completely. +dnl This macro detects the warning and force these 'optimizations' to be +dnl switched off (Clang already has a set of builtin optimizers which should result +dnl in good performance for these type of functions). +dnl +dnl When the issue is detected it will add a define to autoconfig.h which will prevent +dnl bits/string2.h from replacing the standard implementation of strsep/strcmp with it's +dnl macro optimized version. bits/string.h checks these defines before inserting it's +dnl replacements. +dnl +dnl When bits/string2.h get's fixed in the future, this macro should be able to +dnl detect the new behaviour, and when no warning is generated, it will use the optimize +dnl version from bits/string2.h +dnl +dnl +dnl See 'define __strcmp_gc(s1, s2, l2) in bits/string2.h' +dnl +dnl llvm-comment: Normally, this array-bounds warning are suppressed for macros, so that +dnl unused paths like the one that accesses __s1[3] are not warned about. But if you +dnl preprocess manually, and feed the result to another instance of clang, it will warn +dnl about all the possible forks of this particular if statement. +dnl +dnl Instead of switching of this optimization, another solution would be to run the pre- +dnl processing step with -frewrite-includes, which should preserve enough information +dnl so that clang should still be able to suppress the diagnostic at the compile step +dnl later on. +dnl +dnl See also "https://llvm.org/bugs/show_bug.cgi?id=20144" +dnl See also "https://llvm.org/bugs/show_bug.cgi?id=11536" +dnl +AC_DEFUN([AST_CHECK_STRSEP_ARRAY_BOUNDS], [ + AC_MSG_CHECKING([for clang strsep/strcmp optimization]) + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -O1 -Werror=array-bounds" + AC_COMPILE_IFELSE( + [ + AC_LANG_SOURCE([ + #include <stdio.h> + #include <string.h> + + /* fails with clang and -O1 */ + void test_strsep_strcmp (void) { + char *haystackstr = "test1,test2"; + char *outstr; + if (!strcmp(haystackstr, ",")) { + printf("fail\n"); + } + if ((outstr = strsep(&haystackstr, ","))) { + printf("fail:%s\n", outstr); + } + } + int main(int argc, char *argv[]) { + test_strsep_strcmp(); + return 0; + } + ]) + ],[ + AC_MSG_RESULT(no) + ],[ + dnl setting this define in autoconfig.h will prevent bits/string2.h from replacing the standard implementation of strsep/strcmp + AC_DEFINE([_HAVE_STRING_ARCH_strcmp], 1, [Prevent clang array-bounds warning by not using strcmp from bits/string2.h]) + AC_DEFINE([_HAVE_STRING_ARCH_strsep], 1, [Prevent clang array-bounds warning by not using strsep from bits/string2.h]) + AC_MSG_RESULT([prevent use of __string2_1bptr_p / strsep / strcmp from bits/string2.h]) + ] + ) + CFLAGS="$save_CFLAGS" +]) diff --git a/build_tools/get_moduleinfo b/build_tools/get_moduleinfo index 4dbb2942f..e4e72bbc4 100644 --- a/build_tools/get_moduleinfo +++ b/build_tools/get_moduleinfo @@ -1,4 +1,4 @@ -/\/\*\*\* MODULEINFO/ {printit=1; next} +/\/\*\*\* +MODULEINFO/ {printit=1; next} /<support_level>/ {if (gotsupportlevel) { next }; gotsupportlevel=1} /\*\*\*\// {printit=0} /.*/ {if (printit) print} diff --git a/cdr/cdr_csv.c b/cdr/cdr_csv.c index 5f3e95cb3..a480a4731 100644 --- a/cdr/cdr_csv.c +++ b/cdr/cdr_csv.c @@ -58,6 +58,7 @@ static int accountlogs = 1; static int loguniqueid = 0; static int loguserfield = 0; static int loaded = 0; +static int newcdrcolumns = 0; static const char config[] = "cdr.conf"; /* #define CSV_LOGUNIQUEID 1 */ @@ -113,6 +114,7 @@ static int load_config(int reload) usegmtime = 0; loguniqueid = 0; loguserfield = 0; + newcdrcolumns = 0; if (!(v = ast_variable_browse(cfg, "csv"))) { ast_config_destroy(cfg); @@ -129,7 +131,10 @@ static int load_config(int reload) loguniqueid = ast_true(v->value); } else if (!strcasecmp(v->name, "loguserfield")) { loguserfield = ast_true(v->value); + } else if (!strcasecmp(v->name, "newcdrcolumns")) { + newcdrcolumns = ast_true(v->value); } + } ast_config_destroy(cfg); return 1; @@ -241,6 +246,11 @@ static int build_csv_record(char *buf, size_t bufsize, struct ast_cdr *cdr) /* append the user field */ if(loguserfield) append_string(buf, cdr->userfield, bufsize); + if (newcdrcolumns) { + append_string(buf, cdr->peeraccount, bufsize); + append_string(buf, cdr->linkedid, bufsize); + append_int(buf, cdr->sequence, bufsize); + } /* If we hit the end of our buffer, log an error */ if (strlen(buf) < bufsize - 5) { /* Trim off trailing comma */ diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c index b7df2b811..b9405d591 100644 --- a/channels/chan_dahdi.c +++ b/channels/chan_dahdi.c @@ -12346,6 +12346,7 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf, #if defined(HAVE_PRI_MCID) pris[span].pri.mcid_send = conf->pri.pri.mcid_send; #endif /* defined(HAVE_PRI_MCID) */ + pris[span].pri.force_restart_unavailable_chans = conf->pri.pri.force_restart_unavailable_chans; #if defined(HAVE_PRI_DATETIME_SEND) pris[span].pri.datetime_send = conf->pri.pri.datetime_send; #endif /* defined(HAVE_PRI_DATETIME_SEND) */ @@ -18258,6 +18259,8 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct else ast_log(LOG_WARNING, "'%s' is not a valid reset interval, should be >= 60 seconds or 'never' at line %d.\n", v->value, v->lineno); + } else if (!strcasecmp(v->name, "force_restart_unavailable_chans")) { + confp->pri.pri.force_restart_unavailable_chans = ast_true(v->value); } else if (!strcasecmp(v->name, "minunused")) { confp->pri.pri.minunused = atoi(v->value); } else if (!strcasecmp(v->name, "minidle")) { diff --git a/channels/chan_sip.c b/channels/chan_sip.c index aa616cde1..468bfbecb 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -254,7 +254,6 @@ ASTERISK_REGISTER_FILE() #include "asterisk/astobj2.h" #include "asterisk/dnsmgr.h" #include "asterisk/devicestate.h" -#include "asterisk/monitor.h" #include "asterisk/netsock2.h" #include "asterisk/localtime.h" #include "asterisk/abstract_jb.h" diff --git a/channels/sig_pri.c b/channels/sig_pri.c index e4ad589c1..c58a3f358 100644 --- a/channels/sig_pri.c +++ b/channels/sig_pri.c @@ -133,15 +133,6 @@ */ //#define ALWAYS_PICK_CHANNEL 1 -/*! - * Define to force a RESTART on a channel that returns a cause - * code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause - * is because of a stuck channel on the peer and the channel is - * always the next channel we pick for an outgoing call then - * this can help. - */ -#define FORCE_RESTART_UNAVAIL_CHANS 1 - #if defined(HAVE_PRI_CCSS) struct sig_pri_cc_agent_prv { /*! Asterisk span D channel control structure. */ @@ -7158,9 +7149,9 @@ static void *pri_dchannel(void *vpri) pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); pri->pvts[chanpos]->call = NULL; } -#if defined(FORCE_RESTART_UNAVAIL_CHANS) if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL && pri->sig != SIG_BRI_PTMP && !pri->resetting + && pri->force_restart_unavailable_chans && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) { ast_verb(3, "Span %d: Forcing restart of channel %d/%d since channel reported in use\n", @@ -7169,7 +7160,6 @@ static void *pri_dchannel(void *vpri) pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE; pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); } -#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */ if (e->hangup.aoc_units > -1) ast_verb(3, "Channel %d/%d, span %d received AOC-E charging %d unit%s\n", pri->pvts[chanpos]->logicalspan, pri->pvts[chanpos]->prioffset, pri->span, (int)e->hangup.aoc_units, (e->hangup.aoc_units == 1) ? "" : "s"); @@ -7307,9 +7297,9 @@ static void *pri_dchannel(void *vpri) pri_hangup(pri->pri, pri->pvts[chanpos]->call, e->hangup.cause); pri->pvts[chanpos]->call = NULL; } -#if defined(FORCE_RESTART_UNAVAIL_CHANS) if (e->hangup.cause == PRI_CAUSE_REQUESTED_CHAN_UNAVAIL && pri->sig != SIG_BRI_PTMP && !pri->resetting + && pri->force_restart_unavailable_chans && pri->pvts[chanpos]->resetting == SIG_PRI_RESET_IDLE) { ast_verb(3, "Span %d: Forcing restart of channel %d/%d since channel reported in use\n", @@ -7318,7 +7308,6 @@ static void *pri_dchannel(void *vpri) pri->pvts[chanpos]->resetting = SIG_PRI_RESET_ACTIVE; pri_reset(pri->pri, PVT_TO_CHANNEL(pri->pvts[chanpos])); } -#endif /* defined(FORCE_RESTART_UNAVAIL_CHANS) */ #ifdef SUPPORT_USERUSER if (!ast_strlen_zero(e->hangup.useruserinfo)) { diff --git a/channels/sig_pri.h b/channels/sig_pri.h index 12f3dcae7..52e6c729d 100644 --- a/channels/sig_pri.h +++ b/channels/sig_pri.h @@ -496,6 +496,8 @@ struct sig_pri_span { #if defined(HAVE_PRI_MCID) /*! \brief TRUE if allow sending MCID request on this span. */ unsigned int mcid_send:1; + /*! \brief TRUE if forcing RESTART when receive cause 44 on this span. */ + unsigned int force_restart_unavailable_chans:1; #endif /* defined(HAVE_PRI_MCID) */ #if defined(HAVE_PRI_DATETIME_SEND) /*! \brief Configured date/time ie send policy option. */ diff --git a/configs/samples/cdr.conf.sample b/configs/samples/cdr.conf.sample index 2c7cdf6f0..e175a2a76 100644 --- a/configs/samples/cdr.conf.sample +++ b/configs/samples/cdr.conf.sample @@ -154,6 +154,8 @@ usegmtime=yes ; log date/time in GMT. Default is "no" loguniqueid=yes ; log uniqueid. Default is "no" loguserfield=yes ; log user field. Default is "no" accountlogs=yes ; create separate log file for each account code. Default is "yes" +;newcdrcolumns=yes ; Enable logging of post-1.8 CDR columns (peeraccount, linkedid, sequence). + ; Default is "no". ;[radius] ;usegmtime=yes ; log date/time in GMT diff --git a/configs/samples/chan_dahdi.conf.sample b/configs/samples/chan_dahdi.conf.sample index 13691fcdf..e67574b9b 100644 --- a/configs/samples/chan_dahdi.conf.sample +++ b/configs/samples/chan_dahdi.conf.sample @@ -196,6 +196,20 @@ context=public ; ;resetinterval = 3600 ; +; Enable per span to force a RESTART on a channel that returns a cause +; code of PRI_CAUSE_REQUESTED_CHAN_UNAVAIL(44). If the cause is because +; of a stuck channel on the peer and the channel is always the next +; channel we pick for an outgoing call then this might help. +; +; NOTE: Sending a RESTART in response to a cause 44 is not required +; (nor prohibited) by the standards and is likely a primitive chan_dahdi +; response to call collisions (glare) and buggy peers. However, there +; are telco switches out there that ignore the RESTART and continue to +; send calls to the channel in the restarting state. +; Default no. +; +;force_restart_unavailable_chans=yes +; ; Assume inband audio may be present when a SETUP ACK message is received. ; Q.931 Section 5.1.3 says that in scenarios with overlap dialing, when a ; dialtone is sent from the network side, progress indicator 8 "Inband info diff --git a/configs/samples/pjsip.conf.sample b/configs/samples/pjsip.conf.sample index 0f95d19e0..5e3757175 100644 --- a/configs/samples/pjsip.conf.sample +++ b/configs/samples/pjsip.conf.sample @@ -870,9 +870,9 @@ ; Identifier names are derived from res_pjsip_endpoint_identifier_* ; modules. (default: ip,username,anonymous) ;max_initial_qualify_time=4 ; The maximum amount of time (in seconds) from - startup that qualifies should be attempted on all - contacts. If greater than the qualify_frequency - for an aor, qualify_frequency will be used instead. + ; startup that qualifies should be attempted on all + ; contacts. If greater than the qualify_frequency + ; for an aor, qualify_frequency will be used instead. ; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl ;==========================ACL SECTION OPTIONS========================= @@ -687,9 +687,6 @@ PBX_RTLD_NOLOAD PBX_GLOB_BRACE PBX_GLOB_NOMAGIC AST_RPATH -AST_CLANG_BLOCKS -AST_CLANG_BLOCKS_LIBS -AST_NESTED_FUNCTIONS AST_NATIVE_ARCH AST_SHADOW_WARNINGS AST_NO_STRICT_OVERFLOW @@ -1148,6 +1145,10 @@ PBX_ALSA ALSA_DIR ALSA_INCLUDE ALSA_LIB +AST_C_COMPILER_FAMILY +AST_CLANG_BLOCKS +AST_CLANG_BLOCKS_LIBS +AST_NESTED_FUNCTIONS AST_CODE_COVERAGE AST_DEVMODE_STRICT AST_DEVMODE @@ -8227,6 +8228,146 @@ fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RAII support" >&5 +$as_echo_n "checking for RAII support... " >&6; } + AST_C_COMPILER_FAMILY="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int main() { + #if defined(__clang__) + choke + #endif + return 0; + } + + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -fnested-functions" >&5 +$as_echo_n "checking for gcc -fnested-functions... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +auto void foo(void); void foo(void) {} + ; + return 0; +} + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + AST_NESTED_FUNCTIONS="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +else + + AST_NESTED_FUNCTIONS="-fnested-functions" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + AST_C_COMPILER_FAMILY="gcc" + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang -fblocks" >&5 +$as_echo_n "checking for clang -fblocks... " >&6; } + if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then + AST_CLANG_BLOCKS_LIBS="" + AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then + AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime" + AST_CLANG_BLOCKS="-fblocks" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + as_fn_error $? "BlocksRuntime is required for clang, please install libblocksruntime" "$LINENO" 5 + fi + + + AST_C_COMPILER_FAMILY="clang" + + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "${AST_C_COMPILER_FAMILY}"; then + as_fn_error $? "Compiler ${CC} not supported. Mminimum required gcc-4.3 / llvm-gcc-4.3 / clang-3.3 + libblocksruntime-dev" "$LINENO" 5 + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang strsep/strcmp optimization" >&5 +$as_echo_n "checking for clang strsep/strcmp optimization... " >&6; } + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -O1 -Werror=array-bounds" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + + #include <stdio.h> + #include <string.h> + + /* fails with clang and -O1 */ + void test_strsep_strcmp (void) { + char *haystackstr = "test1,test2"; + char *outstr; + if (!strcmp(haystackstr, ",")) { + printf("fail\n"); + } + if ((outstr = strsep(&haystackstr, ","))) { + printf("fail:%s\n", outstr); + } + } + int main(int argc, char *argv) { + test_strsep_strcmp(); + return 0; + } + + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +else + + +$as_echo "#define _HAVE_STRING_ARCH_strcmp 1" >>confdefs.h + + +$as_echo "#define _HAVE_STRING_ARCH_strsep 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: prevent use of __string2_1bptr_p / strsep / strcmp from bits/string2.h" >&5 +$as_echo "prevent use of __string2_1bptr_p / strsep / strcmp from bits/string2.h" >&6; } + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + CFLAGS="$save_CFLAGS" + + # AST_EXT_LIB_SETUP is used to tell configure to handle variables for # various packages. # $1 is the prefix for the variables in makeopts and autoconfig.h @@ -17430,74 +17571,6 @@ $as_echo "no" >&6; } fi -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ - - #if defined(__clang__) - choke - #endif - - ; - return 0; -} - -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gcc -fnested-functions" >&5 -$as_echo_n "checking for gcc -fnested-functions... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -int -main () -{ -auto void foo(void); void foo(void) {} - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } - AST_NESTED_FUNCTIONS= -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - AST_NESTED_FUNCTIONS=-fnested-functions - -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for clang -fblocks" >&5 -$as_echo_n "checking for clang -fblocks... " >&6; } - if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then - AST_CLANG_BLOCKS_LIBS="" - AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then - AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime" - AST_CLANG_BLOCKS="-fblocks" - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -$as_echo "yes" >&6; } - else - as_fn_error $? "\"BlocksRuntime is required for clang\"" "$LINENO" 5 - fi - - - - -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext # Check whether --enable-rpath was given. if test "${enable_rpath+set}" = set; then : diff --git a/configure.ac b/configure.ac index 8a3707543..c09d30a7f 100644 --- a/configure.ac +++ b/configure.ac @@ -386,6 +386,9 @@ AC_ARG_ENABLE([coverage], esac]) AC_SUBST(AST_CODE_COVERAGE) +AST_CHECK_RAII() +AST_CHECK_STRSEP_ARRAY_BOUNDS() + # AST_EXT_LIB_SETUP is used to tell configure to handle variables for # various packages. # $1 is the prefix for the variables in makeopts and autoconfig.h @@ -1134,42 +1137,6 @@ else fi AC_SUBST(AST_NATIVE_ARCH) -dnl Nested functions required for RAII implementation -AC_LINK_IFELSE( - [AC_LANG_PROGRAM([], [ - #if defined(__clang__) - choke - #endif - ]) - ],[ - dnl Nested functions required for RAII implementation - AC_MSG_CHECKING(for gcc -fnested-functions) - AC_COMPILE_IFELSE( - dnl Prototype needed due to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36774 - [AC_LANG_PROGRAM([], [auto void foo(void); void foo(void) {}])], - AC_MSG_RESULT(no) - [AST_NESTED_FUNCTIONS=], - AC_MSG_RESULT(yes) - [AST_NESTED_FUNCTIONS=-fnested-functions] - ) - AC_SUBST(AST_NESTED_FUNCTIONS) - ],[ - AC_MSG_CHECKING(for clang -fblocks) - if test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c - 2>&1`" = ""; then - [AST_CLANG_BLOCKS_LIBS=""] - [AST_CLANG_BLOCKS="-Wno-unknown-warning-option -fblocks"] - AC_MSG_RESULT(yes) - elif test "`echo "int main(){return ^{return 42;}();}" | ${CC} -o /dev/null -fblocks -x c -lBlocksRuntime - 2>&1`" = ""; then - [AST_CLANG_BLOCKS_LIBS="-lBlocksRuntime"] - [AST_CLANG_BLOCKS="-fblocks"] - AC_MSG_RESULT(yes) - else - AC_MSG_ERROR("BlocksRuntime is required for clang") - fi - AC_SUBST(AST_CLANG_BLOCKS_LIBS) - AC_SUBST(AST_CLANG_BLOCKS) - ] -) dnl Check to see if rpath should be set in LDFLAGS AC_ARG_ENABLE(rpath, diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in index 474fb8c31..6b41a8c9a 100644 --- a/include/asterisk/autoconfig.h.in +++ b/include/asterisk/autoconfig.h.in @@ -1314,6 +1314,14 @@ /* Number of bits in a file offset, on hosts where this is settable. */ #undef _FILE_OFFSET_BITS +/* Prevent clang array-bounds warning by not using strcmp from bits/string2.h + */ +#undef _HAVE_STRING_ARCH_strcmp + +/* Prevent clang array-bounds warning by not using strsep from bits/string2.h + */ +#undef _HAVE_STRING_ARCH_strsep + /* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ #undef _LARGEFILE_SOURCE diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h index aec7f7529..fffbe5c09 100644 --- a/include/asterisk/channel.h +++ b/include/asterisk/channel.h @@ -3885,6 +3885,26 @@ enum ama_flags ast_channel_string2amaflag(const char *flag); */ const char *ast_channel_amaflags2string(enum ama_flags flags); +enum AST_MONITORING_STATE { + AST_MONITOR_RUNNING, + AST_MONITOR_PAUSED +}; + +/*! Responsible for channel monitoring data */ +struct ast_channel_monitor { + struct ast_filestream *read_stream; + struct ast_filestream *write_stream; + char read_filename[FILENAME_MAX]; + char write_filename[FILENAME_MAX]; + char filename_base[FILENAME_MAX]; + char beep_id[64]; + int filename_changed; + char *format; + int joinfiles; + enum AST_MONITORING_STATE state; + int (*stop)(struct ast_channel *chan, int need_lock); +}; + /* ACCESSOR FUNTIONS */ /*! \brief Set the channel name */ void ast_channel_name_set(struct ast_channel *chan, const char *name); @@ -3900,7 +3920,7 @@ void ast_channel_name_set(struct ast_channel *chan, const char *name); * * \li language * \li accountcode - * \li peeracccount + * \li peeraccount * \li linkedid */ DECLARE_STRINGFIELD_SETTERS_FOR(name); diff --git a/include/asterisk/monitor.h b/include/asterisk/monitor.h index 6030221a2..377cb62f6 100644 --- a/include/asterisk/monitor.h +++ b/include/asterisk/monitor.h @@ -26,31 +26,11 @@ #include "asterisk/channel.h" #include "asterisk/optional_api.h" -enum AST_MONITORING_STATE { - AST_MONITOR_RUNNING, - AST_MONITOR_PAUSED -}; - /* Streams recording control */ #define X_REC_IN 1 #define X_REC_OUT 2 #define X_JOIN 4 -/*! Responsible for channel monitoring data */ -struct ast_channel_monitor { - struct ast_filestream *read_stream; - struct ast_filestream *write_stream; - char read_filename[FILENAME_MAX]; - char write_filename[FILENAME_MAX]; - char filename_base[FILENAME_MAX]; - char beep_id[64]; - int filename_changed; - char *format; - int joinfiles; - enum AST_MONITORING_STATE state; - int (*stop)(struct ast_channel *chan, int need_lock); -}; - /* Start monitoring a channel */ AST_OPTIONAL_API(int, ast_monitor_start, (struct ast_channel *chan, const char *format_spec, diff --git a/include/asterisk/sip_api.h b/include/asterisk/sip_api.h index 2b8a3f2a1..fddac16e0 100644 --- a/include/asterisk/sip_api.h +++ b/include/asterisk/sip_api.h @@ -23,7 +23,6 @@ extern "C" { #endif -#include "asterisk/optional_api.h" #include "asterisk/config.h" #define AST_SIP_API_VERSION 1 diff --git a/main/asterisk.c b/main/asterisk.c index 86a190bc8..277604bf7 100644 --- a/main/asterisk.c +++ b/main/asterisk.c @@ -4260,7 +4260,10 @@ int main(int argc, char *argv[]) register_config_cli(); read_config_maps(); - astobj2_init(); + if (astobj2_init()) { + printf("Failed: astobj2_init\n%s", term_quit()); + exit(1); + } if (ast_opt_console) { if (el_hist == NULL || el == NULL) diff --git a/main/astobj2.c b/main/astobj2.c index f9dd8d490..1db2dd42d 100644 --- a/main/astobj2.c +++ b/main/astobj2.c @@ -1143,10 +1143,6 @@ int astobj2_init(void) { char ref_filename[1024]; - if (container_init() != 0) { - return -1; - } - if (ast_opt_ref_debug) { snprintf(ref_filename, sizeof(ref_filename), "%s/refs", ast_config_AST_LOG_DIR); ref_log = fopen(ref_filename, "w"); @@ -1155,6 +1151,11 @@ int astobj2_init(void) } } + if (container_init() != 0) { + fclose(ref_log); + return -1; + } + #if defined(AO2_DEBUG) ast_cli_register_multiple(cli_astobj2, ARRAY_LEN(cli_astobj2)); #endif /* defined(AO2_DEBUG) */ diff --git a/main/channel.c b/main/channel.c index fee77630a..fbdf17bd3 100644 --- a/main/channel.c +++ b/main/channel.c @@ -53,7 +53,6 @@ ASTERISK_REGISTER_FILE() #include "asterisk/chanvars.h" #include "asterisk/linkedlists.h" #include "asterisk/indications.h" -#include "asterisk/monitor.h" #include "asterisk/causes.h" #include "asterisk/callerid.h" #include "asterisk/utils.h" diff --git a/main/features.c b/main/features.c index 4acd8aab2..618f91c52 100644 --- a/main/features.c +++ b/main/features.c @@ -66,7 +66,6 @@ ASTERISK_REGISTER_FILE() #include "asterisk/utils.h" #include "asterisk/adsi.h" #include "asterisk/devicestate.h" -#include "asterisk/monitor.h" #include "asterisk/audiohook.h" #include "asterisk/global_datastores.h" #include "asterisk/astobj2.h" diff --git a/main/pbx.c b/main/pbx.c index fee4191aa..45909f5d9 100644 --- a/main/pbx.c +++ b/main/pbx.c @@ -72,6 +72,7 @@ ASTERISK_REGISTER_FILE() #include "asterisk/astobj2.h" #include "asterisk/stasis_channels.h" #include "asterisk/dial.h" +#include "asterisk/vector.h" /*! * \note I M P O R T A N T : @@ -1046,8 +1047,9 @@ struct ast_hint { char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */ char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */ -}; + AST_VECTOR(, char *) devices; /*!< Devices associated with the hint */ +}; #define HINTDEVICE_DATA_LENGTH 16 AST_THREADSTORAGE(hintdevice_data); @@ -1077,15 +1079,28 @@ struct ast_hintdevice { char hintdevice[1]; }; - /*! * \note Using the device for hash */ static int hintdevice_hash_cb(const void *obj, const int flags) { - const struct ast_hintdevice *ext = obj; + const struct ast_hintdevice *ext; + const char *key; - return ast_str_case_hash(ext->hintdevice); + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_KEY: + key = obj; + break; + case OBJ_SEARCH_OBJECT: + ext = obj; + key = ext->hintdevice; + break; + default: + ast_assert(0); + return 0; + } + + return ast_str_case_hash(key); } /*! * \note Devices on hints are not unique so no CMP_STOP is returned @@ -1094,29 +1109,58 @@ static int hintdevice_hash_cb(const void *obj, const int flags) */ static int hintdevice_cmp_multiple(void *obj, void *arg, int flags) { - struct ast_hintdevice *ext = obj, *ext2 = arg; + struct ast_hintdevice *left = obj; + struct ast_hintdevice *right = arg; + const char *right_key = arg; + int cmp; - return !strcasecmp(ext->hintdevice, ext2->hintdevice) ? CMP_MATCH : 0; + switch (flags & OBJ_SEARCH_MASK) { + case OBJ_SEARCH_OBJECT: + right_key = right->hintdevice; + /* Fall through */ + case OBJ_SEARCH_KEY: + cmp = strcmp(left->hintdevice, right_key); + break; + case OBJ_SEARCH_PARTIAL_KEY: + /* + * We could also use a partial key struct containing a length + * so strlen() does not get called for every comparison instead. + */ + cmp = strncmp(left->hintdevice, right_key, strlen(right_key)); + break; + default: + ast_assert(0); + cmp = 0; + break; + } + return cmp ? 0 : CMP_MATCH; } -/* - * \details This is used with ao2_callback to remove old devices - * when they are linked to the hint -*/ -static int hintdevice_remove_cb(void *deviceobj, void *arg, int flags) +/*! \internal \brief \c ao2_callback function to remove hintdevices */ +static int hintdevice_remove_cb(void *obj, void *arg, void *data, int flags) { - struct ast_hintdevice *device = deviceobj; - struct ast_hint *hint = arg; + struct ast_hintdevice *candidate = obj; + char *device = arg; + struct ast_hint *hint = data; - return (device->hint == hint) ? CMP_MATCH : 0; + if (!strcmp(candidate->hintdevice, device) + && candidate->hint == hint) { + return CMP_MATCH; + } + return 0; } static int remove_hintdevice(struct ast_hint *hint) { - /* iterate through all devices and remove the devices which are linked to this hint */ - ao2_t_callback(hintdevices, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK, - hintdevice_remove_cb, hint, - "callback to remove all devices which are linked to a hint"); + while (AST_VECTOR_SIZE(&hint->devices) > 0) { + char *device = AST_VECTOR_GET(&hint->devices, 0); + + ao2_t_callback_data(hintdevices, OBJ_SEARCH_KEY | OBJ_UNLINK | OBJ_NODATA, + hintdevice_remove_cb, device, hint, "Remove device from container"); + AST_VECTOR_REMOVE_UNORDERED(&hint->devices, 0); + ast_free(device); + } + return 0; } @@ -1161,18 +1205,32 @@ static int add_hintdevice(struct ast_hint *hint, const char *devicelist) /* Spit on '&' and ',' to handle presence hints as well */ while ((cur = strsep(&parse, "&,"))) { + char *device_name; + devicelength = strlen(cur); if (!devicelength) { continue; } + + device_name = ast_strdup(cur); + if (!device_name) { + return -1; + } + device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy, "allocating a hintdevice structure"); if (!device) { + ast_free(device_name); return -1; } strcpy(device->hintdevice, cur); ao2_ref(hint, +1); device->hint = hint; + if (AST_VECTOR_APPEND(&hint->devices, device_name)) { + ast_free(device_name); + ao2_ref(device, -1); + return -1; + } ao2_t_link(hintdevices, device, "Linking device into hintdevice container."); ao2_t_ref(device, -1, "hintdevice is linked so we can unref"); } @@ -5385,7 +5443,7 @@ static void device_state_cb(void *unused, struct stasis_subscription *sub, struc ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */ dev_iter = ao2_t_callback(hintdevices, - OBJ_POINTER | OBJ_MULTIPLE, + OBJ_SEARCH_OBJECT | OBJ_MULTIPLE, hintdevice_cmp_multiple, cmpdevice, "find devices in container"); @@ -5697,6 +5755,7 @@ static int hint_id_cmp(void *obj, void *arg, int flags) static void destroy_hint(void *obj) { struct ast_hint *hint = obj; + int i; if (hint->callbacks) { struct ast_state_cb *state_cb; @@ -5726,6 +5785,12 @@ static void destroy_hint(void *obj) } ao2_ref(hint->callbacks, -1); } + + for (i = 0; i < AST_VECTOR_SIZE(&hint->devices); i++) { + char *device = AST_VECTOR_GET(&hint->devices, i); + ast_free(device); + } + AST_VECTOR_FREE(&hint->devices); ast_free(hint->last_presence_subtype); ast_free(hint->last_presence_message); } @@ -5787,6 +5852,7 @@ static int ast_add_hint(struct ast_exten *e) if (!hint_new) { return -1; } + AST_VECTOR_INIT(&hint_new->devices, 8); /* Initialize new hint. */ hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp); @@ -12526,14 +12592,17 @@ static int statecbs_cmp(void *obj, void *arg, int flags) static void pbx_shutdown(void) { if (hints) { + ao2_container_unregister("hints"); ao2_ref(hints, -1); hints = NULL; } if (hintdevices) { + ao2_container_unregister("hintdevices"); ao2_ref(hintdevices, -1); hintdevices = NULL; } if (statecbs) { + ao2_container_unregister("statecbs"); ao2_ref(statecbs, -1); statecbs = NULL; } @@ -12543,11 +12612,53 @@ static void pbx_shutdown(void) pbx_builtin_clear_globals(); } +static void print_hints_key(void *v_obj, void *where, ao2_prnt_fn *prnt) +{ + struct ast_hint *hint = v_obj; + + if (!hint) { + return; + } + prnt(where, "%s@%s", ast_get_extension_name(hint->exten), + ast_get_context_name(ast_get_extension_context(hint->exten))); +} + +static void print_hintdevices_key(void *v_obj, void *where, ao2_prnt_fn *prnt) +{ + struct ast_hintdevice *hintdevice = v_obj; + + if (!hintdevice) { + return; + } + prnt(where, "%s => %s@%s", hintdevice->hintdevice, + ast_get_extension_name(hintdevice->hint->exten), + ast_get_context_name(ast_get_extension_context(hintdevice->hint->exten))); +} + +static void print_statecbs_key(void *v_obj, void *where, ao2_prnt_fn *prnt) +{ + struct ast_state_cb *state_cb = v_obj; + + if (!state_cb) { + return; + } + prnt(where, "%d", state_cb->id); +} + int ast_pbx_init(void) { hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp); + if (hints) { + ao2_container_register("hints", hints, print_hints_key); + } hintdevices = ao2_container_alloc(HASH_EXTENHINT_SIZE, hintdevice_hash_cb, hintdevice_cmp_multiple); + if (hintdevices) { + ao2_container_register("hintdevices", hintdevices, print_hintdevices_key); + } statecbs = ao2_container_alloc(1, NULL, statecbs_cmp); + if (statecbs) { + ao2_container_register("statecbs", statecbs, print_statecbs_key); + } ast_register_cleanup(pbx_shutdown); diff --git a/main/presencestate.c b/main/presencestate.c index 32f19e6c8..399613e39 100644 --- a/main/presencestate.c +++ b/main/presencestate.c @@ -389,7 +389,7 @@ static const char *presence_state_get_id(struct stasis_message *msg) #if defined(TEST_FRAMEWORK) -#define TEST_CATEGORY "/main/presence" +#define TEST_CATEGORY "/main/presence/" static int presence_test_alice_state = AST_PRESENCE_UNAVAILABLE; static int presence_test_bob_state = AST_PRESENCE_UNAVAILABLE; diff --git a/main/stasis_channels.c b/main/stasis_channels.c index 5990cddce..94a24e14f 100644 --- a/main/stasis_channels.c +++ b/main/stasis_channels.c @@ -1326,6 +1326,7 @@ static void dial_target_free(struct dial_target *doomed) return; } ast_free(doomed->dialstring); + ast_channel_cleanup(doomed->peer); ast_free(doomed); } @@ -1348,7 +1349,7 @@ static void dial_masquerade_datastore_cleanup(struct dial_masquerade_datastore * while ((cur = AST_LIST_REMOVE_HEAD(&masq_data->dialed_peers, list))) { dial_target_free(cur); } - masq_data->caller = NULL; + masq_data->caller = ast_channel_cleanup(masq_data->caller); } static void dial_masquerade_datastore_remove_chan(struct dial_masquerade_datastore *masq_data, struct ast_channel *chan) @@ -1556,7 +1557,7 @@ static struct dial_masquerade_datastore *dial_masquerade_datastore_add( ast_datastore_free(datastore); return NULL; } - masq_data->caller = chan; + masq_data->caller = ast_channel_ref(chan); } datastore->data = masq_data; @@ -1604,7 +1605,7 @@ static int set_dial_masquerade(struct ast_channel *caller, struct ast_channel *p return -1; } } - target->peer = peer; + target->peer = ast_channel_ref(peer); /* Put peer target into datastore */ ao2_lock(masq_data); diff --git a/main/term.c b/main/term.c index a19c1f144..cf21719ae 100644 --- a/main/term.c +++ b/main/term.c @@ -311,8 +311,7 @@ const char *ast_term_color(int fgcolor, int bgcolor) const char *ast_term_reset(void) { if (ast_opt_force_black_background) { - static const char reset[] = { ESC, '[', COLOR_BLACK + 10, 'm', 0 }; - return reset; + return enddata; } else { return quitdata; } diff --git a/makeopts.in b/makeopts.in index cc233109d..69636f18e 100644 --- a/makeopts.in +++ b/makeopts.in @@ -111,6 +111,7 @@ AST_SHADOW_WARNINGS=@AST_SHADOW_WARNINGS@ AST_NESTED_FUNCTIONS=@AST_NESTED_FUNCTIONS@ AST_CLANG_BLOCKS=@AST_CLANG_BLOCKS@ AST_CLANG_BLOCKS_LIBS=@AST_CLANG_BLOCKS_LIBS@ +C_COMPILER_FAMILY=@AST_C_COMPILER_FAMILY@ AST_RPATH=@AST_RPATH@ AST_FORTIFY_SOURCE=@AST_FORTIFY_SOURCE@ AST_MARCH_NATIVE=@AST_MARCH_NATIVE@ diff --git a/res/ari/resource_device_states.c b/res/ari/resource_device_states.c index 6f68d52e4..493d7a1ee 100644 --- a/res/ari/resource_device_states.c +++ b/res/ari/resource_device_states.c @@ -24,7 +24,7 @@ */ /*** MODULEINFO - <depend type="module">res_stasis_device_states</depend> + <depend type="module">res_stasis_device_state</depend> <support_level>core</support_level> ***/ diff --git a/res/res_pjsip_dlg_options.c b/res/res_pjsip_dlg_options.c index 45a19408d..34151244b 100644 --- a/res/res_pjsip_dlg_options.c +++ b/res/res_pjsip_dlg_options.c @@ -16,7 +16,7 @@ * at the top of the source tree. */ -/*** MODULEINFO +/*** MODULEINFO <depend>pjproject</depend> <depend>res_pjsip</depend> <depend>res_pjsip_session</depend> |