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 ast_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 (struct ast_format *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 = AST_BUILDOPT_SUM, .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.
{
/*! Simple multicast enabled client/receiver paging like Snom and Barix uses */
MULTICAST_TYPE_BASIC = 0,
/*! More advanced Linksys type paging which requires a start and stop packet */
MULTICAST_TYPE_LINKSYS,
};
| static void __reg_module | ( | void | ) | [static] |
Definition at line 319 of file res_rtp_multicast.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 319 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().
{
struct timeval t;
long ms;
if (ast_tvzero(rtp->txcore)) {
rtp->txcore = ast_tvnow();
rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
}
t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
ms = 0;
}
rtp->txcore = t;
return (unsigned int) ms;
}
| static int load_module | ( | void | ) | [static] |
Definition at line 299 of file res_rtp_multicast.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and ast_rtp_engine_register.
{
if (ast_rtp_engine_register(&multicast_rtp_engine)) {
return AST_MODULE_LOAD_DECLINE;
}
return AST_MODULE_LOAD_SUCCESS;
}
| 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.
{
struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
if (multicast->type != MULTICAST_TYPE_LINKSYS) {
return 0;
}
return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
}
| 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.
{
struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
if (multicast->type == MULTICAST_TYPE_LINKSYS) {
multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD);
}
close(multicast->socket);
ast_free(multicast);
return 0;
}
| static int multicast_rtp_new | ( | struct ast_rtp_instance * | instance, |
| struct ast_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, type, and multicast_rtp::type.
{
struct multicast_rtp *multicast;
const char *type = data;
if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
return -1;
}
if (!strcasecmp(type, "basic")) {
multicast->type = MULTICAST_TYPE_BASIC;
} else if (!strcasecmp(type, "linksys")) {
multicast->type = MULTICAST_TYPE_LINKSYS;
} else {
ast_free(multicast);
return -1;
}
if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
ast_free(multicast);
return -1;
}
multicast->ssrc = ast_random();
ast_rtp_instance_set_data(instance, multicast);
return 0;
}
| 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 294 of file res_rtp_multicast.c.
References ast_null_frame.
{
return &ast_null_frame;
}
| 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::data, ast_frame::datalen, ast_frame::delivery, errno, f, ast_frame_subclass::format, 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.
{
struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
struct ast_frame *f = frame;
struct ast_sockaddr remote_address;
int hdrlen = 12, res = 0, codec;
unsigned char *rtpheader;
unsigned int ms = calc_txstamp(multicast, &frame->delivery);
int rate = rtp_get_rate(&frame->subclass.format) / 1000;
/* We only accept audio, nothing else */
if (frame->frametype != AST_FRAME_VOICE) {
return 0;
}
/* Grab the actual payload number for when we create the RTP packet */
if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, &frame->subclass.format, 0)) < 0) {
return -1;
}
/* If we do not have space to construct an RTP header duplicate the frame so we get some */
if (frame->offset < hdrlen) {
f = ast_frdup(frame);
}
/* Calucate last TS */
multicast->lastts = multicast->lastts + ms * rate;
/* Construct an RTP header for our packet */
rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
if (ast_test_flag(f, AST_FRFLAG_HAS_TIMING_INFO)) {
put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
} else {
put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
}
put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
/* Increment sequence number and wrap to 0 if it overflows 16 bits. */
multicast->seqno = 0xFFFF & (multicast->seqno + 1);
/* Finally send it out to the eager phones listening for us */
ast_rtp_instance_get_remote_address(instance, &remote_address);
if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
ast_sockaddr_stringify(&remote_address),
strerror(errno));
res = -1;
}
/* If we were forced to duplicate the frame free the new one */
if (frame != f) {
ast_frfree(f);
}
return res;
}
| 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().
{
struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
.command = htonl(command),
};
struct ast_sockaddr control_address, remote_address;
ast_rtp_instance_get_local_address(instance, &control_address);
ast_rtp_instance_get_remote_address(instance, &remote_address);
/* Ensure the user of us have given us both the control address and destination address */
if (ast_sockaddr_isnull(&control_address) ||
ast_sockaddr_isnull(&remote_address)) {
return -1;
}
/* The protocol only supports IPv4. */
if (ast_sockaddr_is_ipv6(&remote_address)) {
ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
"remote address.\n");
return -1;
}
control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
control_packet.port = htonl(ast_sockaddr_port(&remote_address));
/* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
return 0;
}
| static int rtp_get_rate | ( | struct ast_format * | format | ) | [static] |
Definition at line 145 of file res_rtp_multicast.c.
References AST_FORMAT_G722, ast_format_rate(), and ast_format::id.
Referenced by multicast_rtp_write().
{
return (format->id == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
}
| static int unload_module | ( | void | ) | [static] |
Definition at line 308 of file res_rtp_multicast.c.
References ast_rtp_engine_unregister().
{
ast_rtp_engine_unregister(&multicast_rtp_engine);
return 0;
}
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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 319 of file res_rtp_multicast.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 319 of file res_rtp_multicast.c.
struct ast_rtp_engine multicast_rtp_engine [static] |
Definition at line 105 of file res_rtp_multicast.c.