Newer
Older
Matthew Jordan
committed
* the world know of its existance
ast_channel_stage_snapshot_done(tmp);
ast_debug(1, "Channel %p '%s' allocated\n", tmp, ast_channel_name(tmp));
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 struct ast_assigned_ids *assignedids,
const struct ast_channel *requestor, enum ama_flags amaflag,
Matthew Jordan
committed
struct ast_endpoint *endpoint,
const char *file, int line, const char *function,
const char *name_fmt, ...)
struct ast_channel *result;
result = __ast_channel_alloc_ap(needqueue, state, cid_num, cid_name, acctcode, exten, context,
Matthew Jordan
committed
assignedids, requestor, amaflag, endpoint, file, line, function, name_fmt, ap);
return result;
}
/* only do the minimum amount of work needed here to make a channel
* structure that can be used to expand channel vars */
#if defined(REF_DEBUG) || defined(__AST_DEBUG_MALLOC)
struct ast_channel *__ast_dummy_channel_alloc(const char *file, int line, const char *function)
#else
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, NULL))) {
/* Dummy channel structure allocation failure. */
return NULL;
}
Richard Mudgett
committed
ast_pbx_hangup_handler_init(tmp);
AST_LIST_HEAD_INIT_NOLOCK(ast_channel_datastores(tmp));
/*
* Init file descriptors to unopened state just in case
* autoservice is called on the channel or something tries to
* read a frame from it.
*/
ast_channel_timingfd_set(tmp, -1);
ast_channel_internal_alertpipe_clear(tmp);
ast_channel_internal_fd_clear_all(tmp);
#ifdef HAVE_EPOLL
ast_channel_epfd_set(tmp, -1);
ast_channel_hold_state_set(tmp, AST_CONTROL_UNHOLD);
ast_channel_internal_setup_topics(tmp);
headp = ast_channel_varshead(tmp);
AST_LIST_HEAD_INIT_NOLOCK(headp);
return tmp;
}
static int __ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin, int head, struct ast_frame *after)
unsigned int new_frames = 0;
unsigned int new_voice_frames = 0;
unsigned int queued_frames = 0;
unsigned int queued_voice_frames = 0;
AST_LIST_HEAD_NOLOCK(,ast_frame) frames;
/*
* Check the last frame on the queue if we are queuing the new
* frames after it.
*/
cur = AST_LIST_LAST(ast_channel_readq(chan));
if (cur && cur->frametype == AST_FRAME_CONTROL && !head && (!after || after == cur)) {
switch (cur->subclass.integer) {
case AST_CONTROL_END_OF_Q:
if (fin->frametype == AST_FRAME_CONTROL
&& fin->subclass.integer == AST_CONTROL_HANGUP) {
/*
* Destroy the end-of-Q marker frame so we can queue the hangup
* frame in its place.
*/
AST_LIST_REMOVE(ast_channel_readq(chan), cur, frame_list);
ast_frfree(cur);
/*
* This has degenerated to a normal queue append anyway. Since
* we just destroyed the last frame in the queue we must make
* sure that "after" is NULL or bad things will happen.
*/
after = NULL;
break;
}
/* Fall through */
case AST_CONTROL_HANGUP:
/* Don't queue anything. */
ast_channel_unlock(chan);
return 0;
default:
break;
}
/* Build copies of all the new frames and count them */
AST_LIST_HEAD_INIT_NOLOCK(&frames);
for (cur = fin; cur; cur = AST_LIST_NEXT(cur, frame_list)) {
if (!(f = ast_frdup(cur))) {
if (AST_LIST_FIRST(&frames)) {
ast_frfree(AST_LIST_FIRST(&frames));
}
return -1;
}
AST_LIST_INSERT_TAIL(&frames, f, frame_list);
new_frames++;
if (f->frametype == AST_FRAME_VOICE) {
new_voice_frames++;
}
}
/* Count how many frames exist on the queue */
AST_LIST_TRAVERSE(ast_channel_readq(chan), cur, frame_list) {
queued_frames++;
if (cur->frametype == AST_FRAME_VOICE) {
queued_voice_frames++;
}
if ((queued_frames + new_frames > 128 || queued_voice_frames + new_voice_frames > 96)) {
int count = 0;
ast_log(LOG_WARNING, "Exceptionally long %squeue length queuing to %s\n", queued_frames + new_frames > 128 ? "" : "voice ", ast_channel_name(chan));
AST_LIST_TRAVERSE_SAFE_BEGIN(ast_channel_readq(chan), cur, frame_list) {
/* Save the most recent frame */
if (!AST_LIST_NEXT(cur, frame_list)) {
break;
} else if (cur->frametype == AST_FRAME_VOICE || cur->frametype == AST_FRAME_VIDEO || cur->frametype == AST_FRAME_NULL) {
if (++count > 64) {
break;
}
AST_LIST_REMOVE_CURRENT(frame_list);
ast_frfree(cur);
/* Read from the alert pipe for each flushed frame. */
ast_channel_internal_alert_read(chan);
AST_LIST_TRAVERSE_SAFE_END;
AST_LIST_INSERT_LIST_AFTER(ast_channel_readq(chan), &frames, after, frame_list);
AST_LIST_APPEND_LIST(&frames, ast_channel_readq(chan), frame_list);
AST_LIST_HEAD_INIT_NOLOCK(ast_channel_readq(chan));
AST_LIST_APPEND_LIST(ast_channel_readq(chan), &frames, frame_list);
if (ast_channel_alert_writable(chan)) {
/* Write to the alert pipe for each added frame */
while (new_frames--) {
if (ast_channel_alert_write(chan)) {
ast_log(LOG_WARNING, "Unable to write to alert pipe on %s (qlen = %u): %s!\n",
ast_channel_name(chan), queued_frames, strerror(errno));
break;
}
} else if (ast_channel_timingfd(chan) > -1) {
ast_timer_enable_continuous(ast_channel_timer(chan));
} else if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_BLOCKING)) {
pthread_kill(ast_channel_blocker(chan), SIGURG);
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *fin)
return __ast_queue_frame(chan, fin, 0, NULL);
int ast_queue_frame_head(struct ast_channel *chan, struct ast_frame *fin)
return __ast_queue_frame(chan, fin, 1, NULL);
/*! \brief Queue a hangup frame for channel */
Michiel van Baak
committed
int ast_queue_hangup(struct ast_channel *chan)
{
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
Richard Mudgett
committed
int res;
Michiel van Baak
committed
/* Yeah, let's not change a lock-critical value without locking */
Richard Mudgett
committed
ast_channel_lock(chan);
ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
ast_channel_publish_blob(chan, ast_channel_hangup_request_type(), NULL);
Richard Mudgett
committed
res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
return res;
Michiel van Baak
committed
}
/*! \brief Queue a hangup frame for channel */
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HANGUP };
Richard Mudgett
committed
int res;
Richard Mudgett
committed
if (cause >= 0) {
Michiel van Baak
committed
f.data.uint32 = cause;
Richard Mudgett
committed
}
/* Yeah, let's not change a lock-critical value without locking */
Richard Mudgett
committed
ast_channel_lock(chan);
ast_channel_softhangup_internal_flag_add(chan, AST_SOFTHANGUP_DEV);
if (cause < 0) {
f.data.uint32 = ast_channel_hangupcause(chan);
blob = ast_json_pack("{s: i}",
"cause", cause);
ast_channel_publish_blob(chan, ast_channel_hangup_request_type(), blob);
Richard Mudgett
committed
res = ast_queue_frame(chan, &f);
ast_channel_unlock(chan);
return res;
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
{
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_HOLD };
struct ast_json *blob = NULL;
int res;
if (!ast_strlen_zero(musicclass)) {
f.data.ptr = (void *) musicclass;
f.datalen = strlen(musicclass) + 1;
blob = ast_json_pack("{s: s}",
"musicclass", musicclass);
}
ast_channel_publish_cached_blob(chan, ast_channel_hold_type(), blob);
res = ast_queue_frame(chan, &f);
ast_json_unref(blob);
return res;
}
int ast_queue_unhold(struct ast_channel *chan)
{
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = AST_CONTROL_UNHOLD };
int res;
ast_channel_publish_cached_blob(chan, ast_channel_unhold_type(), NULL);
res = ast_queue_frame(chan, &f);
return res;
}
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = control };
return ast_queue_frame(chan, &f);
}
/*! \brief Queue a control frame with payload */
int ast_queue_control_data(struct ast_channel *chan, enum ast_control_frame_type control,
const void *data, size_t datalen)
{
struct ast_frame f = { AST_FRAME_CONTROL, .subclass.integer = control, .data.ptr = (void *) data, .datalen = datalen };
Mark Spencer
committed
return ast_queue_frame(chan, &f);
/*! \brief Set defer DTMF flag on channel */
int ast_channel_defer_dtmf(struct ast_channel *chan)
{
int pre = 0;
ast_channel_lock(chan);
pre = ast_test_flag(ast_channel_flags(chan), AST_FLAG_DEFER_DTMF);
ast_set_flag(ast_channel_flags(chan), AST_FLAG_DEFER_DTMF);
ast_channel_unlock(chan);
/*! \brief Unset defer DTMF flag on channel */
void ast_channel_undefer_dtmf(struct ast_channel *chan)
{
if (chan) {
ast_channel_clear_flag(chan, AST_FLAG_DEFER_DTMF);
}
struct ast_channel *ast_channel_callback(ao2_callback_data_fn *cb_fn, void *arg,
void *data, int ao2_flags)
return ao2_callback_data(channels, ao2_flags, cb_fn, arg, data);
}
static int ast_channel_by_name_cb(void *obj, void *arg, void *data, int flags)
{
struct ast_channel *chan = obj;
const char *name = arg;
size_t name_len = *(size_t *) data;
int ret = CMP_MATCH;
if (ast_strlen_zero(name)) {
ast_log(LOG_ERROR, "BUG! Must supply a channel name or partial name to match!\n");
return CMP_STOP;
}
ast_channel_lock(chan);
if ((!name_len && strcasecmp(ast_channel_name(chan), name))
|| (name_len && strncasecmp(ast_channel_name(chan), name, name_len))) {
ret = 0; /* name match failed, keep looking */
}
ast_channel_unlock(chan);
return ret;
}
static int ast_channel_by_exten_cb(void *obj, void *arg, void *data, int flags)
{
struct ast_channel *chan = obj;
char *context = arg;
char *exten = data;
int ret = CMP_MATCH;
if (ast_strlen_zero(exten) || ast_strlen_zero(context)) {
ast_log(LOG_ERROR, "BUG! Must have a context and extension to match!\n");
return CMP_STOP;
}
ast_channel_lock(chan);
if (strcasecmp(ast_channel_context(chan), context) && strcasecmp(ast_channel_macrocontext(chan), context)) {
ret = 0; /* Context match failed, continue */
} else if (strcasecmp(ast_channel_exten(chan), exten) && strcasecmp(ast_channel_macroexten(chan), exten)) {
ret = 0; /* Extension match failed, continue */
}
ast_channel_unlock(chan);
return ret;
}
static int ast_channel_by_uniqueid_cb(void *obj, void *arg, void *data, int flags)
{
struct ast_channel *chan = obj;
char *uniqueid = arg;
size_t id_len = *(size_t *) data;
int ret = CMP_MATCH;
if (ast_strlen_zero(uniqueid)) {
ast_log(LOG_ERROR, "BUG! Must supply a uniqueid or partial uniqueid to match!\n");
return CMP_STOP;
}
ast_channel_lock(chan);
if ((!id_len && strcasecmp(ast_channel_uniqueid(chan), uniqueid))
|| (id_len && strncasecmp(ast_channel_uniqueid(chan), uniqueid, id_len))) {
ret = 0; /* uniqueid match failed, keep looking */
}
ast_channel_unlock(chan);
return ret;
}
struct ast_channel_iterator {
Kevin P. Fleming
committed
/* storage for non-dynamically allocated iterator */
struct ao2_iterator simple_iterator;
/* pointer to the actual iterator (simple_iterator or a dynamically
* allocated iterator)
*/
struct ao2_iterator *active_iterator;
};
struct ast_channel_iterator *ast_channel_iterator_destroy(struct ast_channel_iterator *i)
{
Kevin P. Fleming
committed
ao2_iterator_destroy(i->active_iterator);
ast_free(i);
Kevin P. Fleming
committed
return NULL;
}
struct ast_channel_iterator *ast_channel_iterator_by_exten_new(const char *exten, const char *context)
Kevin P. Fleming
committed
{
struct ast_channel_iterator *i;
char *l_exten = (char *) exten;
char *l_context = (char *) context;
if (!(i = ast_calloc(1, sizeof(*i)))) {
return NULL;
}
i->active_iterator = (void *) ast_channel_callback(ast_channel_by_exten_cb,
l_context, l_exten, OBJ_MULTIPLE);
if (!i->active_iterator) {
ast_free(i);
return NULL;
}
return i;
Kevin P. Fleming
committed
}
Kevin P. Fleming
committed
struct ast_channel_iterator *ast_channel_iterator_by_name_new(const char *name, size_t name_len)
struct ast_channel_iterator *i;
char *l_name = (char *) name;
if (!(i = ast_calloc(1, sizeof(*i)))) {
return NULL;
}
i->active_iterator = (void *) ast_channel_callback(ast_channel_by_name_cb,
l_name, &name_len,
OBJ_MULTIPLE | (name_len == 0 /* match the whole word, so optimize */ ? OBJ_KEY : 0));
if (!i->active_iterator) {
ast_free(i);
return NULL;
}
return i;
Kevin P. Fleming
committed
struct ast_channel_iterator *ast_channel_iterator_all_new(void)
Kevin P. Fleming
committed
struct ast_channel_iterator *i;
Kevin P. Fleming
committed
if (!(i = ast_calloc(1, sizeof(*i)))) {
return NULL;
}
Kevin P. Fleming
committed
i->simple_iterator = ao2_iterator_init(channels, 0);
i->active_iterator = &i->simple_iterator;
Kevin P. Fleming
committed
return i;
}
Kevin P. Fleming
committed
struct ast_channel *ast_channel_iterator_next(struct ast_channel_iterator *i)
{
return ao2_iterator_next(i->active_iterator);
/* Legacy function, not currently used for lookups, but we need a cmp_fn */
static int ast_channel_cmp_cb(void *obj, void *arg, int flags)
{
ast_log(LOG_ERROR, "BUG! Should never be called!\n");
return CMP_STOP;
}
struct ast_channel *ast_channel_get_by_name_prefix(const char *name, size_t name_len)
struct ast_channel *chan;
char *l_name = (char *) name;
chan = ast_channel_callback(ast_channel_by_name_cb, l_name, &name_len,
(name_len == 0) /* optimize if it is a complete name match */ ? OBJ_KEY : 0);
if (chan) {
return chan;
}
if (ast_strlen_zero(l_name)) {
/* We didn't have a name to search for so quit. */
return NULL;
}
/* Now try a search for uniqueid. */
return ast_channel_callback(ast_channel_by_uniqueid_cb, l_name, &name_len, 0);
struct ast_channel *ast_channel_get_by_name(const char *name)
Sean Bright
committed
{
return ast_channel_get_by_name_prefix(name, 0);
}
Sean Bright
committed
struct ast_channel *ast_channel_get_by_exten(const char *exten, const char *context)
{
char *l_exten = (char *) exten;
char *l_context = (char *) context;
return ast_channel_callback(ast_channel_by_exten_cb, l_context, l_exten, 0);
Sean Bright
committed
}
int ast_is_deferrable_frame(const struct ast_frame *frame)
{
/* Do not add a default entry in this switch statement. Each new
* frame type should be addressed directly as to whether it should
* be queued up or not.
*/
switch (frame->frametype) {
Richard Mudgett
committed
case AST_FRAME_BRIDGE_ACTION:
Mark Michelson
committed
case AST_FRAME_BRIDGE_ACTION_SYNC:
case AST_FRAME_CONTROL:
case AST_FRAME_TEXT:
case AST_FRAME_IMAGE:
case AST_FRAME_HTML:
return 1;
case AST_FRAME_DTMF_BEGIN:
case AST_FRAME_VOICE:
case AST_FRAME_VIDEO:
case AST_FRAME_NULL:
case AST_FRAME_IAX:
case AST_FRAME_CNG:
case AST_FRAME_MODEM:
return 0;
}
return 0;
}
/*! \brief Wait, look for hangups and condition arg */
int ast_safe_sleep_conditional(struct ast_channel *chan, int timeout_ms, int (*cond)(void*), void *data)
struct ast_silence_generator *silgen = NULL;
int res = 0;
AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
/* If no other generator is present, start silencegen while waiting */
if (ast_opt_transmit_silence && !ast_channel_generatordata(chan)) {
silgen = ast_channel_start_silence_generator(chan);
}
start = ast_tvnow();
while ((ms = ast_remaining_ms(start, timeout_ms))) {
struct ast_frame *dup_f = NULL;
if (cond && ((*cond)(data) == 0)) {
break;
}
if (ms < 0) {
res = -1;
break;
}
if (!f) {
res = -1;
break;
}
if (!ast_is_deferrable_frame(f)) {
ast_frfree(f);
continue;
}
if ((dup_f = ast_frisolate(f))) {
if (dup_f != f) {
ast_frfree(f);
}
AST_LIST_INSERT_HEAD(&deferred_frames, dup_f, frame_list);
}
/* stop silgen if present */
if (silgen) {
ast_channel_stop_silence_generator(chan, silgen);
}
/* We need to free all the deferred frames, but we only need to
* queue the deferred frames if there was no error and no
* hangup was received
*/
while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
if (!res) {
ast_queue_frame_head(chan, f);
}
ast_frfree(f);
}
ast_channel_unlock(chan);
int ast_safe_sleep(struct ast_channel *chan, int ms)
{
return ast_safe_sleep_conditional(chan, ms, NULL, NULL);
struct ast_channel *ast_channel_release(struct ast_channel *chan)
{
/* Safe, even if already unlinked. */
ao2_unlink(channels, chan);
return ast_channel_unref(chan);
}
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
void ast_party_name_init(struct ast_party_name *init)
{
init->str = NULL;
init->char_set = AST_PARTY_CHAR_SET_ISO8859_1;
init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
init->valid = 0;
}
void ast_party_name_copy(struct ast_party_name *dest, const struct ast_party_name *src)
{
if (dest == src) {
/* Don't copy to self */
return;
}
ast_free(dest->str);
dest->str = ast_strdup(src->str);
dest->char_set = src->char_set;
dest->presentation = src->presentation;
dest->valid = src->valid;
}
void ast_party_name_set_init(struct ast_party_name *init, const struct ast_party_name *guide)
{
init->str = NULL;
init->char_set = guide->char_set;
init->presentation = guide->presentation;
init->valid = guide->valid;
}
void ast_party_name_set(struct ast_party_name *dest, const struct ast_party_name *src)
{
if (dest == src) {
/* Don't set to self */
return;
}
if (src->str && src->str != dest->str) {
ast_free(dest->str);
dest->str = ast_strdup(src->str);
}
dest->char_set = src->char_set;
dest->presentation = src->presentation;
dest->valid = src->valid;
}
void ast_party_name_free(struct ast_party_name *doomed)
{
ast_free(doomed->str);
doomed->str = NULL;
}
void ast_party_number_init(struct ast_party_number *init)
{
init->str = NULL;
init->plan = 0;/* Unknown */
init->presentation = AST_PRES_ALLOWED_USER_NUMBER_NOT_SCREENED;
init->valid = 0;
}
void ast_party_number_copy(struct ast_party_number *dest, const struct ast_party_number *src)
{
if (dest == src) {
/* Don't copy to self */
return;
}
ast_free(dest->str);
dest->str = ast_strdup(src->str);
dest->plan = src->plan;
dest->presentation = src->presentation;
dest->valid = src->valid;
}
void ast_party_number_set_init(struct ast_party_number *init, const struct ast_party_number *guide)
{
init->str = NULL;
init->plan = guide->plan;
init->presentation = guide->presentation;
init->valid = guide->valid;
}
void ast_party_number_set(struct ast_party_number *dest, const struct ast_party_number *src)
{
if (dest == src) {
/* Don't set to self */
return;
}
if (src->str && src->str != dest->str) {
ast_free(dest->str);
dest->str = ast_strdup(src->str);
}
dest->plan = src->plan;
dest->presentation = src->presentation;
dest->valid = src->valid;
}
void ast_party_number_free(struct ast_party_number *doomed)
{
ast_free(doomed->str);
doomed->str = NULL;
}
Richard Mudgett
committed
void ast_party_subaddress_init(struct ast_party_subaddress *init)
{
init->str = NULL;
init->type = 0;
init->odd_even_indicator = 0;
init->valid = 0;
}
void ast_party_subaddress_copy(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
{
if (dest == src) {
/* Don't copy to self */
return;
}
Richard Mudgett
committed
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
dest->str = ast_strdup(src->str);
dest->type = src->type;
dest->odd_even_indicator = src->odd_even_indicator;
dest->valid = src->valid;
}
void ast_party_subaddress_set_init(struct ast_party_subaddress *init, const struct ast_party_subaddress *guide)
{
init->str = NULL;
init->type = guide->type;
init->odd_even_indicator = guide->odd_even_indicator;
init->valid = guide->valid;
}
void ast_party_subaddress_set(struct ast_party_subaddress *dest, const struct ast_party_subaddress *src)
{
if (dest == src) {
/* Don't set to self */
return;
}
if (src->str && src->str != dest->str) {
Richard Mudgett
committed
dest->str = ast_strdup(src->str);
}
dest->type = src->type;
dest->odd_even_indicator = src->odd_even_indicator;
dest->valid = src->valid;
}
void ast_party_subaddress_free(struct ast_party_subaddress *doomed)
{
ast_free(doomed->str);
doomed->str = NULL;
Richard Mudgett
committed
}
Richard Mudgett
committed
void ast_set_party_id_all(struct ast_set_party_id *update_id)
{
update_id->name = 1;
update_id->number = 1;
update_id->subaddress = 1;
}
void ast_party_id_init(struct ast_party_id *init)
Mark Michelson
committed
{
ast_party_name_init(&init->name);
ast_party_number_init(&init->number);
Richard Mudgett
committed
ast_party_subaddress_init(&init->subaddress);
Mark Michelson
committed
}
void ast_party_id_copy(struct ast_party_id *dest, const struct ast_party_id *src)
Mark Michelson
committed
{
if (dest == src) {
/* Don't copy to self */
return;
}
ast_party_name_copy(&dest->name, &src->name);
ast_party_number_copy(&dest->number, &src->number);
ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
Mark Michelson
committed
dest->tag = ast_strdup(src->tag);
Mark Michelson
committed
}
void ast_party_id_set_init(struct ast_party_id *init, const struct ast_party_id *guide)
Mark Michelson
committed
{
ast_party_name_set_init(&init->name, &guide->name);
ast_party_number_set_init(&init->number, &guide->number);
Richard Mudgett
committed
ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
Mark Michelson
committed
}
void ast_party_id_set(struct ast_party_id *dest, const struct ast_party_id *src, const struct ast_set_party_id *update)
Mark Michelson
committed
{
if (dest == src) {
/* Don't set to self */
return;
}
if (!update || update->name) {
ast_party_name_set(&dest->name, &src->name);
Mark Michelson
committed
}
if (!update || update->number) {
ast_party_number_set(&dest->number, &src->number);
}
if (!update || update->subaddress) {
ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
Mark Michelson
committed
}
if (src->tag && src->tag != dest->tag) {
dest->tag = ast_strdup(src->tag);
}
Mark Michelson
committed
}
void ast_party_id_free(struct ast_party_id *doomed)
Mark Michelson
committed
{
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
ast_party_name_free(&doomed->name);
ast_party_number_free(&doomed->number);
ast_party_subaddress_free(&doomed->subaddress);
ast_free(doomed->tag);
doomed->tag = NULL;
}
int ast_party_id_presentation(const struct ast_party_id *id)
{
int number_priority;
int number_value;
int number_screening;
int name_priority;
int name_value;
/* Determine name presentation priority. */
if (!id->name.valid) {
name_value = AST_PRES_UNAVAILABLE;
name_priority = 3;
} else {
name_value = id->name.presentation & AST_PRES_RESTRICTION;
switch (name_value) {
case AST_PRES_RESTRICTED:
name_priority = 0;
break;
case AST_PRES_ALLOWED:
name_priority = 1;
break;
case AST_PRES_UNAVAILABLE:
name_priority = 2;
break;
default:
name_value = AST_PRES_UNAVAILABLE;
name_priority = 3;
break;
}
Mark Michelson
committed
}
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
/* Determine number presentation priority. */
if (!id->number.valid) {
number_screening = AST_PRES_USER_NUMBER_UNSCREENED;
number_value = AST_PRES_UNAVAILABLE;
number_priority = 3;
} else {
number_screening = id->number.presentation & AST_PRES_NUMBER_TYPE;
number_value = id->number.presentation & AST_PRES_RESTRICTION;
switch (number_value) {
case AST_PRES_RESTRICTED:
number_priority = 0;
break;
case AST_PRES_ALLOWED:
number_priority = 1;
break;
case AST_PRES_UNAVAILABLE:
number_priority = 2;
break;
default:
number_screening = AST_PRES_USER_NUMBER_UNSCREENED;
number_value = AST_PRES_UNAVAILABLE;
number_priority = 3;
break;
}
Mark Michelson
committed
}
/* Select the wining presentation value. */
if (name_priority < number_priority) {
number_value = name_value;
Richard Mudgett
committed
if (number_value == AST_PRES_UNAVAILABLE) {
return AST_PRES_NUMBER_NOT_AVAILABLE;
}
return number_value | number_screening;
Mark Michelson
committed
}
Richard Mudgett
committed
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
void ast_party_id_invalidate(struct ast_party_id *id)
{
id->name.valid = 0;
id->number.valid = 0;
id->subaddress.valid = 0;
}
void ast_party_id_reset(struct ast_party_id *id)
{
ast_party_id_free(id);
ast_party_id_init(id);
}
struct ast_party_id ast_party_id_merge(struct ast_party_id *base, struct ast_party_id *overlay)
{
struct ast_party_id merged;
merged = *base;
if (overlay->name.valid) {
merged.name = overlay->name;
}
if (overlay->number.valid) {
merged.number = overlay->number;
}
if (overlay->subaddress.valid) {
merged.subaddress = overlay->subaddress;
}
/* Note the actual structure is returned and not a pointer to it! */
return merged;
}
void ast_party_id_merge_copy(struct ast_party_id *dest, struct ast_party_id *base, struct ast_party_id *overlay)
{
struct ast_party_id merged;
merged = ast_party_id_merge(base, overlay);
ast_party_id_copy(dest, &merged);
}
void ast_party_dialed_init(struct ast_party_dialed *init)
init->number.str = NULL;
init->number.plan = 0;/* Unknown */
ast_party_subaddress_init(&init->subaddress);
init->transit_network_select = 0;
void ast_party_dialed_copy(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
Mark Michelson
committed
{
if (dest == src) {
/* Don't copy to self */
return;
}
ast_free(dest->number.str);
dest->number.str = ast_strdup(src->number.str);
dest->number.plan = src->number.plan;
ast_party_subaddress_copy(&dest->subaddress, &src->subaddress);
dest->transit_network_select = src->transit_network_select;
}
Mark Michelson
committed
void ast_party_dialed_set_init(struct ast_party_dialed *init, const struct ast_party_dialed *guide)
{
init->number.str = NULL;
init->number.plan = guide->number.plan;
ast_party_subaddress_set_init(&init->subaddress, &guide->subaddress);
init->transit_network_select = guide->transit_network_select;
}
Mark Michelson
committed
void ast_party_dialed_set(struct ast_party_dialed *dest, const struct ast_party_dialed *src)
{
if (src->number.str && src->number.str != dest->number.str) {
ast_free(dest->number.str);
dest->number.str = ast_strdup(src->number.str);
dest->number.plan = src->number.plan;
ast_party_subaddress_set(&dest->subaddress, &src->subaddress);
dest->transit_network_select = src->transit_network_select;
}
Mark Michelson
committed
void ast_party_dialed_free(struct ast_party_dialed *doomed)
{