control.h File Reference

Internal API for the Stasis application controller. More...

#include "asterisk/stasis_app.h"

Include dependency graph for control.h:

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

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.
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.
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.


Detailed Description

Internal API for the Stasis application controller.

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

Definition in file control.h.


Function Documentation

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 }

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 }


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