<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>