<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/10622">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Jenkins2: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">stasis: Segment channel snapshot to reduce creation cost.<br><br>When a channel snapshot was created it used to be done<br>from scratch, copying all data (many strings). This incurs<br>a cost when doing so.<br><br>This change segments the channel snapshot into different<br>components which can be reused if unchanged from the<br>previous snapshot creation, reducing the cost. In normal<br>cases this results in some pointers being copied with<br>reference count being bumped, some integers being set,<br>and a string or two copied. The other benefit is that it<br>is now possible to determine if a channel snapshot update<br>is redundant and thus stop it before a message is published<br>to stasis.<br><br>The specific segments in the channel snapshot were split up<br>based on whether they are changed together, how often they<br>are changed, and their general grouping. In practice only<br>1 (or 0) of the segments actually get changed in normal<br>operation.<br><br>Invalidation is done by setting a flag on the channel when<br>the segment source is changed, forcing creation of a new<br>segment when the channel snapshot is created.<br><br>ASTERISK-28119<br><br>Change-Id: I5d7ef3df963a88ac47bc187d73c5225c315f8423<br>---<br>M apps/app_queue.c<br>M channels/chan_pjsip.c<br>M channels/pjsip/cli_commands.c<br>M configs/samples/ari.conf.sample<br>M configs/samples/manager.conf.sample<br>M include/asterisk/channel.h<br>M include/asterisk/stasis_channels.h<br>M main/bridge.c<br>M main/cdr.c<br>M main/cel.c<br>M main/channel.c<br>M main/channel_internal_api.c<br>M main/cli.c<br>M main/core_local.c<br>M main/endpoints.c<br>M main/manager.c<br>M main/manager_bridges.c<br>M main/manager_channels.c<br>M main/stasis_bridges.c<br>M main/stasis_channels.c<br>M pbx/pbx_realtime.c<br>M res/ari/resource_bridges.c<br>M res/ari/resource_channels.c<br>M res/parking/parking_applications.c<br>M res/parking/parking_bridge_features.c<br>M res/res_chan_stats.c<br>M res/res_pjsip/pjsip_configuration.c<br>M res/res_pjsip_refer.c<br>M res/res_stasis.c<br>M res/stasis/app.c<br>M tests/test_cel.c<br>M tests/test_stasis_channels.c<br>32 files changed, 878 insertions(+), 470 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/apps/app_queue.c b/apps/app_queue.c</span><br><span>index 17e35f9..2e59bf6 100644</span><br><span>--- a/apps/app_queue.c</span><br><span>+++ b/apps/app_queue.c</span><br><span>@@ -5890,13 +5890,13 @@</span><br><span>     agent_blob = stasis_message_data(msg);</span><br><span> </span><br><span>   if (ast_channel_agent_login_type() == stasis_message_type(msg)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_queue_log("NONE", agent_blob->snapshot->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,</span><br><span>                       ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),</span><br><span style="color: hsl(0, 100%, 40%);">-                       "AGENTLOGIN", "%s", agent_blob->snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                    "AGENTLOGIN", "%s", agent_blob->snapshot->base->name);</span><br><span>  } else if (ast_channel_agent_logoff_type() == stasis_message_type(msg)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_queue_log("NONE", agent_blob->snapshot->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,</span><br><span>                       ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),</span><br><span style="color: hsl(0, 100%, 40%);">-                       "AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                        "AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->base->name,</span><br><span>                      (long) ast_json_integer_get(ast_json_object_get(agent_blob->blob, "logintime")));</span><br><span>       }</span><br><span> }</span><br><span>@@ -6088,8 +6088,8 @@</span><br><span>               ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);</span><br><span>              break;</span><br><span>       case AST_ATTENDED_TRANSFER_DEST_LINK:</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                                atxfer_msg->dest.links[1]->name);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                             atxfer_msg->dest.links[1]->base->name);</span><br><span>             break;</span><br><span>       case AST_ATTENDED_TRANSFER_DEST_THREEWAY:</span><br><span>    case AST_ATTENDED_TRANSFER_DEST_FAIL:</span><br><span>@@ -6098,7 +6098,7 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_queue_log(queue_data->queue->name, caller->uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_queue_log(queue_data->queue->name, caller->base->uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",</span><br><span>                    ast_str_buffer(transfer_str),</span><br><span>                        (long) (queue_data->starttime - queue_data->holdstart),</span><br><span>                        (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);</span><br><span>@@ -6131,11 +6131,11 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(enter_blob->channel->uniqueid, queue_data->caller_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!strcmp(enter_blob->channel->base->uniqueid, queue_data->caller_uniqueid)) {</span><br><span>                 ast_string_field_set(queue_data, bridge_uniqueid,</span><br><span>                            enter_blob->bridge->uniqueid);</span><br><span>                 ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                          enter_blob->channel->name, queue_data->bridge_uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                             enter_blob->channel->base->name, queue_data->bridge_uniqueid);</span><br><span>   }</span><br><span> }</span><br><span> </span><br><span>@@ -6186,7 +6186,7 @@</span><br><span>   context = transfer_msg->context;</span><br><span> </span><br><span>      ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_queue_log(queue_data->queue->name, caller_snapshot->base->uniqueid, queue_data->member->membername,</span><br><span>                    "BLINDTRANSFER", "%s|%s|%ld|%ld|%d",</span><br><span>                     exten, context,</span><br><span>                      (long) (queue_data->starttime - queue_data->holdstart),</span><br><span>@@ -6302,9 +6302,9 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {</span><br><span>              optimization = &queue_data->member_optimize;</span><br><span style="color: hsl(0, 100%, 40%);">-     } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {</span><br><span>               optimization = &queue_data->caller_optimize;</span><br><span>  } else {</span><br><span>             return;</span><br><span>@@ -6313,9 +6313,9 @@</span><br><span>      /* We only allow move-swap optimizations, so there had BETTER be a source */</span><br><span>         ast_assert(source != NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- optimization->source_chan_uniqueid = ast_strdup(source->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+      optimization->source_chan_uniqueid = ast_strdup(source->base->uniqueid);</span><br><span>    if (!optimization->source_chan_uniqueid) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->name);</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->base->name);</span><br><span>             return;</span><br><span>      }</span><br><span>    id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));</span><br><span>@@ -6354,10 +6354,10 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {</span><br><span>              optimization = &queue_data->member_optimize;</span><br><span>          is_caller = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-  } else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {</span><br><span>               optimization = &queue_data->caller_optimize;</span><br><span>          is_caller = 1;</span><br><span>       } else {</span><br><span>@@ -6420,16 +6420,16 @@</span><br><span>           return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {</span><br><span>              reason = CALLER;</span><br><span style="color: hsl(0, 100%, 40%);">-        } else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->member_uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {</span><br><span>               reason = AGENT;</span><br><span>      } else {</span><br><span>             ao2_unlock(queue_data);</span><br><span>              return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   chan = ast_channel_get_by_name(channel_blob->snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+   chan = ast_channel_get_by_name(channel_blob->snapshot->base->name);</span><br><span>         if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||</span><br><span>                      !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||</span><br><span>                   !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {</span><br><span>@@ -6446,9 +6446,9 @@</span><br><span>        ao2_unlock(queue_data);</span><br><span> </span><br><span>  ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",</span><br><span style="color: hsl(0, 100%, 40%);">-                  channel_blob->snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                  channel_blob->snapshot->base->name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_queue_log(queue_data->queue->name, caller_snapshot->base->uniqueid, queue_data->member->membername,</span><br><span>                    reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",</span><br><span>           (long) (queue_data->starttime - queue_data->holdstart),</span><br><span>                (long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);</span><br><span>diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c</span><br><span>index d0a74cd..e44f328 100644</span><br><span>--- a/channels/chan_pjsip.c</span><br><span>+++ b/channels/chan_pjsip.c</span><br><span>@@ -1169,7 +1169,7 @@</span><br><span>                         continue;</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (chan_pjsip_get_hold(snapshot->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             if (chan_pjsip_get_hold(snapshot->base->uniqueid)) {</span><br><span>                   ast_devstate_aggregate_add(&aggregate, AST_DEVICE_ONHOLD);</span><br><span>               } else {</span><br><span>                     ast_devstate_aggregate_add(&aggregate, ast_state_chan2dev(snapshot->state));</span><br><span>diff --git a/channels/pjsip/cli_commands.c b/channels/pjsip/cli_commands.c</span><br><span>index 9a8dc29..2ce2369 100644</span><br><span>--- a/channels/pjsip/cli_commands.c</span><br><span>+++ b/channels/pjsip/cli_commands.c</span><br><span>@@ -61,13 +61,13 @@</span><br><span> </span><br><span>       switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         right_key = right_obj->name;</span><br><span style="color: hsl(120, 100%, 40%);">+               right_key = right_obj->base->name;</span><br><span>             /* Fall through */</span><br><span>   case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strcmp(left_obj->name, right_key);</span><br><span style="color: hsl(120, 100%, 40%);">+           cmp = strcmp(left_obj->base->name, right_key);</span><br><span>                 break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strncmp(left_obj->name, right_key, strlen(right_key));</span><br><span style="color: hsl(120, 100%, 40%);">+               cmp = strncmp(left_obj->base->name, right_key, strlen(right_key));</span><br><span>             break;</span><br><span>       default:</span><br><span>             cmp = 0;</span><br><span>@@ -86,17 +86,17 @@</span><br><span> </span><br><span>   switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         cmp = strcmp(left_obj->bridgeid, right_obj->bridgeid);</span><br><span style="color: hsl(120, 100%, 40%);">+          cmp = strcmp(left_obj->bridge->id, right_obj->bridge->id);</span><br><span>               if (cmp) {</span><br><span>                   return cmp;</span><br><span>          }</span><br><span style="color: hsl(0, 100%, 40%);">-               right_key = right_obj->name;</span><br><span style="color: hsl(120, 100%, 40%);">+               right_key = right_obj->base->name;</span><br><span>             /* Fall through */</span><br><span>   case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strcmp(left_obj->name, right_key);</span><br><span style="color: hsl(120, 100%, 40%);">+           cmp = strcmp(left_obj->base->name, right_key);</span><br><span>                 break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strncmp(left_obj->name, right_key, strlen(right_key));</span><br><span style="color: hsl(120, 100%, 40%);">+               cmp = strncmp(left_obj->base->name, right_key, strlen(right_key));</span><br><span>             break;</span><br><span>       default:</span><br><span>             cmp = 0;</span><br><span>@@ -115,15 +115,15 @@</span><br><span> </span><br><span>         switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         right_key = right_obj->name;</span><br><span style="color: hsl(120, 100%, 40%);">+               right_key = right_obj->base->name;</span><br><span>             /* Fall through */</span><br><span>   case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            if (strcmp(left_obj->name, right_key) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (strcmp(left_obj->base->name, right_key) == 0) {</span><br><span>                    cmp = CMP_MATCH | CMP_STOP;</span><br><span>          }</span><br><span>            break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            if (strncmp(left_obj->name, right_key, strlen(right_key)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (strncmp(left_obj->base->name, right_key, strlen(right_key)) == 0) {</span><br><span>                        cmp = CMP_MATCH;</span><br><span>             }</span><br><span>            break;</span><br><span>@@ -144,18 +144,18 @@</span><br><span> </span><br><span>   switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         if (strcmp(left_obj->bridgeid, right_obj->bridgeid) == 0</span><br><span style="color: hsl(0, 100%, 40%);">-                  && strcmp(left_obj->name, right_obj->name) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (strcmp(left_obj->bridge->id, right_obj->bridge->id) == 0</span><br><span style="color: hsl(120, 100%, 40%);">+                      && strcmp(left_obj->base->name, right_obj->base->name) == 0) {</span><br><span>                   return CMP_MATCH | CMP_STOP;</span><br><span>                 }</span><br><span>            break;</span><br><span>       case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            if (strcmp(left_obj->name, right_key) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (strcmp(left_obj->base->name, right_key) == 0) {</span><br><span>                    cmp = CMP_MATCH | CMP_STOP;</span><br><span>          }</span><br><span>            break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            if (strncmp(left_obj->name, right_key, strlen(right_key)) == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (strncmp(left_obj->base->name, right_key, strlen(right_key)) == 0) {</span><br><span>                        cmp = CMP_MATCH;</span><br><span>             }</span><br><span>            break;</span><br><span>@@ -172,7 +172,7 @@</span><br><span>         struct ast_channel_snapshot *snapshot = obj;</span><br><span>         struct ao2_container *snapshots = arg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      if (!strcmp(snapshot->type, "PJSIP")) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!strcmp(snapshot->base->type, "PJSIP")) {</span><br><span>                ao2_link(snapshots, snapshot);</span><br><span>               return CMP_MATCH;</span><br><span>    }</span><br><span>@@ -185,8 +185,8 @@</span><br><span>      struct ast_channel_snapshot *channel = obj;</span><br><span>  regex_t *regexbuf = arg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (!regexec(regexbuf, channel->name, 0, NULL, 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            || !regexec(regexbuf, channel->appl, 0, NULL, 0)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!regexec(regexbuf, channel->base->name, 0, NULL, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+         || !regexec(regexbuf, channel->dialplan->appl, 0, NULL, 0)) {</span><br><span>          return 0;</span><br><span>    }</span><br><span> </span><br><span>@@ -236,7 +236,7 @@</span><br><span> {</span><br><span>     const struct ast_channel_snapshot *snapshot = obj;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  return snapshot->name;</span><br><span style="color: hsl(120, 100%, 40%);">+     return snapshot->base->name;</span><br><span> }</span><br><span> </span><br><span> static void *cli_channel_retrieve_by_id(const char *id)</span><br><span>@@ -280,16 +280,16 @@</span><br><span> </span><br><span>   ast_assert(context->output_buffer != NULL);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      print_name_len = strlen(snapshot->name) + strlen(snapshot->appl) + 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   print_name_len = strlen(snapshot->base->name) + strlen(snapshot->dialplan->appl) + 2;</span><br><span>    print_name = alloca(print_name_len);</span><br><span> </span><br><span>     /* Append the application */</span><br><span style="color: hsl(0, 100%, 40%);">-    snprintf(print_name, print_name_len, "%s/%s", snapshot->name, snapshot->appl);</span><br><span style="color: hsl(120, 100%, 40%);">+        snprintf(print_name, print_name_len, "%s/%s", snapshot->base->name, snapshot->dialplan->appl);</span><br><span> </span><br><span>     indent = CLI_INDENT_TO_SPACES(context->indent_level);</span><br><span>     flexwidth = CLI_LAST_TABSTOP - indent;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->base->creationtime.tv_sec, print_time, 32);</span><br><span> </span><br><span>    ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s  %-11.11s\n",</span><br><span>              CLI_INDENT_TO_SPACES(context->indent_level), "Channel",</span><br><span>@@ -307,9 +307,9 @@</span><br><span>                   "%*s: %-*.*s  CLCID: \"%s\" <%s>\n",</span><br><span>                       indent, "Exten",</span><br><span>                   flexwidth, flexwidth,</span><br><span style="color: hsl(0, 100%, 40%);">-                   snapshot->exten,</span><br><span style="color: hsl(0, 100%, 40%);">-                     snapshot->connected_name,</span><br><span style="color: hsl(0, 100%, 40%);">-                    snapshot->connected_number</span><br><span style="color: hsl(120, 100%, 40%);">+                 snapshot->dialplan->exten,</span><br><span style="color: hsl(120, 100%, 40%);">+                      snapshot->connected->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                      snapshot->connected->number</span><br><span>                    );</span><br><span>           context->indent_level--;</span><br><span>          if (context->indent_level == 0) {</span><br><span>@@ -338,7 +338,7 @@</span><br><span> {</span><br><span>      struct ast_sip_cli_context *context = arg;</span><br><span>   const struct ast_channel_snapshot *snapshot = obj;</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_channel *channel = ast_channel_get_by_name(snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_channel *channel = ast_channel_get_by_name(snapshot->base->name);</span><br><span>   struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL;</span><br><span>   struct ast_sip_session *session;</span><br><span>     struct ast_sip_session_media *media;</span><br><span>@@ -351,7 +351,7 @@</span><br><span>   ast_assert(context->output_buffer != NULL);</span><br><span> </span><br><span>   if (!channel) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);</span><br><span>          return -1;</span><br><span>   }</span><br><span> </span><br><span>@@ -359,7 +359,7 @@</span><br><span> </span><br><span>      session = cpvt->session;</span><br><span>  if (!session) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);</span><br><span>          ast_channel_unlock(channel);</span><br><span>                 ao2_cleanup(channel);</span><br><span>                return -1;</span><br><span>@@ -367,7 +367,7 @@</span><br><span> </span><br><span>         media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];</span><br><span>    if (!media || !media->rtp) {</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);</span><br><span>          ast_channel_unlock(channel);</span><br><span>                 ao2_cleanup(channel);</span><br><span>                return -1;</span><br><span>@@ -383,18 +383,18 @@</span><br><span> </span><br><span>       ast_channel_unlock(channel);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        print_name = ast_strdupa(snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+  print_name = ast_strdupa(snapshot->base->name);</span><br><span>        /* Skip the PJSIP/.  We know what channel type it is and we need the space. */</span><br><span>       print_name += 6;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32);</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->base->creationtime.tv_sec, print_time, 32);</span><br><span> </span><br><span>    if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->base->name);</span><br><span>        } else {</span><br><span>             ast_str_append(&context->output_buffer, 0,</span><br><span>                    " %8.8s %-18.18s %-8.8s %-6.6s %6u%s %6u%s %3u %7.3f %6u%s %6u%s %3u %7.3f %7.3f\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  snapshot->bridgeid,</span><br><span style="color: hsl(120, 100%, 40%);">+                        snapshot->bridge->id,</span><br><span>                  print_name,</span><br><span>                  print_time,</span><br><span>                  codec_in_use,</span><br><span>diff --git a/configs/samples/ari.conf.sample b/configs/samples/ari.conf.sample</span><br><span>index 8729b1e..5ce3166 100644</span><br><span>--- a/configs/samples/ari.conf.sample</span><br><span>+++ b/configs/samples/ari.conf.sample</span><br><span>@@ -17,6 +17,8 @@</span><br><span> ; Display certain channel variables every time a channel-oriented</span><br><span> ; event is emitted:</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; Note that this does incur a performance penalty and should be avoided if possible.</span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span> ;channelvars = var1,var2,var3</span><br><span> </span><br><span> ;[username]</span><br><span>diff --git a/configs/samples/manager.conf.sample b/configs/samples/manager.conf.sample</span><br><span>index 989441a..405e0d3 100644</span><br><span>--- a/configs/samples/manager.conf.sample</span><br><span>+++ b/configs/samples/manager.conf.sample</span><br><span>@@ -55,6 +55,8 @@</span><br><span> ; Display certain channel variables every time a channel-oriented</span><br><span> ; event is emitted:</span><br><span> ;</span><br><span style="color: hsl(120, 100%, 40%);">+; Note that this does incur a performance penalty and should be avoided if possible.</span><br><span style="color: hsl(120, 100%, 40%);">+;</span><br><span> ;channelvars = var1,var2,var3</span><br><span> </span><br><span> ; debug = on    ; enable some debugging info in AMI messages (default off).</span><br><span>diff --git a/include/asterisk/channel.h b/include/asterisk/channel.h</span><br><span>index 9627ae2..58a4879 100644</span><br><span>--- a/include/asterisk/channel.h</span><br><span>+++ b/include/asterisk/channel.h</span><br><span>@@ -4258,6 +4258,7 @@</span><br><span> ast_callid ast_channel_callid(const struct ast_channel *chan);</span><br><span> struct ast_channel_snapshot *ast_channel_snapshot(const struct ast_channel *chan);</span><br><span> void ast_channel_snapshot_set(struct ast_channel *chan, struct ast_channel_snapshot *snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_flags *ast_channel_snapshot_segment_flags(struct ast_channel *chan);</span><br><span> </span><br><span> /*!</span><br><span>  * \pre chan is locked</span><br><span>diff --git a/include/asterisk/stasis_channels.h b/include/asterisk/stasis_channels.h</span><br><span>index 2aeff6f..c90470a 100644</span><br><span>--- a/include/asterisk/stasis_channels.h</span><br><span>+++ b/include/asterisk/stasis_channels.h</span><br><span>@@ -29,50 +29,133 @@</span><br><span>  */</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Channel snapshot invalidation flags, used to force generation of segments</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+enum ast_channel_snapshot_segment_invalidation {</span><br><span style="color: hsl(120, 100%, 40%);">+     /*! Invalidate the bridge segment */</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE = (1 << 1),</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Invalidate the dialplan segment */</span><br><span style="color: hsl(120, 100%, 40%);">+        AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN = (1 << 2),</span><br><span style="color: hsl(120, 100%, 40%);">+    /*! Invalidate the connected segment */</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED = (1 << 3),</span><br><span style="color: hsl(120, 100%, 40%);">+   /*! Invalidate the caller segment */</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER = (1 << 4),</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Invalidate the hangup segment */</span><br><span style="color: hsl(120, 100%, 40%);">+  AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP = (1 << 5),</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! Invalidate the peer segment */</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER = (1 << 6),</span><br><span style="color: hsl(120, 100%, 40%);">+        /*! Invalidate the base segment */</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE = (1 << 7),</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing bridge information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_bridge {</span><br><span style="color: hsl(120, 100%, 40%);">+ char id[0]; /*!< Unique Bridge Identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing dialplan information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_dialplan {</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(appl);             /*!< Current application */</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(data);             /*!< Data passed to current application */</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_STRING_FIELD(context);          /*!< Current extension context */</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_STRING_FIELD(exten);            /*!< Current extension number */</span><br><span style="color: hsl(120, 100%, 40%);">+       );</span><br><span style="color: hsl(120, 100%, 40%);">+    int priority; /*!< Current extension priority */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing caller information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_caller {</span><br><span style="color: hsl(120, 100%, 40%);">+    AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(name);           /*!< Caller ID Name */</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_STRING_FIELD(number);         /*!< Caller ID Number */</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_STRING_FIELD(dnid);           /*!< Dialed ID Number */</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_STRING_FIELD(dialed_subaddr); /*!< Dialed subaddress */</span><br><span style="color: hsl(120, 100%, 40%);">+                AST_STRING_FIELD(ani);            /*!< Caller ID ANI Number */</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_STRING_FIELD(rdnis);          /*!< Caller ID RDNIS Number */</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_STRING_FIELD(subaddr);        /*!< Caller subaddress */</span><br><span style="color: hsl(120, 100%, 40%);">+        );</span><br><span style="color: hsl(120, 100%, 40%);">+    int pres; /*!< Caller ID presentation. */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing connected information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_connected {</span><br><span style="color: hsl(120, 100%, 40%);">+     char *number; /*!< Connected Line Number */</span><br><span style="color: hsl(120, 100%, 40%);">+        char name[0]; /*!< Connected Line Name */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing base information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_base {</span><br><span style="color: hsl(120, 100%, 40%);">+       AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(name);        /*!< ASCII unique channel name */</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_STRING_FIELD(uniqueid);    /*!< Unique Channel Identifier */</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_STRING_FIELD(accountcode); /*!< Account code for billing */</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_STRING_FIELD(userfield);   /*!< Userfield for CEL billing */</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_STRING_FIELD(language);    /*!< The default spoken language for the channel */</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_STRING_FIELD(type);        /*!< Type of channel technology */</span><br><span style="color: hsl(120, 100%, 40%);">+  );</span><br><span style="color: hsl(120, 100%, 40%);">+    struct timeval creationtime; /*!< The time of channel creation */</span><br><span style="color: hsl(120, 100%, 40%);">+  int tech_properties;         /*!< Properties of the channel's technology */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing peer information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_peer {</span><br><span style="color: hsl(120, 100%, 40%);">+ char *linkedid;   /*!< Linked Channel Identifier -- gets propagated by linkage */</span><br><span style="color: hsl(120, 100%, 40%);">+  char account[0]; /*!< Peer account code for billing */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Structure containing hangup information for a channel snapshot.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot_hangup {</span><br><span style="color: hsl(120, 100%, 40%);">+      int cause;      /*!< Why is the channel hanged up. See causes.h */</span><br><span style="color: hsl(120, 100%, 40%);">+ char source[0]; /*!< Who is responsible for hanging up this channel */</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \since 12</span><br><span>  * \brief Structure representing a snapshot of channel state.</span><br><span>  *</span><br><span>  * While not enforced programmatically, this object is shared across multiple</span><br><span>  * threads, and should be treated as an immutable object.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * It is guaranteed that the segments of this snapshot will always exist</span><br><span style="color: hsl(120, 100%, 40%);">+ * when accessing the snapshot.</span><br><span>  */</span><br><span> struct ast_channel_snapshot {</span><br><span style="color: hsl(0, 100%, 40%);">-        AST_DECLARE_STRING_FIELDS(</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(name);             /*!< ASCII unique channel name */</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_STRING_FIELD(uniqueid);         /*!< Unique Channel Identifier */</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_STRING_FIELD(linkedid);         /*!< Linked Channel Identifier -- gets propagated by linkage */</span><br><span style="color: hsl(0, 100%, 40%);">-          AST_STRING_FIELD(appl);             /*!< Current application */</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(data);             /*!< Data passed to current application */</span><br><span style="color: hsl(0, 100%, 40%);">-               AST_STRING_FIELD(context);          /*!< Dialplan: Current extension context */</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(exten);            /*!< Dialplan: Current extension number */</span><br><span style="color: hsl(0, 100%, 40%);">-               AST_STRING_FIELD(accountcode);      /*!< Account code for billing */</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_STRING_FIELD(peeraccount);      /*!< Peer account code for billing */</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_STRING_FIELD(userfield);        /*!< Userfield for CEL billing */</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_STRING_FIELD(hangupsource);     /*!< Who is responsible for hanging up this channel */</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_STRING_FIELD(caller_name);      /*!< Caller ID Name */</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_STRING_FIELD(caller_number);    /*!< Caller ID Number */</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_STRING_FIELD(caller_dnid);      /*!< Dialed ID Number */</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_STRING_FIELD(caller_ani);       /*!< Caller ID ANI Number */</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_STRING_FIELD(caller_rdnis);     /*!< Caller ID RDNIS Number */</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_STRING_FIELD(caller_subaddr);   /*!< Caller subaddress */</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_STRING_FIELD(dialed_subaddr);   /*!< Dialed subaddress */</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_STRING_FIELD(connected_name);   /*!< Connected Line Name */</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(connected_number); /*!< Connected Line Number */</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_STRING_FIELD(language);         /*!< The default spoken language for the channel */</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_STRING_FIELD(bridgeid);         /*!< Unique Bridge Identifier */</span><br><span style="color: hsl(0, 100%, 40%);">-         AST_STRING_FIELD(type);             /*!< Type of channel technology */</span><br><span style="color: hsl(0, 100%, 40%);">-       );</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      struct timeval creationtime;            /*!< The time of channel creation */</span><br><span style="color: hsl(0, 100%, 40%);">- enum ast_channel_state state;           /*!< State of line */</span><br><span style="color: hsl(0, 100%, 40%);">-        int priority;                           /*!< Dialplan: Current extension priority */</span><br><span style="color: hsl(0, 100%, 40%);">- int amaflags;                           /*!< AMA flags for billing */</span><br><span style="color: hsl(0, 100%, 40%);">-        int hangupcause;                        /*!< Why is the channel hanged up. See causes.h */</span><br><span style="color: hsl(0, 100%, 40%);">-   int caller_pres;                        /*!< Caller ID presentation. */</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_flags flags;                 /*!< channel flags of AST_FLAG_ type */</span><br><span style="color: hsl(0, 100%, 40%);">-      struct ast_flags softhangup_flags;      /*!< softhangup channel flags */</span><br><span style="color: hsl(0, 100%, 40%);">-     struct varshead *manager_vars;          /*!< Variables to be appended to manager events */</span><br><span style="color: hsl(0, 100%, 40%);">-   int tech_properties;                    /*!< Properties of the channel's technology */</span><br><span style="color: hsl(0, 100%, 40%);">-   struct varshead *ari_vars;              /*!< Variables to be appended to ARI events */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_channel_snapshot_base *base;           /*!< Base information about the channel */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_channel_snapshot_peer *peer;           /*!< Peer information */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_channel_snapshot_caller *caller;       /*!< Information about the caller */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_channel_snapshot_connected *connected; /*!< Information about who this channel is connected to */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_channel_snapshot_bridge *bridge;       /*!< Information about the bridge */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_channel_snapshot_dialplan *dialplan;   /*!< Information about the dialplan */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct ast_channel_snapshot_hangup *hangup;       /*!< Hangup information */</span><br><span style="color: hsl(120, 100%, 40%);">+       enum ast_channel_state state;                     /*!< State of line */</span><br><span style="color: hsl(120, 100%, 40%);">+    int amaflags;                                     /*!< AMA flags for billing */</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_flags flags;                           /*!< channel flags of AST_FLAG_ type */</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_flags softhangup_flags;                /*!< softhangup channel flags */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct varshead *manager_vars;                    /*!< Variables to be appended to manager events */</span><br><span style="color: hsl(120, 100%, 40%);">+       struct varshead *ari_vars;                        /*!< Variables to be appended to ARI events */</span><br><span> };</span><br><span> </span><br><span> /*!</span><br><span>@@ -360,6 +443,18 @@</span><br><span> void ast_channel_stage_snapshot_done(struct ast_channel *chan);</span><br><span> </span><br><span> /*!</span><br><span style="color: hsl(120, 100%, 40%);">+ * \since 17</span><br><span style="color: hsl(120, 100%, 40%);">+ * \brief Invalidate a channel snapshot segment from being reused</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \pre chan is locked</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param chan Channel to invalidate the segment on.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param segment The segment to invalidate.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan,</span><br><span style="color: hsl(120, 100%, 40%);">+   enum ast_channel_snapshot_segment_invalidation segment);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!</span><br><span>  * \since 12</span><br><span>  * \brief Publish a \ref ast_channel_snapshot for a channel.</span><br><span>  *</span><br><span>diff --git a/main/bridge.c b/main/bridge.c</span><br><span>index 024c6ab..a65927d 100644</span><br><span>--- a/main/bridge.c</span><br><span>+++ b/main/bridge.c</span><br><span>@@ -5157,7 +5157,7 @@</span><br><span>               return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_cli(a->fd, "Channel: %s\n", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_cli(a->fd, "Channel: %s\n", snapshot->base->name);</span><br><span>    ao2_ref(snapshot, -1);</span><br><span> </span><br><span>   return 0;</span><br><span>diff --git a/main/cdr.c b/main/cdr.c</span><br><span>index e321c22..2e3b205 100644</span><br><span>--- a/main/cdr.c</span><br><span>+++ b/main/cdr.c</span><br><span>@@ -803,7 +803,7 @@</span><br><span> static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)</span><br><span> {</span><br><span>   CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-              cdr, cdr->party_a.snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+               cdr, cdr->party_a.snapshot->base->name,</span><br><span>             cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);</span><br><span>         cdr->fn_table = fn_table;</span><br><span>         if (cdr->fn_table->init_function) {</span><br><span>@@ -938,9 +938,9 @@</span><br><span> {</span><br><span>         ao2_lock(active_cdrs_all);</span><br><span>   if (cdr->party_b.snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {</span><br><span>                  ao2_unlink_flags(active_cdrs_all, cdr, OBJ_NOLOCK);</span><br><span style="color: hsl(0, 100%, 40%);">-                     ast_string_field_set(cdr, party_b_name, cdr->party_b.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_string_field_set(cdr, party_b_name, cdr->party_b.snapshot->base->name);</span><br><span>                         ao2_link_flags(active_cdrs_all, cdr, OBJ_NOLOCK);</span><br><span>            }</span><br><span>    } else {</span><br><span>@@ -1039,16 +1039,16 @@</span><br><span>           ao2_cleanup(cdr);</span><br><span>            return NULL;</span><br><span>         }</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_string_field_set(cdr, uniqueid, chan->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(cdr, name, chan->name);</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(cdr, linkedid, chan->linkedid);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_set(cdr, uniqueid, chan->base->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_string_field_set(cdr, name, chan->base->name);</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_string_field_set(cdr, linkedid, chan->peer->linkedid);</span><br><span>     cdr->disposition = AST_CDR_NULL;</span><br><span>  cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);</span><br><span> </span><br><span>        cdr->party_a.snapshot = chan;</span><br><span>     ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->name);</span><br><span style="color: hsl(120, 100%, 40%);">+ CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);</span><br><span> </span><br><span>   cdr_object_transition_state(cdr, &single_state_fn_table);</span><br><span> </span><br><span>@@ -1145,11 +1145,11 @@</span><br><span>   * will attempt to clear the application and restore the dummy originate application</span><br><span>          * of "AppDialX". Ignore application changes to AppDialX as a result.</span><br><span>       */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (strcmp(new_snapshot->appl, old_snapshot->appl)</span><br><span style="color: hsl(0, 100%, 40%);">-                && strncasecmp(new_snapshot->appl, "appdial", 7)</span><br><span style="color: hsl(0, 100%, 40%);">-           && (strcmp(new_snapshot->context, old_snapshot->context)</span><br><span style="color: hsl(0, 100%, 40%);">-                  || strcmp(new_snapshot->exten, old_snapshot->exten)</span><br><span style="color: hsl(0, 100%, 40%);">-                       || new_snapshot->priority != old_snapshot->priority)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)</span><br><span style="color: hsl(120, 100%, 40%);">+            && strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)</span><br><span style="color: hsl(120, 100%, 40%);">+            && (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)</span><br><span style="color: hsl(120, 100%, 40%);">+                      || strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)</span><br><span style="color: hsl(120, 100%, 40%);">+                   || new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {</span><br><span>              return 1;</span><br><span>    }</span><br><span> </span><br><span>@@ -1196,11 +1196,11 @@</span><br><span> </span><br><span>  /* Neither party is dialed and neither has the Party A flag - defer to</span><br><span>        * creation time */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {</span><br><span>           return left;</span><br><span style="color: hsl(0, 100%, 40%);">-    } else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {</span><br><span style="color: hsl(120, 100%, 40%);">+       } else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {</span><br><span>            return right;</span><br><span style="color: hsl(0, 100%, 40%);">-   } else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {</span><br><span style="color: hsl(120, 100%, 40%);">+     } else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {</span><br><span>          return right;</span><br><span>        } else {</span><br><span>             /* Okay, fine, take the left one */</span><br><span>@@ -1285,7 +1285,7 @@</span><br><span>          /* Don't create records for CDRs where the party A was a dialed channel */</span><br><span>               if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {</span><br><span>                       ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                         it_cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                                it_cdr->party_a.snapshot->base->name);</span><br><span>                      continue;</span><br><span>            }</span><br><span> </span><br><span>@@ -1300,12 +1300,12 @@</span><br><span> </span><br><span>          /* Party A */</span><br><span>                ast_assert(party_a != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-            ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));</span><br><span>               cdr_copy->amaflags = party_a->amaflags;</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));</span><br><span>                ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));</span><br><span>                ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));</span><br><span>              ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));</span><br><span>@@ -1313,8 +1313,8 @@</span><br><span> </span><br><span>           /* Party B */</span><br><span>                if (party_b) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));</span><br><span>                       if (!ast_strlen_zero(it_cdr->party_b.userfield)) {</span><br><span>                                snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);</span><br><span>                     }</span><br><span>@@ -1375,8 +1375,8 @@</span><br><span>    struct ast_cdr *pub_cdr;</span><br><span> </span><br><span>         CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-           cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-              cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");</span><br><span style="color: hsl(120, 100%, 40%);">+             cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+           cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");</span><br><span>   pub_cdr = cdr_object_create_public_records(cdr);</span><br><span>     cdr_detach(pub_cdr);</span><br><span> }</span><br><span>@@ -1434,10 +1434,10 @@</span><br><span>  if (cdr->disposition == AST_CDR_NULL) {</span><br><span>           if (!ast_tvzero(cdr->answer)) {</span><br><span>                   cdr->disposition = AST_CDR_ANSWERED;</span><br><span style="color: hsl(0, 100%, 40%);">-         } else if (cdr->party_a.snapshot->hangupcause) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);</span><br><span style="color: hsl(0, 100%, 40%);">-              } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {</span><br><span style="color: hsl(0, 100%, 40%);">-                      cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);</span><br><span style="color: hsl(120, 100%, 40%);">+            } else if (cdr->party_a.snapshot->hangup->cause) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangup->cause);</span><br><span style="color: hsl(120, 100%, 40%);">+               } else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangup->cause);</span><br><span>              } else {</span><br><span>                     cdr->disposition = AST_CDR_FAILED;</span><br><span>                }</span><br><span>@@ -1445,7 +1445,7 @@</span><br><span> </span><br><span>        /* tv_usec is suseconds_t, which could be int or long */</span><br><span>     ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      cdr->party_a.snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                    cdr->party_a.snapshot->base->name,</span><br><span>                  (long)cdr->start.tv_sec,</span><br><span>                  (long)cdr->start.tv_usec,</span><br><span>                         (long)cdr->answer.tv_sec,</span><br><span>@@ -1491,19 +1491,19 @@</span><br><span> static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)</span><br><span> {</span><br><span>        if (!old_snapshot->snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-               set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);</span><br><span style="color: hsl(0, 100%, 40%);">-          set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);</span><br><span style="color: hsl(0, 100%, 40%);">-             set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+            set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);</span><br><span style="color: hsl(120, 100%, 40%);">+            set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+               set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);</span><br><span>                return;</span><br><span>      }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);</span><br><span>   }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);</span><br><span>      }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {</span><br><span style="color: hsl(0, 100%, 40%);">-            set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);</span><br><span>        }</span><br><span> }</span><br><span> </span><br><span>@@ -1524,7 +1524,7 @@</span><br><span> </span><br><span> static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);</span><br><span> </span><br><span>     /* Finalize the CDR if we're in hangup logic and we're set to do so */</span><br><span>       if (ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)</span><br><span>@@ -1539,11 +1539,11 @@</span><br><span>   */</span><br><span>  if (!ast_test_flag(&snapshot->flags, AST_FLAG_SUBROUTINE_EXEC)</span><br><span>                || ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             if (strcmp(cdr->context, snapshot->context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    ast_string_field_set(cdr, context, snapshot->context);</span><br><span style="color: hsl(120, 100%, 40%);">+             if (strcmp(cdr->context, snapshot->dialplan->context)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_string_field_set(cdr, context, snapshot->dialplan->context);</span><br><span>               }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (strcmp(cdr->exten, snapshot->exten)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                        ast_string_field_set(cdr, exten, snapshot->exten);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (strcmp(cdr->exten, snapshot->dialplan->exten)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 ast_string_field_set(cdr, exten, snapshot->dialplan->exten);</span><br><span>           }</span><br><span>    }</span><br><span> </span><br><span>@@ -1555,13 +1555,13 @@</span><br><span>       * here.</span><br><span>      */</span><br><span>  if (!ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)</span><br><span style="color: hsl(0, 100%, 40%);">-                && !ast_strlen_zero(snapshot->appl)</span><br><span style="color: hsl(0, 100%, 40%);">-          && (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (strcmp(cdr->appl, snapshot->appl)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_string_field_set(cdr, appl, snapshot->appl);</span><br><span style="color: hsl(120, 100%, 40%);">+           && !ast_strlen_zero(snapshot->dialplan->appl)</span><br><span style="color: hsl(120, 100%, 40%);">+           && (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (strcmp(cdr->appl, snapshot->dialplan->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_string_field_set(cdr, appl, snapshot->dialplan->appl);</span><br><span>             }</span><br><span style="color: hsl(0, 100%, 40%);">-               if (strcmp(cdr->data, snapshot->data)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_string_field_set(cdr, data, snapshot->data);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (strcmp(cdr->data, snapshot->dialplan->data)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_string_field_set(cdr, data, snapshot->dialplan->data);</span><br><span>             }</span><br><span> </span><br><span>                /* Dial (app_dial) is a special case. Because pre-dial handlers, which</span><br><span>@@ -1569,13 +1569,13 @@</span><br><span>              * something people typically don't want to see, if we see a channel enter</span><br><span>                * into Dial here, we set the appl/data accordingly and lock it.</span><br><span>              */</span><br><span style="color: hsl(0, 100%, 40%);">-             if (!strcmp(snapshot->appl, "Dial")) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!strcmp(snapshot->dialplan->appl, "Dial")) {</span><br><span>                     ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);</span><br><span>          }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (strcmp(cdr->linkedid, snapshot->linkedid)) {</span><br><span style="color: hsl(0, 100%, 40%);">-          ast_string_field_set(cdr, linkedid, snapshot->linkedid);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);</span><br><span>         }</span><br><span>    cdr_object_check_party_a_answer(cdr);</span><br><span>        cdr_object_check_party_a_hangup(cdr);</span><br><span>@@ -1603,7 +1603,7 @@</span><br><span> {</span><br><span>   char park_info[128];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ast_assert(!strcasecmp(parking_info->parkee->name, cdr->party_a.snapshot->name));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));</span><br><span> </span><br><span>  /* Update Party A information regardless */</span><br><span>  cdr->fn_table->process_party_a(cdr, parking_info->parkee);</span><br><span>@@ -1637,25 +1637,25 @@</span><br><span> </span><br><span> static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-    if (caller && !strcasecmp(cdr->party_a.snapshot->name, caller->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+      if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {</span><br><span>           base_process_party_a(cdr, caller);</span><br><span>           CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   cdr->party_a.snapshot->base->name);</span><br><span>                 cdr_object_swap_snapshot(&cdr->party_b, peer);</span><br><span>                cdr_all_relink(cdr);</span><br><span>                 CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr->party_b.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   cdr->party_b.snapshot->base->name);</span><br><span> </span><br><span>             /* If we have two parties, lock the application that caused the</span><br><span>               * two parties to be associated. This prevents mid-call event</span><br><span>                 * macros/gosubs from perturbing the CDR application/data</span><br><span>             */</span><br><span>          ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);</span><br><span style="color: hsl(0, 100%, 40%);">-     } else if (!strcasecmp(cdr->party_a.snapshot->name, peer->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {</span><br><span>                /* We're the entity being dialed, i.e., outbound origination */</span><br><span>          base_process_party_a(cdr, peer);</span><br><span>             CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                   cdr->party_a.snapshot->base->name);</span><br><span>         }</span><br><span> </span><br><span>        cdr_object_transition_state(cdr, &dial_state_fn_table);</span><br><span>@@ -1680,15 +1680,15 @@</span><br><span>        struct cdr_object_snapshot *party_a;</span><br><span> </span><br><span>     /* Don't match on ourselves */</span><br><span style="color: hsl(0, 100%, 40%);">-      if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {</span><br><span>              return 1;</span><br><span>    }</span><br><span> </span><br><span>        /* Try the candidate CDR's Party A first */</span><br><span>      party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {</span><br><span>               CDR_DEBUG("%p - Party A %s has new Party B %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                     cdr, cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                      cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);</span><br><span>           cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);</span><br><span>           cdr_all_relink(cdr);</span><br><span>                 if (!cand_cdr->party_b.snapshot) {</span><br><span>@@ -1703,13 +1703,13 @@</span><br><span> </span><br><span>  /* Try their Party B, unless it's us */</span><br><span>  if (!cand_cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-              || !strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          || !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {</span><br><span>               return 1;</span><br><span>    }</span><br><span>    party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {</span><br><span>               CDR_DEBUG("%p - Party A %s has new Party B %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                     cdr, cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                      cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);</span><br><span>           cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);</span><br><span>           cdr_all_relink(cdr);</span><br><span>                 return 0;</span><br><span>@@ -1788,7 +1788,7 @@</span><br><span> {</span><br><span>       ast_assert(snapshot != NULL);</span><br><span>        ast_assert(cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-             && !strcasecmp(cdr->party_b.snapshot->name, snapshot->name));</span><br><span style="color: hsl(120, 100%, 40%);">+                && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));</span><br><span> </span><br><span>         cdr_object_swap_snapshot(&cdr->party_b, snapshot);</span><br><span> </span><br><span>@@ -1839,11 +1839,11 @@</span><br><span>      } else {</span><br><span>             party_a = peer;</span><br><span>      }</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_assert(!strcasecmp(cdr->party_a.snapshot->name, party_a->name));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));</span><br><span>      cdr_object_swap_snapshot(&cdr->party_a, party_a);</span><br><span> </span><br><span>         if (cdr->party_b.snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (strcasecmp(cdr->party_b.snapshot->name, peer->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {</span><br><span>                        /* Not the status for this CDR - defer back to the message router */</span><br><span>                         return 1;</span><br><span>            }</span><br><span>@@ -1901,7 +1901,7 @@</span><br><span>                            }</span><br><span> </span><br><span>                                /* Skip any records that aren't our Party B */</span><br><span style="color: hsl(0, 100%, 40%);">-                              if (strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                          if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {</span><br><span>                                       continue;</span><br><span>                            }</span><br><span>                            cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);</span><br><span>@@ -1982,7 +1982,7 @@</span><br><span> static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)</span><br><span> {</span><br><span>   ast_assert(cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-             && !strcasecmp(cdr->party_b.snapshot->name, snapshot->name));</span><br><span style="color: hsl(120, 100%, 40%);">+                && !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));</span><br><span> </span><br><span>         cdr_object_swap_snapshot(&cdr->party_b, snapshot);</span><br><span> </span><br><span>@@ -1997,9 +1997,9 @@</span><br><span>        if (strcmp(cdr->bridge, bridge->uniqueid)) {</span><br><span>           return 1;</span><br><span>    }</span><br><span style="color: hsl(0, 100%, 40%);">-       if (strcasecmp(cdr->party_a.snapshot->name, channel->name)</span><br><span style="color: hsl(120, 100%, 40%);">+   if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)</span><br><span>                && cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-             && strcasecmp(cdr->party_b.snapshot->name, channel->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         && strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {</span><br><span>              return 1;</span><br><span>    }</span><br><span>    cdr_object_transition_state(cdr, &finalized_state_fn_table);</span><br><span>@@ -2011,7 +2011,7 @@</span><br><span> </span><br><span> static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-     if (strcasecmp(cdr->party_a.snapshot->name, channel->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {</span><br><span>             return 1;</span><br><span>    }</span><br><span>    cdr_object_transition_state(cdr, &finalized_state_fn_table);</span><br><span>@@ -2043,7 +2043,7 @@</span><br><span>  */</span><br><span> static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -2114,19 +2114,19 @@</span><br><span> </span><br><span>       CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",</span><br><span>                 ast_strlen_zero(dial_status) ? "Begin" : "End",</span><br><span style="color: hsl(0, 100%, 40%);">-             caller ? caller->name : "(none)",</span><br><span style="color: hsl(0, 100%, 40%);">-          peer ? peer->name : "(none)",</span><br><span style="color: hsl(120, 100%, 40%);">+            caller ? caller->base->name : "(none)",</span><br><span style="color: hsl(120, 100%, 40%);">+               peer ? peer->base->name : "(none)",</span><br><span>          (unsigned int)stasis_message_timestamp(message)->tv_sec,</span><br><span>          (unsigned int)stasis_message_timestamp(message)->tv_usec);</span><br><span> </span><br><span>    /* Figure out who is running this show */</span><br><span>    if (caller) {</span><br><span style="color: hsl(0, 100%, 40%);">-           cdr = ao2_find(active_cdrs_master, caller->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+              cdr = ao2_find(active_cdrs_master, caller->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>    } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                cdr = ao2_find(active_cdrs_master, peer->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+                cdr = ao2_find(active_cdrs_master, peer->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>      }</span><br><span>    if (!cdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->name : peer->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);</span><br><span>           ast_assert(0);</span><br><span>               return;</span><br><span>      }</span><br><span>@@ -2139,8 +2139,8 @@</span><br><span>                    }</span><br><span>                    CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",</span><br><span>                          it_cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                         caller ? caller->name : "(none)",</span><br><span style="color: hsl(0, 100%, 40%);">-                          peer ? peer->name : "(none)");</span><br><span style="color: hsl(120, 100%, 40%);">+                           caller ? caller->base->name : "(none)",</span><br><span style="color: hsl(120, 100%, 40%);">+                               peer ? peer->base->name : "(none)");</span><br><span>                         res &= it_cdr->fn_table->process_dial_begin(it_cdr,</span><br><span>                                        caller,</span><br><span>                                      peer);</span><br><span>@@ -2150,8 +2150,8 @@</span><br><span>                       }</span><br><span>                    CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",</span><br><span>                            it_cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                         caller ? caller->name : "(none)",</span><br><span style="color: hsl(0, 100%, 40%);">-                          peer ? peer->name : "(none)");</span><br><span style="color: hsl(120, 100%, 40%);">+                           caller ? caller->base->name : "(none)",</span><br><span style="color: hsl(120, 100%, 40%);">+                               peer ? peer->base->name : "(none)");</span><br><span>                         it_cdr->fn_table->process_dial_end(it_cdr,</span><br><span>                                     caller,</span><br><span>                                      peer,</span><br><span>@@ -2185,7 +2185,7 @@</span><br><span>                 * is consistent with the key.</span><br><span>                */</span><br><span>          ast_assert(cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                     && !strcasecmp(cdr->party_b.snapshot->name, party_b->name));</span><br><span style="color: hsl(120, 100%, 40%);">+                 && !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));</span><br><span> #endif</span><br><span> </span><br><span>                /* Don't transition to the finalized state - let the Party A do</span><br><span>@@ -2210,11 +2210,11 @@</span><br><span>                 * asserts the snapshot to be this way.</span><br><span>               */</span><br><span>          if (!cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                   || strcasecmp(cdr->party_b.snapshot->name, party_b->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 || strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {</span><br><span>                      ast_log(LOG_NOTICE,</span><br><span>                          "CDR for Party A %s(%s) has inconsistent Party B %s name.  Message can be ignored but this shouldn't happen.\n",</span><br><span>                               cdr->linkedid,</span><br><span style="color: hsl(0, 100%, 40%);">-                               cdr->party_a.snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                            cdr->party_a.snapshot->base->name,</span><br><span>                          cdr->party_b_name);</span><br><span>                       return 0;</span><br><span>            }</span><br><span>@@ -2236,7 +2236,7 @@</span><br><span>    }</span><br><span> </span><br><span>        /* Auto-fall through will increment the priority but have no application */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (ast_strlen_zero(new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span>           return 0;</span><br><span>    }</span><br><span> </span><br><span>@@ -2272,12 +2272,12 @@</span><br><span>              cdr->is_root = 1;</span><br><span>                 ao2_link(active_cdrs_master, cdr);</span><br><span>   } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                cdr = ao2_find(active_cdrs_master, update->new_snapshot->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+             cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>   }</span><br><span> </span><br><span>        /* Handle Party A */</span><br><span>         if (!cdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);</span><br><span>            ast_assert(0);</span><br><span>       } else {</span><br><span>             int all_reject = 1;</span><br><span>@@ -2303,7 +2303,7 @@</span><br><span> </span><br><span>      if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {</span><br><span>          ao2_lock(cdr);</span><br><span style="color: hsl(0, 100%, 40%);">-          CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);</span><br><span>            for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span>                       cdr_object_finalize(it_cdr);</span><br><span>                 }</span><br><span>@@ -2317,12 +2317,12 @@</span><br><span>  /* Handle Party B */</span><br><span>         if (update->new_snapshot) {</span><br><span>               ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr_object_update_party_b, (char *) update->new_snapshot->name, update->new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+                       cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);</span><br><span>     }</span><br><span> </span><br><span>        if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {</span><br><span>          ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr_object_finalize_party_b, (char *) update->new_snapshot->name, update->new_snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+                     cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);</span><br><span>   }</span><br><span> </span><br><span>        ao2_cleanup(cdr);</span><br><span>@@ -2347,7 +2347,7 @@</span><br><span>             * is consistent with the key.</span><br><span>                */</span><br><span>          ast_assert(cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                     && !strcasecmp(cdr->party_b.snapshot->name, leave_data->channel->name));</span><br><span style="color: hsl(120, 100%, 40%);">+                  && !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));</span><br><span> </span><br><span>           /* It is our Party B, in our bridge. Set the end time and let the handler</span><br><span>             * transition our CDR appropriately when we leave the bridge.</span><br><span>@@ -2399,13 +2399,13 @@</span><br><span>      }</span><br><span> </span><br><span>        CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-           channel->name,</span><br><span style="color: hsl(120, 100%, 40%);">+             channel->base->name,</span><br><span>           (unsigned int)stasis_message_timestamp(message)->tv_sec,</span><br><span>          (unsigned int)stasis_message_timestamp(message)->tv_usec);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+     cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>   if (!cdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);</span><br><span>            ast_assert(0);</span><br><span>               return;</span><br><span>      }</span><br><span>@@ -2417,7 +2417,7 @@</span><br><span>                    continue;</span><br><span>            }</span><br><span>            CDR_DEBUG("%p - Processing Bridge Leave for %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                    it_cdr, channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                    it_cdr, channel->base->name);</span><br><span>          if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {</span><br><span>                        ast_string_field_set(it_cdr, bridge, "");</span><br><span>                  left_bridge = 1;</span><br><span>@@ -2429,7 +2429,7 @@</span><br><span>     if (left_bridge</span><br><span>              && strcmp(bridge->subclass, "parking")) {</span><br><span>               ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,</span><br><span style="color: hsl(0, 100%, 40%);">-                  cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                      cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,</span><br><span>                    &leave_data);</span><br><span>    }</span><br><span> </span><br><span>@@ -2457,8 +2457,8 @@</span><br><span>        ast_string_field_set(new_cdr, bridge, cdr->bridge);</span><br><span>       cdr_object_transition_state(new_cdr, &bridge_state_fn_table);</span><br><span>    CDR_DEBUG("%p - Party A %s has new Party B %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-             new_cdr, new_cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-         party_b->snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+               new_cdr, new_cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+              party_b->snapshot->base->name);</span><br><span> }</span><br><span> </span><br><span> /*!</span><br><span>@@ -2487,16 +2487,16 @@</span><br><span>           }</span><br><span> </span><br><span>                /* If the candidate is us or someone we've taken on, pass on by */</span><br><span style="color: hsl(0, 100%, 40%);">-          if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)</span><br><span style="color: hsl(120, 100%, 40%);">+            if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)</span><br><span>                         || (cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                            && !strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         && !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {</span><br><span>                      break;</span><br><span>               }</span><br><span> </span><br><span>                party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);</span><br><span>          /* We're party A - make a new CDR, append it to us, and set the candidate as</span><br><span>              * Party B */</span><br><span style="color: hsl(0, 100%, 40%);">-           if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {</span><br><span>                       bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);</span><br><span>                         break;</span><br><span>               }</span><br><span>@@ -2504,12 +2504,12 @@</span><br><span>          /* We're Party B. Check if we can add ourselves immediately or if we need</span><br><span>                 * a new CDR for them (they already have a Party B) */</span><br><span>               if (cand_cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                       && strcasecmp(cand_cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   && strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {</span><br><span>                        bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);</span><br><span>                 } else {</span><br><span>                     CDR_DEBUG("%p - Party A %s has new Party B %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                             cand_cdr, cand_cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                               cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                           cand_cdr, cand_cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                            cdr->party_a.snapshot->base->name);</span><br><span>                         cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);</span><br><span>                   cdr_all_relink(cand_cdr);</span><br><span>                    /* It's possible that this joined at one point and was never chosen</span><br><span>@@ -2572,7 +2572,7 @@</span><br><span>              }</span><br><span>            if (it_cdr->fn_table->process_party_a) {</span><br><span>                       CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                              channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                            channel->base->name);</span><br><span>                  it_cdr->fn_table->process_party_a(it_cdr, channel);</span><br><span>            }</span><br><span>    }</span><br><span>@@ -2609,14 +2609,14 @@</span><br><span>  for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span>               if (it_cdr->fn_table->process_party_a) {</span><br><span>                       CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                              channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                            channel->base->name);</span><br><span>                  it_cdr->fn_table->process_party_a(it_cdr, channel);</span><br><span>            }</span><br><span> </span><br><span>                /* Notify all states that they have entered a bridge */</span><br><span>              if (it_cdr->fn_table->process_bridge_enter) {</span><br><span>                  CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,</span><br><span style="color: hsl(0, 100%, 40%);">-                            channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                            channel->base->name);</span><br><span>                  result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);</span><br><span>                      switch (result) {</span><br><span>                    case BRIDGE_ENTER_ONLY_PARTY:</span><br><span>@@ -2689,13 +2689,13 @@</span><br><span>      }</span><br><span> </span><br><span>        CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-           channel->name,</span><br><span style="color: hsl(120, 100%, 40%);">+             channel->base->name,</span><br><span>           (unsigned int)stasis_message_timestamp(message)->tv_sec,</span><br><span>          (unsigned int)stasis_message_timestamp(message)->tv_usec);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+     cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>   if (!cdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);</span><br><span>            ast_assert(0);</span><br><span>               return;</span><br><span>      }</span><br><span>@@ -2739,13 +2739,13 @@</span><br><span>  }</span><br><span> </span><br><span>        CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-            channel->name,</span><br><span style="color: hsl(120, 100%, 40%);">+             channel->base->name,</span><br><span>           (unsigned int)stasis_message_timestamp(message)->tv_sec,</span><br><span>          (unsigned int)stasis_message_timestamp(message)->tv_usec);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+     cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>   if (!cdr) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);</span><br><span>            ast_assert(0);</span><br><span>               return;</span><br><span>      }</span><br><span>@@ -3094,8 +3094,8 @@</span><br><span>    struct cdr_object *cdr = obj;</span><br><span>        const char *name = arg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!strcasecmp(cdr->party_a.snapshot->name, name) ||</span><br><span style="color: hsl(0, 100%, 40%);">-                     (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||</span><br><span style="color: hsl(120, 100%, 40%);">+                  (cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {</span><br><span>               return CMP_MATCH;</span><br><span>    }</span><br><span>    return 0;</span><br><span>@@ -3110,7 +3110,7 @@</span><br><span>    struct cdr_object *cdr = obj;</span><br><span>        const char *name = arg;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     if (!strcasecmp(cdr->party_a.snapshot->name, name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {</span><br><span>                 return CMP_MATCH;</span><br><span>    }</span><br><span>    return 0;</span><br><span>@@ -3170,10 +3170,10 @@</span><br><span>                  if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {</span><br><span>                               continue;</span><br><span>                    }</span><br><span style="color: hsl(0, 100%, 40%);">-                       if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {</span><br><span>                              headp = &it_cdr->party_a.variables;</span><br><span>                   } else if (it_cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                          && !strcasecmp(channel_name, it_cdr->party_b.snapshot->name)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         && !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {</span><br><span>                               headp = &it_cdr->party_b.variables;</span><br><span>                   }</span><br><span>                    if (headp) {</span><br><span>@@ -3212,25 +3212,25 @@</span><br><span>       struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;</span><br><span> </span><br><span>     if (!strcasecmp(name, "clid")) {</span><br><span style="color: hsl(0, 100%, 40%);">-              ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");</span><br><span>         } else if (!strcasecmp(name, "src")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_copy_string(value, party_a->caller_number, length);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_copy_string(value, party_a->caller->number, length);</span><br><span>       } else if (!strcasecmp(name, "dst")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_copy_string(value, party_a->exten, length);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_copy_string(value, party_a->dialplan->exten, length);</span><br><span>      } else if (!strcasecmp(name, "dcontext")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_copy_string(value, party_a->context, length);</span><br><span style="color: hsl(120, 100%, 40%);">+          ast_copy_string(value, party_a->dialplan->context, length);</span><br><span>    } else if (!strcasecmp(name, "channel")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            ast_copy_string(value, party_a->name, length);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_copy_string(value, party_a->base->name, length);</span><br><span>   } else if (!strcasecmp(name, "dstchannel")) {</span><br><span>              if (party_b) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_copy_string(value, party_b->name, length);</span><br><span style="color: hsl(120, 100%, 40%);">+                     ast_copy_string(value, party_b->base->name, length);</span><br><span>           } else {</span><br><span>                     ast_copy_string(value, "", length);</span><br><span>                }</span><br><span>    } else if (!strcasecmp(name, "lastapp")) {</span><br><span style="color: hsl(0, 100%, 40%);">-            ast_copy_string(value, party_a->appl, length);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_copy_string(value, party_a->dialplan->appl, length);</span><br><span>       } else if (!strcasecmp(name, "lastdata")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_copy_string(value, party_a->data, length);</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_copy_string(value, party_a->dialplan->data, length);</span><br><span>       } else if (!strcasecmp(name, "start")) {</span><br><span>           cdr_get_tv(cdr_obj->start, NULL, value, length);</span><br><span>  } else if (!strcasecmp(name, "answer")) {</span><br><span>@@ -3246,15 +3246,15 @@</span><br><span>        } else if (!strcasecmp(name, "amaflags")) {</span><br><span>                snprintf(value, length, "%d", party_a->amaflags);</span><br><span>       } else if (!strcasecmp(name, "accountcode")) {</span><br><span style="color: hsl(0, 100%, 40%);">-                ast_copy_string(value, party_a->accountcode, length);</span><br><span style="color: hsl(120, 100%, 40%);">+              ast_copy_string(value, party_a->base->accountcode, length);</span><br><span>    } else if (!strcasecmp(name, "peeraccount")) {</span><br><span>             if (party_b) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_copy_string(value, party_b->accountcode, length);</span><br><span style="color: hsl(120, 100%, 40%);">+                      ast_copy_string(value, party_b->base->accountcode, length);</span><br><span>            } else {</span><br><span>                     ast_copy_string(value, "", length);</span><br><span>                }</span><br><span>    } else if (!strcasecmp(name, "uniqueid")) {</span><br><span style="color: hsl(0, 100%, 40%);">-           ast_copy_string(value, party_a->uniqueid, length);</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_copy_string(value, party_a->base->uniqueid, length);</span><br><span>       } else if (!strcasecmp(name, "linkedid")) {</span><br><span>                ast_copy_string(value, cdr_obj->linkedid, length);</span><br><span>        } else if (!strcasecmp(name, "userfield")) {</span><br><span>@@ -3431,7 +3431,7 @@</span><br><span>                * is consistent with the key.</span><br><span>                */</span><br><span>          ast_assert(cdr->party_b.snapshot</span><br><span style="color: hsl(0, 100%, 40%);">-                     && !strcasecmp(cdr->party_b.snapshot->name, info->channel_name));</span><br><span style="color: hsl(120, 100%, 40%);">+                    && !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));</span><br><span> </span><br><span>              ast_copy_string(cdr->party_b.userfield, info->userfield,</span><br><span>                       sizeof(cdr->party_b.userfield));</span><br><span>@@ -3624,7 +3624,7 @@</span><br><span>          /* Copy over the basic CDR information. The Party A information is</span><br><span>            * copied over automatically as part of the append</span><br><span>            */</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);</span><br><span>          new_cdr = cdr_object_create_and_append(cdr);</span><br><span>                 if (!new_cdr) {</span><br><span>                      return -1;</span><br><span>@@ -3938,8 +3938,8 @@</span><br><span> </span><br><span>       it_cdrs = ao2_iterator_init(active_cdrs_master, 0);</span><br><span>  while ((cdr = ao2_iterator_next(&it_cdrs))) {</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!strncasecmp(a->word, cdr->party_a.snapshot->name, wordlen)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     if (ast_cli_completion_add(ast_strdup(cdr->party_a.snapshot->name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (ast_cli_completion_add(ast_strdup(cdr->party_a.snapshot->base->name))) {</span><br><span>                                ao2_ref(cdr, -1);</span><br><span>                            break;</span><br><span>                       }</span><br><span>@@ -4001,8 +4001,8 @@</span><br><span>            cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));</span><br><span>                cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));</span><br><span>             cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));</span><br><span style="color: hsl(0, 100%, 40%);">-         ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                          it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+                ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                               it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",</span><br><span>                              it_cdr->appl,</span><br><span>                             start_time_buffer,</span><br><span>                           answer_time_buffer,</span><br><span>@@ -4046,7 +4046,7 @@</span><br><span>          if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {</span><br><span>                       continue;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-               ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller_name, it_cdr->party_a.snapshot->caller_number, "");</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");</span><br><span>            if (ast_tvzero(it_cdr->end)) {</span><br><span>                    end = ast_tvnow();</span><br><span>           } else {</span><br><span>@@ -4056,9 +4056,9 @@</span><br><span>             cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));</span><br><span>               cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));</span><br><span>           ast_cli(a->fd, FORMAT_STRING,</span><br><span style="color: hsl(0, 100%, 40%);">-                                it_cdr->party_a.snapshot->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+                          it_cdr->party_a.snapshot->base->accountcode,</span><br><span>                                clid,</span><br><span style="color: hsl(0, 100%, 40%);">-                           it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",</span><br><span style="color: hsl(120, 100%, 40%);">+                                it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",</span><br><span>                              it_cdr->appl,</span><br><span>                             it_cdr->data,</span><br><span>                             start_time_buffer,</span><br><span>@@ -4415,8 +4415,8 @@</span><br><span>   }</span><br><span>    for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {</span><br><span>               prnt(where, "Party A: %s; Party B: %s; Bridge %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  it_cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                   it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<unknown>",</span><br><span style="color: hsl(120, 100%, 40%);">+                     it_cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                        it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<unknown>",</span><br><span>                   it_cdr->bridge);</span><br><span>  }</span><br><span> }</span><br><span>@@ -4440,8 +4440,8 @@</span><br><span>               return;</span><br><span>      }</span><br><span>    prnt(where, "Party A: %s; Party B: %s; Bridge %s",</span><br><span style="color: hsl(0, 100%, 40%);">-            cdr->party_a.snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-              cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<unknown>",</span><br><span style="color: hsl(120, 100%, 40%);">+           cdr->party_a.snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+           cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<unknown>",</span><br><span>                 cdr->bridge);</span><br><span> }</span><br><span> </span><br><span>diff --git a/main/cel.c b/main/cel.c</span><br><span>index 97e35ad..242aeff 100644</span><br><span>--- a/main/cel.c</span><br><span>+++ b/main/cel.c</span><br><span>@@ -528,22 +528,22 @@</span><br><span>               AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,</span><br><span>             AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,</span><br><span>               AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_name,</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_number,</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_ani,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_rdnis,</span><br><span style="color: hsl(0, 100%, 40%);">-          AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_dnid,</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->exten,</span><br><span style="color: hsl(0, 100%, 40%);">-            AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->context,</span><br><span style="color: hsl(0, 100%, 40%);">-                AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-          AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->appl,</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->data,</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->name,</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->number,</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->ani,</span><br><span style="color: hsl(120, 100%, 40%);">+                AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->rdnis,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->dnid,</span><br><span style="color: hsl(120, 100%, 40%);">+              AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->exten,</span><br><span style="color: hsl(120, 100%, 40%);">+             AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->context,</span><br><span style="color: hsl(120, 100%, 40%);">+         AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+               AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->appl,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->data,</span><br><span>           AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, snapshot->amaflags,</span><br><span style="color: hsl(0, 100%, 40%);">-             AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->accountcode,</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peeraccount,</span><br><span style="color: hsl(0, 100%, 40%);">-           AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->linkedid,</span><br><span style="color: hsl(0, 100%, 40%);">-              AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->userfield,</span><br><span style="color: hsl(120, 100%, 40%);">+          AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->base->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+                AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peer->account,</span><br><span style="color: hsl(120, 100%, 40%);">+            AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->base->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->peer->linkedid,</span><br><span style="color: hsl(120, 100%, 40%);">+           AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->base->userfield,</span><br><span>                AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, S_OR(extra_txt, ""),</span><br><span>              AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, S_OR(peer, ""),</span><br><span>            AST_EVENT_IE_END);</span><br><span>@@ -573,7 +573,7 @@</span><br><span>      * reporting on CHANNEL_START so we can track when to send LINKEDID_END */</span><br><span>   if (event_type == AST_CEL_CHANNEL_START</span><br><span>              && ast_cel_track_event(AST_CEL_LINKEDID_END)) {</span><br><span style="color: hsl(0, 100%, 40%);">-         if (cel_linkedid_ref(snapshot->linkedid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (cel_linkedid_ref(snapshot->peer->linkedid)) {</span><br><span>                      return -1;</span><br><span>           }</span><br><span>    }</span><br><span>@@ -583,7 +583,7 @@</span><br><span>      }</span><br><span> </span><br><span>        if ((event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END)</span><br><span style="color: hsl(0, 100%, 40%);">-          && !cel_track_app(snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               && !cel_track_app(snapshot->dialplan->appl)) {</span><br><span>                 return 0;</span><br><span>    }</span><br><span> </span><br><span>@@ -606,14 +606,14 @@</span><br><span>        RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);</span><br><span>         struct cel_linkedid *lid;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!linkedids || ast_strlen_zero(snapshot->linkedid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!linkedids || ast_strlen_zero(snapshot->peer->linkedid)) {</span><br><span>                 /* The CEL module is shutdown.  Abort. */</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span>        ao2_lock(linkedids);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        lid = ao2_find(linkedids, (void *) snapshot->linkedid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+    lid = ao2_find(linkedids, (void *) snapshot->peer->linkedid, OBJ_SEARCH_KEY);</span><br><span>  if (!lid) {</span><br><span>          ao2_unlock(linkedids);</span><br><span> </span><br><span>@@ -623,7 +623,7 @@</span><br><span>              * of change to make after starting Asterisk.</span><br><span>                 */</span><br><span>          ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                       snapshot->linkedid);</span><br><span style="color: hsl(120, 100%, 40%);">+                       snapshot->peer->linkedid);</span><br><span>             return;</span><br><span>      }</span><br><span> </span><br><span>@@ -898,11 +898,11 @@</span><br><span> </span><br><span>    if (!was_hungup && is_hungup) {</span><br><span>              struct ast_json *extra;</span><br><span style="color: hsl(0, 100%, 40%);">-         struct cel_dialstatus *dialstatus = get_dialstatus(new_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                struct cel_dialstatus *dialstatus = get_dialstatus(new_snapshot->base->uniqueid);</span><br><span> </span><br><span>          extra = ast_json_pack("{s: i, s: s, s: s}",</span><br><span style="color: hsl(0, 100%, 40%);">-                   "hangupcause", new_snapshot->hangupcause,</span><br><span style="color: hsl(0, 100%, 40%);">-                  "hangupsource", new_snapshot->hangupsource,</span><br><span style="color: hsl(120, 100%, 40%);">+                      "hangupcause", new_snapshot->hangup->cause,</span><br><span style="color: hsl(120, 100%, 40%);">+                   "hangupsource", new_snapshot->hangup->source,</span><br><span>                        "dialstatus", dialstatus ? dialstatus->dialstatus : "");</span><br><span>              cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);</span><br><span>           ast_json_unref(extra);</span><br><span>@@ -929,12 +929,12 @@</span><br><span>               return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_assert(!ast_strlen_zero(new_snapshot->linkedid));</span><br><span style="color: hsl(0, 100%, 40%);">-        ast_assert(!ast_strlen_zero(old_snapshot->linkedid));</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_assert(!ast_strlen_zero(new_snapshot->peer->linkedid));</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_assert(!ast_strlen_zero(old_snapshot->peer->linkedid));</span><br><span> </span><br><span>        if (ast_cel_track_event(AST_CEL_LINKEDID_END)</span><br><span style="color: hsl(0, 100%, 40%);">-           && strcmp(old_snapshot->linkedid, new_snapshot->linkedid)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              cel_linkedid_ref(new_snapshot->linkedid);</span><br><span style="color: hsl(120, 100%, 40%);">+          && strcmp(old_snapshot->peer->linkedid, new_snapshot->peer->linkedid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          cel_linkedid_ref(new_snapshot->peer->linkedid);</span><br><span>                check_retire_linkedid(old_snapshot);</span><br><span>         }</span><br><span> }</span><br><span>@@ -943,17 +943,17 @@</span><br><span>       struct ast_channel_snapshot *old_snapshot,</span><br><span>   struct ast_channel_snapshot *new_snapshot)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- if (old_snapshot && !strcmp(old_snapshot->appl, new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (old_snapshot && !strcmp(old_snapshot->dialplan->appl, new_snapshot->dialplan->appl)) {</span><br><span>               return;</span><br><span>      }</span><br><span> </span><br><span>        /* old snapshot has an application, end it */</span><br><span style="color: hsl(0, 100%, 40%);">-   if (old_snapshot && !ast_strlen_zero(old_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (old_snapshot && !ast_strlen_zero(old_snapshot->dialplan->appl)) {</span><br><span>          cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);</span><br><span>   }</span><br><span> </span><br><span>        /* new snapshot has an application, start it */</span><br><span style="color: hsl(0, 100%, 40%);">- if (!ast_strlen_zero(new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span>          cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);</span><br><span>         }</span><br><span> }</span><br><span>@@ -974,7 +974,7 @@</span><br><span>         if (!snapshot) {</span><br><span>             return 0;</span><br><span>    }</span><br><span style="color: hsl(0, 100%, 40%);">-       return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;</span><br><span style="color: hsl(120, 100%, 40%);">+       return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;</span><br><span> }</span><br><span> </span><br><span> static void cel_snapshot_update_cb(void *data, struct stasis_subscription *sub,</span><br><span>@@ -1010,7 +1010,7 @@</span><br><span>                 struct ast_channel_snapshot *current_snapshot;</span><br><span> </span><br><span>           /* Don't add the channel for which this message is being generated */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!strcmp(current_chan, chan->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!strcmp(current_chan, chan->base->uniqueid)) {</span><br><span>                     continue;</span><br><span>            }</span><br><span> </span><br><span>@@ -1019,7 +1019,7 @@</span><br><span>                        continue;</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_append(&peer_str, 0, "%s,", current_snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_str_append(&peer_str, 0, "%s,", current_snapshot->base->name);</span><br><span>               ao2_cleanup(current_snapshot);</span><br><span>       }</span><br><span>    ao2_iterator_destroy(&i);</span><br><span>@@ -1125,7 +1125,7 @@</span><br><span>        if (parked_payload->retriever) {</span><br><span>          extra = ast_json_pack("{s: s, s: s}",</span><br><span>                      "reason", reason ?: "",</span><br><span style="color: hsl(0, 100%, 40%);">-                     "retriever", parked_payload->retriever->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                        "retriever", parked_payload->retriever->base->name);</span><br><span>      } else {</span><br><span>             extra = ast_json_pack("{s: s}", "reason", reason ?: "");</span><br><span>       }</span><br><span>@@ -1147,7 +1147,7 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   dialstatus = ao2_find(dial_statuses, snapshot->uniqueid, OBJ_SEARCH_KEY);</span><br><span style="color: hsl(120, 100%, 40%);">+  dialstatus = ao2_find(dial_statuses, snapshot->base->uniqueid, OBJ_SEARCH_KEY);</span><br><span>        if (dialstatus) {</span><br><span>            if (!strcasecmp(dialstatus_string, "ANSWER") && strcasecmp(dialstatus->dialstatus, "ANSWER")) {</span><br><span>                       /* In the case of an answer after we already have a dial status we give</span><br><span>@@ -1171,7 +1171,7 @@</span><br><span>              return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   ast_copy_string(dialstatus->uniqueid, snapshot->uniqueid, sizeof(dialstatus->uniqueid));</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_copy_string(dialstatus->uniqueid, snapshot->base->uniqueid, sizeof(dialstatus->uniqueid));</span><br><span>   ast_copy_string(dialstatus->dialstatus, dialstatus_string, dialstatus_string_len);</span><br><span> </span><br><span>    ao2_link(dial_statuses, dialstatus);</span><br><span>@@ -1273,8 +1273,8 @@</span><br><span>                 "extension", transfer_msg->exten,</span><br><span>               "context", transfer_msg->context,</span><br><span>               "bridge_id", bridge_snapshot->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-            "transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->name : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-              "transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->uniqueid  : "N/A");</span><br><span style="color: hsl(120, 100%, 40%);">+          "transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->base->name : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+           "transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->base->uniqueid  : "N/A");</span><br><span>        if (extra) {</span><br><span>                 cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);</span><br><span>           ast_json_unref(extra);</span><br><span>@@ -1312,13 +1312,13 @@</span><br><span>     case AST_ATTENDED_TRANSFER_DEST_THREEWAY:</span><br><span>            extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",</span><br><span>                  "bridge1_id", bridge1->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "channel2_name", channel2->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "channel2_uniqueid", channel2->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "channel2_name", channel2->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                        "channel2_uniqueid", channel2->base->uniqueid,</span><br><span>                       "bridge2_id", bridge2->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                      "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                      "transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                 "transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");</span><br><span style="color: hsl(120, 100%, 40%);">+                      "transferee_channel_name", xfer->transferee ? xfer->transferee->base->name : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                   "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->base->uniqueid : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                   "transfer_target_channel_name", xfer->target ? xfer->target->base->name : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                      "transfer_target_channel_uniqueid", xfer->target ? xfer->target->base->uniqueid : "N/A");</span><br><span>            if (!extra) {</span><br><span>                        return;</span><br><span>              }</span><br><span>@@ -1327,13 +1327,13 @@</span><br><span>  case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:</span><br><span>           extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",</span><br><span>                  "bridge1_id", bridge1->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "channel2_name", channel2->name,</span><br><span style="color: hsl(0, 100%, 40%);">-                   "channel2_uniqueid", channel2->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+                 "channel2_name", channel2->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                        "channel2_uniqueid", channel2->base->uniqueid,</span><br><span>                       "app", xfer->dest.app,</span><br><span style="color: hsl(0, 100%, 40%);">-                     "transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                      "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                      "transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",</span><br><span style="color: hsl(0, 100%, 40%);">-                 "transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");</span><br><span style="color: hsl(120, 100%, 40%);">+                      "transferee_channel_name", xfer->transferee ? xfer->transferee->base->name : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                   "transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->base->uniqueid : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                   "transfer_target_channel_name", xfer->target ? xfer->target->base->name : "N/A",</span><br><span style="color: hsl(120, 100%, 40%);">+                      "transfer_target_channel_uniqueid", xfer->target ? xfer->target->base->uniqueid : "N/A");</span><br><span>            if (!extra) {</span><br><span>                        return;</span><br><span>              }</span><br><span>@@ -1357,8 +1357,8 @@</span><br><span>    }</span><br><span> </span><br><span>        extra = ast_json_pack("{s: s, s: s}",</span><br><span style="color: hsl(0, 100%, 40%);">-         "pickup_channel", channel->name,</span><br><span style="color: hsl(0, 100%, 40%);">-           "pickup_channel_uniqueid", channel->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+           "pickup_channel", channel->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                "pickup_channel_uniqueid", channel->base->uniqueid);</span><br><span>         if (!extra) {</span><br><span>                return;</span><br><span>      }</span><br><span>@@ -1381,8 +1381,8 @@</span><br><span>    }</span><br><span> </span><br><span>        extra = ast_json_pack("{s: s, s: s}",</span><br><span style="color: hsl(0, 100%, 40%);">-         "local_two", localtwo->name,</span><br><span style="color: hsl(0, 100%, 40%);">-               "local_two_uniqueid", localtwo->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+               "local_two", localtwo->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+            "local_two_uniqueid", localtwo->base->uniqueid);</span><br><span>     if (!extra) {</span><br><span>                return;</span><br><span>      }</span><br><span>diff --git a/main/channel.c b/main/channel.c</span><br><span>index 3d8e244..7e12f30 100644</span><br><span>--- a/main/channel.c</span><br><span>+++ b/main/channel.c</span><br><span>@@ -6761,6 +6761,12 @@</span><br><span>              ast_channel_name(clonechan), ast_channel_state(clonechan),</span><br><span>           ast_channel_name(original), ast_channel_state(original));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* When all is said and done force new snapshot segments so they are</span><br><span style="color: hsl(120, 100%, 40%);">+   * up to date.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_set_flag(ast_channel_snapshot_segment_flags(original), AST_FLAGS_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_set_flag(ast_channel_snapshot_segment_flags(clonechan), AST_FLAGS_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        /*</span><br><span>    * Remember the original read/write formats.  We turn off any</span><br><span>         * translation on either one</span><br><span>@@ -7183,6 +7189,7 @@</span><br><span> </span><br><span>     ast_channel_lock(chan);</span><br><span>      ast_party_caller_set(ast_channel_caller(chan), caller, update);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span>       ast_channel_unlock(chan);</span><br><span> }</span><br><span> </span><br><span>@@ -7195,6 +7202,7 @@</span><br><span> </span><br><span>       ast_channel_lock(chan);</span><br><span>      ast_party_caller_set(ast_channel_caller(chan), caller, update);</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span>       ast_channel_publish_snapshot(chan);</span><br><span>  ast_channel_unlock(chan);</span><br><span> }</span><br><span>@@ -8120,6 +8128,7 @@</span><br><span> </span><br><span>   ast_channel_lock(chan);</span><br><span>      ast_party_connected_line_set(ast_channel_connected(chan), connected, update);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED);</span><br><span>    ast_channel_publish_snapshot(chan);</span><br><span>  ast_channel_unlock(chan);</span><br><span> }</span><br><span>@@ -8930,6 +8939,7 @@</span><br><span> </span><br><span>   ast_channel_lock(chan);</span><br><span>      ast_party_redirecting_set(ast_channel_redirecting(chan), redirecting, update);</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span>       ast_channel_unlock(chan);</span><br><span> }</span><br><span> </span><br><span>diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c</span><br><span>index 436ba23..30d3909 100644</span><br><span>--- a/main/channel_internal_api.c</span><br><span>+++ b/main/channel_internal_api.c</span><br><span>@@ -221,6 +221,7 @@</span><br><span>    void *stream_topology_change_source; /*!< Source that initiated a stream topology change */</span><br><span>       struct ast_stream *default_streams[AST_MEDIA_TYPE_END]; /*!< Default streams indexed by media type */</span><br><span>     struct ast_channel_snapshot *snapshot; /*!< The current up to date snapshot of the channel */</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_flags snapshot_segment_flags; /*!< Flags regarding the segments of the snapshot */</span><br><span> };</span><br><span> </span><br><span> /*! \brief The monotonically increasing integer counter for channel uniqueids */</span><br><span>@@ -228,18 +229,40 @@</span><br><span> </span><br><span> /* ACCESSORS */</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-#define DEFINE_STRINGFIELD_SETTERS_FOR(field, publish, assert_on_null) \</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEFINE_STRINGFIELD_SETTERS_FOR(field, assert_on_null) \</span><br><span> void ast_channel_##field##_set(struct ast_channel *chan, const char *value) \</span><br><span> { \</span><br><span>   if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \</span><br><span>         if (!strcmp(value, chan->field)) return; \</span><br><span>        ast_string_field_set(chan, field, value); \</span><br><span style="color: hsl(120, 100%, 40%);">+} \</span><br><span style="color: hsl(120, 100%, 40%);">+  \</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_string_field_build_va(chan, field, fmt, ap); \</span><br><span style="color: hsl(120, 100%, 40%);">+} \</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+      va_list ap; \</span><br><span style="color: hsl(120, 100%, 40%);">+ va_start(ap, fmt); \</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_channel_##field##_build_va(chan, fmt, ap); \</span><br><span style="color: hsl(120, 100%, 40%);">+      va_end(ap); \</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(field, publish, assert_on_null, invalidate) \</span><br><span style="color: hsl(120, 100%, 40%);">+void ast_channel_##field##_set(struct ast_channel *chan, const char *value) \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+   if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!strcmp(value, chan->field)) return; \</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(chan, field, value); \</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_snapshot_invalidate_segment(chan, invalidate); \</span><br><span>         if (publish && ast_channel_internal_is_finalized(chan)) ast_channel_publish_snapshot(chan); \</span><br><span> } \</span><br><span>   \</span><br><span> void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) \</span><br><span> { \</span><br><span>   ast_string_field_build_va(chan, field, fmt, ap); \</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_channel_snapshot_invalidate_segment(chan, invalidate); \</span><br><span>         if (publish && ast_channel_internal_is_finalized(chan)) ast_channel_publish_snapshot(chan); \</span><br><span> } \</span><br><span> void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) \</span><br><span>@@ -250,17 +273,17 @@</span><br><span>   va_end(ap); \</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(name, 0, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(language, 1, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(musicclass, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(latest_musicclass, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(accountcode, 1, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(peeraccount, 1, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(userfield, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(call_forward, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(hangupsource, 0, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(name, 0, 1, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(language, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_FOR(musicclass, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_FOR(latest_musicclass, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(accountcode, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(peeraccount, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(userfield, 0, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_FOR(call_forward, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(hangupsource, 0, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP);</span><br><span style="color: hsl(120, 100%, 40%);">+DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0);</span><br><span> </span><br><span> #define DEFINE_STRINGFIELD_GETTER_FOR(field) const char *ast_channel_##field(const struct ast_channel *chan) \</span><br><span> { \</span><br><span>@@ -298,6 +321,7 @@</span><br><span> void ast_channel_appl_set(struct ast_channel *chan, const char *value)</span><br><span> {</span><br><span>      chan->appl = value;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span> }</span><br><span> const char *ast_channel_blockproc(const struct ast_channel *chan)</span><br><span> {</span><br><span>@@ -314,6 +338,7 @@</span><br><span> void ast_channel_data_set(struct ast_channel *chan, const char *value)</span><br><span> {</span><br><span>         chan->data = value;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span> }</span><br><span> </span><br><span> const char *ast_channel_context(const struct ast_channel *chan)</span><br><span>@@ -323,6 +348,7 @@</span><br><span> void ast_channel_context_set(struct ast_channel *chan, const char *value)</span><br><span> {</span><br><span>         ast_copy_string(chan->context, value, sizeof(chan->context));</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span> }</span><br><span> const char *ast_channel_exten(const struct ast_channel *chan)</span><br><span> {</span><br><span>@@ -331,6 +357,7 @@</span><br><span> void ast_channel_exten_set(struct ast_channel *chan, const char *value)</span><br><span> {</span><br><span>    ast_copy_string(chan->exten, value, sizeof(chan->exten));</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span> }</span><br><span> const char *ast_channel_macrocontext(const struct ast_channel *chan)</span><br><span> {</span><br><span>@@ -404,6 +431,7 @@</span><br><span> void ast_channel_hangupcause_set(struct ast_channel *chan, int value)</span><br><span> {</span><br><span>       chan->hangupcause = value;</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP);</span><br><span> }</span><br><span> int ast_channel_macropriority(const struct ast_channel *chan)</span><br><span> {</span><br><span>@@ -420,6 +448,7 @@</span><br><span> void ast_channel_priority_set(struct ast_channel *chan, int value)</span><br><span> {</span><br><span>   chan->priority = value;</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span> }</span><br><span> int ast_channel_rings(const struct ast_channel *chan)</span><br><span> {</span><br><span>@@ -909,18 +938,22 @@</span><br><span> void ast_channel_caller_set(struct ast_channel *chan, struct ast_party_caller *value)</span><br><span> {</span><br><span>    chan->caller = *value;</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span> }</span><br><span> void ast_channel_connected_set(struct ast_channel *chan, struct ast_party_connected_line *value)</span><br><span> {</span><br><span>         chan->connected = *value;</span><br><span style="color: hsl(120, 100%, 40%);">+  ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED);</span><br><span> }</span><br><span> void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value)</span><br><span> {</span><br><span>         chan->dialed = *value;</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span> }</span><br><span> void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value)</span><br><span> {</span><br><span>  chan->redirecting = *value;</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);</span><br><span> }</span><br><span> void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value)</span><br><span> {</span><br><span>@@ -941,6 +974,7 @@</span><br><span> void ast_channel_creationtime_set(struct ast_channel *chan, struct timeval *value)</span><br><span> {</span><br><span>   chan->creationtime = *value;</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);</span><br><span> }</span><br><span> </span><br><span> struct timeval ast_channel_answertime(struct ast_channel *chan)</span><br><span>@@ -1204,6 +1238,7 @@</span><br><span> void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value)</span><br><span> {</span><br><span>    chan->bridge = value;</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE);</span><br><span>       ast_channel_publish_snapshot(chan);</span><br><span> }</span><br><span> </span><br><span>@@ -1335,6 +1370,11 @@</span><br><span> </span><br><span>    AST_VECTOR_INIT(&tmp->fds, AST_MAX_FDS);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+   /* Force all channel snapshot segments to be created on first use, so we don't have to check if</span><br><span style="color: hsl(120, 100%, 40%);">+    * an old snapshot exists.</span><br><span style="color: hsl(120, 100%, 40%);">+     */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_set_flag(&tmp->snapshot_segment_flags, AST_FLAGS_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return tmp;</span><br><span> }</span><br><span> </span><br><span>@@ -1363,6 +1403,7 @@</span><br><span>                 return;</span><br><span>      }</span><br><span>    dest->linkedid = source->linkedid;</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_channel_snapshot_invalidate_segment(dest, AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER);</span><br><span>         ast_channel_publish_snapshot(dest);</span><br><span> }</span><br><span> </span><br><span>@@ -1370,6 +1411,10 @@</span><br><span> {</span><br><span>   struct ast_channel_id temp;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+       /* This operation is used as part of masquerading and so does not invalidate the peer</span><br><span style="color: hsl(120, 100%, 40%);">+  * segment. This is due to the masquerade process invalidating all segments.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>        temp = a->uniqueid;</span><br><span>       a->uniqueid = b->uniqueid;</span><br><span>     b->uniqueid = temp;</span><br><span>@@ -1584,3 +1629,8 @@</span><br><span>       ao2_cleanup(chan->snapshot);</span><br><span>      chan->snapshot = ao2_bump(snapshot);</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_flags *ast_channel_snapshot_segment_flags(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     return &chan->snapshot_segment_flags;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/main/cli.c b/main/cli.c</span><br><span>index 5484e47..e2224f7 100644</span><br><span>--- a/main/cli.c</span><br><span>+++ b/main/cli.c</span><br><span>@@ -1004,8 +1004,8 @@</span><br><span>                 char durbuf[16] = "-";</span><br><span> </span><br><span>                 if (!count) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   if ((concise || verbose)  && !ast_tvzero(cs->creationtime)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);</span><br><span style="color: hsl(120, 100%, 40%);">+                 if ((concise || verbose)  && !ast_tvzero(cs->base->creationtime)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                             int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);</span><br><span>                               if (verbose) {</span><br><span>                                       int durh = duration / 3600;</span><br><span>                                  int durm = (duration % 3600) / 60;</span><br><span>@@ -1016,36 +1016,36 @@</span><br><span>                                 }</span><br><span>                    }</span><br><span>                    if (concise) {</span><br><span style="color: hsl(0, 100%, 40%);">-                          ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       S_OR(cs->appl, "(None)"),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  cs->data,</span><br><span style="color: hsl(0, 100%, 40%);">-                                    cs->caller_number,</span><br><span style="color: hsl(0, 100%, 40%);">-                                   cs->accountcode,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     cs->peeraccount,</span><br><span style="color: hsl(120, 100%, 40%);">+                           ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),</span><br><span style="color: hsl(120, 100%, 40%);">+                                     S_OR(cs->dialplan->appl, "(None)"),</span><br><span style="color: hsl(120, 100%, 40%);">+                                   cs->dialplan->data,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     cs->caller->number,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     cs->base->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  cs->peer->account,</span><br><span>                                     cs->amaflags,</span><br><span>                                     durbuf,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 cs->bridgeid,</span><br><span style="color: hsl(0, 100%, 40%);">-                                        cs->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                                     cs->bridge->id,</span><br><span style="color: hsl(120, 100%, 40%);">+                                 cs->base->uniqueid);</span><br><span>                   } else if (verbose) {</span><br><span style="color: hsl(0, 100%, 40%);">-                           ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),</span><br><span style="color: hsl(0, 100%, 40%);">-                                       S_OR(cs->appl, "(None)"),</span><br><span style="color: hsl(0, 100%, 40%);">-                                  S_OR(cs->data, "(Empty)"),</span><br><span style="color: hsl(0, 100%, 40%);">-                                 cs->caller_number,</span><br><span style="color: hsl(120, 100%, 40%);">+                         ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),</span><br><span style="color: hsl(120, 100%, 40%);">+                                     S_OR(cs->dialplan->appl, "(None)"),</span><br><span style="color: hsl(120, 100%, 40%);">+                                   S_OR(cs->dialplan->data, "(Empty)"),</span><br><span style="color: hsl(120, 100%, 40%);">+                                  cs->caller->number,</span><br><span>                                    durbuf,</span><br><span style="color: hsl(0, 100%, 40%);">-                                 cs->accountcode,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     cs->peeraccount,</span><br><span style="color: hsl(0, 100%, 40%);">-                                     cs->bridgeid);</span><br><span style="color: hsl(120, 100%, 40%);">+                                     cs->base->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+                                  cs->peer->account,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      cs->bridge->id);</span><br><span>                       } else {</span><br><span>                             char locbuf[40] = "(None)";</span><br><span>                                char appdata[40] = "(None)";</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                              if (!ast_strlen_zero(cs->context) && !ast_strlen_zero(cs->exten)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                       snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->exten, cs->context, cs->priority);</span><br><span style="color: hsl(120, 100%, 40%);">+                                if (!ast_strlen_zero(cs->dialplan->context) && !ast_strlen_zero(cs->dialplan->exten)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                   snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->dialplan->exten, cs->dialplan->context, cs->dialplan->priority);</span><br><span>                                }</span><br><span style="color: hsl(0, 100%, 40%);">-                               if (!ast_strlen_zero(cs->appl)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                                    snprintf(appdata, sizeof(appdata), "%s(%s)", cs->appl, S_OR(cs->data, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+                         if (!ast_strlen_zero(cs->dialplan->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                     snprintf(appdata, sizeof(appdata), "%s(%s)", cs->dialplan->appl, S_OR(cs->dialplan->data, ""));</span><br><span>                              }</span><br><span style="color: hsl(0, 100%, 40%);">-                               ast_cli(a->fd, FORMAT_STRING, cs->name, locbuf, ast_state2str(cs->state), appdata);</span><br><span style="color: hsl(120, 100%, 40%);">+                          ast_cli(a->fd, FORMAT_STRING, cs->base->name, locbuf, ast_state2str(cs->state), appdata);</span><br><span>                        }</span><br><span>            }</span><br><span>    }</span><br><span>@@ -1684,14 +1684,14 @@</span><br><span> </span><br><span>      iter = ao2_iterator_init(cached_channels, 0);</span><br><span>        for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {</span><br><span style="color: hsl(0, 100%, 40%);">-              if (!strncasecmp(word, snapshot->name, wordlen) && (++which > state)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {</span><br><span>                       if (state != -1) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              ret = ast_strdup(snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                          ret = ast_strdup(snapshot->base->name);</span><br><span>                                ao2_ref(snapshot, -1);</span><br><span>                               break;</span><br><span>                       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                   if (ast_cli_completion_add(ast_strdup(snapshot->name))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {</span><br><span>                                ao2_ref(snapshot, -1);</span><br><span>                               break;</span><br><span>                       }</span><br><span>diff --git a/main/core_local.c b/main/core_local.c</span><br><span>index c3fa15f..f56aac7 100644</span><br><span>--- a/main/core_local.c</span><br><span>+++ b/main/core_local.c</span><br><span>@@ -493,7 +493,7 @@</span><br><span>             }</span><br><span> </span><br><span>                dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?</span><br><span style="color: hsl(0, 100%, 40%);">-                               local_snapshot_one->uniqueid : local_snapshot_two->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+                            local_snapshot_one->base->uniqueid : local_snapshot_two->base->uniqueid;</span><br><span> </span><br><span>             event = "LocalOptimizationBegin";</span><br><span>          if (source_str) {</span><br><span>diff --git a/main/endpoints.c b/main/endpoints.c</span><br><span>index f3e3372..b958932 100644</span><br><span>--- a/main/endpoints.c</span><br><span>+++ b/main/endpoints.c</span><br><span>@@ -195,7 +195,7 @@</span><br><span>         ast_assert(endpoint != NULL);</span><br><span> </span><br><span>    ao2_lock(endpoint);</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_str_container_remove(endpoint->channel_ids, update->new_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+     ast_str_container_remove(endpoint->channel_ids, update->new_snapshot->base->uniqueid);</span><br><span>   ao2_unlock(endpoint);</span><br><span>        endpoint_publish_snapshot(endpoint);</span><br><span> }</span><br><span>diff --git a/main/manager.c b/main/manager.c</span><br><span>index 76a827c..3e41198 100644</span><br><span>--- a/main/manager.c</span><br><span>+++ b/main/manager.c</span><br><span>@@ -6271,10 +6271,10 @@</span><br><span>                     continue;</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           if (!ast_tvzero(cs->creationtime)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!ast_tvzero(cs->base->creationtime)) {</span><br><span>                     int duration, durh, durm, durs;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-                     duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);</span><br><span style="color: hsl(120, 100%, 40%);">+                     duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);</span><br><span>                   durh = duration / 3600;</span><br><span>                      durm = (duration % 3600) / 60;</span><br><span>                       durs = duration % 60;</span><br><span>@@ -6292,10 +6292,10 @@</span><br><span>                      "\r\n",</span><br><span>                    idText,</span><br><span>                      ast_str_buffer(built),</span><br><span style="color: hsl(0, 100%, 40%);">-                  cs->appl,</span><br><span style="color: hsl(0, 100%, 40%);">-                    cs->data,</span><br><span style="color: hsl(120, 100%, 40%);">+                  cs->dialplan->appl,</span><br><span style="color: hsl(120, 100%, 40%);">+                     cs->dialplan->data,</span><br><span>                    durbuf,</span><br><span style="color: hsl(0, 100%, 40%);">-                 cs->bridgeid);</span><br><span style="color: hsl(120, 100%, 40%);">+                     cs->bridge->id);</span><br><span> </span><br><span>           numchans++;</span><br><span> </span><br><span>diff --git a/main/manager_bridges.c b/main/manager_bridges.c</span><br><span>index 1b57049..4f2cb35 100644</span><br><span>--- a/main/manager_bridges.c</span><br><span>+++ b/main/manager_bridges.c</span><br><span>@@ -536,7 +536,7 @@</span><br><span>           return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {</span><br><span>              return 0;</span><br><span>    }</span><br><span> </span><br><span>diff --git a/main/manager_channels.c b/main/manager_channels.c</span><br><span>index 887f77e..edbc770 100644</span><br><span>--- a/main/manager_channels.c</span><br><span>+++ b/main/manager_channels.c</span><br><span>@@ -493,7 +493,7 @@</span><br><span>         char *connected_name;</span><br><span>        int res;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {</span><br><span>              return NULL;</span><br><span>         }</span><br><span> </span><br><span>@@ -502,8 +502,8 @@</span><br><span>          return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   caller_name = ast_escape_c_alloc(snapshot->caller_name);</span><br><span style="color: hsl(0, 100%, 40%);">-     connected_name = ast_escape_c_alloc(snapshot->connected_name);</span><br><span style="color: hsl(120, 100%, 40%);">+     caller_name = ast_escape_c_alloc(snapshot->caller->name);</span><br><span style="color: hsl(120, 100%, 40%);">+       connected_name = ast_escape_c_alloc(snapshot->connected->name);</span><br><span> </span><br><span>    res = ast_str_set(&out, 0,</span><br><span>               "%sChannel: %s\r\n"</span><br><span>@@ -520,20 +520,20 @@</span><br><span>                "%sPriority: %d\r\n"</span><br><span>               "%sUniqueid: %s\r\n"</span><br><span>               "%sLinkedid: %s\r\n",</span><br><span style="color: hsl(0, 100%, 40%);">-         prefix, snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+            prefix, snapshot->base->name,</span><br><span>          prefix, snapshot->state,</span><br><span>          prefix, ast_state2str(snapshot->state),</span><br><span style="color: hsl(0, 100%, 40%);">-              prefix, S_OR(snapshot->caller_number, "<unknown>"),</span><br><span style="color: hsl(120, 100%, 40%);">+                prefix, S_OR(snapshot->caller->number, "<unknown>"),</span><br><span>           prefix, S_OR(caller_name, "<unknown>"),</span><br><span style="color: hsl(0, 100%, 40%);">-         prefix, S_OR(snapshot->connected_number, "<unknown>"),</span><br><span style="color: hsl(120, 100%, 40%);">+             prefix, S_OR(snapshot->connected->number, "<unknown>"),</span><br><span>                prefix, S_OR(connected_name, "<unknown>"),</span><br><span style="color: hsl(0, 100%, 40%);">-              prefix, snapshot->language,</span><br><span style="color: hsl(0, 100%, 40%);">-          prefix, snapshot->accountcode,</span><br><span style="color: hsl(0, 100%, 40%);">-               prefix, snapshot->context,</span><br><span style="color: hsl(0, 100%, 40%);">-           prefix, snapshot->exten,</span><br><span style="color: hsl(0, 100%, 40%);">-             prefix, snapshot->priority,</span><br><span style="color: hsl(0, 100%, 40%);">-          prefix, snapshot->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-          prefix, snapshot->linkedid);</span><br><span style="color: hsl(120, 100%, 40%);">+               prefix, snapshot->base->language,</span><br><span style="color: hsl(120, 100%, 40%);">+               prefix, snapshot->base->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+            prefix, snapshot->dialplan->context,</span><br><span style="color: hsl(120, 100%, 40%);">+            prefix, snapshot->dialplan->exten,</span><br><span style="color: hsl(120, 100%, 40%);">+              prefix, snapshot->dialplan->priority,</span><br><span style="color: hsl(120, 100%, 40%);">+           prefix, snapshot->base->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+               prefix, snapshot->peer->linkedid);</span><br><span> </span><br><span>         ast_free(caller_name);</span><br><span>       ast_free(connected_name);</span><br><span>@@ -594,8 +594,8 @@</span><br><span>                      EVENT_FLAG_CALL, "Hangup",</span><br><span>                         "Cause: %d\r\n"</span><br><span>                    "Cause-txt: %s\r\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  new_snapshot->hangupcause,</span><br><span style="color: hsl(0, 100%, 40%);">-                   ast_cause2str(new_snapshot->hangupcause));</span><br><span style="color: hsl(120, 100%, 40%);">+                 new_snapshot->hangup->cause,</span><br><span style="color: hsl(120, 100%, 40%);">+                    ast_cause2str(new_snapshot->hangup->cause));</span><br><span>   }</span><br><span> </span><br><span>        if (old_snapshot->state != new_snapshot->state) {</span><br><span>@@ -612,7 +612,7 @@</span><br><span>        struct ast_channel_snapshot *new_snapshot)</span><br><span> {</span><br><span>      /* Empty application is not valid for a Newexten event */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_strlen_zero(new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span>           return NULL;</span><br><span>         }</span><br><span> </span><br><span>@@ -632,9 +632,9 @@</span><br><span>          "Extension: %s\r\n"</span><br><span>                "Application: %s\r\n"</span><br><span>              "AppData: %s\r\n",</span><br><span style="color: hsl(0, 100%, 40%);">-            new_snapshot->exten,</span><br><span style="color: hsl(0, 100%, 40%);">-         new_snapshot->appl,</span><br><span style="color: hsl(0, 100%, 40%);">-          new_snapshot->data);</span><br><span style="color: hsl(120, 100%, 40%);">+               new_snapshot->dialplan->exten,</span><br><span style="color: hsl(120, 100%, 40%);">+          new_snapshot->dialplan->appl,</span><br><span style="color: hsl(120, 100%, 40%);">+           new_snapshot->dialplan->data);</span><br><span> }</span><br><span> </span><br><span> static struct ast_manager_event_blob *channel_new_callerid(</span><br><span>@@ -654,14 +654,14 @@</span><br><span>         }</span><br><span> </span><br><span>        if (!(callerid = ast_escape_c_alloc(</span><br><span style="color: hsl(0, 100%, 40%);">-                  ast_describe_caller_presentation(new_snapshot->caller_pres)))) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ast_describe_caller_presentation(new_snapshot->caller->pres)))) {</span><br><span>                return NULL;</span><br><span>         }</span><br><span> </span><br><span>        res = ast_manager_event_blob_create(</span><br><span>                 EVENT_FLAG_CALL, "NewCallerid",</span><br><span>            "CID-CallingPres: %d (%s)\r\n",</span><br><span style="color: hsl(0, 100%, 40%);">-               new_snapshot->caller_pres,</span><br><span style="color: hsl(120, 100%, 40%);">+         new_snapshot->caller->pres,</span><br><span>            callerid);</span><br><span> </span><br><span>       ast_free(callerid);</span><br><span>@@ -693,13 +693,13 @@</span><br><span>          return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(old_snapshot->accountcode, new_snapshot->accountcode)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!strcmp(old_snapshot->base->accountcode, new_snapshot->base->accountcode)) {</span><br><span>                 return NULL;</span><br><span>         }</span><br><span> </span><br><span>        return ast_manager_event_blob_create(</span><br><span>                EVENT_FLAG_CALL, "NewAccountCode",</span><br><span style="color: hsl(0, 100%, 40%);">-            "OldAccountCode: %s\r\n", old_snapshot->accountcode);</span><br><span style="color: hsl(120, 100%, 40%);">+            "OldAccountCode: %s\r\n", old_snapshot->base->accountcode);</span><br><span> }</span><br><span> </span><br><span> channel_snapshot_monitor channel_monitors[] = {</span><br><span>diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c</span><br><span>index 59b9685..42bf6bc 100644</span><br><span>--- a/main/stasis_bridges.c</span><br><span>+++ b/main/stasis_bridges.c</span><br><span>@@ -1069,7 +1069,7 @@</span><br><span>     case AST_ATTENDED_TRANSFER_DEST_THREEWAY:</span><br><span>            ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");</span><br><span>           ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-             ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+           ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->base->name);</span><br><span>                 break;</span><br><span>       case AST_ATTENDED_TRANSFER_DEST_FAIL:</span><br><span>                ast_str_append(&variable_data, 0, "DestType: Fail\r\n");</span><br><span>@@ -1189,7 +1189,7 @@</span><br><span> {</span><br><span>  transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->base->uniqueid)) {</span><br><span>                transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;</span><br><span>   } else {</span><br><span>             transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;</span><br><span>diff --git a/main/stasis_channels.c b/main/stasis_channels.c</span><br><span>index ec8d70c..d39fb08 100644</span><br><span>--- a/main/stasis_channels.c</span><br><span>+++ b/main/stasis_channels.c</span><br><span>@@ -149,7 +149,7 @@</span><br><span>           key = obj;</span><br><span>           break;</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         key = object->name;</span><br><span style="color: hsl(120, 100%, 40%);">+                key = object->base->name;</span><br><span>              break;</span><br><span>       default:</span><br><span>             ast_assert(0);</span><br><span>@@ -171,12 +171,12 @@</span><br><span> </span><br><span>   switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         right_key = object_right->name;</span><br><span style="color: hsl(120, 100%, 40%);">+            right_key = object_right->base->name;</span><br><span>  case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strcasecmp(object_left->name, right_key);</span><br><span style="color: hsl(120, 100%, 40%);">+            cmp = strcasecmp(object_left->base->name, right_key);</span><br><span>          break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strncasecmp(object_left->name, right_key, strlen(right_key));</span><br><span style="color: hsl(120, 100%, 40%);">+                cmp = strncasecmp(object_left->base->name, right_key, strlen(right_key));</span><br><span>              break;</span><br><span>       default:</span><br><span>             cmp = 0;</span><br><span>@@ -202,7 +202,7 @@</span><br><span>               key = obj;</span><br><span>           break;</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         key = object->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+            key = object->base->uniqueid;</span><br><span>          break;</span><br><span>       default:</span><br><span>             ast_assert(0);</span><br><span>@@ -224,12 +224,12 @@</span><br><span> </span><br><span>   switch (flags & OBJ_SEARCH_MASK) {</span><br><span>       case OBJ_SEARCH_OBJECT:</span><br><span style="color: hsl(0, 100%, 40%);">-         right_key = object_right->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+                right_key = object_right->base->uniqueid;</span><br><span>      case OBJ_SEARCH_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strcasecmp(object_left->uniqueid, right_key);</span><br><span style="color: hsl(120, 100%, 40%);">+                cmp = strcasecmp(object_left->base->uniqueid, right_key);</span><br><span>              break;</span><br><span>       case OBJ_SEARCH_PARTIAL_KEY:</span><br><span style="color: hsl(0, 100%, 40%);">-            cmp = strncasecmp(object_left->uniqueid, right_key, strlen(right_key));</span><br><span style="color: hsl(120, 100%, 40%);">+            cmp = strncasecmp(object_left->base->uniqueid, right_key, strlen(right_key));</span><br><span>          break;</span><br><span>       default:</span><br><span>             cmp = 0;</span><br><span>@@ -245,36 +245,180 @@</span><br><span> {</span><br><span>       struct ast_channel_snapshot *snapshot = obj;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        ast_string_field_free_memory(snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_cleanup(snapshot->base);</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_cleanup(snapshot->peer);</span><br><span style="color: hsl(120, 100%, 40%);">+       ao2_cleanup(snapshot->caller);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_cleanup(snapshot->connected);</span><br><span style="color: hsl(120, 100%, 40%);">+  ao2_cleanup(snapshot->bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_cleanup(snapshot->dialplan);</span><br><span style="color: hsl(120, 100%, 40%);">+   ao2_cleanup(snapshot->hangup);</span><br><span>    ao2_cleanup(snapshot->manager_vars);</span><br><span>      ao2_cleanup(snapshot->ari_vars);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+static void channel_snapshot_base_dtor(void *obj)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_channel_snapshot *snapshot;</span><br><span style="color: hsl(0, 100%, 40%);">-  struct ast_bridge *bridge;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot_base *snapshot = obj;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* no snapshots for dummy channels */</span><br><span style="color: hsl(0, 100%, 40%);">-   if (!ast_channel_tech(chan)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        ast_string_field_free_memory(snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_base *channel_snapshot_base_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_channel_snapshot_base *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_base_dtor,</span><br><span style="color: hsl(120, 100%, 40%);">+           AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!snapshot) {</span><br><span>             return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dtor,</span><br><span style="color: hsl(0, 100%, 40%);">-          AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(0, 100%, 40%);">-     if (!snapshot || ast_string_field_init(snapshot, 1024)) {</span><br><span style="color: hsl(0, 100%, 40%);">-               ao2_cleanup(snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_string_field_init(snapshot, 256)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_ref(snapshot, -1);</span><br><span>               return NULL;</span><br><span>         }</span><br><span> </span><br><span>        ast_string_field_set(snapshot, name, ast_channel_name(chan));</span><br><span>        ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);</span><br><span>       ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));</span><br><span>  ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));</span><br><span>      ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(snapshot, language, ast_channel_language(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       snapshot->creationtime = ast_channel_creationtime(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->tech_properties = ast_channel_tech(chan)->properties;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_peer *channel_snapshot_peer_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const char *linkedid = S_OR(ast_channel_linkedid(chan), "");</span><br><span style="color: hsl(120, 100%, 40%);">+        const char *peeraccount = S_OR(ast_channel_peeraccount(chan), "");</span><br><span style="color: hsl(120, 100%, 40%);">+  size_t linkedid_len = strlen(linkedid) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t peeraccount_len = strlen(peeraccount) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct ast_channel_snapshot_peer *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot = ao2_alloc_options(sizeof(*snapshot) + linkedid_len + peeraccount_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+    if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   strcpy(snapshot->account, peeraccount); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+ snapshot->linkedid = snapshot->account + peeraccount_len;</span><br><span style="color: hsl(120, 100%, 40%);">+       strcpy(snapshot->linkedid, linkedid); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void channel_snapshot_caller_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_channel_snapshot_caller *snapshot = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_free_memory(snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_caller *channel_snapshot_caller_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_channel_snapshot_caller *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_caller_dtor,</span><br><span style="color: hsl(120, 100%, 40%);">+         AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_string_field_init(snapshot, 256)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_string_field_set(snapshot, name,</span><br><span style="color: hsl(120, 100%, 40%);">+          S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_string_field_set(snapshot, number,</span><br><span style="color: hsl(120, 100%, 40%);">+                S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_set(snapshot, subaddr,</span><br><span style="color: hsl(120, 100%, 40%);">+               S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_set(snapshot, ani,</span><br><span style="color: hsl(120, 100%, 40%);">+           S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_string_field_set(snapshot, rdnis,</span><br><span style="color: hsl(120, 100%, 40%);">+         S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_set(snapshot, dnid,</span><br><span style="color: hsl(120, 100%, 40%);">+          S_OR(ast_channel_dialed(chan)->number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_string_field_set(snapshot, dialed_subaddr,</span><br><span style="color: hsl(120, 100%, 40%);">+                S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_connected *channel_snapshot_connected_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *name = S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "");</span><br><span style="color: hsl(120, 100%, 40%);">+   const char *number = S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "");</span><br><span style="color: hsl(120, 100%, 40%);">+     size_t name_len = strlen(name) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   size_t number_len = strlen(number) + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_channel_snapshot_connected *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    snapshot = ao2_alloc_options(sizeof(*snapshot) + name_len + number_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   strcpy(snapshot->name, name); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->number = snapshot->name + name_len;</span><br><span style="color: hsl(120, 100%, 40%);">+   strcpy(snapshot->number, number); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_bridge *channel_snapshot_bridge_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *uniqueid = "";</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_bridge *bridge;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot_bridge *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       bridge = ast_channel_get_bridge(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+        if (bridge && !ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             uniqueid = bridge->uniqueid;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+     ao2_cleanup(bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(uniqueid) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+      if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   strcpy(snapshot->id, uniqueid); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void channel_snapshot_dialplan_dtor(void *obj)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       struct ast_channel_snapshot_dialplan *snapshot = obj;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       ast_string_field_free_memory(snapshot);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_dialplan *channel_snapshot_dialplan_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      struct ast_channel_snapshot_dialplan *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dialplan_dtor,</span><br><span style="color: hsl(120, 100%, 40%);">+               AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_string_field_init(snapshot, 256)) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  if (ast_channel_appl(chan)) {</span><br><span>                ast_string_field_set(snapshot, appl, ast_channel_appl(chan));</span><br><span>        }</span><br><span>@@ -283,50 +427,130 @@</span><br><span>   }</span><br><span>    ast_string_field_set(snapshot, context, ast_channel_context(chan));</span><br><span>  ast_string_field_set(snapshot, exten, ast_channel_exten(chan));</span><br><span style="color: hsl(120, 100%, 40%);">+       snapshot->priority = ast_channel_priority(chan);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(snapshot, caller_name,</span><br><span style="color: hsl(0, 100%, 40%);">-             S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_string_field_set(snapshot, caller_number,</span><br><span style="color: hsl(0, 100%, 40%);">-           S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(snapshot, caller_subaddr,</span><br><span style="color: hsl(0, 100%, 40%);">-          S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(snapshot, caller_ani,</span><br><span style="color: hsl(0, 100%, 40%);">-              S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+     return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- ast_string_field_set(snapshot, caller_rdnis,</span><br><span style="color: hsl(0, 100%, 40%);">-            S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_channel_snapshot_hangup *channel_snapshot_hangup_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *hangupsource = S_OR(ast_channel_hangupsource(chan), "");</span><br><span style="color: hsl(120, 100%, 40%);">+        struct ast_channel_snapshot_hangup *snapshot;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       ast_string_field_set(snapshot, caller_dnid,</span><br><span style="color: hsl(0, 100%, 40%);">-             S_OR(ast_channel_dialed(chan)->number.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_string_field_set(snapshot, dialed_subaddr,</span><br><span style="color: hsl(0, 100%, 40%);">-          S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_string_field_set(snapshot, connected_name,</span><br><span style="color: hsl(0, 100%, 40%);">-          S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">-       ast_string_field_set(snapshot, connected_number,</span><br><span style="color: hsl(0, 100%, 40%);">-                S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   ast_string_field_set(snapshot, language, ast_channel_language(chan));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-   if ((bridge = ast_channel_get_bridge(chan))) {</span><br><span style="color: hsl(0, 100%, 40%);">-          if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                 ast_string_field_set(snapshot, bridgeid, bridge->uniqueid);</span><br><span style="color: hsl(0, 100%, 40%);">-          }</span><br><span style="color: hsl(0, 100%, 40%);">-               ao2_cleanup(bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+  snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(hangupsource) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   snapshot->creationtime = ast_channel_creationtime(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->cause = ast_channel_hangupcause(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+   strcpy(snapshot->source, hangupsource); /* Safe */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       return snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  struct ast_channel_snapshot *old_snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+    struct ast_channel_snapshot *snapshot;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* no snapshots for dummy channels */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!ast_channel_tech(chan)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dtor,</span><br><span style="color: hsl(120, 100%, 40%);">+                AO2_ALLOC_OPT_LOCK_NOLOCK);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!snapshot) {</span><br><span style="color: hsl(120, 100%, 40%);">+              return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   old_snapshot = ast_channel_snapshot(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Channels automatically have all segments invalidated on them initially so a check for an old</span><br><span style="color: hsl(120, 100%, 40%);">+        * snapshot existing before usage is not done here, as it can not happen. If the stored snapshot</span><br><span style="color: hsl(120, 100%, 40%);">+       * on the channel is updated as a result of this then all segments marked as invalidated will be</span><br><span style="color: hsl(120, 100%, 40%);">+       * cleared.</span><br><span style="color: hsl(120, 100%, 40%);">+    */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* The base information has changed so update our snapshot */</span><br><span style="color: hsl(120, 100%, 40%);">+         snapshot->base = channel_snapshot_base_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!snapshot->base) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              snapshot->base = ao2_bump(old_snapshot->base);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER)) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* The peer information has changed so update our snapshot */</span><br><span style="color: hsl(120, 100%, 40%);">+         snapshot->peer = channel_snapshot_peer_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!snapshot->peer) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              snapshot->peer = ao2_bump(old_snapshot->peer);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Unfortunately both caller and connected information do not have an enforced contract with</span><br><span style="color: hsl(120, 100%, 40%);">+   * the channel API. This has allowed consumers to directly get the caller or connected structure</span><br><span style="color: hsl(120, 100%, 40%);">+       * and manipulate it. Until such time as there is an enforced contract (which is being tracked under</span><br><span style="color: hsl(120, 100%, 40%);">+   * ASTERISK-28164) they are each regenerated every time a channel snapshot is created.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->caller = channel_snapshot_caller_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!snapshot->caller) {</span><br><span style="color: hsl(120, 100%, 40%);">+           ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   snapshot->connected = channel_snapshot_connected_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (!snapshot->connected) {</span><br><span style="color: hsl(120, 100%, 40%);">+                ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* The bridge has changed so update our snapshot */</span><br><span style="color: hsl(120, 100%, 40%);">+           snapshot->bridge = channel_snapshot_bridge_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!snapshot->bridge) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              snapshot->bridge = ao2_bump(old_snapshot->bridge);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN)) {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* The dialplan information has changed so update our snapshot */</span><br><span style="color: hsl(120, 100%, 40%);">+             snapshot->dialplan = channel_snapshot_dialplan_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!snapshot->dialplan) {</span><br><span style="color: hsl(120, 100%, 40%);">+                 ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              snapshot->dialplan = ao2_bump(old_snapshot->dialplan);</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* The hangup information has changed so update our snapshot */</span><br><span style="color: hsl(120, 100%, 40%);">+               snapshot->hangup = channel_snapshot_hangup_create(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+           if (!snapshot->hangup) {</span><br><span style="color: hsl(120, 100%, 40%);">+                   ao2_ref(snapshot, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+                        return NULL;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              snapshot->hangup = ao2_bump(old_snapshot->hangup);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  snapshot->state = ast_channel_state(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-   snapshot->priority = ast_channel_priority(chan);</span><br><span>  snapshot->amaflags = ast_channel_amaflags(chan);</span><br><span style="color: hsl(0, 100%, 40%);">-     snapshot->hangupcause = ast_channel_hangupcause(chan);</span><br><span>    ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);</span><br><span style="color: hsl(0, 100%, 40%);">-   snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);</span><br><span>  ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+     /* These have to be recreated as they may have changed, unfortunately */</span><br><span>     snapshot->manager_vars = ast_channel_get_manager_vars(chan);</span><br><span>      snapshot->ari_vars = ast_channel_get_ari_vars(chan);</span><br><span style="color: hsl(0, 100%, 40%);">- snapshot->tech_properties = ast_channel_tech(chan)->properties;</span><br><span> </span><br><span>    return snapshot;</span><br><span> }</span><br><span>@@ -822,6 +1046,12 @@</span><br><span>        ast_channel_publish_snapshot(chan);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan,</span><br><span style="color: hsl(120, 100%, 40%);">+  enum ast_channel_snapshot_segment_invalidation segment)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_set_flag(ast_channel_snapshot_segment_flags(chan), segment);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void ast_channel_publish_snapshot(struct ast_channel *chan)</span><br><span> {</span><br><span>    struct ast_channel_snapshot_update *update;</span><br><span>@@ -840,6 +1070,14 @@</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* If an old snapshot exists and is the same as this newly created one don't bother</span><br><span style="color: hsl(120, 100%, 40%);">+        * raising a message as it hasn't changed.</span><br><span style="color: hsl(120, 100%, 40%);">+         */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (update->old_snapshot && !memcmp(update->old_snapshot, update->new_snapshot, sizeof(struct ast_channel_snapshot))) {</span><br><span style="color: hsl(120, 100%, 40%);">+              ao2_ref(update, -1);</span><br><span style="color: hsl(120, 100%, 40%);">+          return;</span><br><span style="color: hsl(120, 100%, 40%);">+       }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  message = stasis_message_create(ast_channel_snapshot_type(), update);</span><br><span>        /* In the success path message holds a reference to update so it will be valid</span><br><span>        * for the lifetime of this function until the end.</span><br><span>@@ -869,6 +1107,11 @@</span><br><span> </span><br><span>      ast_channel_snapshot_set(chan, update->new_snapshot);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+  /* As this is now the new snapshot any existing invalidated segments have been</span><br><span style="color: hsl(120, 100%, 40%);">+         * created fresh and are up to date.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_clear_flag(ast_channel_snapshot_segment_flags(chan), AST_FLAGS_ALL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>   ast_assert(ast_channel_topic(chan) != NULL);</span><br><span>         stasis_publish(ast_channel_topic(chan), message);</span><br><span>    ao2_ref(message, -1);</span><br><span>@@ -1028,20 +1271,20 @@</span><br><span>              "  s: o, s: o, s: s,"</span><br><span>              "  s: o, s: o, s: s }",</span><br><span>            /* First line */</span><br><span style="color: hsl(0, 100%, 40%);">-                "id", snapshot->uniqueid,</span><br><span style="color: hsl(0, 100%, 40%);">-          "name", snapshot->name,</span><br><span style="color: hsl(120, 100%, 40%);">+          "id", snapshot->base->uniqueid,</span><br><span style="color: hsl(120, 100%, 40%);">+               "name", snapshot->base->name,</span><br><span>                "state", ast_state2str(snapshot->state),</span><br><span>                /* Second line */</span><br><span>            "caller", ast_json_name_number(</span><br><span style="color: hsl(0, 100%, 40%);">-                       snapshot->caller_name, snapshot->caller_number),</span><br><span style="color: hsl(120, 100%, 40%);">+                        snapshot->caller->name, snapshot->caller->number),</span><br><span>               "connected", ast_json_name_number(</span><br><span style="color: hsl(0, 100%, 40%);">-                    snapshot->connected_name, snapshot->connected_number),</span><br><span style="color: hsl(0, 100%, 40%);">-            "accountcode", snapshot->accountcode,</span><br><span style="color: hsl(120, 100%, 40%);">+                    snapshot->connected->name, snapshot->connected->number),</span><br><span style="color: hsl(120, 100%, 40%);">+          "accountcode", snapshot->base->accountcode,</span><br><span>          /* Third line */</span><br><span>             "dialplan", ast_json_dialplan_cep(</span><br><span style="color: hsl(0, 100%, 40%);">-                    snapshot->context, snapshot->exten, snapshot->priority),</span><br><span style="color: hsl(0, 100%, 40%);">-               "creationtime", ast_json_timeval(snapshot->creationtime, NULL),</span><br><span style="color: hsl(0, 100%, 40%);">-            "language", snapshot->language);</span><br><span style="color: hsl(120, 100%, 40%);">+                 snapshot->dialplan->context, snapshot->dialplan->exten, snapshot->dialplan->priority),</span><br><span style="color: hsl(120, 100%, 40%);">+              "creationtime", ast_json_timeval(snapshot->base->creationtime, NULL),</span><br><span style="color: hsl(120, 100%, 40%);">+         "language", snapshot->base->language);</span><br><span> </span><br><span>   if (snapshot->ari_vars && !AST_LIST_EMPTY(snapshot->ari_vars)) {</span><br><span>               ast_json_object_set(json_chan, "channelvars", ast_json_channel_vars(snapshot->ari_vars));</span><br><span>@@ -1061,14 +1304,14 @@</span><br><span>      * application is set. Since empty application is invalid, we treat</span><br><span>   * setting the application from nothing as a CEP change.</span><br><span>      */</span><br><span style="color: hsl(0, 100%, 40%);">-     if (ast_strlen_zero(old_snapshot->appl) &&</span><br><span style="color: hsl(0, 100%, 40%);">-       !ast_strlen_zero(new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (ast_strlen_zero(old_snapshot->dialplan->appl) &&</span><br><span style="color: hsl(120, 100%, 40%);">+        !ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span>          return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   return old_snapshot->priority == new_snapshot->priority &&</span><br><span style="color: hsl(0, 100%, 40%);">-                strcmp(old_snapshot->context, new_snapshot->context) == 0 &&</span><br><span style="color: hsl(0, 100%, 40%);">-              strcmp(old_snapshot->exten, new_snapshot->exten) == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  return old_snapshot->dialplan->priority == new_snapshot->dialplan->priority &&</span><br><span style="color: hsl(120, 100%, 40%);">+            strcmp(old_snapshot->dialplan->context, new_snapshot->dialplan->context) == 0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+          strcmp(old_snapshot->dialplan->exten, new_snapshot->dialplan->exten) == 0;</span><br><span> }</span><br><span> </span><br><span> int ast_channel_snapshot_caller_id_equal(</span><br><span>@@ -1077,8 +1320,8 @@</span><br><span> {</span><br><span>    ast_assert(old_snapshot != NULL);</span><br><span>    ast_assert(new_snapshot != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&</span><br><span style="color: hsl(0, 100%, 40%);">-           strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+      return strcmp(old_snapshot->caller->number, new_snapshot->caller->number) == 0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+         strcmp(old_snapshot->caller->name, new_snapshot->caller->name) == 0;</span><br><span> }</span><br><span> </span><br><span> int ast_channel_snapshot_connected_line_equal(</span><br><span>@@ -1087,8 +1330,8 @@</span><br><span> {</span><br><span>     ast_assert(old_snapshot != NULL);</span><br><span>    ast_assert(new_snapshot != NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-       return strcmp(old_snapshot->connected_number, new_snapshot->connected_number) == 0 &&</span><br><span style="color: hsl(0, 100%, 40%);">-             strcmp(old_snapshot->connected_name, new_snapshot->connected_name) == 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        return strcmp(old_snapshot->connected->number, new_snapshot->connected->number) == 0 &&</span><br><span style="color: hsl(120, 100%, 40%);">+           strcmp(old_snapshot->connected->name, new_snapshot->connected->name) == 0;</span><br><span> }</span><br><span> </span><br><span> static struct ast_json *channel_blob_to_json(</span><br><span>diff --git a/pbx/pbx_realtime.c b/pbx/pbx_realtime.c</span><br><span>index 75e6654..970bb3c 100644</span><br><span>--- a/pbx/pbx_realtime.c</span><br><span>+++ b/pbx/pbx_realtime.c</span><br><span>@@ -344,6 +344,11 @@</span><br><span>                                                  term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));</span><br><span>                           if (ast_channel_snapshot_type()) {</span><br><span>                                   ast_channel_lock(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+                                       /* Force a new dialplan segment that will be unique to use so we can update it with the</span><br><span style="color: hsl(120, 100%, 40%);">+                                        * information we want. In the future when a channel snapshot is published this will</span><br><span style="color: hsl(120, 100%, 40%);">+                                   * occur again and unset this flag.</span><br><span style="color: hsl(120, 100%, 40%);">+                                    */</span><br><span style="color: hsl(120, 100%, 40%);">+                                   ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);</span><br><span>                                     snapshot = ast_channel_snapshot_create(chan);</span><br><span>                                        ast_channel_unlock(chan);</span><br><span>                            }</span><br><span>@@ -351,8 +356,8 @@</span><br><span>                                      /* pbx_exec sets application name and data, but we don't want to log</span><br><span>                                      * every exec. Just update the snapshot here instead.</span><br><span>                                         */</span><br><span style="color: hsl(0, 100%, 40%);">-                                     ast_string_field_set(snapshot, appl, app);</span><br><span style="color: hsl(0, 100%, 40%);">-                                      ast_string_field_set(snapshot, data, !ast_strlen_zero(appdata) ? appdata : "(NULL)");</span><br><span style="color: hsl(120, 100%, 40%);">+                                       ast_string_field_set(snapshot->dialplan, appl, app);</span><br><span style="color: hsl(120, 100%, 40%);">+                                       ast_string_field_set(snapshot->dialplan, data, !ast_strlen_zero(appdata) ? appdata : "(NULL)");</span><br><span>                                         msg = stasis_message_create(ast_channel_snapshot_type(), snapshot);</span><br><span>                                  if (msg) {</span><br><span>                                           stasis_publish(ast_channel_topic(chan), msg);</span><br><span>diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c</span><br><span>index e5fa41c..3c0eeb7 100644</span><br><span>--- a/res/ari/resource_bridges.c</span><br><span>+++ b/res/ari/resource_bridges.c</span><br><span>@@ -377,7 +377,7 @@</span><br><span>             return -1;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   language = S_OR(args_lang, snapshot->language);</span><br><span style="color: hsl(120, 100%, 40%);">+    language = S_OR(args_lang, snapshot->base->language);</span><br><span> </span><br><span>      playback = stasis_app_control_play_uri(control, args_media, args_media_count,</span><br><span>                language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,</span><br><span>diff --git a/res/ari/resource_channels.c b/res/ari/resource_channels.c</span><br><span>index f96192b..311358e 100644</span><br><span>--- a/res/ari/resource_channels.c</span><br><span>+++ b/res/ari/resource_channels.c</span><br><span>@@ -170,8 +170,8 @@</span><br><span>    }</span><br><span> </span><br><span>        if (ast_strlen_zero(args->context)) {</span><br><span style="color: hsl(0, 100%, 40%);">-                context = snapshot->context;</span><br><span style="color: hsl(0, 100%, 40%);">-         exten = S_OR(args->extension, snapshot->exten);</span><br><span style="color: hsl(120, 100%, 40%);">+         context = snapshot->dialplan->context;</span><br><span style="color: hsl(120, 100%, 40%);">+          exten = S_OR(args->extension, snapshot->dialplan->exten);</span><br><span>   } else {</span><br><span>             context = args->context;</span><br><span>          exten = S_OR(args->extension, "s");</span><br><span>@@ -203,7 +203,7 @@</span><br><span>               ipri = args->priority;</span><br><span>    } else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {</span><br><span>               /* Special case. No exten, context, or priority provided, then move on to the next priority */</span><br><span style="color: hsl(0, 100%, 40%);">-          ipri = snapshot->priority + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             ipri = snapshot->dialplan->priority + 1;</span><br><span>       } else {</span><br><span>             ipri = 1;</span><br><span>    }</span><br><span>@@ -263,10 +263,10 @@</span><br><span>            return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (strncasecmp(chan_snapshot->type, tech, tech_len)) {</span><br><span style="color: hsl(120, 100%, 40%);">+    if (strncasecmp(chan_snapshot->base->type, tech, tech_len)) {</span><br><span>          ast_ari_response_error(response, 422, "Unprocessable Entity",</span><br><span>                      "Endpoint technology '%s' does not match channel technology '%s'",</span><br><span style="color: hsl(0, 100%, 40%);">-                    tech, chan_snapshot->type);</span><br><span style="color: hsl(120, 100%, 40%);">+                        tech, chan_snapshot->base->type);</span><br><span>              return;</span><br><span>      }</span><br><span> </span><br><span>@@ -628,7 +628,7 @@</span><br><span>          return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   language = S_OR(args_lang, snapshot->language);</span><br><span style="color: hsl(120, 100%, 40%);">+    language = S_OR(args_lang, snapshot->base->language);</span><br><span> </span><br><span>      playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,</span><br><span>              args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);</span><br><span>diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c</span><br><span>index f9b3e85..46dbedf 100644</span><br><span>--- a/res/parking/parking_applications.c</span><br><span>+++ b/res/parking/parking_applications.c</span><br><span>@@ -819,12 +819,12 @@</span><br><span>         snprintf(buf, sizeof(buf), "%d", parkingspace);</span><br><span>    oh.vars = ast_variable_new("_PARKEDAT", buf, "");</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       inherit_channel_vars_from_id(&oh, parkee_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+  inherit_channel_vars_from_id(&oh, parkee_snapshot->base->uniqueid);</span><br><span> </span><br><span>    dchan = __ast_request_and_dial(dial_tech, cap_slin, NULL, NULL, dial_string, 30000,</span><br><span>          &outstate,</span><br><span style="color: hsl(0, 100%, 40%);">-          parkee_snapshot->caller_number,</span><br><span style="color: hsl(0, 100%, 40%);">-              parkee_snapshot->caller_name,</span><br><span style="color: hsl(120, 100%, 40%);">+              parkee_snapshot->caller->number,</span><br><span style="color: hsl(120, 100%, 40%);">+                parkee_snapshot->caller->name,</span><br><span>                 &oh);</span><br><span> </span><br><span>        ast_variables_destroy(oh.vars);</span><br><span>@@ -877,7 +877,7 @@</span><br><span>                return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (strcmp(payload->parkee->uniqueid, pa_data->parkee_uuid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+       if (strcmp(payload->parkee->base->uniqueid, pa_data->parkee_uuid)) {</span><br><span>             /* We are only concerned with the parkee we are subscribed for. */</span><br><span>           return;</span><br><span>      }</span><br><span>diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c</span><br><span>index 1d3b9e4..d619471 100644</span><br><span>--- a/res/parking/parking_bridge_features.c</span><br><span>+++ b/res/parking/parking_bridge_features.c</span><br><span>@@ -111,7 +111,7 @@</span><br><span>     RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup);</span><br><span>   RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(parkee_to_act_on, parkee_snapshot->base->uniqueid)) {</span><br><span>               return;</span><br><span>      }</span><br><span> </span><br><span>diff --git a/res/res_chan_stats.c b/res/res_chan_stats.c</span><br><span>index bed95a0..e32498b 100644</span><br><span>--- a/res/res_chan_stats.c</span><br><span>+++ b/res/res_chan_stats.c</span><br><span>@@ -110,7 +110,7 @@</span><br><span>             int64_t age;</span><br><span> </span><br><span>             age = ast_tvdiff_ms(*stasis_message_timestamp(message),</span><br><span style="color: hsl(0, 100%, 40%);">-                 update->new_snapshot->creationtime);</span><br><span style="color: hsl(120, 100%, 40%);">+                    update->new_snapshot->base->creationtime);</span><br><span>          ast_statsd_log("channels.calltime", AST_STATSD_TIMER, age);</span><br><span> </span><br><span>            /* And decrement the channel count */</span><br><span>diff --git a/res/res_pjsip/pjsip_configuration.c b/res/res_pjsip/pjsip_configuration.c</span><br><span>index 41195be..d88024a 100644</span><br><span>--- a/res/res_pjsip/pjsip_configuration.c</span><br><span>+++ b/res/res_pjsip/pjsip_configuration.c</span><br><span>@@ -1351,7 +1351,7 @@</span><br><span> {</span><br><span>  const struct ast_channel_snapshot *snapshot = object;</span><br><span>        struct ast_str **buf = arg;</span><br><span style="color: hsl(0, 100%, 40%);">-     ast_str_append(buf, 0, "%s,", snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+   ast_str_append(buf, 0, "%s,", snapshot->base->name);</span><br><span>         return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c</span><br><span>index 3dfaabc..9b75146 100644</span><br><span>--- a/res/res_pjsip_refer.c</span><br><span>+++ b/res/res_pjsip_refer.c</span><br><span>@@ -179,7 +179,7 @@</span><br><span>    }</span><br><span> </span><br><span>        enter_blob = stasis_message_data(message);</span><br><span style="color: hsl(0, 100%, 40%);">-      if (strcmp(enter_blob->channel->uniqueid, progress->transferee)) {</span><br><span style="color: hsl(120, 100%, 40%);">+   if (strcmp(enter_blob->channel->base->uniqueid, progress->transferee)) {</span><br><span>                 /* Don't care */</span><br><span>                 return;</span><br><span>      }</span><br><span>diff --git a/res/res_stasis.c b/res/res_stasis.c</span><br><span>index 704d779..43833e1 100644</span><br><span>--- a/res/res_stasis.c</span><br><span>+++ b/res/res_stasis.c</span><br><span>@@ -1019,7 +1019,7 @@</span><br><span>       }</span><br><span> </span><br><span>        if (replace_channel_snapshot) {</span><br><span style="color: hsl(0, 100%, 40%);">-         app_unsubscribe_channel_id(app, replace_channel_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+               app_unsubscribe_channel_id(app, replace_channel_snapshot->base->uniqueid);</span><br><span>     }</span><br><span>    stasis_publish(ast_app_get_topic(app), msg);</span><br><span>         ao2_ref(msg, -1);</span><br><span>@@ -2051,7 +2051,7 @@</span><br><span> /* \brief Sanitization callback for channel snapshots */</span><br><span> static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        if (!snapshot || !(snapshot->tech_properties & AST_CHAN_TP_INTERNAL)) {</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!snapshot || !(snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {</span><br><span>              return 0;</span><br><span>    }</span><br><span>    return 1;</span><br><span>diff --git a/res/stasis/app.c b/res/stasis/app.c</span><br><span>index b4f3bc6..78f5765 100644</span><br><span>--- a/res/stasis/app.c</span><br><span>+++ b/res/stasis/app.c</span><br><span>@@ -315,7 +315,7 @@</span><br><span>                 return;</span><br><span>      }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   chan = ast_channel_get_by_name(snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+        chan = ast_channel_get_by_name(snapshot->base->uniqueid);</span><br><span>      if (!chan) {</span><br><span>                 return;</span><br><span>      }</span><br><span>@@ -391,8 +391,8 @@</span><br><span>      return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",</span><br><span>             "type", "ChannelDestroyed",</span><br><span>              "timestamp", ast_json_timeval(*tv, NULL),</span><br><span style="color: hsl(0, 100%, 40%);">-             "cause", snapshot->hangupcause,</span><br><span style="color: hsl(0, 100%, 40%);">-            "cause_txt", ast_cause2str(snapshot->hangupcause),</span><br><span style="color: hsl(120, 100%, 40%);">+               "cause", snapshot->hangup->cause,</span><br><span style="color: hsl(120, 100%, 40%);">+             "cause_txt", ast_cause2str(snapshot->hangup->cause),</span><br><span>                 "channel", json_channel);</span><br><span> }</span><br><span> </span><br><span>@@ -436,7 +436,7 @@</span><br><span>   }</span><br><span> </span><br><span>        /* Empty application is not valid for a Newexten event */</span><br><span style="color: hsl(0, 100%, 40%);">-       if (ast_strlen_zero(new_snapshot->appl)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(new_snapshot->dialplan->appl)) {</span><br><span>           return NULL;</span><br><span>         }</span><br><span> </span><br><span>@@ -452,8 +452,8 @@</span><br><span>  return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",</span><br><span>             "type", "ChannelDialplan",</span><br><span>               "timestamp", ast_json_timeval(*tv, NULL),</span><br><span style="color: hsl(0, 100%, 40%);">-             "dialplan_app", new_snapshot->appl,</span><br><span style="color: hsl(0, 100%, 40%);">-                "dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->data),</span><br><span style="color: hsl(120, 100%, 40%);">+         "dialplan_app", new_snapshot->dialplan->appl,</span><br><span style="color: hsl(120, 100%, 40%);">+         "dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->dialplan->data),</span><br><span>           "channel", json_channel);</span><br><span> }</span><br><span> </span><br><span>@@ -481,9 +481,9 @@</span><br><span>   return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",</span><br><span>             "type", "ChannelCallerId",</span><br><span>               "timestamp", ast_json_timeval(*tv, NULL),</span><br><span style="color: hsl(0, 100%, 40%);">-             "caller_presentation", new_snapshot->caller_pres,</span><br><span style="color: hsl(120, 100%, 40%);">+                "caller_presentation", new_snapshot->caller->pres,</span><br><span>           "caller_presentation_txt", ast_describe_caller_presentation(</span><br><span style="color: hsl(0, 100%, 40%);">-                  new_snapshot->caller_pres),</span><br><span style="color: hsl(120, 100%, 40%);">+                        new_snapshot->caller->pres),</span><br><span>           "channel", json_channel);</span><br><span> }</span><br><span> </span><br><span>@@ -541,7 +541,7 @@</span><br><span>   }</span><br><span> </span><br><span>        if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {</span><br><span style="color: hsl(0, 100%, 40%);">-             unsubscribe(app, "channel", update->new_snapshot->uniqueid, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+               unsubscribe(app, "channel", update->new_snapshot->base->uniqueid, 1);</span><br><span>     }</span><br><span> }</span><br><span> </span><br><span>@@ -768,7 +768,7 @@</span><br><span>     struct ast_blind_transfer_message *transfer_msg = stasis_message_data(message);</span><br><span>      struct ast_bridge_snapshot *bridge = transfer_msg->bridge;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       if (bridge_app_subscribed(app, transfer_msg->transferer->uniqueid) ||</span><br><span style="color: hsl(120, 100%, 40%);">+   if (bridge_app_subscribed(app, transfer_msg->transferer->base->uniqueid) ||</span><br><span>                 (bridge && bridge_app_subscribed_involved(app, bridge))) {</span><br><span>           stasis_publish(app->topic, message);</span><br><span>      }</span><br><span>@@ -781,9 +781,9 @@</span><br><span>      struct ast_attended_transfer_message *transfer_msg = stasis_message_data(message);</span><br><span>   int subscribed = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- subscribed = bridge_app_subscribed(app, transfer_msg->to_transferee.channel_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+        subscribed = bridge_app_subscribed(app, transfer_msg->to_transferee.channel_snapshot->base->uniqueid);</span><br><span>      if (!subscribed) {</span><br><span style="color: hsl(0, 100%, 40%);">-              subscribed = bridge_app_subscribed(app, transfer_msg->to_transfer_target.channel_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+           subscribed = bridge_app_subscribed(app, transfer_msg->to_transfer_target.channel_snapshot->base->uniqueid);</span><br><span>         }</span><br><span>    if (!subscribed && transfer_msg->to_transferee.bridge_snapshot) {</span><br><span>                 subscribed = bridge_app_subscribed_involved(app, transfer_msg->to_transferee.bridge_snapshot);</span><br><span>@@ -798,16 +798,16 @@</span><br><span>                    subscribed = bridge_app_subscribed(app, transfer_msg->dest.bridge);</span><br><span>                       break;</span><br><span>               case AST_ATTENDED_TRANSFER_DEST_LINK:</span><br><span style="color: hsl(0, 100%, 40%);">-                   subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[0]->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                 subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[0]->base->uniqueid);</span><br><span>                       if (!subscribed) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[1]->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                         subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[1]->base->uniqueid);</span><br><span>                       }</span><br><span>                    break;</span><br><span>               break;</span><br><span>               case AST_ATTENDED_TRANSFER_DEST_THREEWAY:</span><br><span>                    subscribed = bridge_app_subscribed_involved(app, transfer_msg->dest.threeway.bridge_snapshot);</span><br><span>                    if (!subscribed) {</span><br><span style="color: hsl(0, 100%, 40%);">-                              subscribed = bridge_app_subscribed(app, transfer_msg->dest.threeway.channel_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+                                subscribed = bridge_app_subscribed(app, transfer_msg->dest.threeway.channel_snapshot->base->uniqueid);</span><br><span>                      }</span><br><span>                    break;</span><br><span>               default:</span><br><span>diff --git a/tests/test_cel.c b/tests/test_cel.c</span><br><span>index c1e7340..6c8bd61 100644</span><br><span>--- a/tests/test_cel.c</span><br><span>+++ b/tests/test_cel.c</span><br><span>@@ -329,7 +329,7 @@</span><br><span>                  ao2_cleanup);</span><br><span> </span><br><span>            /* Don't add the channel for which this message is being generated */</span><br><span style="color: hsl(0, 100%, 40%);">-               if (!strcmp(current_chan, chan->uniqueid)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               if (!strcmp(current_chan, chan->base->uniqueid)) {</span><br><span>                     continue;</span><br><span>            }</span><br><span> </span><br><span>@@ -338,7 +338,7 @@</span><br><span>                  continue;</span><br><span>            }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-           ast_str_append(&peer_str, 0, "%s,", current_snapshot->name);</span><br><span style="color: hsl(120, 100%, 40%);">+         ast_str_append(&peer_str, 0, "%s,", current_snapshot->base->name);</span><br><span>       }</span><br><span>    ao2_iterator_destroy(&i);</span><br><span> </span><br><span>@@ -1668,8 +1668,8 @@</span><br><span>    stasis_publish(ast_channel_topic(chan_alice), local_opt_begin);</span><br><span>      stasis_publish(ast_channel_topic(chan_alice), local_opt_end);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       extra = ast_json_pack("{s: s, s: s}", "local_two", bob_snapshot->name,</span><br><span style="color: hsl(0, 100%, 40%);">-           "local_two_uniqueid", bob_snapshot->uniqueid);</span><br><span style="color: hsl(120, 100%, 40%);">+   extra = ast_json_pack("{s: s, s: s}", "local_two", bob_snapshot->base->name,</span><br><span style="color: hsl(120, 100%, 40%);">+                "local_two_uniqueid", bob_snapshot->base->uniqueid);</span><br><span>         ast_test_validate(test, extra != NULL);</span><br><span> </span><br><span>  APPEND_EVENT_SNAPSHOT(alice_snapshot, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);</span><br><span>diff --git a/tests/test_stasis_channels.c b/tests/test_stasis_channels.c</span><br><span>index f73d882..f8d2a03 100644</span><br><span>--- a/tests/test_stasis_channels.c</span><br><span>+++ b/tests/test_stasis_channels.c</span><br><span>@@ -220,12 +220,12 @@</span><br><span>       /* Test for single match */</span><br><span>  snapshot = ast_multi_channel_blob_get_channel(blob, "Caller");</span><br><span>     ast_test_validate(test, NULL != snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_test_validate(test, 0 == strcmp("TEST/Alice", snapshot->name));</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_test_validate(test, 0 == strcmp("TEST/Alice", snapshot->base->name));</span><br><span> </span><br><span>        /* Test for single match, multiple possibilities */</span><br><span>  snapshot = ast_multi_channel_blob_get_channel(blob, "Peer");</span><br><span>       ast_test_validate(test, NULL != snapshot);</span><br><span style="color: hsl(0, 100%, 40%);">-      ast_test_validate(test, 0 != strcmp("TEST/Alice", snapshot->name));</span><br><span style="color: hsl(120, 100%, 40%);">+      ast_test_validate(test, 0 != strcmp("TEST/Alice", snapshot->base->name));</span><br><span> </span><br><span>        /* Multi-match */</span><br><span>    matches = ast_multi_channel_blob_get_channels(blob, "Peer");</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/10622">change 10622</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/10622"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I5d7ef3df963a88ac47bc187d73c5225c315f8423 </div>
<div style="display:none"> Gerrit-Change-Number: 10622 </div>
<div style="display:none"> Gerrit-PatchSet: 10 </div>
<div style="display:none"> Gerrit-Owner: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 (1000185) </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>