resource_endpoints.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  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. /*! \file
  19. *
  20. * \brief /api-docs/endpoints.{format} implementation- Endpoint resources
  21. *
  22. * \author David M. Lee, II <dlee@digium.com>
  23. */
  24. #include "asterisk.h"
  25. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  26. #include "resource_endpoints.h"
  27. #include "asterisk/astobj2.h"
  28. #include "asterisk/stasis.h"
  29. #include "asterisk/stasis_app.h"
  30. #include "asterisk/stasis_endpoints.h"
  31. #include "asterisk/channel.h"
  32. #include "asterisk/message.h"
  33. void ast_ari_endpoints_list(struct ast_variable *headers,
  34. struct ast_ari_endpoints_list_args *args,
  35. struct ast_ari_response *response)
  36. {
  37. RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
  38. RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
  39. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  40. struct ao2_iterator i;
  41. void *obj;
  42. cache = ast_endpoint_cache();
  43. if (!cache) {
  44. ast_ari_response_error(
  45. response, 500, "Internal Server Error",
  46. "Message bus not initialized");
  47. return;
  48. }
  49. ao2_ref(cache, +1);
  50. snapshots = stasis_cache_dump(cache, ast_endpoint_snapshot_type());
  51. if (!snapshots) {
  52. ast_ari_response_alloc_failed(response);
  53. return;
  54. }
  55. json = ast_json_array_create();
  56. if (!json) {
  57. ast_ari_response_alloc_failed(response);
  58. return;
  59. }
  60. i = ao2_iterator_init(snapshots, 0);
  61. while ((obj = ao2_iterator_next(&i))) {
  62. RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
  63. struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
  64. struct ast_json *json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
  65. if (!json_endpoint || ast_json_array_append(json, json_endpoint)) {
  66. ao2_iterator_destroy(&i);
  67. ast_ari_response_alloc_failed(response);
  68. return;
  69. }
  70. }
  71. ao2_iterator_destroy(&i);
  72. ast_ari_response_ok(response, ast_json_ref(json));
  73. }
  74. void ast_ari_endpoints_list_by_tech(struct ast_variable *headers,
  75. struct ast_ari_endpoints_list_by_tech_args *args,
  76. struct ast_ari_response *response)
  77. {
  78. RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
  79. RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
  80. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  81. struct ast_endpoint *tech_endpoint;
  82. struct ao2_iterator i;
  83. void *obj;
  84. tech_endpoint = ast_endpoint_find_by_id(args->tech);
  85. if (!tech_endpoint) {
  86. ast_ari_response_error(response, 404, "Not Found",
  87. "No Endpoints found - invalid tech %s", args->tech);
  88. return;
  89. }
  90. ao2_ref(tech_endpoint, -1);
  91. cache = ast_endpoint_cache();
  92. if (!cache) {
  93. ast_ari_response_error(
  94. response, 500, "Internal Server Error",
  95. "Message bus not initialized");
  96. return;
  97. }
  98. ao2_ref(cache, +1);
  99. snapshots = stasis_cache_dump(cache, ast_endpoint_snapshot_type());
  100. if (!snapshots) {
  101. ast_ari_response_alloc_failed(response);
  102. return;
  103. }
  104. json = ast_json_array_create();
  105. if (!json) {
  106. ast_ari_response_alloc_failed(response);
  107. return;
  108. }
  109. i = ao2_iterator_init(snapshots, 0);
  110. while ((obj = ao2_iterator_next(&i))) {
  111. RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
  112. struct ast_endpoint_snapshot *snapshot = stasis_message_data(msg);
  113. struct ast_json *json_endpoint;
  114. int r;
  115. if (strcasecmp(args->tech, snapshot->tech) != 0) {
  116. continue;
  117. }
  118. json_endpoint = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
  119. if (!json_endpoint) {
  120. continue;
  121. }
  122. r = ast_json_array_append(
  123. json, json_endpoint);
  124. if (r != 0) {
  125. ao2_iterator_destroy(&i);
  126. ast_ari_response_alloc_failed(response);
  127. return;
  128. }
  129. }
  130. ao2_iterator_destroy(&i);
  131. ast_ari_response_ok(response, ast_json_ref(json));
  132. }
  133. void ast_ari_endpoints_get(struct ast_variable *headers,
  134. struct ast_ari_endpoints_get_args *args,
  135. struct ast_ari_response *response)
  136. {
  137. struct ast_json *json;
  138. RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
  139. snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource);
  140. if (!snapshot) {
  141. ast_ari_response_error(response, 404, "Not Found",
  142. "Endpoint not found");
  143. return;
  144. }
  145. json = ast_endpoint_snapshot_to_json(snapshot, stasis_app_get_sanitizer());
  146. if (!json) {
  147. ast_ari_response_alloc_failed(response);
  148. return;
  149. }
  150. ast_ari_response_ok(response, json);
  151. }
  152. static void send_message(const char *to, const char *from, const char *body, struct ast_variable *variables, struct ast_ari_response *response)
  153. {
  154. struct ast_variable *current;
  155. struct ast_msg *msg;
  156. int res = 0;
  157. if (ast_strlen_zero(to)) {
  158. ast_ari_response_error(response, 400, "Bad Request",
  159. "To must be specified");
  160. return;
  161. }
  162. msg = ast_msg_alloc();
  163. if (!msg) {
  164. ast_ari_response_alloc_failed(response);
  165. return;
  166. }
  167. res |= ast_msg_set_from(msg, "%s", from);
  168. res |= ast_msg_set_to(msg, "%s", to);
  169. if (!ast_strlen_zero(body)) {
  170. res |= ast_msg_set_body(msg, "%s", body);
  171. }
  172. for (current = variables; current; current = current->next) {
  173. res |= ast_msg_set_var_outbound(msg, current->name, current->value);
  174. }
  175. if (res) {
  176. ast_ari_response_alloc_failed(response);
  177. ast_msg_destroy(msg);
  178. return;
  179. }
  180. if (ast_msg_send(msg, to, from)) {
  181. ast_ari_response_error(response, 404, "Not Found",
  182. "Endpoint not found");
  183. }
  184. response->message = ast_json_null();
  185. response->response_code = 202;
  186. response->response_text = "Accepted";
  187. }
  188. /*!
  189. * \internal
  190. * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
  191. * \since 13.3.0
  192. *
  193. * \param[out] response HTTP response if error
  194. * \param json_variables The JSON blob containing the variable
  195. * \param[out] variables An out reference to the variables to populate.
  196. *
  197. * \retval 0 on success.
  198. * \retval -1 on error.
  199. */
  200. static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
  201. {
  202. enum ast_json_to_ast_vars_code res;
  203. res = ast_json_to_ast_variables(json_variables, variables);
  204. switch (res) {
  205. case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
  206. return 0;
  207. case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
  208. ast_ari_response_error(response, 400, "Bad Request",
  209. "Only string values in the 'variables' object allowed");
  210. break;
  211. case AST_JSON_TO_AST_VARS_CODE_OOM:
  212. ast_ari_response_alloc_failed(response);
  213. break;
  214. }
  215. ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
  216. return -1;
  217. }
  218. void ast_ari_endpoints_send_message(struct ast_variable *headers,
  219. struct ast_ari_endpoints_send_message_args *args,
  220. struct ast_ari_response *response)
  221. {
  222. struct ast_variable *variables = NULL;
  223. if (args->variables) {
  224. struct ast_json *json_variables;
  225. ast_ari_endpoints_send_message_parse_body(args->variables, args);
  226. json_variables = ast_json_object_get(args->variables, "variables");
  227. if (json_variables
  228. && json_to_ast_variables(response, json_variables, &variables)) {
  229. return;
  230. }
  231. }
  232. send_message(args->to, args->from, args->body, variables, response);
  233. ast_variables_destroy(variables);
  234. }
  235. void ast_ari_endpoints_send_message_to_endpoint(struct ast_variable *headers,
  236. struct ast_ari_endpoints_send_message_to_endpoint_args *args,
  237. struct ast_ari_response *response)
  238. {
  239. struct ast_variable *variables = NULL;
  240. struct ast_endpoint_snapshot *snapshot;
  241. char msg_to[128];
  242. char *tech = ast_strdupa(args->tech);
  243. /* Really, we just want to know if this thing exists */
  244. snapshot = ast_endpoint_latest_snapshot(args->tech, args->resource);
  245. if (!snapshot) {
  246. ast_ari_response_error(response, 404, "Not Found",
  247. "Endpoint not found");
  248. return;
  249. }
  250. ao2_ref(snapshot, -1);
  251. if (args->variables) {
  252. struct ast_json *json_variables;
  253. ast_ari_endpoints_send_message_to_endpoint_parse_body(args->variables, args);
  254. json_variables = ast_json_object_get(args->variables, "variables");
  255. if (json_variables
  256. && json_to_ast_variables(response, json_variables, &variables)) {
  257. return;
  258. }
  259. }
  260. snprintf(msg_to, sizeof(msg_to), "%s:%s", ast_str_to_lower(tech), args->resource);
  261. send_message(msg_to, args->from, args->body, variables, response);
  262. ast_variables_destroy(variables);
  263. }