Wed Jan 8 2020 09:50:19

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

Macros

#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. 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 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 (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.nosp@m.@dig.nosp@m.ium.c.nosp@m.om
Andreas 'MacBrody' Brodmann andre.nosp@m.as.b.nosp@m.rodma.nosp@m.nn@g.nosp@m.mail..nosp@m.com

Definition in file res_rtp_multicast.c.

Macro Definition 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.

64  {
65  /*! Simple multicast enabled client/receiver paging like Snom and Barix uses */
67  /*! More advanced Linksys type paging which requires a start and stop packet */
69 };

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

151 {
152  struct timeval t;
153  long ms;
154 
155  if (ast_tvzero(rtp->txcore)) {
156  rtp->txcore = ast_tvnow();
157  rtp->txcore.tv_usec -= rtp->txcore.tv_usec % 20000;
158  }
159 
160  t = (delivery && !ast_tvzero(*delivery)) ? *delivery : ast_tvnow();
161  if ((ms = ast_tvdiff_ms(t, rtp->txcore)) < 0) {
162  ms = 0;
163  }
164  rtp->txcore = t;
165 
166  return (unsigned int) ms;
167 }
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:100
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:90
struct timeval txcore
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.

301 {
304  }
305 
307 }
#define ast_rtp_engine_register(engine)
Definition: rtp_engine.h:423
static struct ast_rtp_engine multicast_rtp_engine
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.

205 {
206  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
207 
208  if (multicast->type != MULTICAST_TYPE_LINKSYS) {
209  return 0;
210  }
211 
212  return multicast_send_control_packet(instance, multicast, LINKSYS_MCAST_STARTCMD);
213 }
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:369
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.

217 {
218  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
219 
220  if (multicast->type == MULTICAST_TYPE_LINKSYS) {
222  }
223 
224  close(multicast->socket);
225 
226  ast_free(multicast);
227 
228  return 0;
229 }
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_STOPCMD
#define ast_free(a)
Definition: astmm.h:97
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:369
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, type, and multicast_rtp::type.

116 {
117  struct multicast_rtp *multicast;
118  const char *type = data;
119 
120  if (!(multicast = ast_calloc(1, sizeof(*multicast)))) {
121  return -1;
122  }
123 
124  if (!strcasecmp(type, "basic")) {
125  multicast->type = MULTICAST_TYPE_BASIC;
126  } else if (!strcasecmp(type, "linksys")) {
127  multicast->type = MULTICAST_TYPE_LINKSYS;
128  } else {
129  ast_free(multicast);
130  return -1;
131  }
132 
133  if ((multicast->socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
134  ast_free(multicast);
135  return -1;
136  }
137 
138  multicast->ssrc = ast_random();
139 
140  ast_rtp_instance_set_data(instance, multicast);
141 
142  return 0;
143 }
enum multicast_type type
Structure for a multicast paging instance.
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:364
unsigned int ssrc
long int ast_random(void)
Definition: utils.c:1640
#define ast_free(a)
Definition: astmm.h:97
static const char type[]
Definition: chan_nbs.c:57
#define ast_calloc(a, b)
Definition: astmm.h:82
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 295 of file res_rtp_multicast.c.

References ast_null_frame.

296 {
297  return &ast_null_frame;
298 }
struct ast_frame ast_null_frame
Definition: frame.c:131
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.

233 {
234  struct multicast_rtp *multicast = ast_rtp_instance_get_data(instance);
235  struct ast_frame *f = frame;
236  struct ast_sockaddr remote_address;
237  int hdrlen = 12, res = 0, codec;
238  int rate;
239  unsigned char *rtpheader;
240  unsigned int ms = calc_txstamp(multicast, &frame->delivery);
241 
242  /* We only accept audio, nothing else */
243  if (frame->frametype != AST_FRAME_VOICE) {
244  return 0;
245  }
246  rate = rtp_get_rate(frame->subclass.codec) / 1000;
247 
248  /* Grab the actual payload number for when we create the RTP packet */
249  if ((codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(instance), 1, frame->subclass.codec)) < 0) {
250  return -1;
251  }
252 
253  /* If we do not have space to construct an RTP header duplicate the frame so we get some */
254  if (frame->offset < hdrlen) {
255  f = ast_frdup(frame);
256  }
257 
258  /* Calucate last TS */
259  multicast->lastts = multicast->lastts + ms * rate;
260 
261  /* Construct an RTP header for our packet */
262  rtpheader = (unsigned char *)(f->data.ptr - hdrlen);
263  put_unaligned_uint32(rtpheader, htonl((2 << 30) | (codec << 16) | (multicast->seqno)));
264 
266  put_unaligned_uint32(rtpheader + 4, htonl(f->ts * 8));
267  } else {
268  put_unaligned_uint32(rtpheader + 4, htonl(multicast->lastts));
269  }
270 
271  put_unaligned_uint32(rtpheader + 8, htonl(multicast->ssrc));
272 
273  /* Increment sequence number and wrap to 0 if it overflows 16 bits. */
274  multicast->seqno = 0xFFFF & (multicast->seqno + 1);
275 
276  /* Finally send it out to the eager phones listening for us */
277  ast_rtp_instance_get_remote_address(instance, &remote_address);
278 
279  if (ast_sendto(multicast->socket, (void *) rtpheader, f->datalen + hdrlen, 0, &remote_address) < 0) {
280  ast_log(LOG_ERROR, "Multicast RTP Transmission error to %s: %s\n",
281  ast_sockaddr_stringify(&remote_address),
282  strerror(errno));
283  res = -1;
284  }
285 
286  /* If we were forced to duplicate the frame free the new one */
287  if (frame != f) {
288  ast_frfree(f);
289  }
290 
291  return res;
292 }
union ast_frame_subclass subclass
Definition: frame.h:146
static int rtp_get_rate(format_t format)
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:486
int offset
Definition: frame.h:156
#define ast_test_flag(p, flag)
Definition: utils.h:63
void * ptr
Definition: frame.h:160
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:483
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
long ts
Definition: frame.h:168
format_t codec
Definition: frame.h:137
Socket address structure.
Definition: netsock2.h:63
Structure for a multicast paging instance.
unsigned int lastts
unsigned int ssrc
int datalen
Definition: frame.h:148
#define LOG_ERROR
Definition: logger.h:155
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:210
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int errno
void * ast_rtp_instance_get_data(struct ast_rtp_instance *instance)
Get the data portion of an RTP instance.
Definition: rtp_engine.c:369
void ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:447
static struct ast_format f[]
Definition: format_g726.c:181
struct timeval delivery
Definition: frame.h:162
Data structure associated with a single frame of data.
Definition: frame.h:142
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
union ast_frame::@172 data
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code)
Retrieve a payload based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:654
struct ast_frame * ast_frdup(const struct ast_frame *fr)
Copies a frame.
Definition: frame.c:474
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().

171 {
172  struct multicast_control_packet control_packet = { .unique_id = htonl((u_long)time(NULL)),
173  .command = htonl(command),
174  };
175  struct ast_sockaddr control_address, remote_address;
176 
177  ast_rtp_instance_get_local_address(instance, &control_address);
178  ast_rtp_instance_get_remote_address(instance, &remote_address);
179 
180  /* Ensure the user of us have given us both the control address and destination address */
181  if (ast_sockaddr_isnull(&control_address) ||
182  ast_sockaddr_isnull(&remote_address)) {
183  return -1;
184  }
185 
186  /* The protocol only supports IPv4. */
187  if (ast_sockaddr_is_ipv6(&remote_address)) {
188  ast_log(LOG_WARNING, "Cannot send control packet for IPv6 "
189  "remote address.\n");
190  return -1;
191  }
192 
193  control_packet.ip = htonl(ast_sockaddr_ipv4(&remote_address));
194  control_packet.port = htonl(ast_sockaddr_port(&remote_address));
195 
196  /* Based on a recommendation by Brian West who did the FreeSWITCH implementation we send control packets twice */
197  ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
198  ast_sendto(multicast->socket, &control_packet, sizeof(control_packet), 0, &control_address);
199 
200  return 0;
201 }
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:486
#define LOG_WARNING
Definition: logger.h:144
uint32_t ast_sockaddr_ipv4(const struct ast_sockaddr *addr)
Get an IPv4 address of an ast_sockaddr.
Definition: netsock2.c:394
Socket address structure.
Definition: netsock2.h:63
static int ast_sockaddr_isnull(const struct ast_sockaddr *addr)
Checks if the ast_sockaddr is null. &quot;null&quot; in this sense essentially means uninitialized, or having a 0 length.
Definition: netsock2.h:93
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:406
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
void ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:447
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:430
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:418
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().

146 {
147  return (format == AST_FORMAT_G722) ? 8000 : ast_format_rate(format);
148 }
static force_inline int ast_format_rate(format_t format)
Get the sample rate for a given format.
Definition: frame.h:809
#define AST_FORMAT_G722
Definition: frame.h:266
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static int unload_module ( void  )
static

Definition at line 309 of file res_rtp_multicast.c.

References ast_rtp_engine_unregister().

310 {
312 
313  return 0;
314 }
int ast_rtp_engine_unregister(struct ast_rtp_engine *engine)
Unregister an RTP engine.
Definition: rtp_engine.c:222
static struct ast_rtp_engine multicast_rtp_engine

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.

struct ast_rtp_engine multicast_rtp_engine
static

Definition at line 105 of file res_rtp_multicast.c.