Wed Jan 27 20:02:48 2016

Asterisk developer's documentation


res_rtp_multicast.c File Reference

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_framemulticast_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_infoast_module_info = &__mod_info
static struct ast_rtp_engine multicast_rtp_engine

Detailed Description

Multicast RTP Engine.

Author:
Joshua Colp <jcolp@digium.com>
Andreas 'MacBrody' Brodmann <andreas.brodmann@gmail.com>

Definition in file res_rtp_multicast.c.


Define Documentation

#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().


Enumeration Type Documentation

Type of paging to do.

Enumerator:
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 };


Function Documentation

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 }


Variable Documentation

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.

Definition at line 320 of file res_rtp_multicast.c.

Definition at line 105 of file res_rtp_multicast.c.


Generated on 27 Jan 2016 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1