control.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2013, Digium, Inc.
00005  *
00006  * David M. Lee, II <dlee@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Stasis application control support.
00022  *
00023  * \author David M. Lee, II <dlee@digium.com>
00024  */
00025 
00026 #include "asterisk.h"
00027 
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 431718 $")
00029 
00030 #include "asterisk/stasis_channels.h"
00031 
00032 #include "command.h"
00033 #include "control.h"
00034 #include "app.h"
00035 #include "asterisk/dial.h"
00036 #include "asterisk/bridge.h"
00037 #include "asterisk/bridge_after.h"
00038 #include "asterisk/bridge_basic.h"
00039 #include "asterisk/frame.h"
00040 #include "asterisk/pbx.h"
00041 #include "asterisk/musiconhold.h"
00042 #include "asterisk/app.h"
00043 
00044 AST_LIST_HEAD(app_control_rules, stasis_app_control_rule);
00045 
00046 struct stasis_app_control {
00047    ast_cond_t wait_cond;
00048    /*! Queue of commands to dispatch on the channel */
00049    struct ao2_container *command_queue;
00050    /*!
00051     * The associated channel.
00052     * Be very careful with the threading associated w/ manipulating
00053     * the channel.
00054     */
00055    struct ast_channel *channel;
00056    /*!
00057     * When a channel is in a bridge, the bridge that it is in.
00058     */
00059    struct ast_bridge *bridge;
00060    /*!
00061     * Holding place for channel's PBX while imparted to a bridge.
00062     */
00063    struct ast_pbx *pbx;
00064    /*!
00065     * A list of rules to check before adding a channel to a bridge.
00066     */
00067    struct app_control_rules add_rules;
00068    /*!
00069     * A list of rules to check before removing a channel from a bridge.
00070     */
00071    struct app_control_rules remove_rules;
00072    /*!
00073     * Silence generator, when silence is being generated.
00074     */
00075    struct ast_silence_generator *silgen;
00076    /*!
00077     * The app for which this control was created
00078     */
00079    struct stasis_app *app;
00080    /*!
00081     * When set, /c app_stasis should exit and continue in the dialplan.
00082     */
00083    int is_done:1;
00084 };
00085 
00086 static void control_dtor(void *obj)
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 }
00101 
00102 struct stasis_app_control *control_create(struct ast_channel *channel, struct stasis_app *app)
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 }
00136 
00137 static void app_control_register_rule(
00138    const struct stasis_app_control *control,
00139    struct app_control_rules *list, struct stasis_app_control_rule *obj)
00140 {
00141    SCOPED_AO2LOCK(lock, control->command_queue);
00142    AST_LIST_INSERT_TAIL(list, obj, next);
00143 }
00144 
00145 static void app_control_unregister_rule(
00146    const struct stasis_app_control *control,
00147    struct app_control_rules *list, struct stasis_app_control_rule *obj)
00148 {
00149    struct stasis_app_control_rule *rule;
00150    SCOPED_AO2LOCK(lock, control->command_queue);
00151    AST_RWLIST_TRAVERSE_SAFE_BEGIN(list, rule, next) {
00152       if (rule == obj) {
00153          AST_RWLIST_REMOVE_CURRENT(next);
00154          break;
00155       }
00156    }
00157    AST_RWLIST_TRAVERSE_SAFE_END;
00158 }
00159 
00160 /*!
00161  * \internal
00162  * \brief Checks to make sure each rule in the given list passes.
00163  *
00164  * \details Loops over a list of rules checking for rejections or failures.
00165  *          If one rule fails its resulting error code is returned.
00166  *
00167  * \note Command queue should be locked before calling this function.
00168  *
00169  * \param control The stasis application control
00170  * \param list The list of rules to check
00171  *
00172  * \retval 0 if all rules pass
00173  * \retval non-zero error code if a rule fails
00174  */
00175 static enum stasis_app_control_channel_result app_control_check_rules(
00176    const struct stasis_app_control *control,
00177    struct app_control_rules *list)
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 }
00188 
00189 void stasis_app_control_register_add_rule(
00190    struct stasis_app_control *control,
00191    struct stasis_app_control_rule *rule)
00192 {
00193    return app_control_register_rule(control, &control->add_rules, rule);
00194 }
00195 
00196 void stasis_app_control_unregister_add_rule(
00197    struct stasis_app_control *control,
00198    struct stasis_app_control_rule *rule)
00199 {
00200    app_control_unregister_rule(control, &control->add_rules, rule);
00201 }
00202 
00203 void stasis_app_control_register_remove_rule(
00204    struct stasis_app_control *control,
00205    struct stasis_app_control_rule *rule)
00206 {
00207    return app_control_register_rule(control, &control->remove_rules, rule);
00208 }
00209 
00210 void stasis_app_control_unregister_remove_rule(
00211    struct stasis_app_control *control,
00212    struct stasis_app_control_rule *rule)
00213 {
00214    app_control_unregister_rule(control, &control->remove_rules, rule);
00215 }
00216 
00217 static int app_control_can_add_channel_to_bridge(
00218    struct stasis_app_control *control)
00219 {
00220    return app_control_check_rules(control, &control->add_rules);
00221 }
00222 
00223 static int app_control_can_remove_channel_from_bridge(
00224    struct stasis_app_control *control)
00225 {
00226    return app_control_check_rules(control, &control->remove_rules);
00227 }
00228 
00229 static int noop_cb(struct stasis_app_control *control,
00230    struct ast_channel *chan, void *data)
00231 {
00232    return 0;
00233 }
00234 
00235 /*! Callback type to see if the command can execute
00236     note: command_queue is locked during callback */
00237 typedef int (*app_command_can_exec_cb)(struct stasis_app_control *control);
00238 
00239 static struct stasis_app_command *exec_command_on_condition(
00240    struct stasis_app_control *control, stasis_app_command_cb command_fn,
00241    void *data, command_data_destructor_fn data_destructor,
00242    app_command_can_exec_cb can_exec_fn)
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 }
00267 
00268 static struct stasis_app_command *exec_command(
00269    struct stasis_app_control *control, stasis_app_command_cb command_fn,
00270    void *data, command_data_destructor_fn data_destructor)
00271 {
00272    return exec_command_on_condition(control, command_fn, data, data_destructor, NULL);
00273 }
00274 
00275 struct stasis_app_control_dial_data {
00276    char endpoint[AST_CHANNEL_NAME];
00277    int timeout;
00278 };
00279 
00280 static int app_control_dial(struct stasis_app_control *control,
00281    struct ast_channel *chan, void *data)
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 }
00327 
00328 int stasis_app_control_dial(struct stasis_app_control *control, const char *endpoint, const char *exten, const char *context,
00329              int 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 }
00357 
00358 int stasis_app_control_add_role(struct stasis_app_control *control, const char *role)
00359 {
00360    return ast_channel_add_bridge_role(control->channel, role);
00361 }
00362 
00363 void stasis_app_control_clear_roles(struct stasis_app_control *control)
00364 {
00365    ast_channel_clear_bridge_roles(control->channel);
00366 }
00367 
00368 int control_command_count(struct stasis_app_control *control)
00369 {
00370    return ao2_container_count(control->command_queue);
00371 }
00372 
00373 int control_is_done(struct stasis_app_control *control)
00374 {
00375    /* Called from stasis_app_exec thread; no lock needed */
00376    return control->is_done;
00377 }
00378 
00379 void control_mark_done(struct stasis_app_control *control)
00380 {
00381    control->is_done = 1;
00382 }
00383 
00384 struct stasis_app_control_continue_data {
00385    char context[AST_MAX_CONTEXT];
00386    char extension[AST_MAX_EXTENSION];
00387    int priority;
00388 };
00389 
00390 static int app_control_continue(struct stasis_app_control *control,
00391    struct ast_channel *chan, void *data)
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 }
00410 
00411 int stasis_app_control_continue(struct stasis_app_control *control, const char *context, const char *extension, int priority)
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 }
00430 
00431 static int app_control_redirect(struct stasis_app_control *control,
00432    struct ast_channel *chan, void *data)
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 }
00449 
00450 int stasis_app_control_redirect(struct stasis_app_control *control, const char *endpoint)
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 }
00462 
00463 struct stasis_app_control_dtmf_data {
00464    int before;
00465    int between;
00466    unsigned int duration;
00467    int after;
00468    char dtmf[];
00469 };
00470 
00471 static int app_control_dtmf(struct stasis_app_control *control,
00472    struct ast_channel *chan, void *data)
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 }
00492 
00493 int stasis_app_control_dtmf(struct stasis_app_control *control, const char *dtmf, int before, int between, unsigned int duration, int after)
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 }
00511 
00512 static int app_control_ring(struct stasis_app_control *control,
00513    struct ast_channel *chan, void *data)
00514 {
00515    ast_indicate(control->channel, AST_CONTROL_RINGING);
00516 
00517    return 0;
00518 }
00519 
00520 int stasis_app_control_ring(struct stasis_app_control *control)
00521 {
00522    stasis_app_send_command_async(control, app_control_ring, NULL, NULL);
00523 
00524    return 0;
00525 }
00526 
00527 static int app_control_ring_stop(struct stasis_app_control *control,
00528    struct ast_channel *chan, void *data)
00529 {
00530    ast_indicate(control->channel, -1);
00531 
00532    return 0;
00533 }
00534 
00535 int stasis_app_control_ring_stop(struct stasis_app_control *control)
00536 {
00537    stasis_app_send_command_async(control, app_control_ring_stop, NULL, NULL);
00538 
00539    return 0;
00540 }
00541 
00542 struct stasis_app_control_mute_data {
00543    enum ast_frame_type frametype;
00544    unsigned int direction;
00545 };
00546 
00547 static int app_control_mute(struct stasis_app_control *control,
00548    struct ast_channel *chan, void *data)
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 }
00557 
00558 int stasis_app_control_mute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
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 }
00573 
00574 static int app_control_unmute(struct stasis_app_control *control,
00575    struct ast_channel *chan, void *data)
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 }
00584 
00585 int stasis_app_control_unmute(struct stasis_app_control *control, unsigned int direction, enum ast_frame_type frametype)
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 }
00600 
00601 int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value)
00602 {
00603    return pbx_builtin_setvar_helper(control->channel, variable, value);
00604 }
00605 
00606 static int app_control_hold(struct stasis_app_control *control,
00607    struct ast_channel *chan, void *data)
00608 {
00609    ast_indicate(control->channel, AST_CONTROL_HOLD);
00610 
00611    return 0;
00612 }
00613 
00614 void stasis_app_control_hold(struct stasis_app_control *control)
00615 {
00616    stasis_app_send_command_async(control, app_control_hold, NULL, NULL);
00617 }
00618 
00619 static int app_control_unhold(struct stasis_app_control *control,
00620    struct ast_channel *chan, void *data)
00621 {
00622    ast_indicate(control->channel, AST_CONTROL_UNHOLD);
00623 
00624    return 0;
00625 }
00626 
00627 void stasis_app_control_unhold(struct stasis_app_control *control)
00628 {
00629    stasis_app_send_command_async(control, app_control_unhold, NULL, NULL);
00630 }
00631 
00632 static int app_control_moh_start(struct stasis_app_control *control,
00633    struct ast_channel *chan, void *data)
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 }
00645 
00646 void stasis_app_control_moh_start(struct stasis_app_control *control, const char *moh_class)
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 }
00656 
00657 static int app_control_moh_stop(struct stasis_app_control *control,
00658    struct ast_channel *chan, void *data)
00659 {
00660    ast_moh_stop(chan);
00661    return 0;
00662 }
00663 
00664 void stasis_app_control_moh_stop(struct stasis_app_control *control)
00665 {
00666    stasis_app_send_command_async(control, app_control_moh_stop, NULL, NULL);
00667 }
00668 
00669 static int app_control_silence_start(struct stasis_app_control *control,
00670    struct ast_channel *chan, void *data)
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 }
00697 
00698 void stasis_app_control_silence_start(struct stasis_app_control *control)
00699 {
00700    stasis_app_send_command_async(control, app_control_silence_start, NULL, NULL);
00701 }
00702 
00703 static int app_control_silence_stop(struct stasis_app_control *control,
00704    struct ast_channel *chan, void *data)
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 }
00716 
00717 void stasis_app_control_silence_stop(struct stasis_app_control *control)
00718 {
00719    stasis_app_send_command_async(control, app_control_silence_stop, NULL, NULL);
00720 }
00721 
00722 struct ast_channel_snapshot *stasis_app_control_get_snapshot(
00723    const struct stasis_app_control *control)
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 }
00740 
00741 static int app_send_command_on_condition(struct stasis_app_control *control,
00742                 stasis_app_command_cb command_fn, void *data,
00743                 command_data_destructor_fn data_destructor,
00744                 app_command_can_exec_cb can_exec_fn)
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 }
00760 
00761 int stasis_app_send_command(struct stasis_app_control *control,
00762    stasis_app_command_cb command_fn, void *data, command_data_destructor_fn data_destructor)
00763 {
00764    return app_send_command_on_condition(control, command_fn, data, data_destructor, NULL);
00765 }
00766 
00767 int stasis_app_send_command_async(struct stasis_app_control *control,
00768    stasis_app_command_cb command_fn, void *data,
00769    command_data_destructor_fn data_destructor)
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 }
00784 
00785 struct ast_bridge *stasis_app_get_bridge(struct stasis_app_control *control)
00786 {
00787    if (!control) {
00788       return NULL;
00789    } else {
00790       SCOPED_AO2LOCK(lock, control);
00791       return control->bridge;
00792    }
00793 }
00794 
00795 static int bridge_channel_depart(struct stasis_app_control *control,
00796    struct ast_channel *chan, void *data)
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 }
00817 
00818 static void bridge_after_cb(struct ast_channel *chan, void *data)
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 }
00861 
00862 static void bridge_after_cb_failed(enum ast_bridge_after_cb_reason reason,
00863    void *data)
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 }
00872 
00873 int control_add_channel_to_bridge(
00874    struct stasis_app_control *control,
00875    struct ast_channel *chan, void *data)
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 }
00945 
00946 int stasis_app_control_add_channel_to_bridge(
00947    struct stasis_app_control *control, struct ast_bridge *bridge)
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 }
00956 
00957 static int app_control_remove_channel_from_bridge(
00958    struct stasis_app_control *control,
00959    struct ast_channel *chan, void *data)
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 }
00982 
00983 int stasis_app_control_remove_channel_from_bridge(
00984    struct stasis_app_control *control, struct ast_bridge *bridge)
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 }
00992 
00993 const char *stasis_app_control_get_channel_id(
00994    const struct stasis_app_control *control)
00995 {
00996    return ast_channel_uniqueid(control->channel);
00997 }
00998 
00999 void stasis_app_control_publish(
01000    struct stasis_app_control *control, struct stasis_message *message)
01001 {
01002    if (!control || !control->channel || !message) {
01003       return;
01004    }
01005    stasis_publish(ast_channel_topic(control->channel), message);
01006 }
01007 
01008 int stasis_app_control_queue_control(struct stasis_app_control *control,
01009    enum ast_control_frame_type frame_type)
01010 {
01011    return ast_queue_control(control->channel, frame_type);
01012 }
01013 
01014 int control_dispatch_all(struct stasis_app_control *control,
01015    struct ast_channel *chan)
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 }
01034 
01035 void control_wait(struct stasis_app_control *control)
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 }
01054 
01055 int control_prestart_dispatch_all(struct stasis_app_control *control,
01056    struct ast_channel *chan)
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 }
01082 
01083 struct stasis_app *control_app(struct stasis_app_control *control)
01084 {
01085    return control->app;
01086 }

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