diff options
author | Joshua Colp <jcolp@digium.com> | 2016-04-06 05:43:36 -0500 |
---|---|---|
committer | Gerrit Code Review <gerrit2@gerrit.digium.api> | 2016-04-06 05:43:36 -0500 |
commit | 3b71f09bb7778ee48b2af13960a251a4b9934530 (patch) | |
tree | e7ccf91747c4ae73ba9d8de4d9d9082e6544ecac /res/ari | |
parent | 4d06a4f366f571014f99a516c2a2d731563650c3 (diff) | |
parent | dd48d60c5ba239f76b054b1bb6c1e17c68537497 (diff) |
Merge "ARI: Add method to create a new channel."
Diffstat (limited to 'res/ari')
-rw-r--r-- | res/ari/resource_channels.c | 109 | ||||
-rw-r--r-- | res/ari/resource_channels.h | 34 |
2 files changed, 143 insertions, 0 deletions
diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c index 297560175..1954d6bf9 100644 --- a/res/ari/resource_channels.c +++ b/res/ari/resource_channels.c @@ -1461,3 +1461,112 @@ void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers, args->snoop_id, response); } + +struct ari_channel_thread_data { + struct ast_channel *chan; + struct ast_str *stasis_stuff; +}; + +static void chan_data_destroy(struct ari_channel_thread_data *chan_data) +{ + ast_free(chan_data->stasis_stuff); + ast_hangup(chan_data->chan); + ast_free(chan_data); +} + +/*! + * \brief Thread that owns stasis-created channel. + * + * The channel enters into a Stasis application immediately upon creation. In this + * way, the channel can be manipulated by the Stasis application. Once the channel + * exits the Stasis application, it is hung up. + */ +static void *ari_channel_thread(void *data) +{ + struct ari_channel_thread_data *chan_data = data; + struct ast_app *stasis_app; + + stasis_app = pbx_findapp("Stasis"); + if (!stasis_app) { + ast_log(LOG_ERROR, "Stasis dialplan application is not registered"); + chan_data_destroy(chan_data); + return NULL; + } + + pbx_exec(chan_data->chan, stasis_app, ast_str_buffer(chan_data->stasis_stuff)); + + chan_data_destroy(chan_data); + + return NULL; +} + +void ast_ari_channels_create(struct ast_variable *headers, + struct ast_ari_channels_create_args *args, + struct ast_ari_response *response) +{ + struct ast_assigned_ids assignedids = { + .uniqueid = args->channel_id, + .uniqueid2 = args->other_channel_id, + }; + struct ari_channel_thread_data *chan_data; + struct ast_channel_snapshot *snapshot; + pthread_t thread; + char *dialtech; + char dialdevice[AST_CHANNEL_NAME]; + char *stuff; + int cause; + struct ast_format_cap *request_cap; + struct ast_channel *originator; + + chan_data = ast_calloc(1, sizeof(*chan_data)); + if (!chan_data) { + ast_ari_response_alloc_failed(response); + return; + } + + chan_data->stasis_stuff = ast_str_create(32); + if (!chan_data->stasis_stuff) { + ast_ari_response_alloc_failed(response); + chan_data_destroy(chan_data); + return; + } + + ast_str_append(&chan_data->stasis_stuff, 0, "%s", args->app); + if (!ast_strlen_zero(args->app_args)) { + ast_str_append(&chan_data->stasis_stuff, 0, ",%s", args->app_args); + } + + dialtech = ast_strdupa(args->endpoint); + if ((stuff = strchr(dialtech, '/'))) { + *stuff++ = '\0'; + ast_copy_string(dialdevice, stuff, sizeof(dialdevice)); + } + + originator = ast_channel_get_by_name(args->originator); + if (originator) { + request_cap = ao2_bump(ast_channel_nativeformats(originator)); + } else { + request_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT); + ast_format_cap_append_by_type(request_cap, AST_MEDIA_TYPE_AUDIO); + } + + chan_data->chan = ast_request(dialtech, request_cap, &assignedids, originator, dialdevice, &cause); + ao2_cleanup(request_cap); + ast_channel_cleanup(originator); + if (!chan_data->chan) { + ast_ari_response_alloc_failed(response); + chan_data_destroy(chan_data); + return; + } + + snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan_data->chan)); + + if (ast_pthread_create_detached(&thread, NULL, ari_channel_thread, chan_data)) { + ast_ari_response_alloc_failed(response); + chan_data_destroy(chan_data); + } else { + ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL)); + } + + ao2_ref(snapshot, -1); +} diff --git a/res/ari/resource_channels.h b/res/ari/resource_channels.h index 4d3ad5f8b..bd34e0673 100644 --- a/res/ari/resource_channels.h +++ b/res/ari/resource_channels.h @@ -100,6 +100,40 @@ int ast_ari_channels_originate_parse_body( * \param[out] response HTTP response */ void ast_ari_channels_originate(struct ast_variable *headers, struct ast_ari_channels_originate_args *args, struct ast_ari_response *response); +/*! Argument struct for ast_ari_channels_create() */ +struct ast_ari_channels_create_args { + /*! Endpoint for channel communication */ + const char *endpoint; + /*! Stasis Application to place channel into */ + const char *app; + /*! The application arguments to pass to the Stasis application provided by 'app'. Mutually exclusive with 'context', 'extension', 'priority', and 'label'. */ + const char *app_args; + /*! The unique id to assign the channel on creation. */ + const char *channel_id; + /*! The unique id to assign the second channel when using local channels. */ + const char *other_channel_id; + /*! Unique ID of the calling channel */ + const char *originator; +}; +/*! + * \brief Body parsing function for /channels/create. + * \param body The JSON body from which to parse parameters. + * \param[out] args The args structure to parse into. + * \retval zero on success + * \retval non-zero on failure + */ +int ast_ari_channels_create_parse_body( + struct ast_json *body, + struct ast_ari_channels_create_args *args); + +/*! + * \brief Create channel. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void ast_ari_channels_create(struct ast_variable *headers, struct ast_ari_channels_create_args *args, struct ast_ari_response *response); /*! Argument struct for ast_ari_channels_get() */ struct ast_ari_channels_get_args { /*! Channel's id */ |