]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
cdr: add CANCEL dispostion in CDR
authorzhou_jiajian <zhou_0611@163.com>
Thu, 24 Jul 2025 11:39:27 +0000 (19:39 +0800)
committerAsterisk Development Team <asteriskteam@digium.com>
Wed, 10 Sep 2025 19:52:59 +0000 (19:52 +0000)
In the original implementation, both CANCEL and NO ANSWER states were
consolidated under the NO ANSWER disposition. This patch introduces a
separate CANCEL disposition, with an optional configuration switch to
enable this new disposition.

Resolves: #1323

UserNote: A new CDR option "canceldispositionenabled" has been added
that when set to true, the NO ANSWER disposition will be split into
two dispositions: CANCEL and NO ANSWER. The default value is 'no'

(cherry picked from commit 9d4674d93d69acd9e2f4a09c2748838affbc1c74)

configs/samples/cdr.conf.sample
include/asterisk/cdr.h
main/cdr.c

index 46ddb96b7d7ea942f8ee03a0ccc778c73579165f..459a3861c1b9b3c870f5ddf36232f4b007dcb799 100644 (file)
 ; is "yes".
 ;safeshutdown=yes
 
+; Define if the CANCEL disposition state should be used.
+; When enabled, The NO ANSWER disposition will be split into two distinct 
+; dispositions: CANCEL and NO ANSWER.
+; The default value is "no".
+;canceldispositionenabled = no
+
 ;
 ;
 ; CHOOSING A CDR "BACKEND"  (what kind of output to generate)
index 788a8797204cab21f49f287b3ff8a249df29b777..14f644a2cd9e9fcdc061e376ba3d5563a7d2a1a7 100644 (file)
@@ -227,6 +227,7 @@ enum ast_cdr_settings {
        CDR_CHANNEL_DEFAULT_ENABLED = 1 << 7, /*!< Whether CDR is enabled for each channel by default */
        CDR_IGNORE_STATE_CHANGES = 1 << 8,      /*!< Whether to ignore bridge and other call state change events */
        CDR_IGNORE_DIAL_CHANGES = 1 << 9,       /*!< Whether to ignore dial state changes */
+       CDR_CANCEL_DISPOSITION_ENABLED = 1 << 10, /*!< Whether to enable CANCEL disposition in CDR */
 };
 
 /*! \brief CDR Batch Mode settings */
@@ -260,6 +261,7 @@ enum ast_cdr_disposition {
        AST_CDR_BUSY       = (1 << 2),
        AST_CDR_ANSWERED   = (1 << 3),
        AST_CDR_CONGESTION = (1 << 4),
+       AST_CDR_CANCEL     = (1 << 5),
 };
 
 
index d1bc516c16f3c33714d50dd321192d987b6e6dd3..1b936ea630b78bb2401939d41ceb0a8935a65a55 100644 (file)
                                        submission of CDR data during asterisk shutdown, set this to <literal>yes</literal>.</para>
                                        </description>
                                </configOption>
+                               <configOption name="canceldispositionenabled" default="no">
+                                       <synopsis>Whether to enable CANCEL disposition in CDR</synopsis>
+                                       <description><para>
+                                       Define if the CANCEL disposition state should be used.
+                                       When enabled, The NO ANSWER disposition will be split into two distinct dispositions: CANCEL and NO ANSWER.
+                                       </para>
+                                       </description>
+                               </configOption>
                        </configObject>
                </configFile>
        </configInfo>
@@ -1927,7 +1935,13 @@ static enum ast_cdr_disposition dial_status_to_disposition(const char *dial_stat
                return AST_CDR_ANSWERED;
        } else if (!strcmp(dial_status, "BUSY")) {
                return AST_CDR_BUSY;
-       } else if (!strcmp(dial_status, "CANCEL") || !strcmp(dial_status, "NOANSWER")) {
+       } else if (!strcmp(dial_status, "CANCEL")) {
+               if (!is_cdr_flag_set(CDR_CANCEL_DISPOSITION_ENABLED)) {
+                       return AST_CDR_NOANSWER;
+               } else {
+                       return AST_CDR_CANCEL;
+               }
+       } else if (!strcmp(dial_status, "NOANSWER")) {
                return AST_CDR_NOANSWER;
        } else if (!strcmp(dial_status, "CONGESTION")) {
                if (!is_cdr_flag_set(CDR_CONGESTION)) {
@@ -3574,6 +3588,8 @@ const char *ast_cdr_disp2str(int disposition)
                return "ANSWERED";
        case AST_CDR_CONGESTION:
                return "CONGESTION";
+       case AST_CDR_CANCEL:
+               return "CANCEL";
        }
        return "UNKNOWN";
 }
@@ -4312,6 +4328,7 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
                ast_cli(a->fd, "  Log congestion:             %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CONGESTION) ? "Yes" : "No");
                ast_cli(a->fd, "  Ignore bridging changes:    %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_STATE_CHANGES) ? "Yes" : "No");
                ast_cli(a->fd, "  Ignore dial state changes:  %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_IGNORE_DIAL_CHANGES) ? "Yes" : "No");
+               ast_cli(a->fd, "  Cancel disposition enabled: %s\n\n", ast_test_flag(&mod_cfg->general->settings, CDR_CANCEL_DISPOSITION_ENABLED) ? "Yes" : "No");
                if (ast_test_flag(&mod_cfg->general->settings, CDR_BATCHMODE)) {
                        ast_cli(a->fd, "* Batch Mode Settings\n");
                        ast_cli(a->fd, "  -------------------\n");
@@ -4493,6 +4510,7 @@ static int process_config(int reload)
                aco_option_register(&cfg_info, "channeldefaultenabled", ACO_EXACT, general_options, DEFAULT_CHANNEL_ENABLED, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_CHANNEL_DEFAULT_ENABLED);
                aco_option_register(&cfg_info, "ignorestatechanges", ACO_EXACT, general_options, DEFAULT_IGNORE_STATE_CHANGES, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_IGNORE_STATE_CHANGES);
                aco_option_register(&cfg_info, "ignoredialchanges", ACO_EXACT, general_options, DEFAULT_IGNORE_DIAL_CHANGES, OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_IGNORE_DIAL_CHANGES);
+               aco_option_register(&cfg_info, "canceldispositionenabled", ACO_EXACT, general_options, "0", OPT_BOOLFLAG_T, 1, FLDSET(struct ast_cdr_config, settings), CDR_CANCEL_DISPOSITION_ENABLED);
        }
 
        if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {