summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES6
-rw-r--r--apps/app_confbridge.c274
-rw-r--r--apps/app_macro.c36
-rw-r--r--apps/app_queue.c11
-rw-r--r--apps/confbridge/conf_chan_announce.c30
-rw-r--r--apps/confbridge/include/confbridge.h12
-rw-r--r--include/asterisk/channel.h6
-rw-r--r--include/asterisk/chanvars.h2
-rw-r--r--include/asterisk/config.h2
-rw-r--r--include/asterisk/hashtab.h14
-rw-r--r--include/asterisk/heap.h4
-rw-r--r--include/asterisk/res_fax.h22
-rw-r--r--include/asterisk/strings.h6
-rw-r--r--main/bridge_basic.c2
-rw-r--r--main/channel.c2
-rw-r--r--main/chanvars.c4
-rw-r--r--main/config.c4
-rw-r--r--main/hashtab.c40
-rw-r--r--main/heap.c14
-rw-r--r--main/pbx.c25
-rw-r--r--main/strings.c4
-rw-r--r--res/res_fax.c109
-rw-r--r--res/res_pjsip/config_global.c26
-rw-r--r--res/res_pjsip_refer.c7
-rw-r--r--res/res_pjsip_t38.c14
-rw-r--r--res/res_rtp_multicast.c7
-rw-r--r--third-party/pjproject/patches/config_site.h8
27 files changed, 495 insertions, 196 deletions
diff --git a/CHANGES b/CHANGES
index 1dfd445c8..27643f28f 100644
--- a/CHANGES
+++ b/CHANGES
@@ -43,6 +43,12 @@ res_pjsip
when set will override the default user set on Contact headers in outgoing
requests.
+ * If you are using a sorcery realtime backend to store global res_pjsip
+ options (ps_globals table) then you now have to do a res_pjsip reload for
+ changes to these options to take effect. If you are using pjsip.conf to
+ configure these options then you already had to do a reload after making
+ changes.
+
------------------------------------------------------------------------------
--- Functionality changes from Asterisk 13.10.0 to Asterisk 13.11.0 ----------
------------------------------------------------------------------------------
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 991b3a307..ec4136580 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -71,6 +71,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/stasis_bridges.h"
#include "asterisk/json.h"
#include "asterisk/format_cache.h"
+#include "asterisk/taskprocessor.h"
/*** DOCUMENTATION
<application name="ConfBridge" language="en_US">
@@ -959,6 +960,59 @@ static void handle_video_on_exit(struct confbridge_conference *conference, struc
ao2_unlock(conference);
}
+struct hangup_data
+{
+ struct confbridge_conference *conference;
+ ast_mutex_t lock;
+ ast_cond_t cond;
+ int hungup;
+};
+
+/*!
+ * \brief Hang up the announcer channel
+ *
+ * This hangs up the announcer channel in the conference. This
+ * runs in the playback queue taskprocessor since we do not want
+ * to hang up the channel while it's trying to play an announcement.
+ *
+ * This task is performed synchronously, so there is no need to
+ * perform any cleanup on the passed-in data.
+ *
+ * \param data A hangup_data structure
+ * \return 0
+ */
+static int hangup_playback(void *data)
+{
+ struct hangup_data *hangup = data;
+
+ ast_autoservice_stop(hangup->conference->playback_chan);
+
+ ast_hangup(hangup->conference->playback_chan);
+ hangup->conference->playback_chan = NULL;
+
+ ast_mutex_lock(&hangup->lock);
+ hangup->hungup = 1;
+ ast_cond_signal(&hangup->cond);
+ ast_mutex_unlock(&hangup->lock);
+
+ return 0;
+}
+
+static void hangup_data_init(struct hangup_data *hangup, struct confbridge_conference *conference)
+{
+ ast_mutex_init(&hangup->lock);
+ ast_cond_init(&hangup->cond, NULL);
+
+ hangup->conference = conference;
+ hangup->hungup = 0;
+}
+
+static void hangup_data_destroy(struct hangup_data *hangup)
+{
+ ast_mutex_destroy(&hangup->lock);
+ ast_cond_destroy(&hangup->cond);
+}
+
/*!
* \brief Destroy a conference bridge
*
@@ -973,9 +1027,22 @@ static void destroy_conference_bridge(void *obj)
ast_debug(1, "Destroying conference bridge '%s'\n", conference->name);
if (conference->playback_chan) {
- conf_announce_channel_depart(conference->playback_chan);
- ast_hangup(conference->playback_chan);
- conference->playback_chan = NULL;
+ if (conference->playback_queue) {
+ struct hangup_data hangup;
+ hangup_data_init(&hangup, conference);
+ ast_taskprocessor_push(conference->playback_queue, hangup_playback, &hangup);
+
+ ast_mutex_lock(&hangup.lock);
+ while (!hangup.hungup) {
+ ast_cond_wait(&hangup.cond, &hangup.lock);
+ }
+ ast_mutex_unlock(&hangup.lock);
+ hangup_data_destroy(&hangup);
+ } else {
+ /* Playback queue is not yet allocated. Just hang up the channel straight */
+ ast_hangup(conference->playback_chan);
+ conference->playback_chan = NULL;
+ }
}
/* Destroying a conference bridge is simple, all we have to do is destroy the bridging object */
@@ -989,7 +1056,7 @@ static void destroy_conference_bridge(void *obj)
ast_free(conference->record_filename);
conf_bridge_profile_destroy(&conference->b_profile);
- ast_mutex_destroy(&conference->playback_lock);
+ ast_taskprocessor_unreference(conference->playback_queue);
}
/*! \brief Call the proper join event handler for the user for the conference bridge's current state
@@ -1270,6 +1337,72 @@ void conf_ended(struct confbridge_conference *conference)
}
/*!
+ * \internal
+ * \brief Allocate playback channel for a conference.
+ * \pre expects conference to be locked before calling this function
+ */
+static int alloc_playback_chan(struct confbridge_conference *conference)
+{
+ struct ast_format_cap *cap;
+ char taskprocessor_name[AST_TASKPROCESSOR_MAX_NAME + 1];
+
+ cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
+ if (!cap) {
+ return -1;
+ }
+ ast_format_cap_append(cap, ast_format_slin, 0);
+ conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
+ conference->name, NULL);
+ ao2_ref(cap, -1);
+ if (!conference->playback_chan) {
+ return -1;
+ }
+
+ /* To make sure playback_chan has the same language as the bridge */
+ ast_channel_lock(conference->playback_chan);
+ ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
+ ast_channel_unlock(conference->playback_chan);
+
+ ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
+ ast_channel_name(conference->playback_chan), conference->name);
+
+ ast_taskprocessor_build_name(taskprocessor_name, sizeof(taskprocessor_name),
+ "Confbridge/%s", conference->name);
+ conference->playback_queue = ast_taskprocessor_get(taskprocessor_name, TPS_REF_DEFAULT);
+ if (!conference->playback_queue) {
+ ast_hangup(conference->playback_chan);
+ conference->playback_chan = NULL;
+ return -1;
+ }
+ return 0;
+}
+
+/*!
+ * \brief Push the announcer channel into the bridge
+ *
+ * This runs in the playback queue taskprocessor.
+ *
+ * \param data A confbridge_conference
+ * \retval 0 Success
+ * \retval -1 Failed to push the channel to the bridge
+ */
+static int push_announcer(void *data)
+{
+ struct confbridge_conference *conference = data;
+
+ if (conf_announce_channel_push(conference->playback_chan)) {
+ ast_hangup(conference->playback_chan);
+ conference->playback_chan = NULL;
+ ao2_cleanup(conference);
+ return -1;
+ }
+
+ ast_autoservice_start(conference->playback_chan);
+ ao2_cleanup(conference);
+ return 0;
+}
+
+/*!
* \brief Join a conference bridge
*
* \param conference_name The conference name
@@ -1314,9 +1447,6 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
return NULL;
}
- /* Setup lock for playback channel */
- ast_mutex_init(&conference->playback_lock);
-
/* Setup for the record channel */
conference->record_filename = ast_str_create(RECORD_FILENAME_INITIAL_SPACE);
if (!conference->record_filename) {
@@ -1361,6 +1491,22 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen
/* Set the initial state to EMPTY */
conference->state = CONF_STATE_EMPTY;
+ if (alloc_playback_chan(conference)) {
+ ao2_unlink(conference_bridges, conference);
+ ao2_ref(conference, -1);
+ ao2_unlock(conference_bridges);
+ ast_log(LOG_ERROR, "Could not allocate announcer channel for conference '%s'\n", conference_name);
+ return NULL;
+ }
+
+ if (ast_taskprocessor_push(conference->playback_queue, push_announcer, ao2_bump(conference))) {
+ ao2_unlink(conference_bridges, conference);
+ ao2_ref(conference, -1);
+ ao2_unlock(conference_bridges);
+ ast_log(LOG_ERROR, "Could not add announcer channel for conference '%s' bridge\n", conference_name);
+ return NULL;
+ }
+
if (ast_test_flag(&conference->b_profile, BRIDGE_OPT_RECORD_CONFERENCE)) {
ao2_lock(conference);
conf_start_record(conference);
@@ -1481,67 +1627,105 @@ static void leave_conference(struct confbridge_user *user)
user->conference = NULL;
}
+struct playback_task_data {
+ struct confbridge_conference *conference;
+ const char *filename;
+ int say_number;
+ int playback_finished;
+ ast_mutex_t lock;
+ ast_cond_t cond;
+};
+
/*!
- * \internal
- * \brief Allocate playback channel for a conference.
- * \pre expects conference to be locked before calling this function
+ * \brief Play an announcement into a confbridge
+ *
+ * This runs in the playback queue taskprocessor. This ensures that
+ * all playbacks are handled in sequence and do not play over top one
+ * another.
+ *
+ * This task runs synchronously so there is no need for performing any
+ * sort of cleanup on the input parameter.
+ *
+ * \param data A playback_task_data
+ * \return 0
*/
-static int alloc_playback_chan(struct confbridge_conference *conference)
+static int playback_task(void *data)
{
- struct ast_format_cap *cap;
+ struct playback_task_data *ptd = data;
- cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
- if (!cap) {
- return -1;
+ /* Don't try to play if the playback channel has been hung up */
+ if (!ptd->conference->playback_chan) {
+ goto end;
}
- ast_format_cap_append(cap, ast_format_slin, 0);
- conference->playback_chan = ast_request("CBAnn", cap, NULL, NULL,
- conference->name, NULL);
- ao2_ref(cap, -1);
- if (!conference->playback_chan) {
- return -1;
+
+ ast_autoservice_stop(ptd->conference->playback_chan);
+
+ /* The channel is all under our control, in goes the prompt */
+ if (!ast_strlen_zero(ptd->filename)) {
+ ast_stream_and_wait(ptd->conference->playback_chan, ptd->filename, "");
+ } else if (ptd->say_number >= 0) {
+ ast_say_number(ptd->conference->playback_chan, ptd->say_number, "",
+ ast_channel_language(ptd->conference->playback_chan), NULL);
}
+ ast_autoservice_start(ptd->conference->playback_chan);
- /* To make sure playback_chan has the same language of that profile */
- ast_channel_lock(conference->playback_chan);
- ast_channel_language_set(conference->playback_chan, conference->b_profile.language);
- ast_channel_unlock(conference->playback_chan);
+end:
+ ast_mutex_lock(&ptd->lock);
+ ptd->playback_finished = 1;
+ ast_cond_signal(&ptd->cond);
+ ast_mutex_unlock(&ptd->lock);
- ast_debug(1, "Created announcer channel '%s' to conference bridge '%s'\n",
- ast_channel_name(conference->playback_chan), conference->name);
return 0;
}
+static void playback_task_data_init(struct playback_task_data *ptd, struct confbridge_conference *conference,
+ const char *filename, int say_number)
+{
+ ast_mutex_init(&ptd->lock);
+ ast_cond_init(&ptd->cond, NULL);
+
+ ptd->filename = filename;
+ ptd->say_number = say_number;
+ ptd->conference = conference;
+ ptd->playback_finished = 0;
+}
+
+static void playback_task_data_destroy(struct playback_task_data *ptd)
+{
+ ast_mutex_destroy(&ptd->lock);
+ ast_cond_destroy(&ptd->cond);
+}
+
static int play_sound_helper(struct confbridge_conference *conference, const char *filename, int say_number)
{
+ struct playback_task_data ptd;
+
/* Do not waste resources trying to play files that do not exist */
if (!ast_strlen_zero(filename) && !sound_file_exists(filename)) {
return 0;
}
- ast_mutex_lock(&conference->playback_lock);
- if (!conference->playback_chan && alloc_playback_chan(conference)) {
- ast_mutex_unlock(&conference->playback_lock);
- return -1;
- }
- if (conf_announce_channel_push(conference->playback_chan)) {
- ast_mutex_unlock(&conference->playback_lock);
+ playback_task_data_init(&ptd, conference, filename, say_number);
+ if (ast_taskprocessor_push(conference->playback_queue, playback_task, &ptd)) {
+ if (!ast_strlen_zero(filename)) {
+ ast_log(LOG_WARNING, "Unable to play file '%s' to conference %s\n",
+ filename, conference->name);
+ } else {
+ ast_log(LOG_WARNING, "Unable to say number '%d' to conference %s\n",
+ say_number, conference->name);
+ }
+ playback_task_data_destroy(&ptd);
return -1;
}
- /* The channel is all under our control, in goes the prompt */
- if (!ast_strlen_zero(filename)) {
- ast_stream_and_wait(conference->playback_chan, filename, "");
- } else if (say_number >= 0) {
- ast_say_number(conference->playback_chan, say_number, "",
- ast_channel_language(conference->playback_chan), NULL);
+ /* Wait for the playback to complete */
+ ast_mutex_lock(&ptd.lock);
+ while (!ptd.playback_finished) {
+ ast_cond_wait(&ptd.cond, &ptd.lock);
}
+ ast_mutex_unlock(&ptd.lock);
- ast_debug(1, "Departing announcer channel '%s' from conference bridge '%s'\n",
- ast_channel_name(conference->playback_chan), conference->name);
- conf_announce_channel_depart(conference->playback_chan);
-
- ast_mutex_unlock(&conference->playback_lock);
+ playback_task_data_destroy(&ptd);
return 0;
}
diff --git a/apps/app_macro.c b/apps/app_macro.c
index d8fd47fb1..ab80fbc38 100644
--- a/apps/app_macro.c
+++ b/apps/app_macro.c
@@ -243,7 +243,7 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
int setmacrocontext=0;
int autoloopflag, inhangup = 0;
struct ast_str *tmp_subst = NULL;
-
+ const char *my_macro_exten = NULL;
char *save_macro_exten;
char *save_macro_context;
char *save_macro_priority;
@@ -304,12 +304,32 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
}
snprintf(fullmacro, sizeof(fullmacro), "macro-%s", macro);
- if (!ast_exists_extension(chan, fullmacro, "s", 1,
- S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
- if (!ast_context_find(fullmacro))
- ast_log(LOG_WARNING, "No such context '%s' for macro '%s'. Was called by %s@%s\n", fullmacro, macro, ast_channel_exten(chan), ast_channel_context(chan));
- else
- ast_log(LOG_WARNING, "Context '%s' for macro '%s' lacks 's' extension, priority 1\n", fullmacro, macro);
+
+ /* first search for the macro */
+ if (!ast_context_find(fullmacro)) {
+ ast_log(LOG_WARNING, "No such context '%s' for macro '%s'. Was called by %s@%s\n",
+ fullmacro, macro, ast_channel_exten(chan), ast_channel_context(chan));
+ return 0;
+ }
+
+ /* now search for the right extension */
+ if (ast_exists_extension(chan, fullmacro, "s", 1,
+ S_COR(ast_channel_caller(chan)->id.number.valid,
+ ast_channel_caller(chan)->id.number.str, NULL))) {
+ /* We have a normal macro */
+ my_macro_exten = "s";
+ } else if (ast_exists_extension(chan, fullmacro, "~~s~~", 1,
+ S_COR(ast_channel_caller(chan)->id.number.valid,
+ ast_channel_caller(chan)->id.number.str, NULL))) {
+ /* We have an AEL generated macro */
+ my_macro_exten = "~~s~~";
+ }
+
+ /* do we have a valid exten? */
+ if (!my_macro_exten) {
+ ast_log(LOG_WARNING,
+ "Context '%s' for macro '%s' lacks 's' extension, priority 1\n",
+ fullmacro, macro);
return 0;
}
@@ -361,7 +381,7 @@ static int _macro_exec(struct ast_channel *chan, const char *data, int exclusive
ast_set_flag(ast_channel_flags(chan), AST_FLAG_SUBROUTINE_EXEC);
/* Setup environment for new run */
- ast_channel_exten_set(chan, "s");
+ ast_channel_exten_set(chan, my_macro_exten);
ast_channel_context_set(chan, fullmacro);
ast_channel_priority_set(chan, 1);
diff --git a/apps/app_queue.c b/apps/app_queue.c
index e04942f68..9b283d467 100644
--- a/apps/app_queue.c
+++ b/apps/app_queue.c
@@ -4077,6 +4077,17 @@ static void hangupcalls(struct queue_ent *qe, struct callattempt *outgoing, stru
ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
}
ast_channel_publish_dial(qe->chan, outgoing->chan, outgoing->interface, "CANCEL");
+
+ /* When dialing channels it is possible that they may not ever
+ * leave the not in use state (Local channels in particular) by
+ * the time we cancel them. If this occurs but we know they were
+ * dialed we explicitly remove them from the pending members
+ * container so that subsequent call attempts occur.
+ */
+ if (outgoing->member->status == AST_DEVICE_NOT_INUSE) {
+ pending_members_remove(outgoing->member);
+ }
+
ast_hangup(outgoing->chan);
}
oo = outgoing;
diff --git a/apps/confbridge/conf_chan_announce.c b/apps/confbridge/conf_chan_announce.c
index ee4660687..22ac4be39 100644
--- a/apps/confbridge/conf_chan_announce.c
+++ b/apps/confbridge/conf_chan_announce.c
@@ -143,31 +143,6 @@ struct ast_channel_tech *conf_announce_get_tech(void)
return &announce_tech;
}
-void conf_announce_channel_depart(struct ast_channel *chan)
-{
- struct announce_pvt *p = ast_channel_tech_pvt(chan);
-
- if (!p) {
- return;
- }
-
- ao2_ref(p, +1);
- ao2_lock(p);
- if (!ast_test_flag(&p->base, AST_UNREAL_CARETAKER_THREAD)) {
- ao2_unlock(p);
- ao2_ref(p, -1);
- return;
- }
- ast_clear_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
- chan = p->base.chan;
- ao2_unlock(p);
- ao2_ref(p, -1);
- if (chan) {
- ast_bridge_depart(chan);
- ast_channel_unref(chan);
- }
-}
-
int conf_announce_channel_push(struct ast_channel *ast)
{
struct ast_bridge_features *features;
@@ -186,20 +161,17 @@ int conf_announce_channel_push(struct ast_channel *ast)
if (!chan) {
return -1;
}
- ast_channel_ref(chan);
}
features = ast_bridge_features_new();
if (!features) {
- ast_channel_unref(chan);
return -1;
}
ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
/* Impart the output channel into the bridge */
if (ast_bridge_impart(p->bridge, chan, NULL, features,
- AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) {
- ast_channel_unref(chan);
+ AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
return -1;
}
ao2_lock(p);
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index a1fa5a2b7..451d81098 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -225,9 +225,9 @@ struct confbridge_conference {
struct ast_channel *record_chan; /*!< Channel used for recording the conference */
struct ast_str *record_filename; /*!< Recording filename. */
struct ast_str *orig_rec_file; /*!< Previous b_profile.rec_file. */
- ast_mutex_t playback_lock; /*!< Lock used for playback channel */
AST_LIST_HEAD_NOLOCK(, confbridge_user) active_list; /*!< List of users participating in the conference bridge */
AST_LIST_HEAD_NOLOCK(, confbridge_user) waiting_list; /*!< List of users waiting to join the conference bridge */
+ struct ast_taskprocessor *playback_queue; /*!< Queue for playing back bridge announcements and managing the announcer channel */
};
extern struct ao2_container *conference_bridges;
@@ -607,16 +607,6 @@ struct ast_channel_tech *conf_record_get_tech(void);
struct ast_channel_tech *conf_announce_get_tech(void);
/*!
- * \brief Remove the announcer channel from the conference.
- * \since 12.0.0
- *
- * \param chan Either channel in the announcer channel pair.
- *
- * \return Nothing
- */
-void conf_announce_channel_depart(struct ast_channel *chan);
-
-/*!
* \brief Push the announcer channel into the conference.
* \since 12.0.0
*
diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h
index 4cc210d5a..e42307dd9 100644
--- a/include/asterisk/channel.h
+++ b/include/asterisk/channel.h
@@ -2569,7 +2569,11 @@ static inline int ast_fdisset(struct pollfd *pfds, int fd, int maximum, int *sta
return 0;
}
-/*! \brief Retrieves the current T38 state of a channel */
+/*!
+ * \brief Retrieves the current T38 state of a channel
+ *
+ * \note Absolutely _NO_ channel locks should be held before calling this function.
+ */
static inline enum ast_t38_state ast_channel_get_t38_state(struct ast_channel *chan)
{
enum ast_t38_state state = T38_STATE_UNAVAILABLE;
diff --git a/include/asterisk/chanvars.h b/include/asterisk/chanvars.h
index 3693e2a3a..2040c7b65 100644
--- a/include/asterisk/chanvars.h
+++ b/include/asterisk/chanvars.h
@@ -35,7 +35,7 @@ AST_LIST_HEAD_NOLOCK(varshead, ast_var_t);
struct varshead *ast_var_list_create(void);
void ast_var_list_destroy(struct varshead *head);
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_var_t *_ast_var_assign(const char *name, const char *value, const char *file, int lineno, const char *function);
#define ast_var_assign(a,b) _ast_var_assign(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#else
diff --git a/include/asterisk/config.h b/include/asterisk/config.h
index 4c68e5c21..0b59f63b6 100644
--- a/include/asterisk/config.h
+++ b/include/asterisk/config.h
@@ -907,7 +907,7 @@ void ast_category_destroy(struct ast_category *cat);
struct ast_variable *ast_category_detach_variables(struct ast_category *cat);
void ast_category_rename(struct ast_category *cat, const char *name);
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_variable *_ast_variable_new(const char *name, const char *value, const char *filename, const char *file, const char *function, int lineno);
#define ast_variable_new(a, b, c) _ast_variable_new(a, b, c, __FILE__, __PRETTY_FUNCTION__, __LINE__)
#else
diff --git a/include/asterisk/hashtab.h b/include/asterisk/hashtab.h
index 17eff7048..cfe035b28 100644
--- a/include/asterisk/hashtab.h
+++ b/include/asterisk/hashtab.h
@@ -251,7 +251,7 @@ unsigned int ast_hashtab_hash_short(const short num);
* \param hash a func ptr to do the hashing
* \param do_locking use locks to guarantee safety of iterators/insertion/deletion -- real simpleminded right now
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab * _ast_hashtab_create(int initial_buckets,
int (*compare)(const void *a, const void *b),
int (*resize)(struct ast_hashtab *),
@@ -294,7 +294,7 @@ void ast_hashtab_destroy( struct ast_hashtab *tab, void (*objdestroyfunc)(void *
* \retval 1 on success
* \retval 0 if there's a problem
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func);
#define ast_hashtab_insert_immediate(a,b) _ast_hashtab_insert_immediate(a, b, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
@@ -311,7 +311,7 @@ int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj);
* \retval 1 on success
* \retval 0 if there's a problem
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h, const char *file, int lineno, const char *func);
#define ast_hashtab_insert_immediate_bucket(a,b,c) _ast_hashtab_insert_immediate_bucket(a, b, c, __FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
@@ -324,7 +324,7 @@ int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj
* \retval 1 on success
* \retval 0 if there's a problem, or it's already there.
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func);
#define ast_hashtab_insert_safe(a,b) _ast_hashtab_insert_safe(a,b,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
@@ -362,7 +362,7 @@ int ast_hashtab_size( struct ast_hashtab *tab);
int ast_hashtab_capacity( struct ast_hashtab *tab);
/*! \brief Return a copy of the hash table */
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab *_ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_func)(const void *obj), const char *file, int lineno, const char *func);
#define ast_hashtab_dup(a,b) _ast_hashtab_dup(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#else
@@ -370,7 +370,7 @@ struct ast_hashtab *ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_fun
#endif
/*! \brief Gives an iterator to hastable */
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab_iter *_ast_hashtab_start_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func);
#define ast_hashtab_start_traversal(a) _ast_hashtab_start_traversal(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#else
@@ -395,7 +395,7 @@ void *ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj);
/* ------------------ */
/*! \brief Gives an iterator to hastable */
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab_iter *_ast_hashtab_start_write_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func);
#define ast_hashtab_start_write_traversal(a) _ast_hashtab_start_write_traversal(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#else
diff --git a/include/asterisk/heap.h b/include/asterisk/heap.h
index a868ac589..728327936 100644
--- a/include/asterisk/heap.h
+++ b/include/asterisk/heap.h
@@ -97,7 +97,7 @@ typedef int (*ast_heap_cmp_fn)(void *elm1, void *elm2);
* \return An instance of a max heap
* \since 1.6.1
*/
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_heap *_ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_fn,
ssize_t index_offset, const char *file, int lineno, const char *func);
#define ast_heap_create(a,b,c) _ast_heap_create(a,b,c,__FILE__,__LINE__,__PRETTY_FUNCTION__)
@@ -126,7 +126,7 @@ struct ast_heap *ast_heap_destroy(struct ast_heap *h);
* \retval non-zero failure
* \since 1.6.1
*/
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
int _ast_heap_push(struct ast_heap *h, void *elm, const char *file, int lineno, const char *func);
#define ast_heap_push(a,b) _ast_heap_push(a,b,__FILE__,__LINE__,__PRETTY_FUNCTION__)
#else
diff --git a/include/asterisk/res_fax.h b/include/asterisk/res_fax.h
index 5119bfa6c..e88d8002f 100644
--- a/include/asterisk/res_fax.h
+++ b/include/asterisk/res_fax.h
@@ -20,16 +20,16 @@
#ifndef _ASTERISK_RES_FAX_H
#define _ASTERISK_RES_FAX_H
-#include <asterisk.h>
-#include <asterisk/lock.h>
-#include <asterisk/linkedlists.h>
-#include <asterisk/module.h>
-#include <asterisk/utils.h>
-#include <asterisk/options.h>
-#include <asterisk/frame.h>
-#include <asterisk/cli.h>
-#include <asterisk/stringfields.h>
-#include <asterisk/manager.h>
+#include "asterisk.h"
+#include "asterisk/lock.h"
+#include "asterisk/linkedlists.h"
+#include "asterisk/module.h"
+#include "asterisk/utils.h"
+#include "asterisk/options.h"
+#include "asterisk/frame.h"
+#include "asterisk/cli.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/manager.h"
/*! \brief capabilities for res_fax to locate a fax technology module */
enum ast_fax_capabilities {
@@ -187,6 +187,8 @@ struct ast_fax_session_details {
int faxdetect_timeout;
/*! flags used for fax detection */
int faxdetect_flags;
+ /*! Non-zero if T.38 is negotiated */
+ int is_t38_negotiated;
};
struct ast_fax_tech;
diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h
index 2ca75a69c..eb5b4e43c 100644
--- a/include/asterisk/strings.h
+++ b/include/asterisk/strings.h
@@ -616,7 +616,7 @@ int ast_regex_string_to_regex_pattern(const char *regex_string, struct ast_str *
* \note The result of this function is dynamically allocated memory, and must
* be free()'d after it is no longer needed.
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
#define ast_str_create(a) _ast_str_create(a,__FILE__,__LINE__,__PRETTY_FUNCTION__)
AST_INLINE_API(
struct ast_str * attribute_malloc _ast_str_create(size_t init_len,
@@ -771,7 +771,7 @@ char *ast_str_truncate(struct ast_str *buf, ssize_t len),
/*!
* Make space in a new string (e.g. to read in data from a file)
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
AST_INLINE_API(
int _ast_str_make_space(struct ast_str **buf, size_t new_len, const char *file, int lineno, const char *function),
{
@@ -964,7 +964,7 @@ enum {
* through calling one of the other functions or macros defined in this
* file.
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int __attribute__((format(printf, 4, 0))) __ast_debug_str_helper(struct ast_str **buf, ssize_t max_len,
int append, const char *fmt, va_list ap, const char *file, int lineno, const char *func);
#define __ast_str_helper(a,b,c,d,e) __ast_debug_str_helper(a,b,c,d,e,__FILE__,__LINE__,__PRETTY_FUNCTION__)
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index c4cf2a074..b24df0506 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -3090,7 +3090,9 @@ static int attach_framehook(struct attended_transfer_properties *props, struct a
ao2_ref(props, +1);
target_interface.data = props;
+ ast_channel_lock(channel);
props->target_framehook_id = ast_framehook_attach(channel, &target_interface);
+ ast_channel_unlock(channel);
if (props->target_framehook_id == -1) {
ao2_ref(props, -1);
return -1;
diff --git a/main/channel.c b/main/channel.c
index 853935da3..f3f79399f 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -6094,7 +6094,7 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
if (set_security_requirements(requestor, c)) {
ast_log(LOG_WARNING, "Setting security requirements failed\n");
- c = ast_channel_release(c);
+ ast_hangup(c);
*cause = AST_CAUSE_BEARERCAPABILITY_NOTAVAIL;
return NULL;
}
diff --git a/main/chanvars.c b/main/chanvars.c
index 37714e9a2..dbb379bbd 100644
--- a/main/chanvars.c
+++ b/main/chanvars.c
@@ -35,7 +35,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/strings.h"
#include "asterisk/utils.h"
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_var_t *_ast_var_assign(const char *name, const char *value, const char *file, int lineno, const char *function)
#else
struct ast_var_t *ast_var_assign(const char *name, const char *value)
@@ -45,7 +45,7 @@ struct ast_var_t *ast_var_assign(const char *name, const char *value)
int name_len = strlen(name) + 1;
int value_len = strlen(value) + 1;
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
if (!(var = __ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char), file, lineno, function))) {
#else
if (!(var = ast_calloc(sizeof(*var) + name_len + value_len, sizeof(char)))) {
diff --git a/main/config.c b/main/config.c
index ffada0bf3..b81a9f6a2 100644
--- a/main/config.c
+++ b/main/config.c
@@ -283,7 +283,7 @@ struct ast_config_include {
static void ast_variable_destroy(struct ast_variable *doomed);
static void ast_includes_destroy(struct ast_config_include *incls);
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_variable *_ast_variable_new(const char *name, const char *value, const char *filename, const char *file, const char *func, int lineno)
#else
struct ast_variable *ast_variable_new(const char *name, const char *value, const char *filename)
@@ -300,7 +300,7 @@ struct ast_variable *ast_variable_new(const char *name, const char *value, const
}
if (
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
(variable = __ast_calloc(1, fn_len + name_len + val_len + sizeof(*variable), file, lineno, func))
#else
(variable = ast_calloc(1, fn_len + name_len + val_len + sizeof(*variable)))
diff --git a/main/hashtab.c b/main/hashtab.c
index 9b334d4a5..d06d1e129 100644
--- a/main/hashtab.c
+++ b/main/hashtab.c
@@ -43,7 +43,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/hashtab.h"
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
static void _ast_hashtab_resize(struct ast_hashtab *tab, const char *file, int lineno, const char *func);
#define ast_hashtab_resize(a) _ast_hashtab_resize(a,__FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
@@ -218,7 +218,7 @@ unsigned int ast_hashtab_hash_short(const short x)
}
struct ast_hashtab *
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
_ast_hashtab_create
#else
ast_hashtab_create
@@ -229,14 +229,14 @@ ast_hashtab_create
int (*newsize)(struct ast_hashtab *tab),
unsigned int (*hash)(const void *obj),
int do_locking
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
, const char *file, int lineno, const char *function
#endif
)
{
struct ast_hashtab *ht;
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
if (!(ht = __ast_calloc(1, sizeof(*ht), file, lineno, function)))
#else
if (!(ht = ast_calloc(1, sizeof(*ht))))
@@ -246,7 +246,7 @@ ast_hashtab_create
while (!ast_is_prime(initial_buckets)) /* make sure this is prime */
initial_buckets++;
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
if (!(ht->array = __ast_calloc(initial_buckets, sizeof(*(ht->array)), file, lineno, function))) {
#else
if (!(ht->array = ast_calloc(initial_buckets, sizeof(*(ht->array))))) {
@@ -274,7 +274,7 @@ ast_hashtab_create
return ht;
}
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab *_ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_func)(const void *obj), const char *file, int lineno, const char *func)
#else
struct ast_hashtab *ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_func)(const void *obj))
@@ -287,7 +287,7 @@ struct ast_hashtab *ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_fun
return NULL;
if (!(ht->array =
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(tab->hash_tab_size, sizeof(*(ht->array)), file, lineno, func)
#else
ast_calloc(tab->hash_tab_size, sizeof(*(ht->array)))
@@ -315,7 +315,7 @@ struct ast_hashtab *ast_hashtab_dup(struct ast_hashtab *tab, void *(*obj_dup_fun
while (b) {
void *newobj = (*obj_dup_func)(b->object);
if (newobj)
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
_ast_hashtab_insert_immediate_bucket(ht, newobj, i, file, lineno, func);
#else
ast_hashtab_insert_immediate_bucket(ht, newobj, i);
@@ -426,7 +426,7 @@ void ast_hashtab_destroy(struct ast_hashtab *tab, void (*objdestroyfunc)(void *o
}
}
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func)
#else
int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj)
@@ -443,7 +443,7 @@ int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj)
h = (*tab->hash)(obj) % tab->hash_tab_size;
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
res = _ast_hashtab_insert_immediate_bucket(tab, obj, h, file, lineno, func);
#else
res = ast_hashtab_insert_immediate_bucket(tab, obj, h);
@@ -455,7 +455,7 @@ int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj)
return res;
}
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h, const char *file, int lineno, const char *func)
#else
int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj, unsigned int h)
@@ -474,7 +474,7 @@ int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj
tab->largest_bucket_size = c + 1;
if (!(b =
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(1, sizeof(*b), file, lineno, func)
#else
ast_calloc(1, sizeof(*b))
@@ -497,7 +497,7 @@ int ast_hashtab_insert_immediate_bucket(struct ast_hashtab *tab, const void *obj
return 1;
}
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int _ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj, const char *file, int lineno, const char *func)
#else
int ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj)
@@ -513,7 +513,7 @@ int ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj)
ast_rwlock_wrlock(&tab->lock);
if (!ast_hashtab_lookup_bucket(tab, obj, &bucket)) {
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int ret2 = _ast_hashtab_insert_immediate_bucket(tab, obj, bucket, file, lineno, func);
#else
int ret2 = ast_hashtab_insert_immediate_bucket(tab, obj, bucket);
@@ -636,7 +636,7 @@ int ast_hashtab_capacity( struct ast_hashtab *tab)
/* the insert operation calls this, and is wrlock'd when it does. */
/* if you want to call it, you should set the wrlock yourself */
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
static void _ast_hashtab_resize(struct ast_hashtab *tab, const char *file, int lineno, const char *func)
#else
static void ast_hashtab_resize(struct ast_hashtab *tab)
@@ -659,7 +659,7 @@ static void ast_hashtab_resize(struct ast_hashtab *tab)
}
free(tab->array);
if (!(tab->array =
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(newsize, sizeof(*(tab->array)), file, lineno, func)
#else
ast_calloc(newsize, sizeof(*(tab->array)))
@@ -690,7 +690,7 @@ static void ast_hashtab_resize(struct ast_hashtab *tab)
}
}
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab_iter *_ast_hashtab_start_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func)
#else
struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab)
@@ -700,7 +700,7 @@ struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab)
struct ast_hashtab_iter *it;
if (!(it =
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(1, sizeof(*it), file, lineno, func)
#else
ast_calloc(1, sizeof(*it))
@@ -717,7 +717,7 @@ struct ast_hashtab_iter *ast_hashtab_start_traversal(struct ast_hashtab *tab)
}
/* use this function to get a write lock */
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
struct ast_hashtab_iter *_ast_hashtab_start_write_traversal(struct ast_hashtab *tab, const char *file, int lineno, const char *func)
#else
struct ast_hashtab_iter *ast_hashtab_start_write_traversal(struct ast_hashtab *tab)
@@ -727,7 +727,7 @@ struct ast_hashtab_iter *ast_hashtab_start_write_traversal(struct ast_hashtab *t
struct ast_hashtab_iter *it;
if (!(it =
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(1, sizeof(*it), file, lineno, func)
#else
ast_calloc(1, sizeof(*it))
diff --git a/main/heap.c b/main/heap.c
index c04f7a010..d40682af0 100644
--- a/main/heap.c
+++ b/main/heap.c
@@ -111,7 +111,7 @@ int ast_heap_verify(struct ast_heap *h)
return 0;
}
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
struct ast_heap *_ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_fn,
ssize_t index_offset, const char *file, int lineno, const char *func)
#else
@@ -131,7 +131,7 @@ struct ast_heap *ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_f
}
if (!(h =
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(1, sizeof(*h), file, lineno, func)
#else
ast_calloc(1, sizeof(*h))
@@ -145,7 +145,7 @@ struct ast_heap *ast_heap_create(unsigned int init_height, ast_heap_cmp_fn cmp_f
h->avail_len = (1 << init_height) - 1;
if (!(h->heap =
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
__ast_calloc(1, h->avail_len * sizeof(void *), file, lineno, func)
#else
ast_calloc(1, h->avail_len * sizeof(void *))
@@ -176,7 +176,7 @@ struct ast_heap *ast_heap_destroy(struct ast_heap *h)
* \brief Add a row of additional storage for the heap.
*/
static int grow_heap(struct ast_heap *h
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
, const char *file, int lineno, const char *func
#endif
)
@@ -184,7 +184,7 @@ static int grow_heap(struct ast_heap *h
void **new_heap;
size_t new_len = h->avail_len * 2 + 1;
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
new_heap = __ast_realloc(h->heap, new_len * sizeof(void *), file, lineno, func);
#else
new_heap = ast_realloc(h->heap, new_len * sizeof(void *));
@@ -244,14 +244,14 @@ static int bubble_up(struct ast_heap *h, int i)
return i;
}
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
int _ast_heap_push(struct ast_heap *h, void *elm, const char *file, int lineno, const char *func)
#else
int ast_heap_push(struct ast_heap *h, void *elm)
#endif
{
if (h->cur_len == h->avail_len && grow_heap(h
-#ifdef MALLOC_DEBUG
+#ifdef __AST_DEBUG_MALLOC
, file, lineno, func
#endif
)) {
diff --git a/main/pbx.c b/main/pbx.c
index 3b9594a19..5002999b4 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -5745,7 +5745,8 @@ static void manager_dpsendack(struct mansession *s, const struct message *m)
static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
const char *actionidtext, const char *context,
const char *exten, struct dialplan_counters *dpc,
- struct ast_include *rinclude)
+ struct ast_include *rinclude,
+ int includecount, const char *includes[])
{
struct ast_context *c;
int res = 0, old_total_exten = dpc->total_exten;
@@ -5827,7 +5828,24 @@ static int manager_show_dialplan_helper(struct mansession *s, const struct messa
while ( (i = ast_walk_context_includes(c, i)) ) {
if (exten) {
/* Check all includes for the requested extension */
- manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
+ if (includecount >= AST_PBX_MAX_STACK) {
+ ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
+ } else {
+ int dupe = 0;
+ int x;
+ for (x = 0; x < includecount; x++) {
+ if (!strcasecmp(includes[x], ast_get_include_name(i))) {
+ dupe++;
+ break;
+ }
+ }
+ if (!dupe) {
+ includes[includecount] = ast_get_include_name(i);
+ manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
+ } else {
+ ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
+ }
+ }
} else {
if (!dpc->total_items++)
manager_dpsendack(s, m);
@@ -5882,6 +5900,7 @@ static int manager_show_dialplan(struct mansession *s, const struct message *m)
{
const char *exten, *context;
const char *id = astman_get_header(m, "ActionID");
+ const char *incstack[AST_PBX_MAX_STACK];
char idtext[256];
/* Variables used for different counters */
@@ -5897,7 +5916,7 @@ static int manager_show_dialplan(struct mansession *s, const struct message *m)
exten = astman_get_header(m, "Extension");
context = astman_get_header(m, "Context");
- manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
+ manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL, 0, incstack);
if (!ast_strlen_zero(context) && !counters.context_existence) {
char errorbuf[BUFSIZ];
diff --git a/main/strings.c b/main/strings.c
index db78a6cd2..7cb55def0 100644
--- a/main/strings.c
+++ b/main/strings.c
@@ -53,7 +53,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
* ast_str_append_va(...)
*/
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
int __ast_debug_str_helper(struct ast_str **buf, ssize_t max_len,
int append, const char *fmt, va_list ap, const char *file, int lineno, const char *function)
#else
@@ -112,7 +112,7 @@ int __ast_str_helper(struct ast_str **buf, ssize_t max_len,
}
if (
-#if (defined(MALLOC_DEBUG) && !defined(STANDALONE))
+#ifdef __AST_DEBUG_MALLOC
_ast_str_make_space(buf, need, file, lineno, function)
#else
ast_str_make_space(buf, need)
diff --git a/res/res_fax.c b/res/res_fax.c
index 86260d10e..e37091b31 100644
--- a/res/res_fax.c
+++ b/res/res_fax.c
@@ -641,6 +641,7 @@ static void fixup_callback(void *data, struct ast_channel *old_chan, struct ast_
struct ast_fax_session_details *new_details = find_or_create_details(new_chan);
ast_framehook_detach(old_chan, old_details->gateway_id);
+ new_details->is_t38_negotiated = old_details->is_t38_negotiated;
fax_gateway_attach(new_chan, new_details);
ao2_cleanup(new_details);
}
@@ -1439,6 +1440,7 @@ static int report_fax_status(struct ast_channel *chan, struct ast_fax_session_de
static void set_channel_variables(struct ast_channel *chan, struct ast_fax_session_details *details)
{
char buf[10];
+
pbx_builtin_setvar_helper(chan, "FAXSTATUS", S_OR(details->result, NULL));
pbx_builtin_setvar_helper(chan, "FAXERROR", S_OR(details->error, NULL));
pbx_builtin_setvar_helper(chan, "FAXSTATUSSTRING", S_OR(details->resultstr, NULL));
@@ -1447,7 +1449,7 @@ static void set_channel_variables(struct ast_channel *chan, struct ast_fax_sessi
pbx_builtin_setvar_helper(chan, "FAXBITRATE", S_OR(details->transfer_rate, NULL));
pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", S_OR(details->resolution, NULL));
- if (ast_channel_get_t38_state(chan) == T38_STATE_NEGOTIATED) {
+ if (details->is_t38_negotiated) {
pbx_builtin_setvar_helper(chan, "FAXMODE", "T38");
} else {
pbx_builtin_setvar_helper(chan, "FAXMODE", "audio");
@@ -1656,6 +1658,7 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
ast_string_field_set(details, result, "");
ast_string_field_set(details, resultstr, "");
ast_string_field_set(details, error, "");
+ details->is_t38_negotiated = t38negotiated;
set_channel_variables(chan, details);
if (fax->tech->start_session(fax) < 0) {
@@ -1706,12 +1709,18 @@ static int generic_fax_exec(struct ast_channel *chan, struct ast_fax_session_det
* do T.38 as well
*/
t38_parameters_fax_to_ast(&t38_parameters, &details->our_t38_parameters);
- t38_parameters.request_response = (details->caps & AST_FAX_TECH_T38) ? AST_T38_NEGOTIATED : AST_T38_REFUSED;
+ if (details->caps & AST_FAX_TECH_T38) {
+ details->is_t38_negotiated = 1;
+ t38_parameters.request_response = AST_T38_NEGOTIATED;
+ } else {
+ t38_parameters.request_response = AST_T38_REFUSED;
+ }
ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, &t38_parameters, sizeof(t38_parameters));
break;
case AST_T38_NEGOTIATED:
t38_parameters_ast_to_fax(&details->their_t38_parameters, parameters);
t38negotiated = 1;
+ details->is_t38_negotiated = 1;
break;
default:
break;
@@ -2880,11 +2889,17 @@ static struct fax_gateway *fax_gateway_new(struct ast_channel *chan, struct ast_
return gateway;
}
-/*! \brief Create a fax session and start T.30<->T.38 gateway mode
+/*!
+ * \brief Create a fax session and start T.30<->T.38 gateway mode
+ *
* \param gateway a fax gateway object
* \param details fax session details
* \param chan active channel
- * \return 0 on error 1 on success*/
+ *
+ * \pre chan is locked on entry
+ *
+ * \return 0 on error 1 on success
+ */
static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session_details *details, struct ast_channel *chan)
{
struct ast_fax_session *s;
@@ -2896,6 +2911,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
ast_log(LOG_ERROR, "Can't create a FAX session, gateway attempt failed.\n");
@@ -2916,6 +2932,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error starting gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -2928,6 +2945,7 @@ static int fax_gateway_start(struct fax_gateway *gateway, struct ast_fax_session
return 0;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_frame *f)
{
struct ast_frame *fp;
@@ -2960,12 +2978,14 @@ static struct ast_frame *fax_gateway_request_t38(struct fax_gateway *gateway, st
gateway->t38_state = T38_STATE_NEGOTIATING;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ast_debug(1, "requesting T.38 for gateway session for %s\n", ast_channel_name(chan));
return fp;
}
+/*! \pre chan is locked on entry */
static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
{
struct ast_channel *other = (active == chan) ? peer : chan;
@@ -2981,8 +3001,14 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
}
if (gateway->detected_v21) {
+ enum ast_t38_state state_other;
+
destroy_v21_sessions(gateway);
- if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
+
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
+ if (state_other == T38_STATE_UNKNOWN) {
ast_debug(1, "detected v21 preamble from %s\n", ast_channel_name(active));
return fax_gateway_request_t38(gateway, chan, f);
} else {
@@ -2993,21 +3019,29 @@ static struct ast_frame *fax_gateway_detect_v21(struct fax_gateway *gateway, str
return f;
}
-static int fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
+/*! \pre chan is locked on entry */
+static void fax_gateway_indicate_t38(struct ast_channel *chan, struct ast_channel *active, struct ast_control_t38_parameters *control_params)
{
if (active == chan) {
- return ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_unlock(chan);
+ ast_indicate_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_channel_lock(chan);
} else {
- return ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
+ ast_queue_control_data(chan, AST_CONTROL_T38_PARAMETERS, control_params, sizeof(*control_params));
}
}
-/*! \brief T38 Gateway Negotiate t38 parameters
+/*!
+ * \brief T38 Gateway Negotiate t38 parameters
+ *
* \param gateway gateway object
* \param chan channel running the gateway
* \param peer channel im bridged too
* \param active channel the frame originated on
* \param f the control frame to process
+ *
+ * \pre chan is locked on entry
+ *
* \return processed control frame or null frame
*/
static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *active, struct ast_frame *f)
@@ -3015,6 +3049,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
struct ast_control_t38_parameters *control_params = f->data.ptr;
struct ast_channel *other = (active == chan) ? peer : chan;
struct ast_fax_session_details *details;
+ enum ast_t38_state state_other;
if (f->datalen != sizeof(struct ast_control_t38_parameters)) {
/* invalaid AST_CONTROL_T38_PARAMETERS frame, we can't
@@ -3037,9 +3072,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
}
if (control_params->request_response == AST_T38_REQUEST_NEGOTIATE) {
- enum ast_t38_state state = ast_channel_get_t38_state(other);
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
- if (state == T38_STATE_UNKNOWN) {
+ if (state_other == T38_STATE_UNKNOWN) {
/* we detected a request to negotiate T.38 and the
* other channel appears to support T.38, we'll pass
* the request through and only step in if the other
@@ -3048,10 +3085,11 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ao2_ref(details, -1);
return f;
- } else if (state == T38_STATE_UNAVAILABLE || state == T38_STATE_REJECTED) {
+ } else if (state_other == T38_STATE_UNAVAILABLE || state_other == T38_STATE_REJECTED) {
/* the other channel does not support T.38, we need to
* step in here */
ast_debug(1, "%s is attempting to negotiate T.38 but %s does not support it\n", ast_channel_name(active), ast_channel_name(other));
@@ -3063,12 +3101,14 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
if (fax_gateway_start(gateway, details, chan)) {
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
control_params->request_response = AST_T38_NEGOTIATED;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3086,6 +3126,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_ast_to_fax(&details->their_t38_parameters, control_params);
gateway->t38_state = T38_STATE_UNKNOWN;
gateway->timeout_start = ast_tvnow();
+ details->is_t38_negotiated = 0;
details->gateway_timeout = FAX_GATEWAY_TIMEOUT;
ast_debug(1, "%s is attempting to negotiate T.38 after we already sent a negotiation request based on v21 preamble detection\n", ast_channel_name(active));
@@ -3108,6 +3149,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
set_channel_variables(chan, details);
ast_debug(1, "%s is attempting to negotiate T.38 after we already negotiated T.38 with %s, disabling the gateway\n", ast_channel_name(active), ast_channel_name(other));
@@ -3122,11 +3164,15 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
&& control_params->request_response == AST_T38_REFUSED) {
ast_debug(1, "unable to negotiate T.38 on %s for fax gateway\n", ast_channel_name(active));
+ details->is_t38_negotiated = 0;
/* our request to negotiate T.38 was refused, if the other
* channel supports T.38, they might still reinvite and save
* the day. Otherwise disable the gateway. */
- if (ast_channel_get_t38_state(other) == T38_STATE_UNKNOWN) {
+ ast_channel_unlock(chan);
+ state_other = ast_channel_get_t38_state(other);
+ ast_channel_lock(chan);
+ if (state_other == T38_STATE_UNKNOWN) {
gateway->t38_state = T38_STATE_UNAVAILABLE;
} else {
ast_framehook_detach(chan, details->gateway_id);
@@ -3150,11 +3196,13 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
if (fax_gateway_start(gateway, details, chan)) {
ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
gateway->t38_state = T38_STATE_NEGOTIATING;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REQUEST_TERMINATE;
fax_gateway_indicate_t38(chan, active, control_params);
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == active;
report_fax_status(chan, details, "T.38 Negotiated");
}
@@ -3170,14 +3218,16 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
t38_parameters_fax_to_ast(control_params, &details->our_t38_parameters);
if (fax_gateway_start(gateway, details, chan)) {
- ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(active), ast_channel_name(other));
+ ast_log(LOG_ERROR, "error starting T.38 gateway for T.38 channel %s and G.711 channel %s\n", ast_channel_name(other), ast_channel_name(active));
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_REFUSED;
ast_framehook_detach(chan, details->gateway_id);
details->gateway_id = -1;
} else {
gateway->t38_state = T38_STATE_NEGOTIATED;
+ details->is_t38_negotiated = chan == other;
control_params->request_response = AST_T38_NEGOTIATED;
}
@@ -3193,6 +3243,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
details->gateway_id = -1;
gateway->t38_state = T38_STATE_REJECTED;
+ details->is_t38_negotiated = 0;
control_params->request_response = AST_T38_TERMINATED;
fax_gateway_indicate_t38(chan, active, control_params);
@@ -3208,6 +3259,7 @@ static struct ast_frame *fax_gateway_detect_t38(struct fax_gateway *gateway, str
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "no gateway necessary");
ast_string_field_set(details, error, "NATIVE_T38");
+ details->is_t38_negotiated = 1;
set_channel_variables(chan, details);
ao2_ref(details, -1);
@@ -3250,7 +3302,8 @@ static void fax_gateway_framehook_destroy(void *data)
ao2_ref(gateway, -1);
}
-/*! \brief T.30<->T.38 gateway framehook.
+/*!
+ * \brief T.30<->T.38 gateway framehook.
*
* Intercept packets on bridged channels and determine if a T.38 gateway is
* required. If a gateway is required, start a gateway and handle T.38
@@ -3261,6 +3314,8 @@ static void fax_gateway_framehook_destroy(void *data)
* \param event framehook event
* \param data framehook data (struct fax_gateway *)
*
+ * \pre chan is locked on entry
+ *
* \return processed frame or NULL when f is NULL or a null frame
*/
static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data)
@@ -3323,8 +3378,16 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
}
if (!gateway->bridged) {
+ enum ast_t38_state state_chan;
+ enum ast_t38_state state_peer;
+
+ ast_channel_unlock(chan);
+ state_chan = ast_channel_get_t38_state(chan);
+ state_peer = ast_channel_get_t38_state(peer);
+ ast_channel_lock(chan);
+
/* don't start a gateway if neither channel can handle T.38 */
- if (ast_channel_get_t38_state(chan) == T38_STATE_UNAVAILABLE && ast_channel_get_t38_state(peer) == T38_STATE_UNAVAILABLE) {
+ if (state_chan == T38_STATE_UNAVAILABLE && state_peer == T38_STATE_UNAVAILABLE) {
ast_debug(1, "not starting gateway for %s and %s; neither channel supports T.38\n", ast_channel_name(chan), ast_channel_name(peer));
ast_framehook_detach(chan, gateway->framehook);
details->gateway_id = -1;
@@ -3332,6 +3395,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "neither channel supports T.38");
ast_string_field_set(details, error, "T38_NEG_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3376,6 +3440,7 @@ static struct ast_frame *fax_gateway_framehook(struct ast_channel *chan, struct
ast_string_field_set(details, result, "FAILED");
ast_string_field_build(details, resultstr, "no fax activity after %d ms", details->gateway_timeout);
ast_string_field_set(details, error, "TIMEOUT");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return f;
}
@@ -3491,9 +3556,9 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
.disable_inheritance = 1, /* Masquerade inheritance is handled through the datastore fixup */
};
- if (global_fax_debug) {
- details->option.debug = AST_FAX_OPTFLAG_TRUE;
- }
+ if (global_fax_debug) {
+ details->option.debug = AST_FAX_OPTFLAG_TRUE;
+ }
ast_string_field_set(details, result, "SUCCESS");
ast_string_field_set(details, resultstr, "gateway operation started successfully");
@@ -3506,6 +3571,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error initializing gateway session");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
report_fax_status(chan, details, "No Available Resource");
return -1;
@@ -3521,6 +3587,7 @@ static int fax_gateway_attach(struct ast_channel *chan, struct ast_fax_session_d
ast_string_field_set(details, result, "FAILED");
ast_string_field_set(details, resultstr, "error attaching gateway to channel");
ast_string_field_set(details, error, "INIT_ERROR");
+ details->is_t38_negotiated = 0;
set_channel_variables(chan, details);
return -1;
}
@@ -4509,7 +4576,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a T.38 gateway on channel (%s) with gateway already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->gateway_id);
+ ast_channel_unlock(chan);
details->gateway_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
@@ -4561,7 +4630,9 @@ static int acf_faxopt_write(struct ast_channel *chan, const char *cmd, char *dat
ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", ast_channel_name(chan));
}
} else if (ast_false(val)) {
+ ast_channel_lock(chan);
ast_framehook_detach(chan, details->faxdetect_id);
+ ast_channel_unlock(chan);
details->faxdetect_id = -1;
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
diff --git a/res/res_pjsip/config_global.c b/res/res_pjsip/config_global.c
index 975c5eefe..1d0c11c35 100644
--- a/res/res_pjsip/config_global.c
+++ b/res/res_pjsip/config_global.c
@@ -48,6 +48,15 @@
#define DEFAULT_MWI_TPS_QUEUE_LOW -1
#define DEFAULT_MWI_DISABLE_INITIAL_UNSOLICITED 0
+/*!
+ * \brief Cached global config object
+ *
+ * \details
+ * Cached so we don't have to keep asking sorcery for the config.
+ * We could ask for it hundreds of times a second if not more.
+ */
+static AO2_GLOBAL_OBJ_STATIC(global_cfg);
+
static char default_useragent[256];
struct global_config {
@@ -135,23 +144,14 @@ static int global_apply(const struct ast_sorcery *sorcery, void *obj)
ast_sip_add_global_request_header("Max-Forwards", max_forwards, 1);
ast_sip_add_global_request_header("User-Agent", cfg->useragent, 1);
ast_sip_add_global_response_header("Server", cfg->useragent, 1);
+
+ ao2_t_global_obj_replace_unref(global_cfg, cfg, "Applying global settings");
return 0;
}
static struct global_config *get_global_cfg(void)
{
- struct global_config *cfg;
- struct ao2_container *globals;
-
- globals = ast_sorcery_retrieve_by_fields(ast_sip_get_sorcery(), "global",
- AST_RETRIEVE_FLAG_MULTIPLE | AST_RETRIEVE_FLAG_ALL, NULL);
- if (!globals) {
- return NULL;
- }
-
- cfg = ao2_find(globals, NULL, 0);
- ao2_ref(globals, -1);
- return cfg;
+ return ao2_global_obj_ref(global_cfg);
}
char *ast_sip_global_default_outbound_endpoint(void)
@@ -462,6 +462,8 @@ int ast_sip_destroy_sorcery_global(void)
ast_sorcery_instance_observer_remove(sorcery, &observer_callbacks_global);
+ ao2_t_global_obj_release(global_cfg, "Module is unloading");
+
return 0;
}
diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c
index e5bb90e5c..8fe4e8477 100644
--- a/res/res_pjsip_refer.c
+++ b/res/res_pjsip_refer.c
@@ -607,7 +607,10 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
ao2_ref(refer->progress, +1);
/* If we can't attach a frame hook for whatever reason send a notification of success immediately */
- if ((refer->progress->framehook = ast_framehook_attach(chan, &hook)) < 0) {
+ ast_channel_lock(chan);
+ refer->progress->framehook = ast_framehook_attach(chan, &hook);
+ ast_channel_unlock(chan);
+ if (refer->progress->framehook < 0) {
struct refer_progress_notification *notification = refer_progress_notification_alloc(refer->progress, 200,
PJSIP_EVSUB_STATE_TERMINATED);
@@ -638,7 +641,9 @@ static void refer_blind_callback(struct ast_channel *chan, struct transfer_chann
refer_progress_notify(notification);
}
+ ast_channel_lock(chan);
ast_framehook_detach(chan, refer->progress->framehook);
+ ast_channel_unlock(chan);
ao2_cleanup(refer->progress);
}
diff --git a/res/res_pjsip_t38.c b/res/res_pjsip_t38.c
index 992902af2..01bfefdd9 100644
--- a/res/res_pjsip_t38.c
+++ b/res/res_pjsip_t38.c
@@ -501,25 +501,27 @@ static void t38_attach_framehook(struct ast_sip_session *session)
return;
}
- /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
ast_channel_lock(session->channel);
- if ((datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore, NULL))) {
+
+ /* Skip attaching the framehook if the T.38 datastore already exists for the channel */
+ datastore = ast_channel_datastore_find(session->channel, &t38_framehook_datastore,
+ NULL);
+ if (datastore) {
ast_channel_unlock(session->channel);
return;
}
- ast_channel_unlock(session->channel);
framehook_id = ast_framehook_attach(session->channel, &hook);
if (framehook_id < 0) {
- ast_log(LOG_WARNING, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_WARNING, "Could not attach T.38 Frame hook, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
+ ast_channel_unlock(session->channel);
return;
}
- ast_channel_lock(session->channel);
datastore = ast_datastore_alloc(&t38_framehook_datastore, NULL);
if (!datastore) {
- ast_log(LOG_ERROR, "Could not attach T.38 Frame hook to channel, T.38 will be unavailable on '%s'\n",
+ ast_log(LOG_ERROR, "Could not alloc T.38 Frame hook datastore, T.38 will be unavailable on '%s'\n",
ast_channel_name(session->channel));
ast_framehook_detach(session->channel, framehook_id);
ast_channel_unlock(session->channel);
diff --git a/res/res_rtp_multicast.c b/res/res_rtp_multicast.c
index 53bdf14a4..ea313476e 100644
--- a/res/res_rtp_multicast.c
+++ b/res/res_rtp_multicast.c
@@ -143,7 +143,7 @@ struct ast_multicast_rtp_options *ast_multicast_rtp_create_options(const char *t
mcast_options = ast_calloc(1, sizeof(*mcast_options)
+ strlen(type)
- + strlen(options) + 2);
+ + strlen(S_OR(options, "")) + 2);
if (!mcast_options) {
return NULL;
}
@@ -155,8 +155,9 @@ struct ast_multicast_rtp_options *ast_multicast_rtp_create_options(const char *t
mcast_options->type = pos;
pos += strlen(type) + 1;
- /* Safe */
- strcpy(pos, options);
+ if (!ast_strlen_zero(options)) {
+ strcpy(pos, options); /* Safe */
+ }
mcast_options->options = pos;
if (ast_app_parse_options(multicast_rtp_options, &mcast_options->opts,
diff --git a/third-party/pjproject/patches/config_site.h b/third-party/pjproject/patches/config_site.h
index 07e4d97a9..f9f76dc6c 100644
--- a/third-party/pjproject/patches/config_site.h
+++ b/third-party/pjproject/patches/config_site.h
@@ -4,6 +4,14 @@
#include <sys/select.h>
+/*
+ * Defining PJMEDIA_HAS_SRTP to 0 does NOT disable Asterisk's ability to use srtp.
+ * It only disables the pjmedia srtp transport which Asterisk doesn't use.
+ * The reason for the disable is that while Asterisk works fine with older libsrtp
+ * versions, newer versions of pjproject won't compile with them.
+ */
+#define PJMEDIA_HAS_SRTP 0
+
#define PJ_HAS_IPV6 1
#define NDEBUG 1
#define PJ_MAX_HOSTNAME (256)