mirror of
https://github.com/asterisk/asterisk.git
synced 2025-09-03 11:25:35 +00:00
res_stasis: Add ability to switch applications.
Added the ability to move between Stasis applications within Stasis. This can be done by calling 'move' in an application, providing (at minimum) the channel's id and the application to switch to. If the application is not registered or active, nothing will happen and the channel will remain in the current application, and an event will be triggered to let the application know that the move failed. The event name is "ApplicationMoveFailed", and provides the "destination" that the channel was attempting to move to, as well as the usual channel information. Optionally, a list of arguments can be passed to the function call for the receiving application. A full example of a 'move' call would look like this: client.channels.move(channelId, app, appArgs) The control object used to control the channel in Stasis can now switch which application it belongs to, rather than belonging to one Stasis application for its lifetime. This allows us to use the same control object instead of having to tear down the current one and create another. ASTERISK-28267 #close Change-Id: I43d12b10045a98a8d42541889b85695be26f288a
This commit is contained in:
@@ -2028,6 +2028,127 @@ ari_validator ast_ari_validate_mailbox_fn(void)
|
||||
return ast_ari_validate_mailbox;
|
||||
}
|
||||
|
||||
int ast_ari_validate_application_move_failed(struct ast_json *json)
|
||||
{
|
||||
int res = 1;
|
||||
struct ast_json_iter *iter;
|
||||
int has_type = 0;
|
||||
int has_application = 0;
|
||||
int has_args = 0;
|
||||
int has_channel = 0;
|
||||
int has_destination = 0;
|
||||
|
||||
for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) {
|
||||
if (strcmp("asterisk_id", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
prop_is_valid = ast_ari_validate_string(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field asterisk_id failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("type", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
has_type = 1;
|
||||
prop_is_valid = ast_ari_validate_string(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field type failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("application", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
has_application = 1;
|
||||
prop_is_valid = ast_ari_validate_string(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field application failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
prop_is_valid = ast_ari_validate_date(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field timestamp failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("args", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
has_args = 1;
|
||||
prop_is_valid = ast_ari_validate_list(
|
||||
ast_json_object_iter_value(iter),
|
||||
ast_ari_validate_string);
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field args failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("channel", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
has_channel = 1;
|
||||
prop_is_valid = ast_ari_validate_channel(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field channel failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
if (strcmp("destination", ast_json_object_iter_key(iter)) == 0) {
|
||||
int prop_is_valid;
|
||||
has_destination = 1;
|
||||
prop_is_valid = ast_ari_validate_string(
|
||||
ast_json_object_iter_value(iter));
|
||||
if (!prop_is_valid) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed field destination failed validation\n");
|
||||
res = 0;
|
||||
}
|
||||
} else
|
||||
{
|
||||
ast_log(LOG_ERROR,
|
||||
"ARI ApplicationMoveFailed has undocumented field %s\n",
|
||||
ast_json_object_iter_key(iter));
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_type) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed missing required field type\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!has_application) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed missing required field application\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!has_args) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed missing required field args\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!has_channel) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed missing required field channel\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
if (!has_destination) {
|
||||
ast_log(LOG_ERROR, "ARI ApplicationMoveFailed missing required field destination\n");
|
||||
res = 0;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
ari_validator ast_ari_validate_application_move_failed_fn(void)
|
||||
{
|
||||
return ast_ari_validate_application_move_failed;
|
||||
}
|
||||
|
||||
int ast_ari_validate_application_replaced(struct ast_json *json)
|
||||
{
|
||||
int res = 1;
|
||||
@@ -5095,6 +5216,9 @@ int ast_ari_validate_event(struct ast_json *json)
|
||||
if (strcmp("Event", discriminator) == 0) {
|
||||
/* Self type; fall through */
|
||||
} else
|
||||
if (strcmp("ApplicationMoveFailed", discriminator) == 0) {
|
||||
return ast_ari_validate_application_move_failed(json);
|
||||
} else
|
||||
if (strcmp("ApplicationReplaced", discriminator) == 0) {
|
||||
return ast_ari_validate_application_replaced(json);
|
||||
} else
|
||||
@@ -5293,6 +5417,9 @@ int ast_ari_validate_message(struct ast_json *json)
|
||||
if (strcmp("Message", discriminator) == 0) {
|
||||
/* Self type; fall through */
|
||||
} else
|
||||
if (strcmp("ApplicationMoveFailed", discriminator) == 0) {
|
||||
return ast_ari_validate_application_move_failed(json);
|
||||
} else
|
||||
if (strcmp("ApplicationReplaced", discriminator) == 0) {
|
||||
return ast_ari_validate_application_replaced(json);
|
||||
} else
|
||||
|
@@ -623,6 +623,24 @@ int ast_ari_validate_mailbox(struct ast_json *json);
|
||||
*/
|
||||
ari_validator ast_ari_validate_mailbox_fn(void);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ApplicationMoveFailed.
|
||||
*
|
||||
* Notification that trying to move a channel to another Stasis application failed.
|
||||
*
|
||||
* \param json JSON object to validate.
|
||||
* \returns True (non-zero) if valid.
|
||||
* \returns False (zero) if invalid.
|
||||
*/
|
||||
int ast_ari_validate_application_move_failed(struct ast_json *json);
|
||||
|
||||
/*!
|
||||
* \brief Function pointer to ast_ari_validate_application_move_failed().
|
||||
*
|
||||
* See \ref ast_ari_model_validators.h for more details.
|
||||
*/
|
||||
ari_validator ast_ari_validate_application_move_failed_fn(void);
|
||||
|
||||
/*!
|
||||
* \brief Validator for ApplicationReplaced.
|
||||
*
|
||||
@@ -1527,6 +1545,14 @@ ari_validator ast_ari_validate_application_fn(void);
|
||||
* - name: string (required)
|
||||
* - new_messages: int (required)
|
||||
* - old_messages: int (required)
|
||||
* ApplicationMoveFailed
|
||||
* - asterisk_id: string
|
||||
* - type: string (required)
|
||||
* - application: string (required)
|
||||
* - timestamp: Date
|
||||
* - args: List[string] (required)
|
||||
* - channel: Channel (required)
|
||||
* - destination: string (required)
|
||||
* ApplicationReplaced
|
||||
* - asterisk_id: string
|
||||
* - type: string (required)
|
||||
|
@@ -217,6 +217,26 @@ void ast_ari_channels_continue_in_dialplan(
|
||||
ast_ari_response_no_content(response);
|
||||
}
|
||||
|
||||
void ast_ari_channels_move(struct ast_variable *headers,
|
||||
struct ast_ari_channels_move_args *args,
|
||||
struct ast_ari_response *response)
|
||||
{
|
||||
RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
|
||||
|
||||
control = find_control(response, args->channel_id);
|
||||
if (!control) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stasis_app_control_move(control, args->app, args->app_args)) {
|
||||
ast_ari_response_error(response, 500, "Internal Server Error",
|
||||
"Failed to switch Stasis applications");
|
||||
return;
|
||||
}
|
||||
|
||||
ast_ari_response_no_content(response);
|
||||
}
|
||||
|
||||
void ast_ari_channels_redirect(struct ast_variable *headers,
|
||||
struct ast_ari_channels_redirect_args *args,
|
||||
struct ast_ari_response *response)
|
||||
|
@@ -261,6 +261,34 @@ int ast_ari_channels_continue_in_dialplan_parse_body(
|
||||
* \param[out] response HTTP response
|
||||
*/
|
||||
void ast_ari_channels_continue_in_dialplan(struct ast_variable *headers, struct ast_ari_channels_continue_in_dialplan_args *args, struct ast_ari_response *response);
|
||||
/*! Argument struct for ast_ari_channels_move() */
|
||||
struct ast_ari_channels_move_args {
|
||||
/*! Channel's id */
|
||||
const char *channel_id;
|
||||
/*! The channel will be passed to this Stasis application. */
|
||||
const char *app;
|
||||
/*! The application arguments to pass to the Stasis application provided by 'app'. */
|
||||
const char *app_args;
|
||||
};
|
||||
/*!
|
||||
* \brief Body parsing function for /channels/{channelId}/move.
|
||||
* \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_move_parse_body(
|
||||
struct ast_json *body,
|
||||
struct ast_ari_channels_move_args *args);
|
||||
|
||||
/*!
|
||||
* \brief Move the channel from one Stasis application to another.
|
||||
*
|
||||
* \param headers HTTP headers
|
||||
* \param args Swagger parameters
|
||||
* \param[out] response HTTP response
|
||||
*/
|
||||
void ast_ari_channels_move(struct ast_variable *headers, struct ast_ari_channels_move_args *args, struct ast_ari_response *response);
|
||||
/*! Argument struct for ast_ari_channels_redirect() */
|
||||
struct ast_ari_channels_redirect_args {
|
||||
/*! Channel's id */
|
||||
|
Reference in New Issue
Block a user