diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/bridge.c | 51 | ||||
-rw-r--r-- | main/bridge_channel.c | 25 | ||||
-rw-r--r-- | main/format_cap.c | 19 | ||||
-rw-r--r-- | main/loader.c | 28 | ||||
-rw-r--r-- | main/sorcery.c | 7 |
5 files changed, 119 insertions, 11 deletions
diff --git a/main/bridge.c b/main/bridge.c index b2f7b0ffa..ebbfc3976 100644 --- a/main/bridge.c +++ b/main/bridge.c @@ -1549,7 +1549,7 @@ int ast_bridge_join(struct ast_bridge *bridge, } if (!res) { - res = bridge_channel_internal_join(bridge_channel); + res = bridge_channel_internal_join(bridge_channel, NULL); } /* Cleanup all the data in the bridge channel after it leaves the bridge. */ @@ -1579,13 +1579,14 @@ join_exit:; /*! \brief Thread responsible for imparted bridged channels to be departed */ static void *bridge_channel_depart_thread(void *data) { - struct ast_bridge_channel *bridge_channel = data; + struct bridge_channel_internal_cond *cond = data; + struct ast_bridge_channel *bridge_channel = cond->bridge_channel; if (bridge_channel->callid) { ast_callid_threadassoc_add(bridge_channel->callid); } - bridge_channel_internal_join(bridge_channel); + bridge_channel_internal_join(bridge_channel, cond); /* * cleanup @@ -1606,14 +1607,15 @@ static void *bridge_channel_depart_thread(void *data) /*! \brief Thread responsible for independent imparted bridged channels */ static void *bridge_channel_ind_thread(void *data) { - struct ast_bridge_channel *bridge_channel = data; + struct bridge_channel_internal_cond *cond = data; + struct ast_bridge_channel *bridge_channel = cond->bridge_channel; struct ast_channel *chan; if (bridge_channel->callid) { ast_callid_threadassoc_add(bridge_channel->callid); } - bridge_channel_internal_join(bridge_channel); + bridge_channel_internal_join(bridge_channel, cond); chan = bridge_channel->chan; /* cleanup */ @@ -1697,13 +1699,27 @@ int ast_bridge_impart(struct ast_bridge *bridge, /* Actually create the thread that will handle the channel */ if (!res) { + struct bridge_channel_internal_cond cond = { + .done = 0, + .bridge_channel = bridge_channel + }; + ast_mutex_init(&cond.lock); + ast_cond_init(&cond.cond, NULL); + if ((flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_INDEPENDENT) { res = ast_pthread_create_detached(&bridge_channel->thread, NULL, - bridge_channel_ind_thread, bridge_channel); + bridge_channel_ind_thread, &cond); } else { res = ast_pthread_create(&bridge_channel->thread, NULL, - bridge_channel_depart_thread, bridge_channel); + bridge_channel_depart_thread, &cond); } + + if (!res) { + bridge_channel_internal_wait(&cond); + } + + ast_cond_destroy(&cond.cond); + ast_mutex_destroy(&cond.lock); } if (res) { @@ -3953,6 +3969,15 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha struct ast_channel *chan2, struct ast_bridge *bridge1, struct ast_bridge *bridge2, struct ast_attended_transfer_message *transfer_msg) { +#define BRIDGE_LOCK_ONE_OR_BOTH(b1, b2) \ + do { \ + if (b2) { \ + ast_bridge_lock_both(b1, b2); \ + } else { \ + ast_bridge_lock(b1); \ + } \ + } while (0) + static const char *dest = "_attended@transfer/m"; struct ast_channel *local_chan; int cause; @@ -3983,8 +4008,18 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha return AST_BRIDGE_TRANSFER_FAIL; } + /* + * Since bridges need to be unlocked before entering ast_bridge_impart and + * core_local may call into it then the bridges need to be unlocked here. + */ + ast_bridge_unlock(bridge1); + if (bridge2) { + ast_bridge_unlock(bridge2); + } + if (ast_call(local_chan, dest, 0)) { ast_hangup(local_chan); + BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2); return AST_BRIDGE_TRANSFER_FAIL; } @@ -3994,8 +4029,10 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(local_chan); ao2_cleanup(local_chan); + BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2); return AST_BRIDGE_TRANSFER_FAIL; } + BRIDGE_LOCK_ONE_OR_BOTH(bridge1, bridge2); if (bridge2) { RAII_VAR(struct ast_channel *, local_chan2, NULL, ao2_cleanup); diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 159722697..28dfd9ccb 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -2560,7 +2560,27 @@ static void bridge_channel_event_join_leave(struct ast_bridge_channel *bridge_ch ao2_iterator_destroy(&iter); } -int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) +void bridge_channel_internal_wait(struct bridge_channel_internal_cond *cond) +{ + ast_mutex_lock(&cond->lock); + while (!cond->done) { + ast_cond_wait(&cond->cond, &cond->lock); + } + ast_mutex_unlock(&cond->lock); +} + +void bridge_channel_internal_signal(struct bridge_channel_internal_cond *cond) +{ + if (cond) { + ast_mutex_lock(&cond->lock); + cond->done = 1; + ast_cond_signal(&cond->cond); + ast_mutex_unlock(&cond->lock); + } +} + +int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel, + struct bridge_channel_internal_cond *cond) { int res = 0; struct ast_bridge_features *channel_features; @@ -2590,6 +2610,7 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) bridge_channel->bridge->uniqueid, bridge_channel, ast_channel_name(bridge_channel->chan)); + bridge_channel_internal_signal(cond); return -1; } ast_channel_internal_bridge_set(bridge_channel->chan, bridge_channel->bridge); @@ -2624,6 +2645,8 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) } bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp); + bridge_channel_internal_signal(cond); + if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) { /* * Indicate a source change since this channel is entering the diff --git a/main/format_cap.c b/main/format_cap.c index 52262579c..224fe331f 100644 --- a/main/format_cap.c +++ b/main/format_cap.c @@ -293,7 +293,24 @@ int ast_format_cap_update_by_allow_disallow(struct ast_format_cap *cap, const ch } parse = ast_strdupa(list); - while ((this = strsep(&parse, ","))) { + + /* If the list is being fed to us as a result of ast_format_cap_get_names, + * strip off the paranthesis and immediately apply the inverse of the + * allowing option + */ + if (parse[0] == '(' && parse[strlen(parse) - 1] == ')') { + parse++; + parse[strlen(parse) - 1] = '\0'; + + if (allowing) { + ast_format_cap_remove_by_type(cap, AST_MEDIA_TYPE_UNKNOWN); + } else { + ast_format_cap_append_by_type(cap, AST_MEDIA_TYPE_UNKNOWN); + } + } + + + while ((this = strsep(&parse, ",|"))) { int framems = 0; struct ast_format *format = NULL; diff --git a/main/loader.c b/main/loader.c index 99a47b3b4..b2bdd4a3d 100644 --- a/main/loader.c +++ b/main/loader.c @@ -1445,6 +1445,34 @@ int ast_update_module_list_data(int (*modentry)(const char *module, const char * return total_mod_loaded; } +int ast_update_module_list_condition(int (*modentry)(const char *module, const char *description, + int usecnt, const char *status, + const char *like, + enum ast_module_support_level support_level, + void *data, const char *condition), + const char *like, void *data, const char *condition) +{ + struct ast_module *cur; + int conditions_met = 0; + AST_LIST_HEAD_NOLOCK(, ast_module) alpha_module_list = AST_LIST_HEAD_NOLOCK_INIT_VALUE; + + AST_DLLIST_LOCK(&module_list); + + AST_DLLIST_TRAVERSE(&module_list, cur, entry) { + AST_LIST_INSERT_SORTALPHA(&alpha_module_list, cur, list_entry, resource); + } + + while ((cur = AST_LIST_REMOVE_HEAD(&alpha_module_list, list_entry))) { + conditions_met += modentry(cur->resource, cur->info->description, cur->usecount, + cur->flags.running? "Running" : "Not Running", like, cur->info->support_level, data, + condition); + } + + AST_DLLIST_UNLOCK(&module_list); + + return conditions_met; +} + /*! \brief Check if module exists */ int ast_module_check(const char *name) { diff --git a/main/sorcery.c b/main/sorcery.c index 790e782cc..6d24b1486 100644 --- a/main/sorcery.c +++ b/main/sorcery.c @@ -1600,10 +1600,13 @@ struct ast_json *ast_sorcery_objectset_json_create(const struct ast_sorcery *sor char *buf = NULL; struct ast_json *value = NULL; - if ((res = object_field->handler(object, object_field->args, &buf)) + if (object_field->handler(object, object_field->args, &buf) || !(value = ast_json_string_create(buf)) || ast_json_object_set(json, object_field->name, value)) { - res = -1; + ast_free(buf); + ast_debug(5, "Skipping field '%s' for object type '%s'\n", + object_field->name, object_type->name); + continue; } ast_free(buf); |