111
111
to undisable (enable) CDR for a call.</para>
112
112
</description>
113
113
</configOption>
114
+ <configOption name="ignorestatechanges" default="no">
115
+ <synopsis>Whether CDR is updated or forked by bridging changes.</synopsis>
116
+ <description><para>Define whether or not CDR should be updated by bridging changes.
117
+ This includes entering and leaving bridges and call parking.</para>
118
+ <para>If this is set to "no", bridging changes will be ignored for all CDRs.
119
+ This should only be done if these events should not affect CDRs and are undesired,
120
+ such as to use a single CDR for the lifetime of the channel.</para>
121
+ <para>This setting cannot be changed on a reload.</para>
122
+ </description>
123
+ </configOption>
124
+ <configOption name="ignoredialchanges" default="no">
125
+ <synopsis>Whether CDR is updated or forked by dial updates.</synopsis>
126
+ <description><para>Define whether or not CDR should be updated by dial updates.</para>
127
+ <para>If this is set to "no", a single CDR will be used for the channel, even if
128
+ multiple endpoints or destinations are dialed sequentially. Note that you will also
129
+ lose detailed nonanswer dial dispositions if this option is enabled, which may not be acceptable,
130
+ e.g. instead of detailed no-answer dispositions like BUSY and CONGESTION, the disposition
131
+ will always be NO ANSWER if the channel was unanswered (it will still be ANSWERED
132
+ if the channel was answered).</para>
133
+ <para>This option should be enabled if a single CDR is desired for the lifetime of
134
+ the channel.</para>
135
+ </description>
136
+ </configOption>
114
137
<configOption name="unanswered">
115
138
<synopsis>Log calls that are never answered and don't set an outgoing party.</synopsis>
116
139
<description><para>
208
231
#define DEFAULT_END_BEFORE_H_EXTEN "1"
209
232
#define DEFAULT_INITIATED_SECONDS "0"
210
233
#define DEFAULT_CHANNEL_ENABLED "1"
234
+ #define DEFAULT_IGNORE_STATE_CHANGES "0"
235
+ #define DEFAULT_IGNORE_DIAL_CHANGES "0"
211
236
212
237
#define DEFAULT_BATCH_SIZE "100"
213
238
#define MAX_BATCH_SIZE 1000
222
247
} while (0)
223
248
224
249
static int cdr_debug_enabled ;
250
+ static int dial_changes_ignored ;
225
251
226
252
#define CDR_DEBUG (fmt , ...) \
227
253
do { \
@@ -2170,6 +2196,10 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
2170
2196
if (!it_cdr -> fn_table -> process_dial_begin ) {
2171
2197
continue ;
2172
2198
}
2199
+ if (dial_changes_ignored ) {
2200
+ CDR_DEBUG ("%p - Ignoring Dial Begin message\n" , it_cdr );
2201
+ continue ;
2202
+ }
2173
2203
CDR_DEBUG ("%p - Processing Dial Begin message for channel %s, peer %s\n" ,
2174
2204
it_cdr ,
2175
2205
caller ? caller -> base -> name : "(none)" ,
@@ -2181,6 +2211,12 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
2181
2211
if (!it_cdr -> fn_table -> process_dial_end ) {
2182
2212
continue ;
2183
2213
}
2214
+ if (dial_changes_ignored ) {
2215
+ /* Set the disposition, and do nothing else. */
2216
+ it_cdr -> disposition = dial_status_to_disposition (dial_status );
2217
+ CDR_DEBUG ("%p - Setting disposition and that's it (%s)\n" , it_cdr , dial_status );
2218
+ continue ;
2219
+ }
2184
2220
CDR_DEBUG ("%p - Processing Dial End message for channel %s, peer %s\n" ,
2185
2221
it_cdr ,
2186
2222
caller ? caller -> base -> name : "(none)" ,
@@ -2192,15 +2228,19 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
2192
2228
}
2193
2229
}
2194
2230
2195
- /* If no CDR handled a dial begin message, make a new one */
2196
- if (res && ast_strlen_zero (dial_status )) {
2197
- struct cdr_object * new_cdr ;
2231
+ /* If we're ignoring dial changes, don't allow multiple CDRs for this channel. */
2232
+ if (!dial_changes_ignored ) {
2233
+ /* If no CDR handled a dial begin message, make a new one */
2234
+ if (res && ast_strlen_zero (dial_status )) {
2235
+ struct cdr_object * new_cdr ;
2198
2236
2199
- new_cdr = cdr_object_create_and_append (cdr , stasis_message_timestamp (message ));
2200
- if (new_cdr ) {
2201
- new_cdr -> fn_table -> process_dial_begin (new_cdr , caller , peer );
2237
+ new_cdr = cdr_object_create_and_append (cdr , stasis_message_timestamp (message ));
2238
+ if (new_cdr ) {
2239
+ new_cdr -> fn_table -> process_dial_begin (new_cdr , caller , peer );
2240
+ }
2202
2241
}
2203
2242
}
2243
+
2204
2244
ao2_unlock (cdr );
2205
2245
ao2_cleanup (cdr );
2206
2246
}
@@ -4200,6 +4240,8 @@ static char *handle_cli_status(struct ast_cli_entry *e, int cmd, struct ast_cli_
4200
4240
ast_cli (a -> fd , " Log calls by default: %s\n" , ast_test_flag (& mod_cfg -> general -> settings , CDR_CHANNEL_DEFAULT_ENABLED ) ? "Yes" : "No" );
4201
4241
ast_cli (a -> fd , " Log unanswered calls: %s\n" , ast_test_flag (& mod_cfg -> general -> settings , CDR_UNANSWERED ) ? "Yes" : "No" );
4202
4242
ast_cli (a -> fd , " Log congestion: %s\n\n" , ast_test_flag (& mod_cfg -> general -> settings , CDR_CONGESTION ) ? "Yes" : "No" );
4243
+ ast_cli (a -> fd , " Ignore bridging changes: %s\n\n" , ast_test_flag (& mod_cfg -> general -> settings , CDR_IGNORE_STATE_CHANGES ) ? "Yes" : "No" );
4244
+ ast_cli (a -> fd , " Ignore dial state changes: %s\n\n" , ast_test_flag (& mod_cfg -> general -> settings , CDR_IGNORE_DIAL_CHANGES ) ? "Yes" : "No" );
4203
4245
if (ast_test_flag (& mod_cfg -> general -> settings , CDR_BATCHMODE )) {
4204
4246
ast_cli (a -> fd , "* Batch Mode Settings\n" );
4205
4247
ast_cli (a -> fd , " -------------------\n" );
@@ -4379,6 +4421,8 @@ static int process_config(int reload)
4379
4421
aco_option_register (& cfg_info , "size" , ACO_EXACT , general_options , DEFAULT_BATCH_SIZE , OPT_UINT_T , PARSE_IN_RANGE , FLDSET (struct ast_cdr_config , batch_settings .size ), 0 , MAX_BATCH_SIZE );
4380
4422
aco_option_register (& cfg_info , "time" , ACO_EXACT , general_options , DEFAULT_BATCH_TIME , OPT_UINT_T , PARSE_IN_RANGE , FLDSET (struct ast_cdr_config , batch_settings .time ), 1 , MAX_BATCH_TIME );
4381
4423
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 );
4424
+ 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 );
4425
+ 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 );
4382
4426
}
4383
4427
4384
4428
if (aco_process_config (& cfg_info , reload ) == ACO_PROCESS_ERROR ) {
@@ -4541,6 +4585,7 @@ static int unload_module(void)
4541
4585
4542
4586
static int load_module (void )
4543
4587
{
4588
+ struct module_config * mod_cfg = NULL ;
4544
4589
if (process_config (0 )) {
4545
4590
return AST_MODULE_LOAD_FAILURE ;
4546
4591
}
@@ -4561,13 +4606,36 @@ static int load_module(void)
4561
4606
return AST_MODULE_LOAD_FAILURE ;
4562
4607
}
4563
4608
4609
+ mod_cfg = ao2_global_obj_ref (module_configs );
4610
+
4564
4611
stasis_message_router_add (stasis_router , ast_channel_snapshot_type (), handle_channel_snapshot_update_message , NULL );
4612
+
4613
+ /* Always process dial messages, because even if we ignore most of it, we do want the dial status for the disposition. */
4565
4614
stasis_message_router_add (stasis_router , ast_channel_dial_type (), handle_dial_message , NULL );
4566
- stasis_message_router_add (stasis_router , ast_channel_entered_bridge_type (), handle_bridge_enter_message , NULL );
4567
- stasis_message_router_add (stasis_router , ast_channel_left_bridge_type (), handle_bridge_leave_message , NULL );
4568
- stasis_message_router_add (stasis_router , ast_parked_call_type (), handle_parked_call_message , NULL );
4615
+ if (!mod_cfg || !ast_test_flag (& mod_cfg -> general -> settings , CDR_IGNORE_DIAL_CHANGES )) {
4616
+ dial_changes_ignored = 0 ;
4617
+ } else {
4618
+ dial_changes_ignored = 1 ;
4619
+ CDR_DEBUG ("Dial messages will be mostly ignored\n" );
4620
+ }
4621
+
4622
+ /* If explicitly instructed to ignore call state changes, then ignore bridging events, parking, etc. */
4623
+ if (!mod_cfg || !ast_test_flag (& mod_cfg -> general -> settings , CDR_IGNORE_STATE_CHANGES )) {
4624
+ stasis_message_router_add (stasis_router , ast_channel_entered_bridge_type (), handle_bridge_enter_message , NULL );
4625
+ stasis_message_router_add (stasis_router , ast_channel_left_bridge_type (), handle_bridge_leave_message , NULL );
4626
+ stasis_message_router_add (stasis_router , ast_parked_call_type (), handle_parked_call_message , NULL );
4627
+ } else {
4628
+ CDR_DEBUG ("All bridge and parking messages will be ignored\n" );
4629
+ }
4630
+
4569
4631
stasis_message_router_add (stasis_router , cdr_sync_message_type (), handle_cdr_sync_message , NULL );
4570
4632
4633
+ if (mod_cfg ) {
4634
+ ao2_cleanup (mod_cfg );
4635
+ } else {
4636
+ ast_log (LOG_WARNING , "Unable to obtain CDR configuration during module load?\n" );
4637
+ }
4638
+
4571
4639
active_cdrs_master = ao2_container_alloc_hash (AO2_ALLOC_OPT_LOCK_MUTEX , 0 ,
4572
4640
AST_NUM_CHANNEL_BUCKETS , cdr_master_hash_fn , NULL , cdr_master_cmp_fn );
4573
4641
if (!active_cdrs_master ) {
0 commit comments