static int mute_channel(struct ast_channel *chan, const char *direction, int mute) { unsigned int mute_direction = 0; enum ast_frame_type frametype = AST_FRAME_VOICE; int ret = 0; if (!strcmp(direction, "in")) { mute_direction = AST_MUTE_DIRECTION_READ; } else if (!strcmp(direction, "out")) { mute_direction = AST_MUTE_DIRECTION_WRITE; } else if (!strcmp(direction, "all")) { mute_direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE; } else { return -1; } ast_channel_lock(chan); if (mute) { ret = ast_channel_suppress(chan, mute_direction, frametype); } else { ret = ast_channel_unsuppress(chan, mute_direction, frametype); } ast_channel_unlock(chan); return ret; }
int control_prestart_dispatch_all(struct stasis_app_control *control, struct ast_channel *chan) { struct ao2_container *command_queue; int count = 0; struct ao2_iterator iter; struct stasis_app_command *command; ast_channel_lock(chan); command_queue = command_prestart_get_container(chan); ast_channel_unlock(chan); if (!command_queue) { return 0; } iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK); while ((command = ao2_iterator_next(&iter))) { command_invoke(command, control, chan); ao2_cleanup(command); ++count; } ao2_iterator_destroy(&iter); ao2_cleanup(command_queue); return count; }
/*! * \brief Dial timeout * * This is a bridge interval hook callback. The interval hook triggering * means that the dial timeout has been reached. If the channel has not * been answered by the time this callback is called, then the channel * is hung up * * \param bridge_channel Bridge channel on which interval hook has been called * \param ignore Ignored * \return -1 (i.e. remove the interval hook) */ static int bridge_timeout(struct ast_bridge_channel *bridge_channel, void *ignore) { struct ast_datastore *datastore; RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); control = stasis_app_control_find_by_channel(bridge_channel->chan); ast_channel_lock(bridge_channel->chan); if (ast_channel_state(bridge_channel->chan) != AST_STATE_UP) { /* Don't bother removing the datastore because it will happen when the channel is hung up */ ast_channel_unlock(bridge_channel->chan); stasis_app_send_command_async(control, hangup_channel, NULL, NULL); return -1; } datastore = ast_channel_datastore_find(bridge_channel->chan, &timeout_datastore, NULL); if (!datastore) { ast_channel_unlock(bridge_channel->chan); return -1; } ast_channel_datastore_remove(bridge_channel->chan, datastore); ast_channel_unlock(bridge_channel->chan); ast_datastore_free(datastore); return -1; }
/*! * \internal * \since 12.0.0 * \brief Park a call * * \param parker The bridge_channel parking the call * \param exten Optional. The extension where the call was parked. * \param length Optional. If \c exten is specified, the length of the buffer. * * \note This will determine the context and extension to park the channel based on * the configuration of the \ref ast_channel associated with \ref parker. It will then * park either the channel or the entire bridge. * * \retval 0 on success * \retval -1 on error */ static int parking_park_call(struct ast_bridge_channel *parker, char *exten, size_t length) { RAII_VAR(struct parking_lot *, lot, NULL, ao2_cleanup); const char *lot_name = NULL; ast_channel_lock(parker->chan); lot_name = find_channel_parking_lot_name(parker->chan); if (!ast_strlen_zero(lot_name)) { lot_name = ast_strdupa(lot_name); } ast_channel_unlock(parker->chan); if (ast_strlen_zero(lot_name)) { return -1; } lot = parking_lot_find_by_name(lot_name); if (!lot) { ast_log(AST_LOG_WARNING, "Cannot Park %s: lot %s unknown\n", ast_channel_name(parker->chan), lot_name); return -1; } if (exten) { ast_copy_string(exten, lot->cfg->parkext, length); } return parking_blind_transfer_park(parker, lot->cfg->parking_con, lot->cfg->parkext, NULL, NULL); }
static struct chanspy_ds *chanspy_ds_free(struct chanspy_ds *chanspy_ds) { if (!chanspy_ds) return NULL; ast_mutex_lock(&chanspy_ds->lock); if (chanspy_ds->chan) { struct ast_datastore *datastore; struct ast_channel *chan; chan = chanspy_ds->chan; ast_channel_lock(chan); if ((datastore = ast_channel_datastore_find(chan, &chanspy_ds_info, chanspy_ds->unique_id))) { ast_channel_datastore_remove(chan, datastore); /* chanspy_ds->chan is NULL after this call */ chanspy_ds_destroy(datastore->data); datastore->data = NULL; ast_channel_datastore_free(datastore); } ast_channel_unlock(chan); } ast_mutex_unlock(&chanspy_ds->lock); return NULL; }
static int sendtext_exec(struct ast_channel *chan, const char *data) { char *status = "UNSUPPORTED"; struct ast_str *str; /* NOT ast_strlen_zero, because some protocols (e.g. SIP) MUST be able to * send a zero-length message. */ if (!data) { ast_log(LOG_WARNING, "SendText requires an argument (text)\n"); return -1; } if (!(str = ast_str_alloca(strlen(data) + 1))) { return -1; } ast_str_get_encoded_str(&str, -1, data); ast_channel_lock(chan); if (!ast_channel_tech(chan)->send_text) { ast_channel_unlock(chan); /* Does not support transport */ pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status); return 0; } status = "FAILURE"; if (!ast_sendtext(chan, ast_str_buffer(str))) { status = "SUCCESS"; } ast_channel_unlock(chan); pbx_builtin_setvar_helper(chan, "SENDTEXTSTATUS", status); return 0; }
/*! \brief SpeechCreate() Dialplan Application */ static int speech_create(struct ast_channel *chan, const char *data) { struct ast_speech *speech = NULL; struct ast_datastore *datastore = NULL; /* Request a speech object */ speech = ast_speech_new(data, ast_channel_nativeformats(chan)); if (speech == NULL) { /* Not available */ pbx_builtin_setvar_helper(chan, "ERROR", "1"); return 0; } datastore = ast_datastore_alloc(&speech_datastore, NULL); if (datastore == NULL) { ast_speech_destroy(speech); pbx_builtin_setvar_helper(chan, "ERROR", "1"); return 0; } pbx_builtin_setvar_helper(chan, "ERROR", NULL); datastore->data = speech; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); return 0; }
/* Called with ast locked */ static int local_queryoption(struct ast_channel *ast, int option, void *data, int *datalen) { struct local_pvt *p; struct ast_channel *bridged = NULL; struct ast_channel *tmp = NULL; int res = 0; if (option != AST_OPTION_T38_STATE) { /* AST_OPTION_T38_STATE is the only supported option at this time */ return -1; } /* for some reason the channel is not locked in channel.c when this function is called */ if (!(p = ast_channel_tech_pvt(ast))) { return -1; } ao2_lock(p); if (!(tmp = IS_OUTBOUND(ast, p) ? p->owner : p->chan)) { ao2_unlock(p); return -1; } ast_channel_ref(tmp); ao2_unlock(p); ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */ ast_channel_lock(tmp); if (!(bridged = ast_bridged_channel(tmp))) { res = -1; ast_channel_unlock(tmp); goto query_cleanup; } ast_channel_ref(bridged); ast_channel_unlock(tmp); query_cleanup: if (bridged) { res = ast_channel_queryoption(bridged, option, data, datalen, 0); bridged = ast_channel_unref(bridged); } if (tmp) { tmp = ast_channel_unref(tmp); } ast_channel_lock(ast); /* Lock back before we leave */ return res; }
static void bridge_stasis_queue_join_action(struct ast_bridge *self, struct ast_bridge_channel *bridge_channel) { ast_channel_lock(bridge_channel->chan); command_prestart_queue_command(bridge_channel->chan, add_channel_to_bridge, ao2_bump(self), __ao2_cleanup); ast_channel_unlock(bridge_channel->chan); }
struct ast_channel *ast_pickup_find_by_group(struct ast_channel *chan) { struct ao2_container *candidates;/*!< Candidate channels found to pickup. */ struct ast_channel *target;/*!< Potential pickup target */ candidates = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL); if (!candidates) { return NULL; } /* Find all candidate targets by group. */ ast_channel_callback(find_channel_by_group, chan, candidates, 0); /* Find the oldest pickup target candidate */ target = NULL; for (;;) { struct ast_channel *candidate;/*!< Potential new older target */ struct ao2_iterator iter; iter = ao2_iterator_init(candidates, 0); while ((candidate = ao2_iterator_next(&iter))) { if (!target) { /* First target. */ target = candidate; continue; } if (ast_tvcmp(ast_channel_creationtime(candidate), ast_channel_creationtime(target)) < 0) { /* We have a new target. */ ast_channel_unref(target); target = candidate; continue; } ast_channel_unref(candidate); } ao2_iterator_destroy(&iter); if (!target) { /* No candidates found. */ break; } /* The found channel must be locked and ref'd. */ ast_channel_lock(target); /* Recheck pickup ability */ if (ast_can_pickup(target)) { /* This is the channel to pickup. */ break; } /* Someone else picked it up or the call went away. */ ast_channel_unlock(target); ao2_unlink(candidates, target); target = ast_channel_unref(target); } ao2_ref(candidates, -1); return target; }
/*! \brief Helper function which adds frame hook to bridge channel */ static int native_rtp_bridge_framehook_attach(struct ast_bridge_channel *bridge_channel) { struct native_rtp_bridge_data *data = ao2_alloc(sizeof(*data), NULL); static struct ast_framehook_interface hook = { .version = AST_FRAMEHOOK_INTERFACE_VERSION, .event_cb = native_rtp_framehook, .destroy_cb = __ao2_cleanup, .consume_cb = native_rtp_framehook_consume, .disable_inheritance = 1, }; if (!data) { return -1; } ast_channel_lock(bridge_channel->chan); hook.data = ao2_bump(data); data->id = ast_framehook_attach(bridge_channel->chan, &hook); ast_channel_unlock(bridge_channel->chan); if (data->id < 0) { /* We need to drop both the reference we hold, and the one the framehook would hold */ ao2_ref(data, -2); return -1; } bridge_channel->tech_pvt = data; return 0; } /*! \brief Helper function which removes frame hook from bridge channel */ static void native_rtp_bridge_framehook_detach(struct ast_bridge_channel *bridge_channel) { RAII_VAR(struct native_rtp_bridge_data *, data, bridge_channel->tech_pvt, ao2_cleanup); if (!data) { return; } ast_channel_lock(bridge_channel->chan); ast_framehook_detach(bridge_channel->chan, data->id); data->detached = 1; ast_channel_unlock(bridge_channel->chan); bridge_channel->tech_pvt = NULL; }
static int frame_trace_helper(struct ast_channel *chan, const char *cmd, char *data, const char *value) { struct frame_trace_data *framedata; struct ast_datastore *datastore = NULL; struct ast_framehook_interface interface = { .version = AST_FRAMEHOOK_INTERFACE_VERSION, .event_cb = hook_event_cb, .destroy_cb = hook_destroy_cb, }; int i = 0; if (!(framedata = ast_calloc(1, sizeof(*framedata)))) { return 0; } interface.data = framedata; if (!strcasecmp(data, "black")) { framedata->list_type = 1; } for (i = 0; i < ARRAY_LEN(frametype2str); i++) { if (strcasestr(value, frametype2str[i].str)) { framedata->values[i] = 1; } } ast_channel_lock(chan); i = ast_framehook_attach(chan, &interface); if (i >= 0) { int *id; if ((datastore = ast_channel_datastore_find(chan, &frame_trace_datastore, NULL))) { id = datastore->data; ast_framehook_detach(chan, *id); ast_channel_datastore_remove(chan, datastore); } if (!(datastore = ast_datastore_alloc(&frame_trace_datastore, NULL))) { ast_framehook_detach(chan, i); ast_channel_unlock(chan); return 0; } if (!(id = ast_calloc(1, sizeof(int)))) { ast_datastore_free(datastore); ast_framehook_detach(chan, i); ast_channel_unlock(chan); return 0; } *id = i; /* Store off the id. The channel is still locked so it is safe to access this ptr. */ datastore->data = id; ast_channel_datastore_add(chan, datastore); } ast_channel_unlock(chan); return 0; }
/*! \brief Function called to attach T.38 framehook to channel when appropriate */ static void t38_attach_framehook(struct ast_sip_session *session) { int framehook_id; struct ast_datastore *datastore = NULL; static struct ast_framehook_interface hook = { .version = AST_FRAMEHOOK_INTERFACE_VERSION, .event_cb = t38_framehook, .chan_fixup_cb = t38_masq, .chan_breakdown_cb = t38_masq, }; /* Only attach the framehook if t38 is enabled for the endpoint */ if (!session->endpoint->media.t38.enabled) { 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))) { 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_channel_name(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_channel_name(session->channel)); ast_framehook_detach(session->channel, framehook_id); ast_channel_unlock(session->channel); return; } ast_channel_datastore_add(session->channel, datastore); ast_channel_unlock(session->channel); }
static void bridge_after_cb(struct ast_channel *chan, void *data) { struct stasis_app_control *control = data; SCOPED_AO2LOCK(lock, control); struct ast_bridge_channel *bridge_channel; ast_debug(3, "%s, %s: Channel leaving bridge\n", ast_channel_uniqueid(chan), control->bridge->uniqueid); ast_assert(chan == control->channel); /* Restore the channel's PBX */ ast_channel_pbx_set(control->channel, control->pbx); control->pbx = NULL; 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 manager_park(struct mansession *s, const struct message *m) { const char *channel = astman_get_header(m, "Channel"); const char *timeout_channel = S_OR(astman_get_header(m, "TimeoutChannel"), astman_get_header(m, "Channel2")); const char *timeout = astman_get_header(m, "Timeout"); const char *parkinglot = astman_get_header(m, "Parkinglot"); char buf[BUFSIZ]; int timeout_override = -1; RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup); RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup); if (ast_strlen_zero(channel)) { astman_send_error(s, m, "Channel not specified"); return 0; } if (!ast_strlen_zero(timeout)) { if (sscanf(timeout, "%30d", &timeout_override) != 1 || timeout < 0) { astman_send_error(s, m, "Invalid Timeout value."); return 0; } if (timeout_override > 0) { /* If greater than zero, convert to seconds for internal use. Must be >= 1 second. */ timeout_override = MAX(1, timeout_override / 1000); } } if (!(chan = ast_channel_get_by_name(channel))) { snprintf(buf, sizeof(buf), "Channel does not exist: %s", channel); astman_send_error(s, m, buf); return 0; } ast_channel_lock(chan); if (!ast_strlen_zero(timeout_channel)) { pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", timeout_channel); } ast_channel_unlock(chan); if (!(parking_bridge = park_common_setup(chan, chan, parkinglot, NULL, 0, 0, timeout_override, 0))) { astman_send_error(s, m, "Park action failed\n"); return 0; } if (ast_bridge_add_channel(parking_bridge, chan, NULL, 0, NULL)) { astman_send_error(s, m, "Park action failed\n"); return 0; } astman_send_ack(s, m, "Park successful\n"); return 0; }
/*! * \internal * \brief CLI output the channel hangup handlers. * \since 11.0 * * \param fd CLI file descriptor to use. * \param chan Channel to show hangup handlers. * * \return Nothing */ static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan) { struct ast_hangup_handler_list *handlers; struct ast_hangup_handler *h_handler; int first = 1; ast_channel_lock(chan); handlers = ast_channel_hangup_handlers(chan); AST_LIST_TRAVERSE(handlers, h_handler, node) { ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args); first = 0; }
static int linkedid_match(void *obj, void *arg, void *data, int flags) { struct ast_channel *c = obj; struct channel_find_data *find_dat = data; int res; ast_channel_lock(c); res = (c != find_dat->chan && c->linkedid && !strcmp(find_dat->linkedid, c->linkedid)); ast_channel_unlock(c); return res ? CMP_MATCH | CMP_STOP : 0; }
static void parker_parked_call_message_response(struct ast_parked_call_payload *message, struct parked_subscription_data *data, struct stasis_subscription *sub) { const char *parkee_to_act_on = data->parkee_uuid; char saynum_buf[16]; struct ast_channel_snapshot *parkee_snapshot = message->parkee; RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup); RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup); if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) { return; } if (message->event_type != PARKED_CALL && message->event_type != PARKED_CALL_FAILED) { /* We only care about these two event types */ return; } parker = ast_channel_get_by_name(data->parker_uuid); if (!parker) { return; } ast_channel_lock(parker); bridge_channel = ast_channel_get_bridge_channel(parker); ast_channel_unlock(parker); if (!bridge_channel) { return; } /* This subscription callback will block for the duration of the announcement if * parked_subscription_data is tracking a transfer_channel_data struct. */ if (message->event_type == PARKED_CALL) { /* queue the saynum on the bridge channel and hangup */ snprintf(saynum_buf, sizeof(saynum_buf), "%d %u", data->hangup_after, message->parkingspace); if (!data->transfer_data) { ast_bridge_channel_queue_playfile(bridge_channel, say_parking_space, saynum_buf, NULL); } else { ast_bridge_channel_queue_playfile_sync(bridge_channel, say_parking_space, saynum_buf, NULL); data->transfer_data->completed = 1; } wipe_subscription_datastore(parker); } else if (message->event_type == PARKED_CALL_FAILED) { if (!data->transfer_data) { ast_bridge_channel_queue_playfile(bridge_channel, NULL, "pbx-parkingfailed", NULL); } else { ast_bridge_channel_queue_playfile_sync(bridge_channel, NULL, "pbx-parkingfailed", NULL); data->transfer_data->completed = 1; } wipe_subscription_datastore(parker); } }
static int func_channels_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t maxlen) { struct ast_channel *c = NULL; regex_t re; int res; size_t buflen = 0; struct ast_channel_iterator *iter; buf[0] = '\0'; if (!ast_strlen_zero(data)) { if ((res = regcomp(&re, data, REG_EXTENDED | REG_ICASE | REG_NOSUB))) { regerror(res, &re, buf, maxlen); ast_log(LOG_WARNING, "Error compiling regular expression for %s(%s): %s\n", function, data, buf); return -1; } } if (!(iter = ast_channel_iterator_all_new())) { if (!ast_strlen_zero(data)) { regfree(&re); } return -1; } while ((c = ast_channel_iterator_next(iter))) { ast_channel_lock(c); if (ast_strlen_zero(data) || regexec(&re, ast_channel_name(c), 0, NULL, 0) == 0) { size_t namelen = strlen(ast_channel_name(c)); if (buflen + namelen + (ast_strlen_zero(buf) ? 0 : 1) + 1 < maxlen) { if (!ast_strlen_zero(buf)) { strcat(buf, " "); buflen++; } strcat(buf, ast_channel_name(c)); buflen += namelen; } else { ast_log(LOG_WARNING, "Number of channels exceeds the available buffer space. Output will be truncated!\n"); } } ast_channel_unlock(c); c = ast_channel_unref(c); } ast_channel_iterator_destroy(iter); if (!ast_strlen_zero(data)) { regfree(&re); } return 0; }
static void wipe_subscription_datastore(struct ast_channel *chan) { struct ast_datastore *datastore; ast_channel_lock(chan); datastore = ast_channel_datastore_find(chan, &parked_subscription_info, NULL); if (datastore) { ast_channel_datastore_remove(chan, datastore); ast_datastore_free(datastore); } ast_channel_unlock(chan); }
static struct ast_parked_call_payload *parked_call_payload_from_failure(struct ast_channel *chan) { RAII_VAR(struct ast_channel_snapshot *, parkee_snapshot, NULL, ao2_cleanup); ast_channel_lock(chan); parkee_snapshot = ast_channel_snapshot_create(chan); ast_channel_unlock(chan); if (!parkee_snapshot) { return NULL; } return ast_parked_call_payload_create(PARKED_CALL_FAILED, parkee_snapshot, NULL, NULL, NULL, 0, 0, 0); }
static int create_parked_subscription_full(struct ast_channel *chan, const char *parkee_uuid, int hangup_after, struct transfer_channel_data *parked_channel_data) { struct ast_datastore *datastore; struct parked_subscription_datastore *parked_datastore; struct parked_subscription_data *subscription_data; char *parker_uuid = ast_strdupa(ast_channel_uniqueid(chan)); size_t parker_uuid_size = strlen(parker_uuid) + 1; /* If there is already a subscription, get rid of it. */ wipe_subscription_datastore(chan); if (!(datastore = ast_datastore_alloc(&parked_subscription_info, NULL))) { return -1; } if (!(parked_datastore = ast_calloc(1, sizeof(*parked_datastore)))) { ast_datastore_free(datastore); return -1; } if (!(subscription_data = ast_calloc(1, sizeof(*subscription_data) + parker_uuid_size + strlen(parkee_uuid) + 1))) { ast_datastore_free(datastore); ast_free(parked_datastore); return -1; } if (parked_channel_data) { subscription_data->transfer_data = parked_channel_data; ao2_ref(parked_channel_data, +1); } subscription_data->hangup_after = hangup_after; subscription_data->parkee_uuid = subscription_data->parker_uuid + parker_uuid_size; strcpy(subscription_data->parkee_uuid, parkee_uuid); strcpy(subscription_data->parker_uuid, parker_uuid); if (!(parked_datastore->parked_subscription = stasis_subscribe_pool(ast_parking_topic(), parker_update_cb, subscription_data))) { return -1; } datastore->data = parked_datastore; ast_channel_lock(chan); ast_channel_datastore_add(chan, datastore); ast_channel_unlock(chan); return 0; }
/*! * \ingroup applications */ int indicate_congestion(struct ast_channel *chan, const char *data) { ast_indicate(chan, AST_CONTROL_CONGESTION); /* Don't change state of an UP channel, just indicate congestion in audio */ ast_channel_lock(chan); if (ast_channel_state(chan) != AST_STATE_UP) { ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION); ast_setstate(chan, AST_STATE_BUSY); } ast_channel_unlock(chan); wait_for_hangup(chan, data); return -1; }
static int pickup_by_name_cb(void *obj, void *arg, void *data, int flags) { struct ast_channel *target = obj;/*!< Potential pickup target */ struct pickup_by_name_args *args = data; ast_channel_lock(target); if (!strncasecmp(ast_channel_name(target), args->name, args->len) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } ast_channel_unlock(target); return 0; }
static int find_channel_by_group(void *obj, void *arg, void *data, int flags) { struct ast_channel *target = obj; /*!< Potential pickup target */ struct ast_channel *chan = arg; /*!< Channel wanting to pickup call */ if (chan == target) { return 0; } ast_channel_lock(target); if (ast_can_pickup(target)) { /* Lock both channels. */ while (ast_channel_trylock(chan)) { ast_channel_unlock(target); sched_yield(); ast_channel_lock(target); } /* * Both callgroup and namedcallgroup pickup variants are * matched independently. Checking for named group match is * done last since it's a more expensive operation. */ if ((ast_channel_pickupgroup(chan) & ast_channel_callgroup(target)) || (ast_namedgroups_intersect(ast_channel_named_pickupgroups(chan), ast_channel_named_callgroups(target)))) { struct ao2_container *candidates = data;/*!< Candidate channels found. */ /* This is a candidate to pickup */ ao2_link(candidates, target); } ast_channel_unlock(chan); } ast_channel_unlock(target); return 0; }
static int func_channel_read(struct ast_channel *chan, const char *function, char *data, char *buf, size_t len) { int ret = 0; if (!strcasecmp(data, "audionativeformat")) /* use the _multiple version when chan->nativeformats holds multiple formats */ /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_AUDIO_MASK); */ ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_AUDIO_MASK), len); else if (!strcasecmp(data, "videonativeformat")) /* use the _multiple version when chan->nativeformats holds multiple formats */ /* ast_getformatname_multiple(buf, len, chan->nativeformats & AST_FORMAT_VIDEO_MASK); */ ast_copy_string(buf, ast_getformatname(chan->nativeformats & AST_FORMAT_VIDEO_MASK), len); else if (!strcasecmp(data, "audioreadformat")) ast_copy_string(buf, ast_getformatname(chan->readformat), len); else if (!strcasecmp(data, "audiowriteformat")) ast_copy_string(buf, ast_getformatname(chan->writeformat), len); #ifdef CHANNEL_TRACE else if (!strcasecmp(data, "trace")) { ast_channel_lock(chan); ast_copy_string(buf, ast_channel_trace_is_enabled(chan) ? "1" : "0", len); ast_channel_unlock(chan); } #endif else if (!strcasecmp(data, "tonezone") && chan->zone) locked_copy_string(chan, buf, chan->zone->country, len); else if (!strcasecmp(data, "language")) locked_copy_string(chan, buf, chan->language, len); else if (!strcasecmp(data, "musicclass")) locked_copy_string(chan, buf, chan->musicclass, len); else if (!strcasecmp(data, "parkinglot")) locked_copy_string(chan, buf, chan->parkinglot, len); else if (!strcasecmp(data, "state")) locked_copy_string(chan, buf, ast_state2str(chan->_state), len); else if (!strcasecmp(data, "channeltype")) locked_copy_string(chan, buf, chan->tech->type, len); else if (!strcasecmp(data, "transfercapability")) locked_copy_string(chan, buf, transfercapability_table[chan->transfercapability & 0x1f], len); else if (!strcasecmp(data, "callgroup")) { char groupbuf[256]; locked_copy_string(chan, buf, ast_print_group(groupbuf, sizeof(groupbuf), chan->callgroup), len); } else if (!chan->tech->func_channel_read || chan->tech->func_channel_read(chan, function, data, buf, len)) { ast_log(LOG_WARNING, "Unknown or unavailable item requested: '%s'\n", data); ret = -1; } return ret; }
/*! * \brief after bridge callback for the dial bridge * * The only purpose of this callback is to ensure that the control structure's * bridge pointer is NULLed */ static void dial_bridge_after_cb(struct ast_channel *chan, void *data) { struct stasis_app_control *control = data; struct ast_bridge_channel *bridge_channel; ast_channel_lock(chan); bridge_channel = ast_channel_get_bridge_channel(chan); ast_channel_unlock(chan); ast_debug(3, "Channel: <%s> Reason: %d\n", ast_channel_name(control->channel), ast_channel_hangupcause(chan)); stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup); control->bridge = NULL; }
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; }
void ast_pbx_hangup_handler_destroy(struct ast_channel *chan) { struct ast_hangup_handler_list *handlers; struct ast_hangup_handler *h_handler; ast_channel_lock(chan); /* Get rid of each of the hangup handlers on the channel */ handlers = ast_channel_hangup_handlers(chan); while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) { ast_free(h_handler); } ast_channel_unlock(chan); }
static int find_channel_by_group(void *obj, void *arg, void *data, int flags) { struct ast_channel *target = obj;/*!< Potential pickup target */ struct ast_channel *chan = data;/*!< Channel wanting to pickup call */ ast_channel_lock(target); if (chan != target && (chan->pickupgroup & target->callgroup) && ast_can_pickup(target)) { /* Return with the channel still locked on purpose */ return CMP_MATCH | CMP_STOP; } ast_channel_unlock(target); return 0; }