res_ari_asterisk.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  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. * !!!!! DO NOT EDIT !!!!!
  21. * !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  22. * This file is generated by a mustache template. Please see the original
  23. * template in rest-api-templates/res_ari_resource.c.mustache
  24. */
  25. /*! \file
  26. *
  27. * \brief Asterisk resources
  28. *
  29. * \author David M. Lee, II <dlee@digium.com>
  30. */
  31. /*** MODULEINFO
  32. <depend type="module">res_ari</depend>
  33. <depend type="module">res_stasis</depend>
  34. <support_level>core</support_level>
  35. ***/
  36. #include "asterisk.h"
  37. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  38. #include "asterisk/app.h"
  39. #include "asterisk/module.h"
  40. #include "asterisk/stasis_app.h"
  41. #include "ari/resource_asterisk.h"
  42. #if defined(AST_DEVMODE)
  43. #include "ari/ari_model_validators.h"
  44. #endif
  45. #define MAX_VALS 128
  46. int ast_ari_asterisk_get_info_parse_body(
  47. struct ast_json *body,
  48. struct ast_ari_asterisk_get_info_args *args)
  49. {
  50. struct ast_json *field;
  51. /* Parse query parameters out of it */
  52. field = ast_json_object_get(body, "only");
  53. if (field) {
  54. /* If they were silly enough to both pass in a query param and a
  55. * JSON body, free up the query value.
  56. */
  57. ast_free(args->only);
  58. if (ast_json_typeof(field) == AST_JSON_ARRAY) {
  59. /* Multiple param passed as array */
  60. size_t i;
  61. args->only_count = ast_json_array_size(field);
  62. args->only = ast_malloc(sizeof(*args->only) * args->only_count);
  63. if (!args->only) {
  64. return -1;
  65. }
  66. for (i = 0; i < args->only_count; ++i) {
  67. args->only[i] = ast_json_string_get(ast_json_array_get(field, i));
  68. }
  69. } else {
  70. /* Multiple param passed as single value */
  71. args->only_count = 1;
  72. args->only = ast_malloc(sizeof(*args->only) * args->only_count);
  73. if (!args->only) {
  74. return -1;
  75. }
  76. args->only[0] = ast_json_string_get(field);
  77. }
  78. }
  79. return 0;
  80. }
  81. /*!
  82. * \brief Parameter parsing callback for /asterisk/info.
  83. * \param get_params GET parameters in the HTTP request.
  84. * \param path_vars Path variables extracted from the request.
  85. * \param headers HTTP headers.
  86. * \param[out] response Response to the HTTP request.
  87. */
  88. static void ast_ari_asterisk_get_info_cb(
  89. struct ast_tcptls_session_instance *ser,
  90. struct ast_variable *get_params, struct ast_variable *path_vars,
  91. struct ast_variable *headers, struct ast_ari_response *response)
  92. {
  93. struct ast_ari_asterisk_get_info_args args = {};
  94. struct ast_variable *i;
  95. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  96. #if defined(AST_DEVMODE)
  97. int is_valid;
  98. int code;
  99. #endif /* AST_DEVMODE */
  100. for (i = get_params; i; i = i->next) {
  101. if (strcmp(i->name, "only") == 0) {
  102. /* Parse comma separated list */
  103. char *vals[MAX_VALS];
  104. size_t j;
  105. args.only_parse = ast_strdup(i->value);
  106. if (!args.only_parse) {
  107. ast_ari_response_alloc_failed(response);
  108. goto fin;
  109. }
  110. if (strlen(args.only_parse) == 0) {
  111. /* ast_app_separate_args can't handle "" */
  112. args.only_count = 1;
  113. vals[0] = args.only_parse;
  114. } else {
  115. args.only_count = ast_app_separate_args(
  116. args.only_parse, ',', vals,
  117. ARRAY_LEN(vals));
  118. }
  119. if (args.only_count == 0) {
  120. ast_ari_response_alloc_failed(response);
  121. goto fin;
  122. }
  123. if (args.only_count >= MAX_VALS) {
  124. ast_ari_response_error(response, 400,
  125. "Bad Request",
  126. "Too many values for only");
  127. goto fin;
  128. }
  129. args.only = ast_malloc(sizeof(*args.only) * args.only_count);
  130. if (!args.only) {
  131. ast_ari_response_alloc_failed(response);
  132. goto fin;
  133. }
  134. for (j = 0; j < args.only_count; ++j) {
  135. args.only[j] = (vals[j]);
  136. }
  137. } else
  138. {}
  139. }
  140. /* Look for a JSON request entity */
  141. body = ast_http_get_json(ser, headers);
  142. if (!body) {
  143. switch (errno) {
  144. case EFBIG:
  145. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  146. goto fin;
  147. case ENOMEM:
  148. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  149. goto fin;
  150. case EIO:
  151. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  152. goto fin;
  153. }
  154. }
  155. if (ast_ari_asterisk_get_info_parse_body(body, &args)) {
  156. ast_ari_response_alloc_failed(response);
  157. goto fin;
  158. }
  159. ast_ari_asterisk_get_info(headers, &args, response);
  160. #if defined(AST_DEVMODE)
  161. code = response->response_code;
  162. switch (code) {
  163. case 0: /* Implementation is still a stub, or the code wasn't set */
  164. is_valid = response->message == NULL;
  165. break;
  166. case 500: /* Internal Server Error */
  167. case 501: /* Not Implemented */
  168. is_valid = 1;
  169. break;
  170. default:
  171. if (200 <= code && code <= 299) {
  172. is_valid = ast_ari_validate_asterisk_info(
  173. response->message);
  174. } else {
  175. ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/info\n", code);
  176. is_valid = 0;
  177. }
  178. }
  179. if (!is_valid) {
  180. ast_log(LOG_ERROR, "Response validation failed for /asterisk/info\n");
  181. ast_ari_response_error(response, 500,
  182. "Internal Server Error", "Response validation failed");
  183. }
  184. #endif /* AST_DEVMODE */
  185. fin: __attribute__((unused))
  186. ast_free(args.only_parse);
  187. ast_free(args.only);
  188. return;
  189. }
  190. int ast_ari_asterisk_get_global_var_parse_body(
  191. struct ast_json *body,
  192. struct ast_ari_asterisk_get_global_var_args *args)
  193. {
  194. struct ast_json *field;
  195. /* Parse query parameters out of it */
  196. field = ast_json_object_get(body, "variable");
  197. if (field) {
  198. args->variable = ast_json_string_get(field);
  199. }
  200. return 0;
  201. }
  202. /*!
  203. * \brief Parameter parsing callback for /asterisk/variable.
  204. * \param get_params GET parameters in the HTTP request.
  205. * \param path_vars Path variables extracted from the request.
  206. * \param headers HTTP headers.
  207. * \param[out] response Response to the HTTP request.
  208. */
  209. static void ast_ari_asterisk_get_global_var_cb(
  210. struct ast_tcptls_session_instance *ser,
  211. struct ast_variable *get_params, struct ast_variable *path_vars,
  212. struct ast_variable *headers, struct ast_ari_response *response)
  213. {
  214. struct ast_ari_asterisk_get_global_var_args args = {};
  215. struct ast_variable *i;
  216. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  217. #if defined(AST_DEVMODE)
  218. int is_valid;
  219. int code;
  220. #endif /* AST_DEVMODE */
  221. for (i = get_params; i; i = i->next) {
  222. if (strcmp(i->name, "variable") == 0) {
  223. args.variable = (i->value);
  224. } else
  225. {}
  226. }
  227. /* Look for a JSON request entity */
  228. body = ast_http_get_json(ser, headers);
  229. if (!body) {
  230. switch (errno) {
  231. case EFBIG:
  232. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  233. goto fin;
  234. case ENOMEM:
  235. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  236. goto fin;
  237. case EIO:
  238. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  239. goto fin;
  240. }
  241. }
  242. if (ast_ari_asterisk_get_global_var_parse_body(body, &args)) {
  243. ast_ari_response_alloc_failed(response);
  244. goto fin;
  245. }
  246. ast_ari_asterisk_get_global_var(headers, &args, response);
  247. #if defined(AST_DEVMODE)
  248. code = response->response_code;
  249. switch (code) {
  250. case 0: /* Implementation is still a stub, or the code wasn't set */
  251. is_valid = response->message == NULL;
  252. break;
  253. case 500: /* Internal Server Error */
  254. case 501: /* Not Implemented */
  255. case 400: /* Missing variable parameter. */
  256. is_valid = 1;
  257. break;
  258. default:
  259. if (200 <= code && code <= 299) {
  260. is_valid = ast_ari_validate_variable(
  261. response->message);
  262. } else {
  263. ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
  264. is_valid = 0;
  265. }
  266. }
  267. if (!is_valid) {
  268. ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
  269. ast_ari_response_error(response, 500,
  270. "Internal Server Error", "Response validation failed");
  271. }
  272. #endif /* AST_DEVMODE */
  273. fin: __attribute__((unused))
  274. return;
  275. }
  276. int ast_ari_asterisk_set_global_var_parse_body(
  277. struct ast_json *body,
  278. struct ast_ari_asterisk_set_global_var_args *args)
  279. {
  280. struct ast_json *field;
  281. /* Parse query parameters out of it */
  282. field = ast_json_object_get(body, "variable");
  283. if (field) {
  284. args->variable = ast_json_string_get(field);
  285. }
  286. field = ast_json_object_get(body, "value");
  287. if (field) {
  288. args->value = ast_json_string_get(field);
  289. }
  290. return 0;
  291. }
  292. /*!
  293. * \brief Parameter parsing callback for /asterisk/variable.
  294. * \param get_params GET parameters in the HTTP request.
  295. * \param path_vars Path variables extracted from the request.
  296. * \param headers HTTP headers.
  297. * \param[out] response Response to the HTTP request.
  298. */
  299. static void ast_ari_asterisk_set_global_var_cb(
  300. struct ast_tcptls_session_instance *ser,
  301. struct ast_variable *get_params, struct ast_variable *path_vars,
  302. struct ast_variable *headers, struct ast_ari_response *response)
  303. {
  304. struct ast_ari_asterisk_set_global_var_args args = {};
  305. struct ast_variable *i;
  306. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  307. #if defined(AST_DEVMODE)
  308. int is_valid;
  309. int code;
  310. #endif /* AST_DEVMODE */
  311. for (i = get_params; i; i = i->next) {
  312. if (strcmp(i->name, "variable") == 0) {
  313. args.variable = (i->value);
  314. } else
  315. if (strcmp(i->name, "value") == 0) {
  316. args.value = (i->value);
  317. } else
  318. {}
  319. }
  320. /* Look for a JSON request entity */
  321. body = ast_http_get_json(ser, headers);
  322. if (!body) {
  323. switch (errno) {
  324. case EFBIG:
  325. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  326. goto fin;
  327. case ENOMEM:
  328. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  329. goto fin;
  330. case EIO:
  331. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  332. goto fin;
  333. }
  334. }
  335. if (ast_ari_asterisk_set_global_var_parse_body(body, &args)) {
  336. ast_ari_response_alloc_failed(response);
  337. goto fin;
  338. }
  339. ast_ari_asterisk_set_global_var(headers, &args, response);
  340. #if defined(AST_DEVMODE)
  341. code = response->response_code;
  342. switch (code) {
  343. case 0: /* Implementation is still a stub, or the code wasn't set */
  344. is_valid = response->message == NULL;
  345. break;
  346. case 500: /* Internal Server Error */
  347. case 501: /* Not Implemented */
  348. case 400: /* Missing variable parameter. */
  349. is_valid = 1;
  350. break;
  351. default:
  352. if (200 <= code && code <= 299) {
  353. is_valid = ast_ari_validate_void(
  354. response->message);
  355. } else {
  356. ast_log(LOG_ERROR, "Invalid error response %d for /asterisk/variable\n", code);
  357. is_valid = 0;
  358. }
  359. }
  360. if (!is_valid) {
  361. ast_log(LOG_ERROR, "Response validation failed for /asterisk/variable\n");
  362. ast_ari_response_error(response, 500,
  363. "Internal Server Error", "Response validation failed");
  364. }
  365. #endif /* AST_DEVMODE */
  366. fin: __attribute__((unused))
  367. return;
  368. }
  369. /*! \brief REST handler for /api-docs/asterisk.{format} */
  370. static struct stasis_rest_handlers asterisk_info = {
  371. .path_segment = "info",
  372. .callbacks = {
  373. [AST_HTTP_GET] = ast_ari_asterisk_get_info_cb,
  374. },
  375. .num_children = 0,
  376. .children = { }
  377. };
  378. /*! \brief REST handler for /api-docs/asterisk.{format} */
  379. static struct stasis_rest_handlers asterisk_variable = {
  380. .path_segment = "variable",
  381. .callbacks = {
  382. [AST_HTTP_GET] = ast_ari_asterisk_get_global_var_cb,
  383. [AST_HTTP_POST] = ast_ari_asterisk_set_global_var_cb,
  384. },
  385. .num_children = 0,
  386. .children = { }
  387. };
  388. /*! \brief REST handler for /api-docs/asterisk.{format} */
  389. static struct stasis_rest_handlers asterisk = {
  390. .path_segment = "asterisk",
  391. .callbacks = {
  392. },
  393. .num_children = 2,
  394. .children = { &asterisk_info,&asterisk_variable, }
  395. };
  396. static int load_module(void)
  397. {
  398. int res = 0;
  399. stasis_app_ref();
  400. res |= ast_ari_add_handler(&asterisk);
  401. return res;
  402. }
  403. static int unload_module(void)
  404. {
  405. ast_ari_remove_handler(&asterisk);
  406. stasis_app_unref();
  407. return 0;
  408. }
  409. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Asterisk resources",
  410. .support_level = AST_MODULE_SUPPORT_CORE,
  411. .load = load_module,
  412. .unload = unload_module,
  413. .nonoptreq = "res_ari,res_stasis",
  414. );