Asterisk - The Open Source Telephony Project  21.4.1
res_ari_applications.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 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 Stasis application 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"
47 #if defined(AST_DEVMODE)
49 #endif
50 
51 #define MAX_VALS 128
52 
53 /*!
54  * \brief Parameter parsing callback for /applications.
55  * \param ser TCP/TLS session object
56  * \param get_params GET parameters in the HTTP request.
57  * \param path_vars Path variables extracted from the request.
58  * \param headers HTTP headers.
59  * \param body
60  * \param[out] response Response to the HTTP request.
61  */
63  struct ast_tcptls_session_instance *ser,
64  struct ast_variable *get_params, struct ast_variable *path_vars,
65  struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
66 {
67  struct ast_ari_applications_list_args args = {};
68 #if defined(AST_DEVMODE)
69  int is_valid;
70  int code;
71 #endif /* AST_DEVMODE */
72 
73  ast_ari_applications_list(headers, &args, response);
74 #if defined(AST_DEVMODE)
75  code = response->response_code;
76 
77  switch (code) {
78  case 0: /* Implementation is still a stub, or the code wasn't set */
79  is_valid = response->message == NULL;
80  break;
81  case 500: /* Internal Server Error */
82  case 501: /* Not Implemented */
83  is_valid = 1;
84  break;
85  default:
86  if (200 <= code && code <= 299) {
87  is_valid = ast_ari_validate_list(response->message,
89  } else {
90  ast_log(LOG_ERROR, "Invalid error response %d for /applications\n", code);
91  is_valid = 0;
92  }
93  }
94 
95  if (!is_valid) {
96  ast_log(LOG_ERROR, "Response validation failed for /applications\n");
97  ast_ari_response_error(response, 500,
98  "Internal Server Error", "Response validation failed");
99  }
100 #endif /* AST_DEVMODE */
101 
102 fin: __attribute__((unused))
103  return;
104 }
105 /*!
106  * \brief Parameter parsing callback for /applications/{applicationName}.
107  * \param ser TCP/TLS session object
108  * \param get_params GET parameters in the HTTP request.
109  * \param path_vars Path variables extracted from the request.
110  * \param headers HTTP headers.
111  * \param body
112  * \param[out] response Response to the HTTP request.
113  */
115  struct ast_tcptls_session_instance *ser,
116  struct ast_variable *get_params, struct ast_variable *path_vars,
117  struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
118 {
119  struct ast_ari_applications_get_args args = {};
120  struct ast_variable *i;
121 #if defined(AST_DEVMODE)
122  int is_valid;
123  int code;
124 #endif /* AST_DEVMODE */
125 
126  for (i = path_vars; i; i = i->next) {
127  if (strcmp(i->name, "applicationName") == 0) {
128  args.application_name = (i->value);
129  } else
130  {}
131  }
132  ast_ari_applications_get(headers, &args, response);
133 #if defined(AST_DEVMODE)
134  code = response->response_code;
135 
136  switch (code) {
137  case 0: /* Implementation is still a stub, or the code wasn't set */
138  is_valid = response->message == NULL;
139  break;
140  case 500: /* Internal Server Error */
141  case 501: /* Not Implemented */
142  case 404: /* Application does not exist. */
143  is_valid = 1;
144  break;
145  default:
146  if (200 <= code && code <= 299) {
147  is_valid = ast_ari_validate_application(
148  response->message);
149  } else {
150  ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}\n", code);
151  is_valid = 0;
152  }
153  }
154 
155  if (!is_valid) {
156  ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}\n");
157  ast_ari_response_error(response, 500,
158  "Internal Server Error", "Response validation failed");
159  }
160 #endif /* AST_DEVMODE */
161 
162 fin: __attribute__((unused))
163  return;
164 }
166  struct ast_json *body,
168 {
169  struct ast_json *field;
170  /* Parse query parameters out of it */
171  field = ast_json_object_get(body, "eventSource");
172  if (field) {
173  /* If they were silly enough to both pass in a query param and a
174  * JSON body, free up the query value.
175  */
176  ast_free(args->event_source);
177  if (ast_json_typeof(field) == AST_JSON_ARRAY) {
178  /* Multiple param passed as array */
179  size_t i;
181  args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
182 
183  if (!args->event_source) {
184  return -1;
185  }
186 
187  for (i = 0; i < args->event_source_count; ++i) {
189  }
190  } else {
191  /* Multiple param passed as single value */
192  args->event_source_count = 1;
193  args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
194  if (!args->event_source) {
195  return -1;
196  }
197  args->event_source[0] = ast_json_string_get(field);
198  }
199  }
200  return 0;
201 }
202 
203 /*!
204  * \brief Parameter parsing callback for /applications/{applicationName}/subscription.
205  * \param ser TCP/TLS session object
206  * \param get_params GET parameters in the HTTP request.
207  * \param path_vars Path variables extracted from the request.
208  * \param headers HTTP headers.
209  * \param body
210  * \param[out] response Response to the HTTP request.
211  */
213  struct ast_tcptls_session_instance *ser,
214  struct ast_variable *get_params, struct ast_variable *path_vars,
215  struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
216 {
217  struct ast_ari_applications_subscribe_args args = {};
218  struct ast_variable *i;
219 #if defined(AST_DEVMODE)
220  int is_valid;
221  int code;
222 #endif /* AST_DEVMODE */
223 
224  for (i = get_params; i; i = i->next) {
225  if (strcmp(i->name, "eventSource") == 0) {
226  /* Parse comma separated list */
227  char *vals[MAX_VALS];
228  size_t j;
229 
231  if (!args.event_source_parse) {
233  goto fin;
234  }
235 
236  if (strlen(args.event_source_parse) == 0) {
237  /* ast_app_separate_args can't handle "" */
238  args.event_source_count = 1;
239  vals[0] = args.event_source_parse;
240  } else {
241  args.event_source_count = ast_app_separate_args(
242  args.event_source_parse, ',', vals,
243  ARRAY_LEN(vals));
244  }
245 
246  if (args.event_source_count == 0) {
248  goto fin;
249  }
250 
251  if (args.event_source_count >= MAX_VALS) {
252  ast_ari_response_error(response, 400,
253  "Bad Request",
254  "Too many values for event_source");
255  goto fin;
256  }
257 
258  args.event_source = ast_malloc(sizeof(*args.event_source) * args.event_source_count);
259  if (!args.event_source) {
261  goto fin;
262  }
263 
264  for (j = 0; j < args.event_source_count; ++j) {
265  args.event_source[j] = (vals[j]);
266  }
267  } else
268  {}
269  }
270  for (i = path_vars; i; i = i->next) {
271  if (strcmp(i->name, "applicationName") == 0) {
272  args.application_name = (i->value);
273  } else
274  {}
275  }
278  goto fin;
279  }
280  ast_ari_applications_subscribe(headers, &args, response);
281 #if defined(AST_DEVMODE)
282  code = response->response_code;
283 
284  switch (code) {
285  case 0: /* Implementation is still a stub, or the code wasn't set */
286  is_valid = response->message == NULL;
287  break;
288  case 500: /* Internal Server Error */
289  case 501: /* Not Implemented */
290  case 400: /* Missing parameter. */
291  case 404: /* Application does not exist. */
292  case 422: /* Event source does not exist. */
293  is_valid = 1;
294  break;
295  default:
296  if (200 <= code && code <= 299) {
297  is_valid = ast_ari_validate_application(
298  response->message);
299  } else {
300  ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/subscription\n", code);
301  is_valid = 0;
302  }
303  }
304 
305  if (!is_valid) {
306  ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/subscription\n");
307  ast_ari_response_error(response, 500,
308  "Internal Server Error", "Response validation failed");
309  }
310 #endif /* AST_DEVMODE */
311 
312 fin: __attribute__((unused))
313  ast_free(args.event_source_parse);
314  ast_free(args.event_source);
315  return;
316 }
318  struct ast_json *body,
320 {
321  struct ast_json *field;
322  /* Parse query parameters out of it */
323  field = ast_json_object_get(body, "eventSource");
324  if (field) {
325  /* If they were silly enough to both pass in a query param and a
326  * JSON body, free up the query value.
327  */
328  ast_free(args->event_source);
329  if (ast_json_typeof(field) == AST_JSON_ARRAY) {
330  /* Multiple param passed as array */
331  size_t i;
333  args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
334 
335  if (!args->event_source) {
336  return -1;
337  }
338 
339  for (i = 0; i < args->event_source_count; ++i) {
341  }
342  } else {
343  /* Multiple param passed as single value */
344  args->event_source_count = 1;
345  args->event_source = ast_malloc(sizeof(*args->event_source) * args->event_source_count);
346  if (!args->event_source) {
347  return -1;
348  }
349  args->event_source[0] = ast_json_string_get(field);
350  }
351  }
352  return 0;
353 }
354 
355 /*!
356  * \brief Parameter parsing callback for /applications/{applicationName}/subscription.
357  * \param ser TCP/TLS session object
358  * \param get_params GET parameters in the HTTP request.
359  * \param path_vars Path variables extracted from the request.
360  * \param headers HTTP headers.
361  * \param body
362  * \param[out] response Response to the HTTP request.
363  */
365  struct ast_tcptls_session_instance *ser,
366  struct ast_variable *get_params, struct ast_variable *path_vars,
367  struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
368 {
369  struct ast_ari_applications_unsubscribe_args args = {};
370  struct ast_variable *i;
371 #if defined(AST_DEVMODE)
372  int is_valid;
373  int code;
374 #endif /* AST_DEVMODE */
375 
376  for (i = get_params; i; i = i->next) {
377  if (strcmp(i->name, "eventSource") == 0) {
378  /* Parse comma separated list */
379  char *vals[MAX_VALS];
380  size_t j;
381 
383  if (!args.event_source_parse) {
385  goto fin;
386  }
387 
388  if (strlen(args.event_source_parse) == 0) {
389  /* ast_app_separate_args can't handle "" */
390  args.event_source_count = 1;
391  vals[0] = args.event_source_parse;
392  } else {
393  args.event_source_count = ast_app_separate_args(
394  args.event_source_parse, ',', vals,
395  ARRAY_LEN(vals));
396  }
397 
398  if (args.event_source_count == 0) {
400  goto fin;
401  }
402 
403  if (args.event_source_count >= MAX_VALS) {
404  ast_ari_response_error(response, 400,
405  "Bad Request",
406  "Too many values for event_source");
407  goto fin;
408  }
409 
410  args.event_source = ast_malloc(sizeof(*args.event_source) * args.event_source_count);
411  if (!args.event_source) {
413  goto fin;
414  }
415 
416  for (j = 0; j < args.event_source_count; ++j) {
417  args.event_source[j] = (vals[j]);
418  }
419  } else
420  {}
421  }
422  for (i = path_vars; i; i = i->next) {
423  if (strcmp(i->name, "applicationName") == 0) {
424  args.application_name = (i->value);
425  } else
426  {}
427  }
430  goto fin;
431  }
432  ast_ari_applications_unsubscribe(headers, &args, response);
433 #if defined(AST_DEVMODE)
434  code = response->response_code;
435 
436  switch (code) {
437  case 0: /* Implementation is still a stub, or the code wasn't set */
438  is_valid = response->message == NULL;
439  break;
440  case 500: /* Internal Server Error */
441  case 501: /* Not Implemented */
442  case 400: /* Missing parameter; event source scheme not recognized. */
443  case 404: /* Application does not exist. */
444  case 409: /* Application not subscribed to event source. */
445  case 422: /* Event source does not exist. */
446  is_valid = 1;
447  break;
448  default:
449  if (200 <= code && code <= 299) {
450  is_valid = ast_ari_validate_application(
451  response->message);
452  } else {
453  ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/subscription\n", code);
454  is_valid = 0;
455  }
456  }
457 
458  if (!is_valid) {
459  ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/subscription\n");
460  ast_ari_response_error(response, 500,
461  "Internal Server Error", "Response validation failed");
462  }
463 #endif /* AST_DEVMODE */
464 
465 fin: __attribute__((unused))
466  ast_free(args.event_source_parse);
467  ast_free(args.event_source);
468  return;
469 }
471  struct ast_json *body,
473 {
474  /* Parse query parameters out of it */
475  return 0;
476 }
477 
478 /*!
479  * \brief Parameter parsing callback for /applications/{applicationName}/eventFilter.
480  * \param ser TCP/TLS session object
481  * \param get_params GET parameters in the HTTP request.
482  * \param path_vars Path variables extracted from the request.
483  * \param headers HTTP headers.
484  * \param body
485  * \param[out] response Response to the HTTP request.
486  */
488  struct ast_tcptls_session_instance *ser,
489  struct ast_variable *get_params, struct ast_variable *path_vars,
490  struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
491 {
492  struct ast_ari_applications_filter_args args = {};
493  struct ast_variable *i;
494 #if defined(AST_DEVMODE)
495  int is_valid;
496  int code;
497 #endif /* AST_DEVMODE */
498 
499  for (i = path_vars; i; i = i->next) {
500  if (strcmp(i->name, "applicationName") == 0) {
501  args.application_name = (i->value);
502  } else
503  {}
504  }
505  args.filter = body;
506  ast_ari_applications_filter(headers, &args, response);
507 #if defined(AST_DEVMODE)
508  code = response->response_code;
509 
510  switch (code) {
511  case 0: /* Implementation is still a stub, or the code wasn't set */
512  is_valid = response->message == NULL;
513  break;
514  case 500: /* Internal Server Error */
515  case 501: /* Not Implemented */
516  case 400: /* Bad request. */
517  case 404: /* Application does not exist. */
518  is_valid = 1;
519  break;
520  default:
521  if (200 <= code && code <= 299) {
522  is_valid = ast_ari_validate_application(
523  response->message);
524  } else {
525  ast_log(LOG_ERROR, "Invalid error response %d for /applications/{applicationName}/eventFilter\n", code);
526  is_valid = 0;
527  }
528  }
529 
530  if (!is_valid) {
531  ast_log(LOG_ERROR, "Response validation failed for /applications/{applicationName}/eventFilter\n");
532  ast_ari_response_error(response, 500,
533  "Internal Server Error", "Response validation failed");
534  }
535 #endif /* AST_DEVMODE */
536 
537 fin: __attribute__((unused))
538  return;
539 }
540 
541 /*! \brief REST handler for /api-docs/applications.json */
543  .path_segment = "subscription",
544  .callbacks = {
545  [AST_HTTP_POST] = ast_ari_applications_subscribe_cb,
546  [AST_HTTP_DELETE] = ast_ari_applications_unsubscribe_cb,
547  },
548  .num_children = 0,
549  .children = { }
550 };
551 /*! \brief REST handler for /api-docs/applications.json */
553  .path_segment = "eventFilter",
554  .callbacks = {
555  [AST_HTTP_PUT] = ast_ari_applications_filter_cb,
556  },
557  .num_children = 0,
558  .children = { }
559 };
560 /*! \brief REST handler for /api-docs/applications.json */
562  .path_segment = "applicationName",
563  .is_wildcard = 1,
564  .callbacks = {
565  [AST_HTTP_GET] = ast_ari_applications_get_cb,
566  },
567  .num_children = 2,
569 };
570 /*! \brief REST handler for /api-docs/applications.json */
572  .path_segment = "applications",
573  .callbacks = {
574  [AST_HTTP_GET] = ast_ari_applications_list_cb,
575  },
576  .num_children = 1,
577  .children = { &applications_applicationName, }
578 };
579 
580 static int unload_module(void)
581 {
582  ast_ari_remove_handler(&applications);
583  return 0;
584 }
585 
586 static int load_module(void)
587 {
588  int res = 0;
589 
590 
591  res |= ast_ari_add_handler(&applications);
592  if (res) {
593  unload_module();
595  }
596 
598 }
599 
600 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Stasis application resources",
601  .support_level = AST_MODULE_SUPPORT_CORE,
602  .load = load_module,
603  .unload = unload_module,
604  .requires = "res_ari,res_ari_model,res_stasis",
605 );
struct ast_variable * next
Asterisk main include file. File version handling, generic pbx functions.
static void ast_ari_applications_list_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Parameter parsing callback for /applications.
static struct stasis_rest_handlers applications_applicationName_eventFilter
REST handler for /api-docs/applications.json.
void ast_ari_applications_list(struct ast_variable *headers, struct ast_ari_applications_list_args *args, struct ast_ari_response *response)
List all applications.
Structure for variables, used for configurations and for channel variables.
void ast_ari_applications_unsubscribe(struct ast_variable *headers, struct ast_ari_applications_unsubscribe_args *args, struct ast_ari_response *response)
Unsubscribe an application from an event source.
static struct stasis_rest_handlers applications
REST handler for /api-docs/applications.json.
static void ast_ari_applications_get_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Parameter parsing callback for /applications/{applicationName}.
Generated file - Build validators for ARI model objects.
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
void ast_ari_response_alloc_failed(struct ast_ari_response *response)
Fill in response with a 500 message for allocation failures.
Definition: res_ari.c:298
int response_code
Definition: ari.h:99
void ast_ari_applications_get(struct ast_variable *headers, struct ast_ari_applications_get_args *args, struct ast_ari_response *response)
Get details of an application.
void ast_ari_applications_subscribe(struct ast_variable *headers, struct ast_ari_applications_subscribe_args *args, struct ast_ari_response *response)
Subscribe an application to a event source.
int ast_ari_applications_filter_parse_body(struct ast_json *body, struct ast_ari_applications_filter_args *args)
Body parsing function for /applications/{applicationName}/eventFilter.
ari_validator ast_ari_validate_application_fn(void)
Function pointer to ast_ari_validate_application().
int ast_ari_applications_subscribe_parse_body(struct ast_json *body, struct ast_ari_applications_subscribe_args *args)
Body parsing function for /applications/{applicationName}/subscription.
const char * ast_json_string_get(const struct ast_json *string)
Get the value of a JSON string.
Definition: json.c:283
#define ast_malloc(len)
A wrapper for malloc()
Definition: astmm.h:191
describes a server instance
Definition: tcptls.h:150
static void ast_ari_applications_unsubscribe_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Parameter parsing callback for /applications/{applicationName}/subscription.
static void ast_ari_applications_filter_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Parameter parsing callback for /applications/{applicationName}/eventFilter.
int ast_ari_applications_unsubscribe_parse_body(struct ast_json *body, struct ast_ari_applications_unsubscribe_args *args)
Body parsing function for /applications/{applicationName}/subscription.
int ast_ari_add_handler(struct stasis_rest_handlers *handler)
Definition: res_ari.c:179
static struct stasis_rest_handlers applications_applicationName_subscription
REST handler for /api-docs/applications.json.
int ast_ari_remove_handler(struct stasis_rest_handlers *handler)
Definition: res_ari.c:202
void ast_ari_response_error(struct ast_ari_response *response, int response_code, const char *response_text, const char *message_fmt,...)
Fill in an error ast_ari_response.
Definition: res_ari.c:259
enum ast_json_type ast_json_typeof(const struct ast_json *value)
Get the type of value.
Definition: json.c:78
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
struct ast_json * message
Definition: ari.h:94
int ast_ari_validate_application(struct ast_json *json)
Validator for Application.
const char * path_segment
Definition: ari.h:71
static struct stasis_rest_handlers applications_applicationName
REST handler for /api-docs/applications.json.
struct ast_json * ast_json_object_get(struct ast_json *object, const char *key)
Get a field from a JSON object.
Definition: json.c:407
size_t ast_json_array_size(const struct ast_json *array)
Get the size of a JSON array.
Definition: json.c:366
Abstract JSON element (object, array, string, int, ...).
Generated file - declares stubs to be implemented in res/ari/resource_applications.c.
Stasis Application API. See Stasis Application API for detailed documentation.
int ast_ari_validate_list(struct ast_json *json, int(*fn)(struct ast_json *))
Validator for a Swagger List[]/JSON array.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
Asterisk module definitions.
static void ast_ari_applications_subscribe_cb(struct ast_tcptls_session_instance *ser, struct ast_variable *get_params, struct ast_variable *path_vars, struct ast_variable *headers, struct ast_json *body, struct ast_ari_response *response)
Parameter parsing callback for /applications/{applicationName}/subscription.
struct ast_json * ast_json_array_get(const struct ast_json *array, size_t index)
Get an element from an array.
Definition: json.c:370
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
Handler for a single RESTful path segment.
Definition: ari.h:69
void ast_ari_applications_filter(struct ast_variable *headers, struct ast_ari_applications_filter_args *args, struct ast_ari_response *response)
Filter application events types.