summaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
authorScott Griepentrog <sgriepentrog@digium.com>2014-03-07 15:47:55 +0000
committerScott Griepentrog <sgriepentrog@digium.com>2014-03-07 15:47:55 +0000
commit80ef9a21b9d91ff0bafc304923bc29effa230b00 (patch)
treea67db39a4c17a4b01a87201ef37ffdc43189c119 /main
parentd3ac8b8a0e70049af7b5552c4dfd8adc2cc5df11 (diff)
uniqueid: channel linkedid, ami, ari object creation with id's
Much needed was a way to assign id to objects on creation, and much change was necessary to accomplish it. Channel uniqueids and linkedids are split into separate string and creation time components without breaking linkedid propgation. This allowed the uniqueid to be specified by the user interface - and those values are now carried through to channel creation, adding the assignedids value to every function in the chain including the channel drivers. For local channels, the second channel can be specified or left to default to a ;2 suffix of first. In ARI, bridge, playback, and snoop objects can also be created with a specified uniqueid. Along the way, the args order to allocating channels was fixed in chan_mgcp and chan_gtalk, and linkedid is no longer lost as masquerade occurs. (closes issue ASTERISK-23120) Review: https://reviewboard.asterisk.org/r/3191/ ........ Merged revisions 410157 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@410158 65c4cc65-6c06-0410-ace0-fbb531ad65f3
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 --