diff options
-rw-r--r-- | include/asterisk/stasis_app.h | 19 | ||||
-rw-r--r-- | res/res_stasis_http_asterisk.c | 61 | ||||
-rw-r--r-- | res/res_stasis_http_channels.c | 73 | ||||
-rw-r--r-- | res/stasis/control.c | 28 | ||||
-rw-r--r-- | res/stasis_http/resource_asterisk.c | 41 | ||||
-rw-r--r-- | res/stasis_http/resource_asterisk.h | 28 | ||||
-rw-r--r-- | res/stasis_http/resource_channels.c | 52 | ||||
-rw-r--r-- | res/stasis_http/resource_channels.h | 32 | ||||
-rw-r--r-- | rest-api/api-docs/asterisk.json | 56 | ||||
-rw-r--r-- | rest-api/api-docs/channels.json | 92 |
10 files changed, 478 insertions, 4 deletions
diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h index 93d5cf36c..33091409c 100644 --- a/include/asterisk/stasis_app.h +++ b/include/asterisk/stasis_app.h @@ -174,6 +174,25 @@ int stasis_app_control_continue(struct stasis_app_control *control, const char * int stasis_app_control_answer(struct stasis_app_control *control); /*! + * \brief Get the value of a variable on the channel associated with this control. + * \param control Control for \c res_stasis. + * \param variable The name of the variable. + * \return The value of the variable. The returned variable must be freed. + */ +char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable); + +/*! + * \brief Set a variable on the channel associated with this control to value. + * \param control Control for \c res_stasis. + * \param variable The name of the variable + * \param value The value to set the variable to + * + * \return 0 for success. + * \return -1 for error. + */ +int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value); + +/*! * \brief Place the channel associated with the control on hold. * \param control Control for \c res_stasis. */ diff --git a/res/res_stasis_http_asterisk.c b/res/res_stasis_http_asterisk.c index 01f082ad6..c0ff660cd 100644 --- a/res/res_stasis_http_asterisk.c +++ b/res/res_stasis_http_asterisk.c @@ -98,6 +98,53 @@ static void stasis_http_get_asterisk_info_cb( } #endif /* AST_DEVMODE */ } +/*! + * \brief Parameter parsing callback for /asterisk/variable. + * \param get_params GET parameters in the HTTP request. + * \param path_vars Path variables extracted from the request. + * \param headers HTTP headers. + * \param[out] response Response to the HTTP request. + */ +static void stasis_http_get_global_var_cb( + struct ast_variable *get_params, struct ast_variable *path_vars, + struct ast_variable *headers, struct stasis_http_response *response) +{ + struct ast_get_global_var_args args = {}; + struct ast_variable *i; + + for (i = get_params; i; i = i->next) { + if (strcmp(i->name, "variable") == 0) { + args.variable = (i->value); + } else + {} + } + stasis_http_get_global_var(headers, &args, response); +} +/*! + * \brief Parameter parsing callback for /asterisk/variable. + * \param get_params GET parameters in the HTTP request. + * \param path_vars Path variables extracted from the request. + * \param headers HTTP headers. + * \param[out] response Response to the HTTP request. + */ +static void stasis_http_set_global_var_cb( + struct ast_variable *get_params, struct ast_variable *path_vars, + struct ast_variable *headers, struct stasis_http_response *response) +{ + struct ast_set_global_var_args args = {}; + struct ast_variable *i; + + for (i = get_params; i; i = i->next) { + if (strcmp(i->name, "variable") == 0) { + args.variable = (i->value); + } else + if (strcmp(i->name, "value") == 0) { + args.value = (i->value); + } else + {} + } + stasis_http_set_global_var(headers, &args, response); +} /*! \brief REST handler for /api-docs/asterisk.{format} */ static struct stasis_rest_handlers asterisk_info = { @@ -109,12 +156,22 @@ static struct stasis_rest_handlers asterisk_info = { .children = { } }; /*! \brief REST handler for /api-docs/asterisk.{format} */ +static struct stasis_rest_handlers asterisk_variable = { + .path_segment = "variable", + .callbacks = { + [AST_HTTP_GET] = stasis_http_get_global_var_cb, + [AST_HTTP_POST] = stasis_http_set_global_var_cb, + }, + .num_children = 0, + .children = { } +}; +/*! \brief REST handler for /api-docs/asterisk.{format} */ static struct stasis_rest_handlers asterisk = { .path_segment = "asterisk", .callbacks = { }, - .num_children = 1, - .children = { &asterisk_info, } + .num_children = 2, + .children = { &asterisk_info,&asterisk_variable, } }; static int load_module(void) diff --git a/res/res_stasis_http_channels.c b/res/res_stasis_http_channels.c index 108f356c1..a3d2932a2 100644 --- a/res/res_stasis_http_channels.c +++ b/res/res_stasis_http_channels.c @@ -810,6 +810,65 @@ static void stasis_http_record_channel_cb( } #endif /* AST_DEVMODE */ } +/*! + * \brief Parameter parsing callback for /channels/{channelId}/variable. + * \param get_params GET parameters in the HTTP request. + * \param path_vars Path variables extracted from the request. + * \param headers HTTP headers. + * \param[out] response Response to the HTTP request. + */ +static void stasis_http_get_channel_var_cb( + struct ast_variable *get_params, struct ast_variable *path_vars, + struct ast_variable *headers, struct stasis_http_response *response) +{ + struct ast_get_channel_var_args args = {}; + struct ast_variable *i; + + for (i = get_params; i; i = i->next) { + if (strcmp(i->name, "variable") == 0) { + args.variable = (i->value); + } else + {} + } + for (i = path_vars; i; i = i->next) { + if (strcmp(i->name, "channelId") == 0) { + args.channel_id = (i->value); + } else + {} + } + stasis_http_get_channel_var(headers, &args, response); +} +/*! + * \brief Parameter parsing callback for /channels/{channelId}/variable. + * \param get_params GET parameters in the HTTP request. + * \param path_vars Path variables extracted from the request. + * \param headers HTTP headers. + * \param[out] response Response to the HTTP request. + */ +static void stasis_http_set_channel_var_cb( + struct ast_variable *get_params, struct ast_variable *path_vars, + struct ast_variable *headers, struct stasis_http_response *response) +{ + struct ast_set_channel_var_args args = {}; + struct ast_variable *i; + + for (i = get_params; i; i = i->next) { + if (strcmp(i->name, "variable") == 0) { + args.variable = (i->value); + } else + if (strcmp(i->name, "value") == 0) { + args.value = (i->value); + } else + {} + } + for (i = path_vars; i; i = i->next) { + if (strcmp(i->name, "channelId") == 0) { + args.channel_id = (i->value); + } else + {} + } + stasis_http_set_channel_var(headers, &args, response); +} /*! \brief REST handler for /api-docs/channels.{format} */ static struct stasis_rest_handlers channels_channelId_dial = { @@ -893,6 +952,16 @@ static struct stasis_rest_handlers channels_channelId_record = { .children = { } }; /*! \brief REST handler for /api-docs/channels.{format} */ +static struct stasis_rest_handlers channels_channelId_variable = { + .path_segment = "variable", + .callbacks = { + [AST_HTTP_GET] = stasis_http_get_channel_var_cb, + [AST_HTTP_POST] = stasis_http_set_channel_var_cb, + }, + .num_children = 0, + .children = { } +}; +/*! \brief REST handler for /api-docs/channels.{format} */ static struct stasis_rest_handlers channels_channelId = { .path_segment = "channelId", .is_wildcard = 1, @@ -900,8 +969,8 @@ static struct stasis_rest_handlers channels_channelId = { [AST_HTTP_GET] = stasis_http_get_channel_cb, [AST_HTTP_DELETE] = stasis_http_delete_channel_cb, }, - .num_children = 9, - .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_play,&channels_channelId_record, } + .num_children = 10, + .children = { &channels_channelId_dial,&channels_channelId_continue,&channels_channelId_answer,&channels_channelId_mute,&channels_channelId_unmute,&channels_channelId_hold,&channels_channelId_unhold,&channels_channelId_play,&channels_channelId_record,&channels_channelId_variable, } }; /*! \brief REST handler for /api-docs/channels.{format} */ static struct stasis_rest_handlers channels = { diff --git a/res/stasis/control.c b/res/stasis/control.c index 2bba842ed..6a7a9ba4d 100644 --- a/res/stasis/control.c +++ b/res/stasis/control.c @@ -207,6 +207,34 @@ int stasis_app_control_continue(struct stasis_app_control *control, const char * return 0; } +char *stasis_app_control_get_channel_var(struct stasis_app_control *control, const char *variable) +{ + SCOPED_CHANNELLOCK(lockvar, control->channel); + + RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free); + + if (!tmp) { + return NULL; + } + + if (variable[strlen(variable) - 1] == ')') { + if (ast_func_read2(control->channel, variable, &tmp, 0)) { + return NULL; + } + } else { + if (!ast_str_retrieve_variable(&tmp, 0, control->channel, NULL, variable)) { + return NULL; + } + } + + return ast_strdup(ast_str_buffer(tmp)); +} + +int stasis_app_control_set_channel_var(struct stasis_app_control *control, const char *variable, const char *value) +{ + return pbx_builtin_setvar_helper(control->channel, variable, value); +} + static void *app_control_hold(struct stasis_app_control *control, struct ast_channel *chan, void *data) { diff --git a/res/stasis_http/resource_asterisk.c b/res/stasis_http/resource_asterisk.c index b5e8b0f54..c2a0bc0cc 100644 --- a/res/stasis_http/resource_asterisk.c +++ b/res/stasis_http/resource_asterisk.c @@ -32,8 +32,49 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "resource_asterisk.h" +#include "asterisk/pbx.h" void stasis_http_get_asterisk_info(struct ast_variable *headers, struct ast_get_asterisk_info_args *args, struct stasis_http_response *response) { ast_log(LOG_ERROR, "TODO: stasis_http_get_asterisk_info\n"); } + +void stasis_http_get_global_var(struct ast_variable *headers, struct ast_get_global_var_args *args, struct stasis_http_response *response) +{ + RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + RAII_VAR(struct ast_str *, tmp, ast_str_create(32), ast_free); + + const char *value; + + ast_assert(response != NULL); + + if (!tmp) { + stasis_http_response_alloc_failed(response); + return; + } + + value = ast_str_retrieve_variable(&tmp, 0, NULL, NULL, args->variable); + + if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) { + stasis_http_response_alloc_failed(response); + return; + } + + stasis_http_response_ok(response, ast_json_ref(json)); +} + +void stasis_http_set_global_var(struct ast_variable *headers, struct ast_set_global_var_args *args, struct stasis_http_response *response) +{ + ast_assert(response != NULL); + + if (ast_strlen_zero(args->variable)) { + stasis_http_response_error( + response, 400, "Bad Request", + "Variable name is required"); + return; + } + + pbx_builtin_setvar_helper(NULL, args->variable, args->value); + + stasis_http_response_no_content(response); +} diff --git a/res/stasis_http/resource_asterisk.h b/res/stasis_http/resource_asterisk.h index 0d373ccb2..e32e919ab 100644 --- a/res/stasis_http/resource_asterisk.h +++ b/res/stasis_http/resource_asterisk.h @@ -52,5 +52,33 @@ struct ast_get_asterisk_info_args { * \param[out] response HTTP response */ void stasis_http_get_asterisk_info(struct ast_variable *headers, struct ast_get_asterisk_info_args *args, struct stasis_http_response *response); +/*! \brief Argument struct for stasis_http_get_global_var() */ +struct ast_get_global_var_args { + /*! \brief The variable to get */ + const char *variable; +}; +/*! + * \brief Get the value of a global variable. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void stasis_http_get_global_var(struct ast_variable *headers, struct ast_get_global_var_args *args, struct stasis_http_response *response); +/*! \brief Argument struct for stasis_http_set_global_var() */ +struct ast_set_global_var_args { + /*! \brief The variable to set */ + const char *variable; + /*! \brief The value to set the variable to */ + const char *value; +}; +/*! + * \brief Set the value of a global variable. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void stasis_http_set_global_var(struct ast_variable *headers, struct ast_set_global_var_args *args, struct stasis_http_response *response); #endif /* _ASTERISK_RESOURCE_ASTERISK_H */ diff --git a/res/stasis_http/resource_channels.c b/res/stasis_http/resource_channels.c index 8db3b697c..1700b86ca 100644 --- a/res/stasis_http/resource_channels.c +++ b/res/stasis_http/resource_channels.c @@ -561,3 +561,55 @@ void stasis_http_originate(struct ast_variable *headers, stasis_http_response_no_content(response); } + +void stasis_http_get_channel_var(struct ast_variable *headers, struct ast_get_channel_var_args *args, struct stasis_http_response *response) +{ + RAII_VAR(struct ast_json *, json, NULL, ast_json_unref); + RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + RAII_VAR(char *, value, NULL, ast_free); + + ast_assert(response != NULL); + + control = find_control(response, args->channel_id); + if (control == NULL) { + return; + } + + value = stasis_app_control_get_channel_var(control, args->variable); + + if (!(json = ast_json_pack("{s: s}", "value", S_OR(value, "")))) { + stasis_http_response_alloc_failed(response); + return; + } + + stasis_http_response_ok(response, ast_json_ref(json)); +} + +void stasis_http_set_channel_var(struct ast_variable *headers, struct ast_set_channel_var_args *args, struct stasis_http_response *response) +{ + RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup); + + ast_assert(response != NULL); + + control = find_control(response, args->channel_id); + if (control == NULL) { + return; + } + + if (ast_strlen_zero(args->variable)) { + stasis_http_response_error( + response, 400, "Bad Request", + "Variable name is required"); + return; + } + + if (stasis_app_control_set_channel_var(control, args->variable, args->value)) { + stasis_http_response_error( + response, 400, "Bad Request", + "Failed to execute function"); + return; + } + + stasis_http_response_no_content(response); +} + diff --git a/res/stasis_http/resource_channels.h b/res/stasis_http/resource_channels.h index 7e8dc5dbe..999e16954 100644 --- a/res/stasis_http/resource_channels.h +++ b/res/stasis_http/resource_channels.h @@ -264,5 +264,37 @@ struct ast_record_channel_args { * \param[out] response HTTP response */ void stasis_http_record_channel(struct ast_variable *headers, struct ast_record_channel_args *args, struct stasis_http_response *response); +/*! \brief Argument struct for stasis_http_get_channel_var() */ +struct ast_get_channel_var_args { + /*! \brief Channel's id */ + const char *channel_id; + /*! \brief The channel variable or function to get */ + const char *variable; +}; +/*! + * \brief Get the value of a channel variable or function. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void stasis_http_get_channel_var(struct ast_variable *headers, struct ast_get_channel_var_args *args, struct stasis_http_response *response); +/*! \brief Argument struct for stasis_http_set_channel_var() */ +struct ast_set_channel_var_args { + /*! \brief Channel's id */ + const char *channel_id; + /*! \brief The channel variable or function to set */ + const char *variable; + /*! \brief The value to set the variable to */ + const char *value; +}; +/*! + * \brief Set the value of a channel variable or function. + * + * \param headers HTTP headers + * \param args Swagger parameters + * \param[out] response HTTP response + */ +void stasis_http_set_channel_var(struct ast_variable *headers, struct ast_set_channel_var_args *args, struct stasis_http_response *response); #endif /* _ASTERISK_RESOURCE_CHANNELS_H */ diff --git a/rest-api/api-docs/asterisk.json b/rest-api/api-docs/asterisk.json index 8ee88e439..8c404a075 100644 --- a/rest-api/api-docs/asterisk.json +++ b/rest-api/api-docs/asterisk.json @@ -36,6 +36,52 @@ ] } ] + }, + { + "path": "/asterisk/variable", + "description": "Global variables", + "operations": [ + { + "httpMethod": "GET", + "summary": "Get the value of a global variable.", + "nickname": "getGlobalVar", + "responseClass": "Variable", + "parameters": [ + { + "name": "variable", + "description": "The variable to get", + "paramType": "query", + "required": true, + "allowMultiple": false, + "dataType": "string" + } + ] + }, + { + "httpMethod": "POST", + "summary": "Set the value of a global variable.", + "nickname": "setGlobalVar", + "responseClass": "void", + "parameters": [ + { + "name": "variable", + "description": "The variable to set", + "paramType": "query", + "required": true, + "allowMultiple": false, + "dataType": "string" + }, + { + "name": "value", + "description": "The value to set the variable to", + "paramType": "query", + "required": false, + "allowMultiple": false, + "dataType": "string" + } + ] + } + ] } ], "models": { @@ -43,6 +89,16 @@ "id": "AsteriskInfo", "description": "Asterisk system information", "properties": {} + }, + "Variable": { + "id": "Variable", + "properties": { + "variable": { + "required": true, + "type": "string", + "description": "The value of the variable requested" + } + } } } } diff --git a/rest-api/api-docs/channels.json b/rest-api/api-docs/channels.json index 9900db739..a97f22566 100644 --- a/rest-api/api-docs/channels.json +++ b/rest-api/api-docs/channels.json @@ -645,6 +645,88 @@ ] } ] + }, + { + "path": "/channels/{channelId}/variable", + "description": "Variables on a channel", + "operations": [ + { + "httpMethod": "GET", + "summary": "Get the value of a channel variable or function.", + "nickname": "getChannelVar", + "responseClass": "ChannelVariable", + "parameters": [ + { + "name": "channelId", + "description": "Channel's id", + "paramType": "path", + "required": true, + "allowMultiple": false, + "dataType": "string" + }, + { + "name": "variable", + "description": "The channel variable or function to get", + "paramType": "query", + "required": true, + "allowMultiple": false, + "dataType": "string" + } + ], + "errorResponses": [ + { + "code": 404, + "reason": "Channel not found" + }, + { + "code": 409, + "reason": "Channel not in a Stasis application" + } + ] + }, + { + "httpMethod": "POST", + "summary": "Set the value of a channel variable or function.", + "nickname": "setChannelVar", + "responseClass": "void", + "parameters": [ + { + "name": "channelId", + "description": "Channel's id", + "paramType": "path", + "required": true, + "allowMultiple": false, + "dataType": "string" + }, + { + "name": "variable", + "description": "The channel variable or function to set", + "paramType": "query", + "required": true, + "allowMultiple": false, + "dataType": "string" + }, + { + "name": "value", + "description": "The value to set the variable to", + "paramType": "query", + "required": false, + "allowMultiple": false, + "dataType": "string" + } + ], + "errorResponses": [ + { + "code": 404, + "reason": "Channel not found" + }, + { + "code": 409, + "reason": "Channel not in a Stasis application" + } + ] + } + ] } ], "models": { @@ -745,6 +827,16 @@ "description": "Timestamp when channel was created" } } + }, + "Variable": { + "id": "Variable", + "properties": { + "variable": { + "required": true, + "type": "string", + "description": "The value of the variable requested" + } + } } } } |