Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Enumerations | Functions | Variables
func_cdr.c File Reference

Call Detail Record related dialplan functions. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/app.h"
#include "asterisk/cdr.h"
#include "asterisk/stasis.h"
#include "asterisk/stasis_message_router.h"
Include dependency graph for func_cdr.c:

Go to the source code of this file.

Data Structures

struct  cdr_func_data
 
struct  cdr_func_payload
 

Enumerations

enum  cdr_option_flags { OPT_UNPARSED = (1 << 1), OPT_FLOAT = (1 << 2) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int cdr_prop_write (struct ast_channel *chan, const char *cmd, char *parse, const char *value)
 
static void cdr_prop_write_callback (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int cdr_read (struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
 
static void cdr_read_callback (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static struct timeval cdr_retrieve_time (struct ast_channel *chan, const char *time_name)
 
static int cdr_write (struct ast_channel *chan, const char *cmd, char *arguments, const char *value)
 
static void cdr_write_callback (void *data, struct stasis_subscription *sub, struct stasis_message *message)
 
static int load_module (void)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (cdr_read_message_type)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (cdr_write_message_type)
 
 STASIS_MESSAGE_TYPE_DEFN_LOCAL (cdr_prop_write_message_type)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Call Detail Record (CDR) dialplan functions" , .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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "cdr", }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_app_option cdr_func_options [128] = { [ 'f' ] = { .flag = OPT_FLOAT }, [ 'u' ] = { .flag = OPT_UNPARSED }, }
 
static struct ast_custom_function cdr_function
 
static struct ast_custom_function cdr_prop_function
 

Detailed Description

Call Detail Record related dialplan functions.

Author
Anthony Minessale II

Definition in file func_cdr.c.

Enumeration Type Documentation

◆ cdr_option_flags

Enumerator
OPT_UNPARSED 
OPT_FLOAT 

Definition at line 195 of file func_cdr.c.

195  {
196  OPT_UNPARSED = (1 << 1),
197  OPT_FLOAT = (1 << 2),
198 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 712 of file func_cdr.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 712 of file func_cdr.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 712 of file func_cdr.c.

◆ cdr_prop_write()

static int cdr_prop_write ( struct ast_channel chan,
const char *  cmd,
char *  parse,
const char *  value 
)
static

Definition at line 604 of file func_cdr.c.

References ao2_alloc, ao2_cleanup, ast_cdr_message_router(), ast_channel_name(), ast_log, AST_LOG_WARNING, cdr_func_payload::chan, cdr_func_payload::cmd, LOG_WARNING, NULL, parse(), RAII_VAR, router, stasis_message_create(), stasis_message_router_publish_sync(), and cdr_func_payload::value.

606 {
608  RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
610 
611  if (!chan) {
612  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
613  return -1;
614  }
615 
616  if (!router) {
617  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
618  ast_channel_name(chan));
619  return -1;
620  }
621 
622  if (!cdr_prop_write_message_type()) {
623  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
624  ast_channel_name(chan));
625  return -1;
626  }
627 
628  payload = ao2_alloc(sizeof(*payload), NULL);
629  if (!payload) {
630  return -1;
631  }
632  payload->chan = chan;
633  payload->cmd = cmd;
634  payload->arguments = parse;
635  payload->value = value;
636 
637  message = stasis_message_create(cdr_prop_write_message_type(), payload);
638  if (!message) {
639  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
640  ast_channel_name(chan));
641  return -1;
642  }
644 
645  return 0;
646 }
static struct stasis_message_router * router
#define LOG_WARNING
Definition: logger.h:274
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
#define AST_LOG_WARNING
Definition: logger.h:279
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_log
Definition: astobj2.c:42
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)

◆ cdr_prop_write_callback()

static void cdr_prop_write_callback ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 400 of file func_cdr.c.

References args, cdr_func_payload::arguments, AST_APP_ARG, ast_cdr_clear_property(), AST_CDR_FLAG_DISABLE_ALL, AST_CDR_FLAG_PARTY_A, ast_cdr_set_property(), ast_channel_name(), AST_DECLARE_APP_ARGS, ast_log, AST_LOG_WARNING, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, ast_true(), cdr_func_payload::chan, cdr_func_payload::cmd, options, parse(), stasis_message_data(), stasis_message_type(), and cdr_func_payload::value.

Referenced by load_module().

401 {
402  struct cdr_func_payload *payload = stasis_message_data(message);
403  enum ast_cdr_options option;
404  char *parse;
406  AST_APP_ARG(variable);
408  );
409 
410  if (cdr_prop_write_message_type() != stasis_message_type(message)) {
411  return;
412  }
413 
414  if (!payload) {
415  return;
416  }
417 
418  if (ast_strlen_zero(payload->arguments)) {
419  ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
420  payload->cmd, payload->cmd);
421  return;
422  }
423  if (ast_strlen_zero(payload->value)) {
424  ast_log(AST_LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
425  payload->cmd, payload->cmd);
426  return;
427  }
428  parse = ast_strdupa(payload->arguments);
429  AST_STANDARD_APP_ARGS(args, parse);
430 
431  if (!strcasecmp("party_a", args.variable)) {
432  option = AST_CDR_FLAG_PARTY_A;
433  } else if (!strcasecmp("disable", args.variable)) {
434  option = AST_CDR_FLAG_DISABLE_ALL;
435  } else {
436  ast_log(AST_LOG_WARNING, "Unknown option %s used with %s\n", args.variable, payload->cmd);
437  return;
438  }
439 
440  if (ast_true(payload->value)) {
441  ast_cdr_set_property(ast_channel_name(payload->chan), option);
442  } else {
443  ast_cdr_clear_property(ast_channel_name(payload->chan), option);
444  }
445 }
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define AST_LOG_WARNING
Definition: logger.h:279
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
const char * args
ast_cdr_options
CDR manipulation options. Certain function calls will manipulate the state of a CDR object based on t...
Definition: cdr.h:239
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
int ast_cdr_set_property(const char *channel_name, enum ast_cdr_options option)
Set a property on a CDR for a channel.
Definition: cdr.c:3548
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
const char * arguments
Definition: func_cdr.c:208
struct ast_channel * chan
Definition: func_cdr.c:206
const char * ast_channel_name(const struct ast_channel *chan)
const char * value
Definition: func_cdr.c:209
int ast_cdr_clear_property(const char *channel_name, enum ast_cdr_options option)
Clear a property on a CDR for a channel.
Definition: cdr.c:3575
const char * cmd
Definition: func_cdr.c:207
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ cdr_read()

static int cdr_read ( struct ast_channel chan,
const char *  cmd,
char *  parse,
char *  buf,
size_t  len 
)
static

Definition at line 448 of file func_cdr.c.

References ao2_alloc, ao2_cleanup, ast_cdr_message_router(), ast_channel_name(), ast_log, AST_LOG_WARNING, ast_strlen_zero, buf, cdr_func_data::buf, cdr_read_callback(), cdr_func_payload::chan, cdr_func_payload::cmd, cdr_func_data::len, len(), LOG_WARNING, NULL, parse(), RAII_VAR, router, stasis_message_create(), and stasis_message_router_publish_sync().

450 {
452  RAII_VAR(struct cdr_func_payload *, payload, NULL, ao2_cleanup);
453  struct cdr_func_data output = { 0, };
454 
455  if (!chan) {
456  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
457  return -1;
458  }
459 
460  if (!cdr_read_message_type()) {
461  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
462  ast_channel_name(chan));
463  return -1;
464  }
465 
466  payload = ao2_alloc(sizeof(*payload), NULL);
467  if (!payload) {
468  return -1;
469  }
470  payload->chan = chan;
471  payload->cmd = cmd;
472  payload->arguments = parse;
473  payload->data = &output;
474 
475  buf[0] = '\0';/* Ensure the buffer is initialized. */
476  output.buf = buf;
477  output.len = len;
478 
479  message = stasis_message_create(cdr_read_message_type(), payload);
480  if (!message) {
481  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
482  ast_channel_name(chan));
483  return -1;
484  }
485 
486  /* If this is a request on a dummy channel, we're doing post-processing on an
487  * already dispatched CDR. Simply call the callback to calculate the value and
488  * return, instead of posting to Stasis as we would for a running channel.
489  */
490  if (ast_strlen_zero(ast_channel_name(chan))) {
492  } else {
494 
495  if (!router) {
496  ast_log(AST_LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
497  ast_channel_name(chan));
498  return -1;
499  }
501  }
502 
503  return 0;
504 }
static struct stasis_message_router * router
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
#define AST_LOG_WARNING
Definition: logger.h:279
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
char * buf
Definition: func_cdr.c:214
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:248
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
const char * ast_channel_name(const struct ast_channel *chan)
size_t len
Definition: func_cdr.c:215

◆ cdr_read_callback()

static void cdr_read_callback ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 248 of file func_cdr.c.

References amaflags, args, cdr_func_payload::arguments, AST_APP_ARG, ast_app_parse_options(), ast_assert, ast_cdr_disp2str(), ast_cdr_format_var(), ast_cdr_getvar(), ast_channel_amaflags2string(), ast_channel_cdr(), ast_channel_name(), ast_copy_string(), AST_DECLARE_APP_ARGS, ast_localtime(), ast_log, AST_LOG_WARNING, ast_set_flag, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strftime(), ast_strlen_zero, ast_test_flag, ast_tvdiff_us(), ast_tvnow(), ast_tvzero(), cdr_func_data::buf, cdr_func_options, cdr_retrieve_time(), cdr_func_payload::chan, cdr_func_payload::cmd, cdr_func_payload::data, sip_to_pjsip::info(), cdr_func_data::len, NULL, OPT_FLOAT, OPT_UNPARSED, options, stasis_message_data(), stasis_message_type(), and cdr_func_payload::value.

Referenced by cdr_read(), and load_module().

249 {
250  struct cdr_func_payload *payload = stasis_message_data(message);
251  struct cdr_func_data *output;
252  char *info;
253  char *value = NULL;
254  struct ast_flags flags = { 0 };
255  char tempbuf[512];
257  AST_APP_ARG(variable);
259  );
260 
261  if (cdr_read_message_type() != stasis_message_type(message)) {
262  return;
263  }
264 
265  ast_assert(payload != NULL);
266  output = payload->data;
267  ast_assert(output != NULL);
268 
269  if (ast_strlen_zero(payload->arguments)) {
270  ast_log(AST_LOG_WARNING, "%s requires a variable (%s(variable[,option]))\n)",
271  payload->cmd, payload->cmd);
272  return;
273  }
274  info = ast_strdupa(payload->arguments);
276 
277  if (!ast_strlen_zero(args.options)) {
278  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
279  }
280 
281  if (ast_strlen_zero(ast_channel_name(payload->chan))) {
282  /* Format request on a dummy channel */
283  ast_cdr_format_var(ast_channel_cdr(payload->chan), args.variable, &value, tempbuf, sizeof(tempbuf), ast_test_flag(&flags, OPT_UNPARSED));
284  if (ast_strlen_zero(value)) {
285  return;
286  }
287  ast_copy_string(tempbuf, value, sizeof(tempbuf));
288  ast_set_flag(&flags, OPT_UNPARSED);
289  } else if (ast_cdr_getvar(ast_channel_name(payload->chan), args.variable, tempbuf, sizeof(tempbuf))) {
290  return;
291  }
292 
293  if (ast_test_flag(&flags, OPT_FLOAT)
294  && (!strcasecmp("billsec", args.variable) || !strcasecmp("duration", args.variable))) {
295  struct timeval start = cdr_retrieve_time(payload->chan, !strcasecmp("billsec", args.variable) ? "answer" : "start");
296  struct timeval finish = cdr_retrieve_time(payload->chan, "end");
297  double delta;
298 
299  if (ast_tvzero(finish)) {
300  finish = ast_tvnow();
301  }
302 
303  if (ast_tvzero(start)) {
304  delta = 0.0;
305  } else {
306  delta = (double)(ast_tvdiff_us(finish, start) / 1000000.0);
307  }
308  snprintf(tempbuf, sizeof(tempbuf), "%lf", delta);
309 
310  } else if (!ast_test_flag(&flags, OPT_UNPARSED)) {
311  if (!strcasecmp("start", args.variable)
312  || !strcasecmp("end", args.variable)
313  || !strcasecmp("answer", args.variable)) {
314  struct timeval fmt_time;
315  struct ast_tm tm;
316  /* tv_usec is suseconds_t, which could be int or long */
317  long int tv_sec;
318  long int tv_usec;
319 
320  if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) != 2) {
321  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
322  args.variable, tempbuf, ast_channel_name(payload->chan));
323  return;
324  }
325  if (tv_sec) {
326  fmt_time.tv_sec = tv_sec;
327  fmt_time.tv_usec = tv_usec;
328  ast_localtime(&fmt_time, &tm, NULL);
329  ast_strftime(tempbuf, sizeof(tempbuf), "%Y-%m-%d %T", &tm);
330  } else {
331  tempbuf[0] = '\0';
332  }
333  } else if (!strcasecmp("disposition", args.variable)) {
334  int disposition;
335 
336  if (sscanf(tempbuf, "%8d", &disposition) != 1) {
337  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
338  args.variable, tempbuf, ast_channel_name(payload->chan));
339  return;
340  }
341  snprintf(tempbuf, sizeof(tempbuf), "%s", ast_cdr_disp2str(disposition));
342  } else if (!strcasecmp("amaflags", args.variable)) {
343  int amaflags;
344 
345  if (sscanf(tempbuf, "%8d", &amaflags) != 1) {
346  ast_log(AST_LOG_WARNING, "Unable to parse %s (%s) from the CDR for channel %s\n",
347  args.variable, tempbuf, ast_channel_name(payload->chan));
348  return;
349  }
350  snprintf(tempbuf, sizeof(tempbuf), "%s", ast_channel_amaflags2string(amaflags));
351  }
352  }
353 
354  ast_copy_string(output->buf, tempbuf, output->len);
355 }
static int amaflags
Definition: chan_iax2.c:431
struct ast_cdr * ast_channel_cdr(const struct ast_channel *chan)
static struct timeval cdr_retrieve_time(struct ast_channel *chan, const char *time_name)
Definition: func_cdr.c:222
#define ast_test_flag(p, flag)
Definition: utils.h:63
int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
Retrieve a CDR variable from a channel&#39;s current CDR.
Definition: cdr.c:3324
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
static const struct ast_app_option cdr_func_options[128]
Definition: func_cdr.c:203
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
unsigned int flags
Definition: utils.h:200
#define AST_LOG_WARNING
Definition: logger.h:279
int ast_tvzero(const struct timeval t)
Returns true if the argument is 0,0.
Definition: time.h:108
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
const char * ast_channel_amaflags2string(enum ama_flags flags)
Convert the enum representation of an AMA flag to a string representation.
Definition: channel.c:4418
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:150
#define ast_assert(a)
Definition: utils.h:695
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
Definition: cdr.c:3050
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
char * buf
Definition: func_cdr.c:214
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
const char * ast_cdr_disp2str(int disposition)
Disposition to a string.
Definition: cdr.c:3430
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
def info(msg)
const char * arguments
Definition: func_cdr.c:208
struct ast_channel * chan
Definition: func_cdr.c:206
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
Structure used to handle boolean flags.
Definition: utils.h:199
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
const char * ast_channel_name(const struct ast_channel *chan)
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:78
const char * cmd
Definition: func_cdr.c:207
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
size_t len
Definition: func_cdr.c:215
#define AST_APP_ARG(name)
Define an application argument.

◆ cdr_retrieve_time()

static struct timeval cdr_retrieve_time ( struct ast_channel chan,
const char *  time_name 
)
static

Definition at line 222 of file func_cdr.c.

References ast_cdr_format_var(), ast_cdr_getvar(), ast_channel_cdr(), ast_channel_name(), ast_log, AST_LOG_WARNING, ast_strlen_zero, NULL, and cdr_func_payload::value.

Referenced by cdr_read_callback().

223 {
224  struct timeval time = { 0 };
225  char *value = NULL;
226  char tempbuf[128];
227  long int tv_sec;
228  long int tv_usec;
229 
230  if (ast_strlen_zero(ast_channel_name(chan))) {
231  /* Format request on a dummy channel */
232  ast_cdr_format_var(ast_channel_cdr(chan), time_name, &value, tempbuf, sizeof(tempbuf), 1);
233  } else {
234  ast_cdr_getvar(ast_channel_name(chan), time_name, tempbuf, sizeof(tempbuf));
235  }
236 
237  /* time.tv_usec is suseconds_t, which could be int or long */
238  if (sscanf(tempbuf, "%ld.%ld", &tv_sec, &tv_usec) == 2) {
239  time.tv_sec = tv_sec;
240  time.tv_usec = tv_usec;
241  } else {
242  ast_log(AST_LOG_WARNING, "Failed to fully extract '%s' from CDR\n", time_name);
243  }
244 
245  return time;
246 }
struct ast_cdr * ast_channel_cdr(const struct ast_channel *chan)
int ast_cdr_getvar(const char *channel_name, const char *name, char *value, size_t length)
Retrieve a CDR variable from a channel&#39;s current CDR.
Definition: cdr.c:3324
#define AST_LOG_WARNING
Definition: logger.h:279
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
void ast_cdr_format_var(struct ast_cdr *cdr, const char *name, char **ret, char *workspace, int workspacelen, int raw)
Format a CDR variable from an already posted CDR.
Definition: cdr.c:3050
#define ast_log
Definition: astobj2.c:42
const char * ast_channel_name(const struct ast_channel *chan)

◆ cdr_write()

static int cdr_write ( struct ast_channel chan,
const char *  cmd,
char *  arguments,
const char *  value 
)
static

Definition at line 506 of file func_cdr.c.

References amaflags, ao2_alloc, ao2_ref, args, cdr_func_payload::arguments, AST_AMA_NONE, AST_APP_ARG, ast_cdr_message_router(), ast_channel_amaflags_set(), ast_channel_lock, ast_channel_name(), ast_channel_string2amaflag(), ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, cdr_func_payload::chan, cdr_func_payload::cmd, LOG_WARNING, NULL, options, parse(), router, stasis_message_create(), stasis_message_router_publish_sync(), and cdr_func_payload::value.

508 {
509  struct stasis_message *message;
510  struct cdr_func_payload *payload;
513  AST_APP_ARG(variable);
515  );
516  char *parse;
517 
518  if (!chan) {
519  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
520  return -1;
521  }
522  if (ast_strlen_zero(arguments)) {
523  ast_log(LOG_WARNING, "%s requires a variable (%s(variable)=value)\n)",
524  cmd, cmd);
525  return -1;
526  }
527  if (!value) {
528  ast_log(LOG_WARNING, "%s requires a value (%s(variable)=value)\n)",
529  cmd, cmd);
530  return -1;
531  }
532 
533  parse = ast_strdupa(arguments);
534  AST_STANDARD_APP_ARGS(args, parse);
535 
536  /* These CDR variables are no longer supported or set directly on the channel */
537  if (!strcasecmp(args.variable, "accountcode")) {
538  ast_log(LOG_WARNING, "Using the %s function to set 'accountcode' is deprecated. Please use the CHANNEL function instead.\n",
539  cmd);
540  ast_channel_lock(chan);
541  ast_channel_accountcode_set(chan, value);
542  ast_channel_unlock(chan);
543  return 0;
544  }
545  if (!strcasecmp(args.variable, "amaflags")) {
546  int amaflags;
547 
548  ast_log(LOG_WARNING, "Using the %s function to set 'amaflags' is deprecated. Please use the CHANNEL function instead.\n",
549  cmd);
550  if (isdigit(*value)) {
551  if (sscanf(value, "%30d", &amaflags) != 1) {
552  amaflags = AST_AMA_NONE;
553  }
554  } else {
555  amaflags = ast_channel_string2amaflag(value);
556  }
557  ast_channel_lock(chan);
558  ast_channel_amaflags_set(chan, amaflags);
559  ast_channel_unlock(chan);
560  return 0;
561  }
562  if (!strcasecmp(args.variable, "peeraccount")) {
563  ast_log(LOG_WARNING, "The 'peeraccount' setting is not supported. Please set the 'accountcode' on the appropriate channel using the CHANNEL function.\n");
564  return 0;
565  }
566 
567  /* The remaining CDR variables are handled by CDR processing code */
568  if (!cdr_write_message_type()) {
569  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: message type not available\n",
570  ast_channel_name(chan));
571  return -1;
572  }
573 
574  payload = ao2_alloc(sizeof(*payload), NULL);
575  if (!payload) {
576  return -1;
577  }
578  payload->chan = chan;
579  payload->cmd = cmd;
580  payload->arguments = arguments;
581  payload->value = value;
582 
583  message = stasis_message_create(cdr_write_message_type(), payload);
584  ao2_ref(payload, -1);
585  if (!message) {
586  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: unable to create message\n",
587  ast_channel_name(chan));
588  return -1;
589  }
590  router = ast_cdr_message_router();
591  if (!router) {
592  ast_log(LOG_WARNING, "Failed to manipulate CDR for channel %s: no message router\n",
593  ast_channel_name(chan));
594  ao2_ref(message, -1);
595  return -1;
596  }
597  stasis_message_router_publish_sync(router, message);
598  ao2_ref(router, -1);
599  ao2_ref(message, -1);
600 
601  return 0;
602 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static int amaflags
Definition: chan_iax2.c:431
static struct stasis_message_router * router
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
void stasis_message_router_publish_sync(struct stasis_message_router *router, struct stasis_message *message)
Publish a message to a message router&#39;s subscription synchronously.
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
Definition: channel.c:4405
#define ast_log
Definition: astobj2.c:42
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
#define ao2_ref(o, delta)
Definition: astobj2.h:464
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
void ast_channel_amaflags_set(struct ast_channel *chan, enum ama_flags value)
struct stasis_message * stasis_message_create(struct stasis_message_type *type, void *data)
Create a new message.
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:411
#define ast_channel_unlock(chan)
Definition: channel.h:2946
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
const char * arguments
Definition: func_cdr.c:208
struct ast_channel * chan
Definition: func_cdr.c:206
const char * ast_channel_name(const struct ast_channel *chan)
const char * value
Definition: func_cdr.c:209
const char * cmd
Definition: func_cdr.c:207
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ cdr_write_callback()

static void cdr_write_callback ( void *  data,
struct stasis_subscription sub,
struct stasis_message message 
)
static

Definition at line 357 of file func_cdr.c.

References args, cdr_func_payload::arguments, AST_APP_ARG, ast_app_parse_options(), ast_assert, ast_cdr_setuserfield(), ast_cdr_setvar(), ast_channel_name(), AST_DECLARE_APP_ARGS, AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero, cdr_func_options, cdr_func_payload::chan, NULL, options, parse(), stasis_message_data(), stasis_message_type(), and cdr_func_payload::value.

Referenced by load_module().

358 {
359  struct cdr_func_payload *payload;
360  struct ast_flags flags = { 0 };
362  AST_APP_ARG(variable);
364  );
365  char *parse;
366 
367  if (cdr_write_message_type() != stasis_message_type(message)) {
368  return;
369  }
370  payload = stasis_message_data(message);
371  if (!payload) {
372  return;
373  }
374  if (ast_strlen_zero(payload->arguments)
375  || !payload->value) {
376  /* Sanity check. cdr_write() could never send these bad messages */
377  ast_assert(0);
378  return;
379  }
380 
381  parse = ast_strdupa(payload->arguments);
382  AST_STANDARD_APP_ARGS(args, parse);
383 
384  if (!ast_strlen_zero(args.options)) {
385  ast_app_parse_options(cdr_func_options, &flags, NULL, args.options);
386  }
387 
388  /* These are already handled by cdr_write() */
389  ast_assert(strcasecmp(args.variable, "accountcode")
390  && strcasecmp(args.variable, "peeraccount")
391  && strcasecmp(args.variable, "amaflags"));
392 
393  if (!strcasecmp(args.variable, "userfield")) {
394  ast_cdr_setuserfield(ast_channel_name(payload->chan), payload->value);
395  } else {
396  ast_cdr_setvar(ast_channel_name(payload->chan), args.variable, payload->value);
397  }
398 }
int ast_cdr_setvar(const char *channel_name, const char *name, const char *value)
Set a variable on a CDR.
Definition: cdr.c:3178
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
static const struct ast_app_option cdr_func_options[128]
Definition: func_cdr.c:203
unsigned int flags
Definition: utils.h:200
struct stasis_message_type * stasis_message_type(const struct stasis_message *msg)
Get the message type for a stasis_message.
#define ast_assert(a)
Definition: utils.h:695
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
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
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
const char * arguments
Definition: func_cdr.c:208
struct ast_channel * chan
Definition: func_cdr.c:206
void ast_cdr_setuserfield(const char *channel_name, const char *userfield)
Set CDR user field for channel (stored in CDR)
Definition: cdr.c:3477
Structure used to handle boolean flags.
Definition: utils.h:199
const char * ast_channel_name(const struct ast_channel *chan)
const char * value
Definition: func_cdr.c:209
static struct test_options options
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ load_module()

static int load_module ( void  )
static

Definition at line 679 of file func_cdr.c.

References ao2_cleanup, ast_cdr_message_router(), ast_custom_function_register, AST_MODFLAG_DEFAULT, AST_MODULE_INFO(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, AST_MODULE_SUPPORT_CORE, ASTERISK_GPL_KEY, cdr_prop_write_callback(), cdr_read_callback(), cdr_write_callback(), NULL, RAII_VAR, router, stasis_message_router_add(), STASIS_MESSAGE_TYPE_INIT, and unload_module().

680 {
682  int res = 0;
683 
684  if (!router) {
686  }
687 
688  res |= STASIS_MESSAGE_TYPE_INIT(cdr_read_message_type);
689  res |= STASIS_MESSAGE_TYPE_INIT(cdr_write_message_type);
690  res |= STASIS_MESSAGE_TYPE_INIT(cdr_prop_write_message_type);
693  res |= stasis_message_router_add(router, cdr_prop_write_message_type(),
695  res |= stasis_message_router_add(router, cdr_write_message_type(),
697  res |= stasis_message_router_add(router, cdr_read_message_type(),
699 
700  if (res) {
701  unload_module();
703  }
705 }
static int unload_module(void)
Definition: func_cdr.c:660
static struct stasis_message_router * router
static struct ast_custom_function cdr_prop_function
Definition: func_cdr.c:654
int stasis_message_router_add(struct stasis_message_router *router, struct stasis_message_type *message_type, stasis_subscription_cb callback, void *data)
Add a route to a message router.
#define STASIS_MESSAGE_TYPE_INIT(name)
Boiler-plate messaging macro for initializing message types.
Definition: stasis.h:1501
#define NULL
Definition: resample.c:96
static void cdr_prop_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:400
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
Module has failed to load, may be in an inconsistent state.
Definition: module.h:78
static void cdr_read_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:248
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static void cdr_write_callback(void *data, struct stasis_subscription *sub, struct stasis_message *message)
Definition: func_cdr.c:357
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508
static struct ast_custom_function cdr_function
Definition: func_cdr.c:648

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [1/3]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( cdr_read_message_type  )

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [2/3]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( cdr_write_message_type  )

◆ STASIS_MESSAGE_TYPE_DEFN_LOCAL() [3/3]

STASIS_MESSAGE_TYPE_DEFN_LOCAL ( cdr_prop_write_message_type  )

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 660 of file func_cdr.c.

References ao2_cleanup, ast_cdr_message_router(), ast_custom_function_unregister(), RAII_VAR, router, stasis_message_router_remove(), and STASIS_MESSAGE_TYPE_CLEANUP.

Referenced by load_module().

661 {
663  int res = 0;
664 
665  if (router) {
666  stasis_message_router_remove(router, cdr_prop_write_message_type());
667  stasis_message_router_remove(router, cdr_write_message_type());
668  stasis_message_router_remove(router, cdr_read_message_type());
669  }
670  STASIS_MESSAGE_TYPE_CLEANUP(cdr_read_message_type);
671  STASIS_MESSAGE_TYPE_CLEANUP(cdr_write_message_type);
672  STASIS_MESSAGE_TYPE_CLEANUP(cdr_prop_write_message_type);
675 
676  return res;
677 }
static struct stasis_message_router * router
static struct ast_custom_function cdr_prop_function
Definition: func_cdr.c:654
#define STASIS_MESSAGE_TYPE_CLEANUP(name)
Boiler-plate messaging macro for cleaning up message types.
Definition: stasis.h:1523
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
struct stasis_message_router * ast_cdr_message_router(void)
Return the message router for the CDR engine.
Definition: cdr.c:4291
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:911
void stasis_message_router_remove(struct stasis_message_router *router, struct stasis_message_type *message_type)
Remove a route from a message router.
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
static struct ast_custom_function cdr_function
Definition: func_cdr.c:648

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Call Detail Record (CDR) dialplan functions" , .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 = "30ef0c93b36035ec78c9cfd712d36d9b" , .support_level = AST_MODULE_SUPPORT_CORE, .load = load_module, .unload = unload_module, .requires = "cdr", }
static

Definition at line 712 of file func_cdr.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 712 of file func_cdr.c.

◆ cdr_func_options

const struct ast_app_option cdr_func_options[128] = { [ 'f' ] = { .flag = OPT_FLOAT }, [ 'u' ] = { .flag = OPT_UNPARSED }, }
static

Definition at line 203 of file func_cdr.c.

Referenced by cdr_read_callback(), and cdr_write_callback().

◆ cdr_function

struct ast_custom_function cdr_function
static
Initial value:
= {
.name = "CDR",
.read = cdr_read,
.write = cdr_write,
}
static int cdr_write(struct ast_channel *chan, const char *cmd, char *arguments, const char *value)
Definition: func_cdr.c:506
static int cdr_read(struct ast_channel *chan, const char *cmd, char *parse, char *buf, size_t len)
Definition: func_cdr.c:448

Definition at line 648 of file func_cdr.c.

◆ cdr_prop_function

struct ast_custom_function cdr_prop_function
static
Initial value:
= {
.name = "CDR_PROP",
.read = NULL,
.write = cdr_prop_write,
}
#define NULL
Definition: resample.c:96
static int cdr_prop_write(struct ast_channel *chan, const char *cmd, char *parse, const char *value)
Definition: func_cdr.c:604

Definition at line 654 of file func_cdr.c.