res_rtp_multicast.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * Asterisk -- An open source telephony toolkit.
  3. *
  4. * Copyright (C) 2009, Digium, Inc.
  5. *
  6. * Joshua Colp <jcolp@digium.com>
  7. * Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
  8. *
  9. * See http://www.asterisk.org for more information about
  10. * the Asterisk project. Please do not directly contact
  11. * any of the maintainers of this project for assistance;
  12. * the project provides a web site, mailing lists and IRC
  13. * channels for your use.
  14. *
  15. * This program is free software, distributed under the terms of
  16. * the GNU General Public License Version 2. See the LICENSE file
  17. * at the top of the source tree.
  18. */
  19. /*!
  20. * \file
  21. *
  22. * \brief Multicast RTP Engine
  23. *
  24. * \author Joshua Colp <jcolp@digium.com>
  25. * \author Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
  26. *
  27. * \ingroup rtp_engines
  28. */
  29. /*** MODULEINFO
  30. <support_level>core</support_level>
  31. ***/
  32. #include "asterisk.h"
  33. ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
  34. #include <sys/time.h>
  35. #include <signal.h>
  36. #include <fcntl.h>
  37. #include <math.h>
  38. #include "asterisk/pbx.h"
  39. #include "asterisk/frame.h"
  40. #include "asterisk/channel.h"
  41. #include "asterisk/acl.h"
  42. #include "asterisk/config.h"
  43. #include "asterisk/lock.h"
  44. #include "asterisk/utils.h"
  45. #include "asterisk/cli.h"
  46. #include "asterisk/manager.h"
  47. #include "asterisk/unaligned.h"
  48. #include "asterisk/module.h"
  49. #include "asterisk/rtp_engine.h"
  50. #include "asterisk/format_cache.h"
  51. /*! Command value used for Linksys paging to indicate we are starting */
  52. #define LINKSYS_MCAST_STARTCMD 6
  53. /*! Command value used for Linksys paging to indicate we are stopping */
  54. #define LINKSYS_MCAST_STOPCMD 7
  55. /*! \brief Type of paging to do */
  56. enum multicast_type {
  57. /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */
  58. MULTICAST_TYPE_BASIC = 0,
  59. /*! More advanced Linksys type paging which requires a start and stop packet */
  60. MULTICAST_TYPE_LINKSYS,
  61. };
  62. /*! \brief Structure for a Linksys control packet */
  63. struct multicast_control_packet {
  64. /*! Unique identifier for the control packet */
  65. uint32_t unique_id;
  66. /*! Actual command in the control packet */
  67. uint32_t command;
  68. /*! IP address for the RTP */
  69. uint32_t ip;
  70. /*! Port for the RTP */
  71. uint32_t port;
  72. };
  73. /*! \brief Structure for a multicast paging instance */
  74. struct multicast_rtp {
  75. /*! TYpe of multicast paging this instance is doing */
  76. enum multicast_type type;
  77. /*! Socket used for sending the audio on */
  78. int socket;
  79. /*! Synchronization source value, used when creating/sending the RTP packet */
  80. unsigned int ssrc;
  81. /*! Sequence number, used when creating/sending the RTP packet */
  82. uint16_t seqno;
  83. unsigned int lastts;
  84. struct timeval txcore;
  85. };
  86. /* Forward Declarations */
  87. static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data);
  88. static int multicast_rtp_activate(struct ast_rtp_instance *instance);
  89. static int multicast_rtp_destroy(struct ast_rtp_instance *instance);
  90. static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame);
  91. static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp);
  92. /* RTP Engine Declaration */
  93. static struct ast_rtp_engine multicast_rtp_engine = {
  94. .name = "multicast",
  95. .new = multicast_rtp_new,
  96. .activate = multicast_rtp_activate,
  97. .destroy = multicast_rtp_destroy,
  98. .write = multicast_rtp_write,
  99. .read = multicast_rtp_read,
  100. };
  101. /*! \brief Function called to create a new multicast instance */
  102. static int multicast_rtp_new(struct ast_rtp_instance *instance, struct ast_sched_context *sched, struct ast_sockaddr *addr, void *data)
  103. {
  104. struct multicast_rtp *multicast;
  105. const char *type = data;
  106. if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
  107. return -1;
  108. }
  109. if (!strcasecmp(type, "basic")) {
  110. multicast->type = MULTICAST_TYPE_BASIC;
  111. } else if (!strcasecmp(type, "linksys")) {
  112. multicast->type = MULTICAST_TYPE_LINKSYS;
  113. } else {
  114. ast_free(multicast);
  115. return -1;
  116. }
  117. if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
  118. ast_free(multicast);
  119. return -1;
  120. }
  121. multicast->ssrc = ast_random();
  122. ast_rtp_instance_set_data(instance, multicast);
  123. return 0;
  124. }
  125. static int rtp_get_rate(struct ast_format *format)
  126. {
  127. return ast_format_cmp(format, ast_format_g722) == AST_FORMAT_CMP_EQUAL ?
  128. 8000 : ast_format_get_sample_rate(format);
  129. }
  130. static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
  131. {
  132. struct timeval t;
  133. long ms;
  134. if (ast_tvzero(rtp->txcore)) {
  135. rtp->txcore = ast_tvnow();
  136. rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
  137. }
  138. t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
  139. if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
  140. ms = 0;
  141. }
  142. rtp->txcore = t;
  143. return (unsigned int) ms;
  144. }
  145. /*! \brief Helper function which populates a control packet with useful information and sends it */
  146. static int multicast_send_control_packet(struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command)
  147. {
  148. struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
  149. .command = htonl(command),
  150. };
  151. struct ast_sockaddr control_address, remote_address;
  152. ast_rtp_instance_get_local_address(instance, &control_address);
  153. ast_rtp_instance_get_remote_address(instance, &remote_address);
  154. /* Ensure the user of us have given us both the control address and destination address */
  155. if (ast_sockaddr_isnull(&control_address) ||
  156. ast_sockaddr_isnull(&remote_address)) {
  157. return -1;
  158. }
  159. /* The protocol only supports IPv4. */
  160. if (ast_sockaddr_is_ipv6(&remote_address)) {
  161. ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
  162. "remote address.\n");
  163. return -1;
  164. }
  165. control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
  166. control_packet.port = htonl(ast_sockaddr_port(&remote_address));
  167. /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
  168. ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
  169. ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
  170. return 0;
  171. }
  172. /*! \brief Function called to indicate that audio is now going to flow */
  173. static int multicast_rtp_activate(struct ast_rtp_instance *instance)
  174. {
  175. struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
  176. if (multicast->type != MULTICAST_TYPE_LINKSYS) {
  177. return 0;
  178. }
  179. return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
  180. }
  181. /*! \brief Function called to destroy a multicast instance */
  182. static int multicast_rtp_destroy(struct ast_rtp_instance *instance)
  183. {
  184. struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
  185. if (multicast->type == MULTICAST_TYPE_LINKSYS) {
  186. multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
  187. }
  188. close(multicast->socket);
  189. ast_free(multicast);
  190. return 0;
  191. }
  192. /*! \brief Function called to broadcast some audio on a multicast instance */
  193. static int multicast_rtp_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
  194. {
  195. struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
  196. struct ast_frame *f = frame;
  197. struct ast_sockaddr remote_address;
  198. int hdrlen = 12, res = 0, codec;
  199. unsigned char *rtpheader;
  200. unsigned int ms = calc_txstamp(multicast, &frame->delivery);
  201. int rate = rtp_get_rate(frame->subclass.format) / 1000;
  202. /* We only accept audio, nothing else */
  203. if (frame->frametype != AST_FRAME_VOICE) {
  204. return 0;
  205. }
  206. /* Grab the actual payload number for when we create the RTP packet */
  207. if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.format, 0)) < 0) {
  208. return -1;
  209. }
  210. /* If we do not have space to construct an RTP header duplicate the frame so we get some */
  211. if (frame->offset < hdrlen) {
  212. f = ast_frdup(frame);
  213. }
  214. /* Calucate last TS */
  215. multicast->lastts = multicast->lastts + ms * rate;
  216. /* Construct an RTP header for our packet */
  217. rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
  218. put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
  219. if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
  220. put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
  221. } else {
  222. put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
  223. }
  224. put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
  225. /* Increment sequence number and wrap to 0 if it overflows 16 bits. */
  226. multicast->seqno = 0xFFFF & (multicast->seqno + 1);
  227. /* Finally send it out to the eager phones listening for us */
  228. ast_rtp_instance_get_remote_address(instance, &remote_address);
  229. if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
  230. ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
  231. ast_sockaddr_stringify(&remote_address),
  232. strerror(errno));
  233. res = -1;
  234. }
  235. /* If we were forced to duplicate the frame free the new one */
  236. if (frame != f) {
  237. ast_frfree(f);
  238. }
  239. return res;
  240. }
  241. /*! \brief Function called to read from a multicast instance */
  242. static struct ast_frame *multicast_rtp_read(struct ast_rtp_instance *instance, int rtcp)
  243. {
  244. return &ast_null_frame;
  245. }
  246. static int load_module(void)
  247. {
  248. if (ast_rtp_engine_register(&multicast_rtp_engine)) {
  249. return AST_MODULE_LOAD_DECLINE;
  250. }
  251. return AST_MODULE_LOAD_SUCCESS;
  252. }
  253. static int unload_module(void)
  254. {
  255. ast_rtp_engine_unregister(&multicast_rtp_engine);
  256. return 0;
  257. }
  258. AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Multicast RTP Engine",
  259. .support_level = AST_MODULE_SUPPORT_CORE,
  260. .load = load_module,
  261. .unload = unload_module,
  262. .load_pri = AST_MODPRI_CHANNEL_DEPEND,
  263. );