#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 = "88eaa8f5c1bd988bedd71113385e0886" , .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 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 282 of file res_rtp_multicast.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 282 of file res_rtp_multicast.c.
static int load_module | ( | void | ) | [static] |
Definition at line 262 of file res_rtp_multicast.c.
References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_engine_register, and multicast_rtp_engine.
00263 { 00264 if (ast_rtp_engine_register(&multicast_rtp_engine)) { 00265 return AST_MODULE_LOAD_DECLINE; 00266 } 00267 00268 return AST_MODULE_LOAD_SUCCESS; 00269 }
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 178 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.
00179 { 00180 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00181 00182 if (multicast->type != MULTICAST_TYPE_LINKSYS) { 00183 return 0; 00184 } 00185 00186 return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD); 00187 }
static int multicast_rtp_destroy | ( | struct ast_rtp_instance * | instance | ) | [static] |
Function called to destroy a multicast instance.
Definition at line 190 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.
00191 { 00192 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00193 00194 if (multicast->type == MULTICAST_TYPE_LINKSYS) { 00195 multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STOPCMD); 00196 } 00197 00198 close(multicast->socket); 00199 00200 ast_free(multicast); 00201 00202 return 0; 00203 }
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 113 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.
00114 { 00115 struct multicast_rtp *multicast; 00116 const char *type = data; 00117 00118 if (!(multicast = ast_calloc(1, sizeof(*multicast)))) { 00119 return -1; 00120 } 00121 00122 if (!strcasecmp(type, "basic")) { 00123 multicast->type = MULTICAST_TYPE_BASIC; 00124 } else if (!strcasecmp(type, "linksys")) { 00125 multicast->type = MULTICAST_TYPE_LINKSYS; 00126 } else { 00127 ast_free(multicast); 00128 return -1; 00129 } 00130 00131 if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { 00132 ast_free(multicast); 00133 return -1; 00134 } 00135 00136 multicast->ssrc = ast_random(); 00137 00138 ast_rtp_instance_set_data(instance, multicast); 00139 00140 return 0; 00141 }
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 257 of file res_rtp_multicast.c.
References ast_null_frame.
00258 { 00259 return &ast_null_frame; 00260 }
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 206 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.
00207 { 00208 struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance); 00209 struct ast_frame *f = frame; 00210 struct ast_sockaddr remote_address; 00211 int hdrlen = 12, res, codec; 00212 unsigned char *rtpheader; 00213 00214 /* We only accept audio, nothing else */ 00215 if (frame->frametype != AST_FRAME_VOICE) { 00216 return 0; 00217 } 00218 00219 /* Grab the actual payload number for when we create the RTP packet */ 00220 if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) { 00221 return -1; 00222 } 00223 00224 /* If we do not have space to construct an RTP header duplicate the frame so we get some */ 00225 if (frame->offset < hdrlen) { 00226 f = ast_frdup(frame); 00227 } 00228 00229 /* Construct an RTP header for our packet */ 00230 rtpheader = (unsigned char *)(f->data.ptr - hdrlen); 00231 put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno))); 00232 put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8)); 00233 put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc)); 00234 00235 /* Increment sequence number and wrap to 0 if it overflows 16 bits. */ 00236 multicast->seqno = 0xFFFF & (multicast->seqno + 1); 00237 00238 /* Finally send it out to the eager phones listening for us */ 00239 ast_rtp_instance_get_remote_address(instance, &remote_address); 00240 res = ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address); 00241 00242 if (res < 0) { 00243 ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n", 00244 ast_sockaddr_stringify(&remote_address), 00245 strerror(errno)); 00246 } 00247 00248 /* If we were forced to duplicate the frame free the new one */ 00249 if (frame != f) { 00250 ast_frfree(f); 00251 } 00252 00253 return res; 00254 }
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 144 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().
00145 { 00146 struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)), 00147 .command = htonl(command), 00148 }; 00149 struct ast_sockaddr control_address, remote_address; 00150 00151 ast_rtp_instance_get_local_address(instance, &control_address); 00152 ast_rtp_instance_get_remote_address(instance, &remote_address); 00153 00154 /* Ensure the user of us have given us both the control address and destination address */ 00155 if (ast_sockaddr_isnull(&control_address) || 00156 ast_sockaddr_isnull(&remote_address)) { 00157 return -1; 00158 } 00159 00160 /* The protocol only supports IPv4. */ 00161 if (ast_sockaddr_is_ipv6(&remote_address)) { 00162 ast_log(LOG_WARNING, "Cannot send control packet for IPv6 " 00163 "remote address.\n"); 00164 return -1; 00165 } 00166 00167 control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address)); 00168 control_packet.port = htonl(ast_sockaddr_port(&remote_address)); 00169 00170 /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */ 00171 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00172 ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address); 00173 00174 return 0; 00175 }
static int unload_module | ( | void | ) | [static] |
Definition at line 271 of file res_rtp_multicast.c.
References ast_rtp_engine_unregister(), and multicast_rtp_engine.
00272 { 00273 ast_rtp_engine_unregister(&multicast_rtp_engine); 00274 00275 return 0; 00276 }
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 = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static] |
Definition at line 282 of file res_rtp_multicast.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 282 of file res_rtp_multicast.c.
struct ast_rtp_engine multicast_rtp_engine [static] |
Definition at line 103 of file res_rtp_multicast.c.
Referenced by load_module(), and unload_module().