static void internal_bridge_after_cb(struct ast_channel *chan, void *data, enum ast_bridge_after_cb_reason reason) { struct stasis_app_control *control = data; SCOPED_AO2LOCK(lock, control); struct ast_bridge_channel *bridge_channel; ast_debug(3, "%s, %s: %s\n", ast_channel_uniqueid(chan), control->bridge ? control->bridge->uniqueid : "unknown", ast_bridge_after_cb_reason_string(reason)); if (reason == AST_BRIDGE_AFTER_CB_REASON_IMPART_FAILED) { /* The impart actually failed so control->bridge isn't valid. */ control->bridge = NULL; } ast_assert(chan == control->channel); /* Restore the channel's PBX */ ast_channel_pbx_set(control->channel, control->pbx); control->pbx = NULL; if (control->bridge) { app_unsubscribe_bridge(control->app, control->bridge); /* No longer in the bridge */ control->bridge = NULL; /* Get the bridge channel so we don't depart from the wrong bridge */ ast_channel_lock(chan); bridge_channel = ast_channel_get_bridge_channel(chan); ast_channel_unlock(chan); /* Depart this channel from the bridge using the command queue if possible */ stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup); } if (stasis_app_channel_is_stasis_end_published(chan)) { /* The channel has had a StasisEnd published on it, but until now had remained in * the bridging system. This means that the channel moved from a Stasis bridge to a * non-Stasis bridge and is now exiting the bridging system. Because of this, the * channel needs to exit the Stasis application and go to wherever the non-Stasis * bridge has directed it to go. If the non-Stasis bridge has not set up an after * bridge destination, then the channel should be hung up. */ int hangup_flag; hangup_flag = ast_bridge_setup_after_goto(chan) ? AST_SOFTHANGUP_DEV : AST_SOFTHANGUP_ASYNCGOTO; ast_channel_lock(chan); ast_softhangup_nolock(chan, hangup_flag); ast_channel_unlock(chan); } }
static int start_spying(struct ast_autochan *autochan, const char *spychan_name, struct ast_audiohook *audiohook) { int res = 0; ast_log(LOG_NOTICE, "Attaching %s to %s\n", spychan_name, ast_channel_name(autochan->chan)); ast_set_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC | AST_AUDIOHOOK_SMALL_QUEUE); res = ast_audiohook_attach(autochan->chan, audiohook); if (!res) { ast_channel_lock(autochan->chan); if (ast_channel_is_bridged(autochan->chan)) { ast_softhangup_nolock(autochan->chan, AST_SOFTHANGUP_UNBRIDGE); } ast_channel_unlock(autochan->chan); } return res; }
static int pickdown_channel(struct ast_channel *chan, void *pattern) { int ret = 0; struct ast_module_user *u; struct ast_channel *cur; u = ast_module_user_add(chan); cur = find_matching_channel(chan, pattern, AST_STATE_RINGING); if (cur) { ast_verbose(VERBOSE_PREFIX_3 "Channel %s hung up ringing channel %s\n", chan->name, cur->name); pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", cur->name); ast_softhangup_nolock(cur, AST_SOFTHANGUP_DEV); ast_mutex_unlock(&cur->lock); } else { pbx_builtin_setvar_helper(chan, "PICKDOWN_CHANNEL", ""); } ast_module_user_remove(u); return(ret); }
int ast_pbx_hangup_handler_run(struct ast_channel *chan) { struct ast_hangup_handler_list *handlers; struct ast_hangup_handler *h_handler; ast_channel_lock(chan); handlers = ast_channel_hangup_handlers(chan); if (AST_LIST_EMPTY(handlers)) { ast_channel_unlock(chan); return 0; } /* * Make sure that the channel is marked as hungup since we are * going to run the hangup handlers on it. */ ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC); for (;;) { handlers = ast_channel_hangup_handlers(chan); h_handler = AST_LIST_REMOVE_HEAD(handlers, node); if (!h_handler) { break; } publish_hangup_handler_message("run", chan, h_handler->args); ast_channel_unlock(chan); ast_app_exec_sub(NULL, chan, h_handler->args, 1); ast_free(h_handler); ast_channel_lock(chan); } ast_channel_unlock(chan); return 1; }