summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/app_minivm.c2
-rw-r--r--apps/app_record.c56
-rw-r--r--autoconf/ast_gcc_attribute.m43
-rw-r--r--channels/chan_pjsip.c25
-rw-r--r--configs/samples/ast_debug_tools.conf.sample6
-rwxr-xr-xconfigure43
-rw-r--r--configure.ac7
-rwxr-xr-xcontrib/scripts/ast_coredumper156
-rw-r--r--include/asterisk/doxygen/asterisk-git-howto.h235
-rw-r--r--include/asterisk/doxygen/commits.h114
-rw-r--r--include/asterisk/doxygen/releases.h294
-rw-r--r--include/asterisk/doxygen/reviewboard.h125
-rw-r--r--include/asterisk/doxyref.h6
-rw-r--r--include/asterisk/http_websocket.h9
-rw-r--r--include/asterisk/optional_api.h4
-rw-r--r--include/asterisk/sorcery.h37
-rw-r--r--main/aoc.c5
-rw-r--r--main/audiohook.c4
-rw-r--r--main/plc.c2
-rw-r--r--main/sorcery.c51
-rw-r--r--res/res_fax.c15
-rw-r--r--res/res_hep_pjsip.c90
-rw-r--r--res/res_http_websocket.c50
-rw-r--r--res/res_pjsip/pjsip_configuration.c2
-rw-r--r--res/res_pjsip_endpoint_identifier_anonymous.c6
-rw-r--r--res/res_pjsip_endpoint_identifier_user.c12
-rw-r--r--res/res_pjsip_transport_websocket.c18
-rw-r--r--res/res_sorcery_astdb.c38
-rw-r--r--res/res_sorcery_config.c31
-rw-r--r--res/res_sorcery_memory.c25
-rw-r--r--res/res_sorcery_memory_cache.c46
-rw-r--r--res/res_sorcery_realtime.c20
-rw-r--r--res/snmp/agent.c4
-rw-r--r--tests/test_logger.c4
-rw-r--r--tests/test_pbx.c2
35 files changed, 604 insertions, 943 deletions
diff --git a/apps/app_minivm.c b/apps/app_minivm.c
index 6b1e8bb83..dcf0ee2fa 100644
--- a/apps/app_minivm.c
+++ b/apps/app_minivm.c
@@ -1254,7 +1254,7 @@ static int sendmail(struct minivm_template *template, struct minivm_account *vmu
struct ast_channel *chan = NULL;
char *fromaddress;
char *fromemail;
- int res;
+ int res = -1;
if (!str1 || !str2) {
return -1;
diff --git a/apps/app_record.c b/apps/app_record.c
index 104daa51e..d1cdeabce 100644
--- a/apps/app_record.c
+++ b/apps/app_record.c
@@ -139,6 +139,12 @@ enum {
OPTION_NO_TRUNCATE = (1 << 9),
};
+enum dtmf_response {
+ RESPONSE_NO_MATCH = 0,
+ RESPONSE_OPERATOR,
+ RESPONSE_DTMF,
+};
+
AST_APP_OPTIONS(app_opts,{
AST_APP_OPTION('a', OPTION_APPEND),
AST_APP_OPTION('k', OPTION_KEEP),
@@ -162,24 +168,22 @@ AST_APP_OPTIONS(app_opts,{
* \param dtmf_integer the integer value of the DTMF key received
* \param terminator key currently set to be pressed for normal termination
*
- * \retval 0 do not exit
- * \retval -1 do exit
+ * \returns One of enum dtmf_response
*/
-static int record_dtmf_response(struct ast_channel *chan, struct ast_flags *flags, int dtmf_integer, int terminator)
+static enum dtmf_response record_dtmf_response(struct ast_channel *chan,
+ struct ast_flags *flags, int dtmf_integer, int terminator)
{
if ((dtmf_integer == OPERATOR_KEY) &&
(ast_test_flag(flags, OPTION_OPERATOR_EXIT))) {
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "OPERATOR");
- return -1;
+ return RESPONSE_OPERATOR;
}
if ((dtmf_integer == terminator) ||
(ast_test_flag(flags, OPTION_ANY_TERMINATE))) {
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "DTMF");
- return -1;
+ return RESPONSE_DTMF;
}
- return 0;
+ return RESPONSE_NO_MATCH;
}
static int create_destination_directory(const char *path)
@@ -248,6 +252,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
);
int ms;
struct timeval start;
+ const char *status_response = "ERROR";
/* The next few lines of code parse out the filename and header from the input string */
if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
@@ -345,7 +350,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (res) {
ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
+ status_response = "ERROR";
goto out;
}
@@ -381,7 +386,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (create_destination_directory(tmp)) {
ast_log(LOG_WARNING, "Could not create directory for file %s\n", args.filename);
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
+ status_response = "ERROR";
goto out;
}
@@ -390,7 +395,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (!s) {
ast_log(LOG_WARNING, "Could not create file %s\n", args.filename);
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
+ status_response = "ERROR";
goto out;
}
@@ -425,7 +430,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (res) {
ast_log(LOG_WARNING, "Problem writing frame\n");
ast_frfree(f);
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
+ status_response = "ERROR";
break;
}
@@ -441,7 +446,7 @@ static int record_exec(struct ast_channel *chan, const char *data)
/* Ended happily with silence */
ast_frfree(f);
gotsilence = 1;
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "SILENCE");
+ status_response = "SILENCE";
break;
}
}
@@ -450,12 +455,26 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (res) {
ast_log(LOG_WARNING, "Problem writing frame\n");
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
+ status_response = "ERROR";
ast_frfree(f);
break;
}
} else if (f->frametype == AST_FRAME_DTMF) {
- if (record_dtmf_response(chan, &flags, f->subclass.integer, terminator)) {
+ enum dtmf_response rc =
+ record_dtmf_response(chan, &flags, f->subclass.integer, terminator);
+ switch(rc) {
+ case RESPONSE_NO_MATCH:
+ break;
+ case RESPONSE_OPERATOR:
+ status_response = "OPERATOR";
+ ast_debug(1, "Got OPERATOR\n");
+ break;
+ case RESPONSE_DTMF:
+ status_response = "DTMF";
+ ast_debug(1, "Got DTMF\n");
+ break;
+ }
+ if (rc != RESPONSE_NO_MATCH) {
ast_frfree(f);
break;
}
@@ -465,13 +484,13 @@ static int record_exec(struct ast_channel *chan, const char *data)
if (maxduration > 0 && !ms) {
gottimeout = 1;
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "TIMEOUT");
+ status_response = "TIMEOUT";
}
if (!f) {
ast_debug(1, "Got hangup\n");
res = -1;
- pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "HANGUP");
+ status_response = "HANGUP";
if (!ast_test_flag(&flags, OPTION_KEEP)) {
ast_filedelete(args.filename, NULL);
}
@@ -506,6 +525,9 @@ out:
if (sildet) {
ast_dsp_free(sildet);
}
+
+ pbx_builtin_setvar_helper(chan, "RECORD_STATUS", status_response);
+
return res;
}
diff --git a/autoconf/ast_gcc_attribute.m4 b/autoconf/ast_gcc_attribute.m4
index 4ade81404..b1972bedf 100644
--- a/autoconf/ast_gcc_attribute.m4
+++ b/autoconf/ast_gcc_attribute.m4
@@ -7,6 +7,7 @@ AC_MSG_CHECKING(for compiler 'attribute $1' support)
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
m4_ifval([$4],$4=0)
+ax_cv_have_func_attribute_$1=0
if test "x$2" = "x"
then
@@ -15,6 +16,7 @@ AC_COMPILE_IFELSE(
[])],
AC_MSG_RESULT(yes)
m4_ifval([$4],$4=1)
+ ax_cv_have_func_attribute_$1=1
AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]),
AC_MSG_RESULT(no)
)
@@ -24,6 +26,7 @@ AC_COMPILE_IFELSE(
[])],
AC_MSG_RESULT(yes)
m4_ifval([$4],$4=1)
+ ax_cv_have_func_attribute_$1=1
AC_DEFINE_UNQUOTED([HAVE_ATTRIBUTE_$1], 1, [Define to 1 if your GCC C compiler supports the '$1' attribute.]),
AC_MSG_RESULT(no)
)
diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 5efff7eca..c48801756 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -583,7 +583,19 @@ static int answer(void *data)
pjsip_inv_dec_ref(session->inv_session);
#endif
- return (status == PJ_SUCCESS) ? 0 : -1;
+ if (status != PJ_SUCCESS) {
+ char err[PJ_ERR_MSG_SIZE];
+
+ pj_strerror(status, err, sizeof(err));
+ ast_log(LOG_WARNING,"Cannot answer '%s': %s\n",
+ ast_channel_name(session->channel), err);
+ /*
+ * Return this value so we can distinguish between this
+ * failure and the threadpool synchronous push failing.
+ */
+ return -2;
+ }
+ return 0;
}
/*! \brief Function called by core when we should answer a PJSIP session */
@@ -591,6 +603,7 @@ static int chan_pjsip_answer(struct ast_channel *ast)
{
struct ast_sip_channel_pvt *channel = ast_channel_tech_pvt(ast);
struct ast_sip_session *session;
+ int res;
if (ast_channel_state(ast) == AST_STATE_UP) {
return 0;
@@ -611,11 +624,15 @@ static int chan_pjsip_answer(struct ast_channel *ast)
can occur between this thread and bridging (specifically when native bridging
attempts to do direct media) */
ast_channel_unlock(ast);
- if (ast_sip_push_task_synchronous(session->serializer, answer, session)) {
- ast_log(LOG_WARNING, "Unable to push answer task to the threadpool. Cannot answer call\n");
+ res = ast_sip_push_task_synchronous(session->serializer, answer, session);
+ if (res) {
+ if (res == -1) {
+ ast_log(LOG_ERROR,"Cannot answer '%s': Unable to push answer task to the threadpool.\n",
+ ast_channel_name(session->channel));
#ifdef HAVE_PJSIP_INV_SESSION_REF
- pjsip_inv_dec_ref(session->inv_session);
+ pjsip_inv_dec_ref(session->inv_session);
#endif
+ }
ao2_ref(session, -1);
ast_channel_lock(ast);
return -1;
diff --git a/configs/samples/ast_debug_tools.conf.sample b/configs/samples/ast_debug_tools.conf.sample
index f26626b20..1c4827f91 100644
--- a/configs/samples/ast_debug_tools.conf.sample
+++ b/configs/samples/ast_debug_tools.conf.sample
@@ -20,6 +20,12 @@
# anyway.
COREDUMPS=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]$(hostname)!(*.txt))
+# The directory to contain output files and work directories.
+# For output from existing core files, the default is the
+# directory that the core file is found in. For core files
+# produced from a running process, the default is /tmp.
+OUTPUTDIR=/some/directory
+
# Date command for the "running" coredump and tarballs.
# DATEFORMAT will be executed to get the timestamp.
# Don't put quotes around the format string or they'll be
diff --git a/configure b/configure
index d4271af89..f64883be1 100755
--- a/configure
+++ b/configure
@@ -17912,6 +17912,7 @@ $as_echo_n "checking for compiler 'attribute pure' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_pure=0
if test "x" = "x"
then
@@ -17930,6 +17931,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_pure=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_pure 1
@@ -17957,6 +17959,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_pure=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_pure 1
@@ -17980,6 +17983,7 @@ $as_echo_n "checking for compiler 'attribute malloc' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_malloc=0
if test "x" = "x"
then
@@ -17998,6 +18002,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_malloc=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_malloc 1
@@ -18025,6 +18030,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_malloc=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_malloc 1
@@ -18048,6 +18054,7 @@ $as_echo_n "checking for compiler 'attribute const' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_const=0
if test "x" = "x"
then
@@ -18066,6 +18073,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_const=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_const 1
@@ -18093,6 +18101,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_const=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_const 1
@@ -18116,6 +18125,7 @@ $as_echo_n "checking for compiler 'attribute unused' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_unused=0
if test "x" = "x"
then
@@ -18134,6 +18144,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_unused=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_unused 1
@@ -18161,6 +18172,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_unused=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_unused 1
@@ -18184,6 +18196,7 @@ $as_echo_n "checking for compiler 'attribute always_inline' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_always_inline=0
if test "x" = "x"
then
@@ -18202,6 +18215,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_always_inline=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_always_inline 1
@@ -18229,6 +18243,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_always_inline=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_always_inline 1
@@ -18252,6 +18267,7 @@ $as_echo_n "checking for compiler 'attribute deprecated' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_deprecated=0
if test "x" = "x"
then
@@ -18270,6 +18286,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_deprecated=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_deprecated 1
@@ -18297,6 +18314,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_deprecated=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_deprecated 1
@@ -18320,6 +18338,7 @@ $as_echo_n "checking for compiler 'attribute sentinel' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_sentinel=0
if test "x" = "x"
then
@@ -18338,6 +18357,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_sentinel=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_sentinel 1
@@ -18365,6 +18385,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_sentinel=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_sentinel 1
@@ -18388,6 +18409,7 @@ $as_echo_n "checking for compiler 'attribute warn_unused_result' support... " >&
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_warn_unused_result=0
if test "x" = "x"
then
@@ -18406,6 +18428,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_warn_unused_result=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_warn_unused_result 1
@@ -18433,6 +18456,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_warn_unused_result=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_warn_unused_result 1
@@ -18456,6 +18480,7 @@ $as_echo_n "checking for compiler 'attribute may_alias' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_may_alias=0
if test "x" = "x"
then
@@ -18474,6 +18499,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_may_alias=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_may_alias 1
@@ -18501,6 +18527,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_may_alias=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_may_alias 1
@@ -18524,6 +18551,7 @@ $as_echo_n "checking for compiler 'attribute constructor' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_constructor=0
if test "x" = "x"
then
@@ -18542,6 +18570,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_constructor=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_constructor 1
@@ -18569,6 +18598,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_constructor=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_constructor 1
@@ -18586,12 +18616,17 @@ fi
CFLAGS="$saved_CFLAGS"
+if test "$ax_cv_have_func_attribute_constructor" != "1"; then
+ as_fn_error $? "*** Function constructor attribute is not supported by your compiler." "$LINENO" 5
+fi
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler 'attribute destructor' support" >&5
$as_echo_n "checking for compiler 'attribute destructor' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_destructor=0
if test "x" = "x"
then
@@ -18610,6 +18645,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_destructor=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_destructor 1
@@ -18637,6 +18673,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_destructor=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_destructor 1
@@ -18654,12 +18691,16 @@ fi
CFLAGS="$saved_CFLAGS"
+if test "$ax_cv_have_func_attribute_destructor" != "1"; then
+ as_fn_error $? "*** Function destructor attribute is not supported by your compiler." "$LINENO" 5
+fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for compiler 'attribute noreturn' support" >&5
$as_echo_n "checking for compiler 'attribute noreturn' support... " >&6; }
saved_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Wall -Wno-unused -Werror"
+ax_cv_have_func_attribute_noreturn=0
if test "xnoreturn" = "x"
then
@@ -18678,6 +18719,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_noreturn=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_noreturn 1
@@ -18705,6 +18747,7 @@ if ac_fn_c_try_compile "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
$as_echo "yes" >&6; }
+ ax_cv_have_func_attribute_noreturn=1
cat >>confdefs.h <<_ACEOF
#define HAVE_ATTRIBUTE_noreturn 1
diff --git a/configure.ac b/configure.ac
index da0400516..30ff4ac31 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1122,7 +1122,14 @@ AST_GCC_ATTRIBUTE(sentinel)
AST_GCC_ATTRIBUTE(warn_unused_result)
AST_GCC_ATTRIBUTE(may_alias)
AST_GCC_ATTRIBUTE(constructor)
+if test "$ax_cv_have_func_attribute_constructor" != "1"; then
+ AC_MSG_ERROR([*** Function constructor attribute is not supported by your compiler.])
+fi
+
AST_GCC_ATTRIBUTE(destructor)
+if test "$ax_cv_have_func_attribute_destructor" != "1"; then
+ AC_MSG_ERROR([*** Function destructor attribute is not supported by your compiler.])
+fi
AST_GCC_ATTRIBUTE(noreturn,noreturn)
AC_MSG_CHECKING(for -fsanitize=address support)
diff --git a/contrib/scripts/ast_coredumper b/contrib/scripts/ast_coredumper
index 9b01a4239..884ede71f 100755
--- a/contrib/scripts/ast_coredumper
+++ b/contrib/scripts/ast_coredumper
@@ -15,7 +15,7 @@ SYNOPSIS
$prog [ --help ] [ --running | --RUNNING ] [ --latest ]
[ --tarball-coredumps ] [ --delete-coredumps-after ]
[ --tarball-results ] [ --delete-results-after ]
- [ --tarball-uniqueid="<uniqueid>" ]
+ [ --tarball-config ] [ --tarball-uniqueid="<uniqueid>" ]
[ --no-default-search ] [ --append-coredumps ]
[ --asterisk-bin="path" ]
[ <coredump> | <pattern> ... ]
@@ -51,7 +51,8 @@ DESCRIPTION
Create a coredump from the running asterisk instance and
process it along with any other coredumps found (if any).
WARNING: This WILL interrupt call processing. You will be
- asked to confirm.
+ asked to confirm. The coredump will be written to /tmp if
+ $OUTPUTDIR is not defined.
--RUNNING
Same as --running but without the confirmation prompt.
@@ -69,10 +70,11 @@ DESCRIPTION
/usr/sbin/asterisk, /usr/lib(64)/libasterisk* and
/usr/lib(64)/asterisk as those files are needed to properly
examine the coredump. The file will be named
- /tmp/asterisk.<timestamp>.coredumps.tar.gz or
- /tmp/asterisk-<uniqueid>.coredumps.tar.gz if
+ $OUTPUTDIR/asterisk.<timestamp>.coredumps.tar.gz or
+ $OUTPUTDIR/asterisk-<uniqueid>.coredumps.tar.gz if
--tarball-uniqueid was specified.
WARNING: This file could 1gb in size!
+ Mutually exclusive with --tartball-results
--delete-coredumps-after
Deletes all processed coredumps regardless of whether
@@ -81,7 +83,8 @@ DESCRIPTION
--tarball-results
Creates a gzipped tarball of all result files produced.
The tarball name will be:
- /tmp/asterisk.<timestamp>.results.tar.gz
+ $OUTPUTDIR/asterisk.<timestamp>.results.tar.gz
+ Mutually exclusive with --tartball-coredumps
--delete-results-after
Deletes all processed results regardless of whether
@@ -89,6 +92,10 @@ DESCRIPTION
to use this option unless you have also specified
--tarball-results.
+ --tarball-config
+ Adds the contents of /etc/asterisk to the tarball created
+ with --tarball-coredumps or --tarball-results.
+
--tarball-uniqueid="<uniqueid>"
Normally DATEFORMAT is used to make the tarballs unique
but you can use your own unique id in the tarball names
@@ -130,6 +137,10 @@ DESCRIPTION
NOTES
You must be root to use $prog.
+ $OUTPUTDIR can be read from the current environment or from the
+ ast_debug_tools.conf file described below. If not specified,
+ work products are placed in the same directory as the core file.
+
The script relies on not only bash, but also recent GNU date and
gdb with python support. *BSD operating systems may require
installation of the 'coreutils' and 'devel/gdb' packagess and minor
@@ -166,6 +177,12 @@ FILES
# anyway.
COREDUMPS=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]\$(hostname)!(*.txt))
+ # The directory to contain output files and work directories.
+ # For output from existing core files, the default is the
+ # directory that the core file is found in. For core files
+ # produced from a running process, the default is /tmp.
+ OUTPUTDIR=/some/directory
+
# Date command for the "running" coredump and tarballs.
# DATEFORMAT will be executed to get the timestamp.
# Don't put quotes around the format string or they'll be
@@ -227,6 +244,13 @@ if [ -z "$GDB" ] ; then
exit 1
fi
+if [ -n "$OUTPUTDIR" ] ; then
+ if [ ! -d "$OUTPUTDIR" ] ; then
+ echo "OUTPUTDIR $OUTPUTDIR doesn't exists or is not a directory"
+ exit 1
+ fi
+fi
+
if [ ${#COREDUMPS[@]} -eq 0 ] ; then
COREDUMPS+=(/tmp/core[-._]asterisk!(*.txt) /tmp/core[-._]$(hostname)!(*.txt))
fi
@@ -326,6 +350,10 @@ fi
# Timestamp to use for output files
df=${tarball_uniqueid:-$(${DATEFORMAT})}
+if [ -z "$asterisk_bin" ]; then
+ asterisk_bin=$(which asterisk)
+fi
+
if $running || $RUNNING ; then
# We need to go through some gyrations to find the pid of the running
# MAIN asterisk process and not someone or something running asterisk -r.
@@ -351,9 +379,9 @@ if $running || $RUNNING ; then
read -p "WARNING: Taking a core dump of the running asterisk instance will suspend call processing while the dump is saved. Do you wish to continue? (y/N) " answer
fi
if [[ "$answer" =~ ^[Yy] ]] ; then
- cf="/tmp/core-asterisk-running-$df"
+ cf="${OUTPUTDIR:-/tmp}/core-asterisk-running-$df"
echo "Dumping running asterisk process to $cf"
- ${GDB} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1
+ ${GDB} ${asterisk_bin} -p $pid -q --batch --ex "gcore $cf" >/dev/null 2>&1
COREDUMPS+=("$cf")
else
echo "Skipping dump of running process"
@@ -370,20 +398,22 @@ fi
# and save them to /tmp/.gdbinit
ss=`egrep -n "^#@@@SCRIPTSTART@@@" $0 |cut -f1 -d:`
-tail -n +${ss} $0 >/tmp/.ast_coredumper.gdbinit
+tail -n +${ss} $0 >${OUTPUTDIR:-/tmp}/.ast_coredumper.gdbinit
# Now iterate over the coredumps and dump the debugging info
for i in ${!COREDUMPS[@]} ; do
cf=${COREDUMPS[$i]}
echo "Processing $cf"
- 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 | (
+
+ cfdir=`dirname ${cf}`
+ cfname=`basename ${cf}`
+ outputdir=${OUTPUTDIR:-${cfdir}}
+
+ ${GDB} -n --batch -q --ex "source ${OUTPUTDIR:-/tmp}/.ast_coredumper.gdbinit" "$asterisk_bin" "$cf" 2>/dev/null | (
of=/dev/null
while IFS= read line ; do
if [[ "$line" =~ !@!@!@!\ ([^\ ]+)\ !@!@!@! ]] ; then
- of=${cf}-${BASH_REMATCH[1]}
+ of=${outputdir}/${cfname}-${BASH_REMATCH[1]}
of=${of//:/-}
rm -f "$of"
echo "Creating $of"
@@ -391,50 +421,58 @@ for i in ${!COREDUMPS[@]} ; do
echo -e $"$line" >> "$of"
done
)
-done
-if $tarball_coredumps ; then
- tf=/tmp/asterisk-$df.coredumps.tar.gz
- echo "Creating $tf"
- dest=/tmp/asterisk-$df
- rm -rf $dest 2>/dev/null || :
- libdir=usr/lib
- [ -d /usr/lib64 ] && libdir+=64
- mkdir -p $dest/tmp $dest/$libdir/asterisk $dest/etc $dest/usr/sbin
- for i in ${!COREDUMPS[@]} ; do
- ln -s "${COREDUMPS[@]}" $dest/"${COREDUMPS[@]}"
- cp "${COREDUMPS[@]}"*.txt $dest/tmp/
- done
- cp /etc/os-release $dest/etc/
- cp -a /$libdir/libasterisk* $dest/$libdir/
- cp -a /$libdir/asterisk/* $dest/$libdir/asterisk/
- cp -a /usr/sbin/asterisk $dest/usr/sbin
- rm -rf $tf
- tar -chzf $tf --transform="s/^[.]/$df/" -C $dest .
- rm -rf $dest
- echo "Created $tf"
-fi
+ if $tarball_coredumps ; then
+ cfname=${cfname//:/-}
+ tf=${outputdir}/${cfname}.tar.gz
+ echo "Creating ${tf}"
-if $delete_coredumps_after ; then
- for i in ${!COREDUMPS[@]} ; do
- rm -rf "${COREDUMPS[$i]}"
- done
-fi
+ dest=${outputdir}/${cfname}.output
+ rm -rf ${dest} 2>/dev/null || :
-if $tarball_results ; then
- tf=/tmp/asterisk-$df-results.tar
- echo "Creating $tf.gz"
- for i in ${!COREDUMPS[@]} ; do
- tar -uvf $tf "${COREDUMPS[$i]//:/-}"-{brief,full,thread1,locks}.txt 2>/dev/null
- done
- gzip $tf
-fi
+ libdir=usr/lib
+ [ -d /usr/lib64 ] && libdir+=64
+ mkdir -p ${dest}/tmp ${dest}/${libdir}/asterisk ${dest}/etc ${dest}/usr/sbin
-if $delete_results_after ; then
- for i in ${!COREDUMPS[@]} ; do
- rm -rf "${COREDUMPS[$i]//:/-}"-{brief,full,thread1,locks}.txt
- done
-fi
+ ln -s ${cf} ${dest}/tmp/${cfname}
+ cp ${outputdir}/${cfname}*.txt ${dest}/tmp/
+ cp /etc/os-release ${dest}/etc/
+ if $tarball_config ; then
+ cp -a /etc/asterisk ${dest}/etc/
+ fi
+ cp -a /${libdir}/libasterisk* ${dest}/${libdir}/
+ cp -a /${libdir}/asterisk/* ${dest}/${libdir}/asterisk/
+ cp -a /usr/sbin/asterisk ${dest}/usr/sbin
+ rm -rf ${tf}
+ tar -chzf ${tf} --transform="s/^[.]/${cfname}/" -C ${dest} .
+ rm -rf ${dest}
+ echo "Created $tf"
+ elif $tarball_results ; then
+ cfname=${cfname//:/-}
+ tf=${outputdir}/${cfname}.tar.gz
+ echo "Creating ${tf}"
+
+ dest=${outputdir}/${cfname}.output
+ rm -rf ${dest} 2>/dev/null || :
+ mkdir -p ${dest}
+ cp ${outputdir}/${cfname}*.txt ${dest}/
+ if $tarball_config ; then
+ mkdir -p ${dest}/etc
+ cp -a /etc/asterisk ${dest}/etc/
+ fi
+ tar -chzf ${tf} --transform="s/^[.]/${cfname}/" -C ${dest} .
+ rm -rf ${dest}
+ echo "Created $tf"
+ fi
+
+if $delete_coredumps_after ; then
+ rm -rf "${cf}"
+ fi
+
+ if $delete_results_after ; then
+ rm -rf "${cf//:/-}"-{brief,full,thread1,locks}.txt
+ fi
+done
exit
@@ -463,6 +501,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
+ except:
+ pass
+ try:
gdb.execute("thread apply 1 bt full", from_tty)
except:
pass
@@ -470,6 +511,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
+ except:
+ pass
+ try:
gdb.execute("thread apply all bt", from_tty)
except:
pass
@@ -477,6 +521,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
+ except:
+ pass
+ try:
gdb.execute("thread apply all bt full", from_tty)
except:
pass
@@ -484,6 +531,9 @@ class DumpAsteriskCommand(gdb.Command):
try:
gdb.execute("p $_siginfo", from_tty)
gdb.execute("info signal $_siginfo.si_signo")
+ except:
+ pass
+ try:
gdb.execute("show_locks", from_tty)
except:
pass
diff --git a/include/asterisk/doxygen/asterisk-git-howto.h b/include/asterisk/doxygen/asterisk-git-howto.h
deleted file mode 100644
index 1ecce15c0..000000000
--- a/include/asterisk/doxygen/asterisk-git-howto.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2009, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- */
-
-/*!
- * \page AsteriskGitHowto How to setup a local GIT mirror of the Asterisk SVN repository
- *
- * <hr>
- *
- * \section Introduction Introduction
- * This document will instruct you how to setup a local git mirror of the
- * Asterisk SVN repository.
- *
- * Why would you want that? for starters, it's a fast repository browser
- * and works well even when offline. More on why and why not at 'Pros and Cons'
- * in the end of this document.
- * <hr>
- *
- * \section Setup Setup
- *
- * Make sure you have the package
- *
- \verbatim
- git-svn
- \endverbatim
- *
- * installed. It is part of the standard git distribution and included in
- * any recent Linux distribution.
- *
- * Next, get the files from this repository:
- *
- \verbatim
- git clone http://git.tzafrir.org.il/git/asterisk-tools.git
- \endverbatim
- *
- * Which will create the subdirectory 'asterisk-tools' under your working
- * directory. For the purpose of this HOWTO I assume that you will later
- * download Asterisk under the same directory.
- *
- * Now let's get Asterisk:
- *
- \verbatim
- git svn clone -s http://svn.digium.com/svn/asterisk
- \endverbatim
- *
- * This will download the whole /trunk , /tags and /branches hirarchies
- * to a new git repository under asterisk/ .
- * This will take a L O N G time. In the order of magnitude of a
- * day. If it stops in the middle:
- *
- \verbatim
- # cd asterisk; git svn fetch --fetch-all
- \endverbatim
- *
- * All commands as of this point are run from the newly-created subdirectory
- * 'asterisk'
- *
- \verbatim
- cd asterisk
- \endverbatim
- *
- * Next make your repository more compact:
- *
- * \note FIXME: I now get a .git subdirectory of the size of 135MB. This seems
- * overly large considering what I got a few monthes ago.
- *
- \verbatim
- git repack -a
- \endverbatim
- *
- * Now fix the menuselect bits. One possible venue is to use submodules.
- * This would require setting a separate menuselect repository . And
- * fixing the submodule references in every new tag to point to the right
- * place. I gave up at this stage, and instead reimplememented menuselect
- *
- \verbatim
- cp -a ../asterisk-tools/menuselect menuselect
- make -C menuselect dummies
- chmod +x menuselect/menuselect
- \endverbatim
- *
- * Next thing to do is ignore generated files. .gitignore is somewhat
- * like svn:ignore . Though it is possible to use one at the top
- * directory. Hence I decided to make it ignore itself as well:
- *
- \verbatim
- cp ../asterisk-tools/asterisk_gitignore .gitignore
- \endverbatim
- *
- * Now let's generate tags that will point to the tags/* branches.
- * e.g. tag 'v1.4.8' will point to the head of branch tags/1.4.8 .
- * If you don't like the extra 'v', just edit the sed command.
- *
- \verbatim
- ../asterisk-tools/update_tags
- \endverbatim
- *
- * Example configuration (refer to menuselect/menuselelct for more
- * information). For instance: res_snmp breaks building 1.4 from git:
- *
- \verbatim
- echo 'exclude res_snmp' >build_tools/conf
- \endverbatim
- *
- * <hr>
- *
- * \section Update Update
- * The main Asterisk repository tends to get new commits occasionally. I
- * suppose you want those updates in your local copy. The following command
- * should normally be done from the master branch. If you actually use branches,
- * it is recommended to switch to it beforehand:
- *
- \verbatim
- git checkout master
- \endverbatim
- *
- * Next, get all updates.
- * <hr>
- *
- * \section Usage Usage
- *
- * If you use git from the command-line, it is highly recommended to enable
- * programmable bash completion. The git command-line is way more complex
- * than svn, but the completion makes it usable:
- *
- *
- \verbatim
- asterisk$ git show v1.2.28<tab><tab>
- v1.2.28 v1.2.28.1
-
- asterisk$ git show v1.2.28:c<tab><tab>
- callerid.c channel.c cli.c coef_out.h contrib/
- cdr/ channels/ codecs/ config.c cryptostub.c
- cdr.c chanvars.c coef_in.h configs/ cygwin/
-
- asterisk$ git svn<tab><tab>
- clone fetch log set-tree
- commit-diff find-rev propget show-externals
- create-ignore info proplist show-ignore
- dcommit init rebase
-
- asterisk$ git svn rebase --f
- --fetch-all --follow-parent
- \endverbatim
- *
- * Some useful commands:
- *
- \verbatim
- git svn rebase --fetch-all # pull updates from upstream
- man git-FOO # documentation for 'git FOO'
- # <tree> is any place on graph of branches: HEAD, name of a branch or
- # a tag, commit ID, and some others
- git show <tree> # The top commit in this tree (log + diff)
- git show <tree>:directory # directory listing
- git show <tree>:some/file # get that file
- git log <tree> # commit log up to that point
- git branch # shows local branches and in which one you are
- git branch -r # List remote branches. Such are SVN ones.
- \endverbatim
- *
- * For more information, see the man page gittutorial as well as
- * \arg http://git-scm.com/documentation
- *
- \verbatim
- git svn rebase --fetch-all
- \endverbatim
- *
- * <hr>
- *
- * \section ProsAndCons Pros and Cons
- *
- * \subsection TheGood The Good
- *
- * Working off-line:
- * If you want to be able to use 'svn log' and 'svn diff' to a different
- * branch, now you can.
- *
- * Efficient repository browser:
- * With git you can effectively browse commit logs and working copies of
- * various branches. In fact, using it merely as a logs and versions
- * browser can be useful on its own.
- *
- * Branches really work:
- * With SVN merging a branch is complicated. Partially because lack of
- * separate merge tracking.With git you don't need the extra svnmerge:
- * changes that don't collide with your branch merge in a quick merge
- * operation.
- *
- * \subsection Limitations Limitations
- *
- * svn:externals :
- * does not really work well with git-svn (and similar systems: svk,
- * bzr-svn and hg-svn). Git has something called submodules that allows
- * emulating the basic functionality of svn:externals, but is not as
- * transparent.
- *
- * Commiting:
- * Not sure how safe it is to commit from such a copy. In most places I
- * see that it is not recommended to commit directly from git-svn. OTOH,
- * git has some tools that make it easy to prepare a patch set out of a
- * branch (e.g. git format-patch).
- *
- * IIRC there are also some issues for git-svn with https certificate
- * authentication in the first place.
- *
- * Tags:
- * /tags are branches. SVN tags are really branches that we pretend not
- * to change. And in fact in Asterisk we practically do change. But see
- * workaround below to generate tags from the tag branches.
- *
- * /team branches::
- * At least with git 1.5.x you can't easily follow all the team branches.
- * This is due to a bug in their handling of wildcards in branches
- * description. I believe this has been resolved in 1.6 but I didn't get
- * to test that. Even if it will, it will require an extra step of manual
- * editing.
- *
- * <hr>
- */
diff --git a/include/asterisk/doxygen/commits.h b/include/asterisk/doxygen/commits.h
deleted file mode 100644
index 032bfc5f4..000000000
--- a/include/asterisk/doxygen/commits.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2009, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- */
-
-/*!
- * \page CommitMessages Guidelines for Commit Messages
- *
- * <hr>
- *
- * \section CommitMsgFormatting Commit Message Formatting
- *
- * The following illustrates the basic outline for commit messages:
- *
- * \verbatim
- * <One-liner summary of changes>
- *
- * <Empty Line>
- *
- * <Verbose description of the changes>
- *
- * <Empty Line>
- *
- * <Special Tags>
- * \endverbatim
- *
- * Some commit history viewers treat the first line of commit messages as the
- * summary for the commit. So, an effort should be made to format our commit
- * messages in that fashion. The verbose description may contain multiple
- * paragraphs, itemized lists, etc. Always end the first sentence (and any
- * subsequent sentences) with punctuation.
- *
- * Commit messages should be wrapped at 80 %columns.
- *
- * \note For trivial commits, such as "fix the build", or "fix spelling mistake",
- * the verbose description may not be necessary.
- *
- * <hr>
- *
- * \section CommitMsgTags Special Tags for Commit Messages
- *
- * \subsection MantisTags Mantis (https://issues.asterisk.org/)
- *
- * To have a commit noted in an issue, use a tag of the form:
- * \arg (issue #1234)
- *
- * To have a commit automatically close an issue, use a tag of the form:
- * \arg (closes issue #1234)
- *
- * When making a commit for a mantis issue, it is easiest to use the
- * provided commit %message template functionality. It will format the
- * special tags appropriately, and will also include information about who
- * reported the issue, which patches are being applied, and who did testing.
- *
- * Assuming that you have bug marshal access (and if you have commit access,
- * it is pretty safe to assume that you do), you will find the commit %message
- * template section directly below the issue details section and above the
- * issue relationships section. You will have to click the '+' next to
- * "Commit message template" to make the contents of the section visible.
- *
- * Here is an example of what the template will generate for you:
- *
- * \verbatim
- * (closes issue #1234)
- * Reported by: SomeGuy
- * Patches:
- * fix_bug_1234.diff uploaded by SomeDeveloper (license 5678)
- * \endverbatim
- *
- * If the patch being committed was written by the person doing the commit,
- * and is not available to reference as an upload to the issue, there is no
- * need to include something like "fixed by me", as that will be the default
- * assumption when a specific patch is not referenced.
- *
- * \subsection ReviewBoardTags Review Board (https://reviewboard.asterisk.org/)
- *
- * To have a commit set a review request as submitted, include the full URL
- * to the review request. For example:
- * \arg Review: %https://reviewboard.asterisk.org/r/95/
- *
- * \note The trailing slash in the review URL is required.
- *
- * <hr>
- *
- * \section CommitMsgSvnmerge Commit Messages with svnmerge
- *
- * When using the svnmerge tool for merging changes between branches, use the
- * commit %message generated by svnmerge. The '-f' option to svnmerge allows
- * you to specify a file for svnmerge to write out a commit %message to. The
- * '-F' option to svn commit allows you to specify a file that contains the
- * commit %message.
- *
- * If you are using the expect script wrappers for svnmerge from repotools,
- * a commit %message is automatically placed in the file '../merge.msg'.
- *
- * For more detailed information about working with branches and merging,
- * see the following page on %asterisk.org:
- * \arg https://wiki.asterisk.org/wiki/display/AST/Subversion+Usage
- */
diff --git a/include/asterisk/doxygen/releases.h b/include/asterisk/doxygen/releases.h
deleted file mode 100644
index d1b33ffd2..000000000
--- a/include/asterisk/doxygen/releases.h
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Asterisk -- An open source telephony toolkit.
- *
- * Copyright (C) 1999 - 2009, Digium, Inc.
- *
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2. See the LICENSE file
- * at the top of the source tree.
- */
-
-/*!
- * \file
- */
-
-/*!
- * \page ReleaseStatus Asterisk Release Status
- *
- * \section warranty Warranty
- * The following warranty applies to all open source releases of Asterisk:
- *
- * NO WARRANTY
- *
- * BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
- * FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
- * OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
- * PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
- * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
- * TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
- * PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
- * REPAIR OR CORRECTION.
-
- * IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
- * WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
- * REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
- * INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
- * OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
- * TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
- * YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
- * PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGES.
- *
- * \section releasestatustypes Release Status Types
- *
- * Release management is a essentially an agreement between the development
- * community and the %user community on what kind of updates can be expected
- * for Asterisk releases, and what types of changes these updates will contain.
- * Once these policies are established, the development community works very
- * hard to adhere to them. However, the development community does reserve
- * the right to make exceptions to these rules for special cases as the need
- * arises.
- *
- * Asterisk releases are in various states of maintenance. The states are
- * defined here:
- *
- * \arg <b>None</b> - This release series is receiving no updates whatsoever.
- * \arg <b>Security-Only</b> - This release series is receiving updates, but
- * only to address security issues. Security issues found and fixed in
- * this release series will be accompanied by a published security advisory
- * from the Asterisk project.
- * \arg <b>Full-Support</b> - This release series is receiving updates for all
- * types of bugs.
- * \arg <b>Full-Development</b> - Changes in this part of Asterisk include bug
- * fixes, as well as new %features and architectural improvements.
- *
- * \section AsteriskReleases Asterisk Maintenance Levels
- *
- * \htmlonly
- * <table border="1">
- * <tr>
- * <td><b>Name</b></td>
- * <td><b>SVN Branch</b></td>
- * <td><b>Status</b></td>
- * <td><b>Notes</b></td>
- * </tr>
- * <tr>
- * <td>Asterisk 1.0</td>
- * <td>/branches/1.0</td>
- * <td>None</td>
- * </tr>
- * <tr>
- * <td>Asterisk 1.2</td>
- * <td>/branches/1.2</td>
- * <td>Security-Only</td>
- * </tr>
- * <tr>
- * <td>Asterisk 1.4</td>
- * <td>/branches/1.4</td>
- * <td>Full-Support</td>
- * </tr>
- * <tr>
- * <td>Asterisk 1.6.0</td>
- * <td>/branches/1.6.0</td>
- * <td>Full-Support</td>
- * </tr>
- * <tr>
- * <td>Asterisk 1.6.1</td>
- * <td>/branches/1.6.1</td>
- * <td>Full-Support</td>
- * <td>Still in beta</td>
- * </tr>
- * <tr>
- * <td>Asterisk trunk</td>
- * <td>/trunk</td>
- * <td>Full-Development</td>
- * <td>No releases are made directly from trunk.</td>
- * </tr>
- * </table>
- * \endhtmlonly
- *
- * For more information on how and when Asterisk releases are made, see the
- * release policies page:
- * \arg \ref ReleasePolicies
- */
-
-/*!
- * \page ReleasePolicies Asterisk Release and Commit Policies
- *
- * \section releasestatus Asterisk Release Status
- *
- * For more information on the current status of each Asterisk release series,
- * please see the Asterisk Release Status page:
- *
- * \arg \ref ReleaseStatus
- *
- * <hr>
- *
- * \section commitmonitoring Commit Monitoring
- *
- * To monitor commits to Asterisk and related projects, visit
- * <a href="http://lists.digium.com/">http://lists.digium.com</a>. The Digium
- * mailing list server hosts a %number of mailing lists for commits.
- *
- * <hr>
- *
- * \section ast10policy Asterisk 1.0
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /branches/1.0
- *
- * \subsection ast10releases Release and Commit Policy
- * No more releases of Asterisk 1.0 will be made for any reason.
- *
- * No commits should be made to the Asterisk 1.0 branch.
- *
- * <hr>
- *
- * \section ast12policy Asterisk 1.2
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /branches/1.2
- *
- * \subsection ast12releases Release and Commit Policy
- *
- * There will be no more scheduled releases of Asterisk 1.2.
- *
- * Commits to the Asterisk 1.2 branch should only address security issues or
- * regressions introduced by previous security fixes. For a security issue, the
- * commit should be accompanied by an
- * <a href="http://downloads.asterisk.org/pub/security/">Asterisk Security Advisory</a>
- * and an immediate release. When a commit goes in to fix a regression, the previous
- * security advisory that is related to the change that introduced the bug should get
- * updated to indicate that there is an updated version of the fix. A release should
- * be made immediately for these regression fixes, as well.
- *
- * \subsection ast12releasenumbers Release Numbering
- *
- * - 1.2.X - a release that contains new security fixes
- * - 1.2.X.Y - a release that contains fixes to the security patches released in
- * version 1.2.X
- *
- * <hr>
- *
- * \section ast14policy Asterisk 1.4
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /branches/1.4
- *
- * \subsection ast14releases Release and Commit Policy
- *
- * Asterisk 1.4 is receiving regular bug fix release updates. An attempt is made to
- * make releases of every four to six weeks. Since this release series is receiving
- * changes for all types of bugs, the number of changes in a single release can be
- * significant. 1.4.X releases go through a release candidate testing cycle to help
- * catch any regressions that may have been introduced.
- *
- * Commits to Asterisk 1.4 must be to address bugs only. No new %features should be
- * introduced into Asterisk 1.4 to reduce the %number of changes to this established
- * release series. The only exceptions to this %rule are for cases where something
- * that may be considered a feature is needed to address a bug or security issue.
- *
- * \subsection ast14releasenumbers Release Numbering
- *
- * - 1.4.X - a release that contains new bug fixes to the 1.4 release series
- * - 1.4.X.Y - a release that contains very few changes on top of 1.4.X. This
- * may be for a security patch, or for a regression introduced in 1.4.X.
- *
- * <hr>
- *
- * \section ast16policy Asterisk 1.6
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /branches/1.6.*
- *
- * \subsection ast16releases Release and Commit Policy
- *
- * Asterisk 1.6 is managed in a different way than previous Asterisk release series.
- * From a high level, it was inspired by the release model used for Linux 2.6.
- * The intended time frame for 1.6.X releases is every 2 or 3 months. Each 1.6.X
- * release gets its own branch. The 1.6.X branches are branches off of trunk.
- * Once the branch is created, it only receives bug fixes. Each 1.6.X release goes
- * through a beta and release candidate testing cycle.
- *
- * After a 1.6.X release is published, it will be maintained until 1.6.[X + 3] is
- * released. While a 1.6.X release branch is still maintained, it will receive only
- * bug fixes. Periodic maintenance releases will be made and labeled as 1.6.X.Y.
- * 1.6.X.Y releases should go through a release candidate test cycle before being
- * published.
- *
- * For now, all previous 1.6 release will be maintained for security issues. Once
- * we have more 1.6 releases to deal with, this part of the policy will likely change.
- *
- * For some history on the motivations for Asterisk 1.6 release management, see the
- * first two sections of this
- * <a href="http://lists.digium.com/pipermail/asterisk-dev/2007-October/030083.html">mailing list post</a>.
- *
- * \subsection ast16releasenumbers Release Numbering
- *
- * - 1.6.X - a release that includes new functionality
- * - 1.6.X.Y - a release that contains fixes for bugs or security issues identified
- * in the 1.6.X release series.
- *
- * <hr>
- *
- * \section asttrunk Asterisk Trunk
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /trunk
- *
- * \subsection asttrunkpolicy Release and Commit Policy
- *
- * No releases are ever made directly from Asterisk trunk.
- *
- * Asterisk trunk is used as the main development area for upcoming Asterisk 1.6
- * releases. Commits to Asterisk trunk are not limited. They can be bug fixes,
- * new %features, and architectural improvements. However, for larger sets
- * of changes, developers should work with the Asterisk project leaders to
- * schedule them for inclusion. Care is taken not to include too many invasive
- * sets of changes for each new Asterisk 1.6 release.
- *
- * No changes should go into Asterisk trunk that are not ready to go into a
- * release. While the upcoming release will go through a beta and release
- * candidate test cycle, code should not be in trunk until the code has been
- * tested and reviewed such that there is reasonable belief that the code
- * is ready to go.
- *
- * <hr>
- *
- * \section astteam Asterisk Team Branches
- *
- * \subsection svnbranch SVN Branch
- *
- * \arg /team/&lt;developername&gt;
- *
- * \subsection astteampolicy Release and Commit Policy
- *
- * The Asterisk subversion repository has a special directory called "team"
- * where developers can make their own personal development branches. This is
- * where new %features, bug fixes, and architectural improvements are developed
- * while they are in %progress.
- *
- * Just about anything goes as far as commits to this area goes. However,
- * developers should keep in mind that anything committed here, as well as
- * anywhere else on Digium's SVN server, falls under the contributor license
- * agreement.
- *
- * In addition to each developer having their own space for working on projects,
- * there is also a team/group folder where %group development efforts take place.
- *
- * Finally, in each developer folder, there is a folder called "private". This
- * is where developers can create branches for working on things that they are
- * not ready for the whole world to see.
- */
diff --git a/include/asterisk/doxygen/reviewboard.h b/include/asterisk/doxygen/reviewboard.h
deleted file mode 100644
index 59ab852bd..000000000
--- a/include/asterisk/doxygen/reviewboard.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
-* Asterisk -- An open source telephony toolkit.
-*
-* Copyright (C) 1999 - 2009, Digium, Inc.
-*
-* See http://www.asterisk.org for more information about
-* the Asterisk project. Please do not directly contact
-* any of the maintainers of this project for assistance;
-* the project provides a web site, mailing lists and IRC
-* channels for your use.
-*
-* This program is free software, distributed under the terms of
-* the GNU General Public License Version 2. See the LICENSE file
-* at the top of the source tree.
-*/
-
-/*!
-* \file
-*/
-
-/*!
- * \page Reviewboard Reviewboard Usage and Guidelines
- *
- * <hr>
- *
- * \section ReviewboardGuidelines Usage Guidelines
- *
- * Mantis (https://issues.asterisk.org) and Reviewboard (https://reviewboard.asterisk.org)
- * are both utilities that the Asterisk development community uses to help
- * track and review code being written for Asterisk. Since both systems
- * are used for posting patches, it is worth discussing when it is appropriate
- * to use reviewboard and when not.
- *
- * Here are the situations in which it is appropriate to post code to reviewboard:
- * - A committer has a patch that they would like to get some feedback on before
- * merging into one of the main branches.
- * - A committer or bug marshal has requested a contributor to post their patch
- * from Mantis on reviewboard to aid in the review process. This typically
- * happens with complex code contributions where reviewboard can help aid in
- * providing feedback.
- *
- * We do encourage all interested parties to participate in the review process.
- * However, aside from the cases mentioned above, we prefer that all code
- * submissions first go through Mantis.
- *
- * \note It is acceptable for a committer to post patches to reviewboard before
- * they are complete to get some feedback on the approach being taken. However,
- * if the code is not yet ready to be merged, it \b must be documented as such.
- * A review request with a patch proposed for merging should have documented
- * testing and should not have blatant coding guidelines violations. Lack of
- * these things is careless and shows disrespect for those reviewing your code.
- *
- * <hr>
- *
- * \section ReviewboardPosting Posting Code to Reviewboard
- *
- * \subsection postreview Using post-review
- *
- * The easiest way to post a patch to reviewboard is by using the
- * post-review tool. We have post-review in our repotools svn repository.
- *
- * \verbatim
- * $ svn co http://svn.digium.com/svn/repotools
- * \endverbatim
- *
- * Essentially, post-review is a script that will take the output of "svn
- * diff" and create a review request out of it for you. So, once you have
- * a working copy with the changes you expect in the output of "svn diff",
- * you just run the following command:
- *
- * \verbatim
- * $ post-review
- * \endverbatim
- *
- * If it complains about not knowing which reviewboard server to use, add
- * the server option:
- *
- * \verbatim
- * $ post-review --server=https://reviewboard.asterisk.org
- * \endverbatim
- *
- * \subsection postreviewnewfiles Dealing with New Files
- *
- * I have one final note about an oddity with using post-review. If you
- * maintain your code in a team branch, and the new code includes new
- * files, there are some additional steps you must take to get post-review
- * to behave properly.
- *
- * You would start by getting your changes applied to a trunk working copy:
- *
- * \verbatim
- * $ cd .../trunk
- * \endverbatim
- *
- * Then, apply the changes from your branch:
- *
- * \verbatim
- * $ svn merge .../trunk .../team/group/my_new_code
- * \endverbatim
- *
- * Now, the code is merged into your working copy. However, for a new
- * file, subversion treats it as a copy of existing content and not new
- * content, so new files don't show up in "svn diff" at this point. To get
- * it to show up in the diff, use the following commands so svn treats it
- * as new content and publishes it in the diff:
- *
- * \verbatim
- * $ svn revert my_new_file.c
- * $ svn add my_new_file.c
- * \endverbatim
- *
- * Now, it should work, and you can run "post-review" as usual.
- *
- * \subsection postreviewupdate Updating Patch on Existing Review Request
- *
- * Most of the time, a patch on reviewboard will require multiple iterations
- * before other sign off on it being ready to be merged. To update the diff
- * for an existing review request, you can use post-review and the -r option.
- * Apply the current version of the diff to a working copy as described above,
- * and then run the following command:
- *
- * \verbatim
- * $ post-review -r <review request number>
- * \endverbatim
- */
diff --git a/include/asterisk/doxyref.h b/include/asterisk/doxyref.h
index 55500230d..14ebb4b83 100644
--- a/include/asterisk/doxyref.h
+++ b/include/asterisk/doxyref.h
@@ -33,12 +33,6 @@
*
* \section devpolicy Development and Release Policies
* \arg \ref CodeGuide : The must-read document for all developers
- * \arg \ref CommitMessages : Information on formatting and special tags for commit messages
- * \arg \ref ReleaseStatus : The current support level for various Asterisk releases
- * \arg \ref ReleasePolicies : Asterisk Release and Commit Policies
- * \arg \ref Reviewboard : Reviewboard Usage and Guidelines
- * \arg \ref MantisWorkflow : Workflow Guidelines for Asterisk Open Source Issue Tracker
- * \arg \ref AsteriskGitHowto : How to setup a local GIT mirror of the Asterisk SVN repository
* \arg \ref AstCREDITS : A Thank You to contributors (unfortunately out of date)
*
* \section apisandinterfaces Asterisk APIs and Interfaces
diff --git a/include/asterisk/http_websocket.h b/include/asterisk/http_websocket.h
index d8e7d063b..83d5d4f78 100644
--- a/include/asterisk/http_websocket.h
+++ b/include/asterisk/http_websocket.h
@@ -344,6 +344,15 @@ AST_OPTIONAL_API(int, ast_websocket_fd, (struct ast_websocket *session), { errno
AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_remote_address, (struct ast_websocket *session), {return NULL;});
/*!
+ * \brief Get the local address for a WebSocket connection session.
+ *
+ * \retval ast_sockaddr Local address
+ *
+ * \since 13.19.0
+ */
+AST_OPTIONAL_API(struct ast_sockaddr *, ast_websocket_local_address, (struct ast_websocket *session), {return NULL;});
+
+/*!
* \brief Get whether the WebSocket session is using a secure transport or not.
*
* \retval 0 if unsecure
diff --git a/include/asterisk/optional_api.h b/include/asterisk/optional_api.h
index 394aed0e4..8d1498ca9 100644
--- a/include/asterisk/optional_api.h
+++ b/include/asterisk/optional_api.h
@@ -107,10 +107,6 @@
#if defined(OPTIONAL_API)
-#if !defined(HAVE_ATTRIBUTE_constructor) || !defined(HAVE_ATTRIBUTE_constructor)
-#error OPTIONAL_API requires compiler constructor/destructor support
-#endif
-
/*!
* \internal
* \brief Function pointer to an optional API function.
diff --git a/include/asterisk/sorcery.h b/include/asterisk/sorcery.h
index 0cb434766..73ed06078 100644
--- a/include/asterisk/sorcery.h
+++ b/include/asterisk/sorcery.h
@@ -312,6 +312,14 @@ struct ast_sorcery_wizard {
/*! \brief Callback for closing a wizard */
void (*close)(void *data);
+
+ /*! \brief Optional callback for retrieving multiple objects by matching their id with a prefix */
+ void (*retrieve_prefix)(const struct ast_sorcery *sorcery,
+ void *data,
+ const char *type,
+ struct ao2_container *objects,
+ const char *prefix,
+ const size_t prefix_len);
};
/*! \brief Interface for a sorcery object type observer */
@@ -364,9 +372,20 @@ int ast_sorcery_init(void);
int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module);
/*!
+ * \brief Register a sorcery wizard
+ *
+ * \param interface Pointer to a wizard interface
+ * \param module Pointer to the module implementing the interface
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ */
+int __ast_sorcery_wizard_register_with_prefix(const struct ast_sorcery_wizard *interface, struct ast_module *module);
+
+/*!
* \brief See \ref __ast_sorcery_wizard_register()
*/
-#define ast_sorcery_wizard_register(interface) __ast_sorcery_wizard_register(interface, ast_module_info ? ast_module_info->self : NULL)
+#define ast_sorcery_wizard_register(interface) __ast_sorcery_wizard_register_with_prefix(interface, ast_module_info ? ast_module_info->self : NULL)
/*!
* \brief Unregister a sorcery wizard
@@ -1218,6 +1237,22 @@ void *ast_sorcery_retrieve_by_fields(const struct ast_sorcery *sorcery, const ch
struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *sorcery, const char *type, const char *regex);
/*!
+ * \brief Retrieve multiple objects whose id begins with the specified prefix
+ * \since 13.19.0
+ *
+ * \param sorcery Pointer to a sorcery structure
+ * \param type Type of object to retrieve
+ * \param prefix Object id prefix
+ * \param prefix_len The length of prefix in bytes
+ *
+ * \retval non-NULL if error occurs
+ * \retval NULL success
+ *
+ * \note The prefix is matched in a case sensitive manner.
+ */
+struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len);
+
+/*!
* \brief Update an object
*
* \param sorcery Pointer to a sorcery structure
diff --git a/main/aoc.c b/main/aoc.c
index d63fbdf15..707dbb00f 100644
--- a/main/aoc.c
+++ b/main/aoc.c
@@ -1861,7 +1861,10 @@ static void aoc_publish_blob(struct ast_channel *chan, struct stasis_message_typ
msg = stasis_message_create(msg_type, aoc_event);
ao2_ref(aoc_event, -1);
- stasis_publish(ast_manager_get_topic(), msg);
+ if (msg) {
+ stasis_publish(ast_manager_get_topic(), msg);
+ ao2_ref(msg, -1);
+ }
}
static struct ast_manager_event_blob *aoc_to_ami(struct stasis_message *message,
diff --git a/main/audiohook.c b/main/audiohook.c
index 869cb750e..cb3c4bcb3 100644
--- a/main/audiohook.c
+++ b/main/audiohook.c
@@ -947,7 +947,9 @@ static struct ast_frame *audio_audiohook_write_list(struct ast_channel *chan, st
* rely on actual media being present to do things.
*/
if (!middle_frame->data.ptr) {
- ast_frfree(middle_frame);
+ if (middle_frame != start_frame) {
+ ast_frfree(middle_frame);
+ }
return start_frame;
}
diff --git a/main/plc.c b/main/plc.c
index 1f0206920..4421e7a0c 100644
--- a/main/plc.c
+++ b/main/plc.c
@@ -98,7 +98,7 @@ static void normalise_history(plc_state_t *s)
if (s->buf_ptr == 0)
return;
memcpy(tmp, s->history, sizeof(int16_t)*s->buf_ptr);
- memcpy(s->history, s->history + s->buf_ptr, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
+ memmove(s->history, s->history + s->buf_ptr, sizeof(int16_t) * (PLC_HISTORY_LEN - s->buf_ptr));
memcpy(s->history + PLC_HISTORY_LEN - s->buf_ptr, tmp, sizeof(int16_t) * s->buf_ptr);
s->buf_ptr = 0;
}
diff --git a/main/sorcery.c b/main/sorcery.c
index 1bdf2c2f8..cb0aff538 100644
--- a/main/sorcery.c
+++ b/main/sorcery.c
@@ -544,6 +544,27 @@ static void sorcery_internal_wizard_destructor(void *obj)
int __ast_sorcery_wizard_register(const struct ast_sorcery_wizard *interface, struct ast_module *module)
{
+ struct ast_sorcery_wizard compat = {
+ .name = interface->name,
+ .open = interface->open,
+ .load = interface->load,
+ .reload = interface->reload,
+ .create = interface->create,
+ .retrieve_id = interface->retrieve_id,
+ .retrieve_regex = interface->retrieve_regex,
+ .retrieve_fields = interface->retrieve_fields,
+ .retrieve_multiple = interface->retrieve_multiple,
+ .update = interface->update,
+ .delete = interface->delete,
+ .close = interface->close,
+ .retrieve_prefix = NULL,
+ };
+
+ return __ast_sorcery_wizard_register_with_prefix(&compat, module);
+}
+
+int __ast_sorcery_wizard_register_with_prefix(const struct ast_sorcery_wizard *interface, struct ast_module *module)
+{
struct ast_sorcery_internal_wizard *wizard;
int res = -1;
@@ -1982,6 +2003,36 @@ struct ao2_container *ast_sorcery_retrieve_by_regex(const struct ast_sorcery *so
return objects;
}
+struct ao2_container *ast_sorcery_retrieve_by_prefix(const struct ast_sorcery *sorcery, const char *type, const char *prefix, const size_t prefix_len)
+{
+ RAII_VAR(struct ast_sorcery_object_type *, object_type, ao2_find(sorcery->types, type, OBJ_KEY), ao2_cleanup);
+ struct ao2_container *objects;
+ int i;
+
+ if (!object_type || !(objects = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL))) {
+ return NULL;
+ }
+
+ AST_VECTOR_RW_RDLOCK(&object_type->wizards);
+ for (i = 0; i < AST_VECTOR_SIZE(&object_type->wizards); i++) {
+ struct ast_sorcery_object_wizard *wizard =
+ AST_VECTOR_GET(&object_type->wizards, i);
+
+ if (!wizard->wizard->callbacks.retrieve_prefix) {
+ continue;
+ }
+
+ wizard->wizard->callbacks.retrieve_prefix(sorcery, wizard->data, object_type->name, objects, prefix, prefix_len);
+
+ if (wizard->caching && ao2_container_count(objects)) {
+ break;
+ }
+ }
+ AST_VECTOR_RW_UNLOCK(&object_type->wizards);
+
+ return objects;
+}
+
/*! \brief Internal function which returns if the wizard has created the object */
static int sorcery_wizard_create(const struct ast_sorcery_object_wizard *object_wizard, const struct sorcery_details *details)
{
diff --git a/res/res_fax.c b/res/res_fax.c
index 666c2d997..6e4451b67 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -4563,12 +4563,7 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
unsigned int gwtimeout;
if (sscanf(timeout, "%30u", &gwtimeout) == 1) {
- if (gwtimeout >= 0) {
- details->gateway_timeout = gwtimeout * 1000;
- } else {
- ast_log(LOG_WARNING, "%s(%s) timeout cannot be negative. Ignoring timeout\n",
- cmd, data);
- }
+ details->gateway_timeout = gwtimeout * 1000;
} else {
ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n", timeout, data);
}
@@ -4607,13 +4602,7 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
if (details->faxdetect_id < 0) {
if (timeout) {
if (sscanf(timeout, "%30u", &fdtimeout) == 1) {
- if (fdtimeout >= 0) {
- fdtimeout *= 1000;
- } else {
- ast_log(LOG_WARNING, "%s(%s) timeout cannot be negative. Ignoring timeout\n",
- cmd, data);
- fdtimeout = 0;
- }
+ fdtimeout *= 1000;
} else {
ast_log(LOG_WARNING, "Unsupported timeout '%s' passed to FAXOPT(%s).\n",
timeout, data);
diff --git a/res/res_hep_pjsip.c b/res/res_hep_pjsip.c
index 1614b4319..1d99fcc17 100644
--- a/res/res_hep_pjsip.c
+++ b/res/res_hep_pjsip.c
@@ -91,35 +91,44 @@ static pj_status_t logging_on_tx_msg(pjsip_tx_data *tdata)
pjsip_cid_hdr *cid_hdr;
pjsip_from_hdr *from_hdr;
pjsip_to_hdr *to_hdr;
- pjsip_tpmgr_fla2_param prm;
capture_info = hepv3_create_capture_info(tdata->buf.start, (size_t)(tdata->buf.cur - tdata->buf.start));
if (!capture_info) {
return PJ_SUCCESS;
}
- /* Attempt to determine what IP address will we send this packet out of */
- 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;
+ if (!(tdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+ pjsip_tpmgr_fla2_param prm;
- /* If we can't get the local address use what we have already */
- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
- pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
- } else {
- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ /* Attempt to determine what IP address will we send this packet out of */
+ 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;
+
+ /* If we can't get the local address use what we have already */
+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), tdata->pool, &prm) != PJ_SUCCESS) {
+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
} else {
- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ } else {
+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ }
}
+ } else {
+ /* For reliable transports they can only ever come from the transport
+ * local address.
+ */
+ pj_sockaddr_print(&tdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
}
+
pj_sockaddr_print(&tdata->tp_info.dst_addr, remote_buf, sizeof(remote_buf), 3);
cid_hdr = PJSIP_MSG_CID_HDR(tdata->msg);
@@ -152,7 +161,6 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
char remote_buf[256];
char *uuid;
struct hepv3_capture_info *capture_info;
- pjsip_tpmgr_fla2_param prm;
capture_info = hepv3_create_capture_info(&rdata->pkt_info.packet, rdata->pkt_info.len);
if (!capture_info) {
@@ -164,27 +172,33 @@ static pj_bool_t logging_on_rx_msg(pjsip_rx_data *rdata)
}
pj_sockaddr_print(&rdata->pkt_info.src_addr, remote_buf, sizeof(remote_buf), 3);
- /* Attempt to determine what IP address we probably received this packet on */
- pjsip_tpmgr_fla2_param_default(&prm);
- prm.tp_type = rdata->tp_info.transport->key.type;
- pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
- prm.local_if = PJ_TRUE;
+ if (!(rdata->tp_info.transport->flag & PJSIP_TRANSPORT_RELIABLE)) {
+ pjsip_tpmgr_fla2_param prm;
- /* If we can't get the local address use what we have already */
- if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
- pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
- } else {
- if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
- snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ /* Attempt to determine what IP address we probably received this packet on */
+ pjsip_tpmgr_fla2_param_default(&prm);
+ prm.tp_type = rdata->tp_info.transport->key.type;
+ pj_strset2(&prm.dst_host, rdata->pkt_info.src_name);
+ prm.local_if = PJ_TRUE;
+
+ /* If we can't get the local address use what we have already */
+ if (pjsip_tpmgr_find_local_addr2(pjsip_endpt_get_tpmgr(ast_sip_get_pjsip_endpoint()), rdata->tp_info.pool, &prm) != PJ_SUCCESS) {
+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
} else {
- snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
- (int)pj_strlen(&prm.ret_addr),
- pj_strbuf(&prm.ret_addr),
- prm.ret_port);
+ if (prm.tp_type & PJSIP_TRANSPORT_IPV6) {
+ snprintf(local_buf, sizeof(local_buf), "[%.*s]:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ } else {
+ snprintf(local_buf, sizeof(local_buf), "%.*s:%hu",
+ (int)pj_strlen(&prm.ret_addr),
+ pj_strbuf(&prm.ret_addr),
+ prm.ret_port);
+ }
}
+ } else {
+ pj_sockaddr_print(&rdata->tp_info.transport->local_addr, local_buf, sizeof(local_buf), 3);
}
uuid = assign_uuid(&rdata->msg_info.cid->id, &rdata->msg_info.to->tag, &rdata->msg_info.from->tag);
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 2baccc052..75a6eba64 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -87,18 +87,19 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
/*! \brief Structure definition for session */
struct ast_websocket {
- FILE *f; /*!< Pointer to the file instance used for writing and reading */
- int fd; /*!< File descriptor for the session, only used for polling */
- struct ast_sockaddr address; /*!< Address of the remote client */
- enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */
- size_t payload_len; /*!< Length of the payload */
- char *payload; /*!< Pointer to the payload */
- size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
- int timeout; /*!< The timeout for operations on the socket */
- unsigned int secure:1; /*!< Bit to indicate that the transport is secure */
- unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */
- unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
- struct websocket_client *client; /*!< Client object when connected as a client websocket */
+ FILE *f; /*!< Pointer to the file instance used for writing and reading */
+ int fd; /*!< File descriptor for the session, only used for polling */
+ struct ast_sockaddr remote_address; /*!< Address of the remote client */
+ struct ast_sockaddr local_address; /*!< Our local address */
+ enum ast_websocket_opcode opcode; /*!< Cached opcode for multi-frame messages */
+ size_t payload_len; /*!< Length of the payload */
+ char *payload; /*!< Pointer to the payload */
+ size_t reconstruct; /*!< Number of bytes before a reconstructed payload will be returned and a new one started */
+ int timeout; /*!< The timeout for operations on the socket */
+ unsigned int secure:1; /*!< Bit to indicate that the transport is secure */
+ unsigned int closing:1; /*!< Bit to indicate that the session is in the process of being closed */
+ unsigned int close_sent:1; /*!< Bit to indicate that the session close opcode has been sent and no further data will be sent */
+ struct websocket_client *client; /*!< Client object when connected as a client websocket */
};
/*! \brief Hashing function for protocols */
@@ -183,7 +184,7 @@ static void session_destroy_fn(void *obj)
if (session->f) {
fclose(session->f);
ast_verb(2, "WebSocket connection %s '%s' closed\n", session->client ? "to" : "from",
- ast_sockaddr_stringify(&session->address));
+ ast_sockaddr_stringify(&session->remote_address));
}
}
@@ -316,7 +317,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_close)(struct ast_websocket *session, ui
fclose(session->f);
session->f = NULL;
ast_verb(2, "WebSocket connection %s '%s' forcefully closed due to fatal write error\n",
- session->client ? "to" : "from", ast_sockaddr_stringify(&session->address));
+ session->client ? "to" : "from", ast_sockaddr_stringify(&session->remote_address));
}
ao2_unlock(session);
@@ -429,7 +430,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_fd)(struct ast_websocket *session)
struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_remote_address)(struct ast_websocket *session)
{
- return &session->address;
+ return &session->remote_address;
+}
+
+struct ast_sockaddr * AST_OPTIONAL_API_NAME(ast_websocket_local_address)(struct ast_websocket *session)
+{
+ return &session->local_address;
}
int AST_OPTIONAL_API_NAME(ast_websocket_is_secure)(struct ast_websocket *session)
@@ -890,12 +896,22 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
return 0;
}
+ /* Get our local address for the connected socket */
+ if (ast_getsockname(ser->fd, &session->local_address)) {
+ ast_log(LOG_WARNING, "WebSocket connection from '%s' could not be accepted - failed to get local address\n",
+ ast_sockaddr_stringify(&ser->remote_address));
+ websocket_bad_request(ser);
+ ao2_ref(session, -1);
+ ao2_ref(protocol_handler, -1);
+ return 0;
+ }
+
ast_verb(2, "WebSocket connection from '%s' for protocol '%s' accepted using version '%d'\n", ast_sockaddr_stringify(&ser->remote_address), protocol ? : "", version);
/* Populate the session with all the needed details */
session->f = ser->f;
session->fd = ser->fd;
- ast_sockaddr_copy(&session->address, &ser->remote_address);
+ ast_sockaddr_copy(&session->remote_address, &ser->remote_address);
session->opcode = -1;
session->reconstruct = DEFAULT_RECONSTRUCTION_CEILING;
session->secure = ser->ssl ? 1 : 0;
@@ -1350,7 +1366,7 @@ static enum ast_websocket_result websocket_client_connect(struct ast_websocket *
ws->f = ws->client->ser->f;
ws->fd = ws->client->ser->fd;
ws->secure = ws->client->ser->ssl ? 1 : 0;
- ast_sockaddr_copy(&ws->address, &ws->client->ser->remote_address);
+ ast_sockaddr_copy(&ws->remote_address, &ws->client->ser->remote_address);
return WS_OK;
}
diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c
index 81234d695..d2e7b2b69 100644
--- a/res/res_pjsip/pjsip_configuration.c
+++ b/res/res_pjsip/pjsip_configuration.c
@@ -368,7 +368,7 @@ static int contact_acl_to_str(const void *obj, const intptr_t *args, char **buf)
static int dtmf_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
{
struct ast_sip_endpoint *endpoint = obj;
- enum ast_sip_dtmf_mode dtmf = ast_sip_str_to_dtmf(var->value);
+ int dtmf = ast_sip_str_to_dtmf(var->value);
if (dtmf == -1) {
return -1;
diff --git a/res/res_pjsip_endpoint_identifier_anonymous.c b/res/res_pjsip_endpoint_identifier_anonymous.c
index b93133824..2a47cbe3f 100644
--- a/res/res_pjsip_endpoint_identifier_anonymous.c
+++ b/res/res_pjsip_endpoint_identifier_anonymous.c
@@ -56,9 +56,11 @@ static int find_transport_state_in_use(void *obj, void *arg, int flags)
return 0;
}
+#define DOMAIN_NAME_LEN 255
+
static struct ast_sip_endpoint *anonymous_identify(pjsip_rx_data *rdata)
{
- char domain_name[64], id[AST_UUID_STR_LEN];
+ char domain_name[DOMAIN_NAME_LEN + 1];
struct ast_sip_endpoint *endpoint;
RAII_VAR(struct ast_sip_domain_alias *, alias, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, transport_states, NULL, ao2_cleanup);
@@ -70,6 +72,8 @@ static struct ast_sip_endpoint *anonymous_identify(pjsip_rx_data *rdata)
}
if (!ast_sip_get_disable_multi_domain()) {
+ char id[sizeof("anonymous@") + DOMAIN_NAME_LEN];
+
/* Attempt to find the endpoint given the name and domain provided */
snprintf(id, sizeof(id), "anonymous@%s", domain_name);
if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
diff --git a/res/res_pjsip_endpoint_identifier_user.c b/res/res_pjsip_endpoint_identifier_user.c
index 30da062ed..b79dcb59b 100644
--- a/res/res_pjsip_endpoint_identifier_user.c
+++ b/res/res_pjsip_endpoint_identifier_user.c
@@ -74,10 +74,12 @@ static int find_transport_state_in_use(void *obj, void *arg, int flags)
return 0;
}
+#define DOMAIN_NAME_LEN 255
+#define USERNAME_LEN 255
+
static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoint_name,
char *domain_name)
{
- char id[AST_UUID_STR_LEN];
struct ast_sip_endpoint *endpoint;
RAII_VAR(struct ast_sip_domain_alias *, alias, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, transport_states, NULL, ao2_cleanup);
@@ -85,6 +87,8 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
RAII_VAR(struct ast_sip_transport *, transport, NULL, ao2_cleanup);
if (!ast_sip_get_disable_multi_domain()) {
+ char id[DOMAIN_NAME_LEN + USERNAME_LEN + sizeof("@")];
+
/* Attempt to find the endpoint given the name and domain provided */
snprintf(id, sizeof(id), "%s@%s", endpoint_name, domain_name);
if ((endpoint = ast_sorcery_retrieve_by_id(ast_sip_get_sorcery(), "endpoint", id))) {
@@ -116,8 +120,8 @@ static struct ast_sip_endpoint *find_endpoint(pjsip_rx_data *rdata, char *endpoi
static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
{
- char username[64];
- char domain[64];
+ char username[USERNAME_LEN + 1];
+ char domain[DOMAIN_NAME_LEN + 1];
struct ast_sip_endpoint *endpoint;
if (get_from_header(rdata, username, sizeof(username), domain, sizeof(domain))) {
@@ -149,7 +153,7 @@ static struct ast_sip_endpoint *username_identify(pjsip_rx_data *rdata)
static struct ast_sip_endpoint *auth_username_identify(pjsip_rx_data *rdata)
{
- char username[64], realm[64];
+ char username[USERNAME_LEN + 1], realm[DOMAIN_NAME_LEN + 1];
struct ast_sip_endpoint *endpoint;
pjsip_authorization_hdr *auth_header = NULL;
diff --git a/res/res_pjsip_transport_websocket.c b/res/res_pjsip_transport_websocket.c
index c04594fee..b874a4de3 100644
--- a/res/res_pjsip_transport_websocket.c
+++ b/res/res_pjsip_transport_websocket.c
@@ -203,27 +203,25 @@ static int transport_create(void *data)
ast_debug(4, "Creating websocket transport for %s:%s\n",
newtransport->transport.type_name, ws_addr_str);
+ newtransport->transport.info = (char *) pj_pool_alloc(newtransport->transport.pool,
+ strlen(newtransport->transport.type_name) + strlen(ws_addr_str) + sizeof(" to "));
+ sprintf(newtransport->transport.info, "%s to %s", newtransport->transport.type_name, ws_addr_str);
+
pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.key.rem_addr);
if (newtransport->transport.key.rem_addr.addr.sa_family == pj_AF_INET6()) {
newtransport->transport.key.type = transport_type_wss_ipv6;
- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET6_ADDRSTRLEN);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET6_ADDRSTRLEN, 0);
} else {
newtransport->transport.key.type = transport_type_wss;
- newtransport->transport.local_name.host.ptr = (char *)pj_pool_alloc(pool, PJ_INET_ADDRSTRLEN);
- pj_sockaddr_print(&newtransport->transport.key.rem_addr, newtransport->transport.local_name.host.ptr, PJ_INET_ADDRSTRLEN, 0);
}
newtransport->transport.addr_len = pj_sockaddr_get_len(&newtransport->transport.key.rem_addr);
- pj_sockaddr_cp(&newtransport->transport.local_addr, &newtransport->transport.key.rem_addr);
-
- newtransport->transport.local_name.host.slen = pj_ansi_strlen(newtransport->transport.local_name.host.ptr);
- newtransport->transport.local_name.port = pj_sockaddr_get_port(&newtransport->transport.key.rem_addr);
+ ws_addr_str = ast_sockaddr_stringify(ast_websocket_local_address(newtransport->ws_session));
+ pj_sockaddr_parse(pj_AF_UNSPEC(), 0, pj_cstr(&buf, ws_addr_str), &newtransport->transport.local_addr);
+ pj_strdup2(pool, &newtransport->transport.local_name.host, ast_sockaddr_stringify_host(ast_websocket_local_address(newtransport->ws_session)));
+ newtransport->transport.local_name.port = ast_sockaddr_port(ast_websocket_local_address(newtransport->ws_session));
newtransport->transport.flag = pjsip_transport_get_flag_from_type((pjsip_transport_type_e)newtransport->transport.key.type);
- newtransport->transport.info = (char *)pj_pool_alloc(newtransport->transport.pool, 64);
-
newtransport->transport.dir = PJSIP_TP_DIR_INCOMING;
newtransport->transport.tpmgr = tpmgr;
newtransport->transport.send_msg = &ws_send_msg;
diff --git a/res/res_sorcery_astdb.c b/res/res_sorcery_astdb.c
index 1aec0be95..fee857525 100644
--- a/res/res_sorcery_astdb.c
+++ b/res/res_sorcery_astdb.c
@@ -46,6 +46,7 @@ static void *sorcery_astdb_retrieve_fields(const struct ast_sorcery *sorcery, vo
static void sorcery_astdb_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects,
const struct ast_variable *fields);
static void sorcery_astdb_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
+static void sorcery_astdb_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len);
static int sorcery_astdb_update(const struct ast_sorcery *sorcery, void *data, void *object);
static int sorcery_astdb_delete(const struct ast_sorcery *sorcery, void *data, void *object);
static void sorcery_astdb_close(void *data);
@@ -58,6 +59,7 @@ static struct ast_sorcery_wizard astdb_object_wizard = {
.retrieve_fields = sorcery_astdb_retrieve_fields,
.retrieve_multiple = sorcery_astdb_retrieve_multiple,
.retrieve_regex = sorcery_astdb_retrieve_regex,
+ .retrieve_prefix = sorcery_astdb_retrieve_prefix,
.update = sorcery_astdb_update,
.delete = sorcery_astdb_delete,
.close = sorcery_astdb_close,
@@ -329,6 +331,42 @@ static void sorcery_astdb_retrieve_regex(const struct ast_sorcery *sorcery, void
regfree(&expression);
}
+static void sorcery_astdb_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
+{
+ const char *family_prefix = data;
+ size_t family_len = strlen(family_prefix) + strlen(type) + 1; /* +1 for slash delimiter */
+ char family[family_len + 1];
+ char tree[prefix_len + sizeof("%")];
+ RAII_VAR(struct ast_db_entry *, entries, NULL, ast_db_freetree);
+ struct ast_db_entry *entry;
+
+ snprintf(tree, sizeof(tree), "%.*s%%", (int) prefix_len, prefix);
+ snprintf(family, sizeof(family), "%s/%s", family_prefix, type);
+
+ if (!(entries = ast_db_gettree(family, tree))) {
+ return;
+ }
+
+ for (entry = entries; entry; entry = entry->next) {
+ /* The key in the entry includes the family, so we need to strip it out */
+ const char *key = entry->key + family_len + 2;
+ RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
+ struct ast_json_error error;
+ RAII_VAR(void *, object, NULL, ao2_cleanup);
+ RAII_VAR(struct ast_variable *, objset, NULL, ast_variables_destroy);
+
+ if (!(json = ast_json_load_string(entry->data, &error))
+ || (ast_json_to_ast_variables(json, &objset) != AST_JSON_TO_AST_VARS_CODE_SUCCESS)
+ || !(objset = sorcery_astdb_filter_objectset(objset, sorcery, type))
+ || !(object = ast_sorcery_alloc(sorcery, type, key))
+ || ast_sorcery_objectset_apply(sorcery, object, objset)) {
+ return;
+ }
+
+ ao2_link(objects, object);
+ }
+}
+
static int sorcery_astdb_update(const struct ast_sorcery *sorcery, void *data, void *object)
{
const char *prefix = data;
diff --git a/res/res_sorcery_config.c b/res/res_sorcery_config.c
index 7fd7e769a..b02000eab 100644
--- a/res/res_sorcery_config.c
+++ b/res/res_sorcery_config.c
@@ -73,6 +73,12 @@ struct sorcery_config_fields_cmp_params {
/*! \brief Regular expression for checking object id */
regex_t *regex;
+ /*! \brief Prefix for matching object id */
+ const char *prefix;
+
+ /*! \brief Prefix length in bytes for matching object id */
+ const size_t prefix_len;
+
/*! \brief Optional container to put object into */
struct ao2_container *container;
};
@@ -85,6 +91,7 @@ static void *sorcery_config_retrieve_fields(const struct ast_sorcery *sorcery, v
static void sorcery_config_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects,
const struct ast_variable *fields);
static void sorcery_config_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
+static void sorcery_config_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len);
static void sorcery_config_close(void *data);
static struct ast_sorcery_wizard config_object_wizard = {
@@ -96,6 +103,7 @@ static struct ast_sorcery_wizard config_object_wizard = {
.retrieve_fields = sorcery_config_retrieve_fields,
.retrieve_multiple = sorcery_config_retrieve_multiple,
.retrieve_regex = sorcery_config_retrieve_regex,
+ .retrieve_prefix = sorcery_config_retrieve_prefix,
.close = sorcery_config_close,
};
@@ -120,6 +128,11 @@ static int sorcery_config_fields_cmp(void *obj, void *arg, int flags)
ao2_link(params->container, obj);
}
return 0;
+ } else if (params->prefix) {
+ if (!strncmp(params->prefix, ast_sorcery_object_get_id(obj), params->prefix_len)) {
+ ao2_link(params->container, obj);
+ }
+ return 0;
} else if (params->fields &&
(!(objset = ast_sorcery_objectset_create(params->sorcery, obj)) ||
(!ast_variable_lists_match(objset, params->fields, 0)))) {
@@ -208,6 +221,24 @@ static void sorcery_config_retrieve_regex(const struct ast_sorcery *sorcery, voi
regfree(&expression);
}
+static void sorcery_config_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
+{
+ struct sorcery_config *config = data;
+ RAII_VAR(struct ao2_container *, config_objects, ao2_global_obj_ref(config->objects), ao2_cleanup);
+ struct sorcery_config_fields_cmp_params params = {
+ .sorcery = sorcery,
+ .container = objects,
+ .prefix = prefix,
+ .prefix_len = prefix_len,
+ };
+
+ if (!config_objects) {
+ return;
+ }
+
+ ao2_callback(config_objects, OBJ_NODATA | OBJ_MULTIPLE, sorcery_config_fields_cmp, &params);
+}
+
/*! \brief Internal function which determines if criteria has been met for considering an object set applicable */
static int sorcery_is_criteria_met(struct ast_variable *objset, struct ast_variable *criteria)
{
diff --git a/res/res_sorcery_memory.c b/res/res_sorcery_memory.c
index b2f05591b..a05f05d9e 100644
--- a/res/res_sorcery_memory.c
+++ b/res/res_sorcery_memory.c
@@ -48,6 +48,7 @@ static void *sorcery_memory_retrieve_fields(const struct ast_sorcery *sorcery, v
static void sorcery_memory_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects,
const struct ast_variable *fields);
static void sorcery_memory_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
+static void sorcery_memory_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len);
static int sorcery_memory_update(const struct ast_sorcery *sorcery, void *data, void *object);
static int sorcery_memory_delete(const struct ast_sorcery *sorcery, void *data, void *object);
static void sorcery_memory_close(void *data);
@@ -60,6 +61,7 @@ static struct ast_sorcery_wizard memory_object_wizard = {
.retrieve_fields = sorcery_memory_retrieve_fields,
.retrieve_multiple = sorcery_memory_retrieve_multiple,
.retrieve_regex = sorcery_memory_retrieve_regex,
+ .retrieve_prefix = sorcery_memory_retrieve_prefix,
.update = sorcery_memory_update,
.delete = sorcery_memory_delete,
.close = sorcery_memory_close,
@@ -76,6 +78,12 @@ struct sorcery_memory_fields_cmp_params {
/*! \brief Regular expression for checking object id */
regex_t *regex;
+ /*! \brief Prefix for matching object id */
+ const char *prefix;
+
+ /*! \brief Prefix length in bytes for matching object id */
+ const size_t prefix_len;
+
/*! \brief Optional container to put object into */
struct ao2_container *container;
};
@@ -127,6 +135,11 @@ static int sorcery_memory_fields_cmp(void *obj, void *arg, int flags)
ao2_link(params->container, obj);
}
return 0;
+ } else if (params->prefix) {
+ if (!strncmp(params->prefix, ast_sorcery_object_get_id(obj), params->prefix_len)) {
+ ao2_link(params->container, obj);
+ }
+ return 0;
} else if (params->fields &&
(!(objset = ast_sorcery_objectset_create(params->sorcery, obj)) ||
(!ast_variable_lists_match(objset, params->fields, 0)))) {
@@ -200,6 +213,18 @@ static void sorcery_memory_retrieve_regex(const struct ast_sorcery *sorcery, voi
regfree(&expression);
}
+static void sorcery_memory_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *prefix, const size_t prefix_len)
+{
+ struct sorcery_memory_fields_cmp_params params = {
+ .sorcery = sorcery,
+ .container = objects,
+ .prefix = prefix,
+ .prefix_len = prefix_len,
+ };
+
+ ao2_callback(data, 0, sorcery_memory_fields_cmp, &params);
+}
+
static int sorcery_memory_update(const struct ast_sorcery *sorcery, void *data, void *object)
{
RAII_VAR(void *, existing, NULL, ao2_cleanup);
diff --git a/res/res_sorcery_memory_cache.c b/res/res_sorcery_memory_cache.c
index bf2347ccd..30e6ef04b 100644
--- a/res/res_sorcery_memory_cache.c
+++ b/res/res_sorcery_memory_cache.c
@@ -185,6 +185,10 @@ struct sorcery_memory_cache_fields_cmp_params {
const struct ast_variable *fields;
/*! \brief Regular expression for checking object id */
regex_t *regex;
+ /*! \brief Prefix for matching object id */
+ const char *prefix;
+ /*! \brief Prefix length in bytes for matching object id */
+ const size_t prefix_len;
/*! \brief Optional container to put object into */
struct ao2_container *container;
};
@@ -201,6 +205,8 @@ static void sorcery_memory_cache_retrieve_multiple(const struct ast_sorcery *sor
struct ao2_container *objects, const struct ast_variable *fields);
static void sorcery_memory_cache_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type,
struct ao2_container *objects, const char *regex);
+static void sorcery_memory_cache_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type,
+ struct ao2_container *objects, const char *prefix, const size_t prefix_len);
static int sorcery_memory_cache_delete(const struct ast_sorcery *sorcery, void *data, void *object);
static void sorcery_memory_cache_close(void *data);
@@ -216,6 +222,7 @@ static struct ast_sorcery_wizard memory_cache_object_wizard = {
.retrieve_fields = sorcery_memory_cache_retrieve_fields,
.retrieve_multiple = sorcery_memory_cache_retrieve_multiple,
.retrieve_regex = sorcery_memory_cache_retrieve_regex,
+ .retrieve_prefix = sorcery_memory_cache_retrieve_prefix,
.close = sorcery_memory_cache_close,
};
@@ -1253,6 +1260,11 @@ static int sorcery_memory_cache_fields_cmp(void *obj, void *arg, int flags)
ao2_link(params->container, cached->object);
}
return 0;
+ } else if (params->prefix) {
+ if (!strncmp(params->prefix, ast_sorcery_object_get_id(cached->object), params->prefix_len)) {
+ ao2_link(params->container, cached->object);
+ }
+ return 0;
} else if (params->fields &&
(!ast_variable_lists_match(cached->objectset, params->fields, 0))) {
/* If we can't turn the object into an object set OR if differences exist between the fields
@@ -1378,6 +1390,40 @@ static void sorcery_memory_cache_retrieve_regex(const struct ast_sorcery *sorcer
/*!
* \internal
+ * \brief Callback function to retrieve multiple objects whose id matches a prefix
+ *
+ * \param sorcery The sorcery instance
+ * \param data The sorcery memory cache
+ * \param type The type of the object to retrieve
+ * \param objects Container to place the objects into
+ * \param prefix Prefix to match against the object id
+ */
+static void sorcery_memory_cache_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type,
+ struct ao2_container *objects, const char *prefix, const size_t prefix_len)
+{
+ struct sorcery_memory_cache *cache = data;
+ struct sorcery_memory_cache_fields_cmp_params params = {
+ .sorcery = sorcery,
+ .cache = cache,
+ .container = objects,
+ .prefix = prefix,
+ .prefix_len = prefix_len,
+ };
+
+ if (is_passthru_update() || !cache->full_backend_cache) {
+ return;
+ }
+
+ memory_cache_full_update(sorcery, type, cache);
+ ao2_callback(cache->objects, 0, sorcery_memory_cache_fields_cmp, &params);
+
+ if (ao2_container_count(objects)) {
+ memory_cache_stale_check(sorcery, cache);
+ }
+}
+
+/*!
+ * \internal
* \brief Callback function to finish configuring the memory cache
*
* \param data The sorcery memory cache
diff --git a/res/res_sorcery_realtime.c b/res/res_sorcery_realtime.c
index 138d6ea95..1c52eb90f 100644
--- a/res/res_sorcery_realtime.c
+++ b/res/res_sorcery_realtime.c
@@ -59,6 +59,8 @@ static void *sorcery_realtime_retrieve_fields(const struct ast_sorcery *sorcery,
static void sorcery_realtime_retrieve_multiple(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects,
const struct ast_variable *fields);
static void sorcery_realtime_retrieve_regex(const struct ast_sorcery *sorcery, void *data, const char *type, struct ao2_container *objects, const char *regex);
+static void sorcery_realtime_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type,
+ struct ao2_container *objects, const char *prefix, const size_t prefix_len);
static int sorcery_realtime_update(const struct ast_sorcery *sorcery, void *data, void *object);
static int sorcery_realtime_delete(const struct ast_sorcery *sorcery, void *data, void *object);
static void sorcery_realtime_close(void *data);
@@ -71,6 +73,7 @@ static struct ast_sorcery_wizard realtime_object_wizard = {
.retrieve_fields = sorcery_realtime_retrieve_fields,
.retrieve_multiple = sorcery_realtime_retrieve_multiple,
.retrieve_regex = sorcery_realtime_retrieve_regex,
+ .retrieve_prefix = sorcery_realtime_retrieve_prefix,
.update = sorcery_realtime_update,
.delete = sorcery_realtime_delete,
.close = sorcery_realtime_close,
@@ -262,6 +265,23 @@ static void sorcery_realtime_retrieve_regex(const struct ast_sorcery *sorcery, v
sorcery_realtime_retrieve_multiple(sorcery, data, type, objects, fields);
}
+static void sorcery_realtime_retrieve_prefix(const struct ast_sorcery *sorcery, void *data, const char *type,
+ struct ao2_container *objects, const char *prefix, const size_t prefix_len)
+{
+ char field[strlen(UUID_FIELD) + 6], value[prefix_len + 2];
+ RAII_VAR(struct ast_variable *, fields, NULL, ast_variables_destroy);
+
+ if (prefix_len) {
+ snprintf(field, sizeof(field), "%s LIKE", UUID_FIELD);
+ snprintf(value, sizeof(value), "%.*s%%", (int) prefix_len, prefix);
+ if (!(fields = ast_variable_new(field, value, ""))) {
+ return;
+ }
+ }
+
+ sorcery_realtime_retrieve_multiple(sorcery, data, type, objects, fields);
+}
+
static int sorcery_realtime_update(const struct ast_sorcery *sorcery, void *data, void *object)
{
struct sorcery_config *config = data;
diff --git a/res/snmp/agent.c b/res/snmp/agent.c
index 9d1528dde..7cd895559 100644
--- a/res/snmp/agent.c
+++ b/res/snmp/agent.c
@@ -63,6 +63,10 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
+#if !defined(RONLY) && defined(NETSNMP_OLDAPI_RONLY)
+#define RONLY NETSNMP_OLDAPI_RONLY
+#endif
+
#include "asterisk/paths.h" /* need ast_config_AST_SOCKET */
#include "asterisk/channel.h"
#include "asterisk/logger.h"
diff --git a/tests/test_logger.c b/tests/test_logger.c
index bf809ba54..08585a6b8 100644
--- a/tests/test_logger.c
+++ b/tests/test_logger.c
@@ -192,7 +192,7 @@ static char *handle_cli_performance_test(struct ast_cli_entry *e, int cmd, struc
static char *handle_cli_queue_test(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
{
- unsigned int level;
+ int level;
int current_queue_limit;
unsigned int x;
struct timeval start, end;
@@ -222,7 +222,7 @@ static char *handle_cli_queue_test(struct ast_cli_entry *e, int cmd, struct ast_
ast_cli(a->fd, "Test: Failed, could not register level 'queuetest'.\n");
return CLI_SUCCESS;
}
- ast_cli(a->fd, "Test: got level %u for 'queuetest'.\n", level);
+ ast_cli(a->fd, "Test: got level %d for 'queuetest'.\n", level);
if (ast_logger_create_channel(tmppath, "queuetest") != AST_LOGGER_SUCCESS) {
ast_cli(a->fd, "Test: Unable to create logger channel '%s'\n", tmppath);
diff --git a/tests/test_pbx.c b/tests/test_pbx.c
index acf7484c1..df6b88dc8 100644
--- a/tests/test_pbx.c
+++ b/tests/test_pbx.c
@@ -39,6 +39,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/pbx.h"
#include "asterisk/test.h"
+#include <signal.h>
+
/*!
* If we determine that we really need
* to be able to register more than 10