Merge "res_pjsip: New endpoint option "refer_blind_progress""
[asterisk/asterisk.git] / res / res_ari_endpoints.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2012 - 2013, Digium, Inc.
5  *
6  * David M. Lee, II <dlee@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 /*
20  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
21  * !!!!!                               DO NOT EDIT                        !!!!!
22  * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
23  * This file is generated by a mustache template. Please see the original
24  * template in rest-api-templates/res_ari_resource.c.mustache
25  */
26
27 /*! \file
28  *
29  * \brief Endpoint resources
30  *
31  * \author David M. Lee, II <dlee@digium.com>
32  */
33
34 /*** MODULEINFO
35         <depend type="module">res_ari</depend>
36         <depend type="module">res_ari_model</depend>
37         <depend type="module">res_stasis</depend>
38         <support_level>core</support_level>
39  ***/
40
41 #include "asterisk.h"
42
43 #include "asterisk/app.h"
44 #include "asterisk/module.h"
45 #include "asterisk/stasis_app.h"
46 #include "ari/resource_endpoints.h"
47 #if defined(AST_DEVMODE)
48 #include "ari/ari_model_validators.h"
49 #endif
50
51 #define MAX_VALS 128
52
53 /*!
54  * \brief Parameter parsing callback for /endpoints.
55  * \param get_params GET parameters in the HTTP request.
56  * \param path_vars Path variables extracted from the request.
57  * \param headers HTTP headers.
58  * \param[out] response Response to the HTTP request.
59  */
60 static void ast_ari_endpoints_list_cb(
61         struct ast_tcptls_session_instance *ser,
62         struct ast_variable *get_params, struct ast_variable *path_vars,
63         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
64 {
65         struct ast_ari_endpoints_list_args args = {};
66 #if defined(AST_DEVMODE)
67         int is_valid;
68         int code;
69 #endif /* AST_DEVMODE */
70
71         ast_ari_endpoints_list(headers, &args, response);
72 #if defined(AST_DEVMODE)
73         code = response->response_code;
74
75         switch (code) {
76         case 0: /* Implementation is still a stub, or the code wasn't set */
77                 is_valid = response->message == NULL;
78                 break;
79         case 500: /* Internal Server Error */
80         case 501: /* Not Implemented */
81                 is_valid = 1;
82                 break;
83         default:
84                 if (200 <= code && code <= 299) {
85                         is_valid = ast_ari_validate_list(response->message,
86                                 ast_ari_validate_endpoint_fn());
87                 } else {
88                         ast_log(LOG_ERROR, "Invalid error response %d for /endpoints\n", code);
89                         is_valid = 0;
90                 }
91         }
92
93         if (!is_valid) {
94                 ast_log(LOG_ERROR, "Response validation failed for /endpoints\n");
95                 ast_ari_response_error(response, 500,
96                         "Internal Server Error", "Response validation failed");
97         }
98 #endif /* AST_DEVMODE */
99
100 fin: __attribute__((unused))
101         return;
102 }
103 int ast_ari_endpoints_send_message_parse_body(
104         struct ast_json *body,
105         struct ast_ari_endpoints_send_message_args *args)
106 {
107         struct ast_json *field;
108         /* Parse query parameters out of it */
109         field = ast_json_object_get(body, "to");
110         if (field) {
111                 args->to = ast_json_string_get(field);
112         }
113         field = ast_json_object_get(body, "from");
114         if (field) {
115                 args->from = ast_json_string_get(field);
116         }
117         field = ast_json_object_get(body, "body");
118         if (field) {
119                 args->body = ast_json_string_get(field);
120         }
121         return 0;
122 }
123
124 /*!
125  * \brief Parameter parsing callback for /endpoints/sendMessage.
126  * \param get_params GET parameters in the HTTP request.
127  * \param path_vars Path variables extracted from the request.
128  * \param headers HTTP headers.
129  * \param[out] response Response to the HTTP request.
130  */
131 static void ast_ari_endpoints_send_message_cb(
132         struct ast_tcptls_session_instance *ser,
133         struct ast_variable *get_params, struct ast_variable *path_vars,
134         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
135 {
136         struct ast_ari_endpoints_send_message_args args = {};
137         struct ast_variable *i;
138 #if defined(AST_DEVMODE)
139         int is_valid;
140         int code;
141 #endif /* AST_DEVMODE */
142
143         for (i = get_params; i; i = i->next) {
144                 if (strcmp(i->name, "to") == 0) {
145                         args.to = (i->value);
146                 } else
147                 if (strcmp(i->name, "from") == 0) {
148                         args.from = (i->value);
149                 } else
150                 if (strcmp(i->name, "body") == 0) {
151                         args.body = (i->value);
152                 } else
153                 {}
154         }
155         args.variables = body;
156         ast_ari_endpoints_send_message(headers, &args, response);
157 #if defined(AST_DEVMODE)
158         code = response->response_code;
159
160         switch (code) {
161         case 0: /* Implementation is still a stub, or the code wasn't set */
162                 is_valid = response->message == NULL;
163                 break;
164         case 500: /* Internal Server Error */
165         case 501: /* Not Implemented */
166         case 400: /* Invalid parameters for sending a message. */
167         case 404: /* Endpoint not found */
168                 is_valid = 1;
169                 break;
170         default:
171                 if (200 <= code && code <= 299) {
172                         is_valid = ast_ari_validate_void(
173                                 response->message);
174                 } else {
175                         ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/sendMessage\n", code);
176                         is_valid = 0;
177                 }
178         }
179
180         if (!is_valid) {
181                 ast_log(LOG_ERROR, "Response validation failed for /endpoints/sendMessage\n");
182                 ast_ari_response_error(response, 500,
183                         "Internal Server Error", "Response validation failed");
184         }
185 #endif /* AST_DEVMODE */
186
187 fin: __attribute__((unused))
188         return;
189 }
190 /*!
191  * \brief Parameter parsing callback for /endpoints/{tech}.
192  * \param get_params GET parameters in the HTTP request.
193  * \param path_vars Path variables extracted from the request.
194  * \param headers HTTP headers.
195  * \param[out] response Response to the HTTP request.
196  */
197 static void ast_ari_endpoints_list_by_tech_cb(
198         struct ast_tcptls_session_instance *ser,
199         struct ast_variable *get_params, struct ast_variable *path_vars,
200         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
201 {
202         struct ast_ari_endpoints_list_by_tech_args args = {};
203         struct ast_variable *i;
204 #if defined(AST_DEVMODE)
205         int is_valid;
206         int code;
207 #endif /* AST_DEVMODE */
208
209         for (i = path_vars; i; i = i->next) {
210                 if (strcmp(i->name, "tech") == 0) {
211                         args.tech = (i->value);
212                 } else
213                 {}
214         }
215         ast_ari_endpoints_list_by_tech(headers, &args, response);
216 #if defined(AST_DEVMODE)
217         code = response->response_code;
218
219         switch (code) {
220         case 0: /* Implementation is still a stub, or the code wasn't set */
221                 is_valid = response->message == NULL;
222                 break;
223         case 500: /* Internal Server Error */
224         case 501: /* Not Implemented */
225         case 404: /* Endpoints not found */
226                 is_valid = 1;
227                 break;
228         default:
229                 if (200 <= code && code <= 299) {
230                         is_valid = ast_ari_validate_list(response->message,
231                                 ast_ari_validate_endpoint_fn());
232                 } else {
233                         ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}\n", code);
234                         is_valid = 0;
235                 }
236         }
237
238         if (!is_valid) {
239                 ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}\n");
240                 ast_ari_response_error(response, 500,
241                         "Internal Server Error", "Response validation failed");
242         }
243 #endif /* AST_DEVMODE */
244
245 fin: __attribute__((unused))
246         return;
247 }
248 /*!
249  * \brief Parameter parsing callback for /endpoints/{tech}/{resource}.
250  * \param get_params GET parameters in the HTTP request.
251  * \param path_vars Path variables extracted from the request.
252  * \param headers HTTP headers.
253  * \param[out] response Response to the HTTP request.
254  */
255 static void ast_ari_endpoints_get_cb(
256         struct ast_tcptls_session_instance *ser,
257         struct ast_variable *get_params, struct ast_variable *path_vars,
258         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
259 {
260         struct ast_ari_endpoints_get_args args = {};
261         struct ast_variable *i;
262 #if defined(AST_DEVMODE)
263         int is_valid;
264         int code;
265 #endif /* AST_DEVMODE */
266
267         for (i = path_vars; i; i = i->next) {
268                 if (strcmp(i->name, "tech") == 0) {
269                         args.tech = (i->value);
270                 } else
271                 if (strcmp(i->name, "resource") == 0) {
272                         args.resource = (i->value);
273                 } else
274                 {}
275         }
276         ast_ari_endpoints_get(headers, &args, response);
277 #if defined(AST_DEVMODE)
278         code = response->response_code;
279
280         switch (code) {
281         case 0: /* Implementation is still a stub, or the code wasn't set */
282                 is_valid = response->message == NULL;
283                 break;
284         case 500: /* Internal Server Error */
285         case 501: /* Not Implemented */
286         case 400: /* Invalid parameters for sending a message. */
287         case 404: /* Endpoints not found */
288                 is_valid = 1;
289                 break;
290         default:
291                 if (200 <= code && code <= 299) {
292                         is_valid = ast_ari_validate_endpoint(
293                                 response->message);
294                 } else {
295                         ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}\n", code);
296                         is_valid = 0;
297                 }
298         }
299
300         if (!is_valid) {
301                 ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}\n");
302                 ast_ari_response_error(response, 500,
303                         "Internal Server Error", "Response validation failed");
304         }
305 #endif /* AST_DEVMODE */
306
307 fin: __attribute__((unused))
308         return;
309 }
310 int ast_ari_endpoints_send_message_to_endpoint_parse_body(
311         struct ast_json *body,
312         struct ast_ari_endpoints_send_message_to_endpoint_args *args)
313 {
314         struct ast_json *field;
315         /* Parse query parameters out of it */
316         field = ast_json_object_get(body, "from");
317         if (field) {
318                 args->from = ast_json_string_get(field);
319         }
320         field = ast_json_object_get(body, "body");
321         if (field) {
322                 args->body = ast_json_string_get(field);
323         }
324         return 0;
325 }
326
327 /*!
328  * \brief Parameter parsing callback for /endpoints/{tech}/{resource}/sendMessage.
329  * \param get_params GET parameters in the HTTP request.
330  * \param path_vars Path variables extracted from the request.
331  * \param headers HTTP headers.
332  * \param[out] response Response to the HTTP request.
333  */
334 static void ast_ari_endpoints_send_message_to_endpoint_cb(
335         struct ast_tcptls_session_instance *ser,
336         struct ast_variable *get_params, struct ast_variable *path_vars,
337         struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
338 {
339         struct ast_ari_endpoints_send_message_to_endpoint_args args = {};
340         struct ast_variable *i;
341 #if defined(AST_DEVMODE)
342         int is_valid;
343         int code;
344 #endif /* AST_DEVMODE */
345
346         for (i = get_params; i; i = i->next) {
347                 if (strcmp(i->name, "from") == 0) {
348                         args.from = (i->value);
349                 } else
350                 if (strcmp(i->name, "body") == 0) {
351                         args.body = (i->value);
352                 } else
353                 {}
354         }
355         for (i = path_vars; i; i = i->next) {
356                 if (strcmp(i->name, "tech") == 0) {
357                         args.tech = (i->value);
358                 } else
359                 if (strcmp(i->name, "resource") == 0) {
360                         args.resource = (i->value);
361                 } else
362                 {}
363         }
364         args.variables = body;
365         ast_ari_endpoints_send_message_to_endpoint(headers, &args, response);
366 #if defined(AST_DEVMODE)
367         code = response->response_code;
368
369         switch (code) {
370         case 0: /* Implementation is still a stub, or the code wasn't set */
371                 is_valid = response->message == NULL;
372                 break;
373         case 500: /* Internal Server Error */
374         case 501: /* Not Implemented */
375         case 400: /* Invalid parameters for sending a message. */
376         case 404: /* Endpoint not found */
377                 is_valid = 1;
378                 break;
379         default:
380                 if (200 <= code && code <= 299) {
381                         is_valid = ast_ari_validate_void(
382                                 response->message);
383                 } else {
384                         ast_log(LOG_ERROR, "Invalid error response %d for /endpoints/{tech}/{resource}/sendMessage\n", code);
385                         is_valid = 0;
386                 }
387         }
388
389         if (!is_valid) {
390                 ast_log(LOG_ERROR, "Response validation failed for /endpoints/{tech}/{resource}/sendMessage\n");
391                 ast_ari_response_error(response, 500,
392                         "Internal Server Error", "Response validation failed");
393         }
394 #endif /* AST_DEVMODE */
395
396 fin: __attribute__((unused))
397         return;
398 }
399
400 /*! \brief REST handler for /api-docs/endpoints.json */
401 static struct stasis_rest_handlers endpoints_sendMessage = {
402         .path_segment = "sendMessage",
403         .callbacks = {
404                 [AST_HTTP_PUT] = ast_ari_endpoints_send_message_cb,
405         },
406         .num_children = 0,
407         .children = {  }
408 };
409 /*! \brief REST handler for /api-docs/endpoints.json */
410 static struct stasis_rest_handlers endpoints_tech_resource_sendMessage = {
411         .path_segment = "sendMessage",
412         .callbacks = {
413                 [AST_HTTP_PUT] = ast_ari_endpoints_send_message_to_endpoint_cb,
414         },
415         .num_children = 0,
416         .children = {  }
417 };
418 /*! \brief REST handler for /api-docs/endpoints.json */
419 static struct stasis_rest_handlers endpoints_tech_resource = {
420         .path_segment = "resource",
421         .is_wildcard = 1,
422         .callbacks = {
423                 [AST_HTTP_GET] = ast_ari_endpoints_get_cb,
424         },
425         .num_children = 1,
426         .children = { &endpoints_tech_resource_sendMessage, }
427 };
428 /*! \brief REST handler for /api-docs/endpoints.json */
429 static struct stasis_rest_handlers endpoints_tech = {
430         .path_segment = "tech",
431         .is_wildcard = 1,
432         .callbacks = {
433                 [AST_HTTP_GET] = ast_ari_endpoints_list_by_tech_cb,
434         },
435         .num_children = 1,
436         .children = { &endpoints_tech_resource, }
437 };
438 /*! \brief REST handler for /api-docs/endpoints.json */
439 static struct stasis_rest_handlers endpoints = {
440         .path_segment = "endpoints",
441         .callbacks = {
442                 [AST_HTTP_GET] = ast_ari_endpoints_list_cb,
443         },
444         .num_children = 2,
445         .children = { &endpoints_sendMessage,&endpoints_tech, }
446 };
447
448 static int unload_module(void)
449 {
450         ast_ari_remove_handler(&endpoints);
451         stasis_app_unref();
452         return 0;
453 }
454
455 static int load_module(void)
456 {
457         int res = 0;
458         stasis_app_ref();
459         res |= ast_ari_add_handler(&endpoints);
460         if (res) {
461                 unload_module();
462                 return AST_MODULE_LOAD_DECLINE;
463         }
464
465         return AST_MODULE_LOAD_SUCCESS;
466 }
467
468 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Endpoint resources",
469         .support_level = AST_MODULE_SUPPORT_CORE,
470         .load = load_module,
471         .unload = unload_module,
472         .nonoptreq = "res_ari,res_stasis",
473 );