summaryrefslogtreecommitdiff
path: root/main/channel_internal_api.c
diff options
context:
space:
mode:
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)) {