Multicast RTP Engine. More...
#include "asterisk.h"
#include <sys/time.h>
#include <signal.h>
#include <fcntl.h>
#include <math.h>
#include "asterisk/pbx.h"
#include "asterisk/frame.h"
#include "asterisk/channel.h"
#include "asterisk/acl.h"
#include "asterisk/config.h"
#include "asterisk/lock.h"
#include "asterisk/utils.h"
#include "asterisk/cli.h"
#include "asterisk/manager.h"
#include "asterisk/unaligned.h"
#include "asterisk/module.h"
#include "asterisk/rtp_engine.h"
Go to the source code of this file.
Data Structures | |
struct | multicast_control_packet |
Structure for a Linksys control packet. More... | |
struct | multicast_rtp |
Structure for a multicast paging instance. More... | |
Defines | |
#define | LINKSYS_MCAST_STARTCMD 6 |
#define | LINKSYS_MCAST_STOPCMD 7 |
Enumerations | |
enum | multicast_type { MULTICAST_TYPE_BASIC = 0, MULTICAST_TYPE_LINKSYS } |
Type of paging to do. More... | |
Functions | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static unsigned int | calc_txstamp (struct multicast_rtp *rtp, struct timeval *delivery) |
static int | load_module (void) |
static int | multicast_rtp_activate (struct ast_rtp_instance *instance) |
Function called to indicate that audio is now going to flow. | |
static int | multicast_rtp_destroy (struct ast_rtp_instance *instance) |
Function called to destroy a multicast instance. | |
static int | multicast_rtp_new (struct ast_rtp_instance *instance, struct sched_context *sched, struct ast_sockaddr *addr, void *data) |
Function called to create a new multicast instance. | |
static struct ast_frame * | multicast_rtp_read (struct ast_rtp_instance *instance, int rtcp) |
Function called to read from a multicast instance. | |
static int | multicast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame) |
Function called to broadcast some audio on a multicast instance. | |
static int | multicast_send_control_packet (struct ast_rtp_instance *instance, struct multicast_rtp *multicast, int command) |
Helper function which populates a control packet with useful information and sends it. | |
static int | rtp_get_rate (format_t format) |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Multicast RTP Engine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } |
static struct ast_module_info * | ast_module_info = &__mod_info |
static struct ast_rtp_engine | multicast_rtp_engine |
Multicast RTP Engine.
Definition in file res_rtp_multicast.c.
#define LINKSYS_MCAST_STARTCMD 6 |
Command value used for Linksys paging to indicate we are starting
Definition at line 58 of file res_rtp_multicast.c.
Referenced by multicast_rtp_activate().
#define LINKSYS_MCAST_STOPCMD 7 |
Command value used for Linksys paging to indicate we are stopping
Definition at line 61 of file res_rtp_multicast.c.
Referenced by multicast_rtp_destroy().
enum multicast_type |
Type of paging to do.
MULTICAST_TYPE_BASIC |
Simple multicast enabled client/receiver paging like Snom and Barix uses |
MULTICAST_TYPE_LINKSYS |
More advanced Linksys type paging which requires a start and stop packet |
Definition at line 64 of file res_rtp_multicast.c.
00064 { 00065 /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */ 00066 MULTICAST_TYPE_BASIC = 0, 00067 /*! More advanced Linksys type paging which requires a start and stop packet */ 00068 MULTICAST_TYPE_LINKSYS, 00069 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 320 of file res_rtp_multicast.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 320 of file res_rtp_multicast.c.
static unsigned int calc_txstamp | ( | struct multicast_rtp * | rtp, | |
struct timeval * | delivery | |||
) | [static] |
Definition at line 150 of file res_rtp_multicast.c.
References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and multicast_rtp::txcore.
Referenced by multicast_rtp_write().
00151 { 00152 struct timeval t; 00153 long ms; 00154 00155 if (ast_tvzero(rtp->txcore)) { 00156 rtp->txcore = ast_tvnow(); 00157 rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000; 00158 } 00159 00160 t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow(); 00161 if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) { 00162 ms = 0; 00163 } 00164 rtp->txcore = t; 00165 00166 return (unsigned int) ms; 00167 }
static int load_module | ( | void | ) | [static] |
Definition at line 300 of file res_rtp_multicast.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and ast_rtp_engine_register.
00301 { 00302 if (ast_rtp_engine_register(&multicast_rtp_engine)) { 00303 return AST_MODULE_LOAD_DECLINE; 00304 } 00305 00306 return AST_MODULE_LOAD_SUCCESS; 00307 }
static int multicast_rtp_activate | ( | struct ast_rtp_instance * | instance | ) | [static] |
Function called to indicate that audio is now going to flow.
Definition at line 204 of file res_rtp_multicast.c.
References ast_rtp_instance_get_data(), LINKSYS_MCAST_STARTCMD, multicast_send_control_packet(), MULTICAST_TYPE_LINKSYS, and multicast_rtp::type.
00205 { 00206 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00207 00208 if (multicast->type != MULTICAST_TYPE_LINKSYS) { 00209 return 0; 00210 } 00211 00212 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD); 00213 }
static int multicast_rtp_destroy | ( | struct ast_rtp_instance * | instance | ) | [static] |
Function called to destroy a multicast instance.
Definition at line 216 of file res_rtp_multicast.c.
References ast_free, ast_rtp_instance_get_data(), LINKSYS_MCAST_STOPCMD, multicast_send_control_packet(), MULTICAST_TYPE_LINKSYS, multicast_rtp::socket, and multicast_rtp::type.
00217 { 00218 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00219 00220 if (multicast->type == MULTICAST_TYPE_LINKSYS) { 00221 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD); 00222 } 00223 00224 close(multicast->socket); 00225 00226 ast_free(multicast); 00227 00228 return 0; 00229 }
static int multicast_rtp_new | ( | struct ast_rtp_instance * | instance, | |
struct sched_context * | sched, | |||
struct ast_sockaddr * | addr, | |||
void * | data | |||
) | [static] |
Function called to create a new multicast instance.
Definition at line 115 of file res_rtp_multicast.c.
References ast_calloc, ast_free, ast_random(), ast_rtp_instance_set_data(), MULTICAST_TYPE_BASIC, MULTICAST_TYPE_LINKSYS, multicast_rtp::socket, multicast_rtp::ssrc, multicast_rtp::type, and type.
00116 { 00117 struct multicast_rtp *multicast; 00118 const char *type = data; 00119 00120 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) { 00121 return -1; 00122 } 00123 00124 if (!strcasecmp(type, "basic")) { 00125 multicast->type = MULTICAST_TYPE_BASIC; 00126 } else if (!strcasecmp(type, "linksys")) { 00127 multicast->type = MULTICAST_TYPE_LINKSYS; 00128 } else { 00129 ast_free(multicast); 00130 return -1; 00131 } 00132 00133 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00134 ast_free(multicast); 00135 return -1; 00136 } 00137 00138 multicast->ssrc = ast_random(); 00139 00140 ast_rtp_instance_set_data(instance, multicast); 00141 00142 return 0; 00143 }
static struct ast_frame * multicast_rtp_read | ( | struct ast_rtp_instance * | instance, | |
int | rtcp | |||
) | [static, read] |
Function called to read from a multicast instance.
Definition at line 295 of file res_rtp_multicast.c.
References ast_null_frame.
00296 { 00297 return &ast_null_frame; 00298 }
static int multicast_rtp_write | ( | struct ast_rtp_instance * | instance, | |
struct ast_frame * | frame | |||
) | [static] |
Function called to broadcast some audio on a multicast instance.
Definition at line 232 of file res_rtp_multicast.c.
References AST_FRAME_VOICE, ast_frdup(), AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_log(), ast_rtp_codecs_payload_code(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address(), ast_sendto(), ast_sockaddr_stringify(), ast_test_flag, calc_txstamp(), ast_frame_subclass::codec, ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, f, ast_frame::frametype, multicast_rtp::lastts, LOG_ERROR, ast_frame::offset, ast_frame::ptr, put_unaligned_uint32(), rtp_get_rate(), multicast_rtp::seqno, multicast_rtp::socket, multicast_rtp::ssrc, ast_frame::subclass, and ast_frame::ts.
00233 { 00234 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00235 struct ast_frame *f = frame; 00236 struct ast_sockaddr remote_address; 00237 int hdrlen = 12, res = 0, codec; 00238 int rate; 00239 unsigned char *rtpheader; 00240 unsigned int ms = calc_txstamp(multicast, &frame->delivery); 00241 00242 /* We only accept audio, nothing else */ 00243 if (frame->frametype != AST_FRAME_VOICE) { 00244 return 0; 00245 } 00246 rate = rtp_get_rate(frame->subclass.codec) / 1000; 00247 00248 /* Grab the actual payload number for when we create the RTP packet */ 00249 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) { 00250 return -1; 00251 } 00252 00253 /* If we do not have space to construct an RTP header duplicate the frame so we get some */ 00254 if (frame->offset < hdrlen) { 00255 f = ast_frdup(frame); 00256 } 00257 00258 /* Calucate last TS */ 00259 multicast->lastts = multicast->lastts + ms * rate; 00260 00261 /* Construct an RTP header for our packet */ 00262 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 00263 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno))); 00264 00265 if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) { 00266 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8)); 00267 } else { 00268 put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts)); 00269 } 00270 00271 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc)); 00272 00273 /* Increment sequence number and wrap to 0 if it overflows 16 bits. */ 00274 multicast->seqno = 0xFFFF & (multicast->seqno + 1); 00275 00276 /* Finally send it out to the eager phones listening for us */ 00277 ast_rtp_instance_get_remote_address(instance, &remote_address); 00278 00279 if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) { 00280 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n", 00281 ast_sockaddr_stringify(&remote_address), 00282 strerror(errno)); 00283 res = -1; 00284 } 00285 00286 /* If we were forced to duplicate the frame free the new one */ 00287 if (frame != f) { 00288 ast_frfree(f); 00289 } 00290 00291 return res; 00292 }
static int multicast_send_control_packet | ( | struct ast_rtp_instance * | instance, | |
struct multicast_rtp * | multicast, | |||
int | command | |||
) | [static] |
Helper function which populates a control packet with useful information and sends it.
Definition at line 170 of file res_rtp_multicast.c.
References ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_sendto(), ast_sockaddr_ipv4(), ast_sockaddr_is_ipv6(), ast_sockaddr_isnull(), ast_sockaddr_port, multicast_control_packet::ip, LOG_WARNING, multicast_control_packet::port, multicast_rtp::socket, and multicast_control_packet::unique_id.
Referenced by multicast_rtp_activate(), and multicast_rtp_destroy().
00171 { 00172 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)), 00173 .command = htonl(command), 00174 }; 00175 struct ast_sockaddr control_address, remote_address; 00176 00177 ast_rtp_instance_get_local_address(instance, &control_address); 00178 ast_rtp_instance_get_remote_address(instance, &remote_address); 00179 00180 /* Ensure the user of us have given us both the control address and destination address */ 00181 if (ast_sockaddr_isnull(&control_address) || 00182 ast_sockaddr_isnull(&remote_address)) { 00183 return -1; 00184 } 00185 00186 /* The protocol only supports IPv4. */ 00187 if (ast_sockaddr_is_ipv6(&remote_address)) { 00188 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 " 00189 "remote address.\n"); 00190 return -1; 00191 } 00192 00193 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address)); 00194 control_packet.port = htonl(ast_sockaddr_port(&remote_address)); 00195 00196 /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */ 00197 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00198 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00199 00200 return 0; 00201 }
static int rtp_get_rate | ( | format_t | format | ) | [static] |
Definition at line 145 of file res_rtp_multicast.c.
References AST_FORMAT_G722, and ast_format_rate().
Referenced by multicast_rtp_write().
00146 { 00147 return (format == AST_FORMAT_G722) ? 8000 : ast_format_rate(format); 00148 }
static int unload_module | ( | void | ) | [static] |
Definition at line 309 of file res_rtp_multicast.c.
References ast_rtp_engine_unregister().
00310 { 00311 ast_rtp_engine_unregister(&multicast_rtp_engine); 00312 00313 return 0; 00314 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Multicast RTP Engine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 320 of file res_rtp_multicast.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 320 of file res_rtp_multicast.c.
struct ast_rtp_engine multicast_rtp_engine [static] |
Definition at line 105 of file res_rtp_multicast.c.