Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Enumerations | Functions | Variables
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 "asterisk/format_cache.h"
#include "asterisk/multicast_rtp.h"
#include "asterisk/app.h"
#include "asterisk/smoother.h"
Include dependency graph for res_rtp_multicast.c:

Go to the source code of this file.

Data Structures

struct  ast_multicast_rtp_options
 
struct  multicast_control_packet
 Structure for a Linksys control packet. More...
 
struct  multicast_rtp
 Structure for a multicast paging instance. More...
 

Macros

#define LINKSYS_MCAST_STARTCMD   6
 
#define LINKSYS_MCAST_STOPCMD   7
 
#define MAX_TIMESTAMP_SKEW   640
 

Enumerations

enum  { OPT_CODEC = (1 << 0), OPT_LOOP = (1 << 1), OPT_TTL = (1 << 2), OPT_IF = (1 << 3) }
 
enum  {
  OPT_ARG_CODEC = 0, OPT_ARG_LOOP, OPT_ARG_TTL, OPT_ARG_IF,
  OPT_ARG_ARRAY_SIZE
}
 
enum  multicast_type { MULTICAST_TYPE_UNSPECIFIED = 0, MULTICAST_TYPE_BASIC, MULTICAST_TYPE_LINKSYS }
 Type of paging to do. More...
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
struct ast_multicast_rtp_optionsast_multicast_rtp_create_options (const char *type, const char *options)
 Create multicast RTP options. More...
 
void ast_multicast_rtp_free_options (struct ast_multicast_rtp_options *mcast_options)
 Free multicast RTP options. More...
 
struct ast_formatast_multicast_rtp_options_get_format (struct ast_multicast_rtp_options *mcast_options)
 Get format specified in multicast options. More...
 
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. More...
 
static int multicast_rtp_destroy (struct ast_rtp_instance *instance)
 Function called to destroy a multicast instance. More...
 
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. More...
 
static struct ast_framemulticast_rtp_read (struct ast_rtp_instance *instance, int rtcp)
 Function called to read from a multicast instance. More...
 
static int multicast_rtp_write (struct ast_rtp_instance *instance, struct ast_frame *frame)
 Function called to broadcast some audio on a multicast instance. More...
 
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. More...
 
static int rtp_get_rate (struct ast_format *format)
 
static int rtp_raw_write (struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
 
static void set_if (int sock, const char *if_str)
 
static void set_loop (int sock, const char *loop_str)
 
static void set_ttl (int sock, const char *ttl_str)
 
static int set_type (struct multicast_rtp *multicast, const char *type)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | 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, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static struct ast_rtp_engine multicast_rtp_engine
 
static const struct ast_app_option multicast_rtp_options [128] = { [ 'c' ] = { .flag = OPT_CODEC , .arg_index = OPT_ARG_CODEC + 1 }, [ 'l' ] = { .flag = OPT_LOOP , .arg_index = OPT_ARG_LOOP + 1 }, [ 't' ] = { .flag = OPT_TTL , .arg_index = OPT_ARG_TTL + 1 }, [ 'i' ] = { .flag = OPT_IF , .arg_index = OPT_ARG_IF + 1 }, }
 

Detailed Description

Multicast RTP Engine.

Author
Joshua Colp jcolp[email protected]@dig[email protected]ium.c[email protected]om
Andreas 'MacBrody' Brodmann andre[email protected]as.b[email protected]rodma[email protected][email protected][email protected]mail.[email protected]com

Definition in file res_rtp_multicast.c.

Macro Definition Documentation

◆ LINKSYS_MCAST_STARTCMD

#define LINKSYS_MCAST_STARTCMD   6

Command value used for Linksys paging to indicate we are starting

Definition at line 60 of file res_rtp_multicast.c.

Referenced by multicast_rtp_activate().

◆ LINKSYS_MCAST_STOPCMD

#define LINKSYS_MCAST_STOPCMD   7

Command value used for Linksys paging to indicate we are stopping

Definition at line 63 of file res_rtp_multicast.c.

Referenced by multicast_rtp_destroy().

◆ MAX_TIMESTAMP_SKEW

#define MAX_TIMESTAMP_SKEW   640

Definition at line 102 of file res_rtp_multicast.c.

Referenced by rtp_raw_write().

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPT_CODEC 
OPT_LOOP 
OPT_TTL 
OPT_IF 

Definition at line 104 of file res_rtp_multicast.c.

104  {
105  OPT_CODEC = (1 << 0),
106  OPT_LOOP = (1 << 1),
107  OPT_TTL = (1 << 2),
108  OPT_IF = (1 << 3),
109 };

◆ anonymous enum

anonymous enum
Enumerator
OPT_ARG_CODEC 
OPT_ARG_LOOP 
OPT_ARG_TTL 
OPT_ARG_IF 
OPT_ARG_ARRAY_SIZE 

Definition at line 111 of file res_rtp_multicast.c.

◆ multicast_type

Type of paging to do.

Enumerator
MULTICAST_TYPE_UNSPECIFIED 

Type has not been set yet

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 66 of file res_rtp_multicast.c.

66  {
67  /*! Type has not been set yet */
69  /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */
71  /*! More advanced Linksys type paging which requires a start and stop packet */
73 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 567 of file res_rtp_multicast.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 567 of file res_rtp_multicast.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 567 of file res_rtp_multicast.c.

◆ ast_multicast_rtp_create_options()

struct ast_multicast_rtp_options* ast_multicast_rtp_create_options ( const char *  type,
const char *  options 
)

Create multicast RTP options.

These are passed to the multicast RTP engine on its creation.

Parameters
typeThe type of multicast RTP, either "basic" or "linksys"
optionsMiscellaneous options
Return values
NULLFailure
non-NULLsuccess

Definition at line 140 of file res_rtp_multicast.c.

References ast_app_parse_options(), ast_calloc, ast_log, ast_multicast_rtp_free_options(), ast_strlen_zero, ast_multicast_rtp_options::buf, LOG_WARNING, multicast_rtp_options, NULL, ast_multicast_rtp_options::opt_args, ast_multicast_rtp_options::options, ast_multicast_rtp_options::opts, S_OR, and ast_multicast_rtp_options::type.

Referenced by multicast_rtp_request().

142 {
143  struct ast_multicast_rtp_options *mcast_options;
144  char *pos;
145 
146  mcast_options = ast_calloc(1, sizeof(*mcast_options)
147  + strlen(type)
148  + strlen(S_OR(options, "")) + 2);
149  if (!mcast_options) {
150  return NULL;
151  }
152 
153  pos = mcast_options->buf;
154 
155  /* Safe */
156  strcpy(pos, type);
157  mcast_options->type = pos;
158  pos += strlen(type) + 1;
159 
160  if (!ast_strlen_zero(options)) {
161  strcpy(pos, options); /* Safe */
162  }
163  mcast_options->options = pos;
164 
165  if (ast_app_parse_options(multicast_rtp_options, &mcast_options->opts,
166  mcast_options->opt_args, mcast_options->options)) {
167  ast_log(LOG_WARNING, "Error parsing multicast RTP options\n");
168  ast_multicast_rtp_free_options(mcast_options);
169  return NULL;
170  }
171 
172  return mcast_options;
173 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
void ast_multicast_rtp_free_options(struct ast_multicast_rtp_options *mcast_options)
Free multicast RTP options.
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
static const struct ast_app_option multicast_rtp_options[128]
#define ast_log
Definition: astobj2.c:42
char * opt_args[OPT_ARG_ARRAY_SIZE]
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
static struct test_options options

◆ ast_multicast_rtp_free_options()

void ast_multicast_rtp_free_options ( struct ast_multicast_rtp_options mcast_options)

Free multicast RTP options.

This function is NULL-tolerant

Parameters
mcast_optionsOptions to free

Definition at line 175 of file res_rtp_multicast.c.

References ast_free.

Referenced by ast_multicast_rtp_create_options(), and multicast_rtp_request().

176 {
177  ast_free(mcast_options);
178 }
#define ast_free(a)
Definition: astmm.h:182

◆ ast_multicast_rtp_options_get_format()

struct ast_format* ast_multicast_rtp_options_get_format ( struct ast_multicast_rtp_options mcast_options)

Get format specified in multicast options.

Multicast options allow for a format to be selected. This function accesses the selected format and creates an ast_format structure for it.

Parameters
mcast_optionsThe options where a codec was specified
Return values
NULLNo format specified in the options non-NULL The format to use for communication

Definition at line 180 of file res_rtp_multicast.c.

References ast_format_cache_get, ast_strlen_zero, ast_test_flag, multicast_rtp_activate(), multicast_rtp_destroy(), multicast_rtp_new(), multicast_rtp_read(), multicast_rtp_write(), NULL, OPT_ARG_CODEC, ast_multicast_rtp_options::opt_args, OPT_CODEC, and ast_multicast_rtp_options::opts.

Referenced by multicast_rtp_request().

181 {
182  if (ast_test_flag(&mcast_options->opts, OPT_CODEC)
183  && !ast_strlen_zero(mcast_options->opt_args[OPT_ARG_CODEC])) {
184  return ast_format_cache_get(mcast_options->opt_args[OPT_ARG_CODEC]);
185  }
186 
187  return NULL;
188 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define NULL
Definition: resample.c:96
#define ast_format_cache_get(name)
Definition: format_cache.h:286
#define ast_strlen_zero(foo)
Definition: strings.h:52
char * opt_args[OPT_ARG_ARRAY_SIZE]

◆ calc_txstamp()

static unsigned int calc_txstamp ( struct multicast_rtp rtp,
struct timeval *  delivery 
)
static

Definition at line 328 of file res_rtp_multicast.c.

References ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), and multicast_rtp::txcore.

Referenced by rtp_raw_write().

329 {
330  struct timeval t;
331  long ms;
332 
333  if (ast_tvzero(rtp->txcore)) {
334  rtp->txcore = ast_tvnow();
335  rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
336  }
337 
338  t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
339  if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
340  ms = 0;
341  }
342  rtp->txcore = t;
343 
344  return (unsigned int) ms;
345 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:98
struct timeval txcore

◆ load_module()

static int load_module ( void  )
static

Definition at line 546 of file res_rtp_multicast.c.

References AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, and ast_rtp_engine_register.

Referenced by unload_module().

547 {
550  }
551 
553 }
#define ast_rtp_engine_register(engine)
Definition: rtp_engine.h:794
static struct ast_rtp_engine multicast_rtp_engine
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78

◆ multicast_rtp_activate()

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

Referenced by ast_multicast_rtp_options_get_format().

383 {
384  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
385 
386  if (multicast->type != MULTICAST_TYPE_LINKSYS) {
387  return 0;
388  }
389 
390  return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
391 }
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...
enum multicast_type type
Structure for a multicast paging instance.
#define LINKSYS_MCAST_STARTCMD
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ multicast_rtp_destroy()

static int multicast_rtp_destroy ( struct ast_rtp_instance instance)
static

Function called to destroy a multicast instance.

Definition at line 394 of file res_rtp_multicast.c.

References ast_free, ast_rtp_instance_get_data(), ast_smoother_free(), LINKSYS_MCAST_STOPCMD, multicast_send_control_packet(), MULTICAST_TYPE_LINKSYS, multicast_rtp::smoother, multicast_rtp::socket, and multicast_rtp::type.

Referenced by ast_multicast_rtp_options_get_format().

395 {
396  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
397 
398  if (multicast->type == MULTICAST_TYPE_LINKSYS) {
400  }
401 
402  if (multicast->smoother) {
403  ast_smoother_free(multicast->smoother);
404  }
405 
406  close(multicast->socket);
407 
408  ast_free(multicast);
409 
410  return 0;
411 }
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...
enum multicast_type type
void ast_smoother_free(struct ast_smoother *s)
Definition: smoother.c:220
Structure for a multicast paging instance.
struct ast_smoother * smoother
#define LINKSYS_MCAST_STOPCMD
#define ast_free(a)
Definition: astmm.h:182
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563

◆ multicast_rtp_new()

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 284 of file res_rtp_multicast.c.

References ast_calloc, ast_free, ast_random(), ast_rtp_instance_set_data(), ast_test_flag, OPT_ARG_IF, OPT_ARG_LOOP, OPT_ARG_TTL, ast_multicast_rtp_options::opt_args, OPT_IF, OPT_LOOP, OPT_TTL, ast_multicast_rtp_options::opts, set_if(), set_loop(), set_ttl(), set_type(), multicast_rtp::socket, multicast_rtp::ssrc, and ast_multicast_rtp_options::type.

Referenced by ast_multicast_rtp_options_get_format().

285 {
286  struct multicast_rtp *multicast;
287  struct ast_multicast_rtp_options *mcast_options = data;
288 
289  if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
290  return -1;
291  }
292 
293  if (set_type(multicast, mcast_options->type)) {
294  ast_free(multicast);
295  return -1;
296  }
297 
298  if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
299  ast_free(multicast);
300  return -1;
301  }
302 
303  if (ast_test_flag(&mcast_options->opts, OPT_LOOP)) {
304  set_loop(multicast->socket, mcast_options->opt_args[OPT_ARG_LOOP]);
305  }
306 
307  if (ast_test_flag(&mcast_options->opts, OPT_TTL)) {
308  set_ttl(multicast->socket, mcast_options->opt_args[OPT_ARG_TTL]);
309  }
310 
311  if (ast_test_flag(&mcast_options->opts, OPT_IF)) {
312  set_if(multicast->socket, mcast_options->opt_args[OPT_ARG_IF]);
313  }
314 
315  multicast->ssrc = ast_random();
316 
317  ast_rtp_instance_set_data(instance, multicast);
318 
319  return 0;
320 }
static void set_if(int sock, const char *if_str)
#define ast_test_flag(p, flag)
Definition: utils.h:63
static void set_ttl(int sock, const char *ttl_str)
Structure for a multicast paging instance.
char * opt_args[OPT_ARG_ARRAY_SIZE]
void ast_rtp_instance_set_data(struct ast_rtp_instance *instance, void *data)
Set the data portion of an RTP instance.
Definition: rtp_engine.c:558
unsigned int ssrc
long int ast_random(void)
Definition: main/utils.c:2064
static void set_loop(int sock, const char *loop_str)
static int set_type(struct multicast_rtp *multicast, const char *type)
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204

◆ multicast_rtp_read()

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 541 of file res_rtp_multicast.c.

References ast_null_frame.

Referenced by ast_multicast_rtp_options_get_format().

542 {
543  return &ast_null_frame;
544 }
struct ast_frame ast_null_frame
Definition: main/frame.c:79

◆ multicast_rtp_write()

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 469 of file res_rtp_multicast.c.

References ast_format_can_be_smoothed(), ast_format_get_default_ms(), ast_format_get_minimum_bytes(), ast_format_get_minimum_ms(), ast_format_get_name(), ast_format_get_smoother_flags(), AST_FRAME_VOICE, ast_frdup, ast_frfree, ast_log, ast_rtp_codecs_get_framing(), ast_rtp_codecs_payload_code_tx(), ast_rtp_instance_get_codecs(), ast_rtp_instance_get_data(), ast_smoother_feed, ast_smoother_feed_be, AST_SMOOTHER_FLAG_BE, AST_SMOOTHER_FLAG_FORCED, ast_smoother_new(), ast_smoother_read(), ast_smoother_set_flags(), ast_smoother_test_flag(), ast_frame::data, format, ast_frame_subclass::format, ast_frame::frametype, LOG_WARNING, ast_frame::offset, ast_frame::ptr, rtp_raw_write(), multicast_rtp::smoother, and ast_frame::subclass.

Referenced by ast_multicast_rtp_options_get_format().

470 {
471  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
472  struct ast_format *format;
473  struct ast_frame *f;
474  int codec;
475 
476  /* We only accept audio, nothing else */
477  if (frame->frametype != AST_FRAME_VOICE) {
478  return 0;
479  }
480 
481  /* Grab the actual payload number for when we create the RTP packet */
483  1, frame->subclass.format, 0);
484  if (codec < 0) {
485  return -1;
486  }
487 
488  format = frame->subclass.format;
489  if (!multicast->smoother && ast_format_can_be_smoothed(format)) {
490  unsigned int smoother_flags = ast_format_get_smoother_flags(format);
491  unsigned int framing_ms = ast_rtp_codecs_get_framing(ast_rtp_instance_get_codecs(instance));
492 
493  if (!framing_ms && (smoother_flags & AST_SMOOTHER_FLAG_FORCED)) {
494  framing_ms = ast_format_get_default_ms(format);
495  }
496 
497  if (framing_ms) {
498  multicast->smoother = ast_smoother_new((framing_ms * ast_format_get_minimum_bytes(format)) / ast_format_get_minimum_ms(format));
499  if (!multicast->smoother) {
500  ast_log(LOG_WARNING, "Unable to create smoother: format %s ms: %u len %u\n",
501  ast_format_get_name(format), framing_ms, ast_format_get_minimum_bytes(format));
502  return -1;
503  }
504  ast_smoother_set_flags(multicast->smoother, smoother_flags);
505  }
506  }
507 
508  if (multicast->smoother) {
510  ast_smoother_feed_be(multicast->smoother, frame);
511  } else {
512  ast_smoother_feed(multicast->smoother, frame);
513  }
514 
515  while ((f = ast_smoother_read(multicast->smoother)) && f->data.ptr) {
516  rtp_raw_write(instance, f, codec);
517  }
518  } else {
519  int hdrlen = 12;
520 
521  /* If we do not have space to construct an RTP header duplicate the frame so we get some */
522  if (frame->offset < hdrlen) {
523  f = ast_frdup(frame);
524  } else {
525  f = frame;
526  }
527 
528  if (f->data.ptr) {
529  rtp_raw_write(instance, f, codec);
530  }
531 
532  if (f != frame) {
533  ast_frfree(f);
534  }
535  }
536 
537  return 0;
538 }
#define ast_frdup(fr)
Copies a frame.
#define ast_smoother_feed(s, f)
Definition: smoother.h:76
struct ast_smoother * ast_smoother_new(int bytes)
Definition: smoother.c:108
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:727
#define LOG_WARNING
Definition: logger.h:274
Definition of a media format.
Definition: format.c:43
const char * ast_format_get_name(const struct ast_format *format)
Get the name associated with a format.
Definition: format.c:334
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code...
Definition: rtp_engine.c:1928
unsigned int ast_rtp_codecs_get_framing(struct ast_rtp_codecs *codecs)
Get the framing used for a set of codecs.
Definition: rtp_engine.c:1569
struct ast_frame_subclass subclass
int ast_format_get_smoother_flags(const struct ast_format *format)
Get smoother flags for this format.
Definition: format.c:349
Structure for a multicast paging instance.
#define ast_log
Definition: astobj2.c:42
struct ast_smoother * smoother
#define AST_SMOOTHER_FLAG_FORCED
Definition: smoother.h:36
unsigned int ast_format_get_minimum_bytes(const struct ast_format *format)
Get the minimum number of bytes expected in a frame for this format.
Definition: format.c:374
int ast_format_can_be_smoothed(const struct ast_format *format)
Get whether or not the format can be smoothed.
Definition: format.c:344
#define ast_smoother_feed_be(s, f)
Definition: smoother.h:81
static int rtp_raw_write(struct ast_rtp_instance *instance, struct ast_frame *frame, int codec)
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
unsigned int ast_format_get_default_ms(const struct ast_format *format)
Get the default framing size (in milliseconds) for a format.
Definition: format.c:359
int ast_smoother_test_flag(struct ast_smoother *s, int flag)
Definition: smoother.c:128
#define AST_SMOOTHER_FLAG_BE
Definition: smoother.h:35
void ast_smoother_set_flags(struct ast_smoother *smoother, int flags)
Definition: smoother.c:123
struct ast_frame * ast_smoother_read(struct ast_smoother *s)
Definition: smoother.c:169
#define ast_frfree(fr)
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype
struct ast_format * format
unsigned int ast_format_get_minimum_ms(const struct ast_format *format)
Get the minimum amount of media carried in this format.
Definition: format.c:364
static snd_pcm_format_t format
Definition: chan_alsa.c:102

◆ multicast_send_control_packet()

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 348 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, NULL, multicast_control_packet::port, multicast_rtp::socket, and multicast_control_packet::unique_id.

Referenced by multicast_rtp_activate(), and multicast_rtp_destroy().

349 {
350  struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
351  .command = htonl(command),
352  };
353  struct ast_sockaddr control_address, remote_address;
354 
355  ast_rtp_instance_get_local_address(instance, &control_address);
356  ast_rtp_instance_get_remote_address(instance, &remote_address);
357 
358  /* Ensure the user of us have given us both the control address and destination address */
359  if (ast_sockaddr_isnull(&control_address) ||
360  ast_sockaddr_isnull(&remote_address)) {
361  return -1;
362  }
363 
364  /* The protocol only supports IPv4. */
365  if (ast_sockaddr_is_ipv6(&remote_address)) {
366  ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
367  "remote address.\n");
368  return -1;
369  }
370 
371  control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
372  control_packet.port = htonl(ast_sockaddr_port(&remote_address));
373 
374  /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
375  ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
376  ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
377 
378  return 0;
379 }
Structure for a Linksys control packet.
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
#define LOG_WARNING
Definition: logger.h:274
uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
Get an IPv4 address of an ast_sockaddr.
Definition: netsock2.c:491
#define NULL
Definition: resample.c:96
Socket address structure.
Definition: netsock2.h:97
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. "null" in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:127
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
#define ast_log
Definition: astobj2.c:42
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:643
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524

◆ rtp_get_rate()

static int rtp_get_rate ( struct ast_format format)
static

Definition at line 322 of file res_rtp_multicast.c.

References ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g722, and ast_format_get_sample_rate().

Referenced by rtp_raw_write().

323 {
325  8000 : ast_format_get_sample_rate(format);
326 }
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:111
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
unsigned int ast_format_get_sample_rate(const struct ast_format *format)
Get the sample rate of a media format.
Definition: format.c:379

◆ rtp_raw_write()

static int rtp_raw_write ( struct ast_rtp_instance instance,
struct ast_frame frame,
int  codec 
)
static

Definition at line 413 of file res_rtp_multicast.c.

References abs, ast_debug, ast_format_cmp(), AST_FORMAT_CMP_EQUAL, ast_format_g722, AST_FRFLAG_HAS_TIMING_INFO, ast_log, ast_rtp_instance_get_data(), ast_rtp_instance_get_remote_address, ast_sendto(), ast_sockaddr_stringify(), ast_test_flag, ast_tvzero(), calc_txstamp(), ast_frame::data, ast_frame::datalen, ast_frame::delivery, errno, ast_frame_subclass::format, multicast_rtp::lastts, LOG_ERROR, MAX_TIMESTAMP_SKEW, ast_frame::ptr, put_unaligned_uint32(), rtp_get_rate(), ast_frame::samples, multicast_rtp::seqno, multicast_rtp::socket, multicast_rtp::ssrc, ast_frame::subclass, and ast_frame::ts.

Referenced by multicast_rtp_write().

414 {
415  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
416  unsigned int ms = calc_txstamp(multicast, &frame->delivery);
417  unsigned char *rtpheader;
418  struct ast_sockaddr remote_address = { {0,} };
419  int rate = rtp_get_rate(frame->subclass.format) / 1000;
420  int hdrlen = 12, mark = 0;
421 
423  frame->samples /= 2;
424  }
425 
427  multicast->lastts = frame->ts * rate;
428  } else {
429  /* Try to predict what our timestamp should be */
430  int pred = multicast->lastts + frame->samples;
431 
432  /* Calculate last TS */
433  multicast->lastts = multicast->lastts + ms * rate;
434  if (ast_tvzero(frame->delivery)) {
435  int delta = abs((int) multicast->lastts - pred);
436  if (delta < MAX_TIMESTAMP_SKEW) {
437  multicast->lastts = pred;
438  } else {
439  ast_debug(3, "Difference is %d, ms is %u\n", delta, ms);
440  mark = 1;
441  }
442  }
443  }
444 
445  /* Construct an RTP header for our packet */
446  rtpheader = (unsigned char *)(frame->data.ptr - hdrlen);
447 
448  put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno) | (mark << 23)));
449  put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
450  put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
451 
452  /* Increment sequence number and wrap to 0 if it overflows 16 bits. */
453  multicast->seqno = 0xFFFF & (multicast->seqno + 1);
454 
455  /* Finally send it out to the eager phones listening for us */
456  ast_rtp_instance_get_remote_address(instance, &remote_address);
457 
458  if (ast_sendto(multicast->socket, (void *) rtpheader, frame->datalen + hdrlen, 0, &remote_address) < 0) {
459  ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
460  ast_sockaddr_stringify(&remote_address),
461  strerror(errno));
462  return -1;
463  }
464 
465  return 0;
466 }
#define MAX_TIMESTAMP_SKEW
ssize_t ast_sendto(int sockfd, const void *buf, size_t len, int flags, const struct ast_sockaddr *dest_addr)
Wrapper around sendto(2) that uses ast_sockaddr.
Definition: netsock2.c:614
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
static unsigned int calc_txstamp(struct multicast_rtp *rtp, struct timeval *delivery)
static void put_unaligned_uint32(void *p, unsigned int datum)
Definition: unaligned.h:58
struct ast_format * ast_format_g722
Built-in cached g722 format.
Definition: format_cache.c:111
Socket address structure.
Definition: netsock2.h:97
struct ast_frame_subclass subclass
Structure for a multicast paging instance.
unsigned int lastts
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
enum ast_format_cmp_res ast_format_cmp(const struct ast_format *format1, const struct ast_format *format2)
Compare two formats.
Definition: format.c:201
unsigned int ssrc
#define LOG_ERROR
Definition: logger.h:285
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:563
static int rtp_get_rate(struct ast_format *format)
struct timeval delivery
#define abs(x)
Definition: f2c.h:195
union ast_frame::@263 data
struct ast_format * format
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1192

◆ set_if()

static void set_if ( int  sock,
const char *  if_str 
)
static

Definition at line 263 of file res_rtp_multicast.c.

References ast_debug, ast_log, ast_strlen_zero, errno, inet_aton(), and LOG_WARNING.

Referenced by multicast_rtp_new().

264 {
265  struct in_addr iface;
266 
267  if (ast_strlen_zero(if_str)) {
268  return;
269  }
270 
271  ast_debug(3, "Setting multicast if to %s\n", if_str);
272 
273  if (!inet_aton(if_str, &iface)) {
274  ast_log(LOG_WARNING, "Cannot parse if option '%s'\n", if_str);
275  }
276 
277  if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &iface, sizeof(iface)) < 0) {
278  ast_log(LOG_WARNING, "Could not set multicast if to '%s': %s\n",
279  if_str, strerror(errno));
280  }
281 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int errno
int inet_aton(const char *cp, struct in_addr *pin)

◆ set_loop()

static void set_loop ( int  sock,
const char *  loop_str 
)
static

Definition at line 242 of file res_rtp_multicast.c.

References ast_debug, ast_log, ast_strlen_zero, errno, and LOG_WARNING.

Referenced by multicast_rtp_new().

243 {
244  unsigned char loop;
245 
246  if (ast_strlen_zero(loop_str)) {
247  return;
248  }
249 
250  ast_debug(3, "Setting multicast loop to %s\n", loop_str);
251 
252  if (sscanf(loop_str, "%30hhu", &loop) < 1) {
253  ast_log(LOG_WARNING, "Invalid multicast loop option '%s'\n", loop_str);
254  return;
255  }
256 
257  if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) {
258  ast_log(LOG_WARNING, "Could not set multicast loop to '%s': %s\n",
259  loop_str, strerror(errno));
260  }
261 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int errno

◆ set_ttl()

static void set_ttl ( int  sock,
const char *  ttl_str 
)
static

Definition at line 221 of file res_rtp_multicast.c.

References ast_debug, ast_log, ast_strlen_zero, errno, and LOG_WARNING.

Referenced by multicast_rtp_new().

222 {
223  int ttl;
224 
225  if (ast_strlen_zero(ttl_str)) {
226  return;
227  }
228 
229  ast_debug(3, "Setting multicast TTL to %s\n", ttl_str);
230 
231  if (sscanf(ttl_str, "%30d", &ttl) < 1) {
232  ast_log(LOG_WARNING, "Invalid multicast ttl option '%s'\n", ttl_str);
233  return;
234  }
235 
236  if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) {
237  ast_log(LOG_WARNING, "Could not set multicast ttl to '%s': %s\n",
238  ttl_str, strerror(errno));
239  }
240 }
#define LOG_WARNING
Definition: logger.h:274
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
int errno

◆ set_type()

static int set_type ( struct multicast_rtp multicast,
const char *  type 
)
static

Definition at line 207 of file res_rtp_multicast.c.

References ast_log, LOG_WARNING, MULTICAST_TYPE_BASIC, MULTICAST_TYPE_LINKSYS, and multicast_rtp::type.

Referenced by multicast_rtp_new().

208 {
209  if (!strcasecmp(type, "basic")) {
210  multicast->type = MULTICAST_TYPE_BASIC;
211  } else if (!strcasecmp(type, "linksys")) {
212  multicast->type = MULTICAST_TYPE_LINKSYS;
213  } else {
214  ast_log(LOG_WARNING, "Unrecognized multicast type '%s' specified.\n", type);
215  return -1;
216  }
217 
218  return 0;
219 }
static const char type[]
Definition: chan_ooh323.c:109
#define LOG_WARNING
Definition: logger.h:274
enum multicast_type type
#define ast_log
Definition: astobj2.c:42

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 555 of file res_rtp_multicast.c.

References AST_MODFLAG_GLOBAL_SYMBOLS, AST_MODFLAG_LOAD_ORDER, AST_MODPRI_CHANNEL_DEPEND, AST_MODULE_INFO(), AST_MODULE_SUPPORT_CORE, ast_rtp_engine_unregister(), ASTERISK_GPL_KEY, and load_module().

556 {
558 
559  return 0;
560 }
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:364
static struct ast_rtp_engine multicast_rtp_engine

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_GLOBAL_SYMBOLS | 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, .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_CHANNEL_DEPEND, }
static

Definition at line 567 of file res_rtp_multicast.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 567 of file res_rtp_multicast.c.

◆ multicast_rtp_engine

struct ast_rtp_engine multicast_rtp_engine
static

Definition at line 198 of file res_rtp_multicast.c.

◆ multicast_rtp_options

const struct ast_app_option multicast_rtp_options[128] = { [ 'c' ] = { .flag = OPT_CODEC , .arg_index = OPT_ARG_CODEC + 1 }, [ 'l' ] = { .flag = OPT_LOOP , .arg_index = OPT_ARG_LOOP + 1 }, [ 't' ] = { .flag = OPT_TTL , .arg_index = OPT_ARG_TTL + 1 }, [ 'i' ] = { .flag = OPT_IF , .arg_index = OPT_ARG_IF + 1 }, }
static

Definition at line 128 of file res_rtp_multicast.c.

Referenced by ast_multicast_rtp_create_options().