res/stasis: Add CLI commands for displaying/debugging ARI apps
[asterisk/asterisk.git] / res / stasis / cli.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2016, Digium, Inc.
5  *
6  * Matt Jordan <mjordan@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Stasis CLI commands.
22  *
23  * \author Matt Jordan <mjordan@digium.com>
24  */
25
26 #include "asterisk.h"
27
28 #include "asterisk/cli.h"
29 #include "asterisk/astobj2.h"
30
31 #include "cli.h"
32 #include "app.h"
33
34
35 static char *ari_show_apps(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
36 {
37         struct ao2_container *apps;
38         struct ao2_iterator it_apps;
39         char *app;
40
41         switch (cmd) {
42         case CLI_INIT:
43                 e->command = "ari show apps";
44                 e->usage =
45                         "Usage: ari show apps\n"
46                         "       Lists all registered applications.\n"
47                         ;
48                 return NULL;
49         case CLI_GENERATE:
50                 return NULL;
51         default:
52                 break;
53         }
54
55         if (a->argc != 3) {
56                 return CLI_SHOWUSAGE;
57         }
58
59         apps = stasis_app_get_all();
60         if (!apps) {
61                 ast_cli(a->fd, "Unable to retrieve registered applications!\n");
62                 return CLI_FAILURE;
63         }
64
65         ast_cli(a->fd, "Application Name         \n");
66         ast_cli(a->fd, "=========================\n");
67         it_apps = ao2_iterator_init(apps, 0);
68         while ((app = ao2_iterator_next(&it_apps))) {
69                 ast_cli(a->fd, "%-25.25s\n", app);
70                 ao2_ref(app, -1);
71         }
72
73         ao2_iterator_destroy(&it_apps);
74         ao2_ref(apps, -1);
75
76         return CLI_SUCCESS;
77 }
78
79 struct app_complete {
80         /*! Nth app to search for */
81         int state;
82         /*! Which app currently on */
83         int which;
84 };
85
86 static int complete_ari_app_search(void *obj, void *arg, void *data, int flags)
87 {
88         struct app_complete *search = data;
89
90         if (++search->which > search->state) {
91                 return CMP_MATCH;
92         }
93         return 0;
94 }
95
96 static char *complete_ari_app(struct ast_cli_args *a)
97 {
98         RAII_VAR(struct ao2_container *, apps, stasis_app_get_all(), ao2_cleanup);
99         RAII_VAR(char *, app, NULL, ao2_cleanup);
100
101         struct app_complete search = {
102                 .state = a->n,
103         };
104
105         if (!apps) {
106                 ast_cli(a->fd, "Error getting ARI applications\n");
107                 return CLI_FAILURE;
108         }
109
110         app = ao2_callback_data(apps,
111                 ast_strlen_zero(a->word) ? 0 : OBJ_PARTIAL_KEY,
112                 complete_ari_app_search, (char*)a->word, &search);
113
114         return app ? ast_strdup(app) : NULL;
115 }
116
117 static char *complete_ari_show_app(struct ast_cli_args *a)
118 {
119         if (a->pos == 3) {
120                 return complete_ari_app(a);
121         }
122
123         return NULL;
124 }
125
126 static char *ari_show_app(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
127 {
128         void *app;
129
130         switch (cmd) {
131         case CLI_INIT:
132                 e->command = "ari show app";
133                 e->usage =
134                         "Usage: ari show app <application>\n"
135                         "       Provide detailed information about a registered application.\n"
136                         ;
137                 return NULL;
138         case CLI_GENERATE:
139                 return complete_ari_show_app(a);
140         default:
141                 break;
142         }
143
144         if (a->argc != 4) {
145                 return CLI_SHOWUSAGE;
146         }
147
148         app = stasis_app_get_by_name(a->argv[3]);
149         if (!app) {
150                 return CLI_FAILURE;
151         }
152
153         app_to_cli(app, a);
154
155         ao2_ref(app, -1);
156
157         return CLI_SUCCESS;
158 }
159
160 static char *ari_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
161 {
162         void *app;
163         int debug;
164
165         switch (cmd) {
166         case CLI_INIT:
167                 e->command = "ari set debug";
168                 e->usage =
169                         "Usage: ari set debug <application> <on|off>\n"
170                         "       Enable or disable debugging on a specific application.\n"
171                         ;
172                 return NULL;
173         case CLI_GENERATE:
174                 return complete_ari_show_app(a);
175         default:
176                 break;
177         }
178
179         if (a->argc != 5) {
180                 return CLI_SHOWUSAGE;
181         }
182
183         app = stasis_app_get_by_name(a->argv[3]);
184         if (!app) {
185                 return CLI_FAILURE;
186         }
187
188         debug = !strcmp(a->argv[4], "on");
189         app_set_debug(app, debug);
190         ast_cli(a->fd, "Debugging on '%s' %s\n",
191                 app_name(app),
192                 debug ? "enabled" : "disabled");
193
194         ao2_ref(app, -1);
195
196         return CLI_SUCCESS;
197 }
198
199 static struct ast_cli_entry cli_ari[] = {
200         AST_CLI_DEFINE(ari_show_apps, "List registered ARI applications"),
201         AST_CLI_DEFINE(ari_show_app, "Display details of a registered ARI application"),
202         AST_CLI_DEFINE(ari_set_debug, "Enable/disable debugging of an ARI application"),
203 };
204
205
206 int cli_init(void)
207 {
208         return ast_cli_register_multiple(cli_ari, ARRAY_LEN(cli_ari));
209 }
210
211 void cli_cleanup(void)
212 {
213         ast_cli_unregister_multiple(cli_ari, ARRAY_LEN(cli_ari));
214 }