#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 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 | 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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 |
Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>
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 54 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 57 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 60 of file res_rtp_multicast.c.
00060 { 00061 /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */ 00062 MULTICAST_TYPE_BASIC = 0, 00063 /*! More advanced Linksys type paging which requires a start and stop packet */ 00064 MULTICAST_TYPE_LINKSYS, 00065 };
static void __reg_module | ( | void | ) | [static] |
Definition at line 275 of file res_rtp_multicast.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 275 of file res_rtp_multicast.c.
static int load_module | ( | void | ) | [static] |
Definition at line 255 of file res_rtp_multicast.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_engine_register, and multicast_rtp_engine.
00256 { 00257 if (ast_rtp_engine_register(&multicast_rtp_engine)) { 00258 return AST_MODULE_LOAD_DECLINE; 00259 } 00260 00261 return AST_MODULE_LOAD_SUCCESS; 00262 }
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 174 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.
00175 { 00176 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00177 00178 if (multicast->type != MULTICAST_TYPE_LINKSYS) { 00179 return 0; 00180 } 00181 00182 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD); 00183 }
static int multicast_rtp_destroy | ( | struct ast_rtp_instance * | instance | ) | [static] |
Function called to destroy a multicast instance.
Definition at line 186 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.
00187 { 00188 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00189 00190 if (multicast->type == MULTICAST_TYPE_LINKSYS) { 00191 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD); 00192 } 00193 00194 close(multicast->socket); 00195 00196 ast_free(multicast); 00197 00198 return 0; 00199 }
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 109 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, and type.
00110 { 00111 struct multicast_rtp *multicast; 00112 const char *type = data; 00113 00114 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) { 00115 return -1; 00116 } 00117 00118 if (!strcasecmp(type, "basic")) { 00119 multicast->type = MULTICAST_TYPE_BASIC; 00120 } else if (!strcasecmp(type, "linksys")) { 00121 multicast->type = MULTICAST_TYPE_LINKSYS; 00122 } else { 00123 ast_free(multicast); 00124 return -1; 00125 } 00126 00127 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00128 ast_free(multicast); 00129 return -1; 00130 } 00131 00132 multicast->ssrc = ast_random(); 00133 00134 ast_rtp_instance_set_data(instance, multicast); 00135 00136 return 0; 00137 }
static struct ast_frame * multicast_rtp_read | ( | struct ast_rtp_instance * | instance, | |
int | rtcp | |||
) | [static] |
Function called to read from a multicast instance.
Definition at line 250 of file res_rtp_multicast.c.
References ast_null_frame.
00251 { 00252 return &ast_null_frame; 00253 }
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 202 of file res_rtp_multicast.c.
References AST_FRAME_VOICE, ast_frdup(), 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_frame_subclass::codec, errno, f, ast_frame::frametype, LOG_ERROR, ast_frame::offset, put_unaligned_uint32(), multicast_rtp::seqno, multicast_rtp::socket, multicast_rtp::ssrc, and ast_frame::subclass.
00203 { 00204 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00205 struct ast_frame *f = frame; 00206 struct ast_sockaddr remote_address; 00207 int hdrlen = 12, res, codec; 00208 unsigned char *rtpheader; 00209 00210 /* We only accept audio, nothing else */ 00211 if (frame->frametype != AST_FRAME_VOICE) { 00212 return 0; 00213 } 00214 00215 /* Grab the actual payload number for when we create the RTP packet */ 00216 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) { 00217 return -1; 00218 } 00219 00220 /* If we do not have space to construct an RTP header duplicate the frame so we get some */ 00221 if (frame->offset < hdrlen) { 00222 f = ast_frdup(frame); 00223 } 00224 00225 /* Construct an RTP header for our packet */ 00226 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 00227 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno++) | (0 << 23))); 00228 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8)); 00229 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc)); 00230 00231 /* Finally send it out to the eager phones listening for us */ 00232 ast_rtp_instance_get_remote_address(instance, &remote_address); 00233 res = ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address); 00234 00235 if (res < 0) { 00236 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n", 00237 ast_sockaddr_stringify(&remote_address), 00238 strerror(errno)); 00239 } 00240 00241 /* If we were forced to duplicate the frame free the new one */ 00242 if (frame != f) { 00243 ast_frfree(f); 00244 } 00245 00246 return res; 00247 }
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 140 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().
00141 { 00142 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)), 00143 .command = htonl(command), 00144 }; 00145 struct ast_sockaddr control_address, remote_address; 00146 00147 ast_rtp_instance_get_local_address(instance, &control_address); 00148 ast_rtp_instance_get_remote_address(instance, &remote_address); 00149 00150 /* Ensure the user of us have given us both the control address and destination address */ 00151 if (ast_sockaddr_isnull(&control_address) || 00152 ast_sockaddr_isnull(&remote_address)) { 00153 return -1; 00154 } 00155 00156 /* The protocol only supports IPv4. */ 00157 if (ast_sockaddr_is_ipv6(&remote_address)) { 00158 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 " 00159 "remote address.\n"); 00160 return -1; 00161 } 00162 00163 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address)); 00164 control_packet.port = htonl(ast_sockaddr_port(&remote_address)); 00165 00166 /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */ 00167 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00168 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00169 00170 return 0; 00171 }
static int unload_module | ( | void | ) | [static] |
Definition at line 264 of file res_rtp_multicast.c.
References ast_rtp_engine_unregister(), and multicast_rtp_engine.
00265 { 00266 ast_rtp_engine_unregister(&multicast_rtp_engine); 00267 00268 return 0; 00269 }
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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 275 of file res_rtp_multicast.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 275 of file res_rtp_multicast.c.
struct ast_rtp_engine multicast_rtp_engine [static] |
Definition at line 99 of file res_rtp_multicast.c.
Referenced by load_module(), and unload_module().