summaryrefslogtreecommitdiff
path: root/main/channel_internal_api.c
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/channel_internal_api.c
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/channel_internal_api.c')
-rw-r--r--main/channel_internal_api.c108
1 files changed, 90 insertions, 18 deletions
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)) {