resource_channels.c 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  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_app_playback</depend>
  26. <support_level>core</support_level>
  27. ***/
  28. #include "asterisk.h"
  29. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  30. #include "asterisk/file.h"
  31. #include "asterisk/pbx.h"
  32. #include "asterisk/bridge.h"
  33. #include "asterisk/callerid.h"
  34. #include "asterisk/stasis_app.h"
  35. #include "asterisk/stasis_app_playback.h"
  36. #include "asterisk/stasis_app_recording.h"
  37. #include "asterisk/stasis_app_snoop.h"
  38. #include "asterisk/stasis_channels.h"
  39. #include "asterisk/causes.h"
  40. #include "asterisk/format_cache.h"
  41. #include "asterisk/core_local.h"
  42. #include "resource_channels.h"
  43. #include <limits.h>
  44. /*!
  45. * \brief Finds the control object for a channel, filling the response with an
  46. * error, if appropriate.
  47. * \param[out] response Response to fill with an error if control is not found.
  48. * \param channel_id ID of the channel to lookup.
  49. * \return Channel control object.
  50. * \return \c NULL if control object does not exist.
  51. */
  52. static struct stasis_app_control *find_control(
  53. struct ast_ari_response *response,
  54. const char *channel_id)
  55. {
  56. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  57. ast_assert(response != NULL);
  58. control = stasis_app_control_find_by_channel_id(channel_id);
  59. if (control == NULL) {
  60. /* Distinguish between 404 and 409 errors */
  61. RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
  62. chan = ast_channel_get_by_name(channel_id);
  63. if (chan == NULL) {
  64. ast_ari_response_error(response, 404, "Not Found",
  65. "Channel not found");
  66. return NULL;
  67. }
  68. ast_ari_response_error(response, 409, "Conflict",
  69. "Channel not in Stasis application");
  70. return NULL;
  71. }
  72. ao2_ref(control, +1);
  73. return control;
  74. }
  75. void ast_ari_channels_continue_in_dialplan(
  76. struct ast_variable *headers,
  77. struct ast_ari_channels_continue_in_dialplan_args *args,
  78. struct ast_ari_response *response)
  79. {
  80. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  81. ast_assert(response != NULL);
  82. control = find_control(response, args->channel_id);
  83. if (control == NULL) {
  84. return;
  85. }
  86. if (stasis_app_control_continue(control, args->context, args->extension, args->priority)) {
  87. ast_ari_response_alloc_failed(response);
  88. return;
  89. }
  90. ast_ari_response_no_content(response);
  91. }
  92. void ast_ari_channels_answer(struct ast_variable *headers,
  93. struct ast_ari_channels_answer_args *args,
  94. struct ast_ari_response *response)
  95. {
  96. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  97. control = find_control(response, args->channel_id);
  98. if (control == NULL) {
  99. return;
  100. }
  101. if (stasis_app_control_answer(control) != 0) {
  102. ast_ari_response_error(
  103. response, 500, "Internal Server Error",
  104. "Failed to answer channel");
  105. return;
  106. }
  107. ast_ari_response_no_content(response);
  108. }
  109. void ast_ari_channels_ring(struct ast_variable *headers,
  110. struct ast_ari_channels_ring_args *args,
  111. struct ast_ari_response *response)
  112. {
  113. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  114. control = find_control(response, args->channel_id);
  115. if (control == NULL) {
  116. return;
  117. }
  118. stasis_app_control_ring(control);
  119. ast_ari_response_no_content(response);
  120. }
  121. void ast_ari_channels_ring_stop(struct ast_variable *headers,
  122. struct ast_ari_channels_ring_stop_args *args,
  123. struct ast_ari_response *response)
  124. {
  125. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  126. control = find_control(response, args->channel_id);
  127. if (control == NULL) {
  128. return;
  129. }
  130. stasis_app_control_ring_stop(control);
  131. ast_ari_response_no_content(response);
  132. }
  133. void ast_ari_channels_mute(struct ast_variable *headers,
  134. struct ast_ari_channels_mute_args *args,
  135. struct ast_ari_response *response)
  136. {
  137. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  138. unsigned int direction = 0;
  139. enum ast_frame_type frametype = AST_FRAME_VOICE;
  140. control = find_control(response, args->channel_id);
  141. if (control == NULL) {
  142. return;
  143. }
  144. if (ast_strlen_zero(args->direction)) {
  145. ast_ari_response_error(
  146. response, 400, "Bad Request",
  147. "Direction is required");
  148. return;
  149. }
  150. if (!strcmp(args->direction, "in")) {
  151. direction = AST_MUTE_DIRECTION_READ;
  152. } else if (!strcmp(args->direction, "out")) {
  153. direction = AST_MUTE_DIRECTION_WRITE;
  154. } else if (!strcmp(args->direction, "both")) {
  155. direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
  156. } else {
  157. ast_ari_response_error(
  158. response, 400, "Bad Request",
  159. "Invalid direction specified");
  160. return;
  161. }
  162. stasis_app_control_mute(control, direction, frametype);
  163. ast_ari_response_no_content(response);
  164. }
  165. void ast_ari_channels_unmute(struct ast_variable *headers,
  166. struct ast_ari_channels_unmute_args *args,
  167. struct ast_ari_response *response)
  168. {
  169. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  170. unsigned int direction = 0;
  171. enum ast_frame_type frametype = AST_FRAME_VOICE;
  172. control = find_control(response, args->channel_id);
  173. if (control == NULL) {
  174. return;
  175. }
  176. if (ast_strlen_zero(args->direction)) {
  177. ast_ari_response_error(
  178. response, 400, "Bad Request",
  179. "Direction is required");
  180. return;
  181. }
  182. if (!strcmp(args->direction, "in")) {
  183. direction = AST_MUTE_DIRECTION_READ;
  184. } else if (!strcmp(args->direction, "out")) {
  185. direction = AST_MUTE_DIRECTION_WRITE;
  186. } else if (!strcmp(args->direction, "both")) {
  187. direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
  188. } else {
  189. ast_ari_response_error(
  190. response, 400, "Bad Request",
  191. "Invalid direction specified");
  192. return;
  193. }
  194. stasis_app_control_unmute(control, direction, frametype);
  195. ast_ari_response_no_content(response);
  196. }
  197. void ast_ari_channels_send_dtmf(struct ast_variable *headers,
  198. struct ast_ari_channels_send_dtmf_args *args,
  199. struct ast_ari_response *response)
  200. {
  201. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  202. control = find_control(response, args->channel_id);
  203. if (control == NULL) {
  204. return;
  205. }
  206. if (ast_strlen_zero(args->dtmf)) {
  207. ast_ari_response_error(
  208. response, 400, "Bad Request",
  209. "DTMF is required");
  210. return;
  211. }
  212. stasis_app_control_dtmf(control, args->dtmf, args->before, args->between, args->duration, args->after);
  213. ast_ari_response_no_content(response);
  214. }
  215. void ast_ari_channels_hold(struct ast_variable *headers,
  216. struct ast_ari_channels_hold_args *args,
  217. struct ast_ari_response *response)
  218. {
  219. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  220. control = find_control(response, args->channel_id);
  221. if (control == NULL) {
  222. /* Response filled in by find_control */
  223. return;
  224. }
  225. stasis_app_control_hold(control);
  226. ast_ari_response_no_content(response);
  227. }
  228. void ast_ari_channels_unhold(struct ast_variable *headers,
  229. struct ast_ari_channels_unhold_args *args,
  230. struct ast_ari_response *response)
  231. {
  232. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  233. control = find_control(response, args->channel_id);
  234. if (control == NULL) {
  235. /* Response filled in by find_control */
  236. return;
  237. }
  238. stasis_app_control_unhold(control);
  239. ast_ari_response_no_content(response);
  240. }
  241. void ast_ari_channels_start_moh(struct ast_variable *headers,
  242. struct ast_ari_channels_start_moh_args *args,
  243. struct ast_ari_response *response)
  244. {
  245. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  246. control = find_control(response, args->channel_id);
  247. if (control == NULL) {
  248. /* Response filled in by find_control */
  249. return;
  250. }
  251. stasis_app_control_moh_start(control, args->moh_class);
  252. ast_ari_response_no_content(response);
  253. }
  254. void ast_ari_channels_stop_moh(struct ast_variable *headers,
  255. struct ast_ari_channels_stop_moh_args *args,
  256. struct ast_ari_response *response)
  257. {
  258. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  259. control = find_control(response, args->channel_id);
  260. if (control == NULL) {
  261. /* Response filled in by find_control */
  262. return;
  263. }
  264. stasis_app_control_moh_stop(control);
  265. ast_ari_response_no_content(response);
  266. }
  267. void ast_ari_channels_start_silence(struct ast_variable *headers,
  268. struct ast_ari_channels_start_silence_args *args,
  269. struct ast_ari_response *response)
  270. {
  271. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  272. control = find_control(response, args->channel_id);
  273. if (control == NULL) {
  274. /* Response filled in by find_control */
  275. return;
  276. }
  277. stasis_app_control_silence_start(control);
  278. ast_ari_response_no_content(response);
  279. }
  280. void ast_ari_channels_stop_silence(struct ast_variable *headers,
  281. struct ast_ari_channels_stop_silence_args *args,
  282. struct ast_ari_response *response)
  283. {
  284. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  285. control = find_control(response, args->channel_id);
  286. if (control == NULL) {
  287. /* Response filled in by find_control */
  288. return;
  289. }
  290. stasis_app_control_silence_stop(control);
  291. ast_ari_response_no_content(response);
  292. }
  293. static void ari_channels_handle_play(
  294. const char *args_channel_id,
  295. const char *args_media,
  296. const char *args_lang,
  297. int args_offsetms,
  298. int args_skipms,
  299. const char *args_playback_id,
  300. struct ast_ari_response *response)
  301. {
  302. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  303. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  304. RAII_VAR(struct stasis_app_playback *, playback, NULL, ao2_cleanup);
  305. RAII_VAR(char *, playback_url, NULL, ast_free);
  306. struct ast_json *json;
  307. const char *language;
  308. ast_assert(response != NULL);
  309. control = find_control(response, args_channel_id);
  310. if (control == NULL) {
  311. /* Response filled in by find_control */
  312. return;
  313. }
  314. snapshot = stasis_app_control_get_snapshot(control);
  315. if (!snapshot) {
  316. ast_ari_response_error(
  317. response, 404, "Not Found",
  318. "Channel not found");
  319. return;
  320. }
  321. if (args_skipms < 0) {
  322. ast_ari_response_error(
  323. response, 400, "Bad Request",
  324. "skipms cannot be negative");
  325. return;
  326. }
  327. if (args_offsetms < 0) {
  328. ast_ari_response_error(
  329. response, 400, "Bad Request",
  330. "offsetms cannot be negative");
  331. return;
  332. }
  333. language = S_OR(args_lang, snapshot->language);
  334. playback = stasis_app_control_play_uri(control, args_media, language,
  335. args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);
  336. if (!playback) {
  337. ast_ari_response_error(
  338. response, 500, "Internal Server Error",
  339. "Failed to queue media for playback");
  340. return;
  341. }
  342. if (ast_asprintf(&playback_url, "/playback/%s",
  343. stasis_app_playback_get_id(playback)) == -1) {
  344. playback_url = NULL;
  345. ast_ari_response_error(
  346. response, 500, "Internal Server Error",
  347. "Out of memory");
  348. return;
  349. }
  350. json = stasis_app_playback_to_json(playback);
  351. if (!json) {
  352. ast_ari_response_error(
  353. response, 500, "Internal Server Error",
  354. "Out of memory");
  355. return;
  356. }
  357. ast_ari_response_created(response, playback_url, json);
  358. }
  359. void ast_ari_channels_play(struct ast_variable *headers,
  360. struct ast_ari_channels_play_args *args,
  361. struct ast_ari_response *response)
  362. {
  363. ari_channels_handle_play(
  364. args->channel_id,
  365. args->media,
  366. args->lang,
  367. args->offsetms,
  368. args->skipms,
  369. args->playback_id,
  370. response);
  371. }
  372. void ast_ari_channels_play_with_id(struct ast_variable *headers,
  373. struct ast_ari_channels_play_with_id_args *args,
  374. struct ast_ari_response *response)
  375. {
  376. ari_channels_handle_play(
  377. args->channel_id,
  378. args->media,
  379. args->lang,
  380. args->offsetms,
  381. args->skipms,
  382. args->playback_id,
  383. response);
  384. }
  385. void ast_ari_channels_record(struct ast_variable *headers,
  386. struct ast_ari_channels_record_args *args,
  387. struct ast_ari_response *response)
  388. {
  389. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  390. RAII_VAR(struct stasis_app_recording *, recording, NULL, ao2_cleanup);
  391. RAII_VAR(char *, recording_url, NULL, ast_free);
  392. struct ast_json *json;
  393. RAII_VAR(struct stasis_app_recording_options *, options, NULL,
  394. ao2_cleanup);
  395. RAII_VAR(char *, uri_encoded_name, NULL, ast_free);
  396. size_t uri_name_maxlen;
  397. ast_assert(response != NULL);
  398. if (args->max_duration_seconds < 0) {
  399. ast_ari_response_error(
  400. response, 400, "Bad Request",
  401. "max_duration_seconds cannot be negative");
  402. return;
  403. }
  404. if (args->max_silence_seconds < 0) {
  405. ast_ari_response_error(
  406. response, 400, "Bad Request",
  407. "max_silence_seconds cannot be negative");
  408. return;
  409. }
  410. control = find_control(response, args->channel_id);
  411. if (control == NULL) {
  412. /* Response filled in by find_control */
  413. return;
  414. }
  415. options = stasis_app_recording_options_create(args->name, args->format);
  416. if (options == NULL) {
  417. ast_ari_response_error(
  418. response, 500, "Internal Server Error",
  419. "Out of memory");
  420. }
  421. ast_string_field_build(options, target, "channel:%s", args->channel_id);
  422. options->max_silence_seconds = args->max_silence_seconds;
  423. options->max_duration_seconds = args->max_duration_seconds;
  424. options->terminate_on =
  425. stasis_app_recording_termination_parse(args->terminate_on);
  426. options->if_exists =
  427. stasis_app_recording_if_exists_parse(args->if_exists);
  428. options->beep = args->beep;
  429. if (options->terminate_on == STASIS_APP_RECORDING_TERMINATE_INVALID) {
  430. ast_ari_response_error(
  431. response, 400, "Bad Request",
  432. "terminateOn invalid");
  433. return;
  434. }
  435. if (options->if_exists == -1) {
  436. ast_ari_response_error(
  437. response, 400, "Bad Request",
  438. "ifExists invalid");
  439. return;
  440. }
  441. if (!ast_get_format_for_file_ext(options->format)) {
  442. ast_ari_response_error(
  443. response, 422, "Unprocessable Entity",
  444. "specified format is unknown on this system");
  445. return;
  446. }
  447. recording = stasis_app_control_record(control, options);
  448. if (recording == NULL) {
  449. switch(errno) {
  450. case EINVAL:
  451. /* While the arguments are invalid, we should have
  452. * caught them prior to calling record.
  453. */
  454. ast_ari_response_error(
  455. response, 500, "Internal Server Error",
  456. "Error parsing request");
  457. break;
  458. case EEXIST:
  459. ast_ari_response_error(response, 409, "Conflict",
  460. "Recording '%s' already exists and can not be overwritten",
  461. args->name);
  462. break;
  463. case ENOMEM:
  464. ast_ari_response_error(
  465. response, 500, "Internal Server Error",
  466. "Out of memory");
  467. break;
  468. case EPERM:
  469. ast_ari_response_error(
  470. response, 400, "Bad Request",
  471. "Recording name invalid");
  472. break;
  473. default:
  474. ast_log(LOG_WARNING,
  475. "Unrecognized recording error: %s\n",
  476. strerror(errno));
  477. ast_ari_response_error(
  478. response, 500, "Internal Server Error",
  479. "Internal Server Error");
  480. break;
  481. }
  482. return;
  483. }
  484. uri_name_maxlen = strlen(args->name) * 3;
  485. uri_encoded_name = ast_malloc(uri_name_maxlen);
  486. if (!uri_encoded_name) {
  487. ast_ari_response_error(
  488. response, 500, "Internal Server Error",
  489. "Out of memory");
  490. return;
  491. }
  492. ast_uri_encode(args->name, uri_encoded_name, uri_name_maxlen,
  493. ast_uri_http);
  494. if (ast_asprintf(&recording_url, "/recordings/live/%s",
  495. uri_encoded_name) == -1) {
  496. recording_url = NULL;
  497. ast_ari_response_error(
  498. response, 500, "Internal Server Error",
  499. "Out of memory");
  500. return;
  501. }
  502. json = stasis_app_recording_to_json(recording);
  503. if (!json) {
  504. ast_ari_response_error(
  505. response, 500, "Internal Server Error",
  506. "Out of memory");
  507. return;
  508. }
  509. ast_ari_response_created(response, recording_url, json);
  510. }
  511. void ast_ari_channels_get(struct ast_variable *headers,
  512. struct ast_ari_channels_get_args *args,
  513. struct ast_ari_response *response)
  514. {
  515. RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
  516. struct stasis_cache *cache;
  517. struct ast_channel_snapshot *snapshot;
  518. cache = ast_channel_cache();
  519. if (!cache) {
  520. ast_ari_response_error(
  521. response, 500, "Internal Server Error",
  522. "Message bus not initialized");
  523. return;
  524. }
  525. msg = stasis_cache_get(cache, ast_channel_snapshot_type(),
  526. args->channel_id);
  527. if (!msg) {
  528. ast_ari_response_error(
  529. response, 404, "Not Found",
  530. "Channel not found");
  531. return;
  532. }
  533. snapshot = stasis_message_data(msg);
  534. ast_assert(snapshot != NULL);
  535. ast_ari_response_ok(response,
  536. ast_channel_snapshot_to_json(snapshot, NULL));
  537. }
  538. void ast_ari_channels_hangup(struct ast_variable *headers,
  539. struct ast_ari_channels_hangup_args *args,
  540. struct ast_ari_response *response)
  541. {
  542. RAII_VAR(struct ast_channel *, chan, NULL, ao2_cleanup);
  543. int cause;
  544. chan = ast_channel_get_by_name(args->channel_id);
  545. if (chan == NULL) {
  546. ast_ari_response_error(
  547. response, 404, "Not Found",
  548. "Channel not found");
  549. return;
  550. }
  551. if (ast_strlen_zero(args->reason) || !strcmp(args->reason, "normal")) {
  552. cause = AST_CAUSE_NORMAL;
  553. } else if (!strcmp(args->reason, "busy")) {
  554. cause = AST_CAUSE_BUSY;
  555. } else if (!strcmp(args->reason, "congestion")) {
  556. cause = AST_CAUSE_CONGESTION;
  557. } else {
  558. ast_ari_response_error(
  559. response, 400, "Invalid Reason",
  560. "Invalid reason for hangup provided");
  561. return;
  562. }
  563. ast_channel_hangupcause_set(chan, cause);
  564. ast_softhangup(chan, AST_SOFTHANGUP_EXPLICIT);
  565. ast_ari_response_no_content(response);
  566. }
  567. void ast_ari_channels_list(struct ast_variable *headers,
  568. struct ast_ari_channels_list_args *args,
  569. struct ast_ari_response *response)
  570. {
  571. RAII_VAR(struct stasis_cache *, cache, NULL, ao2_cleanup);
  572. RAII_VAR(struct ao2_container *, snapshots, NULL, ao2_cleanup);
  573. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  574. struct ao2_iterator i;
  575. void *obj;
  576. struct stasis_message_sanitizer *sanitize = stasis_app_get_sanitizer();
  577. cache = ast_channel_cache();
  578. if (!cache) {
  579. ast_ari_response_error(
  580. response, 500, "Internal Server Error",
  581. "Message bus not initialized");
  582. return;
  583. }
  584. ao2_ref(cache, +1);
  585. snapshots = stasis_cache_dump(cache, ast_channel_snapshot_type());
  586. if (!snapshots) {
  587. ast_ari_response_alloc_failed(response);
  588. return;
  589. }
  590. json = ast_json_array_create();
  591. if (!json) {
  592. ast_ari_response_alloc_failed(response);
  593. return;
  594. }
  595. i = ao2_iterator_init(snapshots, 0);
  596. while ((obj = ao2_iterator_next(&i))) {
  597. RAII_VAR(struct stasis_message *, msg, obj, ao2_cleanup);
  598. struct ast_channel_snapshot *snapshot = stasis_message_data(msg);
  599. int r;
  600. if (sanitize && sanitize->channel_snapshot
  601. && sanitize->channel_snapshot(snapshot)) {
  602. continue;
  603. }
  604. r = ast_json_array_append(
  605. json, ast_channel_snapshot_to_json(snapshot, NULL));
  606. if (r != 0) {
  607. ast_ari_response_alloc_failed(response);
  608. ao2_iterator_destroy(&i);
  609. return;
  610. }
  611. }
  612. ao2_iterator_destroy(&i);
  613. ast_ari_response_ok(response, ast_json_ref(json));
  614. }
  615. static void ari_channels_handle_originate_with_id(const char *args_endpoint,
  616. const char *args_extension,
  617. const char *args_context,
  618. long args_priority,
  619. const char *args_app,
  620. const char *args_app_args,
  621. const char *args_caller_id,
  622. int args_timeout,
  623. struct ast_variable *variables,
  624. const char *args_channel_id,
  625. const char *args_other_channel_id,
  626. struct ast_ari_response *response)
  627. {
  628. char *dialtech;
  629. char dialdevice[AST_CHANNEL_NAME];
  630. char *caller_id = NULL;
  631. char *cid_num = NULL;
  632. char *cid_name = NULL;
  633. int timeout = 30000;
  634. RAII_VAR(struct ast_format_cap *, cap,
  635. ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT), ao2_cleanup);
  636. char *stuff;
  637. struct ast_channel *chan;
  638. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  639. struct ast_assigned_ids assignedids = {
  640. .uniqueid = args_channel_id,
  641. .uniqueid2 = args_other_channel_id,
  642. };
  643. if (!cap) {
  644. ast_ari_response_alloc_failed(response);
  645. return;
  646. }
  647. ast_format_cap_append(cap, ast_format_slin, 0);
  648. if ((assignedids.uniqueid && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid))
  649. || (assignedids.uniqueid2 && AST_MAX_PUBLIC_UNIQUEID < strlen(assignedids.uniqueid2))) {
  650. ast_ari_response_error(response, 400, "Bad Request",
  651. "Uniqueid length exceeds maximum of %d", AST_MAX_PUBLIC_UNIQUEID);
  652. return;
  653. }
  654. if (ast_strlen_zero(args_endpoint)) {
  655. ast_ari_response_error(response, 400, "Bad Request",
  656. "Endpoint must be specified");
  657. return;
  658. }
  659. dialtech = ast_strdupa(args_endpoint);
  660. if ((stuff = strchr(dialtech, '/'))) {
  661. *stuff++ = '\0';
  662. ast_copy_string(dialdevice, stuff, sizeof(dialdevice));
  663. }
  664. if (ast_strlen_zero(dialtech) || ast_strlen_zero(dialdevice)) {
  665. ast_ari_response_error(response, 400, "Bad Request",
  666. "Invalid endpoint specified");
  667. return;
  668. }
  669. if (args_timeout > 0) {
  670. timeout = args_timeout * 1000;
  671. } else if (args_timeout == -1) {
  672. timeout = -1;
  673. }
  674. if (!ast_strlen_zero(args_caller_id)) {
  675. caller_id = ast_strdupa(args_caller_id);
  676. ast_callerid_parse(caller_id, &cid_name, &cid_num);
  677. if (ast_is_shrinkable_phonenumber(cid_num)) {
  678. ast_shrink_phone_number(cid_num);
  679. }
  680. }
  681. if (!ast_strlen_zero(args_app)) {
  682. const char *app = "Stasis";
  683. RAII_VAR(struct ast_str *, appdata, ast_str_create(64), ast_free);
  684. if (!appdata) {
  685. ast_ari_response_alloc_failed(response);
  686. return;
  687. }
  688. ast_str_set(&appdata, 0, "%s", args_app);
  689. if (!ast_strlen_zero(args_app_args)) {
  690. ast_str_append(&appdata, 0, ",%s", args_app_args);
  691. }
  692. /* originate a channel, putting it into an application */
  693. if (ast_pbx_outgoing_app(dialtech, cap, dialdevice, timeout, app, ast_str_buffer(appdata), NULL, 0, cid_num, cid_name, variables, NULL, &chan, &assignedids)) {
  694. ast_ari_response_alloc_failed(response);
  695. return;
  696. }
  697. } else if (!ast_strlen_zero(args_extension)) {
  698. /* originate a channel, sending it to an extension */
  699. if (ast_pbx_outgoing_exten(dialtech, cap, dialdevice, timeout, S_OR(args_context, "default"), args_extension, args_priority ? args_priority : 1, NULL, 0, cid_num, cid_name, variables, NULL, &chan, 0, &assignedids)) {
  700. ast_ari_response_alloc_failed(response);
  701. return;
  702. }
  703. } else {
  704. ast_ari_response_error(response, 400, "Bad Request",
  705. "Application or extension must be specified");
  706. return;
  707. }
  708. if (!ast_strlen_zero(args_app)) {
  709. struct ast_channel *local_peer;
  710. stasis_app_subscribe_channel(args_app, chan);
  711. /* Subscribe to the Local channel peer also. */
  712. local_peer = ast_local_get_peer(chan);
  713. if (local_peer) {
  714. stasis_app_subscribe_channel(args_app, local_peer);
  715. ast_channel_unref(local_peer);
  716. }
  717. }
  718. snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(chan));
  719. ast_channel_unlock(chan);
  720. ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
  721. ast_channel_unref(chan);
  722. }
  723. void ast_ari_channels_originate_with_id(struct ast_variable *headers,
  724. struct ast_ari_channels_originate_with_id_args *args,
  725. struct ast_ari_response *response)
  726. {
  727. RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
  728. /* Parse any query parameters out of the body parameter */
  729. if (args->variables) {
  730. struct ast_json *json_variables;
  731. ast_ari_channels_originate_with_id_parse_body(args->variables, args);
  732. json_variables = ast_json_object_get(args->variables, "variables");
  733. if (json_variables) {
  734. if (ast_json_to_ast_variables(json_variables, &variables)) {
  735. ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
  736. ast_ari_response_alloc_failed(response);
  737. return;
  738. }
  739. }
  740. }
  741. ari_channels_handle_originate_with_id(
  742. args->endpoint,
  743. args->extension,
  744. args->context,
  745. args->priority,
  746. args->app,
  747. args->app_args,
  748. args->caller_id,
  749. args->timeout,
  750. variables,
  751. args->channel_id,
  752. args->other_channel_id,
  753. response);
  754. }
  755. void ast_ari_channels_originate(struct ast_variable *headers,
  756. struct ast_ari_channels_originate_args *args,
  757. struct ast_ari_response *response)
  758. {
  759. RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
  760. /* Parse any query parameters out of the body parameter */
  761. if (args->variables) {
  762. struct ast_json *json_variables;
  763. ast_ari_channels_originate_parse_body(args->variables, args);
  764. json_variables = ast_json_object_get(args->variables, "variables");
  765. if (json_variables) {
  766. if (ast_json_to_ast_variables(json_variables, &variables)) {
  767. ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
  768. ast_ari_response_alloc_failed(response);
  769. return;
  770. }
  771. }
  772. }
  773. ari_channels_handle_originate_with_id(
  774. args->endpoint,
  775. args->extension,
  776. args->context,
  777. args->priority,
  778. args->app,
  779. args->app_args,
  780. args->caller_id,
  781. args->timeout,
  782. variables,
  783. args->channel_id,
  784. args->other_channel_id,
  785. response);
  786. }
  787. void ast_ari_channels_get_channel_var(struct ast_variable *headers,
  788. struct ast_ari_channels_get_channel_var_args *args,
  789. struct ast_ari_response *response)
  790. {
  791. RAII_VAR(struct ast_json *, json, NULL, ast_json_unref);
  792. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  793. RAII_VAR(struct ast_str *, value, ast_str_create(32), ast_free);
  794. RAII_VAR(struct ast_channel *, channel, NULL, ast_channel_cleanup);
  795. ast_assert(response != NULL);
  796. if (ast_strlen_zero(args->variable)) {
  797. ast_ari_response_error(
  798. response, 400, "Bad Request",
  799. "Variable name is required");
  800. return;
  801. }
  802. if (ast_strlen_zero(args->channel_id)) {
  803. ast_ari_response_error(
  804. response, 400, "Bad Request",
  805. "Channel ID is required");
  806. return;
  807. }
  808. channel = ast_channel_get_by_name(args->channel_id);
  809. if (!channel) {
  810. ast_ari_response_error(
  811. response, 404, "Channel Not Found",
  812. "Provided channel was not found");
  813. return;
  814. }
  815. /* You may be tempted to lock the channel you're about to read from. You
  816. * would be wrong. Some dialplan functions put the channel into
  817. * autoservice, which deadlocks if the channel is already locked.
  818. * ast_str_retrieve_variable() does its own locking, and the dialplan
  819. * functions need to as well. We should be fine without the lock.
  820. */
  821. if (args->variable[strlen(args->variable) - 1] == ')') {
  822. if (ast_func_read2(channel, args->variable, &value, 0)) {
  823. ast_ari_response_error(
  824. response, 500, "Error With Function",
  825. "Unable to read provided function");
  826. return;
  827. }
  828. } else {
  829. if (!ast_str_retrieve_variable(&value, 0, channel, NULL, args->variable)) {
  830. ast_ari_response_alloc_failed(response);
  831. return;
  832. }
  833. }
  834. if (!(json = ast_json_pack("{s: s}", "value", S_OR(ast_str_buffer(value), "")))) {
  835. ast_ari_response_alloc_failed(response);
  836. return;
  837. }
  838. ast_ari_response_ok(response, ast_json_ref(json));
  839. }
  840. void ast_ari_channels_set_channel_var(struct ast_variable *headers,
  841. struct ast_ari_channels_set_channel_var_args *args,
  842. struct ast_ari_response *response)
  843. {
  844. RAII_VAR(struct stasis_app_control *, control, NULL, ao2_cleanup);
  845. ast_assert(response != NULL);
  846. if (ast_strlen_zero(args->variable)) {
  847. ast_ari_response_error(
  848. response, 400, "Bad Request",
  849. "Variable name is required");
  850. return;
  851. }
  852. control = find_control(response, args->channel_id);
  853. if (control == NULL) {
  854. /* response filled in by find_control */
  855. return;
  856. }
  857. if (stasis_app_control_set_channel_var(control, args->variable, args->value)) {
  858. ast_ari_response_error(
  859. response, 400, "Bad Request",
  860. "Failed to execute function");
  861. return;
  862. }
  863. ast_ari_response_no_content(response);
  864. }
  865. static void ari_channels_handle_snoop_channel(
  866. const char *args_channel_id,
  867. const char *args_spy,
  868. const char *args_whisper,
  869. const char *args_app,
  870. const char *args_app_args,
  871. const char *args_snoop_id,
  872. struct ast_ari_response *response)
  873. {
  874. enum stasis_app_snoop_direction spy, whisper;
  875. RAII_VAR(struct ast_channel *, chan, NULL, ast_channel_cleanup);
  876. RAII_VAR(struct ast_channel *, snoop, NULL, ast_channel_cleanup);
  877. RAII_VAR(struct ast_channel_snapshot *, snapshot, NULL, ao2_cleanup);
  878. ast_assert(response != NULL);
  879. if (ast_strlen_zero(args_spy) || !strcmp(args_spy, "none")) {
  880. spy = STASIS_SNOOP_DIRECTION_NONE;
  881. } else if (!strcmp(args_spy, "both")) {
  882. spy = STASIS_SNOOP_DIRECTION_BOTH;
  883. } else if (!strcmp(args_spy, "out")) {
  884. spy = STASIS_SNOOP_DIRECTION_OUT;
  885. } else if (!strcmp(args_spy, "in")) {
  886. spy = STASIS_SNOOP_DIRECTION_IN;
  887. } else {
  888. ast_ari_response_error(
  889. response, 400, "Bad Request",
  890. "Invalid direction specified for spy");
  891. return;
  892. }
  893. if (ast_strlen_zero(args_whisper) || !strcmp(args_whisper, "none")) {
  894. whisper = STASIS_SNOOP_DIRECTION_NONE;
  895. } else if (!strcmp(args_whisper, "both")) {
  896. whisper = STASIS_SNOOP_DIRECTION_BOTH;
  897. } else if (!strcmp(args_whisper, "out")) {
  898. whisper = STASIS_SNOOP_DIRECTION_OUT;
  899. } else if (!strcmp(args_whisper, "in")) {
  900. whisper = STASIS_SNOOP_DIRECTION_IN;
  901. } else {
  902. ast_ari_response_error(
  903. response, 400, "Bad Request",
  904. "Invalid direction specified for whisper");
  905. return;
  906. }
  907. if (spy == STASIS_SNOOP_DIRECTION_NONE && whisper == STASIS_SNOOP_DIRECTION_NONE) {
  908. ast_ari_response_error(
  909. response, 400, "Bad Request",
  910. "Direction must be specified for at least spy or whisper");
  911. return;
  912. } else if (ast_strlen_zero(args_app)) {
  913. ast_ari_response_error(
  914. response, 400, "Bad Request",
  915. "Application name is required");
  916. return;
  917. }
  918. chan = ast_channel_get_by_name(args_channel_id);
  919. if (chan == NULL) {
  920. ast_ari_response_error(
  921. response, 404, "Channel Not Found",
  922. "Provided channel was not found");
  923. return;
  924. }
  925. snoop = stasis_app_control_snoop(chan, spy, whisper, args_app, args_app_args,
  926. args_snoop_id);
  927. if (snoop == NULL) {
  928. ast_ari_response_error(
  929. response, 500, "Internal error",
  930. "Snoop channel could not be created");
  931. return;
  932. }
  933. snapshot = ast_channel_snapshot_get_latest(ast_channel_uniqueid(snoop));
  934. ast_ari_response_ok(response, ast_channel_snapshot_to_json(snapshot, NULL));
  935. }
  936. void ast_ari_channels_snoop_channel(struct ast_variable *headers,
  937. struct ast_ari_channels_snoop_channel_args *args,
  938. struct ast_ari_response *response)
  939. {
  940. ari_channels_handle_snoop_channel(
  941. args->channel_id,
  942. args->spy,
  943. args->whisper,
  944. args->app,
  945. args->app_args,
  946. args->snoop_id,
  947. response);
  948. }
  949. void ast_ari_channels_snoop_channel_with_id(struct ast_variable *headers,
  950. struct ast_ari_channels_snoop_channel_with_id_args *args,
  951. struct ast_ari_response *response)
  952. {
  953. ari_channels_handle_snoop_channel(
  954. args->channel_id,
  955. args->spy,
  956. args->whisper,
  957. args->app,
  958. args->app_args,
  959. args->snoop_id,
  960. response);
  961. }