ari: Fix #include to match generated headers for snakeCase resource files
[asterisk/asterisk.git] / rest-api-templates / res_ari_resource.c.mustache
1 {{#api_declaration}}
2 /*
3  * Asterisk -- An open source telephony toolkit.
4  *
5  * {{{copyright}}}
6  *
7  * {{{author}}}
8 {{! Template Copyright
9  * Copyright (C) 2013, Digium, Inc.
10  *
11  * David M. Lee, II <dlee@digium.com>
12 }}
13  *
14  * See http://www.asterisk.org for more information about
15  * the Asterisk project. Please do not directly contact
16  * any of the maintainers of this project for assistance;
17  * the project provides a web site, mailing lists and IRC
18  * channels for your use.
19  *
20  * This program is free software, distributed under the terms of
21  * the GNU General Public License Version 2. See the LICENSE file
22  * at the top of the source tree.
23  */
24
25 {{! Template for rendering the res_ module for an HTTP resource. }}
26 /*
27 {{> do-not-edit}}
28  * This file is generated by a mustache template. Please see the original
29  * template in rest-api-templates/res_ari_resource.c.mustache
30  */
31
32 /*! \file
33  *
34  * \brief {{{description}}}
35  *
36  * \author {{{author}}}
37  */
38
39 /*** MODULEINFO
40         <depend type="module">res_ari</depend>
41         <depend type="module">res_stasis</depend>
42         <support_level>core</support_level>
43  ***/
44
45 #include "asterisk.h"
46
47 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
48
49 #include "asterisk/app.h"
50 #include "asterisk/module.h"
51 #include "asterisk/stasis_app.h"
52 #include "ari/resource_{{c_name}}.h"
53 #if defined(AST_DEVMODE)
54 #include "ari/ari_model_validators.h"
55 #endif
56 {{^has_websocket}}
57 {{! Only include http_websocket if necessary. Otherwise we'll do a lot of
58  *  unnecessary optional_api intialization, which makes optional_api harder
59  *  to debug
60  }}
61 #include "asterisk/http_websocket.h"
62 {{/has_websocket}}
63
64 #define MAX_VALS 128
65
66 {{#apis}}
67 {{#operations}}
68 {{#is_req}}
69 /*!
70  * \brief Parameter parsing callback for {{path}}.
71  * \param get_params GET parameters in the HTTP request.
72  * \param path_vars Path variables extracted from the request.
73  * \param headers HTTP headers.
74  * \param[out] response Response to the HTTP request.
75  */
76 static void ast_ari_{{c_name}}_{{c_nickname}}_cb(
77         struct ast_variable *get_params, struct ast_variable *path_vars,
78         struct ast_variable *headers, struct ast_ari_response *response)
79 {
80         struct ast_ari_{{c_name}}_{{c_nickname}}_args args = {};
81 {{#has_parameters}}
82         struct ast_variable *i;
83 {{/has_parameters}}
84 #if defined(AST_DEVMODE)
85         int is_valid;
86         int code;
87 #endif /* AST_DEVMODE */
88
89 {{> param_parsing}}
90         ast_ari_{{c_name}}_{{c_nickname}}(headers, &args, response);
91 #if defined(AST_DEVMODE)
92         code = response->response_code;
93
94         switch (code) {
95         case 0: /* Implementation is still a stub, or the code wasn't set */
96                 is_valid = response->message == NULL;
97                 break;
98         case 500: /* Internal Server Error */
99         case 501: /* Not Implemented */
100 {{#error_responses}}
101         case {{code}}: /* {{{reason}}} */
102 {{/error_responses}}
103                 is_valid = 1;
104                 break;
105         default:
106                 if (200 <= code && code <= 299) {
107 {{#response_class}}
108 {{#is_list}}
109                         is_valid = ast_ari_validate_list(response->message,
110                                 ast_ari_validate_{{c_singular_name}}_fn());
111 {{/is_list}}
112 {{^is_list}}
113                         is_valid = ast_ari_validate_{{c_name}}(
114                                 response->message);
115 {{/is_list}}
116 {{/response_class}}
117                 } else {
118                         ast_log(LOG_ERROR, "Invalid error response %d for {{path}}\n", code);
119                         is_valid = 0;
120                 }
121         }
122
123         if (!is_valid) {
124                 ast_log(LOG_ERROR, "Response validation failed for {{path}}\n");
125                 ast_ari_response_error(response, 500,
126                         "Internal Server Error", "Response validation failed");
127         }
128 #endif /* AST_DEVMODE */
129
130 fin: __attribute__((unused))
131 {{> param_cleanup}}
132         return;
133 }
134 {{/is_req}}
135 {{#is_websocket}}
136 static void ast_ari_{{c_name}}_{{c_nickname}}_ws_cb(struct ast_websocket *ws_session,
137         struct ast_variable *get_params, struct ast_variable *headers)
138 {
139         struct ast_ari_{{c_name}}_{{c_nickname}}_args args = {};
140 {{#has_parameters}}
141         RAII_VAR(struct ast_ari_response *, response, NULL, ast_free);
142         struct ast_variable *i;
143 {{/has_parameters}}
144         RAII_VAR(struct ast_websocket *, s, ws_session, ast_websocket_unref);
145         RAII_VAR(struct ast_ari_websocket_session *, session, NULL, ao2_cleanup);
146 {{#has_path_parameters}}
147         /* TODO: It's not immediately obvious how to pass path params through
148          * the websocket code to this callback. Not needed right now, so we'll
149          * just punt. */
150         struct ast_variable *path_vars = NULL;
151 {{/has_path_parameters}}
152
153 {{#has_parameters}}
154         response = ast_calloc(1, sizeof(*response));
155         if (!response) {
156                 ast_log(LOG_ERROR, "Failed to create response.\n");
157                 goto fin;
158         }
159 {{/has_parameters}}
160
161 #if defined(AST_DEVMODE)
162         session = ast_ari_websocket_session_create(ws_session,
163                 ast_ari_validate_{{response_class.c_name}}_fn());
164 #else
165         session = ast_ari_websocket_session_create(ws_session, NULL);
166 #endif
167         if (!session) {
168                 ast_log(LOG_ERROR, "Failed to create ARI session\n");
169                 goto fin;
170         }
171
172 {{> param_parsing}}
173
174         ast_ari_websocket_{{c_name}}_{{c_nickname}}(session, headers, &args);
175
176 fin: __attribute__((unused))
177         if (response && response->response_code != 0) {
178                 /* Param parsing failure */
179                 /* TODO - ideally, this would return the error code to the
180                  * HTTP client; but we've already done the WebSocket
181                  * negotiation. Param parsing should happen earlier, but we
182                  * need a way to pass it through the WebSocket code to the
183                  * callback */
184                 RAII_VAR(char *, msg, NULL, ast_json_free);
185                 if (response->message) {
186                         msg = ast_json_dump_string(response->message);
187                 } else {
188                         ast_log(LOG_ERROR, "Missing response message\n");
189                 }
190                 if (msg) {
191                         ast_websocket_write(ws_session,
192                                 AST_WEBSOCKET_OPCODE_TEXT, msg, strlen(msg));
193                 }
194         }
195 {{> param_cleanup}}
196 }
197 {{/is_websocket}}
198 {{/operations}}
199 {{/apis}}
200
201 {{! The rest_handler partial expands to the tree of stasis_rest_handlers }}
202 {{#root_path}}
203 {{> rest_handler}}
204 {{/root_path}}
205
206 static int load_module(void)
207 {
208         int res = 0;
209 {{#apis}}
210 {{#has_websocket}}
211         {{full_name}}.ws_server = ast_websocket_server_create();
212         if (!{{full_name}}.ws_server) {
213                 return AST_MODULE_LOAD_FAILURE;
214         }
215 {{/has_websocket}}
216 {{#operations}}
217 {{#is_websocket}}
218         res |= ast_websocket_server_add_protocol({{full_name}}.ws_server,
219                 "{{websocket_protocol}}", ast_ari_{{c_name}}_{{c_nickname}}_ws_cb);
220 {{/is_websocket}}
221 {{/operations}}
222 {{/apis}}
223         stasis_app_ref();
224         res |= ast_ari_add_handler(&{{root_full_name}});
225         return res;
226 }
227
228 static int unload_module(void)
229 {
230         ast_ari_remove_handler(&{{root_full_name}});
231 {{#apis}}
232 {{#has_websocket}}
233         ao2_cleanup({{full_name}}.ws_server);
234         {{full_name}}.ws_server = NULL;
235 {{/has_websocket}}
236 {{/apis}}
237         stasis_app_unref();
238         return 0;
239 }
240
241 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - {{{description}}}",
242         .load = load_module,
243         .unload = unload_module,
244         .nonoptreq = "res_ari,res_stasis",
245         );
246 {{/api_declaration}}