summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/bridge.c18
-rw-r--r--main/bridge_basic.c8
-rw-r--r--main/bridge_channel.c15
-rw-r--r--main/ccss.c2
-rw-r--r--main/cel.c3
-rw-r--r--main/channel.c86
-rw-r--r--main/channel_internal_api.c108
-rw-r--r--main/core_local.c6
-rw-r--r--main/core_unreal.c24
-rw-r--r--main/dial.c32
-rw-r--r--main/manager.c28
-rw-r--r--main/message.c2
-rw-r--r--main/pbx.c14
13 files changed, 214 insertions, 132 deletions
diff --git a/main/bridge.c b/main/bridge.c
index 8acf260d1..1baf01cfc 100644
--- a/main/bridge.c
+++ b/main/bridge.c
@@ -732,7 +732,7 @@ struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_
return bridge;
}
-struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name)
+struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
{
char uuid_hold[AST_UUID_STR_LEN];
@@ -740,8 +740,12 @@ struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabiliti
return NULL;
}
- ast_uuid_generate_str(uuid_hold, AST_UUID_STR_LEN);
- ast_string_field_set(self, uniqueid, uuid_hold);
+ if (!ast_strlen_zero(id)) {
+ ast_string_field_set(self, uniqueid, id);
+ } else {
+ ast_uuid_generate_str(uuid_hold, AST_UUID_STR_LEN);
+ ast_string_field_set(self, uniqueid, uuid_hold);
+ }
ast_string_field_set(self, creator, creator);
if (!ast_strlen_zero(creator)) {
ast_string_field_set(self, name, name);
@@ -901,12 +905,12 @@ struct ast_bridge_methods ast_bridge_base_v_table = {
.get_merge_priority = bridge_base_get_merge_priority,
};
-struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name)
+struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name, const char *id)
{
void *bridge;
bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_base_v_table);
- bridge = bridge_base_init(bridge, capabilities, flags, creator, name);
+ bridge = bridge_base_init(bridge, capabilities, flags, creator, name, id);
bridge = bridge_register(bridge);
return bridge;
}
@@ -3716,7 +3720,7 @@ static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transf
int cause;
snprintf(chan_name, sizeof(chan_name), "%s@%s", exten, context);
- local = ast_request("Local", ast_channel_nativeformats(transferer), transferer,
+ local = ast_request("Local", ast_channel_nativeformats(transferer), NULL, transferer,
chan_name, &cause);
if (!local) {
return AST_BRIDGE_TRANSFER_FAIL;
@@ -3879,7 +3883,7 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha
int res;
const char *app = NULL;
- local_chan = ast_request("Local", ast_channel_nativeformats(chan1), chan1,
+ local_chan = ast_request("Local", ast_channel_nativeformats(chan1), NULL, chan1,
dest, &cause);
if (!local_chan) {
diff --git a/main/bridge_basic.c b/main/bridge_basic.c
index 317c574a6..4a68f4904 100644
--- a/main/bridge_basic.c
+++ b/main/bridge_basic.c
@@ -2237,7 +2237,7 @@ static int recalling_enter(struct attended_transfer_properties *props)
return -1;
}
- if (ast_dial_append(props->dial, props->transferer_type, props->transferer_addr)) {
+ if (ast_dial_append(props->dial, props->transferer_type, props->transferer_addr, NULL)) {
return -1;
}
@@ -2360,7 +2360,7 @@ static int retransfer_enter(struct attended_transfer_properties *props)
ast_format_cap_add(cap, ast_format_set(&fmt, AST_FORMAT_SLINEAR, 0));
/* Get a channel that is the destination we wish to call */
- props->recall_target = ast_request("Local", cap, NULL, destination, &cause);
+ props->recall_target = ast_request("Local", cap, NULL, NULL, destination, &cause);
if (!props->recall_target) {
ast_log(LOG_ERROR, "Unable to request outbound channel for recall target\n");
return -1;
@@ -2920,7 +2920,7 @@ static struct ast_channel *dial_transfer(struct ast_channel *caller, const char
int cause;
/* Now we request a local channel to prepare to call the destination */
- chan = ast_request("Local", ast_channel_nativeformats(caller), caller, destination,
+ chan = ast_request("Local", ast_channel_nativeformats(caller), NULL, caller, destination,
&cause);
if (!chan) {
return NULL;
@@ -3239,7 +3239,7 @@ struct ast_bridge *ast_bridge_basic_new(void)
bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table);
bridge = bridge_base_init(bridge,
AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX
- | AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS, NULL, NULL);
+ | AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS, NULL, NULL, NULL);
bridge = bridge_basic_personality_alloc(bridge);
bridge = bridge_register(bridge);
return bridge;
diff --git a/main/bridge_channel.c b/main/bridge_channel.c
index ae33cd056..06da4eeed 100644
--- a/main/bridge_channel.c
+++ b/main/bridge_channel.c
@@ -222,28 +222,27 @@ void ast_bridge_channel_update_linkedids(struct ast_bridge_channel *bridge_chann
{
struct ast_bridge_channel *other = NULL;
struct ast_bridge *bridge = bridge_channel->bridge;
- const char *oldest_linkedid = ast_channel_linkedid(bridge_channel->chan);
+ struct ast_channel *oldest_linkedid_chan = bridge_channel->chan;
AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
if (other == swap) {
continue;
}
- oldest_linkedid = ast_channel_oldest_linkedid(oldest_linkedid, ast_channel_linkedid(other->chan));
- }
-
- if (ast_strlen_zero(oldest_linkedid)) {
- return;
+ oldest_linkedid_chan = ast_channel_internal_oldest_linkedid(
+ oldest_linkedid_chan, other->chan);
}
ast_channel_lock(bridge_channel->chan);
- ast_channel_linkedid_set(bridge_channel->chan, oldest_linkedid);
+ ast_channel_internal_copy_linkedid(bridge_channel->chan,
+ oldest_linkedid_chan);
ast_channel_unlock(bridge_channel->chan);
AST_LIST_TRAVERSE(&bridge->channels, other, entry) {
if (other == swap) {
continue;
}
ast_channel_lock(other->chan);
- ast_channel_linkedid_set(other->chan, oldest_linkedid);
+ ast_channel_internal_copy_linkedid(other->chan,
+ oldest_linkedid_chan);
ast_channel_unlock(other->chan);
}
}
diff --git a/main/ccss.c b/main/ccss.c
index fadc6e36f..625147382 100644
--- a/main/ccss.c
+++ b/main/ccss.c
@@ -2827,7 +2827,7 @@ static void *generic_recall(void *data)
}
ast_format_cap_add(tmp_cap, ast_format_set(&tmp_fmt, AST_FORMAT_SLINEAR, 0));
- if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
+ if (!(chan = ast_request_and_dial(tech, tmp_cap, NULL, NULL, target, recall_timer, &reason, generic_pvt->cid_num, generic_pvt->cid_name))) {
/* Hmm, no channel. Sucks for you, bud.
*/
ast_log_dynamic_level(cc_logger_level, "Core %d: Failed to call back %s for reason %d\n",
diff --git a/main/cel.c b/main/cel.c
index 1cd5099a0..d1602f8ea 100644
--- a/main/cel.c
+++ b/main/cel.c
@@ -829,8 +829,7 @@ struct ast_channel *ast_cel_fabricate_channel_from_event(const struct ast_event
ast_channel_exten_set(tchan, record.extension);
ast_channel_context_set(tchan, record.context);
ast_channel_name_set(tchan, record.channel_name);
- ast_channel_uniqueid_set(tchan, record.unique_id);
- ast_channel_linkedid_set(tchan, record.linked_id);
+ ast_channel_internal_set_fake_ids(tchan, record.unique_id, record.linked_id);
ast_channel_accountcode_set(tchan, record.account_code);
ast_channel_peeraccount_set(tchan, record.peer_account);
ast_channel_userfield_set(tchan, record.user_field);
diff --git a/main/channel.c b/main/channel.c
index da4f794df..0252bd8b7 100644
--- a/main/channel.c
+++ b/main/channel.c
@@ -857,8 +857,8 @@ static void ast_dummy_channel_destructor(void *obj);
/*! \brief Create a new channel structure */
static struct ast_channel * attribute_malloc __attribute__((format(printf, 13, 0)))
__ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char *cid_name,
- const char *acctcode, const char *exten, const char *context,
- const char *linkedid, enum ama_flags amaflag, const char *file, int line,
+ const char *acctcode, const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
+ const struct ast_channel *requestor, enum ama_flags amaflag, const char *file, int line,
const char *function, const char *name_fmt, va_list ap)
{
struct ast_channel *tmp;
@@ -876,7 +876,7 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
return NULL;
}
- if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, linkedid))) {
+ if (!(tmp = ast_channel_internal_alloc(ast_channel_destructor, assignedids, requestor))) {
/* Channel structure allocation failure. */
return NULL;
}
@@ -1039,8 +1039,8 @@ __ast_channel_alloc_ap(int needqueue, int state, const char *cid_num, const char
struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *cid_num,
const char *cid_name, const char *acctcode,
- const char *exten, const char *context,
- const char *linkedid, enum ama_flags amaflag,
+ const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
+ const struct ast_channel *requestor, enum ama_flags amaflag,
const char *file, int line, const char *function,
const char *name_fmt, ...)
{
@@ -1049,7 +1049,7 @@ struct ast_channel *__ast_channel_alloc(int needqueue, int state, const char *ci
va_start(ap, name_fmt);
result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context,
- linkedid, amaflag, file, line, function, name_fmt, ap);
+ assignedids, requestor, amaflag, file, line, function, name_fmt, ap);
va_end(ap);
return result;
@@ -1066,7 +1066,7 @@ struct ast_channel *ast_dummy_channel_alloc(void)
struct ast_channel *tmp;
struct varshead *headp;
- if (!(tmp = ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL))) {
+ if (!(tmp = ast_channel_internal_alloc(ast_dummy_channel_destructor, NULL, NULL))) {
/* Dummy channel structure allocation failure. */
return NULL;
}
@@ -5595,7 +5595,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
data = tmpchan;
type = "Local";
}
- if (!(new_chan = ast_request(type, cap, orig, data, &cause))) {
+ if (!(new_chan = ast_request(type, cap, NULL, orig, data, &cause))) {
ast_log(LOG_NOTICE, "Unable to create channel for call forward to '%s/%s' (cause = %d)\n", type, data, cause);
handle_cause(cause, outstate);
ast_hangup(orig);
@@ -5645,7 +5645,7 @@ struct ast_channel *ast_call_forward(struct ast_channel *caller, struct ast_chan
return new_chan;
}
-struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *addr, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
+struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int timeout, int *outstate, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
{
int dummy_outstate;
int cause = 0;
@@ -5659,7 +5659,7 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
else
outstate = &dummy_outstate; /* make outstate always a valid pointer */
- chan = ast_request(type, cap, requestor, addr, &cause);
+ chan = ast_request(type, cap, assignedids, requestor, addr, &cause);
if (!chan) {
ast_log(LOG_NOTICE, "Unable to request channel %s/%s\n", type, addr);
handle_cause(cause, outstate);
@@ -5831,9 +5831,9 @@ struct ast_channel *__ast_request_and_dial(const char *type, struct ast_format_c
return chan;
}
-struct ast_channel *ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *addr, int timeout, int *outstate, const char *cidnum, const char *cidname)
+struct ast_channel *ast_request_and_dial(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int timeout, int *outstate, const char *cidnum, const char *cidname)
{
- return __ast_request_and_dial(type, cap, requestor, addr, timeout, outstate, cidnum, cidname, NULL);
+ return __ast_request_and_dial(type, cap, assignedids, requestor, addr, timeout, outstate, cidnum, cidname, NULL);
}
static int set_security_requirements(const struct ast_channel *requestor, struct ast_channel *out)
@@ -5876,7 +5876,7 @@ static int set_security_requirements(const struct ast_channel *requestor, struct
return 0;
}
-struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_channel *requestor, const char *addr, int *cause)
+struct ast_channel *ast_request(const char *type, struct ast_format_cap *request_cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *addr, int *cause)
{
struct chanlist *chan;
struct ast_channel *c;
@@ -5933,7 +5933,7 @@ struct ast_channel *ast_request(const char *type, struct ast_format_cap *request
ast_format_cap_remove_bytype(joint_cap, AST_FORMAT_TYPE_AUDIO);
ast_format_cap_add(joint_cap, &best_audio_fmt);
- if (!(c = chan->tech->requester(type, joint_cap, requestor, addr, cause))) {
+ if (!(c = chan->tech->requester(type, joint_cap, assignedids, requestor, addr, cause))) {
ast_format_cap_destroy(joint_cap);
return NULL;
}
@@ -6330,55 +6330,6 @@ static void clone_variables(struct ast_channel *original, struct ast_channel *cl
}
}
-const char *ast_channel_oldest_linkedid(const char *a, const char *b)
-{
- const char *satime, *saseq;
- const char *sbtime, *sbseq;
- const char *dash;
- unsigned int atime, aseq, btime, bseq;
-
- if (ast_strlen_zero(a)) {
- return b;
- }
-
- if (ast_strlen_zero(b)) {
- return a;
- }
-
- satime = a;
- sbtime = b;
-
- /* jump over the system name */
- if ((dash = strrchr(satime, '-'))) {
- satime = dash+1;
- }
- if ((dash = strrchr(sbtime, '-'))) {
- sbtime = dash+1;
- }
-
- /* the sequence comes after the '.' */
- saseq = strchr(satime, '.');
- sbseq = strchr(sbtime, '.');
- if (!saseq || !sbseq) {
- return NULL;
- }
- saseq++;
- sbseq++;
-
- /* convert it all to integers */
- atime = atoi(satime); /* note that atoi is ignoring the '.' after the time string */
- btime = atoi(sbtime); /* note that atoi is ignoring the '.' after the time string */
- aseq = atoi(saseq);
- bseq = atoi(sbseq);
-
- /* and finally compare */
- if (atime == btime) {
- return (aseq < bseq) ? a : b;
- }
- else {
- return (atime < btime) ? a : b;
- }
-}
void ast_channel_name_to_dial_string(char *channel_name)
{
@@ -6422,7 +6373,6 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
struct ast_format wformat;
struct ast_format tmp_format;
char tmp_name[AST_CHANNEL_NAME];
- const char *tmp_id;
char clone_sending_dtmf_digit;
struct timeval clone_sending_dtmf_tv;
@@ -6488,9 +6438,7 @@ static void channel_do_masquerade(struct ast_channel *original, struct ast_chann
/* Swap uniqueid's of the channels. This needs to happen before channel renames,
* so rename events get the proper id's.
*/
- tmp_id = ast_strdupa(ast_channel_uniqueid(clonechan));
- ast_channel_uniqueid_set(clonechan, ast_channel_uniqueid(original));
- ast_channel_uniqueid_set(original, tmp_id);
+ ast_channel_internal_swap_uniqueid_and_linkedid(clonechan, original);
/* Swap channel names. This uses ast_channel_name_set directly, so we
* don't get any spurious rename events.
@@ -10203,7 +10151,6 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
char *accountcode;
char *exten;
char *context;
- char *linkedid;
char *name;
int amaflags;
struct ast_format readformat;
@@ -10214,7 +10161,6 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
my_vars.accountcode = ast_strdupa(ast_channel_accountcode(yankee));
my_vars.exten = ast_strdupa(ast_channel_exten(yankee));
my_vars.context = ast_strdupa(ast_channel_context(yankee));
- my_vars.linkedid = ast_strdupa(ast_channel_linkedid(yankee));
my_vars.name = ast_strdupa(ast_channel_name(yankee));
my_vars.amaflags = ast_channel_amaflags(yankee);
ast_format_copy(&my_vars.writeformat, ast_channel_writeformat(yankee));
@@ -10224,7 +10170,7 @@ struct ast_channel *ast_channel_yank(struct ast_channel *yankee)
/* Do not hold any channel locks while calling channel_alloc() since the function
* locks the channel container when linking the new channel in. */
if (!(yanked_chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, my_vars.accountcode,
- my_vars.exten, my_vars.context, my_vars.linkedid, my_vars.amaflags,
+ my_vars.exten, my_vars.context, NULL, yankee, my_vars.amaflags,
"Surrogate/%s", my_vars.name))) {
return NULL;
}
diff --git a/main/channel_internal_api.c b/main/channel_internal_api.c
index 51d83e12c..d444d7fba 100644
--- a/main/channel_internal_api.c
+++ b/main/channel_internal_api.c
@@ -51,6 +51,16 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/test.h"
/*!
+ * \brief Channel UniqueId structure
+ * \note channel creation time used for determining LinkedId Propagation
+ */
+struct ast_channel_id {
+ time_t creation_time; /*!< Creation time */
+ int creation_unique; /*!< sub-second unique value */
+ char unique_id[AST_MAX_UNIQUEID]; /*< Unique Identifier */
+};
+
+/*!
* \brief Main Channel structure associated with a channel.
*
* \note When adding fields to this structure, it is important to add the field
@@ -101,13 +111,14 @@ struct ast_channel {
AST_STRING_FIELD(peeraccount); /*!< Peer account code for billing */
AST_STRING_FIELD(userfield); /*!< Userfield for CEL billing */
AST_STRING_FIELD(call_forward); /*!< Where to forward to if asked to dial on this interface */
- AST_STRING_FIELD(uniqueid); /*!< Unique Channel Identifier */
- AST_STRING_FIELD(linkedid); /*!< Linked Channel Identifier -- gets propagated by linkage */
AST_STRING_FIELD(parkinglot); /*! Default parking lot, if empty, default parking lot */
AST_STRING_FIELD(hangupsource); /*! Who is responsible for hanging up this channel */
AST_STRING_FIELD(dialcontext); /*!< Dial: Extension context that we were called from */
);
+ struct ast_channel_id uniqueid; /*!< Unique Channel Identifier - can be specified on creation */
+ struct ast_channel_id linkedid; /*!< Linked Channel Identifier - oldest propagated when bridged */
+
struct timeval whentohangup; /*!< Non-zero, set to actual time when channel is to be hung up */
pthread_t blocker; /*!< If anyone is blocking, this is them */
@@ -239,8 +250,6 @@ AST_DATA_STRUCTURE(ast_callerid, DATA_EXPORT_CALLERID);
MEMBER(ast_channel, peeraccount, AST_DATA_STRING) \
MEMBER(ast_channel, userfield, AST_DATA_STRING) \
MEMBER(ast_channel, call_forward, AST_DATA_STRING) \
- MEMBER(ast_channel, uniqueid, AST_DATA_STRING) \
- MEMBER(ast_channel, linkedid, AST_DATA_STRING) \
MEMBER(ast_channel, parkinglot, AST_DATA_STRING) \
MEMBER(ast_channel, hangupsource, AST_DATA_STRING) \
MEMBER(ast_channel, dialcontext, AST_DATA_STRING) \
@@ -314,6 +323,9 @@ int ast_channel_data_add_structure(struct ast_data *tree,
}
}
+ ast_data_add_str(tree, "uniqueid", ast_channel_uniqueid(chan));
+ ast_data_add_str(tree, "linkedid", ast_channel_linkedid(chan));
+
ast_data_add_codec(tree, "oldwriteformat", ast_channel_oldwriteformat(chan));
ast_data_add_codec(tree, "readformat", ast_channel_readformat(chan));
ast_data_add_codec(tree, "writeformat", ast_channel_writeformat(chan));
@@ -450,8 +462,6 @@ 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(uniqueid, 0, 1);
-DEFINE_STRINGFIELD_SETTERS_FOR(linkedid, 1, 1);
DEFINE_STRINGFIELD_SETTERS_FOR(parkinglot, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(hangupsource, 0, 0);
DEFINE_STRINGFIELD_SETTERS_FOR(dialcontext, 0, 0);
@@ -469,12 +479,22 @@ DEFINE_STRINGFIELD_GETTER_FOR(accountcode);
DEFINE_STRINGFIELD_GETTER_FOR(peeraccount);
DEFINE_STRINGFIELD_GETTER_FOR(userfield);
DEFINE_STRINGFIELD_GETTER_FOR(call_forward);
-DEFINE_STRINGFIELD_GETTER_FOR(uniqueid);
-DEFINE_STRINGFIELD_GETTER_FOR(linkedid);
DEFINE_STRINGFIELD_GETTER_FOR(parkinglot);
DEFINE_STRINGFIELD_GETTER_FOR(hangupsource);
DEFINE_STRINGFIELD_GETTER_FOR(dialcontext);
+const char *ast_channel_uniqueid(const struct ast_channel *chan)
+{
+ ast_assert(chan->uniqueid.unique_id[0] != '\0');
+ return chan->uniqueid.unique_id;
+}
+
+const char *ast_channel_linkedid(const struct ast_channel *chan)
+{
+ ast_assert(chan->linkedid.unique_id[0] != '\0');
+ return chan->linkedid.unique_id;
+}
+
const char *ast_channel_appl(const struct ast_channel *chan)
{
return chan->appl;
@@ -1379,7 +1399,7 @@ static int pvt_cause_cmp_fn(void *obj, void *vstr, int flags)
#define DIALED_CAUSES_BUCKETS 37
-struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const char *linkedid, const char *file, int line, const char *function)
+struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj), const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *file, int line, const char *function)
{
struct ast_channel *tmp;
#if defined(REF_DEBUG)
@@ -1400,23 +1420,75 @@ struct ast_channel *__ast_channel_internal_alloc(void (*destructor)(void *obj),
return ast_channel_unref(tmp);
}
- if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
- ast_channel_uniqueid_build(tmp, "%li.%d", (long)time(NULL),
- ast_atomic_fetchadd_int(&uniqueint, 1));
+ /* set the creation time in the uniqueid */
+ tmp->uniqueid.creation_time = time(NULL);
+ tmp->uniqueid.creation_unique = ast_atomic_fetchadd_int(&uniqueint, 1);
+
+ /* use provided id or default to historical {system-}time.# format */
+ if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
+ ast_copy_string(tmp->uniqueid.unique_id, assignedids->uniqueid, sizeof(tmp->uniqueid.unique_id));
+ } else if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) {
+ snprintf(tmp->uniqueid.unique_id, sizeof(tmp->uniqueid.unique_id), "%li.%d",
+ (long)(tmp->uniqueid.creation_time),
+ tmp->uniqueid.creation_unique);
} else {
- ast_channel_uniqueid_build(tmp, "%s-%li.%d", ast_config_AST_SYSTEM_NAME,
- (long)time(NULL), ast_atomic_fetchadd_int(&uniqueint, 1));
+ snprintf(tmp->uniqueid.unique_id, sizeof(tmp->uniqueid.unique_id), "%s-%li.%d",
+ ast_config_AST_SYSTEM_NAME,
+ (long)(tmp->uniqueid.creation_time),
+ tmp->uniqueid.creation_unique);
}
- if (!ast_strlen_zero(linkedid)) {
- ast_string_field_set(tmp, linkedid, linkedid);
+ /* copy linked id from parent channel if known */
+ if (requestor) {
+ tmp->linkedid = requestor->linkedid;
} else {
- ast_string_field_set(tmp, linkedid, tmp->uniqueid);
+ tmp->linkedid = tmp->uniqueid;
}
return tmp;
}
+struct ast_channel *ast_channel_internal_oldest_linkedid(struct ast_channel *a, struct ast_channel *b)
+{
+ ast_assert(a->linkedid.creation_time != 0);
+ ast_assert(b->linkedid.creation_time != 0);
+
+ if (a->linkedid.creation_time < b->linkedid.creation_time) {
+ return a;
+ }
+ if (b->linkedid.creation_time < a->linkedid.creation_time) {
+ return b;
+ }
+ if (a->linkedid.creation_unique < b->linkedid.creation_unique) {
+ return a;
+ }
+ return b;
+}
+
+void ast_channel_internal_copy_linkedid(struct ast_channel *dest, struct ast_channel *source)
+{
+ dest->linkedid = source->linkedid;
+}
+
+void ast_channel_internal_swap_uniqueid_and_linkedid(struct ast_channel *a, struct ast_channel *b)
+{
+ struct ast_channel_id temp;
+
+ temp = a->uniqueid;
+ a->uniqueid = b->uniqueid;
+ b->uniqueid = temp;
+
+ temp = a->linkedid;
+ a->linkedid = b->linkedid;
+ b->linkedid = temp;
+}
+
+void ast_channel_internal_set_fake_ids(struct ast_channel *chan, const char *uniqueid, const char *linkedid)
+{
+ strncpy(chan->uniqueid.unique_id, uniqueid, sizeof(chan->uniqueid.unique_id));
+ strncpy(chan->linkedid.unique_id, linkedid, sizeof(chan->linkedid.unique_id));
+}
+
void ast_channel_internal_cleanup(struct ast_channel *chan)
{
if (chan->dialed_causes) {
@@ -1480,7 +1552,7 @@ int ast_channel_forward_endpoint(struct ast_channel *chan,
int ast_channel_internal_setup_topics(struct ast_channel *chan)
{
- const char *topic_name = chan->uniqueid;
+ const char *topic_name = chan->uniqueid.unique_id;
ast_assert(chan->topics == NULL);
if (ast_strlen_zero(topic_name)) {
diff --git a/main/core_local.c b/main/core_local.c
index edf28399b..98db5e575 100644
--- a/main/core_local.c
+++ b/main/core_local.c
@@ -137,7 +137,7 @@ static const char tdesc[] = "Local Proxy Channel Driver";
static struct ao2_container *locals;
-static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
+static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause);
static int local_call(struct ast_channel *ast, const char *dest, int timeout);
static int local_hangup(struct ast_channel *ast);
static int local_devicestate(const char *data);
@@ -869,7 +869,7 @@ static struct local_pvt *local_alloc(const char *data, struct ast_format_cap *ca
}
/*! \brief Part of PBX interface */
-static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
+static struct ast_channel *local_request(const char *type, struct ast_format_cap *cap, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor, const char *data, int *cause)
{
struct local_pvt *p;
struct ast_channel *chan;
@@ -882,7 +882,7 @@ static struct ast_channel *local_request(const char *type, struct ast_format_cap
}
callid = ast_read_threadstorage_callid();
chan = ast_unreal_new_channels(&p->base, &local_tech, AST_STATE_DOWN, AST_STATE_RING,
- p->exten, p->context, requestor, callid);
+ p->exten, p->context, assignedids, requestor, callid);
if (chan) {
ao2_link(locals, p);
}
diff --git a/main/core_unreal.c b/main/core_unreal.c
index 7ab7da765..bc081f5f4 100644
--- a/main/core_unreal.c
+++ b/main/core_unreal.c
@@ -888,15 +888,29 @@ struct ast_unreal_pvt *ast_unreal_alloc(size_t size, ao2_destructor_fn destructo
struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
const struct ast_channel_tech *tech, int semi1_state, int semi2_state,
- const char *exten, const char *context, const struct ast_channel *requestor,
- struct ast_callid *callid)
+ const char *exten, const char *context, const struct ast_assigned_ids *assignedids,
+ const struct ast_channel *requestor, struct ast_callid *callid)
{
struct ast_channel *owner;
struct ast_channel *chan;
- const char *linkedid = requestor ? ast_channel_linkedid(requestor) : NULL;
struct ast_format fmt;
+ struct ast_assigned_ids id1 = {NULL, NULL};
+ struct ast_assigned_ids id2 = {NULL, NULL};
int generated_seqno = ast_atomic_fetchadd_int((int *) &name_sequence, +1);
+ /* set unique ids for the two channels */
+ if (assignedids && !ast_strlen_zero(assignedids->uniqueid)) {
+ id1.uniqueid = assignedids->uniqueid;
+ id2.uniqueid = assignedids->uniqueid2;
+ }
+
+ /* if id1 given but not id2, use default of id1;2 */
+ if (id1.uniqueid && ast_strlen_zero(id2.uniqueid)) {
+ char *uniqueid2;
+ ast_asprintf(&uniqueid2, "%s;2", id1.uniqueid);
+ id2.uniqueid = uniqueid2;
+ }
+
/*
* Allocate two new Asterisk channels
*
@@ -905,7 +919,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
* isn't set, then each channel will generate its own linkedid.
*/
if (!(owner = ast_channel_alloc(1, semi1_state, NULL, NULL, NULL,
- exten, context, linkedid, 0,
+ exten, context, &id1, requestor, 0,
"%s/%s-%08x;1", tech->type, p->name, generated_seqno))) {
ast_log(LOG_WARNING, "Unable to allocate owner channel structure\n");
return NULL;
@@ -944,7 +958,7 @@ struct ast_channel *ast_unreal_new_channels(struct ast_unreal_pvt *p,
ast_channel_unlock(owner);
if (!(chan = ast_channel_alloc(1, semi2_state, NULL, NULL, NULL,
- exten, context, ast_channel_linkedid(owner), 0,
+ exten, context, &id2, owner, 0,
"%s/%s-%08x;2", tech->type, p->name, generated_seqno))) {
ast_log(LOG_WARNING, "Unable to allocate chan channel structure\n");
ao2_ref(p, -1);
diff --git a/main/dial.c b/main/dial.c
index 6ff0e7f7d..246d4f406 100644
--- a/main/dial.c
+++ b/main/dial.c
@@ -69,6 +69,8 @@ struct ast_dial_channel {
void *options[AST_DIAL_OPTION_MAX]; /*!< Channel specific options */
int cause; /*!< Cause code in case of failure */
unsigned int is_running_app:1; /*!< Is this running an application? */
+ char *assignedid1; /*!< UniqueID to assign channel */
+ char *assignedid2; /*!< UniqueID to assign 2nd channel */
struct ast_channel *owner; /*!< Asterisk channel */
AST_LIST_ENTRY(ast_dial_channel) list; /*!< Linked list information */
};
@@ -247,7 +249,7 @@ struct ast_dial *ast_dial_create(void)
* \note Appends a channel to a dialing structure
* \return Returns channel reference number on success, -1 on failure
*/
-int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
+int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device, const struct ast_assigned_ids *assignedids)
{
struct ast_dial_channel *channel = NULL;
@@ -263,6 +265,16 @@ int ast_dial_append(struct ast_dial *dial, const char *tech, const char *device)
channel->tech = ast_strdup(tech);
channel->device = ast_strdup(device);
+ /* Store the assigned id */
+ if (assignedids && !ast_strlen_zero(assignedids->uniqueid))
+ {
+ channel->assignedid1 = ast_strdup(assignedids->uniqueid);
+
+ if (!ast_strlen_zero(assignedids->uniqueid2)) {
+ channel->assignedid2 = ast_strdup(assignedids->uniqueid2);
+ }
+ }
+
/* Grab reference number from dial structure */
channel->num = ast_atomic_fetchadd_int(&dial->num, +1);
@@ -281,6 +293,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
char numsubst[AST_MAX_EXTENSION];
struct ast_format_cap *cap_all_audio = NULL;
struct ast_format_cap *cap_request;
+ struct ast_assigned_ids assignedids = {channel->assignedid1, channel->assignedid2};
/* Copy device string over */
ast_copy_string(numsubst, channel->device, sizeof(numsubst));
@@ -296,7 +309,7 @@ static int begin_dial_prerun(struct ast_dial_channel *channel, struct ast_channe
}
/* If we fail to create our owner channel bail out */
- if (!(channel->owner = ast_request(channel->tech, cap_request, chan, numsubst, &channel->cause))) {
+ if (!(channel->owner = ast_request(channel->tech, cap_request, &assignedids, chan, numsubst, &channel->cause))) {
cap_all_audio = ast_format_cap_destroy(cap_all_audio);
return -1;
}
@@ -461,6 +474,14 @@ static int handle_call_forward(struct ast_dial *dial, struct ast_dial_channel *c
/* Drop old destination information */
ast_free(channel->tech);
ast_free(channel->device);
+ if (channel->assignedid1) {
+ ast_free(channel->assignedid1);
+ channel->assignedid1 = NULL;
+ }
+ if (channel->assignedid2) {
+ ast_free(channel->assignedid2);
+ channel->assignedid2 = NULL;
+ }
/* Update the dial channel with the new destination information */
channel->tech = ast_strdup(tech);
@@ -1045,6 +1066,13 @@ int ast_dial_destroy(struct ast_dial *dial)
/* Free structure */
ast_free(channel->tech);
ast_free(channel->device);
+ if (channel->assignedid1) {
+ ast_free(channel->assignedid1);
+ }
+ if (channel->assignedid2) {
+ ast_free(channel->assignedid2);
+ }
+
AST_LIST_REMOVE_CURRENT(list);
ast_free(channel);
}
diff --git a/main/manager.c b/main/manager.c
index 095293921..18755b507 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -542,6 +542,12 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<parameter name="Codecs">
<para>Comma-separated list of codecs to use for this call.</para>
</parameter>
+ <parameter name="ChannelId">
+ <para>Channel UniqueId to be set on the channel.</para>
+ </parameter>
+ <parameter name="OtherChannelId">
+ <para>Channel UniqueId to be set on the second local channel.</para>
+ </parameter>
</syntax>
<description>
<para>Generates an outgoing call to a
@@ -4381,6 +4387,8 @@ struct fast_originate_helper {
AST_STRING_FIELD(exten);
AST_STRING_FIELD(idtext);
AST_STRING_FIELD(account);
+ AST_STRING_FIELD(channelid);
+ AST_STRING_FIELD(otherchannelid);
);
int priority;
struct ast_variable *vars;
@@ -4408,19 +4416,20 @@ static void *fast_originate(void *data)
int reason = 0;
struct ast_channel *chan = NULL, *chans[1];
char requested_channel[AST_CHANNEL_NAME];
+ struct ast_assigned_ids assignedids = {in->channelid, in->otherchannelid};
if (!ast_strlen_zero(in->app)) {
res = ast_pbx_outgoing_app(in->tech, in->cap, in->data,
in->timeout, in->app, in->appdata, &reason, 1,
S_OR(in->cid_num, NULL),
S_OR(in->cid_name, NULL),
- in->vars, in->account, &chan);
+ in->vars, in->account, &chan, &assignedids);
} else {
res = ast_pbx_outgoing_exten(in->tech, in->cap, in->data,
in->timeout, in->context, in->exten, in->priority, &reason, 1,
S_OR(in->cid_num, NULL),
S_OR(in->cid_name, NULL),
- in->vars, in->account, &chan, in->early_media);
+ in->vars, in->account, &chan, in->early_media, &assignedids);
}
/* Any vars memory was passed to the ast_pbx_outgoing_xxx() calls. */
in->vars = NULL;
@@ -4701,6 +4710,10 @@ static int action_originate(struct mansession *s, const struct message *m)
const char *id = astman_get_header(m, "ActionID");
const char *codecs = astman_get_header(m, "Codecs");
const char *early_media = astman_get_header(m, "Earlymedia");
+ struct ast_assigned_ids assignedids = {
+ astman_get_header(m, "ChannelId"),
+ astman_get_header(m, "OtherChannelId")
+ };
struct ast_variable *vars = NULL;
char *tech, *data;
char *l = NULL, *n = NULL;
@@ -4715,6 +4728,11 @@ static int action_originate(struct mansession *s, const struct message *m)
pthread_t th;
int bridge_early = 0;
+ if (strlen(assignedids.uniqueid) >= AST_MAX_UNIQUEID ||
+ strlen(assignedids.uniqueid2) >= AST_MAX_UNIQUEID) {
+ ast_log(LOG_WARNING, "Uniqueid length exceeds maximum of %d\n", AST_MAX_UNIQUEID);
+ }
+
if (!cap) {
astman_send_error(s, m, "Internal Error. Memory allocation failure.");
return 0;
@@ -4842,6 +4860,8 @@ static int action_originate(struct mansession *s, const struct message *m)
ast_string_field_set(fast, context, context);
ast_string_field_set(fast, exten, exten);
ast_string_field_set(fast, account, account);
+ ast_string_field_set(fast, channelid, assignedids.uniqueid);
+ ast_string_field_set(fast, otherchannelid, assignedids.uniqueid2);
fast->vars = vars;
fast->cap = cap;
cap = NULL; /* transfered originate helper the capabilities structure. It is now responsible for freeing it. */
@@ -4856,11 +4876,11 @@ static int action_originate(struct mansession *s, const struct message *m)
}
}
} else if (!ast_strlen_zero(app)) {
- res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL);
+ res = ast_pbx_outgoing_app(tech, cap, data, to, app, appdata, &reason, 1, l, n, vars, account, NULL, assignedids.uniqueid ? &assignedids : NULL);
/* Any vars memory was passed to ast_pbx_outgoing_app(). */
} else {
if (exten && context && pi) {
- res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early);
+ res = ast_pbx_outgoing_exten(tech, cap, data, to, context, exten, pi, &reason, 1, l, n, vars, account, NULL, bridge_early, assignedids.uniqueid ? &assignedids : NULL);
/* Any vars memory was passed to ast_pbx_outgoing_exten(). */
} else {
astman_send_error(s, m, "Originate with 'Exten' requires 'Context' and 'Priority'");
diff --git a/main/message.c b/main/message.c
index 7690e4a88..70bda4150 100644
--- a/main/message.c
+++ b/main/message.c
@@ -671,7 +671,7 @@ static struct ast_channel *create_msg_q_chan(void)
chan = ast_channel_alloc(1, AST_STATE_UP,
NULL, NULL, NULL,
- NULL, NULL, NULL, 0,
+ NULL, NULL, NULL, NULL, 0,
"%s", "Message/ast_msg_queue");
if (!chan) {
diff --git a/main/pbx.c b/main/pbx.c
index 3662e85bb..b24bcd8c8 100644
--- a/main/pbx.c
+++ b/main/pbx.c
@@ -10213,7 +10213,7 @@ static void pbx_outgoing_state_callback(struct ast_dial *dial)
static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context,
const char *exten, int priority, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num,
- const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media)
+ const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media, const struct ast_assigned_ids *assignedids)
{
RAII_VAR(struct pbx_outgoing *, outgoing, ao2_alloc(sizeof(*outgoing), pbx_outgoing_destroy), ao2_cleanup);
struct ast_channel *dialed;
@@ -10240,7 +10240,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
return -1;
}
- if (ast_dial_append(outgoing->dial, type, addr)) {
+ if (ast_dial_append(outgoing->dial, type, addr, assignedids)) {
return -1;
}
@@ -10355,7 +10355,7 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
if ((synchronous > 1) && ast_dial_state(outgoing->dial) != AST_DIAL_RESULT_ANSWERED &&
ast_strlen_zero(app) && ast_exists_extension(NULL, context, "failed", 1, NULL)) {
- struct ast_channel *failed = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
+ struct ast_channel *failed = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, NULL, 0, "OutgoingSpoolFailed");
if (failed) {
char failed_reason[4] = "";
@@ -10384,20 +10384,20 @@ static int pbx_outgoing_attempt(const char *type, struct ast_format_cap *cap, co
return 0;
}
-int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media)
+int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media, const struct ast_assigned_ids *assignedids)
{
return pbx_outgoing_attempt(type, cap, addr, timeout, context, exten, priority, NULL, NULL, reason, synchronous, cid_num,
- cid_name, vars, account, channel, early_media);
+ cid_name, vars, account, channel, early_media, assignedids);
}
-int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
+int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
{
if (ast_strlen_zero(app)) {
return -1;
}
return pbx_outgoing_attempt(type, cap, addr, timeout, NULL, NULL, 0, app, appdata, reason, synchronous, cid_num,
- cid_name, vars, account, locked_channel, 0);
+ cid_name, vars, account, locked_channel, 0, assignedids);
}
/* this is the guts of destroying a context --