Mon Mar 12 2012 21:45:00

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"
Include dependency graph for res_rtp_multicast.c:

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_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 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_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.

                    {
   /*! 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,
};

Function Documentation

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]
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.

{
   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 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.

{
   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 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, 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 257 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 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, ast_frame::data, ast_frame::datalen, errno, f, ast_frame::frametype, LOG_ERROR, ast_frame::offset, ast_frame::ptr, put_unaligned_uint32(), 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, codec;
   unsigned char *rtpheader;

   /* 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.codec)) < 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);
   }

   /* 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)));
   put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
   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);
   res = ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address);

   if (res < 0) {
      ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
         ast_sockaddr_stringify(&remote_address),
         strerror(errno));
   }

   /* 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 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().

{
   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 unload_module ( void  ) [static]

Definition at line 271 of file res_rtp_multicast.c.

References ast_rtp_engine_unregister().


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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, } [static]

Definition at line 282 of file res_rtp_multicast.c.

Definition at line 282 of file res_rtp_multicast.c.

Definition at line 103 of file res_rtp_multicast.c.