core_unreal.c 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2013 Digium, Inc.
  5. *
  6. * Richard Mudgett <rmudgett@digium.com>
  7. *
  8. * See http://www.asterisk.org for more information about
  9. * the Asterisk project. Please do not directly contact
  10. * any of the maintainers of this project for assistance;
  11. * the project provides a web site, mailing lists and IRC
  12. * channels for your use.
  13. *
  14. * This program is free software, distributed under the terms of
  15. * the GNU General Public License Version 2. See the LICENSE file
  16. * at the top of the source tree.
  17. */
  18. /*!
  19. * \file
  20. * \brief Unreal channel derivatives framework for channel drivers like local channels.
  21. *
  22. * \author Richard Mudgett <rmudgett@digium.com>
  23. *
  24. * See Also:
  25. * \arg \ref AstCREDITS
  26. */
  27. /*** MODULEINFO
  28. <support_level>core</support_level>
  29. ***/
  30. #include "asterisk.h"
  31. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  32. #include "asterisk/causes.h"
  33. #include "asterisk/channel.h"
  34. #include "asterisk/stasis_channels.h"
  35. #include "asterisk/pbx.h"
  36. #include "asterisk/musiconhold.h"
  37. #include "asterisk/astobj2.h"
  38. #include "asterisk/bridge.h"
  39. #include "asterisk/core_unreal.h"
  40. static unsigned int name_sequence = 0;
  41. void ast_unreal_lock_all(struct ast_unreal_pvt *p, struct ast_channel **outchan, struct ast_channel **outowner)
  42. {
  43. struct ast_channel *chan = NULL;
  44. struct ast_channel *owner = NULL;
  45. ao2_lock(p);
  46. for (;;) {
  47. if (p->chan) {
  48. chan = p->chan;
  49. ast_channel_ref(chan);
  50. }
  51. if (p->owner) {
  52. owner = p->owner;
  53. ast_channel_ref(owner);
  54. }
  55. ao2_unlock(p);
  56. /* if we don't have both channels, then this is very easy */
  57. if (!owner || !chan) {
  58. if (owner) {
  59. ast_channel_lock(owner);
  60. } else if(chan) {
  61. ast_channel_lock(chan);
  62. }
  63. } else {
  64. /* lock both channels first, then get the pvt lock */
  65. ast_channel_lock_both(chan, owner);
  66. }
  67. ao2_lock(p);
  68. /* Now that we have all the locks, validate that nothing changed */
  69. if (p->owner != owner || p->chan != chan) {
  70. if (owner) {
  71. ast_channel_unlock(owner);
  72. owner = ast_channel_unref(owner);
  73. }
  74. if (chan) {
  75. ast_channel_unlock(chan);
  76. chan = ast_channel_unref(chan);
  77. }
  78. continue;
  79. }
  80. break;
  81. }
  82. *outowner = p->owner;
  83. *outchan = p->chan;
  84. }
  85. /* Called with ast locked */
  86. int ast_unreal_setoption(struct ast_channel *ast, int option, void *data, int datalen)
  87. {
  88. int res = 0;
  89. struct ast_unreal_pvt *p;
  90. struct ast_channel *otherchan = NULL;
  91. ast_chan_write_info_t *write_info;
  92. char *info_data;
  93. if (option != AST_OPTION_CHANNEL_WRITE) {
  94. return -1;
  95. }
  96. write_info = data;
  97. if (write_info->version != AST_CHAN_WRITE_INFO_T_VERSION) {
  98. ast_log(LOG_ERROR, "The chan_write_info_t type has changed, and this channel hasn't been updated!\n");
  99. return -1;
  100. }
  101. info_data = write_info->data;
  102. if (!strcmp(write_info->function, "CHANNEL")) {
  103. if (!strncasecmp(info_data, "hangup_handler_", 15)) {
  104. /* Block CHANNEL(hangup_handler_xxx) writes to the other unreal channel. */
  105. return 0;
  106. }
  107. /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
  108. if (!strcasecmp(info_data, "accountcode")) {
  109. info_data = "peeraccount";
  110. } else if (!strcasecmp(info_data, "peeraccount")) {
  111. info_data = "accountcode";
  112. }
  113. }
  114. /* get the tech pvt */
  115. if (!(p = ast_channel_tech_pvt(ast))) {
  116. return -1;
  117. }
  118. ao2_ref(p, 1);
  119. ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
  120. /* get the channel we are supposed to write to */
  121. ao2_lock(p);
  122. otherchan = (write_info->chan == p->owner) ? p->chan : p->owner;
  123. if (!otherchan || otherchan == write_info->chan) {
  124. res = -1;
  125. otherchan = NULL;
  126. ao2_unlock(p);
  127. goto setoption_cleanup;
  128. }
  129. ast_channel_ref(otherchan);
  130. /* clear the pvt lock before grabbing the channel */
  131. ao2_unlock(p);
  132. ast_channel_lock(otherchan);
  133. res = write_info->write_fn(otherchan, write_info->function, info_data, write_info->value);
  134. ast_channel_unlock(otherchan);
  135. setoption_cleanup:
  136. ao2_ref(p, -1);
  137. if (otherchan) {
  138. ast_channel_unref(otherchan);
  139. }
  140. ast_channel_lock(ast); /* Lock back before we leave */
  141. return res;
  142. }
  143. /* Called with ast locked */
  144. int ast_unreal_queryoption(struct ast_channel *ast, int option, void *data, int *datalen)
  145. {
  146. struct ast_unreal_pvt *p;
  147. struct ast_channel *peer;
  148. struct ast_channel *other;
  149. int res = 0;
  150. if (option != AST_OPTION_T38_STATE) {
  151. /* AST_OPTION_T38_STATE is the only supported option at this time */
  152. return -1;
  153. }
  154. /* for some reason the channel is not locked in channel.c when this function is called */
  155. if (!(p = ast_channel_tech_pvt(ast))) {
  156. return -1;
  157. }
  158. ao2_lock(p);
  159. other = AST_UNREAL_IS_OUTBOUND(ast, p) ? p->owner : p->chan;
  160. if (!other) {
  161. ao2_unlock(p);
  162. return -1;
  163. }
  164. ast_channel_ref(other);
  165. ao2_unlock(p);
  166. ast_channel_unlock(ast); /* Held when called, unlock before locking another channel */
  167. peer = ast_channel_bridge_peer(other);
  168. if (peer) {
  169. res = ast_channel_queryoption(peer, option, data, datalen, 0);
  170. ast_channel_unref(peer);
  171. }
  172. ast_channel_unref(other);
  173. ast_channel_lock(ast); /* Lock back before we leave */
  174. return res;
  175. }
  176. /*!
  177. * \brief queue a frame onto either the p->owner or p->chan
  178. *
  179. * \note the ast_unreal_pvt MUST have it's ref count bumped before entering this function and
  180. * decremented after this function is called. This is a side effect of the deadlock
  181. * avoidance that is necessary to lock 2 channels and a tech_pvt. Without a ref counted
  182. * ast_unreal_pvt, it is impossible to guarantee it will not be destroyed by another thread
  183. * during deadlock avoidance.
  184. */
  185. static int unreal_queue_frame(struct ast_unreal_pvt *p, int isoutbound, struct ast_frame *f,
  186. struct ast_channel *us, int us_locked)
  187. {
  188. struct ast_channel *other;
  189. /* Recalculate outbound channel */
  190. other = isoutbound ? p->owner : p->chan;
  191. if (!other) {
  192. return 0;
  193. }
  194. /* do not queue media frames if a generator is on both unreal channels */
  195. if (us
  196. && (f->frametype == AST_FRAME_VOICE || f->frametype == AST_FRAME_VIDEO)
  197. && ast_channel_generator(us)
  198. && ast_channel_generator(other)) {
  199. return 0;
  200. }
  201. /* grab a ref on the channel before unlocking the pvt,
  202. * other can not go away from us now regardless of locking */
  203. ast_channel_ref(other);
  204. if (us && us_locked) {
  205. ast_channel_unlock(us);
  206. }
  207. ao2_unlock(p);
  208. if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_RINGING) {
  209. ast_setstate(other, AST_STATE_RINGING);
  210. }
  211. ast_queue_frame(other, f);
  212. other = ast_channel_unref(other);
  213. if (us && us_locked) {
  214. ast_channel_lock(us);
  215. }
  216. ao2_lock(p);
  217. return 0;
  218. }
  219. int ast_unreal_answer(struct ast_channel *ast)
  220. {
  221. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  222. int isoutbound;
  223. int res = -1;
  224. if (!p) {
  225. return -1;
  226. }
  227. ao2_ref(p, 1);
  228. ao2_lock(p);
  229. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  230. if (isoutbound) {
  231. /* Pass along answer since somebody answered us */
  232. struct ast_frame answer = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
  233. res = unreal_queue_frame(p, isoutbound, &answer, ast, 1);
  234. } else {
  235. ast_log(LOG_WARNING, "Huh? %s is being asked to answer?\n",
  236. ast_channel_name(ast));
  237. }
  238. ao2_unlock(p);
  239. ao2_ref(p, -1);
  240. return res;
  241. }
  242. /*!
  243. * \internal
  244. * \brief Check and optimize out the unreal channels between bridges.
  245. * \since 12.0.0
  246. *
  247. * \param ast Channel writing a frame into the unreal channels.
  248. * \param p Unreal channel private.
  249. *
  250. * \note It is assumed that ast is locked.
  251. * \note It is assumed that p is locked.
  252. *
  253. * \retval 0 if unreal channels were not optimized out.
  254. * \retval non-zero if unreal channels were optimized out.
  255. */
  256. static int got_optimized_out(struct ast_channel *ast, struct ast_unreal_pvt *p)
  257. {
  258. int res = 0;
  259. /* Do a few conditional checks early on just to see if this optimization is possible */
  260. if (ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION) || !p->chan || !p->owner) {
  261. return res;
  262. }
  263. if (ast == p->owner) {
  264. res = ast_bridge_unreal_optimize_out(p->owner, p->chan, p);
  265. } else if (ast == p->chan) {
  266. res = ast_bridge_unreal_optimize_out(p->chan, p->owner, p);
  267. }
  268. return res;
  269. }
  270. struct ast_frame *ast_unreal_read(struct ast_channel *ast)
  271. {
  272. return &ast_null_frame;
  273. }
  274. int ast_unreal_write(struct ast_channel *ast, struct ast_frame *f)
  275. {
  276. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  277. int res = -1;
  278. if (!p) {
  279. return -1;
  280. }
  281. /* Just queue for delivery to the other side */
  282. ao2_ref(p, 1);
  283. ao2_lock(p);
  284. switch (f->frametype) {
  285. case AST_FRAME_VOICE:
  286. case AST_FRAME_VIDEO:
  287. if (got_optimized_out(ast, p)) {
  288. break;
  289. }
  290. /* fall through */
  291. default:
  292. res = unreal_queue_frame(p, AST_UNREAL_IS_OUTBOUND(ast, p), f, ast, 1);
  293. break;
  294. }
  295. ao2_unlock(p);
  296. ao2_ref(p, -1);
  297. return res;
  298. }
  299. int ast_unreal_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
  300. {
  301. struct ast_unreal_pvt *p = ast_channel_tech_pvt(newchan);
  302. struct ast_bridge *bridge_owner;
  303. struct ast_bridge *bridge_chan;
  304. if (!p) {
  305. return -1;
  306. }
  307. ao2_lock(p);
  308. if ((p->owner != oldchan) && (p->chan != oldchan)) {
  309. ast_log(LOG_WARNING, "Old channel %p wasn't %p or %p\n", oldchan, p->owner, p->chan);
  310. ao2_unlock(p);
  311. return -1;
  312. }
  313. if (p->owner == oldchan) {
  314. p->owner = newchan;
  315. } else {
  316. p->chan = newchan;
  317. }
  318. if (ast_check_hangup(newchan) || !p->owner || !p->chan) {
  319. ao2_unlock(p);
  320. return 0;
  321. }
  322. /* Do not let a masquerade cause an unreal channel to be bridged to itself! */
  323. bridge_owner = ast_channel_internal_bridge(p->owner);
  324. bridge_chan = ast_channel_internal_bridge(p->chan);
  325. if (bridge_owner && bridge_owner == bridge_chan) {
  326. ast_log(LOG_WARNING, "You can not bridge an unreal channel (%s) to itself!\n",
  327. ast_channel_name(newchan));
  328. ao2_unlock(p);
  329. ast_queue_hangup(newchan);
  330. return -1;
  331. }
  332. ao2_unlock(p);
  333. return 0;
  334. }
  335. /*!
  336. * \internal
  337. * \brief Queue up a frame representing the indication as a control frame.
  338. * \since 12.0.0
  339. *
  340. * \param p Unreal private structure.
  341. * \param ast Channel indicating the condition.
  342. * \param condition What is being indicated.
  343. * \param data Extra data.
  344. * \param datalen Length of extra data.
  345. *
  346. * \retval 0 on success.
  347. * \retval AST_T38_REQUEST_PARMS if successful and condition is AST_CONTROL_T38_PARAMETERS.
  348. * \retval -1 on error.
  349. */
  350. static int unreal_queue_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition, const void *data, size_t datalen)
  351. {
  352. int res = 0;
  353. int isoutbound;
  354. ao2_lock(p);
  355. /*
  356. * Block -1 stop tones events if we are to be optimized out. We
  357. * don't need a flurry of these events on an unreal channel chain
  358. * when initially connected to slow the optimization process.
  359. */
  360. if (0 <= condition || ast_test_flag(p, AST_UNREAL_NO_OPTIMIZATION)) {
  361. struct ast_frame f = {
  362. .frametype = AST_FRAME_CONTROL,
  363. .subclass.integer = condition,
  364. .data.ptr = (void *) data,
  365. .datalen = datalen,
  366. };
  367. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  368. res = unreal_queue_frame(p, isoutbound, &f, ast, 1);
  369. if (!res
  370. && condition == AST_CONTROL_T38_PARAMETERS
  371. && datalen == sizeof(struct ast_control_t38_parameters)) {
  372. const struct ast_control_t38_parameters *parameters = data;
  373. if (parameters->request_response == AST_T38_REQUEST_PARMS) {
  374. res = AST_T38_REQUEST_PARMS;
  375. }
  376. }
  377. } else {
  378. ast_debug(4, "Blocked indication %d\n", condition);
  379. }
  380. ao2_unlock(p);
  381. return res;
  382. }
  383. /*!
  384. * \internal
  385. * \brief Handle COLP and redirecting conditions.
  386. * \since 12.0.0
  387. *
  388. * \param p Unreal private structure.
  389. * \param ast Channel indicating the condition.
  390. * \param condition What is being indicated.
  391. *
  392. * \retval 0 on success.
  393. * \retval -1 on error.
  394. */
  395. static int unreal_colp_redirect_indicate(struct ast_unreal_pvt *p, struct ast_channel *ast, int condition)
  396. {
  397. struct ast_channel *my_chan;
  398. struct ast_channel *my_owner;
  399. struct ast_channel *this_channel;
  400. struct ast_channel *the_other_channel;
  401. int isoutbound;
  402. int res = 0;
  403. unsigned char frame_data[1024];
  404. struct ast_frame f = {
  405. .frametype = AST_FRAME_CONTROL,
  406. .subclass.integer = condition,
  407. .data.ptr = frame_data,
  408. };
  409. /*
  410. * A connected line update frame may only contain a partial
  411. * amount of data, such as just a source, or just a ton, and not
  412. * the full amount of information. However, the collected
  413. * information is all stored in the outgoing channel's
  414. * connectedline structure, so when receiving a connected line
  415. * update on an outgoing unreal channel, we need to transmit the
  416. * collected connected line information instead of whatever
  417. * happens to be in this control frame. The same applies for
  418. * redirecting information, which is why it is handled here as
  419. * well.
  420. */
  421. ast_channel_unlock(ast);
  422. ast_unreal_lock_all(p, &my_chan, &my_owner);
  423. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  424. if (isoutbound) {
  425. this_channel = p->chan;
  426. the_other_channel = p->owner;
  427. } else {
  428. this_channel = p->owner;
  429. the_other_channel = p->chan;
  430. }
  431. if (the_other_channel) {
  432. if (condition == AST_CONTROL_CONNECTED_LINE) {
  433. ast_connected_line_copy_to_caller(ast_channel_caller(the_other_channel),
  434. ast_channel_connected(this_channel));
  435. f.datalen = ast_connected_line_build_data(frame_data, sizeof(frame_data),
  436. ast_channel_connected(this_channel), NULL);
  437. } else {
  438. f.datalen = ast_redirecting_build_data(frame_data, sizeof(frame_data),
  439. ast_channel_redirecting(this_channel), NULL);
  440. }
  441. }
  442. if (my_chan) {
  443. ast_channel_unlock(my_chan);
  444. ast_channel_unref(my_chan);
  445. }
  446. if (my_owner) {
  447. ast_channel_unlock(my_owner);
  448. ast_channel_unref(my_owner);
  449. }
  450. if (the_other_channel) {
  451. res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
  452. }
  453. ao2_unlock(p);
  454. ast_channel_lock(ast);
  455. return res;
  456. }
  457. int ast_unreal_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
  458. {
  459. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  460. int res = 0;
  461. if (!p) {
  462. return -1;
  463. }
  464. ao2_ref(p, 1); /* ref for unreal_queue_frame */
  465. switch (condition) {
  466. case AST_CONTROL_MASQUERADE_NOTIFY:
  467. /*
  468. * Always block this because this is the channel being
  469. * masqueraded; not anything down the chain.
  470. */
  471. break;
  472. case AST_CONTROL_CONNECTED_LINE:
  473. case AST_CONTROL_REDIRECTING:
  474. res = unreal_colp_redirect_indicate(p, ast, condition);
  475. break;
  476. case AST_CONTROL_HOLD:
  477. if (ast_test_flag(p, AST_UNREAL_MOH_INTERCEPT)) {
  478. ast_moh_start(ast, data, NULL);
  479. break;
  480. }
  481. res = unreal_queue_indicate(p, ast, condition, data, datalen);
  482. break;
  483. case AST_CONTROL_UNHOLD:
  484. if (ast_test_flag(p, AST_UNREAL_MOH_INTERCEPT)) {
  485. ast_moh_stop(ast);
  486. break;
  487. }
  488. res = unreal_queue_indicate(p, ast, condition, data, datalen);
  489. break;
  490. default:
  491. res = unreal_queue_indicate(p, ast, condition, data, datalen);
  492. break;
  493. }
  494. ao2_ref(p, -1);
  495. return res;
  496. }
  497. int ast_unreal_digit_begin(struct ast_channel *ast, char digit)
  498. {
  499. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  500. int res = -1;
  501. struct ast_frame f = { AST_FRAME_DTMF_BEGIN, };
  502. int isoutbound;
  503. if (!p) {
  504. return -1;
  505. }
  506. ao2_ref(p, 1); /* ref for unreal_queue_frame */
  507. ao2_lock(p);
  508. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  509. f.subclass.integer = digit;
  510. res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
  511. ao2_unlock(p);
  512. ao2_ref(p, -1);
  513. return res;
  514. }
  515. int ast_unreal_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
  516. {
  517. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  518. int res = -1;
  519. struct ast_frame f = { AST_FRAME_DTMF_END, };
  520. int isoutbound;
  521. if (!p) {
  522. return -1;
  523. }
  524. ao2_ref(p, 1); /* ref for unreal_queue_frame */
  525. ao2_lock(p);
  526. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  527. f.subclass.integer = digit;
  528. f.len = duration;
  529. res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
  530. ao2_unlock(p);
  531. ao2_ref(p, -1);
  532. return res;
  533. }
  534. int ast_unreal_sendtext(struct ast_channel *ast, const char *text)
  535. {
  536. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  537. int res = -1;
  538. struct ast_frame f = { AST_FRAME_TEXT, };
  539. int isoutbound;
  540. if (!p) {
  541. return -1;
  542. }
  543. ao2_ref(p, 1); /* ref for unreal_queue_frame */
  544. ao2_lock(p);
  545. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  546. f.data.ptr = (char *) text;
  547. f.datalen = strlen(text) + 1;
  548. res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
  549. ao2_unlock(p);
  550. ao2_ref(p, -1);
  551. return res;
  552. }
  553. int ast_unreal_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
  554. {
  555. struct ast_unreal_pvt *p = ast_channel_tech_pvt(ast);
  556. int res = -1;
  557. struct ast_frame f = { AST_FRAME_HTML, };
  558. int isoutbound;
  559. if (!p) {
  560. return -1;
  561. }
  562. ao2_ref(p, 1); /* ref for unreal_queue_frame */
  563. ao2_lock(p);
  564. isoutbound = AST_UNREAL_IS_OUTBOUND(ast, p);
  565. f.subclass.integer = subclass;
  566. f.data.ptr = (char *)data;
  567. f.datalen = datalen;
  568. res = unreal_queue_frame(p, isoutbound, &f, ast, 0);
  569. ao2_unlock(p);
  570. ao2_ref(p, -1);
  571. return res;
  572. }
  573. void ast_unreal_call_setup(struct ast_channel *semi1, struct ast_channel *semi2)
  574. {
  575. struct ast_var_t *varptr;
  576. struct ast_var_t *clone_var;
  577. ast_channel_stage_snapshot(semi2);
  578. /*
  579. * Note that cid_num and cid_name aren't passed in the
  580. * ast_channel_alloc calls in ast_unreal_new_channels(). It's
  581. * done here instead.
  582. */
  583. ast_party_redirecting_copy(ast_channel_redirecting(semi2), ast_channel_redirecting(semi1));
  584. ast_party_dialed_copy(ast_channel_dialed(semi2), ast_channel_dialed(semi1));
  585. /* Crossover the CallerID and conected-line to cross the unreal bridge. */
  586. ast_connected_line_copy_to_caller(ast_channel_caller(semi2), ast_channel_connected(semi1));
  587. ast_connected_line_copy_from_caller(ast_channel_connected(semi2), ast_channel_caller(semi1));
  588. ast_channel_language_set(semi2, ast_channel_language(semi1));
  589. /* Crossover the accountcode and peeraccount to cross the unreal bridge. */
  590. ast_channel_accountcode_set(semi2, ast_channel_peeraccount(semi1));
  591. ast_channel_peeraccount_set(semi2, ast_channel_accountcode(semi1));
  592. ast_channel_musicclass_set(semi2, ast_channel_musicclass(semi1));
  593. ast_channel_cc_params_init(semi2, ast_channel_get_cc_config_params(semi1));
  594. /*
  595. * Make sure we inherit the AST_CAUSE_ANSWERED_ELSEWHERE if it's
  596. * set on the queue/dial call request in the dialplan.
  597. */
  598. if (ast_channel_hangupcause(semi1) == AST_CAUSE_ANSWERED_ELSEWHERE) {
  599. ast_channel_hangupcause_set(semi2, AST_CAUSE_ANSWERED_ELSEWHERE);
  600. }
  601. /*
  602. * Copy the channel variables from the semi1 channel to the
  603. * outgoing channel.
  604. *
  605. * Note that due to certain assumptions, they MUST be in the
  606. * same order.
  607. */
  608. AST_LIST_TRAVERSE(ast_channel_varshead(semi1), varptr, entries) {
  609. clone_var = ast_var_assign(varptr->name, varptr->value);
  610. if (clone_var) {
  611. AST_LIST_INSERT_TAIL(ast_channel_varshead(semi2), clone_var, entries);
  612. ast_channel_publish_varset(semi2, ast_var_full_name(clone_var),
  613. ast_var_value(clone_var));
  614. }
  615. }
  616. ast_channel_datastore_inherit(semi1, semi2);
  617. ast_channel_stage_snapshot_done(semi2);
  618. }
  619. int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge *bridge, unsigned int flags)
  620. {
  621. struct ast_bridge_features *features;
  622. struct ast_channel *chan;
  623. struct ast_channel *owner;
  624. RAII_VAR(struct ast_unreal_pvt *, p, NULL, ao2_cleanup);
  625. RAII_VAR(struct ast_callid *, bridge_callid, NULL, ast_callid_cleanup);
  626. ast_bridge_lock(bridge);
  627. bridge_callid = bridge->callid ? ast_callid_ref(bridge->callid) : NULL;
  628. ast_bridge_unlock(bridge);
  629. {
  630. SCOPED_CHANNELLOCK(lock, ast);
  631. p = ast_channel_tech_pvt(ast);
  632. if (!p) {
  633. return -1;
  634. }
  635. ao2_ref(p, +1);
  636. }
  637. {
  638. SCOPED_AO2LOCK(lock, p);
  639. chan = p->chan;
  640. if (!chan) {
  641. return -1;
  642. }
  643. owner = p->owner;
  644. if (!owner) {
  645. return -1;
  646. }
  647. ast_channel_ref(chan);
  648. ast_channel_ref(owner);
  649. }
  650. if (bridge_callid) {
  651. struct ast_callid *chan_callid;
  652. struct ast_callid *owner_callid;
  653. /* chan side call ID setting */
  654. ast_channel_lock(chan);
  655. chan_callid = ast_channel_callid(chan);
  656. if (!chan_callid) {
  657. ast_channel_callid_set(chan, bridge_callid);
  658. }
  659. ast_channel_unlock(chan);
  660. ast_callid_cleanup(chan_callid);
  661. /* owner side call ID setting */
  662. ast_channel_lock(owner);
  663. owner_callid = ast_channel_callid(owner);
  664. if (!owner_callid) {
  665. ast_channel_callid_set(owner, bridge_callid);
  666. }
  667. ast_channel_unlock(owner);
  668. ast_callid_cleanup(owner_callid);
  669. }
  670. /* We are done with the owner now that its call ID matches the bridge */
  671. ast_channel_unref(owner);
  672. owner = NULL;
  673. features = ast_bridge_features_new();
  674. if (!features) {
  675. ast_channel_unref(chan);
  676. return -1;
  677. }
  678. ast_set_flag(&features->feature_flags, flags);
  679. /* Impart the semi2 channel into the bridge */
  680. if (ast_bridge_impart(bridge, chan, NULL, features,
  681. AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
  682. ast_bridge_features_destroy(features);
  683. ast_channel_unref(chan);
  684. return -1;
  685. }
  686. ao2_lock(p);
  687. ast_set_flag(p, AST_UNREAL_CARETAKER_THREAD);
  688. ao2_unlock(p);
  689. ast_channel_unref(chan);
  690. return 0;
  691. }
  692. int ast_unreal_hangup(struct ast_unreal_pvt *p, struct ast_channel *ast)
  693. {
  694. int hangup_chan = 0;
  695. int res = 0;
  696. int cause;
  697. struct ast_channel *owner = NULL;
  698. struct ast_channel *chan = NULL;
  699. /* the pvt isn't going anywhere, it has a ref */
  700. ast_channel_unlock(ast);
  701. /* lock everything */
  702. ast_unreal_lock_all(p, &chan, &owner);
  703. if (ast != chan && ast != owner) {
  704. res = -1;
  705. goto unreal_hangup_cleanup;
  706. }
  707. cause = ast_channel_hangupcause(ast);
  708. if (ast == p->chan) {
  709. /* Outgoing side is hanging up. */
  710. ast_clear_flag(p, AST_UNREAL_CARETAKER_THREAD);
  711. p->chan = NULL;
  712. if (p->owner) {
  713. const char *status = pbx_builtin_getvar_helper(p->chan, "DIALSTATUS");
  714. if (status) {
  715. ast_channel_hangupcause_set(p->owner, cause);
  716. pbx_builtin_setvar_helper(p->owner, "CHANLOCALSTATUS", status);
  717. }
  718. ast_queue_hangup_with_cause(p->owner, cause);
  719. }
  720. } else {
  721. /* Owner side is hanging up. */
  722. p->owner = NULL;
  723. if (p->chan) {
  724. if (cause == AST_CAUSE_ANSWERED_ELSEWHERE) {
  725. ast_channel_hangupcause_set(p->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
  726. ast_debug(2, "%s has AST_CAUSE_ANSWERED_ELSEWHERE set.\n",
  727. ast_channel_name(p->chan));
  728. }
  729. if (!ast_test_flag(p, AST_UNREAL_CARETAKER_THREAD)) {
  730. /*
  731. * Need to actually hangup p->chan since nothing else is taking
  732. * care of it.
  733. */
  734. hangup_chan = 1;
  735. } else {
  736. ast_queue_hangup_with_cause(p->chan, cause);
  737. }
  738. }
  739. }
  740. /* this is one of our locked channels, doesn't matter which */
  741. ast_channel_tech_pvt_set(ast, NULL);
  742. ao2_ref(p, -1);
  743. unreal_hangup_cleanup:
  744. ao2_unlock(p);
  745. if (owner) {
  746. ast_channel_unlock(owner);
  747. ast_channel_unref(owner);
  748. }
  749. if (chan) {
  750. ast_channel_unlock(chan);
  751. if (hangup_chan) {
  752. ast_hangup(chan);
  753. }
  754. ast_channel_unref(chan);
  755. }
  756. /* leave with the channel locked that came in */
  757. ast_channel_lock(ast);
  758. return res;
  759. }
  760. void ast_unreal_destructor(void *vdoomed)
  761. {
  762. struct ast_unreal_pvt *doomed = vdoomed;
  763. ao2_cleanup(doomed->reqcap);
  764. doomed->reqcap = NULL;
  765. }
  766. struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructor, struct ast_format_cap *cap)
  767. {
  768. struct ast_unreal_pvt *unreal;
  769. static const struct ast_jb_conf jb_conf = {
  770. .flags = 0,
  771. .max_size = -1,
  772. .resync_threshold = -1,
  773. .impl = "",
  774. .target_extra = -1,
  775. };
  776. unreal = ao2_alloc(size, destructor);
  777. if (!unreal) {
  778. return NULL;
  779. }
  780. unreal->reqcap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_DEFAULT);
  781. if (!unreal->reqcap) {
  782. ao2_ref(unreal, -1);
  783. return NULL;
  784. }
  785. ast_format_cap_append_from_cap(unreal->reqcap, cap, AST_MEDIA_TYPE_UNKNOWN);
  786. memcpy(&unreal->jb_conf, &jb_conf, sizeof(unreal->jb_conf));
  787. return unreal;
  788. }
  789. struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
  790. const struct ast_channel_tech *tech, int semi1_state, int semi2_state,
  791. const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
  792. const struct ast_channel *requestor, struct ast_callid *callid)
  793. {
  794. struct ast_channel *owner;
  795. struct ast_channel *chan;
  796. RAII_VAR(struct ast_format *, fmt, NULL, ao2_cleanup);
  797. struct ast_assigned_ids id1 = {NULL, NULL};
  798. struct ast_assigned_ids id2 = {NULL, NULL};
  799. int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
  800. /* set unique ids for the two channels */
  801. if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
  802. id1.uniqueid = assignedids->uniqueid;
  803. id2.uniqueid = assignedids->uniqueid2;
  804. }
  805. /* if id1 given but not id2, use default of id1;2 */
  806. if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
  807. char *uniqueid2;
  808. uniqueid2 = ast_alloca(strlen(id1.uniqueid) + 3);
  809. strcpy(uniqueid2, id1.uniqueid);/* Safe */
  810. strcat(uniqueid2, ";2");/* Safe */
  811. id2.uniqueid = uniqueid2;
  812. }
  813. /*
  814. * Allocate two new Asterisk channels
  815. *
  816. * Make sure that the ;2 channel gets the same linkedid as ;1.
  817. * You can't pass linkedid to both allocations since if linkedid
  818. * isn't set, then each channel will generate its own linkedid.
  819. */
  820. owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
  821. exten, context, &id1, requestor, 0,
  822. "%s/%s-%08x;1", tech->type, p->name, (unsigned)generated_seqno);
  823. if (!owner) {
  824. ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
  825. return NULL;
  826. }
  827. if (callid) {
  828. ast_channel_callid_set(owner, callid);
  829. }
  830. ast_channel_tech_set(owner, tech);
  831. ao2_ref(p, +1);
  832. ast_channel_tech_pvt_set(owner, p);
  833. ast_channel_nativeformats_set(owner, p->reqcap);
  834. /* Determine our read/write format and set it on each channel */
  835. fmt = ast_format_cap_get_format(p->reqcap, 0);
  836. if (!fmt) {
  837. ast_channel_tech_pvt_set(owner, NULL);
  838. ao2_ref(p, -1);
  839. ast_channel_unlock(owner);
  840. ast_channel_release(owner);
  841. return NULL;
  842. }
  843. ast_channel_set_writeformat(owner, fmt);
  844. ast_channel_set_rawwriteformat(owner, fmt);
  845. ast_channel_set_readformat(owner, fmt);
  846. ast_channel_set_rawreadformat(owner, fmt);
  847. ast_set_flag(ast_channel_flags(owner), AST_FLAG_DISABLE_DEVSTATE_CACHE);
  848. ast_jb_configure(owner, &p->jb_conf);
  849. if (ast_channel_cc_params_init(owner, requestor
  850. ? ast_channel_get_cc_config_params((struct ast_channel *) requestor) : NULL)) {
  851. ast_channel_tech_pvt_set(owner, NULL);
  852. ao2_ref(p, -1);
  853. ast_channel_tech_pvt_set(owner, NULL);
  854. ast_channel_unlock(owner);
  855. ast_channel_release(owner);
  856. return NULL;
  857. }
  858. p->owner = owner;
  859. ast_channel_unlock(owner);
  860. chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
  861. exten, context, &id2, owner, 0,
  862. "%s/%s-%08x;2", tech->type, p->name, (unsigned)generated_seqno);
  863. if (!chan) {
  864. ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
  865. ast_channel_tech_pvt_set(owner, NULL);
  866. ao2_ref(p, -1);
  867. ast_channel_tech_pvt_set(owner, NULL);
  868. ast_channel_release(owner);
  869. return NULL;
  870. }
  871. if (callid) {
  872. ast_channel_callid_set(chan, callid);
  873. }
  874. ast_channel_tech_set(chan, tech);
  875. ao2_ref(p, +1);
  876. ast_channel_tech_pvt_set(chan, p);
  877. ast_channel_nativeformats_set(chan, p->reqcap);
  878. /* Format was already determined when setting up owner */
  879. ast_channel_set_writeformat(chan, fmt);
  880. ast_channel_set_rawwriteformat(chan, fmt);
  881. ast_channel_set_readformat(chan, fmt);
  882. ast_channel_set_rawreadformat(chan, fmt);
  883. ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_DEVSTATE_CACHE);
  884. p->chan = chan;
  885. ast_channel_unlock(chan);
  886. return owner;
  887. }