control.c File Reference

Stasis application control support. More...

#include "asterisk.h"
#include "asterisk/stasis_channels.h"
#include "command.h"
#include "control.h"
#include "app.h"
#include "asterisk/dial.h"
#include "asterisk/bridge.h"
#include "asterisk/bridge_after.h"
#include "asterisk/bridge_basic.h"
#include "asterisk/frame.h"
#include "asterisk/pbx.h"
#include "asterisk/musiconhold.h"
#include "asterisk/app.h"

Include dependency graph for control.c:

Go to the source code of this file.

Data Structures

struct  app_control_rules
struct  stasis_app_control
struct  stasis_app_control_continue_data
struct  stasis_app_control_dial_data
struct  stasis_app_control_dtmf_data
struct  stasis_app_control_mute_data

Typedefs

typedef int(* app_command_can_exec_cb )(struct stasis_app_control *control)

Functions

static int app_control_can_add_channel_to_bridge (struct stasis_app_control *control)
static int app_control_can_remove_channel_from_bridge (struct stasis_app_control *control)
static enum
stasis_app_control_channel_result 
app_control_check_rules (const struct stasis_app_control *control, struct app_control_rules *list)
static int app_control_continue (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_dial (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_dtmf (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_hold (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_moh_start (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_moh_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_mute (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_redirect (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static void app_control_register_rule (const struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
static int app_control_remove_channel_from_bridge (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_ring (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_ring_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_silence_start (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_silence_stop (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_unhold (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static int app_control_unmute (struct stasis_app_control *control, struct ast_channel *chan, void *data)
static void app_control_unregister_rule (const struct stasis_app_control *control, struct app_control_rules *list, struct stasis_app_control_rule *obj)
static int app_send_command_on_condition (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
static void bridge_after_cb (struct ast_channel *chan, void *data)
static void bridge_after_cb_failed (enum ast_bridge_after_cb_reason reason, void *data)
static int bridge_channel_depart (struct stasis_app_control *control, struct ast_channel *chan, void *data)
int control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_channel *chan, void *data)
 Command callback for adding a channel to a bridge.
struct stasis_appcontrol_app (struct stasis_app_control *control)
 Returns the pointer (non-reffed) to the app associated with this control.
int control_command_count (struct stasis_app_control *control)
 Returns the count of items in a control's command queue.
struct stasis_app_controlcontrol_create (struct ast_channel *channel, struct stasis_app *app)
 Create a control object.
int control_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all commands enqueued to this control.
static void control_dtor (void *obj)
int control_is_done (struct stasis_app_control *control)
 Returns true if control_continue() has been called on this control.
void control_mark_done (struct stasis_app_control *control)
int control_prestart_dispatch_all (struct stasis_app_control *control, struct ast_channel *chan)
 Dispatch all queued prestart commands.
void control_wait (struct stasis_app_control *control)
 Blocks until control's command queue has a command available.
static struct stasis_app_commandexec_command (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
static struct stasis_app_commandexec_command_on_condition (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor, app_command_can_exec_cb can_exec_fn)
static int noop_cb (struct stasis_app_control *control, struct ast_channel *chan, void *data)
int stasis_app_control_add_channel_to_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Add a channel to the bridge.
int stasis_app_control_add_role (struct stasis_app_control *control, const char *role)
 Apply a bridge role to a channel controlled by a stasis app control.
void stasis_app_control_clear_roles (struct stasis_app_control *control)
 Clear bridge roles currently applied to a channel controlled by a stasis app control.
int stasis_app_control_continue (struct stasis_app_control *control, const char *context, const char *extension, int priority)
 Exit res_stasis and continue execution in the dialplan.
int stasis_app_control_dial (struct stasis_app_control *control, const char *endpoint, const char *exten, const char *context, int timeout)
 Dial an endpoint and bridge it to a channel in res_stasis.
int stasis_app_control_dtmf (struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
 Send DTMF to the channel associated with this control.
const char * stasis_app_control_get_channel_id (const struct stasis_app_control *control)
 Returns the uniqueid of the channel associated with this control.
struct ast_channel_snapshotstasis_app_control_get_snapshot (const struct stasis_app_control *control)
 Returns the most recent snapshot for the associated channel.
void stasis_app_control_hold (struct stasis_app_control *control)
 Place the channel associated with the control on hold.
void stasis_app_control_moh_start (struct stasis_app_control *control, const char *moh_class)
 Play music on hold to a channel (does not affect hold status).
void stasis_app_control_moh_stop (struct stasis_app_control *control)
 Stop playing music on hold to a channel (does not affect hold status).
int stasis_app_control_mute (struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
 Mute the channel associated with this control.
void stasis_app_control_publish (struct stasis_app_control *control, struct stasis_message *message)
 Publish a message to the control's channel's topic.
int stasis_app_control_queue_control (struct stasis_app_control *control, enum ast_control_frame_type frame_type)
 Queue a control frame without payload.
int stasis_app_control_redirect (struct stasis_app_control *control, const char *endpoint)
 Redirect a channel in res_stasis to a particular endpoint.
void stasis_app_control_register_add_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Registers an add channel to bridge rule.
void stasis_app_control_register_remove_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Registers a remove channel from bridge rule.
int stasis_app_control_remove_channel_from_bridge (struct stasis_app_control *control, struct ast_bridge *bridge)
 Remove a channel from the bridge.
int stasis_app_control_ring (struct stasis_app_control *control)
 Indicate ringing to the channel associated with this control.
int stasis_app_control_ring_stop (struct stasis_app_control *control)
 Stop locally generated ringing on the channel associated with this control.
int stasis_app_control_set_channel_var (struct stasis_app_control *control, const char *variable, const char *value)
 Set a variable on the channel associated with this control to value.
void stasis_app_control_silence_start (struct stasis_app_control *control)
 Start playing silence to a channel.
void stasis_app_control_silence_stop (struct stasis_app_control *control)
 Stop playing silence to a channel.
void stasis_app_control_unhold (struct stasis_app_control *control)
 Remove the channel associated with the control from hold.
int stasis_app_control_unmute (struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
 Unmute the channel associated with this control.
void stasis_app_control_unregister_add_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 UnRegister an add channel to bridge rule.
void stasis_app_control_unregister_remove_rule (struct stasis_app_control *control, struct stasis_app_control_rule *rule)
 Unregisters a remove channel from bridge rule.
struct ast_bridgestasis_app_get_bridge (struct stasis_app_control *control)
 Gets the bridge currently associated with a control object.
int stasis_app_send_command (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 Invokes a command on a control's channel.
int stasis_app_send_command_async (struct stasis_app_control *control, stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
 Asynchronous version of stasis_app_send_command().


Detailed Description

Stasis application control support.

Author:
David M. Lee, II <dlee@digium.com>

Definition in file control.c.


Typedef Documentation

typedef int(* app_command_can_exec_cb)(struct stasis_app_control *control)

Callback type to see if the command can execute note: command_queue is locked during callback

Definition at line 237 of file control.c.


Function Documentation

static int app_control_can_add_channel_to_bridge ( struct stasis_app_control control  )  [static]

Definition at line 217 of file control.c.

References stasis_app_control::add_rules, and app_control_check_rules().

Referenced by stasis_app_control_add_channel_to_bridge().

00219 {
00220    return app_control_check_rules(control, &control->add_rules);
00221 }

static int app_control_can_remove_channel_from_bridge ( struct stasis_app_control control  )  [static]

Definition at line 223 of file control.c.

References app_control_check_rules(), and stasis_app_control::remove_rules.

Referenced by stasis_app_control_remove_channel_from_bridge().

00225 {
00226    return app_control_check_rules(control, &control->remove_rules);
00227 }

static enum stasis_app_control_channel_result app_control_check_rules ( const struct stasis_app_control control,
struct app_control_rules list 
) [static]

Definition at line 175 of file control.c.

References AST_LIST_TRAVERSE, stasis_app_control_rule::check_rule, and stasis_app_control_rule::next.

Referenced by app_control_can_add_channel_to_bridge(), and app_control_can_remove_channel_from_bridge().

00178 {
00179    int res = 0;
00180    struct stasis_app_control_rule *rule;
00181    AST_LIST_TRAVERSE(list, rule, next) {
00182       if ((res = rule->check_rule(control))) {
00183          return res;
00184       }
00185    }
00186    return res;
00187 }

static int app_control_continue ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 390 of file control.c.

References ast_assert, ast_bridge_depart(), ast_explicit_goto(), stasis_app_control::channel, stasis_app_control_continue_data::context, stasis_app_control_continue_data::extension, stasis_app_control::is_done, NULL, stasis_app_control_continue_data::priority, and stasis_app_get_bridge().

Referenced by stasis_app_control_continue().

00392 {
00393    struct stasis_app_control_continue_data *continue_data = data;
00394 
00395    ast_assert(control->channel != NULL);
00396 
00397    /* If we're in a Stasis bridge, depart it before going back to the
00398     * dialplan */
00399    if (stasis_app_get_bridge(control)) {
00400       ast_bridge_depart(control->channel);
00401    }
00402 
00403    /* Called from stasis_app_exec thread; no lock needed */
00404    ast_explicit_goto(control->channel, continue_data->context, continue_data->extension, continue_data->priority);
00405 
00406    control->is_done = 1;
00407 
00408    return 0;
00409 }

static int app_control_dial ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 280 of file control.c.

References ao2_cleanup, ast_bridge_basic_new(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_INDEPENDENT, ast_dial_answered_steal(), ast_dial_append(), ast_dial_create(), ast_dial_destroy(), AST_DIAL_RESULT_ANSWERED, ast_dial_run(), ast_dial_set_global_timeout(), ast_hangup(), ast_log, ast_channel::bridge, control_add_channel_to_bridge(), stasis_app_control_dial_data::endpoint, LOG_ERROR, NULL, RAII_VAR, and stasis_app_control_dial_data::timeout.

Referenced by stasis_app_control_dial().

00282 {
00283    RAII_VAR(struct ast_dial *, dial, ast_dial_create(), ast_dial_destroy);
00284    struct stasis_app_control_dial_data *dial_data = data;
00285    enum ast_dial_result res;
00286    char *tech, *resource;
00287    struct ast_channel *new_chan;
00288    RAII_VAR(struct ast_bridge *, bridge, NULL, ao2_cleanup);
00289 
00290    tech = dial_data->endpoint;
00291    if (!(resource = strchr(tech, '/'))) {
00292       return -1;
00293    }
00294    *resource++ = '\0';
00295 
00296    if (!dial) {
00297       ast_log(LOG_ERROR, "Failed to create dialing structure.\n");
00298       return -1;
00299    }
00300 
00301    if (ast_dial_append(dial, tech, resource, NULL) < 0) {
00302       ast_log(LOG_ERROR, "Failed to add %s/%s to dialing structure.\n", tech, resource);
00303       return -1;
00304    }
00305 
00306    ast_dial_set_global_timeout(dial, dial_data->timeout);
00307 
00308    res = ast_dial_run(dial, NULL, 0);
00309    if (res != AST_DIAL_RESULT_ANSWERED || !(new_chan = ast_dial_answered_steal(dial))) {
00310       return -1;
00311    }
00312 
00313    if (!(bridge = ast_bridge_basic_new())) {
00314       ast_log(LOG_ERROR, "Failed to create basic bridge.\n");
00315       return -1;
00316    }
00317 
00318    if (ast_bridge_impart(bridge, new_chan, NULL, NULL,
00319       AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
00320       ast_hangup(new_chan);
00321    } else {
00322       control_add_channel_to_bridge(control, chan, bridge);
00323    }
00324 
00325    return 0;
00326 }

static int app_control_dtmf ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 471 of file control.c.

References stasis_app_control_dtmf_data::after, AST_CONTROL_PROGRESS, ast_dtmf_stream(), ast_indicate(), ast_safe_sleep(), AST_STATE_UP, stasis_app_control_dtmf_data::before, stasis_app_control_dtmf_data::between, stasis_app_control_dtmf_data::dtmf, stasis_app_control_dtmf_data::duration, and NULL.

Referenced by stasis_app_control_dtmf().

00473 {
00474    struct stasis_app_control_dtmf_data *dtmf_data = data;
00475 
00476    if (ast_channel_state(chan) != AST_STATE_UP) {
00477       ast_indicate(chan, AST_CONTROL_PROGRESS);
00478    }
00479 
00480    if (dtmf_data->before) {
00481       ast_safe_sleep(chan, dtmf_data->before);
00482    }
00483 
00484    ast_dtmf_stream(chan, NULL, dtmf_data->dtmf, dtmf_data->between, dtmf_data->duration);
00485 
00486    if (dtmf_data->after) {
00487       ast_safe_sleep(chan, dtmf_data->after);
00488    }
00489 
00490    return 0;
00491 }

static int app_control_hold ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 606 of file control.c.

References AST_CONTROL_HOLD, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_hold().

00608 {
00609    ast_indicate(control->channel, AST_CONTROL_HOLD);
00610 
00611    return 0;
00612 }

static int app_control_moh_start ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 632 of file control.c.

References AST_CONTROL_PROGRESS, ast_indicate(), ast_moh_start(), AST_STATE_UP, and NULL.

Referenced by stasis_app_control_moh_start().

00634 {
00635    char *moh_class = data;
00636 
00637    if (ast_channel_state(chan) != AST_STATE_UP) {
00638       ast_indicate(chan, AST_CONTROL_PROGRESS);
00639    }
00640 
00641    ast_moh_start(chan, moh_class, NULL);
00642 
00643    return 0;
00644 }

static int app_control_moh_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 657 of file control.c.

References ast_moh_stop().

Referenced by stasis_app_control_moh_stop().

00659 {
00660    ast_moh_stop(chan);
00661    return 0;
00662 }

static int app_control_mute ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 547 of file control.c.

References ast_channel_suppress(), stasis_app_control::channel, stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and SCOPED_CHANNELLOCK.

Referenced by stasis_app_control_mute().

00549 {
00550    struct stasis_app_control_mute_data *mute_data = data;
00551    SCOPED_CHANNELLOCK(lockvar, chan);
00552 
00553    ast_channel_suppress(control->channel, mute_data->direction, mute_data->frametype);
00554 
00555    return 0;
00556 }

static int app_control_redirect ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 431 of file control.c.

References ast_assert, ast_channel_name(), ast_log, ast_transfer(), stasis_app_control::channel, LOG_NOTICE, and NULL.

Referenced by stasis_app_control_redirect().

00433 {
00434    char *endpoint = data;
00435    int res;
00436 
00437    ast_assert(control->channel != NULL);
00438    ast_assert(endpoint != NULL);
00439 
00440    res = ast_transfer(control->channel, endpoint);
00441    if (!res) {
00442       ast_log(LOG_NOTICE, "Unsupported transfer requested on channel '%s'\n",
00443          ast_channel_name(control->channel));
00444       return 0;
00445    }
00446 
00447    return 0;
00448 }

static void app_control_register_rule ( const struct stasis_app_control control,
struct app_control_rules list,
struct stasis_app_control_rule obj 
) [static]

static int app_control_remove_channel_from_bridge ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 957 of file control.c.

References ast_bridge_depart(), ast_debug, ast_log, LOG_WARNING, stasis_app_control_get_channel_id(), stasis_app_get_bridge(), and ast_bridge::uniqueid.

Referenced by stasis_app_control_remove_channel_from_bridge().

00960 {
00961    struct ast_bridge *bridge = data;
00962 
00963    if (!control) {
00964       return -1;
00965    }
00966 
00967    /* We should only depart from our own bridge */
00968    ast_debug(3, "%s: Departing bridge %s\n",
00969       stasis_app_control_get_channel_id(control),
00970       bridge->uniqueid);
00971 
00972    if (bridge != stasis_app_get_bridge(control)) {
00973       ast_log(LOG_WARNING, "%s: Not in bridge %s; not removing\n",
00974          stasis_app_control_get_channel_id(control),
00975          bridge->uniqueid);
00976       return -1;
00977    }
00978 
00979    ast_bridge_depart(chan);
00980    return 0;
00981 }

static int app_control_ring ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 512 of file control.c.

References AST_CONTROL_RINGING, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_ring().

00514 {
00515    ast_indicate(control->channel, AST_CONTROL_RINGING);
00516 
00517    return 0;
00518 }

static int app_control_ring_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 527 of file control.c.

References ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_ring_stop().

00529 {
00530    ast_indicate(control->channel, -1);
00531 
00532    return 0;
00533 }

static int app_control_silence_start ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 669 of file control.c.

References ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), AST_CONTROL_PROGRESS, ast_debug, ast_indicate(), ast_log, AST_STATE_UP, stasis_app_control::channel, LOG_WARNING, stasis_app_control::silgen, and stasis_app_control_get_channel_id().

Referenced by stasis_app_control_silence_start().

00671 {
00672    if (ast_channel_state(chan) != AST_STATE_UP) {
00673       ast_indicate(chan, AST_CONTROL_PROGRESS);
00674    }
00675 
00676    if (control->silgen) {
00677       /* We have a silence generator, but it may have been implicitly
00678        * disabled by media actions (music on hold, playing media,
00679        * etc.) Just stop it and restart a new one.
00680        */
00681       ast_channel_stop_silence_generator(
00682          control->channel, control->silgen);
00683    }
00684 
00685    ast_debug(3, "%s: Starting silence generator\n",
00686       stasis_app_control_get_channel_id(control));
00687    control->silgen = ast_channel_start_silence_generator(control->channel);
00688 
00689    if (!control->silgen) {
00690       ast_log(LOG_WARNING,
00691          "%s: Failed to start silence generator.\n",
00692          stasis_app_control_get_channel_id(control));
00693    }
00694 
00695    return 0;
00696 }

static int app_control_silence_stop ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 703 of file control.c.

References ast_channel_stop_silence_generator(), ast_debug, stasis_app_control::channel, NULL, stasis_app_control::silgen, and stasis_app_control_get_channel_id().

Referenced by stasis_app_control_silence_stop().

00705 {
00706    if (control->silgen) {
00707       ast_debug(3, "%s: Stopping silence generator\n",
00708          stasis_app_control_get_channel_id(control));
00709       ast_channel_stop_silence_generator(
00710          control->channel, control->silgen);
00711       control->silgen = NULL;
00712    }
00713 
00714    return 0;
00715 }

static int app_control_unhold ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 619 of file control.c.

References AST_CONTROL_UNHOLD, ast_indicate(), and stasis_app_control::channel.

Referenced by stasis_app_control_unhold().

00621 {
00622    ast_indicate(control->channel, AST_CONTROL_UNHOLD);
00623 
00624    return 0;
00625 }

static int app_control_unmute ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 574 of file control.c.

References ast_channel_unsuppress(), stasis_app_control::channel, stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and SCOPED_CHANNELLOCK.

Referenced by stasis_app_control_unmute().

00576 {
00577    struct stasis_app_control_mute_data *mute_data = data;
00578    SCOPED_CHANNELLOCK(lockvar, chan);
00579 
00580    ast_channel_unsuppress(control->channel, mute_data->direction, mute_data->frametype);
00581 
00582    return 0;
00583 }

static void app_control_unregister_rule ( const struct stasis_app_control control,
struct app_control_rules list,
struct stasis_app_control_rule obj 
) [static]

static int app_send_command_on_condition ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor,
app_command_can_exec_cb  can_exec_fn 
) [static]

Definition at line 741 of file control.c.

References ao2_cleanup, command_join(), exec_command_on_condition(), NULL, and RAII_VAR.

Referenced by stasis_app_control_add_channel_to_bridge(), stasis_app_control_remove_channel_from_bridge(), and stasis_app_send_command().

00745 {
00746    RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
00747 
00748    if (control == NULL) {
00749       return -1;
00750    }
00751 
00752    command = exec_command_on_condition(
00753       control, command_fn, data, data_destructor, can_exec_fn);
00754    if (!command) {
00755       return -1;
00756    }
00757 
00758    return command_join(command);
00759 }

static void bridge_after_cb ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 818 of file control.c.

References __ao2_cleanup(), stasis_app_control::app, app_unsubscribe_bridge(), ast_assert, ast_bridge_setup_after_goto(), ast_channel_get_bridge_channel(), ast_channel_lock, ast_channel_pbx_set(), ast_channel_uniqueid(), ast_channel_unlock, ast_debug, AST_SOFTHANGUP_ASYNCGOTO, AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), stasis_app_control::bridge, bridge_channel_depart(), stasis_app_control::channel, lock, NULL, stasis_app_control::pbx, SCOPED_AO2LOCK, stasis_app_channel_is_stasis_end_published(), stasis_app_send_command_async(), and ast_bridge::uniqueid.

Referenced by bridge_after_cb_failed(), and control_add_channel_to_bridge().

00819 {
00820    struct stasis_app_control *control = data;
00821    SCOPED_AO2LOCK(lock, control);
00822    struct ast_bridge_channel *bridge_channel;
00823 
00824    ast_debug(3, "%s, %s: Channel leaving bridge\n",
00825       ast_channel_uniqueid(chan), control->bridge->uniqueid);
00826 
00827    ast_assert(chan == control->channel);
00828 
00829    /* Restore the channel's PBX */
00830    ast_channel_pbx_set(control->channel, control->pbx);
00831    control->pbx = NULL;
00832 
00833    app_unsubscribe_bridge(control->app, control->bridge);
00834 
00835    /* No longer in the bridge */
00836    control->bridge = NULL;
00837 
00838    /* Get the bridge channel so we don't depart from the wrong bridge */
00839    ast_channel_lock(chan);
00840    bridge_channel = ast_channel_get_bridge_channel(chan);
00841    ast_channel_unlock(chan);
00842 
00843    /* Depart this channel from the bridge using the command queue if possible */
00844    stasis_app_send_command_async(control, bridge_channel_depart, bridge_channel, __ao2_cleanup);
00845    if (stasis_app_channel_is_stasis_end_published(chan)) {
00846       /* The channel has had a StasisEnd published on it, but until now had remained in
00847        * the bridging system. This means that the channel moved from a Stasis bridge to a
00848        * non-Stasis bridge and is now exiting the bridging system. Because of this, the
00849        * channel needs to exit the Stasis application and go to wherever the non-Stasis
00850        * bridge has directed it to go. If the non-Stasis bridge has not set up an after
00851        * bridge destination, then the channel should be hung up.
00852        */
00853       int hangup_flag;
00854 
00855       hangup_flag = ast_bridge_setup_after_goto(chan) ? AST_SOFTHANGUP_DEV : AST_SOFTHANGUP_ASYNCGOTO;
00856       ast_channel_lock(chan);
00857       ast_softhangup_nolock(chan, hangup_flag);
00858       ast_channel_unlock(chan);
00859    }
00860 }

static void bridge_after_cb_failed ( enum ast_bridge_after_cb_reason  reason,
void *  data 
) [static]

Definition at line 862 of file control.c.

References ast_bridge_after_cb_reason_string(), ast_debug, bridge_after_cb(), and stasis_app_control::channel.

Referenced by control_add_channel_to_bridge().

00864 {
00865    struct stasis_app_control *control = data;
00866 
00867    bridge_after_cb(control->channel, data);
00868 
00869    ast_debug(3, "  reason: %s\n",
00870       ast_bridge_after_cb_reason_string(reason));
00871 }

static int bridge_channel_depart ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 795 of file control.c.

References ast_bridge_depart(), ast_channel_internal_bridge_channel(), ast_channel_uniqueid(), ast_debug, lock, and SCOPED_CHANNELLOCK.

Referenced by bridge_after_cb().

00797 {
00798    struct ast_bridge_channel *bridge_channel = data;
00799 
00800    {
00801       SCOPED_CHANNELLOCK(lock, chan);
00802 
00803       if (bridge_channel != ast_channel_internal_bridge_channel(chan)) {
00804          ast_debug(3, "%s: Channel is no longer in departable state\n",
00805             ast_channel_uniqueid(chan));
00806          return -1;
00807       }
00808    }
00809 
00810    ast_debug(3, "%s: Channel departing bridge\n",
00811       ast_channel_uniqueid(chan));
00812 
00813    ast_bridge_depart(chan);
00814 
00815    return 0;
00816 }

int control_add_channel_to_bridge ( struct stasis_app_control control,
struct ast_channel chan,
void *  obj 
)

Command callback for adding a channel to a bridge.

Parameters:
control The control for chan
channel The channel on which commands should be executed
bridge Data to be passed to the callback

Definition at line 873 of file control.c.

References stasis_app_control::app, app_subscribe_bridge(), ast_assert, ast_bridge_depart(), ast_bridge_impart(), AST_BRIDGE_IMPART_CHAN_DEPARTABLE, ast_bridge_set_after_callback(), ast_channel_pbx(), ast_channel_pbx_set(), ast_debug, ast_log, stasis_app_control::bridge, bridge_after_cb(), bridge_after_cb_failed(), lock, LOG_ERROR, NULL, stasis_app_control::pbx, SCOPED_AO2LOCK, stasis_app_control_get_channel_id(), stasis_app_get_bridge(), and ast_bridge::uniqueid.

Referenced by add_channel_to_bridge(), app_control_dial(), and stasis_app_control_add_channel_to_bridge().

00876 {
00877    struct ast_bridge *bridge = data;
00878    int res;
00879 
00880    if (!control || !bridge) {
00881       return -1;
00882    }
00883 
00884    ast_debug(3, "%s: Adding to bridge %s\n",
00885       stasis_app_control_get_channel_id(control),
00886       bridge->uniqueid);
00887 
00888    ast_assert(chan != NULL);
00889 
00890    /* Depart whatever Stasis bridge we're currently in. */
00891    if (stasis_app_get_bridge(control)) {
00892       /* Note that it looks like there's a race condition here, since
00893        * we don't have control locked. But this happens from the
00894        * control callback thread, so there won't be any other
00895        * concurrent attempts to bridge.
00896        */
00897       ast_bridge_depart(chan);
00898    }
00899 
00900 
00901    res = ast_bridge_set_after_callback(chan, bridge_after_cb,
00902       bridge_after_cb_failed, control);
00903    if (res != 0) {
00904       ast_log(LOG_ERROR, "Error setting after-bridge callback\n");
00905       return -1;
00906    }
00907 
00908    {
00909       /* pbx and bridge are modified by the bridging impart thread.
00910        * It shouldn't happen concurrently, but we still need to lock
00911        * for the memory fence.
00912        */
00913       SCOPED_AO2LOCK(lock, control);
00914 
00915       /* Ensure the controlling application is subscribed early enough
00916        * to receive the ChannelEnteredBridge message. This works in concert
00917        * with the subscription handled in the Stasis application execution
00918        * loop */
00919       app_subscribe_bridge(control->app, bridge);
00920 
00921       /* Save off the channel's PBX */
00922       ast_assert(control->pbx == NULL);
00923       if (!control->pbx) {
00924          control->pbx = ast_channel_pbx(chan);
00925          ast_channel_pbx_set(chan, NULL);
00926       }
00927 
00928       res = ast_bridge_impart(bridge,
00929          chan,
00930          NULL, /* swap channel */
00931          NULL, /* features */
00932          AST_BRIDGE_IMPART_CHAN_DEPARTABLE);
00933       if (res != 0) {
00934          ast_log(LOG_ERROR, "Error adding channel to bridge\n");
00935          ast_channel_pbx_set(chan, control->pbx);
00936          control->pbx = NULL;
00937          return -1;
00938       }
00939 
00940       ast_assert(stasis_app_get_bridge(control) == NULL);
00941       control->bridge = bridge;
00942    }
00943    return 0;
00944 }

struct stasis_app* control_app ( struct stasis_app_control control  )  [read]

Returns the pointer (non-reffed) to the app associated with this control.

Parameters:
control Control to query.
Returns:
A pointer to the associated stasis_app

Definition at line 1083 of file control.c.

References stasis_app_control::app.

Referenced by bridge_stasis_moving(), bridge_stasis_push_peek(), channel_replaced_cb(), and channel_stolen_cb().

01084 {
01085    return control->app;
01086 }

int control_command_count ( struct stasis_app_control control  ) 

Returns the count of items in a control's command queue.

Parameters:
control Control to count commands on
Return values:
number of commands in the command que

Definition at line 368 of file control.c.

References ao2_container_count(), and stasis_app_control::command_queue.

Referenced by stasis_app_control_execute_until_exhausted().

00369 {
00370    return ao2_container_count(control->command_queue);
00371 }

struct stasis_app_control* control_create ( struct ast_channel channel,
struct stasis_app app 
) [read]

Create a control object.

Parameters:
channel Channel to control.
app stasis_app for which this control is being created.
Returns:
New control object.

NULL on error.

Definition at line 102 of file control.c.

References ao2_alloc, AO2_ALLOC_OPT_LOCK_MUTEX, ao2_bump, ao2_cleanup, ao2_container_alloc_list, ao2_ref, ast_cond_init, AST_LIST_HEAD_INIT, ast_log, control_dtor(), errno, LOG_ERROR, NULL, and RAII_VAR.

Referenced by stasis_app_control_create(), and stasis_app_exec().

00103 {
00104    RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
00105    int res;
00106 
00107    control = ao2_alloc(sizeof(*control), control_dtor);
00108    if (!control) {
00109       return NULL;
00110    }
00111 
00112    control->app = ao2_bump(app);
00113 
00114    res = ast_cond_init(&control->wait_cond, NULL);
00115    if (res != 0) {
00116       ast_log(LOG_ERROR, "Error initializing ast_cond_t: %s\n",
00117          strerror(errno));
00118       return NULL;
00119    }
00120 
00121    control->command_queue = ao2_container_alloc_list(
00122       AO2_ALLOC_OPT_LOCK_MUTEX, 0, NULL, NULL);
00123 
00124    if (!control->command_queue) {
00125       return NULL;
00126    }
00127 
00128    control->channel = channel;
00129 
00130    AST_LIST_HEAD_INIT(&control->add_rules);
00131    AST_LIST_HEAD_INIT(&control->remove_rules);
00132 
00133    ao2_ref(control, +1);
00134    return control;
00135 }

int control_dispatch_all ( struct stasis_app_control control,
struct ast_channel chan 
)

Dispatch all commands enqueued to this control.

Parameters:
control Control object to dispatch.
chan Associated channel.
Returns:
Number of commands executed

Definition at line 1014 of file control.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ast_assert, stasis_app_control::channel, command_invoke(), stasis_app_control::command_queue, and RAII_VAR.

Referenced by stasis_app_control_execute_until_exhausted(), and stasis_app_exec().

01016 {
01017    int count = 0;
01018    struct ao2_iterator i;
01019    void *obj;
01020 
01021    ast_assert(control->channel == chan);
01022 
01023    i = ao2_iterator_init(control->command_queue, AO2_ITERATOR_UNLINK);
01024 
01025    while ((obj = ao2_iterator_next(&i))) {
01026       RAII_VAR(struct stasis_app_command *, command, obj, ao2_cleanup);
01027       command_invoke(command, control, chan);
01028       ++count;
01029    }
01030 
01031    ao2_iterator_destroy(&i);
01032    return count;
01033 }

static void control_dtor ( void *  obj  )  [static]

Definition at line 86 of file control.c.

References stasis_app_control::add_rules, ao2_cleanup, stasis_app_control::app, ast_channel_stop_silence_generator(), ast_cond_destroy, AST_LIST_HEAD_DESTROY, stasis_app_control::channel, stasis_app_control::command_queue, NULL, stasis_app_control::remove_rules, stasis_app_control::silgen, and stasis_app_control::wait_cond.

Referenced by control_create().

00087 {
00088    struct stasis_app_control *control = obj;
00089 
00090    AST_LIST_HEAD_DESTROY(&control->add_rules);
00091    AST_LIST_HEAD_DESTROY(&control->remove_rules);
00092 
00093    /* We may have a lingering silence generator; free it */
00094    ast_channel_stop_silence_generator(control->channel, control->silgen);
00095    control->silgen = NULL;
00096 
00097    ao2_cleanup(control->command_queue);
00098    ast_cond_destroy(&control->wait_cond);
00099    ao2_cleanup(control->app);
00100 }

int control_is_done ( struct stasis_app_control control  ) 

Returns true if control_continue() has been called on this control.

Parameters:
control Control to query.
Returns:
True (non-zero) if control_continue() has been called.

False (zero) otherwise.

Definition at line 373 of file control.c.

References stasis_app_control::is_done.

Referenced by stasis_app_control_execute_until_exhausted(), stasis_app_control_is_done(), and stasis_app_exec().

00374 {
00375    /* Called from stasis_app_exec thread; no lock needed */
00376    return control->is_done;
00377 }

void control_mark_done ( struct stasis_app_control control  ) 

Definition at line 379 of file control.c.

References stasis_app_control::is_done.

Referenced by stasis_app_control_execute_until_exhausted().

00380 {
00381    control->is_done = 1;
00382 }

int control_prestart_dispatch_all ( struct stasis_app_control control,
struct ast_channel chan 
)

Dispatch all queued prestart commands.

Parameters:
control The control for chan
channel The channel on which commands should be executed
Returns:
The number of commands executed

Definition at line 1055 of file control.c.

References ao2_cleanup, ao2_iterator_destroy(), ao2_iterator_init(), ao2_iterator_next, AO2_ITERATOR_UNLINK, ast_channel_lock, ast_channel_unlock, command_invoke(), and command_prestart_get_container().

Referenced by stasis_app_exec().

01057 {
01058    struct ao2_container *command_queue;
01059    int count = 0;
01060    struct ao2_iterator iter;
01061    struct stasis_app_command *command;
01062 
01063    ast_channel_lock(chan);
01064    command_queue = command_prestart_get_container(chan);
01065    ast_channel_unlock(chan);
01066    if (!command_queue) {
01067       return 0;
01068    }
01069 
01070    iter = ao2_iterator_init(command_queue, AO2_ITERATOR_UNLINK);
01071 
01072    while ((command = ao2_iterator_next(&iter))) {
01073       command_invoke(command, control, chan);
01074       ao2_cleanup(command);
01075       ++count;
01076    }
01077 
01078    ao2_iterator_destroy(&iter);
01079    ao2_cleanup(command_queue);
01080    return count;
01081 }

void control_wait ( struct stasis_app_control control  ) 

Blocks until control's command queue has a command available.

Parameters:
control Control to block on.

Definition at line 1035 of file control.c.

References ao2_container_count(), ao2_lock, ao2_object_get_lockaddr(), ao2_unlock, ast_assert, ast_cond_wait, ast_log, stasis_app_control::command_queue, LOG_ERROR, NULL, and stasis_app_control::wait_cond.

Referenced by stasis_app_exec().

01036 {
01037    if (!control) {
01038       return;
01039    }
01040 
01041    ast_assert(control->command_queue != NULL);
01042 
01043    ao2_lock(control->command_queue);
01044    while (ao2_container_count(control->command_queue) == 0) {
01045       int res = ast_cond_wait(&control->wait_cond,
01046          ao2_object_get_lockaddr(control->command_queue));
01047       if (res < 0) {
01048          ast_log(LOG_ERROR, "Error waiting on command queue\n");
01049          break;
01050       }
01051    }
01052    ao2_unlock(control->command_queue);
01053 }

static struct stasis_app_command* exec_command ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor 
) [static, read]

Definition at line 268 of file control.c.

References exec_command_on_condition(), and NULL.

Referenced by stasis_app_send_command_async().

00271 {
00272    return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
00273 }

static struct stasis_app_command* exec_command_on_condition ( struct stasis_app_control control,
stasis_app_command_cb  command_fn,
void *  data,
command_data_destructor_fn  data_destructor,
app_command_can_exec_cb  can_exec_fn 
) [static, read]

Definition at line 239 of file control.c.

References ao2_link_flags, ao2_lock, ao2_unlock, ast_cond_signal, command_complete(), command_create(), stasis_app_control::command_queue, noop_cb(), NULL, OBJ_NOLOCK, retval, and stasis_app_control::wait_cond.

Referenced by app_send_command_on_condition(), and exec_command().

00243 {
00244    int retval;
00245    struct stasis_app_command *command;
00246 
00247    command_fn = command_fn ? : noop_cb;
00248 
00249    command = command_create(command_fn, data, data_destructor);
00250    if (!command) {
00251       return NULL;
00252    }
00253 
00254    ao2_lock(control->command_queue);
00255    if (can_exec_fn && (retval = can_exec_fn(control))) {
00256       ao2_unlock(control->command_queue);
00257       command_complete(command, retval);
00258       return command;
00259    }
00260 
00261    ao2_link_flags(control->command_queue, command, OBJ_NOLOCK);
00262    ast_cond_signal(&control->wait_cond);
00263    ao2_unlock(control->command_queue);
00264 
00265    return command;
00266 }

static int noop_cb ( struct stasis_app_control control,
struct ast_channel chan,
void *  data 
) [static]

Definition at line 229 of file control.c.

Referenced by exec_command_on_condition().

00231 {
00232    return 0;
00233 }

int stasis_app_control_add_channel_to_bridge ( struct stasis_app_control control,
struct ast_bridge bridge 
)

Add a channel to the bridge.

Parameters:
control Control whose channel should be added to the bridge
bridge Pointer to the bridge
Returns:
non-zero on failure

zero on success

Definition at line 946 of file control.c.

References app_control_can_add_channel_to_bridge(), app_send_command_on_condition(), ast_debug, control_add_channel_to_bridge(), NULL, and stasis_app_control_get_channel_id().

Referenced by ast_ari_bridges_add_channel().

00948 {
00949    ast_debug(3, "%s: Sending channel add_to_bridge command\n",
00950          stasis_app_control_get_channel_id(control));
00951 
00952    return app_send_command_on_condition(
00953       control, control_add_channel_to_bridge, bridge, NULL,
00954       app_control_can_add_channel_to_bridge);
00955 }

int stasis_app_control_add_role ( struct stasis_app_control control,
const char *  role 
)

Apply a bridge role to a channel controlled by a stasis app control.

Parameters:
control Control for res_stasis
role Role to apply
Returns:
0 for success

-1 for error.

Definition at line 358 of file control.c.

References ast_channel_add_bridge_role(), and stasis_app_control::channel.

Referenced by ast_ari_bridges_add_channel().

00359 {
00360    return ast_channel_add_bridge_role(control->channel, role);
00361 }

void stasis_app_control_clear_roles ( struct stasis_app_control control  ) 

Clear bridge roles currently applied to a channel controlled by a stasis app control.

Parameters:
control Control for res_stasis

Definition at line 363 of file control.c.

References ast_channel_clear_bridge_roles(), and stasis_app_control::channel.

Referenced by ast_ari_bridges_add_channel().

00364 {
00365    ast_channel_clear_bridge_roles(control->channel);
00366 }

int stasis_app_control_continue ( struct stasis_app_control control,
const char *  context,
const char *  extension,
int  priority 
)

Exit res_stasis and continue execution in the dialplan.

If the channel is no longer in res_stasis, this function does nothing.

Parameters:
control Control for res_stasis
context An optional context to continue to
extension An optional extension to continue to
priority An optional priority to continue to
Returns:
0 for success

-1 for error.

Definition at line 411 of file control.c.

References app_control_continue(), ast_calloc, ast_copy_string(), ast_free_ptr, stasis_app_control_continue_data::context, stasis_app_control_continue_data::extension, stasis_app_control_continue_data::priority, S_OR, and stasis_app_send_command_async().

Referenced by ast_ari_channels_continue_in_dialplan().

00412 {
00413    struct stasis_app_control_continue_data *continue_data;
00414 
00415    if (!(continue_data = ast_calloc(1, sizeof(*continue_data)))) {
00416       return -1;
00417    }
00418    ast_copy_string(continue_data->context, S_OR(context, ""), sizeof(continue_data->context));
00419    ast_copy_string(continue_data->extension, S_OR(extension, ""), sizeof(continue_data->extension));
00420    if (priority > 0) {
00421       continue_data->priority = priority;
00422    } else {
00423       continue_data->priority = -1;
00424    }
00425 
00426    stasis_app_send_command_async(control, app_control_continue, continue_data, ast_free_ptr);
00427 
00428    return 0;
00429 }

int stasis_app_control_dial ( struct stasis_app_control control,
const char *  endpoint,
const char *  exten,
const char *  context,
int  timeout 
)

Dial an endpoint and bridge it to a channel in res_stasis.

If the channel is no longer in res_stasis, this function does nothing.

Parameters:
control Control for res_stasis
endpoint The endpoint to dial.
exten Extension to dial if no endpoint specified.
context Context to use with extension.
timeout The amount of time to wait for answer, before giving up.
Returns:
0 for success

-1 for error.

Definition at line 328 of file control.c.

References app_control_dial(), ast_calloc, ast_copy_string(), ast_free_ptr, ast_strlen_zero, stasis_app_control_dial_data::endpoint, stasis_app_send_command_async(), and stasis_app_control_dial_data::timeout.

00330 {
00331    struct stasis_app_control_dial_data *dial_data;
00332 
00333    if (!(dial_data = ast_calloc(1, sizeof(*dial_data)))) {
00334       return -1;
00335    }
00336 
00337    if (!ast_strlen_zero(endpoint)) {
00338       ast_copy_string(dial_data->endpoint, endpoint, sizeof(dial_data->endpoint));
00339    } else if (!ast_strlen_zero(exten) && !ast_strlen_zero(context)) {
00340       snprintf(dial_data->endpoint, sizeof(dial_data->endpoint), "Local/%s@%s", exten, context);
00341    } else {
00342       return -1;
00343    }
00344 
00345    if (timeout > 0) {
00346       dial_data->timeout = timeout * 1000;
00347    } else if (timeout == -1) {
00348       dial_data->timeout = -1;
00349    } else {
00350       dial_data->timeout = 30000;
00351    }
00352 
00353    stasis_app_send_command_async(control, app_control_dial, dial_data, ast_free_ptr);
00354 
00355    return 0;
00356 }

int stasis_app_control_dtmf ( struct stasis_app_control control,
const char *  dtmf,
int  before,
int  between,
unsigned int  duration,
int  after 
)

Send DTMF to the channel associated with this control.

Parameters:
control Control for res_stasis.
dtmf DTMF string.
before Amount of time to wait before sending DTMF digits.
between Amount of time between each DTMF digit.
duration Amount of time each DTMF digit lasts for.
after Amount of time to wait after sending DTMF digits.
Returns:
0 for success.

-1 for error.

Definition at line 493 of file control.c.

References stasis_app_control_dtmf_data::after, app_control_dtmf(), ast_calloc, ast_free_ptr, stasis_app_control_dtmf_data::before, stasis_app_control_dtmf_data::between, stasis_app_control_dtmf_data::dtmf, stasis_app_control_dtmf_data::duration, and stasis_app_send_command_async().

Referenced by ast_ari_channels_send_dtmf().

00494 {
00495    struct stasis_app_control_dtmf_data *dtmf_data;
00496 
00497    if (!(dtmf_data = ast_calloc(1, sizeof(*dtmf_data) + strlen(dtmf) + 1))) {
00498       return -1;
00499    }
00500 
00501    dtmf_data->before = before;
00502    dtmf_data->between = between;
00503    dtmf_data->duration = duration;
00504    dtmf_data->after = after;
00505    strcpy(dtmf_data->dtmf, dtmf);
00506 
00507    stasis_app_send_command_async(control, app_control_dtmf, dtmf_data, ast_free_ptr);
00508 
00509    return 0;
00510 }

const char* stasis_app_control_get_channel_id ( const struct stasis_app_control control  ) 

struct ast_channel_snapshot* stasis_app_control_get_snapshot ( const struct stasis_app_control control  )  [read]

Returns the most recent snapshot for the associated channel.

The returned pointer is AO2 managed, so ao2_cleanup() when you're done.

Parameters:
control Control for res_stasis.
Returns:
Most recent snapshot. ao2_cleanup() when done.

NULL if channel isn't in cache.

Definition at line 722 of file control.c.

References ao2_cleanup, ao2_ref, ast_assert, ast_channel_cache(), ast_channel_snapshot_type(), NULL, RAII_VAR, stasis_app_control_get_channel_id(), stasis_cache_get(), and stasis_message_data().

Referenced by ari_bridges_play_helper(), ari_channels_handle_play(), and ast_ari_channels_continue_in_dialplan().

00724 {
00725    RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
00726    struct ast_channel_snapshot *snapshot;
00727 
00728    msg = stasis_cache_get(ast_channel_cache(), ast_channel_snapshot_type(),
00729       stasis_app_control_get_channel_id(control));
00730    if (!msg) {
00731       return NULL;
00732    }
00733 
00734    snapshot = stasis_message_data(msg);
00735    ast_assert(snapshot != NULL);
00736 
00737    ao2_ref(snapshot, +1);
00738    return snapshot;
00739 }

void stasis_app_control_hold ( struct stasis_app_control control  ) 

Place the channel associated with the control on hold.

Parameters:
control Control for res_stasis.

Definition at line 614 of file control.c.

References app_control_hold(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_hold().

00615 {
00616    stasis_app_send_command_async(control, app_control_hold, NULL, NULL);
00617 }

void stasis_app_control_moh_start ( struct stasis_app_control control,
const char *  moh_class 
)

Play music on hold to a channel (does not affect hold status).

Parameters:
control Control for res_stasis.
moh_class class of music on hold to play (NULL allowed)

Definition at line 646 of file control.c.

References app_control_moh_start(), ast_free_ptr, ast_strdup, ast_strlen_zero, NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_start_moh().

00647 {
00648    char *data = NULL;
00649 
00650    if (!ast_strlen_zero(moh_class)) {
00651       data = ast_strdup(moh_class);
00652    }
00653 
00654    stasis_app_send_command_async(control, app_control_moh_start, data, ast_free_ptr);
00655 }

void stasis_app_control_moh_stop ( struct stasis_app_control control  ) 

Stop playing music on hold to a channel (does not affect hold status).

Parameters:
control Control for res_stasis.

Definition at line 664 of file control.c.

References app_control_moh_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_stop_moh().

00665 {
00666    stasis_app_send_command_async(control, app_control_moh_stop, NULL, NULL);
00667 }

int stasis_app_control_mute ( struct stasis_app_control control,
unsigned int  direction,
enum ast_frame_type  frametype 
)

Mute the channel associated with this control.

Parameters:
control Control for res_stasis.
direction The direction in which the audio should be muted.
frametype The type of stream that should be muted.
Returns:
0 for success

-1 for error.

Definition at line 558 of file control.c.

References app_control_mute(), ast_calloc, ast_free_ptr, stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and stasis_app_send_command_async().

Referenced by ast_ari_channels_mute().

00559 {
00560    struct stasis_app_control_mute_data *mute_data;
00561 
00562    if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
00563       return -1;
00564    }
00565 
00566    mute_data->direction = direction;
00567    mute_data->frametype = frametype;
00568 
00569    stasis_app_send_command_async(control, app_control_mute, mute_data, ast_free_ptr);
00570 
00571    return 0;
00572 }

void stasis_app_control_publish ( struct stasis_app_control control,
struct stasis_message message 
)

Publish a message to the control's channel's topic.

Parameters:
control Control to publish to
message Message to publish

Definition at line 999 of file control.c.

References ast_channel_topic(), stasis_app_control::channel, and stasis_publish().

Referenced by playback_publish(), and recording_publish().

01001 {
01002    if (!control || !control->channel || !message) {
01003       return;
01004    }
01005    stasis_publish(ast_channel_topic(control->channel), message);
01006 }

int stasis_app_control_queue_control ( struct stasis_app_control control,
enum ast_control_frame_type  frame_type 
)

Queue a control frame without payload.

Parameters:
control Control to publish to.
frame_type type of control frame.
Returns:
zero on success

non-zero on failure

Definition at line 1008 of file control.c.

References ast_queue_control(), and stasis_app_control::channel.

Referenced by playback_forward(), playback_pause(), playback_restart(), playback_reverse(), playback_stop(), playback_unpause(), recording_cancel(), recording_mute(), recording_pause(), recording_stop(), recording_unmute(), and recording_unpause().

01010 {
01011    return ast_queue_control(control->channel, frame_type);
01012 }

int stasis_app_control_redirect ( struct stasis_app_control control,
const char *  endpoint 
)

Redirect a channel in res_stasis to a particular endpoint.

Parameters:
control Control for res_stasis
endpoint The endpoint transfer string where the channel should be sent to
Returns:
0 for success

-1 for error

Definition at line 450 of file control.c.

References app_control_redirect(), ast_free_ptr, ast_strdup, and stasis_app_send_command_async().

Referenced by ast_ari_channels_redirect().

00451 {
00452    char *endpoint_data = ast_strdup(endpoint);
00453 
00454    if (!endpoint_data) {
00455       return -1;
00456    }
00457 
00458    stasis_app_send_command_async(control, app_control_redirect, endpoint_data, ast_free_ptr);
00459 
00460    return 0;
00461 }

void stasis_app_control_register_add_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Registers an add channel to bridge rule.

Parameters:
control Control object
rule The rule to register

Definition at line 189 of file control.c.

References stasis_app_control::add_rules, and app_control_register_rule().

Referenced by stasis_app_control_record().

00192 {
00193    return app_control_register_rule(control, &control->add_rules, rule);
00194 }

void stasis_app_control_register_remove_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Registers a remove channel from bridge rule.

Parameters:
control Control object
rule The rule to register

Definition at line 203 of file control.c.

References app_control_register_rule(), and stasis_app_control::remove_rules.

00206 {
00207    return app_control_register_rule(control, &control->remove_rules, rule);
00208 }

int stasis_app_control_remove_channel_from_bridge ( struct stasis_app_control control,
struct ast_bridge bridge 
)

Remove a channel from the bridge.

Parameters:
control Control whose channel should be removed from the bridge
bridge Pointer to the bridge
Returns:
non-zero on failure

zero on success

Definition at line 983 of file control.c.

References app_control_can_remove_channel_from_bridge(), app_control_remove_channel_from_bridge(), app_send_command_on_condition(), ast_debug, NULL, and stasis_app_control_get_channel_id().

Referenced by ast_ari_bridges_remove_channel().

00985 {
00986    ast_debug(3, "%s: Sending channel remove_from_bridge command\n",
00987          stasis_app_control_get_channel_id(control));
00988    return app_send_command_on_condition(
00989       control, app_control_remove_channel_from_bridge, bridge, NULL,
00990       app_control_can_remove_channel_from_bridge);
00991 }

int stasis_app_control_ring ( struct stasis_app_control control  ) 

Indicate ringing to the channel associated with this control.

Parameters:
control Control for res_stasis.
Returns:
0 for success.

-1 for error.

Definition at line 520 of file control.c.

References app_control_ring(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_ring().

00521 {
00522    stasis_app_send_command_async(control, app_control_ring, NULL, NULL);
00523 
00524    return 0;
00525 }

int stasis_app_control_ring_stop ( struct stasis_app_control control  ) 

Stop locally generated ringing on the channel associated with this control.

Parameters:
control Control for res_stasis.
Returns:
0 for success.

-1 for error.

Definition at line 535 of file control.c.

References app_control_ring_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_ring_stop().

00536 {
00537    stasis_app_send_command_async(control, app_control_ring_stop, NULL, NULL);
00538 
00539    return 0;
00540 }

int stasis_app_control_set_channel_var ( struct stasis_app_control control,
const char *  variable,
const char *  value 
)

Set a variable on the channel associated with this control to value.

Parameters:
control Control for res_stasis.
variable The name of the variable
value The value to set the variable to
Returns:
0 for success.

-1 for error.

Definition at line 601 of file control.c.

References stasis_app_control::channel, and pbx_builtin_setvar_helper().

Referenced by ast_ari_channels_set_channel_var().

00602 {
00603    return pbx_builtin_setvar_helper(control->channel, variable, value);
00604 }

void stasis_app_control_silence_start ( struct stasis_app_control control  ) 

Start playing silence to a channel.

Parameters:
control Control for res_stasis.

Definition at line 698 of file control.c.

References app_control_silence_start(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_start_silence().

void stasis_app_control_silence_stop ( struct stasis_app_control control  ) 

Stop playing silence to a channel.

Parameters:
control Control for res_stasis.

Definition at line 717 of file control.c.

References app_control_silence_stop(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_stop_silence().

void stasis_app_control_unhold ( struct stasis_app_control control  ) 

Remove the channel associated with the control from hold.

Parameters:
control Control for res_stasis.

Definition at line 627 of file control.c.

References app_control_unhold(), NULL, and stasis_app_send_command_async().

Referenced by ast_ari_channels_unhold().

00628 {
00629    stasis_app_send_command_async(control, app_control_unhold, NULL, NULL);
00630 }

int stasis_app_control_unmute ( struct stasis_app_control control,
unsigned int  direction,
enum ast_frame_type  frametype 
)

Unmute the channel associated with this control.

Parameters:
control Control for res_stasis.
direction The direction in which the audio should be unmuted.
frametype The type of stream that should be unmuted.
Returns:
0 for success

-1 for error.

Definition at line 585 of file control.c.

References app_control_unmute(), ast_calloc, ast_free_ptr, stasis_app_control_mute_data::direction, stasis_app_control_mute_data::frametype, and stasis_app_send_command_async().

Referenced by ast_ari_channels_unmute().

00586 {
00587    struct stasis_app_control_mute_data *mute_data;
00588 
00589    if (!(mute_data = ast_calloc(1, sizeof(*mute_data)))) {
00590       return -1;
00591    }
00592 
00593    mute_data->direction = direction;
00594    mute_data->frametype = frametype;
00595 
00596    stasis_app_send_command_async(control, app_control_unmute, mute_data, ast_free_ptr);
00597 
00598    return 0;
00599 }

void stasis_app_control_unregister_add_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

UnRegister an add channel to bridge rule.

Parameters:
control Control object
rule The rule to unregister

Definition at line 196 of file control.c.

References stasis_app_control::add_rules, and app_control_unregister_rule().

Referenced by record_file(), and recording_fail().

00199 {
00200    app_control_unregister_rule(control, &control->add_rules, rule);
00201 }

void stasis_app_control_unregister_remove_rule ( struct stasis_app_control control,
struct stasis_app_control_rule rule 
)

Unregisters a remove channel from bridge rule.

Parameters:
control Control object
rule The rule to unregister

Definition at line 210 of file control.c.

References app_control_unregister_rule(), and stasis_app_control::remove_rules.

00213 {
00214    app_control_unregister_rule(control, &control->remove_rules, rule);
00215 }

struct ast_bridge* stasis_app_get_bridge ( struct stasis_app_control control  )  [read]

Gets the bridge currently associated with a control object.

Since:
12
Note:
If the bridge returned by this function is to be held for any length of time, its refcount should be incremented until the caller is finished with it.
Parameters:
control Control object for the channel to query.
Returns:
Associated ast_bridge.

NULL if not associated with a bridge.

Definition at line 785 of file control.c.

References stasis_app_control::bridge, lock, NULL, and SCOPED_AO2LOCK.

Referenced by app_control_continue(), app_control_remove_channel_from_bridge(), ast_ari_bridges_remove_channel(), control_add_channel_to_bridge(), play_uri(), record_file(), and stasis_app_exec().

00786 {
00787    if (!control) {
00788       return NULL;
00789    } else {
00790       SCOPED_AO2LOCK(lock, control);
00791       return control->bridge;
00792    }
00793 }

int stasis_app_send_command ( struct stasis_app_control control,
stasis_app_command_cb  command,
void *  data,
command_data_destructor_fn  data_destructor 
)

Invokes a command on a control's channel.

Since:
12 This function dispatches the command to be executed in the context of stasis_app_exec(), so this command will block waiting for the results of the command.
Parameters:
control Control object for the channel to send the command to.
command Command function to execute.
data Optional data to pass along with the control function.
data_destructor Optional function which will be called on the data in either the event of command completion or failure to schedule or complete the command
Returns:
zero on success.

error code otherwise.

Definition at line 761 of file control.c.

References app_send_command_on_condition(), and NULL.

Referenced by stasis_app_control_answer().

00763 {
00764    return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
00765 }

int stasis_app_send_command_async ( struct stasis_app_control control,
stasis_app_command_cb  command,
void *  data,
command_data_destructor_fn  data_destructor 
)

Asynchronous version of stasis_app_send_command().

Since:
12 This function enqueues a command for execution, but returns immediately without waiting for the response.
Parameters:
control Control object for the channel to send the command to.
command Command function to execute.
data Optional data to pass along with the control function.
data_destructor Optional function which will be called on the data in either the event of command completion or failure to schedule or complete the command
Returns:
0 on success.

Non-zero on error.

Definition at line 767 of file control.c.

References ao2_cleanup, exec_command(), NULL, and RAII_VAR.

Referenced by bridge_after_cb(), stasis_app_control_continue(), stasis_app_control_dial(), stasis_app_control_dtmf(), stasis_app_control_hold(), stasis_app_control_moh_start(), stasis_app_control_moh_stop(), stasis_app_control_mute(), stasis_app_control_play_uri(), stasis_app_control_record(), stasis_app_control_redirect(), stasis_app_control_ring(), stasis_app_control_ring_stop(), stasis_app_control_silence_start(), stasis_app_control_silence_stop(), stasis_app_control_unhold(), and stasis_app_control_unmute().

00770 {
00771    RAII_VAR(struct stasis_app_command *, command, NULL, ao2_cleanup);
00772 
00773    if (control == NULL) {
00774       return -1;
00775    }
00776 
00777    command = exec_command(control, command_fn, data, data_destructor);
00778    if (!command) {
00779       return -1;
00780    }
00781 
00782    return 0;
00783 }


Generated on Thu Apr 16 06:30:30 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6