Merge "stasis: Segment channel snapshot to reduce creation cost."

pull/12/head
Jenkins2 7 years ago committed by Gerrit Code Review
commit 4ca709768d

@ -5890,13 +5890,13 @@ static void queue_agent_cb(void *userdata, struct stasis_subscription *sub,
agent_blob = stasis_message_data(msg);
if (ast_channel_agent_login_type() == stasis_message_type(msg)) {
ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,
ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
"AGENTLOGIN", "%s", agent_blob->snapshot->name);
"AGENTLOGIN", "%s", agent_blob->snapshot->base->name);
} else if (ast_channel_agent_logoff_type() == stasis_message_type(msg)) {
ast_queue_log("NONE", agent_blob->snapshot->uniqueid,
ast_queue_log("NONE", agent_blob->snapshot->base->uniqueid,
ast_json_string_get(ast_json_object_get(agent_blob->blob, "agent")),
"AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->name,
"AGENTLOGOFF", "%s|%ld", agent_blob->snapshot->base->name,
(long) ast_json_integer_get(ast_json_object_get(agent_blob->blob, "logintime")));
}
}
@ -6088,8 +6088,8 @@ static void log_attended_transfer(struct queue_stasis_data *queue_data, struct a
ast_str_set(&transfer_str, 0, "APP|%s", atxfer_msg->dest.app);
break;
case AST_ATTENDED_TRANSFER_DEST_LINK:
ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->name,
atxfer_msg->dest.links[1]->name);
ast_str_set(&transfer_str, 0, "LINK|%s|%s", atxfer_msg->dest.links[0]->base->name,
atxfer_msg->dest.links[1]->base->name);
break;
case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
case AST_ATTENDED_TRANSFER_DEST_FAIL:
@ -6098,7 +6098,7 @@ static void log_attended_transfer(struct queue_stasis_data *queue_data, struct a
return;
}
ast_queue_log(queue_data->queue->name, caller->uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",
ast_queue_log(queue_data->queue->name, caller->base->uniqueid, queue_data->member->membername, "ATTENDEDTRANSFER", "%s|%ld|%ld|%d",
ast_str_buffer(transfer_str),
(long) (queue_data->starttime - queue_data->holdstart),
(long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);
@ -6131,11 +6131,11 @@ static void handle_bridge_enter(void *userdata, struct stasis_subscription *sub,
return;
}
if (!strcmp(enter_blob->channel->uniqueid, queue_data->caller_uniqueid)) {
if (!strcmp(enter_blob->channel->base->uniqueid, queue_data->caller_uniqueid)) {
ast_string_field_set(queue_data, bridge_uniqueid,
enter_blob->bridge->uniqueid);
ast_debug(3, "Detected entry of caller channel %s into bridge %s\n",
enter_blob->channel->name, queue_data->bridge_uniqueid);
enter_blob->channel->base->name, queue_data->bridge_uniqueid);
}
}
@ -6186,7 +6186,7 @@ static void handle_blind_transfer(void *userdata, struct stasis_subscription *su
context = transfer_msg->context;
ast_debug(3, "Detected blind transfer in queue %s\n", queue_data->queue->name);
ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,
ast_queue_log(queue_data->queue->name, caller_snapshot->base->uniqueid, queue_data->member->membername,
"BLINDTRANSFER", "%s|%s|%ld|%ld|%d",
exten, context,
(long) (queue_data->starttime - queue_data->holdstart),
@ -6302,9 +6302,9 @@ static void handle_local_optimization_begin(void *userdata, struct stasis_subscr
return;
}
if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
optimization = &queue_data->member_optimize;
} else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
} else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
optimization = &queue_data->caller_optimize;
} else {
return;
@ -6313,9 +6313,9 @@ static void handle_local_optimization_begin(void *userdata, struct stasis_subscr
/* We only allow move-swap optimizations, so there had BETTER be a source */
ast_assert(source != NULL);
optimization->source_chan_uniqueid = ast_strdup(source->uniqueid);
optimization->source_chan_uniqueid = ast_strdup(source->base->uniqueid);
if (!optimization->source_chan_uniqueid) {
ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->name);
ast_log(LOG_ERROR, "Unable to track local channel optimization for channel %s. Expect further errors\n", local_one->base->name);
return;
}
id = ast_json_integer_get(ast_json_object_get(ast_multi_channel_blob_get_json(optimization_blob), "id"));
@ -6354,10 +6354,10 @@ static void handle_local_optimization_end(void *userdata, struct stasis_subscrip
return;
}
if (!strcmp(local_one->uniqueid, queue_data->member_uniqueid)) {
if (!strcmp(local_one->base->uniqueid, queue_data->member_uniqueid)) {
optimization = &queue_data->member_optimize;
is_caller = 0;
} else if (!strcmp(local_two->uniqueid, queue_data->caller_uniqueid)) {
} else if (!strcmp(local_two->base->uniqueid, queue_data->caller_uniqueid)) {
optimization = &queue_data->caller_optimize;
is_caller = 1;
} else {
@ -6420,16 +6420,16 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub,
return;
}
if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->caller_uniqueid)) {
if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->caller_uniqueid)) {
reason = CALLER;
} else if (!strcmp(channel_blob->snapshot->uniqueid, queue_data->member_uniqueid)) {
} else if (!strcmp(channel_blob->snapshot->base->uniqueid, queue_data->member_uniqueid)) {
reason = AGENT;
} else {
ao2_unlock(queue_data);
return;
}
chan = ast_channel_get_by_name(channel_blob->snapshot->name);
chan = ast_channel_get_by_name(channel_blob->snapshot->base->name);
if (chan && (ast_channel_has_role(chan, AST_TRANSFERER_ROLE_NAME) ||
!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "ATTENDEDTRANSFER")) ||
!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "BLINDTRANSFER")))) {
@ -6446,9 +6446,9 @@ static void handle_hangup(void *userdata, struct stasis_subscription *sub,
ao2_unlock(queue_data);
ast_debug(3, "Detected hangup of queue %s channel %s\n", reason == CALLER ? "caller" : "member",
channel_blob->snapshot->name);
channel_blob->snapshot->base->name);
ast_queue_log(queue_data->queue->name, caller_snapshot->uniqueid, queue_data->member->membername,
ast_queue_log(queue_data->queue->name, caller_snapshot->base->uniqueid, queue_data->member->membername,
reason == CALLER ? "COMPLETECALLER" : "COMPLETEAGENT", "%ld|%ld|%d",
(long) (queue_data->starttime - queue_data->holdstart),
(long) (time(NULL) - queue_data->starttime), queue_data->caller_pos);

@ -1169,7 +1169,7 @@ static int chan_pjsip_devicestate(const char *data)
continue;
}
if (chan_pjsip_get_hold(snapshot->uniqueid)) {
if (chan_pjsip_get_hold(snapshot->base->uniqueid)) {
ast_devstate_aggregate_add(&aggregate, AST_DEVICE_ONHOLD);
} else {
ast_devstate_aggregate_add(&aggregate, ast_state_chan2dev(snapshot->state));

@ -61,13 +61,13 @@ static int cli_channel_sort(const void *obj, const void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
right_key = right_obj->name;
right_key = right_obj->base->name;
/* Fall through */
case OBJ_SEARCH_KEY:
cmp = strcmp(left_obj->name, right_key);
cmp = strcmp(left_obj->base->name, right_key);
break;
case OBJ_SEARCH_PARTIAL_KEY:
cmp = strncmp(left_obj->name, right_key, strlen(right_key));
cmp = strncmp(left_obj->base->name, right_key, strlen(right_key));
break;
default:
cmp = 0;
@ -86,17 +86,17 @@ static int cli_channelstats_sort(const void *obj, const void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
cmp = strcmp(left_obj->bridgeid, right_obj->bridgeid);
cmp = strcmp(left_obj->bridge->id, right_obj->bridge->id);
if (cmp) {
return cmp;
}
right_key = right_obj->name;
right_key = right_obj->base->name;
/* Fall through */
case OBJ_SEARCH_KEY:
cmp = strcmp(left_obj->name, right_key);
cmp = strcmp(left_obj->base->name, right_key);
break;
case OBJ_SEARCH_PARTIAL_KEY:
cmp = strncmp(left_obj->name, right_key, strlen(right_key));
cmp = strncmp(left_obj->base->name, right_key, strlen(right_key));
break;
default:
cmp = 0;
@ -115,15 +115,15 @@ static int cli_channel_compare(void *obj, void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
right_key = right_obj->name;
right_key = right_obj->base->name;
/* Fall through */
case OBJ_SEARCH_KEY:
if (strcmp(left_obj->name, right_key) == 0) {
if (strcmp(left_obj->base->name, right_key) == 0) {
cmp = CMP_MATCH | CMP_STOP;
}
break;
case OBJ_SEARCH_PARTIAL_KEY:
if (strncmp(left_obj->name, right_key, strlen(right_key)) == 0) {
if (strncmp(left_obj->base->name, right_key, strlen(right_key)) == 0) {
cmp = CMP_MATCH;
}
break;
@ -144,18 +144,18 @@ static int cli_channelstats_compare(void *obj, void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
if (strcmp(left_obj->bridgeid, right_obj->bridgeid) == 0
&& strcmp(left_obj->name, right_obj->name) == 0) {
if (strcmp(left_obj->bridge->id, right_obj->bridge->id) == 0
&& strcmp(left_obj->base->name, right_obj->base->name) == 0) {
return CMP_MATCH | CMP_STOP;
}
break;
case OBJ_SEARCH_KEY:
if (strcmp(left_obj->name, right_key) == 0) {
if (strcmp(left_obj->base->name, right_key) == 0) {
cmp = CMP_MATCH | CMP_STOP;
}
break;
case OBJ_SEARCH_PARTIAL_KEY:
if (strncmp(left_obj->name, right_key, strlen(right_key)) == 0) {
if (strncmp(left_obj->base->name, right_key, strlen(right_key)) == 0) {
cmp = CMP_MATCH;
}
break;
@ -172,7 +172,7 @@ static int cli_message_to_snapshot(void *obj, void *arg, int flags)
struct ast_channel_snapshot *snapshot = obj;
struct ao2_container *snapshots = arg;
if (!strcmp(snapshot->type, "PJSIP")) {
if (!strcmp(snapshot->base->type, "PJSIP")) {
ao2_link(snapshots, snapshot);
return CMP_MATCH;
}
@ -185,8 +185,8 @@ static int cli_filter_channels(void *obj, void *arg, int flags)
struct ast_channel_snapshot *channel = obj;
regex_t *regexbuf = arg;
if (!regexec(regexbuf, channel->name, 0, NULL, 0)
|| !regexec(regexbuf, channel->appl, 0, NULL, 0)) {
if (!regexec(regexbuf, channel->base->name, 0, NULL, 0)
|| !regexec(regexbuf, channel->dialplan->appl, 0, NULL, 0)) {
return 0;
}
@ -236,7 +236,7 @@ static const char *cli_channel_get_id(const void *obj)
{
const struct ast_channel_snapshot *snapshot = obj;
return snapshot->name;
return snapshot->base->name;
}
static void *cli_channel_retrieve_by_id(const char *id)
@ -280,16 +280,16 @@ static int cli_channel_print_body(void *obj, void *arg, int flags)
ast_assert(context->output_buffer != NULL);
print_name_len = strlen(snapshot->name) + strlen(snapshot->appl) + 2;
print_name_len = strlen(snapshot->base->name) + strlen(snapshot->dialplan->appl) + 2;
print_name = alloca(print_name_len);
/* Append the application */
snprintf(print_name, print_name_len, "%s/%s", snapshot->name, snapshot->appl);
snprintf(print_name, print_name_len, "%s/%s", snapshot->base->name, snapshot->dialplan->appl);
indent = CLI_INDENT_TO_SPACES(context->indent_level);
flexwidth = CLI_LAST_TABSTOP - indent;
ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32);
ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->base->creationtime.tv_sec, print_time, 32);
ast_str_append(&context->output_buffer, 0, "%*s: %-*.*s %-12.12s %-11.11s\n",
CLI_INDENT_TO_SPACES(context->indent_level), "Channel",
@ -307,9 +307,9 @@ static int cli_channel_print_body(void *obj, void *arg, int flags)
"%*s: %-*.*s CLCID: \"%s\" <%s>\n",
indent, "Exten",
flexwidth, flexwidth,
snapshot->exten,
snapshot->connected_name,
snapshot->connected_number
snapshot->dialplan->exten,
snapshot->connected->name,
snapshot->connected->number
);
context->indent_level--;
if (context->indent_level == 0) {
@ -338,7 +338,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
{
struct ast_sip_cli_context *context = arg;
const struct ast_channel_snapshot *snapshot = obj;
struct ast_channel *channel = ast_channel_get_by_name(snapshot->name);
struct ast_channel *channel = ast_channel_get_by_name(snapshot->base->name);
struct ast_sip_channel_pvt *cpvt = channel ? ast_channel_tech_pvt(channel) : NULL;
struct ast_sip_session *session;
struct ast_sip_session_media *media;
@ -351,7 +351,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
ast_assert(context->output_buffer != NULL);
if (!channel) {
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
return -1;
}
@ -359,7 +359,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
session = cpvt->session;
if (!session) {
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
ast_channel_unlock(channel);
ao2_cleanup(channel);
return -1;
@ -367,7 +367,7 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
media = session->active_media_state->default_session[AST_MEDIA_TYPE_AUDIO];
if (!media || !media->rtp) {
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->name);
ast_str_append(&context->output_buffer, 0, " %s not valid\n", snapshot->base->name);
ast_channel_unlock(channel);
ao2_cleanup(channel);
return -1;
@ -383,18 +383,18 @@ static int cli_channelstats_print_body(void *obj, void *arg, int flags)
ast_channel_unlock(channel);
print_name = ast_strdupa(snapshot->name);
print_name = ast_strdupa(snapshot->base->name);
/* Skip the PJSIP/. We know what channel type it is and we need the space. */
print_name += 6;
ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->creationtime.tv_sec, print_time, 32);
ast_format_duration_hh_mm_ss(ast_tvnow().tv_sec - snapshot->base->creationtime.tv_sec, print_time, 32);
if (ast_rtp_instance_get_stats(rtp, &stats, AST_RTP_INSTANCE_STAT_ALL)) {
ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->name);
ast_str_append(&context->output_buffer, 0, "%s direct media\n", snapshot->base->name);
} else {
ast_str_append(&context->output_buffer, 0,
" %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",
snapshot->bridgeid,
snapshot->bridge->id,
print_name,
print_time,
codec_in_use,

@ -17,6 +17,8 @@ enabled = yes ; When set to no, ARI support is disabled.
; Display certain channel variables every time a channel-oriented
; event is emitted:
;
; Note that this does incur a performance penalty and should be avoided if possible.
;
;channelvars = var1,var2,var3
;[username]

@ -55,6 +55,8 @@ bindaddr = 0.0.0.0
; Display certain channel variables every time a channel-oriented
; event is emitted:
;
; Note that this does incur a performance penalty and should be avoided if possible.
;
;channelvars = var1,var2,var3
; debug = on ; enable some debugging info in AMI messages (default off).

@ -4258,6 +4258,7 @@ enum ast_channel_state ast_channel_state(const struct ast_channel *chan);
ast_callid ast_channel_callid(const struct ast_channel *chan);
struct ast_channel_snapshot *ast_channel_snapshot(const struct ast_channel *chan);
void ast_channel_snapshot_set(struct ast_channel *chan, struct ast_channel_snapshot *snapshot);
struct ast_flags *ast_channel_snapshot_segment_flags(struct ast_channel *chan);
/*!
* \pre chan is locked

@ -28,51 +28,134 @@
* @{
*/
/*!
* \since 17
* \brief Channel snapshot invalidation flags, used to force generation of segments
*/
enum ast_channel_snapshot_segment_invalidation {
/*! Invalidate the bridge segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE = (1 << 1),
/*! Invalidate the dialplan segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN = (1 << 2),
/*! Invalidate the connected segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED = (1 << 3),
/*! Invalidate the caller segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER = (1 << 4),
/*! Invalidate the hangup segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP = (1 << 5),
/*! Invalidate the peer segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER = (1 << 6),
/*! Invalidate the base segment */
AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE = (1 << 7),
};
/*!
* \since 17
* \brief Structure containing bridge information for a channel snapshot.
*/
struct ast_channel_snapshot_bridge {
char id[0]; /*!< Unique Bridge Identifier */
};
/*!
* \since 17
* \brief Structure containing dialplan information for a channel snapshot.
*/
struct ast_channel_snapshot_dialplan {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(appl); /*!< Current application */
AST_STRING_FIELD(data); /*!< Data passed to current application */
AST_STRING_FIELD(context); /*!< Current extension context */
AST_STRING_FIELD(exten); /*!< Current extension number */
);
int priority; /*!< Current extension priority */
};
/*!
* \since 17
* \brief Structure containing caller information for a channel snapshot.
*/
struct ast_channel_snapshot_caller {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(name); /*!< Caller ID Name */
AST_STRING_FIELD(number); /*!< Caller ID Number */
AST_STRING_FIELD(dnid); /*!< Dialed ID Number */
AST_STRING_FIELD(dialed_subaddr); /*!< Dialed subaddress */
AST_STRING_FIELD(ani); /*!< Caller ID ANI Number */
AST_STRING_FIELD(rdnis); /*!< Caller ID RDNIS Number */
AST_STRING_FIELD(subaddr); /*!< Caller subaddress */
);
int pres; /*!< Caller ID presentation. */
};
/*!
* \since 17
* \brief Structure containing connected information for a channel snapshot.
*/
struct ast_channel_snapshot_connected {
char *number; /*!< Connected Line Number */
char name[0]; /*!< Connected Line Name */
};
/*!
* \since 17
* \brief Structure containing base information for a channel snapshot.
*/
struct ast_channel_snapshot_base {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(name); /*!< ASCII unique channel name */
AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
AST_STRING_FIELD(accountcode); /*!< Account code for billing */
AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
AST_STRING_FIELD(language); /*!< The default spoken language for the channel */
AST_STRING_FIELD(type); /*!< Type of channel technology */
);
struct timeval creationtime; /*!< The time of channel creation */
int tech_properties; /*!< Properties of the channel's technology */
};
/*!
* \since 17
* \brief Structure containing peer information for a channel snapshot.
*/
struct ast_channel_snapshot_peer {
char *linkedid; /*!< Linked Channel Identifier -- gets propagated by linkage */
char account[0]; /*!< Peer account code for billing */
};
/*!
* \since 17
* \brief Structure containing hangup information for a channel snapshot.
*/
struct ast_channel_snapshot_hangup {
int cause; /*!< Why is the channel hanged up. See causes.h */
char source[0]; /*!< Who is responsible for hanging up this channel */
};
/*!
* \since 12
* \brief Structure representing a snapshot of channel state.
*
* While not enforced programmatically, this object is shared across multiple
* threads, and should be treated as an immutable object.
*
* It is guaranteed that the segments of this snapshot will always exist
* when accessing the snapshot.
*/
struct ast_channel_snapshot {
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(name); /*!< ASCII unique channel name */
AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */
AST_STRING_FIELD(appl); /*!< Current application */
AST_STRING_FIELD(data); /*!< Data passed to current application */
AST_STRING_FIELD(context); /*!< Dialplan: Current extension context */
AST_STRING_FIELD(exten); /*!< Dialplan: Current extension number */
AST_STRING_FIELD(accountcode); /*!< Account code for billing */
AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */
AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
AST_STRING_FIELD(hangupsource); /*!< Who is responsible for hanging up this channel */
AST_STRING_FIELD(caller_name); /*!< Caller ID Name */
AST_STRING_FIELD(caller_number); /*!< Caller ID Number */
AST_STRING_FIELD(caller_dnid); /*!< Dialed ID Number */
AST_STRING_FIELD(caller_ani); /*!< Caller ID ANI Number */
AST_STRING_FIELD(caller_rdnis); /*!< Caller ID RDNIS Number */
AST_STRING_FIELD(caller_subaddr); /*!< Caller subaddress */
AST_STRING_FIELD(dialed_subaddr); /*!< Dialed subaddress */
AST_STRING_FIELD(connected_name); /*!< Connected Line Name */
AST_STRING_FIELD(connected_number); /*!< Connected Line Number */
AST_STRING_FIELD(language); /*!< The default spoken language for the channel */
AST_STRING_FIELD(bridgeid); /*!< Unique Bridge Identifier */
AST_STRING_FIELD(type); /*!< Type of channel technology */
);
struct timeval creationtime; /*!< The time of channel creation */
enum ast_channel_state state; /*!< State of line */
int priority; /*!< Dialplan: Current extension priority */
int amaflags; /*!< AMA flags for billing */
int hangupcause; /*!< Why is the channel hanged up. See causes.h */
int caller_pres; /*!< Caller ID presentation. */
struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
struct ast_flags softhangup_flags; /*!< softhangup channel flags */
struct varshead *manager_vars; /*!< Variables to be appended to manager events */
int tech_properties; /*!< Properties of the channel's technology */
struct varshead *ari_vars; /*!< Variables to be appended to ARI events */
struct ast_channel_snapshot_base *base; /*!< Base information about the channel */
struct ast_channel_snapshot_peer *peer; /*!< Peer information */
struct ast_channel_snapshot_caller *caller; /*!< Information about the caller */
struct ast_channel_snapshot_connected *connected; /*!< Information about who this channel is connected to */
struct ast_channel_snapshot_bridge *bridge; /*!< Information about the bridge */
struct ast_channel_snapshot_dialplan *dialplan; /*!< Information about the dialplan */
struct ast_channel_snapshot_hangup *hangup; /*!< Hangup information */
enum ast_channel_state state; /*!< State of line */
int amaflags; /*!< AMA flags for billing */
struct ast_flags flags; /*!< channel flags of AST_FLAG_ type */
struct ast_flags softhangup_flags; /*!< softhangup channel flags */
struct varshead *manager_vars; /*!< Variables to be appended to manager events */
struct varshead *ari_vars; /*!< Variables to be appended to ARI events */
};
/*!
@ -359,6 +442,18 @@ void ast_channel_stage_snapshot(struct ast_channel *chan);
*/
void ast_channel_stage_snapshot_done(struct ast_channel *chan);
/*!
* \since 17
* \brief Invalidate a channel snapshot segment from being reused
*
* \pre chan is locked
*
* \param chan Channel to invalidate the segment on.
* \param segment The segment to invalidate.
*/
void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan,
enum ast_channel_snapshot_segment_invalidation segment);
/*!
* \since 12
* \brief Publish a \ref ast_channel_snapshot for a channel.

@ -5157,7 +5157,7 @@ static int bridge_show_specific_print_channel(void *obj, void *arg, int flags)
return 0;
}
ast_cli(a->fd, "Channel: %s\n", snapshot->name);
ast_cli(a->fd, "Channel: %s\n", snapshot->base->name);
ao2_ref(snapshot, -1);
return 0;

@ -803,7 +803,7 @@ static void cdr_object_snapshot_copy(struct cdr_object_snapshot *dst, struct cdr
static void cdr_object_transition_state(struct cdr_object *cdr, struct cdr_object_fn_table *fn_table)
{
CDR_DEBUG("%p - Transitioning CDR for %s from state %s to %s\n",
cdr, cdr->party_a.snapshot->name,
cdr, cdr->party_a.snapshot->base->name,
cdr->fn_table ? cdr->fn_table->name : "NONE", fn_table->name);
cdr->fn_table = fn_table;
if (cdr->fn_table->init_function) {
@ -938,9 +938,9 @@ static void cdr_all_relink(struct cdr_object *cdr)
{
ao2_lock(active_cdrs_all);
if (cdr->party_b.snapshot) {
if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->name)) {
if (strcasecmp(cdr->party_b_name, cdr->party_b.snapshot->base->name)) {
ao2_unlink_flags(active_cdrs_all, cdr, OBJ_NOLOCK);
ast_string_field_set(cdr, party_b_name, cdr->party_b.snapshot->name);
ast_string_field_set(cdr, party_b_name, cdr->party_b.snapshot->base->name);
ao2_link_flags(active_cdrs_all, cdr, OBJ_NOLOCK);
}
} else {
@ -1039,16 +1039,16 @@ static struct cdr_object *cdr_object_alloc(struct ast_channel_snapshot *chan)
ao2_cleanup(cdr);
return NULL;
}
ast_string_field_set(cdr, uniqueid, chan->uniqueid);
ast_string_field_set(cdr, name, chan->name);
ast_string_field_set(cdr, linkedid, chan->linkedid);
ast_string_field_set(cdr, uniqueid, chan->base->uniqueid);
ast_string_field_set(cdr, name, chan->base->name);
ast_string_field_set(cdr, linkedid, chan->peer->linkedid);
cdr->disposition = AST_CDR_NULL;
cdr->sequence = ast_atomic_fetchadd_int(&global_cdr_sequence, +1);
cdr->party_a.snapshot = chan;
ao2_t_ref(cdr->party_a.snapshot, +1, "bump snapshot during CDR creation");
CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->name);
CDR_DEBUG("%p - Created CDR for channel %s\n", cdr, chan->base->name);
cdr_object_transition_state(cdr, &single_state_fn_table);
@ -1145,11 +1145,11 @@ static int snapshot_cep_changed(struct ast_channel_snapshot *old_snapshot,
* will attempt to clear the application and restore the dummy originate application
* of "AppDialX". Ignore application changes to AppDialX as a result.
*/
if (strcmp(new_snapshot->appl, old_snapshot->appl)
&& strncasecmp(new_snapshot->appl, "appdial", 7)
&& (strcmp(new_snapshot->context, old_snapshot->context)
|| strcmp(new_snapshot->exten, old_snapshot->exten)
|| new_snapshot->priority != old_snapshot->priority)) {
if (strcmp(new_snapshot->dialplan->appl, old_snapshot->dialplan->appl)
&& strncasecmp(new_snapshot->dialplan->appl, "appdial", 7)
&& (strcmp(new_snapshot->dialplan->context, old_snapshot->dialplan->context)
|| strcmp(new_snapshot->dialplan->exten, old_snapshot->dialplan->exten)
|| new_snapshot->dialplan->priority != old_snapshot->dialplan->priority)) {
return 1;
}
@ -1196,11 +1196,11 @@ static struct cdr_object_snapshot *cdr_object_pick_party_a(struct cdr_object_sna
/* Neither party is dialed and neither has the Party A flag - defer to
* creation time */
if (left->snapshot->creationtime.tv_sec < right->snapshot->creationtime.tv_sec) {
if (left->snapshot->base->creationtime.tv_sec < right->snapshot->base->creationtime.tv_sec) {
return left;
} else if (left->snapshot->creationtime.tv_sec > right->snapshot->creationtime.tv_sec) {
} else if (left->snapshot->base->creationtime.tv_sec > right->snapshot->base->creationtime.tv_sec) {
return right;
} else if (left->snapshot->creationtime.tv_usec > right->snapshot->creationtime.tv_usec) {
} else if (left->snapshot->base->creationtime.tv_usec > right->snapshot->base->creationtime.tv_usec) {
return right;
} else {
/* Okay, fine, take the left one */
@ -1285,7 +1285,7 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
/* Don't create records for CDRs where the party A was a dialed channel */
if (snapshot_is_dialed(it_cdr->party_a.snapshot) && !it_cdr->party_b.snapshot) {
ast_debug(1, "CDR for %s is dialed and has no Party B; discarding\n",
it_cdr->party_a.snapshot->name);
it_cdr->party_a.snapshot->base->name);
continue;
}
@ -1300,12 +1300,12 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
/* Party A */
ast_assert(party_a != NULL);
ast_copy_string(cdr_copy->accountcode, party_a->accountcode, sizeof(cdr_copy->accountcode));
ast_copy_string(cdr_copy->accountcode, party_a->base->accountcode, sizeof(cdr_copy->accountcode));
cdr_copy->amaflags = party_a->amaflags;
ast_copy_string(cdr_copy->channel, party_a->name, sizeof(cdr_copy->channel));
ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller_name, party_a->caller_number, "");
ast_copy_string(cdr_copy->src, party_a->caller_number, sizeof(cdr_copy->src));
ast_copy_string(cdr_copy->uniqueid, party_a->uniqueid, sizeof(cdr_copy->uniqueid));
ast_copy_string(cdr_copy->channel, party_a->base->name, sizeof(cdr_copy->channel));
ast_callerid_merge(cdr_copy->clid, sizeof(cdr_copy->clid), party_a->caller->name, party_a->caller->number, "");
ast_copy_string(cdr_copy->src, party_a->caller->number, sizeof(cdr_copy->src));
ast_copy_string(cdr_copy->uniqueid, party_a->base->uniqueid, sizeof(cdr_copy->uniqueid));
ast_copy_string(cdr_copy->lastapp, it_cdr->appl, sizeof(cdr_copy->lastapp));
ast_copy_string(cdr_copy->lastdata, it_cdr->data, sizeof(cdr_copy->lastdata));
ast_copy_string(cdr_copy->dst, it_cdr->exten, sizeof(cdr_copy->dst));
@ -1313,8 +1313,8 @@ static struct ast_cdr *cdr_object_create_public_records(struct cdr_object *cdr)
/* Party B */
if (party_b) {
ast_copy_string(cdr_copy->dstchannel, party_b->name, sizeof(cdr_copy->dstchannel));
ast_copy_string(cdr_copy->peeraccount, party_b->accountcode, sizeof(cdr_copy->peeraccount));
ast_copy_string(cdr_copy->dstchannel, party_b->base->name, sizeof(cdr_copy->dstchannel));
ast_copy_string(cdr_copy->peeraccount, party_b->base->accountcode, sizeof(cdr_copy->peeraccount));
if (!ast_strlen_zero(it_cdr->party_b.userfield)) {
snprintf(cdr_copy->userfield, sizeof(cdr_copy->userfield), "%s;%s", it_cdr->party_a.userfield, it_cdr->party_b.userfield);
}
@ -1375,8 +1375,8 @@ static void cdr_object_dispatch(struct cdr_object *cdr)
struct ast_cdr *pub_cdr;
CDR_DEBUG("%p - Dispatching CDR for Party A %s, Party B %s\n", cdr,
cdr->party_a.snapshot->name,
cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<none>");
cdr->party_a.snapshot->base->name,
cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<none>");
pub_cdr = cdr_object_create_public_records(cdr);
cdr_detach(pub_cdr);
}
@ -1434,10 +1434,10 @@ static void cdr_object_finalize(struct cdr_object *cdr)
if (cdr->disposition == AST_CDR_NULL) {
if (!ast_tvzero(cdr->answer)) {
cdr->disposition = AST_CDR_ANSWERED;
} else if (cdr->party_a.snapshot->hangupcause) {
cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangupcause);
} else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangupcause) {
cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangupcause);
} else if (cdr->party_a.snapshot->hangup->cause) {
cdr_object_set_disposition(cdr, cdr->party_a.snapshot->hangup->cause);
} else if (cdr->party_b.snapshot && cdr->party_b.snapshot->hangup->cause) {
cdr_object_set_disposition(cdr, cdr->party_b.snapshot->hangup->cause);
} else {
cdr->disposition = AST_CDR_FAILED;
}
@ -1445,7 +1445,7 @@ static void cdr_object_finalize(struct cdr_object *cdr)
/* tv_usec is suseconds_t, which could be int or long */
ast_debug(1, "Finalized CDR for %s - start %ld.%06ld answer %ld.%06ld end %ld.%06ld dispo %s\n",
cdr->party_a.snapshot->name,
cdr->party_a.snapshot->base->name,
(long)cdr->start.tv_sec,
(long)cdr->start.tv_usec,
(long)cdr->answer.tv_sec,
@ -1491,19 +1491,19 @@ static void cdr_object_check_party_a_answer(struct cdr_object *cdr)
static void cdr_object_update_cid(struct cdr_object_snapshot *old_snapshot, struct ast_channel_snapshot *new_snapshot)
{
if (!old_snapshot->snapshot) {
set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
return;
}
if (strcmp(old_snapshot->snapshot->caller_dnid, new_snapshot->caller_dnid)) {
set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller_dnid);
if (strcmp(old_snapshot->snapshot->caller->dnid, new_snapshot->caller->dnid)) {
set_variable(&old_snapshot->variables, "dnid", new_snapshot->caller->dnid);
}
if (strcmp(old_snapshot->snapshot->caller_subaddr, new_snapshot->caller_subaddr)) {
set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller_subaddr);
if (strcmp(old_snapshot->snapshot->caller->subaddr, new_snapshot->caller->subaddr)) {
set_variable(&old_snapshot->variables, "callingsubaddr", new_snapshot->caller->subaddr);
}
if (strcmp(old_snapshot->snapshot->dialed_subaddr, new_snapshot->dialed_subaddr)) {
set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->dialed_subaddr);
if (strcmp(old_snapshot->snapshot->caller->dialed_subaddr, new_snapshot->caller->dialed_subaddr)) {
set_variable(&old_snapshot->variables, "calledsubaddr", new_snapshot->caller->dialed_subaddr);
}
}
@ -1524,7 +1524,7 @@ static void cdr_object_swap_snapshot(struct cdr_object_snapshot *old_snapshot,
static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
{
ast_assert(strcasecmp(snapshot->name, cdr->party_a.snapshot->name) == 0);
ast_assert(strcasecmp(snapshot->base->name, cdr->party_a.snapshot->base->name) == 0);
/* Finalize the CDR if we're in hangup logic and we're set to do so */
if (ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)
@ -1539,11 +1539,11 @@ static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snaps
*/
if (!ast_test_flag(&snapshot->flags, AST_FLAG_SUBROUTINE_EXEC)
|| ast_test_flag(&snapshot->softhangup_flags, AST_SOFTHANGUP_HANGUP_EXEC)) {
if (strcmp(cdr->context, snapshot->context)) {
ast_string_field_set(cdr, context, snapshot->context);
if (strcmp(cdr->context, snapshot->dialplan->context)) {
ast_string_field_set(cdr, context, snapshot->dialplan->context);
}
if (strcmp(cdr->exten, snapshot->exten)) {
ast_string_field_set(cdr, exten, snapshot->exten);
if (strcmp(cdr->exten, snapshot->dialplan->exten)) {
ast_string_field_set(cdr, exten, snapshot->dialplan->exten);
}
}
@ -1555,13 +1555,13 @@ static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snaps
* here.
*/
if (!ast_test_flag(&cdr->flags, AST_CDR_LOCK_APP)
&& !ast_strlen_zero(snapshot->appl)
&& (strncasecmp(snapshot->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
if (strcmp(cdr->appl, snapshot->appl)) {
ast_string_field_set(cdr, appl, snapshot->appl);
&& !ast_strlen_zero(snapshot->dialplan->appl)
&& (strncasecmp(snapshot->dialplan->appl, "appdial", 7) || ast_strlen_zero(cdr->appl))) {
if (strcmp(cdr->appl, snapshot->dialplan->appl)) {
ast_string_field_set(cdr, appl, snapshot->dialplan->appl);
}
if (strcmp(cdr->data, snapshot->data)) {
ast_string_field_set(cdr, data, snapshot->data);
if (strcmp(cdr->data, snapshot->dialplan->data)) {
ast_string_field_set(cdr, data, snapshot->dialplan->data);
}
/* Dial (app_dial) is a special case. Because pre-dial handlers, which
@ -1569,13 +1569,13 @@ static int base_process_party_a(struct cdr_object *cdr, struct ast_channel_snaps
* something people typically don't want to see, if we see a channel enter
* into Dial here, we set the appl/data accordingly and lock it.
*/
if (!strcmp(snapshot->appl, "Dial")) {
if (!strcmp(snapshot->dialplan->appl, "Dial")) {
ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
}
}
if (strcmp(cdr->linkedid, snapshot->linkedid)) {
ast_string_field_set(cdr, linkedid, snapshot->linkedid);
if (strcmp(cdr->linkedid, snapshot->peer->linkedid)) {
ast_string_field_set(cdr, linkedid, snapshot->peer->linkedid);
}
cdr_object_check_party_a_answer(cdr);
cdr_object_check_party_a_hangup(cdr);
@ -1603,7 +1603,7 @@ static int base_process_parked_channel(struct cdr_object *cdr, struct ast_parked
{
char park_info[128];
ast_assert(!strcasecmp(parking_info->parkee->name, cdr->party_a.snapshot->name));
ast_assert(!strcasecmp(parking_info->parkee->base->name, cdr->party_a.snapshot->base->name));
/* Update Party A information regardless */
cdr->fn_table->process_party_a(cdr, parking_info->parkee);
@ -1637,25 +1637,25 @@ static void single_state_process_party_b(struct cdr_object *cdr, struct ast_chan
static int single_state_process_dial_begin(struct cdr_object *cdr, struct ast_channel_snapshot *caller, struct ast_channel_snapshot *peer)
{
if (caller && !strcasecmp(cdr->party_a.snapshot->name, caller->name)) {
if (caller && !strcasecmp(cdr->party_a.snapshot->base->name, caller->base->name)) {
base_process_party_a(cdr, caller);
CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
cdr->party_a.snapshot->name);
cdr->party_a.snapshot->base->name);
cdr_object_swap_snapshot(&cdr->party_b, peer);
cdr_all_relink(cdr);
CDR_DEBUG("%p - Updated Party B %s snapshot\n", cdr,
cdr->party_b.snapshot->name);
cdr->party_b.snapshot->base->name);
/* If we have two parties, lock the application that caused the
* two parties to be associated. This prevents mid-call event
* macros/gosubs from perturbing the CDR application/data
*/
ast_set_flag(&cdr->flags, AST_CDR_LOCK_APP);
} else if (!strcasecmp(cdr->party_a.snapshot->name, peer->name)) {
} else if (!strcasecmp(cdr->party_a.snapshot->base->name, peer->base->name)) {
/* We're the entity being dialed, i.e., outbound origination */
base_process_party_a(cdr, peer);
CDR_DEBUG("%p - Updated Party A %s snapshot\n", cdr,
cdr->party_a.snapshot->name);
cdr->party_a.snapshot->base->name);
}
cdr_object_transition_state(cdr, &dial_state_fn_table);
@ -1680,15 +1680,15 @@ static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
struct cdr_object_snapshot *party_a;
/* Don't match on ourselves */
if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)) {
if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
return 1;
}
/* Try the candidate CDR's Party A first */
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
CDR_DEBUG("%p - Party A %s has new Party B %s\n",
cdr, cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name);
cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name);
cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
cdr_all_relink(cdr);
if (!cand_cdr->party_b.snapshot) {
@ -1703,13 +1703,13 @@ static int single_state_bridge_enter_comparison(struct cdr_object *cdr,
/* Try their Party B, unless it's us */
if (!cand_cdr->party_b.snapshot
|| !strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name)) {
|| !strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name)) {
return 1;
}
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_b);
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
CDR_DEBUG("%p - Party A %s has new Party B %s\n",
cdr, cdr->party_a.snapshot->name, cand_cdr->party_b.snapshot->name);
cdr, cdr->party_a.snapshot->base->name, cand_cdr->party_b.snapshot->base->name);
cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_b);
cdr_all_relink(cdr);
return 0;
@ -1788,7 +1788,7 @@ static void dial_state_process_party_b(struct cdr_object *cdr, struct ast_channe
{
ast_assert(snapshot != NULL);
ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, snapshot->name));
&& !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
cdr_object_swap_snapshot(&cdr->party_b, snapshot);
@ -1839,11 +1839,11 @@ static int dial_state_process_dial_end(struct cdr_object *cdr, struct ast_channe
} else {
party_a = peer;
}
ast_assert(!strcasecmp(cdr->party_a.snapshot->name, party_a->name));
ast_assert(!strcasecmp(cdr->party_a.snapshot->base->name, party_a->base->name));
cdr_object_swap_snapshot(&cdr->party_a, party_a);
if (cdr->party_b.snapshot) {
if (strcasecmp(cdr->party_b.snapshot->name, peer->name)) {
if (strcasecmp(cdr->party_b.snapshot->base->name, peer->base->name)) {
/* Not the status for this CDR - defer back to the message router */
return 1;
}
@ -1901,7 +1901,7 @@ static enum process_bridge_enter_results dial_state_process_bridge_enter(struct
}
/* Skip any records that aren't our Party B */
if (strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name)) {
if (strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)) {
continue;
}
cdr_object_snapshot_copy(&cdr->party_b, &cand_cdr->party_a);
@ -1982,7 +1982,7 @@ static int dialed_pending_state_process_dial_begin(struct cdr_object *cdr, struc
static void bridge_state_process_party_b(struct cdr_object *cdr, struct ast_channel_snapshot *snapshot)
{
ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, snapshot->name));
&& !strcasecmp(cdr->party_b.snapshot->base->name, snapshot->base->name));
cdr_object_swap_snapshot(&cdr->party_b, snapshot);
@ -1997,9 +1997,9 @@ static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_
if (strcmp(cdr->bridge, bridge->uniqueid)) {
return 1;
}
if (strcasecmp(cdr->party_a.snapshot->name, channel->name)
if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)
&& cdr->party_b.snapshot
&& strcasecmp(cdr->party_b.snapshot->name, channel->name)) {
&& strcasecmp(cdr->party_b.snapshot->base->name, channel->base->name)) {
return 1;
}
cdr_object_transition_state(cdr, &finalized_state_fn_table);
@ -2011,7 +2011,7 @@ static int bridge_state_process_bridge_leave(struct cdr_object *cdr, struct ast_
static int parked_state_process_bridge_leave(struct cdr_object *cdr, struct ast_bridge_snapshot *bridge, struct ast_channel_snapshot *channel)
{
if (strcasecmp(cdr->party_a.snapshot->name, channel->name)) {
if (strcasecmp(cdr->party_a.snapshot->base->name, channel->base->name)) {
return 1;
}
cdr_object_transition_state(cdr, &finalized_state_fn_table);
@ -2043,7 +2043,7 @@ static int finalized_state_process_party_a(struct cdr_object *cdr, struct ast_ch
*/
static int filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
{
return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
}
/*!
@ -2114,19 +2114,19 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
CDR_DEBUG("Dial %s message for %s, %s: %u.%08u\n",
ast_strlen_zero(dial_status) ? "Begin" : "End",
caller ? caller->name : "(none)",
peer ? peer->name : "(none)",
caller ? caller->base->name : "(none)",
peer ? peer->base->name : "(none)",
(unsigned int)stasis_message_timestamp(message)->tv_sec,
(unsigned int)stasis_message_timestamp(message)->tv_usec);
/* Figure out who is running this show */
if (caller) {
cdr = ao2_find(active_cdrs_master, caller->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, caller->base->uniqueid, OBJ_SEARCH_KEY);
} else {
cdr = ao2_find(active_cdrs_master, peer->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, peer->base->uniqueid, OBJ_SEARCH_KEY);
}
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->name : peer->name);
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", caller ? caller->base->name : peer->base->name);
ast_assert(0);
return;
}
@ -2139,8 +2139,8 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
}
CDR_DEBUG("%p - Processing Dial Begin message for channel %s, peer %s\n",
it_cdr,
caller ? caller->name : "(none)",
peer ? peer->name : "(none)");
caller ? caller->base->name : "(none)",
peer ? peer->base->name : "(none)");
res &= it_cdr->fn_table->process_dial_begin(it_cdr,
caller,
peer);
@ -2150,8 +2150,8 @@ static void handle_dial_message(void *data, struct stasis_subscription *sub, str
}
CDR_DEBUG("%p - Processing Dial End message for channel %s, peer %s\n",
it_cdr,
caller ? caller->name : "(none)",
peer ? peer->name : "(none)");
caller ? caller->base->name : "(none)",
peer ? peer->base->name : "(none)");
it_cdr->fn_table->process_dial_end(it_cdr,
caller,
peer,
@ -2185,7 +2185,7 @@ static int cdr_object_finalize_party_b(void *obj, void *arg, void *data, int fla
* is consistent with the key.
*/
ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, party_b->name));
&& !strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name));
#endif
/* Don't transition to the finalized state - let the Party A do
@ -2210,11 +2210,11 @@ static int cdr_object_update_party_b(void *obj, void *arg, void *data, int flags
* asserts the snapshot to be this way.
*/
if (!cdr->party_b.snapshot
|| strcasecmp(cdr->party_b.snapshot->name, party_b->name)) {
|| strcasecmp(cdr->party_b.snapshot->base->name, party_b->base->name)) {
ast_log(LOG_NOTICE,
"CDR for Party A %s(%s) has inconsistent Party B %s name. Message can be ignored but this shouldn't happen.\n",
cdr->linkedid,
cdr->party_a.snapshot->name,
cdr->party_a.snapshot->base->name,
cdr->party_b_name);
return 0;
}
@ -2236,7 +2236,7 @@ static int check_new_cdr_needed(struct ast_channel_snapshot *old_snapshot,
}
/* Auto-fall through will increment the priority but have no application */
if (ast_strlen_zero(new_snapshot->appl)) {
if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
return 0;
}
@ -2272,12 +2272,12 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
cdr->is_root = 1;
ao2_link(active_cdrs_master, cdr);
} else {
cdr = ao2_find(active_cdrs_master, update->new_snapshot->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, update->new_snapshot->base->uniqueid, OBJ_SEARCH_KEY);
}
/* Handle Party A */
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->name);
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", update->new_snapshot->base->name);
ast_assert(0);
} else {
int all_reject = 1;
@ -2303,7 +2303,7 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
ao2_lock(cdr);
CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->name);
CDR_DEBUG("%p - Beginning finalize/dispatch for %s\n", cdr, update->old_snapshot->base->name);
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
cdr_object_finalize(it_cdr);
}
@ -2317,12 +2317,12 @@ static void handle_channel_snapshot_update_message(void *data, struct stasis_sub
/* Handle Party B */
if (update->new_snapshot) {
ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
cdr_object_update_party_b, (char *) update->new_snapshot->name, update->new_snapshot);
cdr_object_update_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
}
if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
cdr_object_finalize_party_b, (char *) update->new_snapshot->name, update->new_snapshot);
cdr_object_finalize_party_b, (char *) update->new_snapshot->base->name, update->new_snapshot);
}
ao2_cleanup(cdr);
@ -2347,7 +2347,7 @@ static int cdr_object_party_b_left_bridge_cb(void *obj, void *arg, void *data, i
* is consistent with the key.
*/
ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, leave_data->channel->name));
&& !strcasecmp(cdr->party_b.snapshot->base->name, leave_data->channel->base->name));
/* It is our Party B, in our bridge. Set the end time and let the handler
* transition our CDR appropriately when we leave the bridge.
@ -2399,13 +2399,13 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
}
CDR_DEBUG("Bridge Leave message for %s: %u.%08u\n",
channel->name,
channel->base->name,
(unsigned int)stasis_message_timestamp(message)->tv_sec,
(unsigned int)stasis_message_timestamp(message)->tv_usec);
cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
ast_assert(0);
return;
}
@ -2417,7 +2417,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
continue;
}
CDR_DEBUG("%p - Processing Bridge Leave for %s\n",
it_cdr, channel->name);
it_cdr, channel->base->name);
if (!it_cdr->fn_table->process_bridge_leave(it_cdr, bridge, channel)) {
ast_string_field_set(it_cdr, bridge, "");
left_bridge = 1;
@ -2429,7 +2429,7 @@ static void handle_bridge_leave_message(void *data, struct stasis_subscription *
if (left_bridge
&& strcmp(bridge->subclass, "parking")) {
ao2_callback_data(active_cdrs_all, OBJ_NODATA | OBJ_MULTIPLE | OBJ_SEARCH_KEY,
cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->name,
cdr_object_party_b_left_bridge_cb, (char *) leave_data.channel->base->name,
&leave_data);
}
@ -2457,8 +2457,8 @@ static void bridge_candidate_add_to_cdr(struct cdr_object *cdr,
ast_string_field_set(new_cdr, bridge, cdr->bridge);
cdr_object_transition_state(new_cdr, &bridge_state_fn_table);
CDR_DEBUG("%p - Party A %s has new Party B %s\n",
new_cdr, new_cdr->party_a.snapshot->name,
party_b->snapshot->name);
new_cdr, new_cdr->party_a.snapshot->base->name,
party_b->snapshot->base->name);
}
/*!
@ -2487,16 +2487,16 @@ static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *
}
/* If the candidate is us or someone we've taken on, pass on by */
if (!strcasecmp(cdr->party_a.snapshot->name, cand_cdr->party_a.snapshot->name)
if (!strcasecmp(cdr->party_a.snapshot->base->name, cand_cdr->party_a.snapshot->base->name)
|| (cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, cand_cdr->party_a.snapshot->name))) {
&& !strcasecmp(cdr->party_b.snapshot->base->name, cand_cdr->party_a.snapshot->base->name))) {
break;
}
party_a = cdr_object_pick_party_a(&cdr->party_a, &cand_cdr->party_a);
/* We're party A - make a new CDR, append it to us, and set the candidate as
* Party B */
if (!strcasecmp(party_a->snapshot->name, cdr->party_a.snapshot->name)) {
if (!strcasecmp(party_a->snapshot->base->name, cdr->party_a.snapshot->base->name)) {
bridge_candidate_add_to_cdr(cdr, &cand_cdr->party_a);
break;
}
@ -2504,12 +2504,12 @@ static void bridge_candidate_process(struct cdr_object *cdr, struct cdr_object *
/* We're Party B. Check if we can add ourselves immediately or if we need
* a new CDR for them (they already have a Party B) */
if (cand_cdr->party_b.snapshot
&& strcasecmp(cand_cdr->party_b.snapshot->name, cdr->party_a.snapshot->name)) {
&& strcasecmp(cand_cdr->party_b.snapshot->base->name, cdr->party_a.snapshot->base->name)) {
bridge_candidate_add_to_cdr(cand_cdr, &cdr->party_a);
} else {
CDR_DEBUG("%p - Party A %s has new Party B %s\n",
cand_cdr, cand_cdr->party_a.snapshot->name,
cdr->party_a.snapshot->name);
cand_cdr, cand_cdr->party_a.snapshot->base->name,
cdr->party_a.snapshot->base->name);
cdr_object_snapshot_copy(&cand_cdr->party_b, &cdr->party_a);
cdr_all_relink(cand_cdr);
/* It's possible that this joined at one point and was never chosen
@ -2572,7 +2572,7 @@ static void handle_parking_bridge_enter_message(struct cdr_object *cdr,
}
if (it_cdr->fn_table->process_party_a) {
CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
channel->name);
channel->base->name);
it_cdr->fn_table->process_party_a(it_cdr, channel);
}
}
@ -2609,14 +2609,14 @@ try_again:
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
if (it_cdr->fn_table->process_party_a) {
CDR_DEBUG("%p - Updating Party A %s snapshot\n", it_cdr,
channel->name);
channel->base->name);
it_cdr->fn_table->process_party_a(it_cdr, channel);
}
/* Notify all states that they have entered a bridge */
if (it_cdr->fn_table->process_bridge_enter) {
CDR_DEBUG("%p - Processing bridge enter for %s\n", it_cdr,
channel->name);
channel->base->name);
result = it_cdr->fn_table->process_bridge_enter(it_cdr, bridge, channel);
switch (result) {
case BRIDGE_ENTER_ONLY_PARTY:
@ -2689,13 +2689,13 @@ static void handle_bridge_enter_message(void *data, struct stasis_subscription *
}
CDR_DEBUG("Bridge Enter message for channel %s: %u.%08u\n",
channel->name,
channel->base->name,
(unsigned int)stasis_message_timestamp(message)->tv_sec,
(unsigned int)stasis_message_timestamp(message)->tv_usec);
cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
ast_assert(0);
return;
}
@ -2739,13 +2739,13 @@ static void handle_parked_call_message(void *data, struct stasis_subscription *s
}
CDR_DEBUG("Parked Call message for channel %s: %u.%08u\n",
channel->name,
channel->base->name,
(unsigned int)stasis_message_timestamp(message)->tv_sec,
(unsigned int)stasis_message_timestamp(message)->tv_usec);
cdr = ao2_find(active_cdrs_master, channel->uniqueid, OBJ_SEARCH_KEY);
cdr = ao2_find(active_cdrs_master, channel->base->uniqueid, OBJ_SEARCH_KEY);
if (!cdr) {
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->name);
ast_log(AST_LOG_WARNING, "No CDR for channel %s\n", channel->base->name);
ast_assert(0);
return;
}
@ -3094,8 +3094,8 @@ static int cdr_object_select_all_by_name_cb(void *obj, void *arg, int flags)
struct cdr_object *cdr = obj;
const char *name = arg;
if (!strcasecmp(cdr->party_a.snapshot->name, name) ||
(cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->name, name))) {
if (!strcasecmp(cdr->party_a.snapshot->base->name, name) ||
(cdr->party_b.snapshot && !strcasecmp(cdr->party_b.snapshot->base->name, name))) {
return CMP_MATCH;
}
return 0;
@ -3110,7 +3110,7 @@ static int cdr_object_get_by_name_cb(void *obj, void *arg, int flags)
struct cdr_object *cdr = obj;
const char *name = arg;
if (!strcasecmp(cdr->party_a.snapshot->name, name)) {
if (!strcasecmp(cdr->party_a.snapshot->base->name, name)) {
return CMP_MATCH;
}
return 0;
@ -3170,10 +3170,10 @@ int ast_cdr_setvar(const char *channel_name, const char *name, const char *value
if (it_cdr->fn_table == &finalized_state_fn_table && it_cdr->next != NULL) {
continue;
}
if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->name)) {
if (!strcasecmp(channel_name, it_cdr->party_a.snapshot->base->name)) {
headp = &it_cdr->party_a.variables;
} else if (it_cdr->party_b.snapshot
&& !strcasecmp(channel_name, it_cdr->party_b.snapshot->name)) {
&& !strcasecmp(channel_name, it_cdr->party_b.snapshot->base->name)) {
headp = &it_cdr->party_b.variables;
}
if (headp) {
@ -3212,25 +3212,25 @@ static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *na
struct ast_channel_snapshot *party_b = cdr_obj->party_b.snapshot;
if (!strcasecmp(name, "clid")) {
ast_callerid_merge(value, length, party_a->caller_name, party_a->caller_number, "");
ast_callerid_merge(value, length, party_a->caller->name, party_a->caller->number, "");
} else if (!strcasecmp(name, "src")) {
ast_copy_string(value, party_a->caller_number, length);
ast_copy_string(value, party_a->caller->number, length);
} else if (!strcasecmp(name, "dst")) {
ast_copy_string(value, party_a->exten, length);
ast_copy_string(value, party_a->dialplan->exten, length);
} else if (!strcasecmp(name, "dcontext")) {
ast_copy_string(value, party_a->context, length);
ast_copy_string(value, party_a->dialplan->context, length);
} else if (!strcasecmp(name, "channel")) {
ast_copy_string(value, party_a->name, length);
ast_copy_string(value, party_a->base->name, length);
} else if (!strcasecmp(name, "dstchannel")) {
if (party_b) {
ast_copy_string(value, party_b->name, length);
ast_copy_string(value, party_b->base->name, length);
} else {
ast_copy_string(value, "", length);
}
} else if (!strcasecmp(name, "lastapp")) {
ast_copy_string(value, party_a->appl, length);
ast_copy_string(value, party_a->dialplan->appl, length);
} else if (!strcasecmp(name, "lastdata")) {
ast_copy_string(value, party_a->data, length);
ast_copy_string(value, party_a->dialplan->data, length);
} else if (!strcasecmp(name, "start")) {
cdr_get_tv(cdr_obj->start, NULL, value, length);
} else if (!strcasecmp(name, "answer")) {
@ -3246,15 +3246,15 @@ static int cdr_object_format_property(struct cdr_object *cdr_obj, const char *na
} else if (!strcasecmp(name, "amaflags")) {
snprintf(value, length, "%d", party_a->amaflags);
} else if (!strcasecmp(name, "accountcode")) {
ast_copy_string(value, party_a->accountcode, length);
ast_copy_string(value, party_a->base->accountcode, length);
} else if (!strcasecmp(name, "peeraccount")) {
if (party_b) {
ast_copy_string(value, party_b->accountcode, length);
ast_copy_string(value, party_b->base->accountcode, length);
} else {
ast_copy_string(value, "", length);
}
} else if (!strcasecmp(name, "uniqueid")) {
ast_copy_string(value, party_a->uniqueid, length);
ast_copy_string(value, party_a->base->uniqueid, length);
} else if (!strcasecmp(name, "linkedid")) {
ast_copy_string(value, cdr_obj->linkedid, length);
} else if (!strcasecmp(name, "userfield")) {
@ -3431,7 +3431,7 @@ static int cdr_object_update_party_b_userfield_cb(void *obj, void *arg, void *da
* is consistent with the key.
*/
ast_assert(cdr->party_b.snapshot
&& !strcasecmp(cdr->party_b.snapshot->name, info->channel_name));
&& !strcasecmp(cdr->party_b.snapshot->base->name, info->channel_name));
ast_copy_string(cdr->party_b.userfield, info->userfield,
sizeof(cdr->party_b.userfield));
@ -3624,7 +3624,7 @@ int ast_cdr_fork(const char *channel_name, struct ast_flags *options)
/* Copy over the basic CDR information. The Party A information is
* copied over automatically as part of the append
*/
ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->name);
ast_debug(1, "Forking CDR for channel %s\n", cdr->party_a.snapshot->base->name);
new_cdr = cdr_object_create_and_append(cdr);
if (!new_cdr) {
return -1;
@ -3938,8 +3938,8 @@ static char *cli_complete_show(struct ast_cli_args *a)
it_cdrs = ao2_iterator_init(active_cdrs_master, 0);
while ((cdr = ao2_iterator_next(&it_cdrs))) {
if (!strncasecmp(a->word, cdr->party_a.snapshot->name, wordlen)) {
if (ast_cli_completion_add(ast_strdup(cdr->party_a.snapshot->name))) {
if (!strncasecmp(a->word, cdr->party_a.snapshot->base->name, wordlen)) {
if (ast_cli_completion_add(ast_strdup(cdr->party_a.snapshot->base->name))) {
ao2_ref(cdr, -1);
break;
}
@ -4001,8 +4001,8 @@ static void cli_show_channels(struct ast_cli_args *a)
cdr_get_tv(start_time, "%T", start_time_buffer, sizeof(start_time_buffer));
cdr_get_tv(answer_time, "%T", answer_time_buffer, sizeof(answer_time_buffer));
cdr_get_tv(end_time, "%T", end_time_buffer, sizeof(end_time_buffer));
ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->name,
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
ast_cli(a->fd, FORMAT_STRING, it_cdr->party_a.snapshot->base->name,
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
it_cdr->appl,
start_time_buffer,
answer_time_buffer,
@ -4046,7 +4046,7 @@ static void cli_show_channel(struct ast_cli_args *a)
if (snapshot_is_dialed(it_cdr->party_a.snapshot)) {
continue;
}
ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller_name, it_cdr->party_a.snapshot->caller_number, "");
ast_callerid_merge(clid, sizeof(clid), it_cdr->party_a.snapshot->caller->name, it_cdr->party_a.snapshot->caller->number, "");
if (ast_tvzero(it_cdr->end)) {
end = ast_tvnow();
} else {
@ -4056,9 +4056,9 @@ static void cli_show_channel(struct ast_cli_args *a)
cdr_get_tv(it_cdr->answer, "%T", answer_time_buffer, sizeof(answer_time_buffer));
cdr_get_tv(end, "%T", end_time_buffer, sizeof(end_time_buffer));
ast_cli(a->fd, FORMAT_STRING,
it_cdr->party_a.snapshot->accountcode,
it_cdr->party_a.snapshot->base->accountcode,
clid,
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<none>",
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<none>",
it_cdr->appl,
it_cdr->data,
start_time_buffer,
@ -4415,8 +4415,8 @@ static void cdr_master_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
}
for (it_cdr = cdr; it_cdr; it_cdr = it_cdr->next) {
prnt(where, "Party A: %s; Party B: %s; Bridge %s\n",
it_cdr->party_a.snapshot->name,
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->name : "<unknown>",
it_cdr->party_a.snapshot->base->name,
it_cdr->party_b.snapshot ? it_cdr->party_b.snapshot->base->name : "<unknown>",
it_cdr->bridge);
}
}
@ -4440,8 +4440,8 @@ static void cdr_all_print_fn(void *v_obj, void *where, ao2_prnt_fn *prnt)
return;
}
prnt(where, "Party A: %s; Party B: %s; Bridge %s",
cdr->party_a.snapshot->name,
cdr->party_b.snapshot ? cdr->party_b.snapshot->name : "<unknown>",
cdr->party_a.snapshot->base->name,
cdr->party_b.snapshot ? cdr->party_b.snapshot->base->name : "<unknown>",
cdr->bridge);
}

@ -528,22 +528,22 @@ struct ast_event *ast_cel_create_event(struct ast_channel_snapshot *snapshot,
AST_EVENT_IE_CEL_EVENT_TIME, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_sec,
AST_EVENT_IE_CEL_EVENT_TIME_USEC, AST_EVENT_IE_PLTYPE_UINT, eventtime.tv_usec,
AST_EVENT_IE_CEL_USEREVENT_NAME, AST_EVENT_IE_PLTYPE_STR, S_OR(userdefevname, ""),
AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_name,
AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_number,
AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_ani,
AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_rdnis,
AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller_dnid,
AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->exten,
AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->context,
AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->name,
AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->appl,
AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->data,
AST_EVENT_IE_CEL_CIDNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->name,
AST_EVENT_IE_CEL_CIDNUM, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->number,
AST_EVENT_IE_CEL_CIDANI, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->ani,
AST_EVENT_IE_CEL_CIDRDNIS, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->rdnis,
AST_EVENT_IE_CEL_CIDDNID, AST_EVENT_IE_PLTYPE_STR, snapshot->caller->dnid,
AST_EVENT_IE_CEL_EXTEN, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->exten,
AST_EVENT_IE_CEL_CONTEXT, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->context,
AST_EVENT_IE_CEL_CHANNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->base->name,
AST_EVENT_IE_CEL_APPNAME, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->appl,
AST_EVENT_IE_CEL_APPDATA, AST_EVENT_IE_PLTYPE_STR, snapshot->dialplan->data,
AST_EVENT_IE_CEL_AMAFLAGS, AST_EVENT_IE_PLTYPE_UINT, snapshot->amaflags,
AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->accountcode,
AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peeraccount,
AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->uniqueid,
AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->linkedid,
AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->userfield,
AST_EVENT_IE_CEL_ACCTCODE, AST_EVENT_IE_PLTYPE_STR, snapshot->base->accountcode,
AST_EVENT_IE_CEL_PEERACCT, AST_EVENT_IE_PLTYPE_STR, snapshot->peer->account,
AST_EVENT_IE_CEL_UNIQUEID, AST_EVENT_IE_PLTYPE_STR, snapshot->base->uniqueid,
AST_EVENT_IE_CEL_LINKEDID, AST_EVENT_IE_PLTYPE_STR, snapshot->peer->linkedid,
AST_EVENT_IE_CEL_USERFIELD, AST_EVENT_IE_PLTYPE_STR, snapshot->base->userfield,
AST_EVENT_IE_CEL_EXTRA, AST_EVENT_IE_PLTYPE_STR, S_OR(extra_txt, ""),
AST_EVENT_IE_CEL_PEER, AST_EVENT_IE_PLTYPE_STR, S_OR(peer, ""),
AST_EVENT_IE_END);
@ -573,7 +573,7 @@ static int cel_report_event(struct ast_channel_snapshot *snapshot,
* reporting on CHANNEL_START so we can track when to send LINKEDID_END */
if (event_type == AST_CEL_CHANNEL_START
&& ast_cel_track_event(AST_CEL_LINKEDID_END)) {
if (cel_linkedid_ref(snapshot->linkedid)) {
if (cel_linkedid_ref(snapshot->peer->linkedid)) {
return -1;
}
}
@ -583,7 +583,7 @@ static int cel_report_event(struct ast_channel_snapshot *snapshot,
}
if ((event_type == AST_CEL_APP_START || event_type == AST_CEL_APP_END)
&& !cel_track_app(snapshot->appl)) {
&& !cel_track_app(snapshot->dialplan->appl)) {
return 0;
}
@ -606,14 +606,14 @@ static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)
RAII_VAR(struct ao2_container *, linkedids, ao2_global_obj_ref(cel_linkedids), ao2_cleanup);
struct cel_linkedid *lid;
if (!linkedids || ast_strlen_zero(snapshot->linkedid)) {
if (!linkedids || ast_strlen_zero(snapshot->peer->linkedid)) {
/* The CEL module is shutdown. Abort. */
return;
}
ao2_lock(linkedids);
lid = ao2_find(linkedids, (void *) snapshot->linkedid, OBJ_SEARCH_KEY);
lid = ao2_find(linkedids, (void *) snapshot->peer->linkedid, OBJ_SEARCH_KEY);
if (!lid) {
ao2_unlock(linkedids);
@ -623,7 +623,7 @@ static void check_retire_linkedid(struct ast_channel_snapshot *snapshot)
* of change to make after starting Asterisk.
*/
ast_log(LOG_ERROR, "Something weird happened, couldn't find linkedid %s\n",
snapshot->linkedid);
snapshot->peer->linkedid);
return;
}
@ -898,11 +898,11 @@ static void cel_channel_state_change(
if (!was_hungup && is_hungup) {
struct ast_json *extra;
struct cel_dialstatus *dialstatus = get_dialstatus(new_snapshot->uniqueid);
struct cel_dialstatus *dialstatus = get_dialstatus(new_snapshot->base->uniqueid);
extra = ast_json_pack("{s: i, s: s, s: s}",
"hangupcause", new_snapshot->hangupcause,
"hangupsource", new_snapshot->hangupsource,
"hangupcause", new_snapshot->hangup->cause,
"hangupsource", new_snapshot->hangup->source,
"dialstatus", dialstatus ? dialstatus->dialstatus : "");
cel_report_event(new_snapshot, AST_CEL_HANGUP, NULL, extra, NULL);
ast_json_unref(extra);
@ -929,12 +929,12 @@ static void cel_channel_linkedid_change(
return;
}
ast_assert(!ast_strlen_zero(new_snapshot->linkedid));
ast_assert(!ast_strlen_zero(old_snapshot->linkedid));
ast_assert(!ast_strlen_zero(new_snapshot->peer->linkedid));
ast_assert(!ast_strlen_zero(old_snapshot->peer->linkedid));
if (ast_cel_track_event(AST_CEL_LINKEDID_END)
&& strcmp(old_snapshot->linkedid, new_snapshot->linkedid)) {
cel_linkedid_ref(new_snapshot->linkedid);
&& strcmp(old_snapshot->peer->linkedid, new_snapshot->peer->linkedid)) {
cel_linkedid_ref(new_snapshot->peer->linkedid);
check_retire_linkedid(old_snapshot);
}
}
@ -943,17 +943,17 @@ static void cel_channel_app_change(
struct ast_channel_snapshot *old_snapshot,
struct ast_channel_snapshot *new_snapshot)
{
if (old_snapshot && !strcmp(old_snapshot->appl, new_snapshot->appl)) {
if (old_snapshot && !strcmp(old_snapshot->dialplan->appl, new_snapshot->dialplan->appl)) {
return;
}
/* old snapshot has an application, end it */
if (old_snapshot && !ast_strlen_zero(old_snapshot->appl)) {
if (old_snapshot && !ast_strlen_zero(old_snapshot->dialplan->appl)) {
cel_report_event(old_snapshot, AST_CEL_APP_END, NULL, NULL, NULL);
}
/* new snapshot has an application, start it */
if (!ast_strlen_zero(new_snapshot->appl)) {
if (!ast_strlen_zero(new_snapshot->dialplan->appl)) {
cel_report_event(new_snapshot, AST_CEL_APP_START, NULL, NULL, NULL);
}
}
@ -974,7 +974,7 @@ static int cel_filter_channel_snapshot(struct ast_channel_snapshot *snapshot)
if (!snapshot) {
return 0;
}
return snapshot->tech_properties & AST_CHAN_TP_INTERNAL;
return snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL;
}
static void cel_snapshot_update_cb(void *data, struct stasis_subscription *sub,
@ -1010,7 +1010,7 @@ static struct ast_str *cel_generate_peer_str(
struct ast_channel_snapshot *current_snapshot;
/* Don't add the channel for which this message is being generated */
if (!strcmp(current_chan, chan->uniqueid)) {
if (!strcmp(current_chan, chan->base->uniqueid)) {
continue;
}
@ -1019,7 +1019,7 @@ static struct ast_str *cel_generate_peer_str(
continue;
}
ast_str_append(&peer_str, 0, "%s,", current_snapshot->name);
ast_str_append(&peer_str, 0, "%s,", current_snapshot->base->name);
ao2_cleanup(current_snapshot);
}
ao2_iterator_destroy(&i);
@ -1125,7 +1125,7 @@ static void cel_parking_cb(
if (parked_payload->retriever) {
extra = ast_json_pack("{s: s, s: s}",
"reason", reason ?: "",
"retriever", parked_payload->retriever->name);
"retriever", parked_payload->retriever->base->name);
} else {
extra = ast_json_pack("{s: s}", "reason", reason ?: "");
}
@ -1147,7 +1147,7 @@ static void save_dialstatus(struct ast_multi_channel_blob *blob, struct ast_chan
return;
}
dialstatus = ao2_find(dial_statuses, snapshot->uniqueid, OBJ_SEARCH_KEY);
dialstatus = ao2_find(dial_statuses, snapshot->base->uniqueid, OBJ_SEARCH_KEY);
if (dialstatus) {
if (!strcasecmp(dialstatus_string, "ANSWER") && strcasecmp(dialstatus->dialstatus, "ANSWER")) {
/* In the case of an answer after we already have a dial status we give
@ -1171,7 +1171,7 @@ static void save_dialstatus(struct ast_multi_channel_blob *blob, struct ast_chan
return;
}
ast_copy_string(dialstatus->uniqueid, snapshot->uniqueid, sizeof(dialstatus->uniqueid));
ast_copy_string(dialstatus->uniqueid, snapshot->base->uniqueid, sizeof(dialstatus->uniqueid));
ast_copy_string(dialstatus->dialstatus, dialstatus_string, dialstatus_string_len);
ao2_link(dial_statuses, dialstatus);
@ -1273,8 +1273,8 @@ static void cel_blind_transfer_cb(
"extension", transfer_msg->exten,
"context", transfer_msg->context,
"bridge_id", bridge_snapshot->uniqueid,
"transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->name : "N/A",
"transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->uniqueid : "N/A");
"transferee_channel_name", transfer_msg->transferee ? transfer_msg->transferee->base->name : "N/A",
"transferee_channel_uniqueid", transfer_msg->transferee ? transfer_msg->transferee->base->uniqueid : "N/A");
if (extra) {
cel_report_event(chan_snapshot, AST_CEL_BLINDTRANSFER, NULL, extra, NULL);
ast_json_unref(extra);
@ -1312,13 +1312,13 @@ static void cel_attended_transfer_cb(
case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
"bridge1_id", bridge1->uniqueid,
"channel2_name", channel2->name,
"channel2_uniqueid", channel2->uniqueid,
"channel2_name", channel2->base->name,
"channel2_uniqueid", channel2->base->uniqueid,
"bridge2_id", bridge2->uniqueid,
"transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",
"transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",
"transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",
"transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");
"transferee_channel_name", xfer->transferee ? xfer->transferee->base->name : "N/A",
"transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->base->uniqueid : "N/A",
"transfer_target_channel_name", xfer->target ? xfer->target->base->name : "N/A",
"transfer_target_channel_uniqueid", xfer->target ? xfer->target->base->uniqueid : "N/A");
if (!extra) {
return;
}
@ -1327,13 +1327,13 @@ static void cel_attended_transfer_cb(
case AST_ATTENDED_TRANSFER_DEST_LOCAL_APP:
extra = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: s, s: s}",
"bridge1_id", bridge1->uniqueid,
"channel2_name", channel2->name,
"channel2_uniqueid", channel2->uniqueid,
"channel2_name", channel2->base->name,
"channel2_uniqueid", channel2->base->uniqueid,
"app", xfer->dest.app,
"transferee_channel_name", xfer->transferee ? xfer->transferee->name : "N/A",
"transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->uniqueid : "N/A",
"transfer_target_channel_name", xfer->target ? xfer->target->name : "N/A",
"transfer_target_channel_uniqueid", xfer->target ? xfer->target->uniqueid : "N/A");
"transferee_channel_name", xfer->transferee ? xfer->transferee->base->name : "N/A",
"transferee_channel_uniqueid", xfer->transferee ? xfer->transferee->base->uniqueid : "N/A",
"transfer_target_channel_name", xfer->target ? xfer->target->base->name : "N/A",
"transfer_target_channel_uniqueid", xfer->target ? xfer->target->base->uniqueid : "N/A");
if (!extra) {
return;
}
@ -1357,8 +1357,8 @@ static void cel_pickup_cb(
}
extra = ast_json_pack("{s: s, s: s}",
"pickup_channel", channel->name,
"pickup_channel_uniqueid", channel->uniqueid);
"pickup_channel", channel->base->name,
"pickup_channel_uniqueid", channel->base->uniqueid);
if (!extra) {
return;
}
@ -1381,8 +1381,8 @@ static void cel_local_cb(
}
extra = ast_json_pack("{s: s, s: s}",
"local_two", localtwo->name,
"local_two_uniqueid", localtwo->uniqueid);
"local_two", localtwo->base->name,
"local_two_uniqueid", localtwo->base->uniqueid);
if (!extra) {
return;
}

@ -6761,6 +6761,12 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
ast_channel_name(clonechan), ast_channel_state(clonechan),
ast_channel_name(original), ast_channel_state(original));
/* When all is said and done force new snapshot segments so they are
* up to date.
*/
ast_set_flag(ast_channel_snapshot_segment_flags(original), AST_FLAGS_ALL);
ast_set_flag(ast_channel_snapshot_segment_flags(clonechan), AST_FLAGS_ALL);
/*
* Remember the original read/write formats. We turn off any
* translation on either one
@ -7183,6 +7189,7 @@ void ast_channel_set_caller(struct ast_channel *chan, const struct ast_party_cal
ast_channel_lock(chan);
ast_party_caller_set(ast_channel_caller(chan), caller, update);
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
ast_channel_unlock(chan);
}
@ -7195,6 +7202,7 @@ void ast_channel_set_caller_event(struct ast_channel *chan, const struct ast_par
ast_channel_lock(chan);
ast_party_caller_set(ast_channel_caller(chan), caller, update);
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
ast_channel_publish_snapshot(chan);
ast_channel_unlock(chan);
}
@ -8120,6 +8128,7 @@ void ast_channel_set_connected_line(struct ast_channel *chan, const struct ast_p
ast_channel_lock(chan);
ast_party_connected_line_set(ast_channel_connected(chan), connected, update);
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED);
ast_channel_publish_snapshot(chan);
ast_channel_unlock(chan);
}
@ -8930,6 +8939,7 @@ void ast_channel_set_redirecting(struct ast_channel *chan, const struct ast_part
ast_channel_lock(chan);
ast_party_redirecting_set(ast_channel_redirecting(chan), redirecting, update);
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
ast_channel_unlock(chan);
}

@ -221,6 +221,7 @@ struct ast_channel {
void *stream_topology_change_source; /*!< Source that initiated a stream topology change */
struct ast_stream *default_streams[AST_MEDIA_TYPE_END]; /*!< Default streams indexed by media type */
struct ast_channel_snapshot *snapshot; /*!< The current up to date snapshot of the channel */
struct ast_flags snapshot_segment_flags; /*!< Flags regarding the segments of the snapshot */
};
/*! \brief The monotonically increasing integer counter for channel uniqueids */
@ -228,18 +229,40 @@ static int uniqueint;
/* ACCESSORS */
#define DEFINE_STRINGFIELD_SETTERS_FOR(field, publish, assert_on_null) \
#define DEFINE_STRINGFIELD_SETTERS_FOR(field, assert_on_null) \
void ast_channel_##field##_set(struct ast_channel *chan, const char *value) \
{ \
if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \
if (!strcmp(value, chan->field)) return; \
ast_string_field_set(chan, field, value); \
} \
\
void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) \
{ \
ast_string_field_build_va(chan, field, fmt, ap); \
} \
void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) \
{ \
va_list ap; \
va_start(ap, fmt); \
ast_channel_##field##_build_va(chan, fmt, ap); \
va_end(ap); \
}
#define DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(field, publish, assert_on_null, invalidate) \
void ast_channel_##field##_set(struct ast_channel *chan, const char *value) \
{ \
if ((assert_on_null)) ast_assert(!ast_strlen_zero(value)); \
if (!strcmp(value, chan->field)) return; \
ast_string_field_set(chan, field, value); \
ast_channel_snapshot_invalidate_segment(chan, invalidate); \
if (publish && ast_channel_internal_is_finalized(chan)) ast_channel_publish_snapshot(chan); \
} \
\
void ast_channel_##field##_build_va(struct ast_channel *chan, const char *fmt, va_list ap) \
{ \
ast_string_field_build_va(chan, field, fmt, ap); \
ast_channel_snapshot_invalidate_segment(chan, invalidate); \
if (publish && ast_channel_internal_is_finalized(chan)) ast_channel_publish_snapshot(chan); \
} \
void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...) \
@ -250,17 +273,17 @@ void ast_channel_##field##_build(struct ast_channel *chan, const char *fmt, ...)
va_end(ap); \
}
DEFINE_STRINGFIELD_SETTERS_FOR(name, 0, 1);
DEFINE_STRINGFIELD_SETTERS_FOR(language, 1, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(musicclass, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(latest_musicclass, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(accountcode, 1, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(peeraccount, 1, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(userfield, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(call_forward, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(hangupsource, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0, 0);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(name, 0, 1, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(language, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);
DEFINE_STRINGFIELD_SETTERS_FOR(musicclass, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(latest_musicclass, 0);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(accountcode, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(peeraccount, 1, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(userfield, 0, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);
DEFINE_STRINGFIELD_SETTERS_FOR(call_forward, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0);
DEFINE_STRINGFIELD_SETTERS_AND_INVALIDATE_FOR(hangupsource, 0, 0, AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP);
DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0);
#define DEFINE_STRINGFIELD_GETTER_FOR(field) const char *ast_channel_##field(const struct ast_channel *chan) \
{ \
@ -298,6 +321,7 @@ const char *ast_channel_appl(const struct ast_channel *chan)
void ast_channel_appl_set(struct ast_channel *chan, const char *value)
{
chan->appl = value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
}
const char *ast_channel_blockproc(const struct ast_channel *chan)
{
@ -314,6 +338,7 @@ const char *ast_channel_data(const struct ast_channel *chan)
void ast_channel_data_set(struct ast_channel *chan, const char *value)
{
chan->data = value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
}
const char *ast_channel_context(const struct ast_channel *chan)
@ -323,6 +348,7 @@ const char *ast_channel_context(const struct ast_channel *chan)
void ast_channel_context_set(struct ast_channel *chan, const char *value)
{
ast_copy_string(chan->context, value, sizeof(chan->context));
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
}
const char *ast_channel_exten(const struct ast_channel *chan)
{
@ -331,6 +357,7 @@ const char *ast_channel_exten(const struct ast_channel *chan)
void ast_channel_exten_set(struct ast_channel *chan, const char *value)
{
ast_copy_string(chan->exten, value, sizeof(chan->exten));
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
}
const char *ast_channel_macrocontext(const struct ast_channel *chan)
{
@ -404,6 +431,7 @@ int ast_channel_hangupcause(const struct ast_channel *chan)
void ast_channel_hangupcause_set(struct ast_channel *chan, int value)
{
chan->hangupcause = value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP);
}
int ast_channel_macropriority(const struct ast_channel *chan)
{
@ -420,6 +448,7 @@ int ast_channel_priority(const struct ast_channel *chan)
void ast_channel_priority_set(struct ast_channel *chan, int value)
{
chan->priority = value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
}
int ast_channel_rings(const struct ast_channel *chan)
{
@ -909,18 +938,22 @@ void ast_channel_jb_set(struct ast_channel *chan, struct ast_jb *value)
void ast_channel_caller_set(struct ast_channel *chan, struct ast_party_caller *value)
{
chan->caller = *value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
}
void ast_channel_connected_set(struct ast_channel *chan, struct ast_party_connected_line *value)
{
chan->connected = *value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CONNECTED);
}
void ast_channel_dialed_set(struct ast_channel *chan, struct ast_party_dialed *value)
{
chan->dialed = *value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
}
void ast_channel_redirecting_set(struct ast_channel *chan, struct ast_party_redirecting *value)
{
chan->redirecting = *value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_CALLER);
}
void ast_channel_dtmf_tv_set(struct ast_channel *chan, struct timeval *value)
{
@ -941,6 +974,7 @@ struct timeval ast_channel_creationtime(struct ast_channel *chan)
void ast_channel_creationtime_set(struct ast_channel *chan, struct timeval *value)
{
chan->creationtime = *value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE);
}
struct timeval ast_channel_answertime(struct ast_channel *chan)
@ -1204,6 +1238,7 @@ struct ast_bridge *ast_channel_internal_bridge(const struct ast_channel *chan)
void ast_channel_internal_bridge_set(struct ast_channel *chan, struct ast_bridge *value)
{
chan->bridge = value;
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE);
ast_channel_publish_snapshot(chan);
}
@ -1335,6 +1370,11 @@ struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj),
AST_VECTOR_INIT(&tmp->fds, AST_MAX_FDS);
/* Force all channel snapshot segments to be created on first use, so we don't have to check if
* an old snapshot exists.
*/
ast_set_flag(&tmp->snapshot_segment_flags, AST_FLAGS_ALL);
return tmp;
}
@ -1363,6 +1403,7 @@ void ast_channel_internal_copy_linkedid(struct ast_channel *dest, struct ast_cha
return;
}
dest->linkedid = source->linkedid;
ast_channel_snapshot_invalidate_segment(dest, AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER);
ast_channel_publish_snapshot(dest);
}
@ -1370,6 +1411,10 @@ void ast_channel_internal_swap_uniqueid_and_linkedid(struct ast_channel *a, stru
{
struct ast_channel_id temp;
/* This operation is used as part of masquerading and so does not invalidate the peer
* segment. This is due to the masquerade process invalidating all segments.
*/
temp = a->uniqueid;
a->uniqueid = b->uniqueid;
b->uniqueid = temp;
@ -1584,3 +1629,8 @@ void ast_channel_snapshot_set(struct ast_channel *chan, struct ast_channel_snaps
ao2_cleanup(chan->snapshot);
chan->snapshot = ao2_bump(snapshot);
}
struct ast_flags *ast_channel_snapshot_segment_flags(struct ast_channel *chan)
{
return &chan->snapshot_segment_flags;
}

@ -1004,8 +1004,8 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
char durbuf[16] = "-";
if (!count) {
if ((concise || verbose) && !ast_tvzero(cs->creationtime)) {
int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);
if ((concise || verbose) && !ast_tvzero(cs->base->creationtime)) {
int duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
if (verbose) {
int durh = duration / 3600;
int durm = (duration % 3600) / 60;
@ -1016,36 +1016,36 @@ static char *handle_chanlist(struct ast_cli_entry *e, int cmd, struct ast_cli_ar
}
}
if (concise) {
ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),
S_OR(cs->appl, "(None)"),
cs->data,
cs->caller_number,
cs->accountcode,
cs->peeraccount,
ast_cli(a->fd, CONCISE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),
S_OR(cs->dialplan->appl, "(None)"),
cs->dialplan->data,
cs->caller->number,
cs->base->accountcode,
cs->peer->account,
cs->amaflags,
durbuf,
cs->bridgeid,
cs->uniqueid);
cs->bridge->id,
cs->base->uniqueid);
} else if (verbose) {
ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->name, cs->context, cs->exten, cs->priority, ast_state2str(cs->state),
S_OR(cs->appl, "(None)"),
S_OR(cs->data, "(Empty)"),
cs->caller_number,
ast_cli(a->fd, VERBOSE_FORMAT_STRING, cs->base->name, cs->dialplan->context, cs->dialplan->exten, cs->dialplan->priority, ast_state2str(cs->state),
S_OR(cs->dialplan->appl, "(None)"),
S_OR(cs->dialplan->data, "(Empty)"),
cs->caller->number,
durbuf,
cs->accountcode,
cs->peeraccount,
cs->bridgeid);
cs->base->accountcode,
cs->peer->account,
cs->bridge->id);
} else {
char locbuf[40] = "(None)";
char appdata[40] = "(None)";
if (!ast_strlen_zero(cs->context) && !ast_strlen_zero(cs->exten)) {
snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->exten, cs->context, cs->priority);
if (!ast_strlen_zero(cs->dialplan->context) && !ast_strlen_zero(cs->dialplan->exten)) {
snprintf(locbuf, sizeof(locbuf), "%s@%s:%d", cs->dialplan->exten, cs->dialplan->context, cs->dialplan->priority);
}
if (!ast_strlen_zero(cs->appl)) {
snprintf(appdata, sizeof(appdata), "%s(%s)", cs->appl, S_OR(cs->data, ""));
if (!ast_strlen_zero(cs->dialplan->appl)) {
snprintf(appdata, sizeof(appdata), "%s(%s)", cs->dialplan->appl, S_OR(cs->dialplan->data, ""));
}
ast_cli(a->fd, FORMAT_STRING, cs->name, locbuf, ast_state2str(cs->state), appdata);
ast_cli(a->fd, FORMAT_STRING, cs->base->name, locbuf, ast_state2str(cs->state), appdata);
}
}
}
@ -1684,14 +1684,14 @@ char *ast_complete_channels(const char *line, const char *word, int pos, int sta
iter = ao2_iterator_init(cached_channels, 0);
for (; (snapshot = ao2_iterator_next(&iter)); ao2_ref(snapshot, -1)) {
if (!strncasecmp(word, snapshot->name, wordlen) && (++which > state)) {
if (!strncasecmp(word, snapshot->base->name, wordlen) && (++which > state)) {
if (state != -1) {
ret = ast_strdup(snapshot->name);
ret = ast_strdup(snapshot->base->name);
ao2_ref(snapshot, -1);
break;
}
if (ast_cli_completion_add(ast_strdup(snapshot->name))) {
if (ast_cli_completion_add(ast_strdup(snapshot->base->name))) {
ao2_ref(snapshot, -1);
break;
}

@ -493,7 +493,7 @@ static struct ast_manager_event_blob *local_message_to_ami(struct stasis_message
}
dest_uniqueid = ast_json_object_get(blob, "dest") == AST_UNREAL_OWNER ?
local_snapshot_one->uniqueid : local_snapshot_two->uniqueid;
local_snapshot_one->base->uniqueid : local_snapshot_two->base->uniqueid;
event = "LocalOptimizationBegin";
if (source_str) {

@ -195,7 +195,7 @@ static void endpoint_cache_clear(void *data,
ast_assert(endpoint != NULL);
ao2_lock(endpoint);
ast_str_container_remove(endpoint->channel_ids, update->new_snapshot->uniqueid);
ast_str_container_remove(endpoint->channel_ids, update->new_snapshot->base->uniqueid);
ao2_unlock(endpoint);
endpoint_publish_snapshot(endpoint);
}

@ -6271,10 +6271,10 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m
continue;
}
if (!ast_tvzero(cs->creationtime)) {
if (!ast_tvzero(cs->base->creationtime)) {
int duration, durh, durm, durs;
duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->creationtime) / 1000);
duration = (int)(ast_tvdiff_ms(ast_tvnow(), cs->base->creationtime) / 1000);
durh = duration / 3600;
durm = (duration % 3600) / 60;
durs = duration % 60;
@ -6292,10 +6292,10 @@ static int action_coreshowchannels(struct mansession *s, const struct message *m
"\r\n",
idText,
ast_str_buffer(built),
cs->appl,
cs->data,
cs->dialplan->appl,
cs->dialplan->data,
durbuf,
cs->bridgeid);
cs->bridge->id);
numchans++;

@ -536,7 +536,7 @@ static int send_bridge_info_item_cb(void *obj, void *arg, void *data, int flags)
return 0;
}
if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) {
if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {
return 0;
}

@ -493,7 +493,7 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
char *connected_name;
int res;
if (snapshot->tech_properties & AST_CHAN_TP_INTERNAL) {
if (snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL) {
return NULL;
}
@ -502,8 +502,8 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
return NULL;
}
caller_name = ast_escape_c_alloc(snapshot->caller_name);
connected_name = ast_escape_c_alloc(snapshot->connected_name);
caller_name = ast_escape_c_alloc(snapshot->caller->name);
connected_name = ast_escape_c_alloc(snapshot->connected->name);
res = ast_str_set(&out, 0,
"%sChannel: %s\r\n"
@ -520,20 +520,20 @@ struct ast_str *ast_manager_build_channel_state_string_prefix(
"%sPriority: %d\r\n"
"%sUniqueid: %s\r\n"
"%sLinkedid: %s\r\n",
prefix, snapshot->name,
prefix, snapshot->base->name,
prefix, snapshot->state,
prefix, ast_state2str(snapshot->state),
prefix, S_OR(snapshot->caller_number, "<unknown>"),
prefix, S_OR(snapshot->caller->number, "<unknown>"),
prefix, S_OR(caller_name, "<unknown>"),
prefix, S_OR(snapshot->connected_number, "<unknown>"),
prefix, S_OR(snapshot->connected->number, "<unknown>"),
prefix, S_OR(connected_name, "<unknown>"),
prefix, snapshot->language,
prefix, snapshot->accountcode,
prefix, snapshot->context,
prefix, snapshot->exten,
prefix, snapshot->priority,
prefix, snapshot->uniqueid,
prefix, snapshot->linkedid);
prefix, snapshot->base->language,
prefix, snapshot->base->accountcode,
prefix, snapshot->dialplan->context,
prefix, snapshot->dialplan->exten,
prefix, snapshot->dialplan->priority,
prefix, snapshot->base->uniqueid,
prefix, snapshot->peer->linkedid);
ast_free(caller_name);
ast_free(connected_name);
@ -594,8 +594,8 @@ static struct ast_manager_event_blob *channel_state_change(
EVENT_FLAG_CALL, "Hangup",
"Cause: %d\r\n"
"Cause-txt: %s\r\n",
new_snapshot->hangupcause,
ast_cause2str(new_snapshot->hangupcause));
new_snapshot->hangup->cause,
ast_cause2str(new_snapshot->hangup->cause));
}
if (old_snapshot->state != new_snapshot->state) {
@ -612,7 +612,7 @@ static struct ast_manager_event_blob *channel_newexten(
struct ast_channel_snapshot *new_snapshot)
{
/* Empty application is not valid for a Newexten event */
if (ast_strlen_zero(new_snapshot->appl)) {
if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
return NULL;
}
@ -632,9 +632,9 @@ static struct ast_manager_event_blob *channel_newexten(
"Extension: %s\r\n"
"Application: %s\r\n"
"AppData: %s\r\n",
new_snapshot->exten,
new_snapshot->appl,
new_snapshot->data);
new_snapshot->dialplan->exten,
new_snapshot->dialplan->appl,
new_snapshot->dialplan->data);
}
static struct ast_manager_event_blob *channel_new_callerid(
@ -654,14 +654,14 @@ static struct ast_manager_event_blob *channel_new_callerid(
}
if (!(callerid = ast_escape_c_alloc(
ast_describe_caller_presentation(new_snapshot->caller_pres)))) {
ast_describe_caller_presentation(new_snapshot->caller->pres)))) {
return NULL;
}
res = ast_manager_event_blob_create(
EVENT_FLAG_CALL, "NewCallerid",
"CID-CallingPres: %d (%s)\r\n",
new_snapshot->caller_pres,
new_snapshot->caller->pres,
callerid);
ast_free(callerid);
@ -693,13 +693,13 @@ static struct ast_manager_event_blob *channel_new_accountcode(
return NULL;
}
if (!strcmp(old_snapshot->accountcode, new_snapshot->accountcode)) {
if (!strcmp(old_snapshot->base->accountcode, new_snapshot->base->accountcode)) {
return NULL;
}
return ast_manager_event_blob_create(
EVENT_FLAG_CALL, "NewAccountCode",
"OldAccountCode: %s\r\n", old_snapshot->accountcode);
"OldAccountCode: %s\r\n", old_snapshot->base->accountcode);
}
channel_snapshot_monitor channel_monitors[] = {

@ -1069,7 +1069,7 @@ static struct ast_manager_event_blob *attended_transfer_to_ami(struct stasis_mes
case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
ast_str_append(&variable_data, 0, "DestType: Threeway\r\n");
ast_str_append(&variable_data, 0, "DestBridgeUniqueid: %s\r\n", transfer_msg->dest.threeway.bridge_snapshot->uniqueid);
ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->name);
ast_str_append(&variable_data, 0, "DestTransfererChannel: %s\r\n", transfer_msg->dest.threeway.channel_snapshot->base->name);
break;
case AST_ATTENDED_TRANSFER_DEST_FAIL:
ast_str_append(&variable_data, 0, "DestType: Fail\r\n");
@ -1189,7 +1189,7 @@ int ast_attended_transfer_message_add_threeway(struct ast_attended_transfer_mess
{
transfer_msg->dest_type = AST_ATTENDED_TRANSFER_DEST_THREEWAY;
if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->uniqueid)) {
if (!strcmp(ast_channel_uniqueid(survivor_channel), transfer_msg->to_transferee.channel_snapshot->base->uniqueid)) {
transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transferee.channel_snapshot;
} else {
transfer_msg->dest.threeway.channel_snapshot = transfer_msg->to_transfer_target.channel_snapshot;

@ -149,7 +149,7 @@ static int channel_snapshot_hash_cb(const void *obj, const int flags)
key = obj;
break;
case OBJ_SEARCH_OBJECT:
key = object->name;
key = object->base->name;
break;
default:
ast_assert(0);
@ -171,12 +171,12 @@ static int channel_snapshot_cmp_cb(void *obj, void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
right_key = object_right->name;
right_key = object_right->base->name;
case OBJ_SEARCH_KEY:
cmp = strcasecmp(object_left->name, right_key);
cmp = strcasecmp(object_left->base->name, right_key);
break;
case OBJ_SEARCH_PARTIAL_KEY:
cmp = strncasecmp(object_left->name, right_key, strlen(right_key));
cmp = strncasecmp(object_left->base->name, right_key, strlen(right_key));
break;
default:
cmp = 0;
@ -202,7 +202,7 @@ static int channel_snapshot_uniqueid_hash_cb(const void *obj, const int flags)
key = obj;
break;
case OBJ_SEARCH_OBJECT:
key = object->uniqueid;
key = object->base->uniqueid;
break;
default:
ast_assert(0);
@ -224,12 +224,12 @@ static int channel_snapshot_uniqueid_cmp_cb(void *obj, void *arg, int flags)
switch (flags & OBJ_SEARCH_MASK) {
case OBJ_SEARCH_OBJECT:
right_key = object_right->uniqueid;
right_key = object_right->base->uniqueid;
case OBJ_SEARCH_KEY:
cmp = strcasecmp(object_left->uniqueid, right_key);
cmp = strcasecmp(object_left->base->uniqueid, right_key);
break;
case OBJ_SEARCH_PARTIAL_KEY:
cmp = strncasecmp(object_left->uniqueid, right_key, strlen(right_key));
cmp = strncasecmp(object_left->base->uniqueid, right_key, strlen(right_key));
break;
default:
cmp = 0;
@ -245,88 +245,312 @@ static void channel_snapshot_dtor(void *obj)
{
struct ast_channel_snapshot *snapshot = obj;
ast_string_field_free_memory(snapshot);
ao2_cleanup(snapshot->base);
ao2_cleanup(snapshot->peer);
ao2_cleanup(snapshot->caller);
ao2_cleanup(snapshot->connected);
ao2_cleanup(snapshot->bridge);
ao2_cleanup(snapshot->dialplan);
ao2_cleanup(snapshot->hangup);
ao2_cleanup(snapshot->manager_vars);
ao2_cleanup(snapshot->ari_vars);
}
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
static void channel_snapshot_base_dtor(void *obj)
{
struct ast_channel_snapshot *snapshot;
struct ast_bridge *bridge;
struct ast_channel_snapshot_base *snapshot = obj;
/* no snapshots for dummy channels */
if (!ast_channel_tech(chan)) {
ast_string_field_free_memory(snapshot);
}
static struct ast_channel_snapshot_base *channel_snapshot_base_create(struct ast_channel *chan)
{
struct ast_channel_snapshot_base *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_base_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot || ast_string_field_init(snapshot, 1024)) {
ao2_cleanup(snapshot);
if (ast_string_field_init(snapshot, 256)) {
ao2_ref(snapshot, -1);
return NULL;
}
ast_string_field_set(snapshot, name, ast_channel_name(chan));
ast_string_field_set(snapshot, type, ast_channel_tech(chan)->type);
ast_string_field_set(snapshot, accountcode, ast_channel_accountcode(chan));
ast_string_field_set(snapshot, peeraccount, ast_channel_peeraccount(chan));
ast_string_field_set(snapshot, userfield, ast_channel_userfield(chan));
ast_string_field_set(snapshot, uniqueid, ast_channel_uniqueid(chan));
ast_string_field_set(snapshot, linkedid, ast_channel_linkedid(chan));
ast_string_field_set(snapshot, hangupsource, ast_channel_hangupsource(chan));
if (ast_channel_appl(chan)) {
ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
ast_string_field_set(snapshot, language, ast_channel_language(chan));
snapshot->creationtime = ast_channel_creationtime(chan);
snapshot->tech_properties = ast_channel_tech(chan)->properties;
return snapshot;
}
static struct ast_channel_snapshot_peer *channel_snapshot_peer_create(struct ast_channel *chan)
{
const char *linkedid = S_OR(ast_channel_linkedid(chan), "");
const char *peeraccount = S_OR(ast_channel_peeraccount(chan), "");
size_t linkedid_len = strlen(linkedid) + 1;
size_t peeraccount_len = strlen(peeraccount) + 1;
struct ast_channel_snapshot_peer *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot) + linkedid_len + peeraccount_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
if (ast_channel_data(chan)) {
ast_string_field_set(snapshot, data, ast_channel_data(chan));
strcpy(snapshot->account, peeraccount); /* Safe */
snapshot->linkedid = snapshot->account + peeraccount_len;
strcpy(snapshot->linkedid, linkedid); /* Safe */
return snapshot;
}
static void channel_snapshot_caller_dtor(void *obj)
{
struct ast_channel_snapshot_caller *snapshot = obj;
ast_string_field_free_memory(snapshot);
}
static struct ast_channel_snapshot_caller *channel_snapshot_caller_create(struct ast_channel *chan)
{
struct ast_channel_snapshot_caller *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_caller_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
if (ast_string_field_init(snapshot, 256)) {
ao2_ref(snapshot, -1);
return NULL;
}
ast_string_field_set(snapshot, context, ast_channel_context(chan));
ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
ast_string_field_set(snapshot, caller_name,
ast_string_field_set(snapshot, name,
S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, ""));
ast_string_field_set(snapshot, caller_number,
ast_string_field_set(snapshot, number,
S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""));
ast_string_field_set(snapshot, caller_subaddr,
ast_string_field_set(snapshot, subaddr,
S_COR(ast_channel_caller(chan)->id.subaddress.valid, ast_channel_caller(chan)->id.subaddress.str, ""));
ast_string_field_set(snapshot, caller_ani,
ast_string_field_set(snapshot, ani,
S_COR(ast_channel_caller(chan)->ani.number.valid, ast_channel_caller(chan)->ani.number.str, ""));
ast_string_field_set(snapshot, caller_rdnis,
ast_string_field_set(snapshot, rdnis,
S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, ""));
ast_string_field_set(snapshot, caller_dnid,
ast_string_field_set(snapshot, dnid,
S_OR(ast_channel_dialed(chan)->number.str, ""));
ast_string_field_set(snapshot, dialed_subaddr,
S_COR(ast_channel_dialed(chan)->subaddress.valid, ast_channel_dialed(chan)->subaddress.str, ""));
ast_string_field_set(snapshot, connected_name,
S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, ""));
ast_string_field_set(snapshot, connected_number,
S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, ""));
snapshot->pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
ast_string_field_set(snapshot, language, ast_channel_language(chan));
return snapshot;
}
static struct ast_channel_snapshot_connected *channel_snapshot_connected_create(struct ast_channel *chan)
{
const char *name = S_COR(ast_channel_connected(chan)->id.name.valid, ast_channel_connected(chan)->id.name.str, "");
const char *number = S_COR(ast_channel_connected(chan)->id.number.valid, ast_channel_connected(chan)->id.number.str, "");
size_t name_len = strlen(name) + 1;
size_t number_len = strlen(number) + 1;
struct ast_channel_snapshot_connected *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot) + name_len + number_len, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
strcpy(snapshot->name, name); /* Safe */
snapshot->number = snapshot->name + name_len;
strcpy(snapshot->number, number); /* Safe */
return snapshot;
}
static struct ast_channel_snapshot_bridge *channel_snapshot_bridge_create(struct ast_channel *chan)
{
const char *uniqueid = "";
struct ast_bridge *bridge;
struct ast_channel_snapshot_bridge *snapshot;
bridge = ast_channel_get_bridge(chan);
if (bridge && !ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
uniqueid = bridge->uniqueid;
}
ao2_cleanup(bridge);
snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(uniqueid) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
strcpy(snapshot->id, uniqueid); /* Safe */
return snapshot;
}
static void channel_snapshot_dialplan_dtor(void *obj)
{
struct ast_channel_snapshot_dialplan *snapshot = obj;
ast_string_field_free_memory(snapshot);
}
static struct ast_channel_snapshot_dialplan *channel_snapshot_dialplan_create(struct ast_channel *chan)
{
struct ast_channel_snapshot_dialplan *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dialplan_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
if ((bridge = ast_channel_get_bridge(chan))) {
if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_INVISIBLE)) {
ast_string_field_set(snapshot, bridgeid, bridge->uniqueid);
if (ast_string_field_init(snapshot, 256)) {
ao2_ref(snapshot, -1);
return NULL;
}
if (ast_channel_appl(chan)) {
ast_string_field_set(snapshot, appl, ast_channel_appl(chan));
}
if (ast_channel_data(chan)) {
ast_string_field_set(snapshot, data, ast_channel_data(chan));
}
ast_string_field_set(snapshot, context, ast_channel_context(chan));
ast_string_field_set(snapshot, exten, ast_channel_exten(chan));
snapshot->priority = ast_channel_priority(chan);
return snapshot;
}
static struct ast_channel_snapshot_hangup *channel_snapshot_hangup_create(struct ast_channel *chan)
{
const char *hangupsource = S_OR(ast_channel_hangupsource(chan), "");
struct ast_channel_snapshot_hangup *snapshot;
snapshot = ao2_alloc_options(sizeof(*snapshot) + strlen(hangupsource) + 1, NULL, AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
snapshot->cause = ast_channel_hangupcause(chan);
strcpy(snapshot->source, hangupsource); /* Safe */
return snapshot;
}
struct ast_channel_snapshot *ast_channel_snapshot_create(struct ast_channel *chan)
{
struct ast_channel_snapshot *old_snapshot;
struct ast_channel_snapshot *snapshot;
/* no snapshots for dummy channels */
if (!ast_channel_tech(chan)) {
return NULL;
}
snapshot = ao2_alloc_options(sizeof(*snapshot), channel_snapshot_dtor,
AO2_ALLOC_OPT_LOCK_NOLOCK);
if (!snapshot) {
return NULL;
}
old_snapshot = ast_channel_snapshot(chan);
/* Channels automatically have all segments invalidated on them initially so a check for an old
* snapshot existing before usage is not done here, as it can not happen. If the stored snapshot
* on the channel is updated as a result of this then all segments marked as invalidated will be
* cleared.
*/
if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_BASE)) {
/* The base information has changed so update our snapshot */
snapshot->base = channel_snapshot_base_create(chan);
if (!snapshot->base) {
ao2_ref(snapshot, -1);
return NULL;
}
ao2_cleanup(bridge);
} else {
snapshot->base = ao2_bump(old_snapshot->base);
}
if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_PEER)) {
/* The peer information has changed so update our snapshot */
snapshot->peer = channel_snapshot_peer_create(chan);
if (!snapshot->peer) {
ao2_ref(snapshot, -1);
return NULL;
}
} else {
snapshot->peer = ao2_bump(old_snapshot->peer);
}
/* Unfortunately both caller and connected information do not have an enforced contract with
* the channel API. This has allowed consumers to directly get the caller or connected structure
* and manipulate it. Until such time as there is an enforced contract (which is being tracked under
* ASTERISK-28164) they are each regenerated every time a channel snapshot is created.
*/
snapshot->caller = channel_snapshot_caller_create(chan);
if (!snapshot->caller) {
ao2_ref(snapshot, -1);
return NULL;
}
snapshot->connected = channel_snapshot_connected_create(chan);
if (!snapshot->connected) {
ao2_ref(snapshot, -1);
return NULL;
}
if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_BRIDGE)) {
/* The bridge has changed so update our snapshot */
snapshot->bridge = channel_snapshot_bridge_create(chan);
if (!snapshot->bridge) {
ao2_ref(snapshot, -1);
return NULL;
}
} else {
snapshot->bridge = ao2_bump(old_snapshot->bridge);
}
if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN)) {
/* The dialplan information has changed so update our snapshot */
snapshot->dialplan = channel_snapshot_dialplan_create(chan);
if (!snapshot->dialplan) {
ao2_ref(snapshot, -1);
return NULL;
}
} else {
snapshot->dialplan = ao2_bump(old_snapshot->dialplan);
}
if (ast_test_flag(ast_channel_snapshot_segment_flags(chan), AST_CHANNEL_SNAPSHOT_INVALIDATE_HANGUP)) {
/* The hangup information has changed so update our snapshot */
snapshot->hangup = channel_snapshot_hangup_create(chan);
if (!snapshot->hangup) {
ao2_ref(snapshot, -1);
return NULL;
}
} else {
snapshot->hangup = ao2_bump(old_snapshot->hangup);
}
snapshot->creationtime = ast_channel_creationtime(chan);
snapshot->state = ast_channel_state(chan);
snapshot->priority = ast_channel_priority(chan);
snapshot->amaflags = ast_channel_amaflags(chan);
snapshot->hangupcause = ast_channel_hangupcause(chan);
ast_copy_flags(&snapshot->flags, ast_channel_flags(chan), 0xFFFFFFFF);
snapshot->caller_pres = ast_party_id_presentation(&ast_channel_caller(chan)->id);
ast_set_flag(&snapshot->softhangup_flags, ast_channel_softhangup_internal_flag(chan));
/* These have to be recreated as they may have changed, unfortunately */
snapshot->manager_vars = ast_channel_get_manager_vars(chan);
snapshot->ari_vars = ast_channel_get_ari_vars(chan);
snapshot->tech_properties = ast_channel_tech(chan)->properties;
return snapshot;
}
@ -822,6 +1046,12 @@ void ast_channel_stage_snapshot_done(struct ast_channel *chan)
ast_channel_publish_snapshot(chan);
}
void ast_channel_snapshot_invalidate_segment(struct ast_channel *chan,
enum ast_channel_snapshot_segment_invalidation segment)
{
ast_set_flag(ast_channel_snapshot_segment_flags(chan), segment);
}
void ast_channel_publish_snapshot(struct ast_channel *chan)
{
struct ast_channel_snapshot_update *update;
@ -840,6 +1070,14 @@ void ast_channel_publish_snapshot(struct ast_channel *chan)
return;
}
/* If an old snapshot exists and is the same as this newly created one don't bother
* raising a message as it hasn't changed.
*/
if (update->old_snapshot && !memcmp(update->old_snapshot, update->new_snapshot, sizeof(struct ast_channel_snapshot))) {
ao2_ref(update, -1);
return;
}
message = stasis_message_create(ast_channel_snapshot_type(), update);
/* In the success path message holds a reference to update so it will be valid
* for the lifetime of this function until the end.
@ -869,6 +1107,11 @@ void ast_channel_publish_snapshot(struct ast_channel *chan)
ast_channel_snapshot_set(chan, update->new_snapshot);
/* As this is now the new snapshot any existing invalidated segments have been
* created fresh and are up to date.
*/
ast_clear_flag(ast_channel_snapshot_segment_flags(chan), AST_FLAGS_ALL);
ast_assert(ast_channel_topic(chan) != NULL);
stasis_publish(ast_channel_topic(chan), message);
ao2_ref(message, -1);
@ -1028,20 +1271,20 @@ struct ast_json *ast_channel_snapshot_to_json(
" s: o, s: o, s: s,"
" s: o, s: o, s: s }",
/* First line */
"id", snapshot->uniqueid,
"name", snapshot->name,
"id", snapshot->base->uniqueid,
"name", snapshot->base->name,
"state", ast_state2str(snapshot->state),
/* Second line */
"caller", ast_json_name_number(
snapshot->caller_name, snapshot->caller_number),
snapshot->caller->name, snapshot->caller->number),
"connected", ast_json_name_number(
snapshot->connected_name, snapshot->connected_number),
"accountcode", snapshot->accountcode,
snapshot->connected->name, snapshot->connected->number),
"accountcode", snapshot->base->accountcode,
/* Third line */
"dialplan", ast_json_dialplan_cep(
snapshot->context, snapshot->exten, snapshot->priority),
"creationtime", ast_json_timeval(snapshot->creationtime, NULL),
"language", snapshot->language);
snapshot->dialplan->context, snapshot->dialplan->exten, snapshot->dialplan->priority),
"creationtime", ast_json_timeval(snapshot->base->creationtime, NULL),
"language", snapshot->base->language);
if (snapshot->ari_vars && !AST_LIST_EMPTY(snapshot->ari_vars)) {
ast_json_object_set(json_chan, "channelvars", ast_json_channel_vars(snapshot->ari_vars));
@ -1061,14 +1304,14 @@ int ast_channel_snapshot_cep_equal(
* application is set. Since empty application is invalid, we treat
* setting the application from nothing as a CEP change.
*/
if (ast_strlen_zero(old_snapshot->appl) &&
!ast_strlen_zero(new_snapshot->appl)) {
if (ast_strlen_zero(old_snapshot->dialplan->appl) &&
!ast_strlen_zero(new_snapshot->dialplan->appl)) {
return 0;
}
return old_snapshot->priority == new_snapshot->priority &&
strcmp(old_snapshot->context, new_snapshot->context) == 0 &&
strcmp(old_snapshot->exten, new_snapshot->exten) == 0;
return old_snapshot->dialplan->priority == new_snapshot->dialplan->priority &&
strcmp(old_snapshot->dialplan->context, new_snapshot->dialplan->context) == 0 &&
strcmp(old_snapshot->dialplan->exten, new_snapshot->dialplan->exten) == 0;
}
int ast_channel_snapshot_caller_id_equal(
@ -1077,8 +1320,8 @@ int ast_channel_snapshot_caller_id_equal(
{
ast_assert(old_snapshot != NULL);
ast_assert(new_snapshot != NULL);
return strcmp(old_snapshot->caller_number, new_snapshot->caller_number) == 0 &&
strcmp(old_snapshot->caller_name, new_snapshot->caller_name) == 0;
return strcmp(old_snapshot->caller->number, new_snapshot->caller->number) == 0 &&
strcmp(old_snapshot->caller->name, new_snapshot->caller->name) == 0;
}
int ast_channel_snapshot_connected_line_equal(
@ -1087,8 +1330,8 @@ int ast_channel_snapshot_connected_line_equal(
{
ast_assert(old_snapshot != NULL);
ast_assert(new_snapshot != NULL);
return strcmp(old_snapshot->connected_number, new_snapshot->connected_number) == 0 &&
strcmp(old_snapshot->connected_name, new_snapshot->connected_name) == 0;
return strcmp(old_snapshot->connected->number, new_snapshot->connected->number) == 0 &&
strcmp(old_snapshot->connected->name, new_snapshot->connected->name) == 0;
}
static struct ast_json *channel_blob_to_json(

@ -344,6 +344,11 @@ static int realtime_exec(struct ast_channel *chan, const char *context, const ch
term_color(tmp3, S_OR(appdata, ""), COLOR_BRMAGENTA, 0, sizeof(tmp3)));
if (ast_channel_snapshot_type()) {
ast_channel_lock(chan);
/* Force a new dialplan segment that will be unique to use so we can update it with the
* information we want. In the future when a channel snapshot is published this will
* occur again and unset this flag.
*/
ast_channel_snapshot_invalidate_segment(chan, AST_CHANNEL_SNAPSHOT_INVALIDATE_DIALPLAN);
snapshot = ast_channel_snapshot_create(chan);
ast_channel_unlock(chan);
}
@ -351,8 +356,8 @@ static int realtime_exec(struct ast_channel *chan, const char *context, const ch
/* pbx_exec sets application name and data, but we don't want to log
* every exec. Just update the snapshot here instead.
*/
ast_string_field_set(snapshot, appl, app);
ast_string_field_set(snapshot, data, !ast_strlen_zero(appdata) ? appdata : "(NULL)");
ast_string_field_set(snapshot->dialplan, appl, app);
ast_string_field_set(snapshot->dialplan, data, !ast_strlen_zero(appdata) ? appdata : "(NULL)");
msg = stasis_message_create(ast_channel_snapshot_type(), snapshot);
if (msg) {
stasis_publish(ast_channel_topic(chan), msg);

@ -377,7 +377,7 @@ static int ari_bridges_play_helper(const char **args_media,
return -1;
}
language = S_OR(args_lang, snapshot->language);
language = S_OR(args_lang, snapshot->base->language);
playback = stasis_app_control_play_uri(control, args_media, args_media_count,
language, bridge->uniqueid, STASIS_PLAYBACK_TARGET_BRIDGE, args_skipms,

@ -170,8 +170,8 @@ void ast_ari_channels_continue_in_dialplan(
}
if (ast_strlen_zero(args->context)) {
context = snapshot->context;
exten = S_OR(args->extension, snapshot->exten);
context = snapshot->dialplan->context;
exten = S_OR(args->extension, snapshot->dialplan->exten);
} else {
context = args->context;
exten = S_OR(args->extension, "s");
@ -203,7 +203,7 @@ void ast_ari_channels_continue_in_dialplan(
ipri = args->priority;
} else if (ast_strlen_zero(args->context) && ast_strlen_zero(args->extension)) {
/* Special case. No exten, context, or priority provided, then move on to the next priority */
ipri = snapshot->priority + 1;
ipri = snapshot->dialplan->priority + 1;
} else {
ipri = 1;
}
@ -263,10 +263,10 @@ void ast_ari_channels_redirect(struct ast_variable *headers,
return;
}
if (strncasecmp(chan_snapshot->type, tech, tech_len)) {
if (strncasecmp(chan_snapshot->base->type, tech, tech_len)) {
ast_ari_response_error(response, 422, "Unprocessable Entity",
"Endpoint technology '%s' does not match channel technology '%s'",
tech, chan_snapshot->type);
tech, chan_snapshot->base->type);
return;
}
@ -628,7 +628,7 @@ static void ari_channels_handle_play(
return;
}
language = S_OR(args_lang, snapshot->language);
language = S_OR(args_lang, snapshot->base->language);
playback = stasis_app_control_play_uri(control, args_media, args_media_count, language,
args_channel_id, STASIS_PLAYBACK_TARGET_CHANNEL, args_skipms, args_offsetms, args_playback_id);

@ -819,12 +819,12 @@ static void announce_to_dial(char *dial_string, char *announce_string, int parki
snprintf(buf, sizeof(buf), "%d", parkingspace);
oh.vars = ast_variable_new("_PARKEDAT", buf, "");
inherit_channel_vars_from_id(&oh, parkee_snapshot->uniqueid);
inherit_channel_vars_from_id(&oh, parkee_snapshot->base->uniqueid);
dchan = __ast_request_and_dial(dial_tech, cap_slin, NULL, NULL, dial_string, 30000,
&outstate,
parkee_snapshot->caller_number,
parkee_snapshot->caller_name,
parkee_snapshot->caller->number,
parkee_snapshot->caller->name,
&oh);
ast_variables_destroy(oh.vars);
@ -877,7 +877,7 @@ static void park_announce_update_cb(void *data, struct stasis_subscription *sub,
return;
}
if (strcmp(payload->parkee->uniqueid, pa_data->parkee_uuid)) {
if (strcmp(payload->parkee->base->uniqueid, pa_data->parkee_uuid)) {
/* We are only concerned with the parkee we are subscribed for. */
return;
}

@ -111,7 +111,7 @@ static void parker_parked_call_message_response(struct ast_parked_call_payload *
RAII_VAR(struct ast_channel *, parker, NULL, ast_channel_cleanup);
RAII_VAR(struct ast_bridge_channel *, bridge_channel, NULL, ao2_cleanup);
if (strcmp(parkee_to_act_on, parkee_snapshot->uniqueid)) {
if (strcmp(parkee_to_act_on, parkee_snapshot->base->uniqueid)) {
return;
}

@ -110,7 +110,7 @@ static void updates(void *data, struct stasis_subscription *sub,
int64_t age;
age = ast_tvdiff_ms(*stasis_message_timestamp(message),
update->new_snapshot->creationtime);
update->new_snapshot->base->creationtime);
ast_statsd_log("channels.calltime", AST_STATSD_TIMER, age);
/* And decrement the channel count */

@ -1351,7 +1351,7 @@ static int active_channels_to_str_cb(void *object, void *arg, int flags)
{
const struct ast_channel_snapshot *snapshot = object;
struct ast_str **buf = arg;
ast_str_append(buf, 0, "%s,", snapshot->name);
ast_str_append(buf, 0, "%s,", snapshot->base->name);
return 0;
}

@ -179,7 +179,7 @@ static void refer_progress_bridge(void *data, struct stasis_subscription *sub,
}
enter_blob = stasis_message_data(message);
if (strcmp(enter_blob->channel->uniqueid, progress->transferee)) {
if (strcmp(enter_blob->channel->base->uniqueid, progress->transferee)) {
/* Don't care */
return;
}

@ -1019,7 +1019,7 @@ static int send_start_msg_snapshots(struct ast_channel *chan, struct stasis_app
}
if (replace_channel_snapshot) {
app_unsubscribe_channel_id(app, replace_channel_snapshot->uniqueid);
app_unsubscribe_channel_id(app, replace_channel_snapshot->base->uniqueid);
}
stasis_publish(ast_app_get_topic(app), msg);
ao2_ref(msg, -1);
@ -2051,7 +2051,7 @@ static int unload_module(void)
/* \brief Sanitization callback for channel snapshots */
static int channel_snapshot_sanitizer(const struct ast_channel_snapshot *snapshot)
{
if (!snapshot || !(snapshot->tech_properties & AST_CHAN_TP_INTERNAL)) {
if (!snapshot || !(snapshot->base->tech_properties & AST_CHAN_TP_INTERNAL)) {
return 0;
}
return 1;

@ -315,7 +315,7 @@ static void call_forwarded_handler(struct stasis_app *app, struct stasis_message
return;
}
chan = ast_channel_get_by_name(snapshot->uniqueid);
chan = ast_channel_get_by_name(snapshot->base->uniqueid);
if (!chan) {
return;
}
@ -391,8 +391,8 @@ static struct ast_json *channel_destroyed_event(
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
"type", "ChannelDestroyed",
"timestamp", ast_json_timeval(*tv, NULL),
"cause", snapshot->hangupcause,
"cause_txt", ast_cause2str(snapshot->hangupcause),
"cause", snapshot->hangup->cause,
"cause_txt", ast_cause2str(snapshot->hangup->cause),
"channel", json_channel);
}
@ -436,7 +436,7 @@ static struct ast_json *channel_dialplan(
}
/* Empty application is not valid for a Newexten event */
if (ast_strlen_zero(new_snapshot->appl)) {
if (ast_strlen_zero(new_snapshot->dialplan->appl)) {
return NULL;
}
@ -452,8 +452,8 @@ static struct ast_json *channel_dialplan(
return ast_json_pack("{s: s, s: o, s: s, s: s, s: o}",
"type", "ChannelDialplan",
"timestamp", ast_json_timeval(*tv, NULL),
"dialplan_app", new_snapshot->appl,
"dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->data),
"dialplan_app", new_snapshot->dialplan->appl,
"dialplan_app_data", AST_JSON_UTF8_VALIDATE(new_snapshot->dialplan->data),
"channel", json_channel);
}
@ -481,9 +481,9 @@ static struct ast_json *channel_callerid(
return ast_json_pack("{s: s, s: o, s: i, s: s, s: o}",
"type", "ChannelCallerId",
"timestamp", ast_json_timeval(*tv, NULL),
"caller_presentation", new_snapshot->caller_pres,
"caller_presentation", new_snapshot->caller->pres,
"caller_presentation_txt", ast_describe_caller_presentation(
new_snapshot->caller_pres),
new_snapshot->caller->pres),
"channel", json_channel);
}
@ -541,7 +541,7 @@ static void sub_channel_update_handler(void *data,
}
if (ast_test_flag(&update->new_snapshot->flags, AST_FLAG_DEAD)) {
unsubscribe(app, "channel", update->new_snapshot->uniqueid, 1);
unsubscribe(app, "channel", update->new_snapshot->base->uniqueid, 1);
}
}
@ -768,7 +768,7 @@ static void bridge_blind_transfer_handler(void *data, struct stasis_subscription
struct ast_blind_transfer_message *transfer_msg = stasis_message_data(message);
struct ast_bridge_snapshot *bridge = transfer_msg->bridge;
if (bridge_app_subscribed(app, transfer_msg->transferer->uniqueid) ||
if (bridge_app_subscribed(app, transfer_msg->transferer->base->uniqueid) ||
(bridge && bridge_app_subscribed_involved(app, bridge))) {
stasis_publish(app->topic, message);
}
@ -781,9 +781,9 @@ static void bridge_attended_transfer_handler(void *data, struct stasis_subscript
struct ast_attended_transfer_message *transfer_msg = stasis_message_data(message);
int subscribed = 0;
subscribed = bridge_app_subscribed(app, transfer_msg->to_transferee.channel_snapshot->uniqueid);
subscribed = bridge_app_subscribed(app, transfer_msg->to_transferee.channel_snapshot->base->uniqueid);
if (!subscribed) {
subscribed = bridge_app_subscribed(app, transfer_msg->to_transfer_target.channel_snapshot->uniqueid);
subscribed = bridge_app_subscribed(app, transfer_msg->to_transfer_target.channel_snapshot->base->uniqueid);
}
if (!subscribed && transfer_msg->to_transferee.bridge_snapshot) {
subscribed = bridge_app_subscribed_involved(app, transfer_msg->to_transferee.bridge_snapshot);
@ -798,16 +798,16 @@ static void bridge_attended_transfer_handler(void *data, struct stasis_subscript
subscribed = bridge_app_subscribed(app, transfer_msg->dest.bridge);
break;
case AST_ATTENDED_TRANSFER_DEST_LINK:
subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[0]->uniqueid);
subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[0]->base->uniqueid);
if (!subscribed) {
subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[1]->uniqueid);
subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[1]->base->uniqueid);
}
break;
break;
case AST_ATTENDED_TRANSFER_DEST_THREEWAY:
subscribed = bridge_app_subscribed_involved(app, transfer_msg->dest.threeway.bridge_snapshot);
if (!subscribed) {
subscribed = bridge_app_subscribed(app, transfer_msg->dest.threeway.channel_snapshot->uniqueid);
subscribed = bridge_app_subscribed(app, transfer_msg->dest.threeway.channel_snapshot->base->uniqueid);
}
break;
default:

@ -329,7 +329,7 @@ static struct ast_str *__test_cel_generate_peer_str(struct ast_channel_snapshot
ao2_cleanup);
/* Don't add the channel for which this message is being generated */
if (!strcmp(current_chan, chan->uniqueid)) {
if (!strcmp(current_chan, chan->base->uniqueid)) {
continue;
}
@ -338,7 +338,7 @@ static struct ast_str *__test_cel_generate_peer_str(struct ast_channel_snapshot
continue;
}
ast_str_append(&peer_str, 0, "%s,", current_snapshot->name);
ast_str_append(&peer_str, 0, "%s,", current_snapshot->base->name);
}
ao2_iterator_destroy(&i);
@ -1668,8 +1668,8 @@ AST_TEST_DEFINE(test_cel_local_optimize)
stasis_publish(ast_channel_topic(chan_alice), local_opt_begin);
stasis_publish(ast_channel_topic(chan_alice), local_opt_end);
extra = ast_json_pack("{s: s, s: s}", "local_two", bob_snapshot->name,
"local_two_uniqueid", bob_snapshot->uniqueid);
extra = ast_json_pack("{s: s, s: s}", "local_two", bob_snapshot->base->name,
"local_two_uniqueid", bob_snapshot->base->uniqueid);
ast_test_validate(test, extra != NULL);
APPEND_EVENT_SNAPSHOT(alice_snapshot, AST_CEL_LOCAL_OPTIMIZE, NULL, extra, NULL);

@ -220,12 +220,12 @@ AST_TEST_DEFINE(multi_channel_blob_snapshots)
/* Test for single match */
snapshot = ast_multi_channel_blob_get_channel(blob, "Caller");
ast_test_validate(test, NULL != snapshot);
ast_test_validate(test, 0 == strcmp("TEST/Alice", snapshot->name));
ast_test_validate(test, 0 == strcmp("TEST/Alice", snapshot->base->name));
/* Test for single match, multiple possibilities */
snapshot = ast_multi_channel_blob_get_channel(blob, "Peer");
ast_test_validate(test, NULL != snapshot);
ast_test_validate(test, 0 != strcmp("TEST/Alice", snapshot->name));
ast_test_validate(test, 0 != strcmp("TEST/Alice", snapshot->base->name));
/* Multi-match */
matches = ast_multi_channel_blob_get_channels(blob, "Peer");

Loading…
Cancel
Save