res_ari_endpoints.c 13 KB

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