conf_chan_announce.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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 ConfBridge announcer channel driver
  21. *
  22. * \author Richard Mudgett <rmudgett@digium.com>
  23. *
  24. * See Also:
  25. * \arg \ref AstCREDITS
  26. */
  27. #include "asterisk.h"
  28. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  29. #include "asterisk/channel.h"
  30. #include "asterisk/bridge.h"
  31. #include "asterisk/core_unreal.h"
  32. #include "include/confbridge.h"
  33. /* ------------------------------------------------------------------- */
  34. /*! ConfBridge announcer channel private. */
  35. struct announce_pvt {
  36. /*! Unreal channel driver base class values. */
  37. struct ast_unreal_pvt base;
  38. /*! Conference bridge associated with this announcer. */
  39. struct ast_bridge *bridge;
  40. };
  41. static int announce_call(struct ast_channel *chan, const char *addr, int timeout)
  42. {
  43. /* Make sure anyone calling ast_call() for this channel driver is going to fail. */
  44. return -1;
  45. }
  46. static int announce_hangup(struct ast_channel *ast)
  47. {
  48. struct announce_pvt *p = ast_channel_tech_pvt(ast);
  49. int res;
  50. if (!p) {
  51. return -1;
  52. }
  53. /* give the pvt a ref to fulfill calling requirements. */
  54. ao2_ref(p, +1);
  55. res = ast_unreal_hangup(&p->base, ast);
  56. ao2_ref(p, -1);
  57. return res;
  58. }
  59. static void announce_pvt_destructor(void *vdoomed)
  60. {
  61. struct announce_pvt *doomed = vdoomed;
  62. ao2_cleanup(doomed->bridge);
  63. doomed->bridge = NULL;
  64. ast_unreal_destructor(&doomed->base);
  65. }
  66. static struct ast_channel *announce_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
  67. {
  68. struct ast_channel *chan;
  69. const char *conf_name = data;
  70. RAII_VAR(struct confbridge_conference *, conference, NULL, ao2_cleanup);
  71. RAII_VAR(struct announce_pvt *, pvt, NULL, ao2_cleanup);
  72. conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
  73. if (!conference) {
  74. return NULL;
  75. }
  76. ast_assert(conference->bridge != NULL);
  77. /* Allocate a new private structure and then Asterisk channels */
  78. pvt = (struct announce_pvt *) ast_unreal_alloc(sizeof(*pvt), announce_pvt_destructor,
  79. cap);
  80. if (!pvt) {
  81. return NULL;
  82. }
  83. ast_set_flag(&pvt->base, AST_UNREAL_NO_OPTIMIZATION);
  84. ast_copy_string(pvt->base.name, conf_name, sizeof(pvt->base.name));
  85. pvt->bridge = conference->bridge;
  86. ao2_ref(pvt->bridge, +1);
  87. chan = ast_unreal_new_channels(&pvt->base, conf_announce_get_tech(),
  88. AST_STATE_UP, AST_STATE_UP, NULL, NULL, assignedids, requestor, NULL);
  89. if (chan) {
  90. ast_answer(pvt->base.owner);
  91. ast_answer(pvt->base.chan);
  92. if (ast_channel_add_bridge_role(pvt->base.chan, "announcer")) {
  93. ast_hangup(chan);
  94. chan = NULL;
  95. }
  96. }
  97. return chan;
  98. }
  99. static struct ast_channel_tech announce_tech = {
  100. .type = "CBAnn",
  101. .description = "Conference Bridge Announcing Channel",
  102. .requester = announce_request,
  103. .call = announce_call,
  104. .hangup = announce_hangup,
  105. .send_digit_begin = ast_unreal_digit_begin,
  106. .send_digit_end = ast_unreal_digit_end,
  107. .read = ast_unreal_read,
  108. .write = ast_unreal_write,
  109. .write_video = ast_unreal_write,
  110. .exception = ast_unreal_read,
  111. .indicate = ast_unreal_indicate,
  112. .fixup = ast_unreal_fixup,
  113. .send_html = ast_unreal_sendhtml,
  114. .send_text = ast_unreal_sendtext,
  115. .queryoption = ast_unreal_queryoption,
  116. .setoption = ast_unreal_setoption,
  117. .properties = AST_CHAN_TP_INTERNAL,
  118. };
  119. struct ast_channel_tech *conf_announce_get_tech(void)
  120. {
  121. return &announce_tech;
  122. }
  123. int conf_announce_channel_push(struct ast_channel *ast)
  124. {
  125. struct ast_bridge_features *features;
  126. struct ast_channel *chan;
  127. RAII_VAR(struct announce_pvt *, p, NULL, ao2_cleanup);
  128. {
  129. SCOPED_CHANNELLOCK(lock, ast);
  130. p = ast_channel_tech_pvt(ast);
  131. if (!p) {
  132. return -1;
  133. }
  134. ao2_ref(p, +1);
  135. chan = p->base.chan;
  136. if (!chan) {
  137. return -1;
  138. }
  139. }
  140. features = ast_bridge_features_new();
  141. if (!features) {
  142. return -1;
  143. }
  144. ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE);
  145. /* Impart the output channel into the bridge */
  146. if (ast_bridge_impart(p->bridge, chan, NULL, features,
  147. AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) {
  148. return -1;
  149. }
  150. ao2_lock(p);
  151. ast_set_flag(&p->base, AST_UNREAL_CARETAKER_THREAD);
  152. ao2_unlock(p);
  153. return 0;
  154. }