mirror of
https://github.com/asterisk/asterisk.git
synced 2026-07-22 14:34:09 -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
124 lines
7.7 KiB
C
124 lines
7.7 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/CEL field registry
|
|
*
|
|
*/
|
|
|
|
#include "cdrel.h"
|
|
|
|
#include "asterisk/json.h"
|
|
#include "asterisk/cdr.h"
|
|
#include "asterisk/cel.h"
|
|
|
|
/*!
|
|
* \internal
|
|
* \brief Helper macro that populates the static array of cdrel_fields.
|
|
*
|
|
* \param _record_type The type of record: CDR or CEL.
|
|
* \param _field_id For CEL, it's the event field. For CDR it's one of cdr_field_id.
|
|
* \param _name The field name.
|
|
* \param _input_type The input data type. Drives the getters.
|
|
* \param output_types An array of types, one each for dsv, json and sql. Drives the formatters.
|
|
* \param _mallocd Not used.
|
|
*/
|
|
#define REGISTER_FIELD(_record_type, _field_id, _name, _input_type, _output_type) \
|
|
{ _record_type, _field_id, _name, _input_type, _output_type, { 0 } }
|
|
|
|
static const struct cdrel_field cdrel_field_registry[] = {
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_ENUM, "eventenum", cdrel_type_event_enum, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TYPE, "eventtype", cdrel_type_event_type, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TIME, "eventtime", cdrel_type_timeval, cdrel_type_cel_timefmt),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EVENT_TIME_USEC, "eventtimeusec", cdrel_type_uint32, cdrel_type_uint32),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_USEREVENT_NAME, "usereventname", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_USEREVENT_NAME, "userdeftype", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CIDNAME, "name", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CIDNUM, "num", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EXTEN, "exten", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CONTEXT, "context", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CHANNAME, "channame", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_APPNAME, "appname", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_APPDATA, "appdata", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_AMAFLAGS, "amaflags", cdrel_type_uint32, cdrel_type_uint32),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_ACCTCODE, "accountcode", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_UNIQUEID, "uniqueid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_USERFIELD, "userfield", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CIDANI, "ani", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CIDRDNIS, "rdnis", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_CIDDNID, "dnid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_PEER, "peer", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_PEER, "bridgepeer", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_LINKEDID, "linkedid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_PEERACCT, "peeraccount", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_EXTRA, "eventextra", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_TENANTID, "tenantid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cel, AST_EVENT_IE_CEL_LITERAL, "literal", cdrel_type_literal, cdrel_type_string),
|
|
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_clid, "clid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_src, "src", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_dst, "dst", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_dcontext, "dcontext", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_channel, "channel", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_dstchannel, "dstchannel", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_lastapp, "lastapp", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_lastdata, "lastdata", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_start, "start", cdrel_type_timeval, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_answer, "answer", cdrel_type_timeval, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_end, "end", cdrel_type_timeval, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_duration, "duration", cdrel_type_int64, cdrel_type_int64),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_billsec, "billsec", cdrel_type_int64, cdrel_type_int64),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_disposition, "disposition", cdrel_type_int64, cdrel_type_disposition),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_amaflags, "amaflags", cdrel_type_int64, cdrel_type_amaflags),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_accountcode, "accountcode", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_peeraccount, "peeraccount", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_flags, "flags", cdrel_type_uint32, cdrel_type_uint32),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_uniqueid, "uniqueid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_linkedid, "linkedid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_tenantid, "tenantid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_peertenantid, "peertenantid", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_userfield, "userfield", cdrel_type_string, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_sequence, "sequence", cdrel_type_int32, cdrel_type_int32),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_varshead, "uservar", cdrel_type_uservar, cdrel_type_string),
|
|
REGISTER_FIELD(cdrel_record_cdr, cdr_field_literal, "literal", cdrel_type_literal, cdrel_type_string),
|
|
};
|
|
|
|
/*
|
|
* \internal
|
|
* \brief Get a cdrel_field structure by record type and field name.
|
|
*
|
|
* \param record_type The cdrel_record_type to search.
|
|
* \param name The field name to search for.
|
|
* \returns A pointer to a constant cdrel_field structure or NULL if not found.
|
|
* This pointer must never be freed.
|
|
*/
|
|
const struct cdrel_field *get_registered_field_by_name(enum cdrel_record_type type, const char *name)
|
|
{
|
|
int ix = 0;
|
|
|
|
for (ix = 0; ix < ARRAY_LEN(cdrel_field_registry); ix++) {
|
|
if (cdrel_field_registry[ix].record_type == type && strcasecmp(cdrel_field_registry[ix].name, name) == 0) {
|
|
return &cdrel_field_registry[ix];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|