chan_bridge.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 1999 - 2008, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@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. * \author Joshua Colp <jcolp@digium.com>
  21. *
  22. * \brief Bridge Interaction Channel
  23. *
  24. * \ingroup channel_drivers
  25. */
  26. /*** MODULEINFO
  27. <support_level>core</support_level>
  28. ***/
  29. #include "asterisk.h"
  30. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  31. #include <fcntl.h>
  32. #include <sys/signal.h>
  33. #include "asterisk/lock.h"
  34. #include "asterisk/channel.h"
  35. #include "asterisk/config.h"
  36. #include "asterisk/module.h"
  37. #include "asterisk/pbx.h"
  38. #include "asterisk/sched.h"
  39. #include "asterisk/io.h"
  40. #include "asterisk/acl.h"
  41. #include "asterisk/callerid.h"
  42. #include "asterisk/file.h"
  43. #include "asterisk/cli.h"
  44. #include "asterisk/app.h"
  45. #include "asterisk/bridging.h"
  46. static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause);
  47. static int bridge_call(struct ast_channel *ast, char *dest, int timeout);
  48. static int bridge_hangup(struct ast_channel *ast);
  49. static struct ast_frame *bridge_read(struct ast_channel *ast);
  50. static int bridge_write(struct ast_channel *ast, struct ast_frame *f);
  51. static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
  52. static const struct ast_channel_tech bridge_tech = {
  53. .type = "Bridge",
  54. .description = "Bridge Interaction Channel",
  55. .capabilities = -1,
  56. .requester = bridge_request,
  57. .call = bridge_call,
  58. .hangup = bridge_hangup,
  59. .read = bridge_read,
  60. .write = bridge_write,
  61. .write_video = bridge_write,
  62. .exception = bridge_read,
  63. .bridged_channel = bridge_bridgedchannel,
  64. };
  65. struct bridge_pvt {
  66. ast_mutex_t lock; /*!< Lock that protects this structure */
  67. struct ast_channel *input; /*!< Input channel - talking to source */
  68. struct ast_channel *output; /*!< Output channel - talking to bridge */
  69. };
  70. /*! \brief Called when the user of this channel wants to get the actual channel in the bridge */
  71. static struct ast_channel *bridge_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
  72. {
  73. struct bridge_pvt *p = chan->tech_pvt;
  74. return (chan == p->input) ? p->output : bridge;
  75. }
  76. /*! \brief Called when a frame should be read from the channel */
  77. static struct ast_frame *bridge_read(struct ast_channel *ast)
  78. {
  79. return &ast_null_frame;
  80. }
  81. /*! \brief Called when a frame should be written out to a channel */
  82. static int bridge_write(struct ast_channel *ast, struct ast_frame *f)
  83. {
  84. struct bridge_pvt *p = ast->tech_pvt;
  85. struct ast_channel *other;
  86. ast_mutex_lock(&p->lock);
  87. other = (p->input == ast ? p->output : p->input);
  88. while (other && ast_channel_trylock(other)) {
  89. ast_mutex_unlock(&p->lock);
  90. do {
  91. CHANNEL_DEADLOCK_AVOIDANCE(ast);
  92. } while (ast_mutex_trylock(&p->lock));
  93. other = (p->input == ast ? p->output : p->input);
  94. }
  95. /* We basically queue the frame up on the other channel if present */
  96. if (other) {
  97. ast_queue_frame(other, f);
  98. ast_channel_unlock(other);
  99. }
  100. ast_mutex_unlock(&p->lock);
  101. return 0;
  102. }
  103. /*! \brief Called when the channel should actually be dialed */
  104. static int bridge_call(struct ast_channel *ast, char *dest, int timeout)
  105. {
  106. struct bridge_pvt *p = ast->tech_pvt;
  107. /* If no bridge has been provided on the input channel, bail out */
  108. if (!ast->bridge) {
  109. return -1;
  110. }
  111. /* Impart the output channel upon the given bridge of the input channel */
  112. ast_bridge_impart(p->input->bridge, p->output, NULL, NULL);
  113. return 0;
  114. }
  115. /*! \brief Helper function to not deadlock when queueing the hangup frame */
  116. static void bridge_queue_hangup(struct bridge_pvt *p, struct ast_channel *us)
  117. {
  118. struct ast_channel *other = (p->input == us ? p->output : p->input);
  119. while (other && ast_channel_trylock(other)) {
  120. ast_mutex_unlock(&p->lock);
  121. do {
  122. CHANNEL_DEADLOCK_AVOIDANCE(us);
  123. } while (ast_mutex_trylock(&p->lock));
  124. other = (p->input == us ? p->output : p->input);
  125. }
  126. /* We basically queue the frame up on the other channel if present */
  127. if (other) {
  128. ast_queue_hangup(other);
  129. ast_channel_unlock(other);
  130. }
  131. return;
  132. }
  133. /*! \brief Called when a channel should be hung up */
  134. static int bridge_hangup(struct ast_channel *ast)
  135. {
  136. struct bridge_pvt *p = ast->tech_pvt;
  137. ast_mutex_lock(&p->lock);
  138. /* Figure out which channel this is... and set it to NULL as it has gone, but also queue up a hangup frame. */
  139. if (p->input == ast) {
  140. if (p->output) {
  141. bridge_queue_hangup(p, ast);
  142. }
  143. p->input = NULL;
  144. } else if (p->output == ast) {
  145. if (p->input) {
  146. bridge_queue_hangup(p, ast);
  147. }
  148. p->output = NULL;
  149. }
  150. /* Deal with the Asterisk portion of it */
  151. ast->tech_pvt = NULL;
  152. /* If both sides have been terminated free the structure and be done with things */
  153. if (!p->input && !p->output) {
  154. ast_mutex_unlock(&p->lock);
  155. ast_mutex_destroy(&p->lock);
  156. ast_free(p);
  157. } else {
  158. ast_mutex_unlock(&p->lock);
  159. }
  160. return 0;
  161. }
  162. /*! \brief Called when we want to place a call somewhere, but not actually call it... yet */
  163. static struct ast_channel *bridge_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
  164. {
  165. struct bridge_pvt *p = NULL;
  166. /* Try to allocate memory for our very minimal pvt structure */
  167. if (!(p = ast_calloc(1, sizeof(*p)))) {
  168. return NULL;
  169. }
  170. /* Try to grab two Asterisk channels to use as input and output channels */
  171. if (!(p->input = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-input", p))) {
  172. ast_free(p);
  173. return NULL;
  174. }
  175. if (!(p->output = ast_channel_alloc(1, AST_STATE_UP, 0, 0, "", "", "", requestor ? requestor->linkedid : NULL, 0, "Bridge/%p-output", p))) {
  176. p->input = ast_channel_release(p->input);
  177. ast_free(p);
  178. return NULL;
  179. }
  180. /* Setup the lock on the pvt structure, we will need that */
  181. ast_mutex_init(&p->lock);
  182. /* Setup parameters on both new channels */
  183. p->input->tech = p->output->tech = &bridge_tech;
  184. p->input->tech_pvt = p->output->tech_pvt = p;
  185. p->input->nativeformats = p->output->nativeformats = AST_FORMAT_SLINEAR;
  186. p->input->readformat = p->output->readformat = AST_FORMAT_SLINEAR;
  187. p->input->rawreadformat = p->output->rawreadformat = AST_FORMAT_SLINEAR;
  188. p->input->writeformat = p->output->writeformat = AST_FORMAT_SLINEAR;
  189. p->input->rawwriteformat = p->output->rawwriteformat = AST_FORMAT_SLINEAR;
  190. return p->input;
  191. }
  192. /*! \brief Load module into PBX, register channel */
  193. static int load_module(void)
  194. {
  195. /* Make sure we can register our channel type */
  196. if (ast_channel_register(&bridge_tech)) {
  197. ast_log(LOG_ERROR, "Unable to register channel class 'Bridge'\n");
  198. return AST_MODULE_LOAD_FAILURE;
  199. }
  200. return AST_MODULE_LOAD_SUCCESS;
  201. }
  202. /*! \brief Unload the bridge interaction channel from Asterisk */
  203. static int unload_module(void)
  204. {
  205. ast_channel_unregister(&bridge_tech);
  206. return 0;
  207. }
  208. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Bridge Interaction Channel",
  209. .load = load_module,
  210. .unload = unload_module,
  211. .load_pri = AST_MODPRI_CHANNEL_DRIVER,
  212. );