resource_channels.c 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513
  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 Implementation for ARI stubs.
  21. *
  22. * \author David M. Lee, II <dlee@digium.com>
  23. */
  24. /*** MODULEINFO
  25. <depend type="module">res_stasis_answer</depend>
  26. <depend type="module">res_stasis_playback</depend>
  27. <depend type="module">res_stasis_recording</depend>
  28. <depend type="module">res_stasis_snoop</depend>
  29. <support_level>core</support_level>
  30. ***/
  31. #include "asterisk.h"
  32. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  33. #include "asterisk/file.h"
  34. #include "asterisk/pbx.h"
  35. #include "asterisk/bridge.h"
  36. #include "asterisk/callerid.h"
  37. #include "asterisk/stasis_app.h"
  38. #include "asterisk/stasis_app_playback.h"
  39. #include "asterisk/stasis_app_recording.h"
  40. #include "asterisk/stasis_app_snoop.h"
  41. #include "asterisk/stasis_channels.h"
  42. #include "asterisk/causes.h"
  43. #include "asterisk/format_cache.h"
  44. #include "asterisk/core_local.h"
  45. #include "asterisk/dial.h"
  46. #include "resource_channels.h"
  47. #include <limits.h>
  48. /*!
  49. * \brief Finds the control object for a channel, filling the response with an
  50. * error, if appropriate.
  51. * \param[out] response Response to fill with an error if control is not found.
  52. * \param channel_id ID of the channel to lookup.
  53. * \return Channel control object.
  54. * \return \c NULL if control object does not exist.
  55. */
  56. static struct stasis_app_control *find_control(
  57. struct ast_ari_response *response,
  58. const char *channel_id)
  59. {
  60. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  61. ast_assert(response != NULL);
  62. control = stasis_app_control_find_by_channel_id(channel_id);
  63. if (control == NULL) {
  64. /* Distinguish between 404 and 409 errors */
  65. RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
  66. chan = ast_channel_get_by_name(channel_id);
  67. if (chan == NULL) {
  68. ast_ari_response_error(response, 404, "Not Found",
  69. "Channel not found");
  70. return NULL;
  71. }
  72. ast_ari_response_error(response, 409, "Conflict",
  73. "Channel not in Stasis application");
  74. return NULL;
  75. }
  76. ao2_ref(control, +1);
  77. return control;
  78. }
  79. void ast_ari_channels_continue_in_dialplan(
  80. struct ast_variable *headers,
  81. struct ast_ari_channels_continue_in_dialplan_args *args,
  82. struct ast_ari_response *response)
  83. {
  84. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  85. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  86. int ipri;
  87. const char *context;
  88. const char *exten;
  89. ast_assert(response != NULL);
  90. control = find_control(response, args->channel_id);
  91. if (control == NULL) {
  92. return;
  93. }
  94. snapshot = stasis_app_control_get_snapshot(control);
  95. if (!snapshot) {
  96. return;
  97. }
  98. if (ast_strlen_zero(args->context)) {
  99. context = snapshot->context;
  100. exten = S_OR(args->extension, snapshot->exten);
  101. } else {
  102. context = args->context;
  103. exten = S_OR(args->extension, "s");
  104. }
  105. if (!ast_strlen_zero(args->label)) {
  106. /* A label was provided in the request, use that */
  107. if (sscanf(args->label, "%30d", &ipri) != 1) {
  108. ipri = ast_findlabel_extension(NULL, context, exten, args->label, NULL);
  109. if (ipri == -1) {
  110. ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args->label, context);
  111. ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
  112. return;
  113. }
  114. } else {
  115. ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
  116. }
  117. if (ipri == 0) {
  118. ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
  119. args->label, exten, context);
  120. ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
  121. return;
  122. }
  123. } else if (args->priority) {
  124. /* No label provided, use provided priority */
  125. ipri = args->priority;
  126. } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
  127. /* Special case. No exten, context, or priority provided, then move on to the next priority */
  128. ipri = snapshot->priority + 1;
  129. } else {
  130. ipri = 1;
  131. }
  132. if (stasis_app_control_continue(control, context, exten, ipri)) {
  133. ast_ari_response_alloc_failed(response);
  134. return;
  135. }
  136. ast_ari_response_no_content(response);
  137. }
  138. void ast_ari_channels_redirect(struct ast_variable *headers,
  139. struct ast_ari_channels_redirect_args *args,
  140. struct ast_ari_response *response)
  141. {
  142. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  143. RAII_VAR(struct ast_channel_snapshot *, chan_snapshot, NULL, ao2_cleanup);
  144. char *tech;
  145. char *resource;
  146. int tech_len;
  147. control = find_control(response, args->channel_id);
  148. if (!control) {
  149. return;
  150. }
  151. if (ast_strlen_zero(args->endpoint)) {
  152. ast_ari_response_error(response, 400, "Not Found",
  153. "Required parameter 'endpoint' not provided.");
  154. return;
  155. }
  156. tech = ast_strdupa(args->endpoint);
  157. if (!(resource = strchr(tech, '/')) || !(tech_len = resource - tech)) {
  158. ast_ari_response_error(response, 422, "Unprocessable Entity",
  159. "Endpoint parameter '%s' does not contain tech/resource", args->endpoint);
  160. return;
  161. }
  162. *resource++ = '\0';
  163. if (ast_strlen_zero(resource)) {
  164. ast_ari_response_error(response, 422, "Unprocessable Entity",
  165. "No resource provided in endpoint parameter '%s'", args->endpoint);
  166. return;
  167. }
  168. chan_snapshot = ast_channel_snapshot_get_latest(args->channel_id);
  169. if (!chan_snapshot) {
  170. ast_ari_response_error(response, 500, "Internal Server Error",
  171. "Unable to find channel snapshot for '%s'", args->channel_id);
  172. return;
  173. }
  174. if (strncasecmp(chan_snapshot->type, tech, tech_len)) {
  175. ast_ari_response_error(response, 422, "Unprocessable Entity",
  176. "Endpoint technology '%s' does not match channel technology '%s'",
  177. tech, chan_snapshot->type);
  178. return;
  179. }
  180. if (stasis_app_control_redirect(control, resource)) {
  181. ast_ari_response_error(response, 500, "Internal Server Error",
  182. "Failed to redirect channel");
  183. return;
  184. }
  185. ast_ari_response_no_content(response);
  186. }
  187. void ast_ari_channels_answer(struct ast_variable *headers,
  188. struct ast_ari_channels_answer_args *args,
  189. struct ast_ari_response *response)
  190. {
  191. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  192. control = find_control(response, args->channel_id);
  193. if (control == NULL) {
  194. return;
  195. }
  196. if (stasis_app_control_answer(control) != 0) {
  197. ast_ari_response_error(
  198. response, 500, "Internal Server Error",
  199. "Failed to answer channel");
  200. return;
  201. }
  202. ast_ari_response_no_content(response);
  203. }
  204. void ast_ari_channels_ring(struct ast_variable *headers,
  205. struct ast_ari_channels_ring_args *args,
  206. struct ast_ari_response *response)
  207. {
  208. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  209. control = find_control(response, args->channel_id);
  210. if (control == NULL) {
  211. return;
  212. }
  213. stasis_app_control_ring(control);
  214. ast_ari_response_no_content(response);
  215. }
  216. void ast_ari_channels_ring_stop(struct ast_variable *headers,
  217. struct ast_ari_channels_ring_stop_args *args,
  218. struct ast_ari_response *response)
  219. {
  220. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  221. control = find_control(response, args->channel_id);
  222. if (control == NULL) {
  223. return;
  224. }
  225. stasis_app_control_ring_stop(control);
  226. ast_ari_response_no_content(response);
  227. }
  228. void ast_ari_channels_mute(struct ast_variable *headers,
  229. struct ast_ari_channels_mute_args *args,
  230. struct ast_ari_response *response)
  231. {
  232. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  233. unsigned int direction = 0;
  234. enum ast_frame_type frametype = AST_FRAME_VOICE;
  235. control = find_control(response, args->channel_id);
  236. if (control == NULL) {
  237. return;
  238. }
  239. if (ast_strlen_zero(args->direction)) {
  240. ast_ari_response_error(
  241. response, 400, "Bad Request",
  242. "Direction is required");
  243. return;
  244. }
  245. if (!strcmp(args->direction, "in")) {
  246. direction = AST_MUTE_DIRECTION_READ;
  247. } else if (!strcmp(args->direction, "out")) {
  248. direction = AST_MUTE_DIRECTION_WRITE;
  249. } else if (!strcmp(args->direction, "both")) {
  250. direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
  251. } else {
  252. ast_ari_response_error(
  253. response, 400, "Bad Request",
  254. "Invalid direction specified");
  255. return;
  256. }
  257. stasis_app_control_mute(control, direction, frametype);
  258. ast_ari_response_no_content(response);
  259. }
  260. void ast_ari_channels_unmute(struct ast_variable *headers,
  261. struct ast_ari_channels_unmute_args *args,
  262. struct ast_ari_response *response)
  263. {
  264. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  265. unsigned int direction = 0;
  266. enum ast_frame_type frametype = AST_FRAME_VOICE;
  267. control = find_control(response, args->channel_id);
  268. if (control == NULL) {
  269. return;
  270. }
  271. if (ast_strlen_zero(args->direction)) {
  272. ast_ari_response_error(
  273. response, 400, "Bad Request",
  274. "Direction is required");
  275. return;
  276. }
  277. if (!strcmp(args->direction, "in")) {
  278. direction = AST_MUTE_DIRECTION_READ;
  279. } else if (!strcmp(args->direction, "out")) {
  280. direction = AST_MUTE_DIRECTION_WRITE;
  281. } else if (!strcmp(args->direction, "both")) {
  282. direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
  283. } else {
  284. ast_ari_response_error(
  285. response, 400, "Bad Request",
  286. "Invalid direction specified");
  287. return;
  288. }
  289. stasis_app_control_unmute(control, direction, frametype);
  290. ast_ari_response_no_content(response);
  291. }
  292. void ast_ari_channels_send_dtmf(struct ast_variable *headers,
  293. struct ast_ari_channels_send_dtmf_args *args,
  294. struct ast_ari_response *response)
  295. {
  296. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  297. control = find_control(response, args->channel_id);
  298. if (control == NULL) {
  299. return;
  300. }
  301. if (ast_strlen_zero(args->dtmf)) {
  302. ast_ari_response_error(
  303. response, 400, "Bad Request",
  304. "DTMF is required");
  305. return;
  306. }
  307. stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
  308. ast_ari_response_no_content(response);
  309. }
  310. void ast_ari_channels_hold(struct ast_variable *headers,
  311. struct ast_ari_channels_hold_args *args,
  312. struct ast_ari_response *response)
  313. {
  314. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  315. control = find_control(response, args->channel_id);
  316. if (control == NULL) {
  317. /* Response filled in by find_control */
  318. return;
  319. }
  320. stasis_app_control_hold(control);
  321. ast_ari_response_no_content(response);
  322. }
  323. void ast_ari_channels_unhold(struct ast_variable *headers,
  324. struct ast_ari_channels_unhold_args *args,
  325. struct ast_ari_response *response)
  326. {
  327. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  328. control = find_control(response, args->channel_id);
  329. if (control == NULL) {
  330. /* Response filled in by find_control */
  331. return;
  332. }
  333. stasis_app_control_unhold(control);
  334. ast_ari_response_no_content(response);
  335. }
  336. void ast_ari_channels_start_moh(struct ast_variable *headers,
  337. struct ast_ari_channels_start_moh_args *args,
  338. struct ast_ari_response *response)
  339. {
  340. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  341. control = find_control(response, args->channel_id);
  342. if (control == NULL) {
  343. /* Response filled in by find_control */
  344. return;
  345. }
  346. stasis_app_control_moh_start(control, args->moh_class);
  347. ast_ari_response_no_content(response);
  348. }
  349. void ast_ari_channels_stop_moh(struct ast_variable *headers,
  350. struct ast_ari_channels_stop_moh_args *args,
  351. struct ast_ari_response *response)
  352. {
  353. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  354. control = find_control(response, args->channel_id);
  355. if (control == NULL) {
  356. /* Response filled in by find_control */
  357. return;
  358. }
  359. stasis_app_control_moh_stop(control);
  360. ast_ari_response_no_content(response);
  361. }
  362. void ast_ari_channels_start_silence(struct ast_variable *headers,
  363. struct ast_ari_channels_start_silence_args *args,
  364. struct ast_ari_response *response)
  365. {
  366. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  367. control = find_control(response, args->channel_id);
  368. if (control == NULL) {
  369. /* Response filled in by find_control */
  370. return;
  371. }
  372. stasis_app_control_silence_start(control);
  373. ast_ari_response_no_content(response);
  374. }
  375. void ast_ari_channels_stop_silence(struct ast_variable *headers,
  376. struct ast_ari_channels_stop_silence_args *args,
  377. struct ast_ari_response *response)
  378. {
  379. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  380. control = find_control(response, args->channel_id);
  381. if (control == NULL) {
  382. /* Response filled in by find_control */
  383. return;
  384. }
  385. stasis_app_control_silence_stop(control);
  386. ast_ari_response_no_content(response);
  387. }
  388. static void ari_channels_handle_play(
  389. const char *args_channel_id,
  390. const char *args_media,
  391. const char *args_lang,
  392. int args_offsetms,
  393. int args_skipms,
  394. const char *args_playback_id,
  395. struct ast_ari_response *response)
  396. {
  397. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  398. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  399. RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
  400. RAII_VAR(char *, playback_url, NULL, ast_free);
  401. struct ast_json *json;
  402. const char *language;
  403. ast_assert(response != NULL);
  404. control = find_control(response, args_channel_id);
  405. if (control == NULL) {
  406. /* Response filled in by find_control */
  407. return;
  408. }
  409. snapshot = stasis_app_control_get_snapshot(control);
  410. if (!snapshot) {
  411. ast_ari_response_error(
  412. response, 404, "Not Found",
  413. "Channel not found");
  414. return;
  415. }
  416. if (args_skipms < 0) {
  417. ast_ari_response_error(
  418. response, 400, "Bad Request",
  419. "skipms cannot be negative");
  420. return;
  421. }
  422. if (args_offsetms < 0) {
  423. ast_ari_response_error(
  424. response, 400, "Bad Request",
  425. "offsetms cannot be negative");
  426. return;
  427. }
  428. language = S_OR(args_lang, snapshot->language);
  429. playback = stasis_app_control_play_uri(control, args_media, language,
  430. args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
  431. if (!playback) {
  432. ast_ari_response_error(
  433. response, 500, "Internal Server Error",
  434. "Failed to queue media for playback");
  435. return;
  436. }
  437. if (ast_asprintf(&playback_url, "/playbacks/%s",
  438. stasis_app_playback_get_id(playback)) == -1) {
  439. playback_url = NULL;
  440. ast_ari_response_error(
  441. response, 500, "Internal Server Error",
  442. "Out of memory");
  443. return;
  444. }
  445. json = stasis_app_playback_to_json(playback);
  446. if (!json) {
  447. ast_ari_response_error(
  448. response, 500, "Internal Server Error",
  449. "Out of memory");
  450. return;
  451. }
  452. ast_ari_response_created(response, playback_url, json);
  453. }
  454. void ast_ari_channels_play(struct ast_variable *headers,
  455. struct ast_ari_channels_play_args *args,
  456. struct ast_ari_response *response)
  457. {
  458. ari_channels_handle_play(
  459. args->channel_id,
  460. args->media,
  461. args->lang,
  462. args->offsetms,
  463. args->skipms,
  464. args->playback_id,
  465. response);
  466. }
  467. void ast_ari_channels_play_with_id(struct ast_variable *headers,
  468. struct ast_ari_channels_play_with_id_args *args,
  469. struct ast_ari_response *response)
  470. {
  471. ari_channels_handle_play(
  472. args->channel_id,
  473. args->media,
  474. args->lang,
  475. args->offsetms,
  476. args->skipms,
  477. args->playback_id,
  478. response);
  479. }
  480. void ast_ari_channels_record(struct ast_variable *headers,
  481. struct ast_ari_channels_record_args *args,
  482. struct ast_ari_response *response)
  483. {
  484. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  485. RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
  486. RAII_VAR(char *, recording_url, NULL, ast_free);
  487. struct ast_json *json;
  488. RAII_VAR(struct stasis_app_recording_options *, options, NULL,
  489. ao2_cleanup);
  490. RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
  491. size_t uri_name_maxlen;
  492. ast_assert(response != NULL);
  493. if (args->max_duration_seconds < 0) {
  494. ast_ari_response_error(
  495. response, 400, "Bad Request",
  496. "max_duration_seconds cannot be negative");
  497. return;
  498. }
  499. if (args->max_silence_seconds < 0) {
  500. ast_ari_response_error(
  501. response, 400, "Bad Request",
  502. "max_silence_seconds cannot be negative");
  503. return;
  504. }
  505. control = find_control(response, args->channel_id);
  506. if (control == NULL) {
  507. /* Response filled in by find_control */
  508. return;
  509. }
  510. options = stasis_app_recording_options_create(args->name, args->format);
  511. if (options == NULL) {
  512. ast_ari_response_error(
  513. response, 500, "Internal Server Error",
  514. "Out of memory");
  515. }
  516. ast_string_field_build(options, target, "channel:%s", args->channel_id);
  517. options->max_silence_seconds = args->max_silence_seconds;
  518. options->max_duration_seconds = args->max_duration_seconds;
  519. options->terminate_on =
  520. stasis_app_recording_termination_parse(args->terminate_on);
  521. options->if_exists =
  522. stasis_app_recording_if_exists_parse(args->if_exists);
  523. options->beep = args->beep;
  524. if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
  525. ast_ari_response_error(
  526. response, 400, "Bad Request",
  527. "terminateOn invalid");
  528. return;
  529. }
  530. if (options->if_exists == AST_RECORD_IF_EXISTS_ERROR) {
  531. ast_ari_response_error(
  532. response, 400, "Bad Request",
  533. "ifExists invalid");
  534. return;
  535. }
  536. if (!ast_get_format_for_file_ext(options->format)) {
  537. ast_ari_response_error(
  538. response, 422, "Unprocessable Entity",
  539. "specified format is unknown on this system");
  540. return;
  541. }
  542. recording = stasis_app_control_record(control, options);
  543. if (recording == NULL) {
  544. switch(errno) {
  545. case EINVAL:
  546. /* While the arguments are invalid, we should have
  547. * caught them prior to calling record.
  548. */
  549. ast_ari_response_error(
  550. response, 500, "Internal Server Error",
  551. "Error parsing request");
  552. break;
  553. case EEXIST:
  554. ast_ari_response_error(response, 409, "Conflict",
  555. "Recording '%s' already exists and can not be overwritten",
  556. args->name);
  557. break;
  558. case ENOMEM:
  559. ast_ari_response_error(
  560. response, 500, "Internal Server Error",
  561. "Out of memory");
  562. break;
  563. case EPERM:
  564. ast_ari_response_error(
  565. response, 400, "Bad Request",
  566. "Recording name invalid");
  567. break;
  568. default:
  569. ast_log(LOG_WARNING,
  570. "Unrecognized recording error: %s\n",
  571. strerror(errno));
  572. ast_ari_response_error(
  573. response, 500, "Internal Server Error",
  574. "Internal Server Error");
  575. break;
  576. }
  577. return;
  578. }
  579. uri_name_maxlen = strlen(args->name) * 3;
  580. uri_encoded_name = ast_malloc(uri_name_maxlen);
  581. if (!uri_encoded_name) {
  582. ast_ari_response_error(
  583. response, 500, "Internal Server Error",
  584. "Out of memory");
  585. return;
  586. }
  587. ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
  588. ast_uri_http);
  589. if (ast_asprintf(&recording_url, "/recordings/live/%s",
  590. uri_encoded_name) == -1) {
  591. recording_url = NULL;
  592. ast_ari_response_error(
  593. response, 500, "Internal Server Error",
  594. "Out of memory");
  595. return;
  596. }
  597. json = stasis_app_recording_to_json(recording);
  598. if (!json) {
  599. ast_ari_response_error(
  600. response, 500, "Internal Server Error",
  601. "Out of memory");
  602. return;
  603. }
  604. ast_ari_response_created(response, recording_url, json);
  605. }
  606. void ast_ari_channels_get(struct ast_variable *headers,
  607. struct ast_ari_channels_get_args *args,
  608. struct ast_ari_response *response)
  609. {
  610. RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
  611. struct stasis_cache *cache;
  612. struct ast_channel_snapshot *snapshot;
  613. cache = ast_channel_cache();
  614. if (!cache) {
  615. ast_ari_response_error(
  616. response, 500, "Internal Server Error",
  617. "Message bus not initialized");
  618. return;
  619. }
  620. msg = stasis_cache_get(cache, ast_channel_snapshot_type(),
  621. args->channel_id);
  622. if (!msg) {
  623. ast_ari_response_error(
  624. response, 404, "Not Found",
  625. "Channel not found");
  626. return;
  627. }
  628. snapshot = stasis_message_data(msg);
  629. ast_assert(snapshot != NULL);
  630. ast_ari_response_ok(response,
  631. ast_channel_snapshot_to_json(snapshot, NULL));
  632. }
  633. void ast_ari_channels_hangup(struct ast_variable *headers,
  634. struct ast_ari_channels_hangup_args *args,
  635. struct ast_ari_response *response)
  636. {
  637. RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
  638. int cause;
  639. chan = ast_channel_get_by_name(args->channel_id);
  640. if (chan == NULL) {
  641. ast_ari_response_error(
  642. response, 404, "Not Found",
  643. "Channel not found");
  644. return;
  645. }
  646. if (ast_strlen_zero(args->reason) || !strcmp(args->reason, "normal")) {
  647. cause = AST_CAUSE_NORMAL;
  648. } else if (!strcmp(args->reason, "busy")) {
  649. cause = AST_CAUSE_BUSY;
  650. } else if (!strcmp(args->reason, "congestion")) {
  651. cause = AST_CAUSE_CONGESTION;
  652. } else if (!strcmp(args->reason, "no_answer")) {
  653. cause = AST_CAUSE_NOANSWER;
  654. } else {
  655. ast_ari_response_error(
  656. response, 400, "Invalid Reason",
  657. "Invalid reason for hangup provided");
  658. return;
  659. }
  660. ast_channel_hangupcause_set(chan, cause);
  661. ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
  662. ast_ari_response_no_content(response);
  663. }
  664. void ast_ari_channels_list(struct ast_variable *headers,
  665. struct ast_ari_channels_list_args *args,
  666. struct ast_ari_response *response)
  667. {
  668. RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
  669. RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
  670. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  671. struct ao2_iterator i;
  672. void *obj;
  673. struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
  674. cache = ast_channel_cache();
  675. if (!cache) {
  676. ast_ari_response_error(
  677. response, 500, "Internal Server Error",
  678. "Message bus not initialized");
  679. return;
  680. }
  681. ao2_ref(cache, +1);
  682. snapshots = stasis_cache_dump(cache, ast_channel_snapshot_type());
  683. if (!snapshots) {
  684. ast_ari_response_alloc_failed(response);
  685. return;
  686. }
  687. json = ast_json_array_create();
  688. if (!json) {
  689. ast_ari_response_alloc_failed(response);
  690. return;
  691. }
  692. i = ao2_iterator_init(snapshots, 0);
  693. while ((obj = ao2_iterator_next(&i))) {
  694. RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
  695. struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
  696. int r;
  697. if (sanitize && sanitize->channel_snapshot
  698. && sanitize->channel_snapshot(snapshot)) {
  699. continue;
  700. }
  701. r = ast_json_array_append(
  702. json, ast_channel_snapshot_to_json(snapshot, NULL));
  703. if (r != 0) {
  704. ast_ari_response_alloc_failed(response);
  705. ao2_iterator_destroy(&i);
  706. return;
  707. }
  708. }
  709. ao2_iterator_destroy(&i);
  710. ast_ari_response_ok(response, ast_json_ref(json));
  711. }
  712. /*! \brief Structure used for origination */
  713. struct ari_origination {
  714. /*! \brief Dialplan context */
  715. char context[AST_MAX_CONTEXT];
  716. /*! \brief Dialplan extension */
  717. char exten[AST_MAX_EXTENSION];
  718. /*! \brief Dialplan priority */
  719. int priority;
  720. /*! \brief Application data to pass to Stasis application */
  721. char appdata[0];
  722. };
  723. /*! \brief Thread which dials and executes upon answer */
  724. static void *ari_originate_dial(void *data)
  725. {
  726. struct ast_dial *dial = data;
  727. struct ari_origination *origination = ast_dial_get_user_data(dial);
  728. enum ast_dial_result res;
  729. res = ast_dial_run(dial, NULL, 0);
  730. if (res != AST_DIAL_RESULT_ANSWERED) {
  731. goto end;
  732. }
  733. if (!ast_strlen_zero(origination->appdata)) {
  734. struct ast_app *app = pbx_findapp("Stasis");
  735. if (app) {
  736. ast_verb(4, "Launching Stasis(%s) on %s\n", origination->appdata,
  737. ast_channel_name(ast_dial_answered(dial)));
  738. pbx_exec(ast_dial_answered(dial), app, origination->appdata);
  739. } else {
  740. ast_log(LOG_WARNING, "No such application 'Stasis'\n");
  741. }
  742. } else {
  743. struct ast_channel *answered = ast_dial_answered(dial);
  744. if (!ast_strlen_zero(origination->context)) {
  745. ast_channel_context_set(answered, origination->context);
  746. }
  747. if (!ast_strlen_zero(origination->exten)) {
  748. ast_channel_exten_set(answered, origination->exten);
  749. }
  750. if (origination->priority > 0) {
  751. ast_channel_priority_set(answered, origination->priority);
  752. }
  753. if (ast_pbx_run(answered)) {
  754. ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(answered));
  755. } else {
  756. /* PBX will have taken care of hanging up, so we steal the answered channel so dial doesn't do it */
  757. ast_dial_answered_steal(dial);
  758. }
  759. }
  760. end:
  761. ast_dial_destroy(dial);
  762. ast_free(origination);
  763. return NULL;
  764. }
  765. static void ari_channels_handle_originate_with_id(const char *args_endpoint,
  766. const char *args_extension,
  767. const char *args_context,
  768. long args_priority,
  769. const char *args_label,
  770. const char *args_app,
  771. const char *args_app_args,
  772. const char *args_caller_id,
  773. int args_timeout,
  774. struct ast_variable *variables,
  775. const char *args_channel_id,
  776. const char *args_other_channel_id,
  777. const char *args_originator,
  778. const char *args_formats,
  779. struct ast_ari_response *response)
  780. {
  781. char *dialtech;
  782. char dialdevice[AST_CHANNEL_NAME];
  783. struct ast_dial *dial;
  784. char *caller_id = NULL;
  785. char *cid_num = NULL;
  786. char *cid_name = NULL;
  787. char *stuff;
  788. struct ast_channel *other = NULL;
  789. struct ast_channel *chan = NULL;
  790. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  791. struct ast_assigned_ids assignedids = {
  792. .uniqueid = args_channel_id,
  793. .uniqueid2 = args_other_channel_id,
  794. };
  795. struct ari_origination *origination;
  796. pthread_t thread;
  797. struct ast_format_cap *format_cap = NULL;
  798. if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
  799. || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
  800. ast_ari_response_error(response, 400, "Bad Request",
  801. "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
  802. return;
  803. }
  804. if (ast_strlen_zero(args_endpoint)) {
  805. ast_ari_response_error(response, 400, "Bad Request",
  806. "Endpoint must be specified");
  807. return;
  808. }
  809. if (!ast_strlen_zero(args_originator) && !ast_strlen_zero(args_formats)) {
  810. ast_ari_response_error(response, 400, "Bad Request",
  811. "Originator and formats can't both be specified");
  812. return;
  813. }
  814. dialtech = ast_strdupa(args_endpoint);
  815. if ((stuff = strchr(dialtech, '/'))) {
  816. *stuff++ = '\0';
  817. ast_copy_string(dialdevice, stuff, sizeof(dialdevice));
  818. }
  819. if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
  820. ast_ari_response_error(response, 400, "Bad Request",
  821. "Invalid endpoint specified");
  822. return;
  823. }
  824. if (!ast_strlen_zero(args_app)) {
  825. RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
  826. if (!appdata) {
  827. ast_ari_response_alloc_failed(response);
  828. return;
  829. }
  830. ast_str_set(&appdata, 0, "%s", args_app);
  831. if (!ast_strlen_zero(args_app_args)) {
  832. ast_str_append(&appdata, 0, ",%s", args_app_args);
  833. }
  834. origination = ast_calloc(1, sizeof(*origination) + ast_str_size(appdata) + 1);
  835. if (!origination) {
  836. ast_ari_response_alloc_failed(response);
  837. return;
  838. }
  839. strcpy(origination->appdata, ast_str_buffer(appdata));
  840. } else if (!ast_strlen_zero(args_extension)) {
  841. origination = ast_calloc(1, sizeof(*origination) + 1);
  842. if (!origination) {
  843. ast_ari_response_alloc_failed(response);
  844. return;
  845. }
  846. ast_copy_string(origination->context, S_OR(args_context, "default"), sizeof(origination->context));
  847. ast_copy_string(origination->exten, args_extension, sizeof(origination->exten));
  848. if (!ast_strlen_zero(args_label)) {
  849. /* A label was provided in the request, use that */
  850. int ipri = 1;
  851. if (sscanf(args_label, "%30d", &ipri) != 1) {
  852. ipri = ast_findlabel_extension(chan, origination->context, origination->exten, args_label, args_caller_id);
  853. if (ipri == -1) {
  854. ast_log(AST_LOG_ERROR, "Requested label: %s can not be found in context: %s\n", args_label, args_context);
  855. ast_ari_response_error(response, 404, "Not Found", "Requested label can not be found");
  856. return;
  857. }
  858. } else {
  859. ast_debug(3, "Numeric value provided for label, jumping to that priority\n");
  860. }
  861. if (ipri == 0) {
  862. ast_log(AST_LOG_ERROR, "Invalid priority label '%s' specified for extension %s in context: %s\n",
  863. args_label, args_extension, args_context);
  864. ast_ari_response_error(response, 400, "Bad Request", "Requested priority is illegal");
  865. return;
  866. }
  867. /* Our priority was provided by a label */
  868. origination->priority = ipri;
  869. } else {
  870. /* No label provided, use provided priority */
  871. origination->priority = args_priority ? args_priority : 1;
  872. }
  873. origination->appdata[0] = '\0';
  874. } else {
  875. ast_ari_response_error(response, 400, "Bad Request",
  876. "Application or extension must be specified");
  877. return;
  878. }
  879. dial = ast_dial_create();
  880. if (!dial) {
  881. ast_ari_response_alloc_failed(response);
  882. ast_free(origination);
  883. return;
  884. }
  885. ast_dial_set_user_data(dial, origination);
  886. if (ast_dial_append(dial, dialtech, dialdevice, &assignedids)) {
  887. ast_ari_response_alloc_failed(response);
  888. ast_dial_destroy(dial);
  889. ast_free(origination);
  890. return;
  891. }
  892. if (args_timeout > 0) {
  893. ast_dial_set_global_timeout(dial, args_timeout * 1000);
  894. } else if (args_timeout == -1) {
  895. ast_dial_set_global_timeout(dial, -1);
  896. } else {
  897. ast_dial_set_global_timeout(dial, 30000);
  898. }
  899. if (!ast_strlen_zero(args_caller_id)) {
  900. caller_id = ast_strdupa(args_caller_id);
  901. ast_callerid_parse(caller_id, &cid_name, &cid_num);
  902. if (ast_is_shrinkable_phonenumber(cid_num)) {
  903. ast_shrink_phone_number(cid_num);
  904. }
  905. }
  906. if (!ast_strlen_zero(args_originator)) {
  907. other = ast_channel_get_by_name(args_originator);
  908. if (!other) {
  909. ast_ari_response_error(
  910. response, 400, "Bad Request",
  911. "Provided originator channel was not found");
  912. ast_dial_destroy(dial);
  913. ast_free(origination);
  914. return;
  915. }
  916. }
  917. if (!ast_strlen_zero(args_formats)) {
  918. char *format_name;
  919. char *formats_copy = ast_strdupa(args_formats);
  920. if (!(format_cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT))) {
  921. ast_ari_response_alloc_failed(response);
  922. ast_dial_destroy(dial);
  923. ast_free(origination);
  924. ast_channel_cleanup(other);
  925. return;
  926. }
  927. while ((format_name = ast_strip(strsep(&formats_copy, ",")))) {
  928. struct ast_format *fmt = ast_format_cache_get(format_name);
  929. if (!fmt || ast_format_cap_append(format_cap, fmt, 0)) {
  930. if (!fmt) {
  931. ast_ari_response_error(
  932. response, 400, "Bad Request",
  933. "Provided format (%s) was not found", format_name);
  934. } else {
  935. ast_ari_response_alloc_failed(response);
  936. }
  937. ast_dial_destroy(dial);
  938. ast_free(origination);
  939. ast_channel_cleanup(other);
  940. ao2_ref(format_cap, -1);
  941. ao2_cleanup(fmt);
  942. return;
  943. }
  944. ao2_ref(fmt, -1);
  945. }
  946. }
  947. if (ast_dial_prerun(dial, other, format_cap)) {
  948. if (ast_channel_errno() == AST_CHANNEL_ERROR_ID_EXISTS) {
  949. ast_ari_response_error(response, 409, "Conflict",
  950. "Channel with given unique ID already exists");
  951. } else {
  952. ast_ari_response_alloc_failed(response);
  953. }
  954. ast_dial_destroy(dial);
  955. ast_free(origination);
  956. ast_channel_cleanup(other);
  957. return;
  958. }
  959. ast_channel_cleanup(other);
  960. ao2_cleanup(format_cap);
  961. chan = ast_dial_get_channel(dial, 0);
  962. if (!chan) {
  963. ast_ari_response_alloc_failed(response);
  964. ast_dial_destroy(dial);
  965. ast_free(origination);
  966. return;
  967. }
  968. if (!ast_strlen_zero(cid_num) || !ast_strlen_zero(cid_name)) {
  969. struct ast_party_connected_line connected;
  970. /*
  971. * It seems strange to set the CallerID on an outgoing call leg
  972. * to whom we are calling, but this function's callers are doing
  973. * various Originate methods. This call leg goes to the local
  974. * user. Once the called party answers, the dialplan needs to
  975. * be able to access the CallerID from the CALLERID function as
  976. * if the called party had placed this call.
  977. */
  978. ast_set_callerid(chan, cid_num, cid_name, cid_num);
  979. ast_party_connected_line_set_init(&connected, ast_channel_connected(chan));
  980. if (!ast_strlen_zero(cid_num)) {
  981. connected.id.number.valid = 1;
  982. connected.id.number.str = (char *) cid_num;
  983. connected.id.number.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
  984. }
  985. if (!ast_strlen_zero(cid_name)) {
  986. connected.id.name.valid = 1;
  987. connected.id.name.str = (char *) cid_name;
  988. connected.id.name.presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
  989. }
  990. ast_channel_set_connected_line(chan, &connected, NULL);
  991. }
  992. ast_channel_lock(chan);
  993. if (variables) {
  994. ast_set_variables(chan, variables);
  995. }
  996. ast_set_flag(ast_channel_flags(chan), AST_FLAG_ORIGINATED);
  997. if (!ast_strlen_zero(args_app)) {
  998. struct ast_channel *local_peer;
  999. stasis_app_subscribe_channel(args_app, chan);
  1000. /* Subscribe to the Local channel peer also. */
  1001. local_peer = ast_local_get_peer(chan);
  1002. if (local_peer) {
  1003. stasis_app_subscribe_channel(args_app, local_peer);
  1004. ast_channel_unref(local_peer);
  1005. }
  1006. }
  1007. snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
  1008. ast_channel_unlock(chan);
  1009. /* Before starting the async dial bump the ref in case the dial quickly goes away and takes
  1010. * the reference with it
  1011. */
  1012. ast_channel_ref(chan);
  1013. if (ast_pthread_create_detached(&thread, NULL, ari_originate_dial, dial)) {
  1014. ast_ari_response_alloc_failed(response);
  1015. ast_dial_destroy(dial);
  1016. ast_free(origination);
  1017. } else {
  1018. ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
  1019. }
  1020. ast_channel_unref(chan);
  1021. return;
  1022. }
  1023. /*!
  1024. * \internal
  1025. * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
  1026. * \since 13.3.0
  1027. *
  1028. * \param[out] response HTTP response if error
  1029. * \param json_variables The JSON blob containing the variable
  1030. * \param[out] variables An out reference to the variables to populate.
  1031. *
  1032. * \retval 0 on success.
  1033. * \retval -1 on error.
  1034. */
  1035. static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
  1036. {
  1037. enum ast_json_to_ast_vars_code res;
  1038. res = ast_json_to_ast_variables(json_variables, variables);
  1039. switch (res) {
  1040. case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
  1041. return 0;
  1042. case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
  1043. ast_ari_response_error(response, 400, "Bad Request",
  1044. "Only string values in the 'variables' object allowed");
  1045. break;
  1046. case AST_JSON_TO_AST_VARS_CODE_OOM:
  1047. ast_ari_response_alloc_failed(response);
  1048. break;
  1049. }
  1050. ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
  1051. return -1;
  1052. }
  1053. void ast_ari_channels_originate_with_id(struct ast_variable *headers,
  1054. struct ast_ari_channels_originate_with_id_args *args,
  1055. struct ast_ari_response *response)
  1056. {
  1057. struct ast_variable *variables = NULL;
  1058. /* Parse any query parameters out of the body parameter */
  1059. if (args->variables) {
  1060. struct ast_json *json_variables;
  1061. ast_ari_channels_originate_with_id_parse_body(args->variables, args);
  1062. json_variables = ast_json_object_get(args->variables, "variables");
  1063. if (json_variables
  1064. && json_to_ast_variables(response, json_variables, &variables)) {
  1065. return;
  1066. }
  1067. }
  1068. ari_channels_handle_originate_with_id(
  1069. args->endpoint,
  1070. args->extension,
  1071. args->context,
  1072. args->priority,
  1073. args->label,
  1074. args->app,
  1075. args->app_args,
  1076. args->caller_id,
  1077. args->timeout,
  1078. variables,
  1079. args->channel_id,
  1080. args->other_channel_id,
  1081. args->originator,
  1082. args->formats,
  1083. response);
  1084. ast_variables_destroy(variables);
  1085. }
  1086. void ast_ari_channels_originate(struct ast_variable *headers,
  1087. struct ast_ari_channels_originate_args *args,
  1088. struct ast_ari_response *response)
  1089. {
  1090. struct ast_variable *variables = NULL;
  1091. /* Parse any query parameters out of the body parameter */
  1092. if (args->variables) {
  1093. struct ast_json *json_variables;
  1094. ast_ari_channels_originate_parse_body(args->variables, args);
  1095. json_variables = ast_json_object_get(args->variables, "variables");
  1096. if (json_variables
  1097. && json_to_ast_variables(response, json_variables, &variables)) {
  1098. return;
  1099. }
  1100. }
  1101. ari_channels_handle_originate_with_id(
  1102. args->endpoint,
  1103. args->extension,
  1104. args->context,
  1105. args->priority,
  1106. args->label,
  1107. args->app,
  1108. args->app_args,
  1109. args->caller_id,
  1110. args->timeout,
  1111. variables,
  1112. args->channel_id,
  1113. args->other_channel_id,
  1114. args->originator,
  1115. args->formats,
  1116. response);
  1117. ast_variables_destroy(variables);
  1118. }
  1119. void ast_ari_channels_get_channel_var(struct ast_variable *headers,
  1120. struct ast_ari_channels_get_channel_var_args *args,
  1121. struct ast_ari_response *response)
  1122. {
  1123. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  1124. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  1125. RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
  1126. RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
  1127. ast_assert(response != NULL);
  1128. if (!value) {
  1129. ast_ari_response_alloc_failed(response);
  1130. return;
  1131. }
  1132. if (ast_strlen_zero(args->variable)) {
  1133. ast_ari_response_error(
  1134. response, 400, "Bad Request",
  1135. "Variable name is required");
  1136. return;
  1137. }
  1138. if (ast_strlen_zero(args->channel_id)) {
  1139. ast_ari_response_error(
  1140. response, 400, "Bad Request",
  1141. "Channel ID is required");
  1142. return;
  1143. }
  1144. channel = ast_channel_get_by_name(args->channel_id);
  1145. if (!channel) {
  1146. ast_ari_response_error(
  1147. response, 404, "Channel Not Found",
  1148. "Provided channel was not found");
  1149. return;
  1150. }
  1151. /* You may be tempted to lock the channel you're about to read from. You
  1152. * would be wrong. Some dialplan functions put the channel into
  1153. * autoservice, which deadlocks if the channel is already locked.
  1154. * ast_str_retrieve_variable() does its own locking, and the dialplan
  1155. * functions need to as well. We should be fine without the lock.
  1156. */
  1157. if (args->variable[strlen(args->variable) - 1] == ')') {
  1158. if (ast_func_read2(channel, args->variable, &value, 0)) {
  1159. ast_ari_response_error(
  1160. response, 500, "Error With Function",
  1161. "Unable to read provided function");
  1162. return;
  1163. }
  1164. } else {
  1165. if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
  1166. ast_ari_response_error(
  1167. response, 404, "Variable Not Found",
  1168. "Provided variable was not found");
  1169. return;
  1170. }
  1171. }
  1172. if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
  1173. ast_ari_response_alloc_failed(response);
  1174. return;
  1175. }
  1176. ast_ari_response_ok(response, ast_json_ref(json));
  1177. }
  1178. void ast_ari_channels_set_channel_var(struct ast_variable *headers,
  1179. struct ast_ari_channels_set_channel_var_args *args,
  1180. struct ast_ari_response *response)
  1181. {
  1182. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  1183. ast_assert(response != NULL);
  1184. if (ast_strlen_zero(args->variable)) {
  1185. ast_ari_response_error(
  1186. response, 400, "Bad Request",
  1187. "Variable name is required");
  1188. return;
  1189. }
  1190. control = find_control(response, args->channel_id);
  1191. if (control == NULL) {
  1192. /* response filled in by find_control */
  1193. return;
  1194. }
  1195. if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
  1196. ast_ari_response_error(
  1197. response, 400, "Bad Request",
  1198. "Failed to execute function");
  1199. return;
  1200. }
  1201. ast_ari_response_no_content(response);
  1202. }
  1203. static void ari_channels_handle_snoop_channel(
  1204. const char *args_channel_id,
  1205. const char *args_spy,
  1206. const char *args_whisper,
  1207. const char *args_app,
  1208. const char *args_app_args,
  1209. const char *args_snoop_id,
  1210. struct ast_ari_response *response)
  1211. {
  1212. enum stasis_app_snoop_direction spy, whisper;
  1213. RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
  1214. RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
  1215. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  1216. ast_assert(response != NULL);
  1217. if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
  1218. spy = STASIS_SNOOP_DIRECTION_NONE;
  1219. } else if (!strcmp(args_spy, "both")) {
  1220. spy = STASIS_SNOOP_DIRECTION_BOTH;
  1221. } else if (!strcmp(args_spy, "out")) {
  1222. spy = STASIS_SNOOP_DIRECTION_OUT;
  1223. } else if (!strcmp(args_spy, "in")) {
  1224. spy = STASIS_SNOOP_DIRECTION_IN;
  1225. } else {
  1226. ast_ari_response_error(
  1227. response, 400, "Bad Request",
  1228. "Invalid direction specified for spy");
  1229. return;
  1230. }
  1231. if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
  1232. whisper = STASIS_SNOOP_DIRECTION_NONE;
  1233. } else if (!strcmp(args_whisper, "both")) {
  1234. whisper = STASIS_SNOOP_DIRECTION_BOTH;
  1235. } else if (!strcmp(args_whisper, "out")) {
  1236. whisper = STASIS_SNOOP_DIRECTION_OUT;
  1237. } else if (!strcmp(args_whisper, "in")) {
  1238. whisper = STASIS_SNOOP_DIRECTION_IN;
  1239. } else {
  1240. ast_ari_response_error(
  1241. response, 400, "Bad Request",
  1242. "Invalid direction specified for whisper");
  1243. return;
  1244. }
  1245. if (spy == STASIS_SNOOP_DIRECTION_NONE && whisper == STASIS_SNOOP_DIRECTION_NONE) {
  1246. ast_ari_response_error(
  1247. response, 400, "Bad Request",
  1248. "Direction must be specified for at least spy or whisper");
  1249. return;
  1250. } else if (ast_strlen_zero(args_app)) {
  1251. ast_ari_response_error(
  1252. response, 400, "Bad Request",
  1253. "Application name is required");
  1254. return;
  1255. }
  1256. chan = ast_channel_get_by_name(args_channel_id);
  1257. if (chan == NULL) {
  1258. ast_ari_response_error(
  1259. response, 404, "Channel Not Found",
  1260. "Provided channel was not found");
  1261. return;
  1262. }
  1263. snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
  1264. args_snoop_id);
  1265. if (snoop == NULL) {
  1266. ast_ari_response_error(
  1267. response, 500, "Internal error",
  1268. "Snoop channel could not be created");
  1269. return;
  1270. }
  1271. snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(snoop));
  1272. ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
  1273. }
  1274. void ast_ari_channels_snoop_channel(struct ast_variable *headers,
  1275. struct ast_ari_channels_snoop_channel_args *args,
  1276. struct ast_ari_response *response)
  1277. {
  1278. ari_channels_handle_snoop_channel(
  1279. args->channel_id,
  1280. args->spy,
  1281. args->whisper,
  1282. args->app,
  1283. args->app_args,
  1284. args->snoop_id,
  1285. response);
  1286. }
  1287. void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers,
  1288. struct ast_ari_channels_snoop_channel_with_id_args *args,
  1289. struct ast_ari_response *response)
  1290. {
  1291. ari_channels_handle_snoop_channel(
  1292. args->channel_id,
  1293. args->spy,
  1294. args->whisper,
  1295. args->app,
  1296. args->app_args,
  1297. args->snoop_id,
  1298. response);
  1299. }