diff options
-rw-r--r-- | CHANGES | 6 | ||||
-rw-r--r-- | apps/app_confbridge.c | 274 | ||||
-rw-r--r-- | apps/app_macro.c | 36 | ||||
-rw-r--r-- | apps/app_queue.c | 11 | ||||
-rw-r--r-- | apps/confbridge/conf_chan_announce.c | 30 | ||||
-rw-r--r-- | apps/confbridge/include/confbridge.h | 12 | ||||
-rw-r--r-- | include/asterisk/channel.h | 6 | ||||
-rw-r--r-- | include/asterisk/chanvars.h | 2 | ||||
-rw-r--r-- | include/asterisk/config.h | 2 | ||||
-rw-r--r-- | include/asterisk/hashtab.h | 14 | ||||
-rw-r--r-- | include/asterisk/heap.h | 4 | ||||
-rw-r--r-- | include/asterisk/res_fax.h | 22 | ||||
-rw-r--r-- | include/asterisk/strings.h | 6 | ||||
-rw-r--r-- | main/bridge_basic.c | 2 | ||||
-rw-r--r-- | main/channel.c | 2 | ||||
-rw-r--r-- | main/chanvars.c | 4 | ||||
-rw-r--r-- | main/config.c | 4 | ||||
-rw-r--r-- | main/hashtab.c | 40 | ||||
-rw-r--r-- | main/heap.c | 14 | ||||
-rw-r--r-- | main/pbx.c | 25 | ||||
-rw-r--r-- | main/strings.c | 4 | ||||
-rw-r--r-- | res/res_fax.c | 109 | ||||
-rw-r--r-- | res/res_pjsip/config_global.c | 26 | ||||
-rw-r--r-- | res/res_pjsip_refer.c | 7 | ||||
-rw-r--r-- | res/res_pjsip_t38.c | 14 | ||||
-rw-r--r-- | res/res_rtp_multicast.c | 7 | ||||
-rw-r--r-- | third-party/pjproject/patches/config_site.h | 8 |
27 files changed, 495 insertions, 196 deletions
@@ -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) |