diff options
Diffstat (limited to 'main')
-rw-r--r-- | main/bridge.c | 18 | ||||
-rw-r--r-- | main/bridge_basic.c | 8 | ||||
-rw-r--r-- | main/bridge_channel.c | 15 | ||||
-rw-r--r-- | main/ccss.c | 2 | ||||
-rw-r--r-- | main/cel.c | 3 | ||||
-rw-r--r-- | main/channel.c | 86 | ||||
-rw-r--r-- | main/channel_internal_api.c | 108 | ||||
-rw-r--r-- | main/core_local.c | 6 | ||||
-rw-r--r-- | main/core_unreal.c | 24 | ||||
-rw-r--r-- | main/dial.c | 32 | ||||
-rw-r--r-- | main/manager.c | 28 | ||||
-rw-r--r-- | main/message.c | 2 | ||||
-rw-r--r-- | main/pbx.c | 14 |
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 -- |