res_ari_bridges.c 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420
  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 Bridge 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_bridges.h"
  42. #if defined(AST_DEVMODE)
  43. #include "ari/ari_model_validators.h"
  44. #endif
  45. #define MAX_VALS 128
  46. /*!
  47. * \brief Parameter parsing callback for /bridges.
  48. * \param get_params GET parameters in the HTTP request.
  49. * \param path_vars Path variables extracted from the request.
  50. * \param headers HTTP headers.
  51. * \param[out] response Response to the HTTP request.
  52. */
  53. static void ast_ari_bridges_list_cb(
  54. struct ast_tcptls_session_instance *ser,
  55. struct ast_variable *get_params, struct ast_variable *path_vars,
  56. struct ast_variable *headers, struct ast_ari_response *response)
  57. {
  58. struct ast_ari_bridges_list_args args = {};
  59. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  60. #if defined(AST_DEVMODE)
  61. int is_valid;
  62. int code;
  63. #endif /* AST_DEVMODE */
  64. ast_ari_bridges_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_bridge_fn());
  79. } else {
  80. ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
  81. is_valid = 0;
  82. }
  83. }
  84. if (!is_valid) {
  85. ast_log(LOG_ERROR, "Response validation failed for /bridges\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_bridges_create_parse_body(
  94. struct ast_json *body,
  95. struct ast_ari_bridges_create_args *args)
  96. {
  97. struct ast_json *field;
  98. /* Parse query parameters out of it */
  99. field = ast_json_object_get(body, "type");
  100. if (field) {
  101. args->type = ast_json_string_get(field);
  102. }
  103. field = ast_json_object_get(body, "bridgeId");
  104. if (field) {
  105. args->bridge_id = ast_json_string_get(field);
  106. }
  107. field = ast_json_object_get(body, "name");
  108. if (field) {
  109. args->name = ast_json_string_get(field);
  110. }
  111. return 0;
  112. }
  113. /*!
  114. * \brief Parameter parsing callback for /bridges.
  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_bridges_create_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_ari_response *response)
  124. {
  125. struct ast_ari_bridges_create_args args = {};
  126. struct ast_variable *i;
  127. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  128. #if defined(AST_DEVMODE)
  129. int is_valid;
  130. int code;
  131. #endif /* AST_DEVMODE */
  132. for (i = get_params; i; i = i->next) {
  133. if (strcmp(i->name, "type") == 0) {
  134. args.type = (i->value);
  135. } else
  136. if (strcmp(i->name, "bridgeId") == 0) {
  137. args.bridge_id = (i->value);
  138. } else
  139. if (strcmp(i->name, "name") == 0) {
  140. args.name = (i->value);
  141. } else
  142. {}
  143. }
  144. /* Look for a JSON request entity */
  145. body = ast_http_get_json(ser, headers);
  146. if (!body) {
  147. switch (errno) {
  148. case EFBIG:
  149. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  150. goto fin;
  151. case ENOMEM:
  152. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  153. goto fin;
  154. case EIO:
  155. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  156. goto fin;
  157. }
  158. }
  159. if (ast_ari_bridges_create_parse_body(body, &args)) {
  160. ast_ari_response_alloc_failed(response);
  161. goto fin;
  162. }
  163. ast_ari_bridges_create(headers, &args, response);
  164. #if defined(AST_DEVMODE)
  165. code = response->response_code;
  166. switch (code) {
  167. case 0: /* Implementation is still a stub, or the code wasn't set */
  168. is_valid = response->message == NULL;
  169. break;
  170. case 500: /* Internal Server Error */
  171. case 501: /* Not Implemented */
  172. is_valid = 1;
  173. break;
  174. default:
  175. if (200 <= code && code <= 299) {
  176. is_valid = ast_ari_validate_bridge(
  177. response->message);
  178. } else {
  179. ast_log(LOG_ERROR, "Invalid error response %d for /bridges\n", code);
  180. is_valid = 0;
  181. }
  182. }
  183. if (!is_valid) {
  184. ast_log(LOG_ERROR, "Response validation failed for /bridges\n");
  185. ast_ari_response_error(response, 500,
  186. "Internal Server Error", "Response validation failed");
  187. }
  188. #endif /* AST_DEVMODE */
  189. fin: __attribute__((unused))
  190. return;
  191. }
  192. int ast_ari_bridges_create_or_update_with_id_parse_body(
  193. struct ast_json *body,
  194. struct ast_ari_bridges_create_or_update_with_id_args *args)
  195. {
  196. struct ast_json *field;
  197. /* Parse query parameters out of it */
  198. field = ast_json_object_get(body, "type");
  199. if (field) {
  200. args->type = ast_json_string_get(field);
  201. }
  202. field = ast_json_object_get(body, "name");
  203. if (field) {
  204. args->name = ast_json_string_get(field);
  205. }
  206. return 0;
  207. }
  208. /*!
  209. * \brief Parameter parsing callback for /bridges/{bridgeId}.
  210. * \param get_params GET parameters in the HTTP request.
  211. * \param path_vars Path variables extracted from the request.
  212. * \param headers HTTP headers.
  213. * \param[out] response Response to the HTTP request.
  214. */
  215. static void ast_ari_bridges_create_or_update_with_id_cb(
  216. struct ast_tcptls_session_instance *ser,
  217. struct ast_variable *get_params, struct ast_variable *path_vars,
  218. struct ast_variable *headers, struct ast_ari_response *response)
  219. {
  220. struct ast_ari_bridges_create_or_update_with_id_args args = {};
  221. struct ast_variable *i;
  222. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  223. #if defined(AST_DEVMODE)
  224. int is_valid;
  225. int code;
  226. #endif /* AST_DEVMODE */
  227. for (i = get_params; i; i = i->next) {
  228. if (strcmp(i->name, "type") == 0) {
  229. args.type = (i->value);
  230. } else
  231. if (strcmp(i->name, "name") == 0) {
  232. args.name = (i->value);
  233. } else
  234. {}
  235. }
  236. for (i = path_vars; i; i = i->next) {
  237. if (strcmp(i->name, "bridgeId") == 0) {
  238. args.bridge_id = (i->value);
  239. } else
  240. {}
  241. }
  242. /* Look for a JSON request entity */
  243. body = ast_http_get_json(ser, headers);
  244. if (!body) {
  245. switch (errno) {
  246. case EFBIG:
  247. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  248. goto fin;
  249. case ENOMEM:
  250. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  251. goto fin;
  252. case EIO:
  253. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  254. goto fin;
  255. }
  256. }
  257. if (ast_ari_bridges_create_or_update_with_id_parse_body(body, &args)) {
  258. ast_ari_response_alloc_failed(response);
  259. goto fin;
  260. }
  261. ast_ari_bridges_create_or_update_with_id(headers, &args, response);
  262. #if defined(AST_DEVMODE)
  263. code = response->response_code;
  264. switch (code) {
  265. case 0: /* Implementation is still a stub, or the code wasn't set */
  266. is_valid = response->message == NULL;
  267. break;
  268. case 500: /* Internal Server Error */
  269. case 501: /* Not Implemented */
  270. is_valid = 1;
  271. break;
  272. default:
  273. if (200 <= code && code <= 299) {
  274. is_valid = ast_ari_validate_bridge(
  275. response->message);
  276. } else {
  277. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
  278. is_valid = 0;
  279. }
  280. }
  281. if (!is_valid) {
  282. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
  283. ast_ari_response_error(response, 500,
  284. "Internal Server Error", "Response validation failed");
  285. }
  286. #endif /* AST_DEVMODE */
  287. fin: __attribute__((unused))
  288. return;
  289. }
  290. /*!
  291. * \brief Parameter parsing callback for /bridges/{bridgeId}.
  292. * \param get_params GET parameters in the HTTP request.
  293. * \param path_vars Path variables extracted from the request.
  294. * \param headers HTTP headers.
  295. * \param[out] response Response to the HTTP request.
  296. */
  297. static void ast_ari_bridges_get_cb(
  298. struct ast_tcptls_session_instance *ser,
  299. struct ast_variable *get_params, struct ast_variable *path_vars,
  300. struct ast_variable *headers, struct ast_ari_response *response)
  301. {
  302. struct ast_ari_bridges_get_args args = {};
  303. struct ast_variable *i;
  304. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  305. #if defined(AST_DEVMODE)
  306. int is_valid;
  307. int code;
  308. #endif /* AST_DEVMODE */
  309. for (i = path_vars; i; i = i->next) {
  310. if (strcmp(i->name, "bridgeId") == 0) {
  311. args.bridge_id = (i->value);
  312. } else
  313. {}
  314. }
  315. ast_ari_bridges_get(headers, &args, response);
  316. #if defined(AST_DEVMODE)
  317. code = response->response_code;
  318. switch (code) {
  319. case 0: /* Implementation is still a stub, or the code wasn't set */
  320. is_valid = response->message == NULL;
  321. break;
  322. case 500: /* Internal Server Error */
  323. case 501: /* Not Implemented */
  324. case 404: /* Bridge not found */
  325. is_valid = 1;
  326. break;
  327. default:
  328. if (200 <= code && code <= 299) {
  329. is_valid = ast_ari_validate_bridge(
  330. response->message);
  331. } else {
  332. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
  333. is_valid = 0;
  334. }
  335. }
  336. if (!is_valid) {
  337. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
  338. ast_ari_response_error(response, 500,
  339. "Internal Server Error", "Response validation failed");
  340. }
  341. #endif /* AST_DEVMODE */
  342. fin: __attribute__((unused))
  343. return;
  344. }
  345. /*!
  346. * \brief Parameter parsing callback for /bridges/{bridgeId}.
  347. * \param get_params GET parameters in the HTTP request.
  348. * \param path_vars Path variables extracted from the request.
  349. * \param headers HTTP headers.
  350. * \param[out] response Response to the HTTP request.
  351. */
  352. static void ast_ari_bridges_destroy_cb(
  353. struct ast_tcptls_session_instance *ser,
  354. struct ast_variable *get_params, struct ast_variable *path_vars,
  355. struct ast_variable *headers, struct ast_ari_response *response)
  356. {
  357. struct ast_ari_bridges_destroy_args args = {};
  358. struct ast_variable *i;
  359. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  360. #if defined(AST_DEVMODE)
  361. int is_valid;
  362. int code;
  363. #endif /* AST_DEVMODE */
  364. for (i = path_vars; i; i = i->next) {
  365. if (strcmp(i->name, "bridgeId") == 0) {
  366. args.bridge_id = (i->value);
  367. } else
  368. {}
  369. }
  370. ast_ari_bridges_destroy(headers, &args, response);
  371. #if defined(AST_DEVMODE)
  372. code = response->response_code;
  373. switch (code) {
  374. case 0: /* Implementation is still a stub, or the code wasn't set */
  375. is_valid = response->message == NULL;
  376. break;
  377. case 500: /* Internal Server Error */
  378. case 501: /* Not Implemented */
  379. case 404: /* Bridge not found */
  380. is_valid = 1;
  381. break;
  382. default:
  383. if (200 <= code && code <= 299) {
  384. is_valid = ast_ari_validate_void(
  385. response->message);
  386. } else {
  387. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}\n", code);
  388. is_valid = 0;
  389. }
  390. }
  391. if (!is_valid) {
  392. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}\n");
  393. ast_ari_response_error(response, 500,
  394. "Internal Server Error", "Response validation failed");
  395. }
  396. #endif /* AST_DEVMODE */
  397. fin: __attribute__((unused))
  398. return;
  399. }
  400. int ast_ari_bridges_add_channel_parse_body(
  401. struct ast_json *body,
  402. struct ast_ari_bridges_add_channel_args *args)
  403. {
  404. struct ast_json *field;
  405. /* Parse query parameters out of it */
  406. field = ast_json_object_get(body, "channel");
  407. if (field) {
  408. /* If they were silly enough to both pass in a query param and a
  409. * JSON body, free up the query value.
  410. */
  411. ast_free(args->channel);
  412. if (ast_json_typeof(field) == AST_JSON_ARRAY) {
  413. /* Multiple param passed as array */
  414. size_t i;
  415. args->channel_count = ast_json_array_size(field);
  416. args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
  417. if (!args->channel) {
  418. return -1;
  419. }
  420. for (i = 0; i < args->channel_count; ++i) {
  421. args->channel[i] = ast_json_string_get(ast_json_array_get(field, i));
  422. }
  423. } else {
  424. /* Multiple param passed as single value */
  425. args->channel_count = 1;
  426. args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
  427. if (!args->channel) {
  428. return -1;
  429. }
  430. args->channel[0] = ast_json_string_get(field);
  431. }
  432. }
  433. field = ast_json_object_get(body, "role");
  434. if (field) {
  435. args->role = ast_json_string_get(field);
  436. }
  437. return 0;
  438. }
  439. /*!
  440. * \brief Parameter parsing callback for /bridges/{bridgeId}/addChannel.
  441. * \param get_params GET parameters in the HTTP request.
  442. * \param path_vars Path variables extracted from the request.
  443. * \param headers HTTP headers.
  444. * \param[out] response Response to the HTTP request.
  445. */
  446. static void ast_ari_bridges_add_channel_cb(
  447. struct ast_tcptls_session_instance *ser,
  448. struct ast_variable *get_params, struct ast_variable *path_vars,
  449. struct ast_variable *headers, struct ast_ari_response *response)
  450. {
  451. struct ast_ari_bridges_add_channel_args args = {};
  452. struct ast_variable *i;
  453. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  454. #if defined(AST_DEVMODE)
  455. int is_valid;
  456. int code;
  457. #endif /* AST_DEVMODE */
  458. for (i = get_params; i; i = i->next) {
  459. if (strcmp(i->name, "channel") == 0) {
  460. /* Parse comma separated list */
  461. char *vals[MAX_VALS];
  462. size_t j;
  463. args.channel_parse = ast_strdup(i->value);
  464. if (!args.channel_parse) {
  465. ast_ari_response_alloc_failed(response);
  466. goto fin;
  467. }
  468. if (strlen(args.channel_parse) == 0) {
  469. /* ast_app_separate_args can't handle "" */
  470. args.channel_count = 1;
  471. vals[0] = args.channel_parse;
  472. } else {
  473. args.channel_count = ast_app_separate_args(
  474. args.channel_parse, ',', vals,
  475. ARRAY_LEN(vals));
  476. }
  477. if (args.channel_count == 0) {
  478. ast_ari_response_alloc_failed(response);
  479. goto fin;
  480. }
  481. if (args.channel_count >= MAX_VALS) {
  482. ast_ari_response_error(response, 400,
  483. "Bad Request",
  484. "Too many values for channel");
  485. goto fin;
  486. }
  487. args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
  488. if (!args.channel) {
  489. ast_ari_response_alloc_failed(response);
  490. goto fin;
  491. }
  492. for (j = 0; j < args.channel_count; ++j) {
  493. args.channel[j] = (vals[j]);
  494. }
  495. } else
  496. if (strcmp(i->name, "role") == 0) {
  497. args.role = (i->value);
  498. } else
  499. {}
  500. }
  501. for (i = path_vars; i; i = i->next) {
  502. if (strcmp(i->name, "bridgeId") == 0) {
  503. args.bridge_id = (i->value);
  504. } else
  505. {}
  506. }
  507. /* Look for a JSON request entity */
  508. body = ast_http_get_json(ser, headers);
  509. if (!body) {
  510. switch (errno) {
  511. case EFBIG:
  512. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  513. goto fin;
  514. case ENOMEM:
  515. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  516. goto fin;
  517. case EIO:
  518. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  519. goto fin;
  520. }
  521. }
  522. if (ast_ari_bridges_add_channel_parse_body(body, &args)) {
  523. ast_ari_response_alloc_failed(response);
  524. goto fin;
  525. }
  526. ast_ari_bridges_add_channel(headers, &args, response);
  527. #if defined(AST_DEVMODE)
  528. code = response->response_code;
  529. switch (code) {
  530. case 0: /* Implementation is still a stub, or the code wasn't set */
  531. is_valid = response->message == NULL;
  532. break;
  533. case 500: /* Internal Server Error */
  534. case 501: /* Not Implemented */
  535. case 400: /* Channel not found */
  536. case 404: /* Bridge not found */
  537. case 409: /* Bridge not in Stasis application; Channel currently recording */
  538. case 422: /* Channel not in Stasis application */
  539. is_valid = 1;
  540. break;
  541. default:
  542. if (200 <= code && code <= 299) {
  543. is_valid = ast_ari_validate_void(
  544. response->message);
  545. } else {
  546. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/addChannel\n", code);
  547. is_valid = 0;
  548. }
  549. }
  550. if (!is_valid) {
  551. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/addChannel\n");
  552. ast_ari_response_error(response, 500,
  553. "Internal Server Error", "Response validation failed");
  554. }
  555. #endif /* AST_DEVMODE */
  556. fin: __attribute__((unused))
  557. ast_free(args.channel_parse);
  558. ast_free(args.channel);
  559. return;
  560. }
  561. int ast_ari_bridges_remove_channel_parse_body(
  562. struct ast_json *body,
  563. struct ast_ari_bridges_remove_channel_args *args)
  564. {
  565. struct ast_json *field;
  566. /* Parse query parameters out of it */
  567. field = ast_json_object_get(body, "channel");
  568. if (field) {
  569. /* If they were silly enough to both pass in a query param and a
  570. * JSON body, free up the query value.
  571. */
  572. ast_free(args->channel);
  573. if (ast_json_typeof(field) == AST_JSON_ARRAY) {
  574. /* Multiple param passed as array */
  575. size_t i;
  576. args->channel_count = ast_json_array_size(field);
  577. args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
  578. if (!args->channel) {
  579. return -1;
  580. }
  581. for (i = 0; i < args->channel_count; ++i) {
  582. args->channel[i] = ast_json_string_get(ast_json_array_get(field, i));
  583. }
  584. } else {
  585. /* Multiple param passed as single value */
  586. args->channel_count = 1;
  587. args->channel = ast_malloc(sizeof(*args->channel) * args->channel_count);
  588. if (!args->channel) {
  589. return -1;
  590. }
  591. args->channel[0] = ast_json_string_get(field);
  592. }
  593. }
  594. return 0;
  595. }
  596. /*!
  597. * \brief Parameter parsing callback for /bridges/{bridgeId}/removeChannel.
  598. * \param get_params GET parameters in the HTTP request.
  599. * \param path_vars Path variables extracted from the request.
  600. * \param headers HTTP headers.
  601. * \param[out] response Response to the HTTP request.
  602. */
  603. static void ast_ari_bridges_remove_channel_cb(
  604. struct ast_tcptls_session_instance *ser,
  605. struct ast_variable *get_params, struct ast_variable *path_vars,
  606. struct ast_variable *headers, struct ast_ari_response *response)
  607. {
  608. struct ast_ari_bridges_remove_channel_args args = {};
  609. struct ast_variable *i;
  610. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  611. #if defined(AST_DEVMODE)
  612. int is_valid;
  613. int code;
  614. #endif /* AST_DEVMODE */
  615. for (i = get_params; i; i = i->next) {
  616. if (strcmp(i->name, "channel") == 0) {
  617. /* Parse comma separated list */
  618. char *vals[MAX_VALS];
  619. size_t j;
  620. args.channel_parse = ast_strdup(i->value);
  621. if (!args.channel_parse) {
  622. ast_ari_response_alloc_failed(response);
  623. goto fin;
  624. }
  625. if (strlen(args.channel_parse) == 0) {
  626. /* ast_app_separate_args can't handle "" */
  627. args.channel_count = 1;
  628. vals[0] = args.channel_parse;
  629. } else {
  630. args.channel_count = ast_app_separate_args(
  631. args.channel_parse, ',', vals,
  632. ARRAY_LEN(vals));
  633. }
  634. if (args.channel_count == 0) {
  635. ast_ari_response_alloc_failed(response);
  636. goto fin;
  637. }
  638. if (args.channel_count >= MAX_VALS) {
  639. ast_ari_response_error(response, 400,
  640. "Bad Request",
  641. "Too many values for channel");
  642. goto fin;
  643. }
  644. args.channel = ast_malloc(sizeof(*args.channel) * args.channel_count);
  645. if (!args.channel) {
  646. ast_ari_response_alloc_failed(response);
  647. goto fin;
  648. }
  649. for (j = 0; j < args.channel_count; ++j) {
  650. args.channel[j] = (vals[j]);
  651. }
  652. } else
  653. {}
  654. }
  655. for (i = path_vars; i; i = i->next) {
  656. if (strcmp(i->name, "bridgeId") == 0) {
  657. args.bridge_id = (i->value);
  658. } else
  659. {}
  660. }
  661. /* Look for a JSON request entity */
  662. body = ast_http_get_json(ser, headers);
  663. if (!body) {
  664. switch (errno) {
  665. case EFBIG:
  666. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  667. goto fin;
  668. case ENOMEM:
  669. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  670. goto fin;
  671. case EIO:
  672. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  673. goto fin;
  674. }
  675. }
  676. if (ast_ari_bridges_remove_channel_parse_body(body, &args)) {
  677. ast_ari_response_alloc_failed(response);
  678. goto fin;
  679. }
  680. ast_ari_bridges_remove_channel(headers, &args, response);
  681. #if defined(AST_DEVMODE)
  682. code = response->response_code;
  683. switch (code) {
  684. case 0: /* Implementation is still a stub, or the code wasn't set */
  685. is_valid = response->message == NULL;
  686. break;
  687. case 500: /* Internal Server Error */
  688. case 501: /* Not Implemented */
  689. case 400: /* Channel not found */
  690. case 404: /* Bridge not found */
  691. case 409: /* Bridge not in Stasis application */
  692. case 422: /* Channel not in this bridge */
  693. is_valid = 1;
  694. break;
  695. default:
  696. if (200 <= code && code <= 299) {
  697. is_valid = ast_ari_validate_void(
  698. response->message);
  699. } else {
  700. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/removeChannel\n", code);
  701. is_valid = 0;
  702. }
  703. }
  704. if (!is_valid) {
  705. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/removeChannel\n");
  706. ast_ari_response_error(response, 500,
  707. "Internal Server Error", "Response validation failed");
  708. }
  709. #endif /* AST_DEVMODE */
  710. fin: __attribute__((unused))
  711. ast_free(args.channel_parse);
  712. ast_free(args.channel);
  713. return;
  714. }
  715. int ast_ari_bridges_start_moh_parse_body(
  716. struct ast_json *body,
  717. struct ast_ari_bridges_start_moh_args *args)
  718. {
  719. struct ast_json *field;
  720. /* Parse query parameters out of it */
  721. field = ast_json_object_get(body, "mohClass");
  722. if (field) {
  723. args->moh_class = ast_json_string_get(field);
  724. }
  725. return 0;
  726. }
  727. /*!
  728. * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
  729. * \param get_params GET parameters in the HTTP request.
  730. * \param path_vars Path variables extracted from the request.
  731. * \param headers HTTP headers.
  732. * \param[out] response Response to the HTTP request.
  733. */
  734. static void ast_ari_bridges_start_moh_cb(
  735. struct ast_tcptls_session_instance *ser,
  736. struct ast_variable *get_params, struct ast_variable *path_vars,
  737. struct ast_variable *headers, struct ast_ari_response *response)
  738. {
  739. struct ast_ari_bridges_start_moh_args args = {};
  740. struct ast_variable *i;
  741. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  742. #if defined(AST_DEVMODE)
  743. int is_valid;
  744. int code;
  745. #endif /* AST_DEVMODE */
  746. for (i = get_params; i; i = i->next) {
  747. if (strcmp(i->name, "mohClass") == 0) {
  748. args.moh_class = (i->value);
  749. } else
  750. {}
  751. }
  752. for (i = path_vars; i; i = i->next) {
  753. if (strcmp(i->name, "bridgeId") == 0) {
  754. args.bridge_id = (i->value);
  755. } else
  756. {}
  757. }
  758. /* Look for a JSON request entity */
  759. body = ast_http_get_json(ser, headers);
  760. if (!body) {
  761. switch (errno) {
  762. case EFBIG:
  763. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  764. goto fin;
  765. case ENOMEM:
  766. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  767. goto fin;
  768. case EIO:
  769. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  770. goto fin;
  771. }
  772. }
  773. if (ast_ari_bridges_start_moh_parse_body(body, &args)) {
  774. ast_ari_response_alloc_failed(response);
  775. goto fin;
  776. }
  777. ast_ari_bridges_start_moh(headers, &args, response);
  778. #if defined(AST_DEVMODE)
  779. code = response->response_code;
  780. switch (code) {
  781. case 0: /* Implementation is still a stub, or the code wasn't set */
  782. is_valid = response->message == NULL;
  783. break;
  784. case 500: /* Internal Server Error */
  785. case 501: /* Not Implemented */
  786. case 404: /* Bridge not found */
  787. case 409: /* Bridge not in Stasis application */
  788. is_valid = 1;
  789. break;
  790. default:
  791. if (200 <= code && code <= 299) {
  792. is_valid = ast_ari_validate_void(
  793. response->message);
  794. } else {
  795. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
  796. is_valid = 0;
  797. }
  798. }
  799. if (!is_valid) {
  800. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
  801. ast_ari_response_error(response, 500,
  802. "Internal Server Error", "Response validation failed");
  803. }
  804. #endif /* AST_DEVMODE */
  805. fin: __attribute__((unused))
  806. return;
  807. }
  808. /*!
  809. * \brief Parameter parsing callback for /bridges/{bridgeId}/moh.
  810. * \param get_params GET parameters in the HTTP request.
  811. * \param path_vars Path variables extracted from the request.
  812. * \param headers HTTP headers.
  813. * \param[out] response Response to the HTTP request.
  814. */
  815. static void ast_ari_bridges_stop_moh_cb(
  816. struct ast_tcptls_session_instance *ser,
  817. struct ast_variable *get_params, struct ast_variable *path_vars,
  818. struct ast_variable *headers, struct ast_ari_response *response)
  819. {
  820. struct ast_ari_bridges_stop_moh_args args = {};
  821. struct ast_variable *i;
  822. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  823. #if defined(AST_DEVMODE)
  824. int is_valid;
  825. int code;
  826. #endif /* AST_DEVMODE */
  827. for (i = path_vars; i; i = i->next) {
  828. if (strcmp(i->name, "bridgeId") == 0) {
  829. args.bridge_id = (i->value);
  830. } else
  831. {}
  832. }
  833. ast_ari_bridges_stop_moh(headers, &args, response);
  834. #if defined(AST_DEVMODE)
  835. code = response->response_code;
  836. switch (code) {
  837. case 0: /* Implementation is still a stub, or the code wasn't set */
  838. is_valid = response->message == NULL;
  839. break;
  840. case 500: /* Internal Server Error */
  841. case 501: /* Not Implemented */
  842. case 404: /* Bridge not found */
  843. case 409: /* Bridge not in Stasis application */
  844. is_valid = 1;
  845. break;
  846. default:
  847. if (200 <= code && code <= 299) {
  848. is_valid = ast_ari_validate_void(
  849. response->message);
  850. } else {
  851. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/moh\n", code);
  852. is_valid = 0;
  853. }
  854. }
  855. if (!is_valid) {
  856. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/moh\n");
  857. ast_ari_response_error(response, 500,
  858. "Internal Server Error", "Response validation failed");
  859. }
  860. #endif /* AST_DEVMODE */
  861. fin: __attribute__((unused))
  862. return;
  863. }
  864. int ast_ari_bridges_play_parse_body(
  865. struct ast_json *body,
  866. struct ast_ari_bridges_play_args *args)
  867. {
  868. struct ast_json *field;
  869. /* Parse query parameters out of it */
  870. field = ast_json_object_get(body, "media");
  871. if (field) {
  872. args->media = ast_json_string_get(field);
  873. }
  874. field = ast_json_object_get(body, "lang");
  875. if (field) {
  876. args->lang = ast_json_string_get(field);
  877. }
  878. field = ast_json_object_get(body, "offsetms");
  879. if (field) {
  880. args->offsetms = ast_json_integer_get(field);
  881. }
  882. field = ast_json_object_get(body, "skipms");
  883. if (field) {
  884. args->skipms = ast_json_integer_get(field);
  885. }
  886. field = ast_json_object_get(body, "playbackId");
  887. if (field) {
  888. args->playback_id = ast_json_string_get(field);
  889. }
  890. return 0;
  891. }
  892. /*!
  893. * \brief Parameter parsing callback for /bridges/{bridgeId}/play.
  894. * \param get_params GET parameters in the HTTP request.
  895. * \param path_vars Path variables extracted from the request.
  896. * \param headers HTTP headers.
  897. * \param[out] response Response to the HTTP request.
  898. */
  899. static void ast_ari_bridges_play_cb(
  900. struct ast_tcptls_session_instance *ser,
  901. struct ast_variable *get_params, struct ast_variable *path_vars,
  902. struct ast_variable *headers, struct ast_ari_response *response)
  903. {
  904. struct ast_ari_bridges_play_args args = {};
  905. struct ast_variable *i;
  906. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  907. #if defined(AST_DEVMODE)
  908. int is_valid;
  909. int code;
  910. #endif /* AST_DEVMODE */
  911. for (i = get_params; i; i = i->next) {
  912. if (strcmp(i->name, "media") == 0) {
  913. args.media = (i->value);
  914. } else
  915. if (strcmp(i->name, "lang") == 0) {
  916. args.lang = (i->value);
  917. } else
  918. if (strcmp(i->name, "offsetms") == 0) {
  919. args.offsetms = atoi(i->value);
  920. } else
  921. if (strcmp(i->name, "skipms") == 0) {
  922. args.skipms = atoi(i->value);
  923. } else
  924. if (strcmp(i->name, "playbackId") == 0) {
  925. args.playback_id = (i->value);
  926. } else
  927. {}
  928. }
  929. for (i = path_vars; i; i = i->next) {
  930. if (strcmp(i->name, "bridgeId") == 0) {
  931. args.bridge_id = (i->value);
  932. } else
  933. {}
  934. }
  935. /* Look for a JSON request entity */
  936. body = ast_http_get_json(ser, headers);
  937. if (!body) {
  938. switch (errno) {
  939. case EFBIG:
  940. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  941. goto fin;
  942. case ENOMEM:
  943. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  944. goto fin;
  945. case EIO:
  946. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  947. goto fin;
  948. }
  949. }
  950. if (ast_ari_bridges_play_parse_body(body, &args)) {
  951. ast_ari_response_alloc_failed(response);
  952. goto fin;
  953. }
  954. ast_ari_bridges_play(headers, &args, response);
  955. #if defined(AST_DEVMODE)
  956. code = response->response_code;
  957. switch (code) {
  958. case 0: /* Implementation is still a stub, or the code wasn't set */
  959. is_valid = response->message == NULL;
  960. break;
  961. case 500: /* Internal Server Error */
  962. case 501: /* Not Implemented */
  963. case 404: /* Bridge not found */
  964. case 409: /* Bridge not in a Stasis application */
  965. is_valid = 1;
  966. break;
  967. default:
  968. if (200 <= code && code <= 299) {
  969. is_valid = ast_ari_validate_playback(
  970. response->message);
  971. } else {
  972. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play\n", code);
  973. is_valid = 0;
  974. }
  975. }
  976. if (!is_valid) {
  977. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play\n");
  978. ast_ari_response_error(response, 500,
  979. "Internal Server Error", "Response validation failed");
  980. }
  981. #endif /* AST_DEVMODE */
  982. fin: __attribute__((unused))
  983. return;
  984. }
  985. int ast_ari_bridges_play_with_id_parse_body(
  986. struct ast_json *body,
  987. struct ast_ari_bridges_play_with_id_args *args)
  988. {
  989. struct ast_json *field;
  990. /* Parse query parameters out of it */
  991. field = ast_json_object_get(body, "media");
  992. if (field) {
  993. args->media = ast_json_string_get(field);
  994. }
  995. field = ast_json_object_get(body, "lang");
  996. if (field) {
  997. args->lang = ast_json_string_get(field);
  998. }
  999. field = ast_json_object_get(body, "offsetms");
  1000. if (field) {
  1001. args->offsetms = ast_json_integer_get(field);
  1002. }
  1003. field = ast_json_object_get(body, "skipms");
  1004. if (field) {
  1005. args->skipms = ast_json_integer_get(field);
  1006. }
  1007. return 0;
  1008. }
  1009. /*!
  1010. * \brief Parameter parsing callback for /bridges/{bridgeId}/play/{playbackId}.
  1011. * \param get_params GET parameters in the HTTP request.
  1012. * \param path_vars Path variables extracted from the request.
  1013. * \param headers HTTP headers.
  1014. * \param[out] response Response to the HTTP request.
  1015. */
  1016. static void ast_ari_bridges_play_with_id_cb(
  1017. struct ast_tcptls_session_instance *ser,
  1018. struct ast_variable *get_params, struct ast_variable *path_vars,
  1019. struct ast_variable *headers, struct ast_ari_response *response)
  1020. {
  1021. struct ast_ari_bridges_play_with_id_args args = {};
  1022. struct ast_variable *i;
  1023. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  1024. #if defined(AST_DEVMODE)
  1025. int is_valid;
  1026. int code;
  1027. #endif /* AST_DEVMODE */
  1028. for (i = get_params; i; i = i->next) {
  1029. if (strcmp(i->name, "media") == 0) {
  1030. args.media = (i->value);
  1031. } else
  1032. if (strcmp(i->name, "lang") == 0) {
  1033. args.lang = (i->value);
  1034. } else
  1035. if (strcmp(i->name, "offsetms") == 0) {
  1036. args.offsetms = atoi(i->value);
  1037. } else
  1038. if (strcmp(i->name, "skipms") == 0) {
  1039. args.skipms = atoi(i->value);
  1040. } else
  1041. {}
  1042. }
  1043. for (i = path_vars; i; i = i->next) {
  1044. if (strcmp(i->name, "bridgeId") == 0) {
  1045. args.bridge_id = (i->value);
  1046. } else
  1047. if (strcmp(i->name, "playbackId") == 0) {
  1048. args.playback_id = (i->value);
  1049. } else
  1050. {}
  1051. }
  1052. /* Look for a JSON request entity */
  1053. body = ast_http_get_json(ser, headers);
  1054. if (!body) {
  1055. switch (errno) {
  1056. case EFBIG:
  1057. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  1058. goto fin;
  1059. case ENOMEM:
  1060. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  1061. goto fin;
  1062. case EIO:
  1063. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  1064. goto fin;
  1065. }
  1066. }
  1067. if (ast_ari_bridges_play_with_id_parse_body(body, &args)) {
  1068. ast_ari_response_alloc_failed(response);
  1069. goto fin;
  1070. }
  1071. ast_ari_bridges_play_with_id(headers, &args, response);
  1072. #if defined(AST_DEVMODE)
  1073. code = response->response_code;
  1074. switch (code) {
  1075. case 0: /* Implementation is still a stub, or the code wasn't set */
  1076. is_valid = response->message == NULL;
  1077. break;
  1078. case 500: /* Internal Server Error */
  1079. case 501: /* Not Implemented */
  1080. case 404: /* Bridge not found */
  1081. case 409: /* Bridge not in a Stasis application */
  1082. is_valid = 1;
  1083. break;
  1084. default:
  1085. if (200 <= code && code <= 299) {
  1086. is_valid = ast_ari_validate_playback(
  1087. response->message);
  1088. } else {
  1089. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/play/{playbackId}\n", code);
  1090. is_valid = 0;
  1091. }
  1092. }
  1093. if (!is_valid) {
  1094. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/play/{playbackId}\n");
  1095. ast_ari_response_error(response, 500,
  1096. "Internal Server Error", "Response validation failed");
  1097. }
  1098. #endif /* AST_DEVMODE */
  1099. fin: __attribute__((unused))
  1100. return;
  1101. }
  1102. int ast_ari_bridges_record_parse_body(
  1103. struct ast_json *body,
  1104. struct ast_ari_bridges_record_args *args)
  1105. {
  1106. struct ast_json *field;
  1107. /* Parse query parameters out of it */
  1108. field = ast_json_object_get(body, "name");
  1109. if (field) {
  1110. args->name = ast_json_string_get(field);
  1111. }
  1112. field = ast_json_object_get(body, "format");
  1113. if (field) {
  1114. args->format = ast_json_string_get(field);
  1115. }
  1116. field = ast_json_object_get(body, "maxDurationSeconds");
  1117. if (field) {
  1118. args->max_duration_seconds = ast_json_integer_get(field);
  1119. }
  1120. field = ast_json_object_get(body, "maxSilenceSeconds");
  1121. if (field) {
  1122. args->max_silence_seconds = ast_json_integer_get(field);
  1123. }
  1124. field = ast_json_object_get(body, "ifExists");
  1125. if (field) {
  1126. args->if_exists = ast_json_string_get(field);
  1127. }
  1128. field = ast_json_object_get(body, "beep");
  1129. if (field) {
  1130. args->beep = ast_json_is_true(field);
  1131. }
  1132. field = ast_json_object_get(body, "terminateOn");
  1133. if (field) {
  1134. args->terminate_on = ast_json_string_get(field);
  1135. }
  1136. return 0;
  1137. }
  1138. /*!
  1139. * \brief Parameter parsing callback for /bridges/{bridgeId}/record.
  1140. * \param get_params GET parameters in the HTTP request.
  1141. * \param path_vars Path variables extracted from the request.
  1142. * \param headers HTTP headers.
  1143. * \param[out] response Response to the HTTP request.
  1144. */
  1145. static void ast_ari_bridges_record_cb(
  1146. struct ast_tcptls_session_instance *ser,
  1147. struct ast_variable *get_params, struct ast_variable *path_vars,
  1148. struct ast_variable *headers, struct ast_ari_response *response)
  1149. {
  1150. struct ast_ari_bridges_record_args args = {};
  1151. struct ast_variable *i;
  1152. RAII_VAR(struct ast_json *, body, NULL, ast_json_unref);
  1153. #if defined(AST_DEVMODE)
  1154. int is_valid;
  1155. int code;
  1156. #endif /* AST_DEVMODE */
  1157. for (i = get_params; i; i = i->next) {
  1158. if (strcmp(i->name, "name") == 0) {
  1159. args.name = (i->value);
  1160. } else
  1161. if (strcmp(i->name, "format") == 0) {
  1162. args.format = (i->value);
  1163. } else
  1164. if (strcmp(i->name, "maxDurationSeconds") == 0) {
  1165. args.max_duration_seconds = atoi(i->value);
  1166. } else
  1167. if (strcmp(i->name, "maxSilenceSeconds") == 0) {
  1168. args.max_silence_seconds = atoi(i->value);
  1169. } else
  1170. if (strcmp(i->name, "ifExists") == 0) {
  1171. args.if_exists = (i->value);
  1172. } else
  1173. if (strcmp(i->name, "beep") == 0) {
  1174. args.beep = ast_true(i->value);
  1175. } else
  1176. if (strcmp(i->name, "terminateOn") == 0) {
  1177. args.terminate_on = (i->value);
  1178. } else
  1179. {}
  1180. }
  1181. for (i = path_vars; i; i = i->next) {
  1182. if (strcmp(i->name, "bridgeId") == 0) {
  1183. args.bridge_id = (i->value);
  1184. } else
  1185. {}
  1186. }
  1187. /* Look for a JSON request entity */
  1188. body = ast_http_get_json(ser, headers);
  1189. if (!body) {
  1190. switch (errno) {
  1191. case EFBIG:
  1192. ast_ari_response_error(response, 413, "Request Entity Too Large", "Request body too large");
  1193. goto fin;
  1194. case ENOMEM:
  1195. ast_ari_response_error(response, 500, "Internal Server Error", "Error processing request");
  1196. goto fin;
  1197. case EIO:
  1198. ast_ari_response_error(response, 400, "Bad Request", "Error parsing request body");
  1199. goto fin;
  1200. }
  1201. }
  1202. if (ast_ari_bridges_record_parse_body(body, &args)) {
  1203. ast_ari_response_alloc_failed(response);
  1204. goto fin;
  1205. }
  1206. ast_ari_bridges_record(headers, &args, response);
  1207. #if defined(AST_DEVMODE)
  1208. code = response->response_code;
  1209. switch (code) {
  1210. case 0: /* Implementation is still a stub, or the code wasn't set */
  1211. is_valid = response->message == NULL;
  1212. break;
  1213. case 500: /* Internal Server Error */
  1214. case 501: /* Not Implemented */
  1215. case 400: /* Invalid parameters */
  1216. case 404: /* Bridge not found */
  1217. case 409: /* Bridge is not in a Stasis application; A recording with the same name already exists on the system and can not be overwritten because it is in progress or ifExists=fail */
  1218. case 422: /* The format specified is unknown on this system */
  1219. is_valid = 1;
  1220. break;
  1221. default:
  1222. if (200 <= code && code <= 299) {
  1223. is_valid = ast_ari_validate_live_recording(
  1224. response->message);
  1225. } else {
  1226. ast_log(LOG_ERROR, "Invalid error response %d for /bridges/{bridgeId}/record\n", code);
  1227. is_valid = 0;
  1228. }
  1229. }
  1230. if (!is_valid) {
  1231. ast_log(LOG_ERROR, "Response validation failed for /bridges/{bridgeId}/record\n");
  1232. ast_ari_response_error(response, 500,
  1233. "Internal Server Error", "Response validation failed");
  1234. }
  1235. #endif /* AST_DEVMODE */
  1236. fin: __attribute__((unused))
  1237. return;
  1238. }
  1239. /*! \brief REST handler for /api-docs/bridges.{format} */
  1240. static struct stasis_rest_handlers bridges_bridgeId_addChannel = {
  1241. .path_segment = "addChannel",
  1242. .callbacks = {
  1243. [AST_HTTP_POST] = ast_ari_bridges_add_channel_cb,
  1244. },
  1245. .num_children = 0,
  1246. .children = { }
  1247. };
  1248. /*! \brief REST handler for /api-docs/bridges.{format} */
  1249. static struct stasis_rest_handlers bridges_bridgeId_removeChannel = {
  1250. .path_segment = "removeChannel",
  1251. .callbacks = {
  1252. [AST_HTTP_POST] = ast_ari_bridges_remove_channel_cb,
  1253. },
  1254. .num_children = 0,
  1255. .children = { }
  1256. };
  1257. /*! \brief REST handler for /api-docs/bridges.{format} */
  1258. static struct stasis_rest_handlers bridges_bridgeId_moh = {
  1259. .path_segment = "moh",
  1260. .callbacks = {
  1261. [AST_HTTP_POST] = ast_ari_bridges_start_moh_cb,
  1262. [AST_HTTP_DELETE] = ast_ari_bridges_stop_moh_cb,
  1263. },
  1264. .num_children = 0,
  1265. .children = { }
  1266. };
  1267. /*! \brief REST handler for /api-docs/bridges.{format} */
  1268. static struct stasis_rest_handlers bridges_bridgeId_play_playbackId = {
  1269. .path_segment = "playbackId",
  1270. .is_wildcard = 1,
  1271. .callbacks = {
  1272. [AST_HTTP_POST] = ast_ari_bridges_play_with_id_cb,
  1273. },
  1274. .num_children = 0,
  1275. .children = { }
  1276. };
  1277. /*! \brief REST handler for /api-docs/bridges.{format} */
  1278. static struct stasis_rest_handlers bridges_bridgeId_play = {
  1279. .path_segment = "play",
  1280. .callbacks = {
  1281. [AST_HTTP_POST] = ast_ari_bridges_play_cb,
  1282. },
  1283. .num_children = 1,
  1284. .children = { &bridges_bridgeId_play_playbackId, }
  1285. };
  1286. /*! \brief REST handler for /api-docs/bridges.{format} */
  1287. static struct stasis_rest_handlers bridges_bridgeId_record = {
  1288. .path_segment = "record",
  1289. .callbacks = {
  1290. [AST_HTTP_POST] = ast_ari_bridges_record_cb,
  1291. },
  1292. .num_children = 0,
  1293. .children = { }
  1294. };
  1295. /*! \brief REST handler for /api-docs/bridges.{format} */
  1296. static struct stasis_rest_handlers bridges_bridgeId = {
  1297. .path_segment = "bridgeId",
  1298. .is_wildcard = 1,
  1299. .callbacks = {
  1300. [AST_HTTP_POST] = ast_ari_bridges_create_or_update_with_id_cb,
  1301. [AST_HTTP_GET] = ast_ari_bridges_get_cb,
  1302. [AST_HTTP_DELETE] = ast_ari_bridges_destroy_cb,
  1303. },
  1304. .num_children = 5,
  1305. .children = { &bridges_bridgeId_addChannel,&bridges_bridgeId_removeChannel,&bridges_bridgeId_moh,&bridges_bridgeId_play,&bridges_bridgeId_record, }
  1306. };
  1307. /*! \brief REST handler for /api-docs/bridges.{format} */
  1308. static struct stasis_rest_handlers bridges = {
  1309. .path_segment = "bridges",
  1310. .callbacks = {
  1311. [AST_HTTP_GET] = ast_ari_bridges_list_cb,
  1312. [AST_HTTP_POST] = ast_ari_bridges_create_cb,
  1313. },
  1314. .num_children = 1,
  1315. .children = { &bridges_bridgeId, }
  1316. };
  1317. static int load_module(void)
  1318. {
  1319. int res = 0;
  1320. stasis_app_ref();
  1321. res |= ast_ari_add_handler(&bridges);
  1322. return res;
  1323. }
  1324. static int unload_module(void)
  1325. {
  1326. ast_ari_remove_handler(&bridges);
  1327. stasis_app_unref();
  1328. return 0;
  1329. }
  1330. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "RESTful API module - Bridge resources",
  1331. .support_level = AST_MODULE_SUPPORT_CORE,
  1332. .load = load_module,
  1333. .unload = unload_module,
  1334. .nonoptreq = "res_ari,res_stasis",
  1335. );