CDR: Improve handling of parking; resolve assertion when originating into park
authorMatthew Jordan <mjordan@digium.com>
Sat, 28 Sep 2013 20:55:48 +0000 (20:55 +0000)
committerMatthew Jordan <mjordan@digium.com>
Sat, 28 Sep 2013 20:55:48 +0000 (20:55 +0000)
This patch covers two problems:

1) Currently, when a call is transferred into a parking lot from a bridge
   (using either the blind transfer or one touch parking mechanisms), the
   application fails to be set to "Park" in the resulting CDR record for
   the parked channel. This is due to the ParkedCall message arriving before
   the BridgeEnter for the channel entering the parking bridge. The ParkedCall
   message isn't handled as the CDR for the channel has already been finalized
   (due to the channel having left its two party bridge), and the BridgeEnter -
   which creates the new CDR - doesn't have the parking information. This patch
   modifies the behavior so that reception of a ParkedCall message will - if
   not handled by a CDR chain - cause a new CDR to be created and put into the
   Parking state.

2) It fixes a FRACK that occurred when a channel is originated into a parking
   space. The DialedPending state - which occurs for both Dialed and Originated
   channels - assumed that it couldn't handle the parking transitions due to it
   having a Party B; however, Originated channels don't have a Party B. As such,
   the existing CDR needs to transition into the parking state - this patch does
   that.

Review: https://reviewboard.asterisk.org/r/2877/

(closes issue ASTERISK-22482)
Reported by: Richard Mudgett
........

Merged revisions 400062 from http://svn.asterisk.org/svn/asterisk/branches/12

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400063 65c4cc65-6c06-0410-ace0-fbb531ad65f3

main/cdr.c

index 9180c73..fb02d33 100644 (file)
@@ -1749,8 +1749,12 @@ static enum process_bridge_enter_results dialed_pending_state_process_bridge_ent
 
 static int dialed_pending_state_process_parking_bridge_enter(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
 {
-       /* We can't handle this as we have a Party B - ask for a new one */
-       return 1;
+       if (cdr->party_b.snapshot) {
+               /* We can't handle this as we have a Party B - ask for a new one */
+               return 1;
+       }
+       cdr_object_transition_state(cdr, &parked_state_fn_table);
+       return 0;
 }
 
 static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
@@ -2497,6 +2501,7 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s
        RAII_VAR(struct cdr_object *, cdr, NULL, ao2_cleanup);
        RAII_VAR(struct module_config *, mod_cfg,
                        ao2_global_obj_ref(module_configs), ao2_cleanup);
+       int unhandled = 1;
        struct cdr_object *it_cdr;
 
        /* Anything other than getting parked will be handled by other updates */
@@ -2524,7 +2529,18 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s
 
        for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
                if (it_cdr->fn_table->process_parked_channel) {
-                       it_cdr->fn_table->process_parked_channel(it_cdr, payload);
+                       unhandled &= it_cdr->fn_table->process_parked_channel(it_cdr, payload);
+               }
+       }
+
+       if (unhandled) {
+               /* Nothing handled the messgae - we need a new one! */
+               struct cdr_object *new_cdr = cdr_object_create_and_append(cdr);
+               if (new_cdr) {
+                       /* As the new CDR is created in the single state, it is guaranteed
+                        * to have a function for the parked call message and will handle
+                        * the message */
+                       new_cdr->fn_table->process_parked_channel(new_cdr, payload);
                }
        }