|
|
|
@ -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;
|
|
|
|
|
}
|
|
|
|
|