Add the ability to continue and originate using priority labels.
authorMark Michelson <mmichelson@digium.com>
Wed, 7 Jan 2015 18:54:06 +0000 (18:54 +0000)
committerMark Michelson <mmichelson@digium.com>
Wed, 7 Jan 2015 18:54:06 +0000 (18:54 +0000)
With this patch, the following two ARI commands

POST /channels
POST /channels/{id}/continue

Accept a new parameter, label, that can be used to continue to or originate
to a priority label in the dialplan.

Because this is adding a new parameter to ARI commands, the API version of
ARI has been bumped from 1.6.0 to 1.7.0.

This patch comes courtesy of Nir Simionovich from Greenfield Tech. Thanks!

ASTERISK-24412 #close
Reported by Nir Simionovich

Review: https://reviewboard.asterisk.org/r/4285
........

Merged revisions 430337 from http://svn.asterisk.org/svn/asterisk/branches/13

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@430338 65c4cc65-6c06-0410-ace0-fbb531ad65f3

CHANGES
res/ari/resource_channels.c
res/ari/resource_channels.h
res/res_ari_channels.c
rest-api/api-docs/channels.json
rest-api/resources.json

diff --git a/CHANGES b/CHANGES
index 05c2f60..5f6a50e 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -128,6 +128,11 @@ ARI
  * "language" (the default spoken language for the channel) is now included in
    the standard channel state output for suitable events.
 
  * "language" (the default spoken language for the channel) is now included in
    the standard channel state output for suitable events.
 
+ * The POST channels/{id} operation and the POST channels/{id}/continue operation
+   now have a new "label" parameter. This allows for origination or continuation
+   to a labeled priority in the dialplan instead of requiring a specific priority
+   number. The ARI version has been bumped to 1.7.0 as a result.
+
 AMI
 ------------------
  * "Language" (the default spoken language for the channel) is now included in
 AMI
 ------------------
  * "Language" (the default spoken language for the channel) is now included in
index e3ef9eb..d1d54a2 100644 (file)
@@ -91,6 +91,10 @@ void ast_ari_channels_continue_in_dialplan(
        struct ast_ari_response *response)
 {
        RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
        struct ast_ari_response *response)
 {
        RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
+       RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
+       int ipri;
+       const char *context;
+       const char *exten;
 
        ast_assert(response != NULL);
 
 
        ast_assert(response != NULL);
 
@@ -99,7 +103,52 @@ void ast_ari_channels_continue_in_dialplan(
                return;
        }
 
                return;
        }
 
-       if (stasis_app_control_continue(control, args->context, args->extension, args->priority)) {
+       snapshot = stasis_app_control_get_snapshot(control);
+       if (!snapshot) {
+               return;
+       }
+
+       if (ast_strlen_zero(args->context)) {
+               context = snapshot->context;
+               exten = S_OR(args->extension, snapshot->exten);
+       } else {
+               context = args->context;
+               exten = S_OR(args->extension, "s");
+       }
+
+       if (!ast_strlen_zero(args->label)) {
+               /* A label was provided in the request, use that */
+
+               if (sscanf(args->label, "%30d", &ipri) != 1) {
+                       ipri = ast_findlabel_extension(NULL, context, exten, args->label, NULL);
+                       if (ipri == -1) {
+                               ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args->label, context);
+                               ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
+                               return;
+                       }
+               } else {
+                       ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
+               }
+
+               if (ipri == 0) {
+                       ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
+                                       args->label, exten, context);
+                       ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
+                       return;
+               }
+
+       } else if (args->priority) {
+               /* No label provided, use provided priority */
+               ipri = args->priority;
+       } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
+               /* Special case. No exten, context, or priority provided, then move on to the next priority */
+               ipri = snapshot->priority + 1;
+       } else {
+               ipri = 1;
+       }
+
+
+       if (stasis_app_control_continue(control, context, exten, ipri)) {
                ast_ari_response_alloc_failed(response);
                return;
        }
                ast_ari_response_alloc_failed(response);
                return;
        }
@@ -791,6 +840,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
        const char *args_extension,
        const char *args_context,
        long args_priority,
        const char *args_extension,
        const char *args_context,
        long args_priority,
+       const char *args_label,
        const char *args_app,
        const char *args_app_args,
        const char *args_caller_id,
        const char *args_app,
        const char *args_app_args,
        const char *args_caller_id,
@@ -811,7 +861,7 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
                ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
        char *stuff;
        struct ast_channel *other = NULL;
                ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
        char *stuff;
        struct ast_channel *other = NULL;
-       struct ast_channel *chan;
+       struct ast_channel *chan = NULL;
        RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
        struct ast_assigned_ids assignedids = {
                .uniqueid = args_channel_id,
        RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
        struct ast_assigned_ids assignedids = {
                .uniqueid = args_channel_id,
@@ -880,7 +930,36 @@ static void ari_channels_handle_originate_with_id(const char *args_endpoint,
 
                ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
                ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
 
                ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
                ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
-               origination->priority = args_priority ? args_priority : 1;
+
+               if (!ast_strlen_zero(args_label)) {
+                       /* A label was provided in the request, use that */
+                       int ipri = 1;
+                       if (sscanf(args_label, "%30d", &ipri) != 1) {
+                               ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
+
+                               if (ipri == -1) {
+                                       ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
+                                       ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
+                                       return;
+                               }
+                       } else {
+                               ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
+                       }
+
+                       if (ipri == 0) {
+                               ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
+                                               args_label, args_extension, args_context);
+                               ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
+                               return;
+                       }
+
+                       /* Our priority was provided by a label */
+                       origination->priority =  ipri;
+               } else {
+                       /* No label provided, use provided priority */
+                       origination->priority = args_priority ? args_priority : 1;
+               }
+
                origination->appdata[0] = '\0';
        } else {
                ast_ari_response_error(response, 400, "Bad Request",
                origination->appdata[0] = '\0';
        } else {
                ast_ari_response_error(response, 400, "Bad Request",
@@ -1042,6 +1121,7 @@ void ast_ari_channels_originate_with_id(struct ast_variable *headers,
                args->extension,
                args->context,
                args->priority,
                args->extension,
                args->context,
                args->priority,
+               args->label,
                args->app,
                args->app_args,
                args->caller_id,
                args->app,
                args->app_args,
                args->caller_id,
@@ -1079,6 +1159,7 @@ void ast_ari_channels_originate(struct ast_variable *headers,
                args->extension,
                args->context,
                args->priority,
                args->extension,
                args->context,
                args->priority,
+               args->label,
                args->app,
                args->app_args,
                args->caller_id,
                args->app,
                args->app_args,
                args->caller_id,
index 627f9c9..dddfcf3 100644 (file)
@@ -60,6 +60,8 @@ struct ast_ari_channels_originate_args {
        const char *context;
        /*! The priority to dial after the endpoint answers. If omitted, uses 1 */
        long priority;
        const char *context;
        /*! The priority to dial after the endpoint answers. If omitted, uses 1 */
        long priority;
+       /*! The label to dial after the endpoint answers. Will supersede 'priority' if provided. */
+       const char *label;
        /*! The application that is subscribed to the originated channel, and passed to the Stasis application. */
        const char *app;
        /*! The application arguments to pass to the Stasis application. */
        /*! The application that is subscribed to the originated channel, and passed to the Stasis application. */
        const char *app;
        /*! The application arguments to pass to the Stasis application. */
@@ -123,6 +125,8 @@ struct ast_ari_channels_originate_with_id_args {
        const char *context;
        /*! The priority to dial after the endpoint answers. If omitted, uses 1 */
        long priority;
        const char *context;
        /*! The priority to dial after the endpoint answers. If omitted, uses 1 */
        long priority;
+       /*! The label to dial after the endpoint answers. Will supersede priority, if provided */
+       const char *label;
        /*! The application that is subscribed to the originated channel, and passed to the Stasis application. */
        const char *app;
        /*! The application arguments to pass to the Stasis application. */
        /*! The application that is subscribed to the originated channel, and passed to the Stasis application. */
        const char *app;
        /*! The application arguments to pass to the Stasis application. */
@@ -195,6 +199,8 @@ struct ast_ari_channels_continue_in_dialplan_args {
        const char *extension;
        /*! The priority to continue to. */
        int priority;
        const char *extension;
        /*! The priority to continue to. */
        int priority;
+       /*! The label to continue to - will supersede 'priority' if both are provided. */
+       const char *label;
 };
 /*!
  * \brief Body parsing function for /channels/{channelId}/continue.
 };
 /*!
  * \brief Body parsing function for /channels/{channelId}/continue.
index 8cc25f1..82bb662 100644 (file)
@@ -124,6 +124,10 @@ int ast_ari_channels_originate_parse_body(
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
+       field = ast_json_object_get(body, "label");
+       if (field) {
+               args->label = ast_json_string_get(field);
+       }
        field = ast_json_object_get(body, "app");
        if (field) {
                args->app = ast_json_string_get(field);
        field = ast_json_object_get(body, "app");
        if (field) {
                args->app = ast_json_string_get(field);
@@ -188,6 +192,9 @@ static void ast_ari_channels_originate_cb(
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atol(i->value);
                } else
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atol(i->value);
                } else
+               if (strcmp(i->name, "label") == 0) {
+                       args.label = (i->value);
+               } else
                if (strcmp(i->name, "app") == 0) {
                        args.app = (i->value);
                } else
                if (strcmp(i->name, "app") == 0) {
                        args.app = (i->value);
                } else
@@ -341,6 +348,10 @@ int ast_ari_channels_originate_with_id_parse_body(
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
+       field = ast_json_object_get(body, "label");
+       if (field) {
+               args->label = ast_json_string_get(field);
+       }
        field = ast_json_object_get(body, "app");
        if (field) {
                args->app = ast_json_string_get(field);
        field = ast_json_object_get(body, "app");
        if (field) {
                args->app = ast_json_string_get(field);
@@ -401,6 +412,9 @@ static void ast_ari_channels_originate_with_id_cb(
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atol(i->value);
                } else
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atol(i->value);
                } else
+               if (strcmp(i->name, "label") == 0) {
+                       args.label = (i->value);
+               } else
                if (strcmp(i->name, "app") == 0) {
                        args.app = (i->value);
                } else
                if (strcmp(i->name, "app") == 0) {
                        args.app = (i->value);
                } else
@@ -592,6 +606,10 @@ int ast_ari_channels_continue_in_dialplan_parse_body(
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
        if (field) {
                args->priority = ast_json_integer_get(field);
        }
+       field = ast_json_object_get(body, "label");
+       if (field) {
+               args->label = ast_json_string_get(field);
+       }
        return 0;
 }
 
        return 0;
 }
 
@@ -625,6 +643,9 @@ static void ast_ari_channels_continue_in_dialplan_cb(
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atoi(i->value);
                } else
                if (strcmp(i->name, "priority") == 0) {
                        args.priority = atoi(i->value);
                } else
+               if (strcmp(i->name, "label") == 0) {
+                       args.label = (i->value);
+               } else
                {}
        }
        for (i = path_vars; i; i = i->next) {
                {}
        }
        for (i = path_vars; i; i = i->next) {
index cd309db..87dee7c 100644 (file)
                                                        "dataType": "long"
                                                },
                                                {
                                                        "dataType": "long"
                                                },
                                                {
+                                                       "name": "label",
+                                                       "description": "The label to dial after the endpoint answers. Will supersede 'priority' if provided.",
+                                                       "paramType": "query",
+                                                       "required": false,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
+                                               },
+                                               {
                                                        "name": "app",
                                                        "description": "The application that is subscribed to the originated channel, and passed to the Stasis application.",
                                                        "paramType": "query",
                                                        "name": "app",
                                                        "description": "The application that is subscribed to the originated channel, and passed to the Stasis application.",
                                                        "paramType": "query",
                                                        "dataType": "long"
                                                },
                                                {
                                                        "dataType": "long"
                                                },
                                                {
+                                                       "name": "label",
+                                                       "description": "The label to dial after the endpoint answers. Will supersede priority, if provided",
+                                                       "paramType": "query",
+                                                       "required": false,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
+                                               },
+                                               {
                                                        "name": "app",
                                                        "description": "The application that is subscribed to the originated channel, and passed to the Stasis application.",
                                                        "paramType": "query",
                                                        "name": "app",
                                                        "description": "The application that is subscribed to the originated channel, and passed to the Stasis application.",
                                                        "paramType": "query",
                                                        "required": false,
                                                        "allowMultiple": false,
                                                        "dataType": "int"
                                                        "required": false,
                                                        "allowMultiple": false,
                                                        "dataType": "int"
+                                               },
+                                               {
+                                                       "name": "label",
+                                                       "description": "The label to continue to - will supersede 'priority' if both are provided.",
+                                                       "paramType": "query",
+                                                       "required": false,
+                                                       "allowMultiple": false,
+                                                       "dataType": "string"
                                                }
                                        ],
                                        "errorResponses": [
                                                }
                                        ],
                                        "errorResponses": [
index 2cc039d..4a098f5 100644 (file)
@@ -2,7 +2,7 @@
        "_copyright": "Copyright (C) 2012 - 2013, Digium, Inc.",
        "_author": "David M. Lee, II <dlee@digium.com>",
        "_svn_revision": "$Revision$",
        "_copyright": "Copyright (C) 2012 - 2013, Digium, Inc.",
        "_author": "David M. Lee, II <dlee@digium.com>",
        "_svn_revision": "$Revision$",
-       "apiVersion": "1.6.0",
+       "apiVersion": "1.7.0",
        "swaggerVersion": "1.1",
        "basePath": "http://localhost:8088/ari",
        "apis": [
        "swaggerVersion": "1.1",
        "basePath": "http://localhost:8088/ari",
        "apis": [