mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-12 15:45:18 +00:00
main/cdr: Allow modules to modify CDR fields before dispatching them
This patch adds the functions ast_cdr_modifier_register() ast_cdr_modifier_unregister() That work much like ast_cdr_register() and ast_cdr_unregister(). Modules registered will be given a chance to modify (or to do whatever they want) CDR fields just before they are passed to registered engines. Thus, for instance, if a module change the "userfield" field of a CDR, the modified value will be passed to every registered CDR backend for logging. ASTERISK-25479 #close Change-Id: If11d8fd19ef89b1a66ecacf1201e10fcf86ccd56
This commit is contained in:
committed by
Joshua Colp
parent
b19860c03a
commit
77780790e0
@@ -535,6 +535,36 @@ int ast_cdr_backend_suspend(const char *name);
|
||||
*/
|
||||
int ast_cdr_backend_unsuspend(const char *name);
|
||||
|
||||
/*!
|
||||
* \brief Register a CDR modifier
|
||||
* \param name name associated with the particular CDR modifier
|
||||
* \param desc description of the CDR modifier
|
||||
* \param be function pointer to a CDR modifier
|
||||
*
|
||||
* Used to register a Call Detail Record modifier.
|
||||
*
|
||||
* This gives modules a chance to modify CDR fields before they are dispatched
|
||||
* to registered backends (odbc, syslog, etc).
|
||||
*
|
||||
* \note The *modified* CDR will be passed to **all** registered backends for
|
||||
* logging. For instance, if cdr_manager changes the CDR data, cdr_adaptive_odbc
|
||||
* will also get the modified CDR.
|
||||
*
|
||||
* \retval 0 on success.
|
||||
* \retval -1 on error
|
||||
*/
|
||||
int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be);
|
||||
|
||||
/*!
|
||||
* \brief Unregister a CDR modifier
|
||||
* \param name name of CDR modifier to unregister
|
||||
* Unregisters a CDR modifier by its name
|
||||
*
|
||||
* \retval 0 The modifier unregistered successfully
|
||||
* \retval -1 The modifier could not be unregistered at this time
|
||||
*/
|
||||
int ast_cdr_modifier_unregister(const char *name);
|
||||
|
||||
/*!
|
||||
* \brief Disposition to a string
|
||||
* \param disposition input binary form
|
||||
|
56
main/cdr.c
56
main/cdr.c
@@ -297,6 +297,9 @@ struct cdr_beitem {
|
||||
/*! \brief List of registered backends */
|
||||
static AST_RWLIST_HEAD_STATIC(be_list, cdr_beitem);
|
||||
|
||||
/*! \brief List of registered modifiers */
|
||||
static AST_RWLIST_HEAD_STATIC(mo_list, cdr_beitem);
|
||||
|
||||
/*! \brief Queued CDR waiting to be batched */
|
||||
struct cdr_batch_item {
|
||||
struct ast_cdr *cdr;
|
||||
@@ -2678,7 +2681,7 @@ int ast_cdr_backend_unsuspend(const char *name)
|
||||
return success;
|
||||
}
|
||||
|
||||
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
|
||||
static int cdr_generic_register(struct be_list *generic_list, const char *name, const char *desc, ast_cdrbe be)
|
||||
{
|
||||
struct cdr_beitem *i = NULL;
|
||||
|
||||
@@ -2690,11 +2693,11 @@ int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_RWLIST_WRLOCK(&be_list);
|
||||
AST_RWLIST_TRAVERSE(&be_list, i, list) {
|
||||
AST_RWLIST_WRLOCK(generic_list);
|
||||
AST_RWLIST_TRAVERSE(generic_list, i, list) {
|
||||
if (!strcasecmp(name, i->name)) {
|
||||
ast_log(LOG_WARNING, "Already have a CDR backend called '%s'\n", name);
|
||||
AST_RWLIST_UNLOCK(&be_list);
|
||||
AST_RWLIST_UNLOCK(generic_list);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -2706,40 +2709,50 @@ int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
|
||||
ast_copy_string(i->name, name, sizeof(i->name));
|
||||
ast_copy_string(i->desc, desc, sizeof(i->desc));
|
||||
|
||||
AST_RWLIST_INSERT_HEAD(&be_list, i, list);
|
||||
AST_RWLIST_UNLOCK(&be_list);
|
||||
AST_RWLIST_INSERT_HEAD(generic_list, i, list);
|
||||
AST_RWLIST_UNLOCK(generic_list);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_cdr_unregister(const char *name)
|
||||
int ast_cdr_register(const char *name, const char *desc, ast_cdrbe be)
|
||||
{
|
||||
return cdr_generic_register(&be_list, name, desc, be);
|
||||
}
|
||||
|
||||
int ast_cdr_modifier_register(const char *name, const char *desc, ast_cdrbe be)
|
||||
{
|
||||
return cdr_generic_register((struct be_list *)&mo_list, name, desc, be);
|
||||
}
|
||||
|
||||
static int ast_cdr_generic_unregister(struct be_list *generic_list, const char *name)
|
||||
{
|
||||
struct cdr_beitem *match = NULL;
|
||||
int active_count;
|
||||
|
||||
AST_RWLIST_WRLOCK(&be_list);
|
||||
AST_RWLIST_TRAVERSE(&be_list, match, list) {
|
||||
AST_RWLIST_WRLOCK(generic_list);
|
||||
AST_RWLIST_TRAVERSE(generic_list, match, list) {
|
||||
if (!strcasecmp(name, match->name)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match) {
|
||||
AST_RWLIST_UNLOCK(&be_list);
|
||||
AST_RWLIST_UNLOCK(generic_list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
active_count = ao2_container_count(active_cdrs_by_channel);
|
||||
|
||||
if (!match->suspended && active_count != 0) {
|
||||
AST_RWLIST_UNLOCK(&be_list);
|
||||
AST_RWLIST_UNLOCK(generic_list);
|
||||
ast_log(AST_LOG_WARNING, "Unable to unregister CDR backend %s; %d CDRs are still active\n",
|
||||
name, active_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
AST_RWLIST_REMOVE(&be_list, match, list);
|
||||
AST_RWLIST_UNLOCK(&be_list);
|
||||
AST_RWLIST_REMOVE(generic_list, match, list);
|
||||
AST_RWLIST_UNLOCK(generic_list);
|
||||
|
||||
ast_verb(2, "Unregistered '%s' CDR backend\n", name);
|
||||
ast_free(match);
|
||||
@@ -2747,6 +2760,16 @@ int ast_cdr_unregister(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ast_cdr_unregister(const char *name)
|
||||
{
|
||||
return ast_cdr_generic_unregister(&be_list, name);
|
||||
}
|
||||
|
||||
int ast_cdr_modifier_unregister(const char *name)
|
||||
{
|
||||
return ast_cdr_generic_unregister((struct be_list *)&mo_list, name);
|
||||
}
|
||||
|
||||
struct ast_cdr *ast_cdr_dup(struct ast_cdr *cdr)
|
||||
{
|
||||
struct ast_cdr *newcdr;
|
||||
@@ -3262,6 +3285,13 @@ static void post_cdr(struct ast_cdr *cdr)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Modify CDR's */
|
||||
AST_RWLIST_RDLOCK(&mo_list);
|
||||
AST_RWLIST_TRAVERSE(&mo_list, i, list) {
|
||||
i->be(cdr);
|
||||
}
|
||||
AST_RWLIST_UNLOCK(&mo_list);
|
||||
|
||||
if (ast_test_flag(cdr, AST_CDR_FLAG_DISABLE)) {
|
||||
continue;
|
||||
}
|
||||
|
Reference in New Issue
Block a user