mirror of
https://github.com/asterisk/asterisk.git
synced 2026-07-23 16:05:30 -07:00
242276bbaa
Several issues are resolved: * Internally, floats were used for timestamp values but this could result in wrapping so they've been changed to doubles. * Historically, the default CEL eventtime format is `<seconds>.<microseconds>` with `<microseconds>` always being 6 digits. This should have continued to be the case but res_cdrel_custom wasn't checking the `dateformat` setting in cel.conf and was defaulting to `%F %T`. res_cdrel_custom now gets the default date format from cel.conf, which will be whatever the `dateformat` parameter is set to or `<seconds>.<microseconds>` if not set. * The timeval field formatter for both CDR and CEL wasn't handling custom strftime format strings correctly. This is now fixed so you should be able to specifiy custom strftime format strings for the CEL `eventtime` and CDR `start`, `answer` and `end` fields. For example: `eventtime(%FT%T%z)`. Resolves: #1844 Resolves: #1845
117 lines
3.6 KiB
C
117 lines
3.6 KiB
C
/*
|
|
* Asterisk -- An open source telephony toolkit.
|
|
*
|
|
* Copyright (C) 2026, Sangoma Technologies Corporation
|
|
*
|
|
* George Joseph <gjoseph@sangoma.com>
|
|
*
|
|
* See http://www.asterisk.org for more information about
|
|
* the Asterisk project. Please do not directly contact
|
|
* any of the maintainers of this project for assistance;
|
|
* the project provides a web site, mailing lists and IRC
|
|
* channels for your use.
|
|
*
|
|
* This program is free software, distributed under the terms of
|
|
* the GNU General Public License Version 2. See the LICENSE file
|
|
* at the top of the source tree.
|
|
*/
|
|
|
|
/*!
|
|
* \file
|
|
* \author George Joseph <gjoseph@sangoma.com>
|
|
*
|
|
* \brief CDR Getters
|
|
*
|
|
*/
|
|
|
|
#include "cdrel.h"
|
|
#include "asterisk/cdr.h"
|
|
|
|
static int cdr_get_string(void *record, struct cdrel_config *config,
|
|
struct cdrel_field *field, struct cdrel_value *value)
|
|
{
|
|
struct ast_cdr *cdr = record;
|
|
value->data_type = field->input_data_type;
|
|
value->field_name = field->name;
|
|
value->values.string = CDR_FIELD(cdr, field->field_id);
|
|
return 0;
|
|
}
|
|
|
|
#define DEFINE_CDR_GETTER(_sname, _ename, _type) \
|
|
static int cdr_get_ ## _ename (void *record, struct cdrel_config *config, \
|
|
struct cdrel_field *field, struct cdrel_value *value) \
|
|
{ \
|
|
struct ast_cdr *cdr = record; \
|
|
value->data_type = field->input_data_type; \
|
|
value->field_name = field->name; \
|
|
value->values._sname = *(_type *)CDR_FIELD(cdr, field->field_id); \
|
|
return 0; \
|
|
}\
|
|
|
|
DEFINE_CDR_GETTER(int32, int32, int32_t)
|
|
DEFINE_CDR_GETTER(uint32, uint32, uint32_t)
|
|
DEFINE_CDR_GETTER(int64, int64, int64_t)
|
|
DEFINE_CDR_GETTER(uint64, uint64, uint64_t)
|
|
DEFINE_CDR_GETTER(tv, timeval, struct timeval)
|
|
DEFINE_CDR_GETTER(doubler, double, double)
|
|
|
|
static int cdr_get_literal(void *record, struct cdrel_config *config,
|
|
struct cdrel_field *field, struct cdrel_value *value)
|
|
{
|
|
value->data_type = cdrel_type_string;
|
|
value->field_name = field->name;
|
|
value->values.string = field->data;
|
|
return 0;
|
|
}
|
|
|
|
static int cdr_get_uservar(void *record, struct cdrel_config *config,
|
|
struct cdrel_field *field, struct cdrel_value *value)
|
|
{
|
|
struct ast_cdr *cdr = record;
|
|
struct ast_var_t *variables;
|
|
const char *rtn = NULL;
|
|
|
|
value->data_type = cdrel_type_string;
|
|
value->field_name = field->name;
|
|
AST_LIST_TRAVERSE(&cdr->varshead, variables, entries) {
|
|
if (strcasecmp(field->data, ast_var_name(variables)) == 0) {
|
|
rtn = ast_var_value(variables);
|
|
}
|
|
}
|
|
|
|
value->values.string = (char *)S_OR(rtn, "");
|
|
return 0;
|
|
}
|
|
|
|
static struct ast_channel *dummy_chan_alloc_cdr(struct cdrel_config *config, void *data)
|
|
{
|
|
struct ast_cdr *cdr = data;
|
|
struct ast_channel *dummy = NULL;
|
|
|
|
dummy = ast_dummy_channel_alloc();
|
|
if (!dummy) {
|
|
ast_log(LOG_ERROR, "Unable to fabricate channel from CDR for '%s'\n",
|
|
config->output_filename);
|
|
return NULL;
|
|
}
|
|
ast_channel_cdr_set(dummy, ast_cdr_dup(cdr));
|
|
return dummy;
|
|
}
|
|
|
|
int load_cdr(void)
|
|
{
|
|
ast_debug(1, "Loading CDR getters\n");
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_string] = cdr_get_string;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_literal] = cdr_get_literal;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_int32] = cdr_get_int32;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_uint32] = cdr_get_uint32;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_int64] = cdr_get_int64;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_uint64] = cdr_get_uint64;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_timeval] = cdr_get_timeval;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_double] = cdr_get_double;
|
|
cdrel_field_getters[cdrel_record_cdr][cdrel_type_uservar] = cdr_get_uservar;
|
|
cdrel_dummy_channel_allocators[cdrel_record_cdr] = dummy_chan_alloc_cdr;
|
|
|
|
return 0;
|
|
}
|