#define DIAL_STILLGOING (1 << 31)
#define DIAL_NOFORWARDHTML ((uint64_t)1 << 32) /* flags are now 64 bits, so keep it up! */
-#define DIAL_NOCONNECTEDLINE ((uint64_t)1 << 33)
+#define DIAL_CALLERID_ABSENT ((uint64_t)1 << 33) /* TRUE if caller id is not available for connected line. */
#define OPT_CANCEL_ELSEWHERE ((uint64_t)1 << 34)
#define OPT_PEER_H ((uint64_t)1 << 35)
#define OPT_CALLEE_GO_ON ((uint64_t)1 << 36)
struct chanlist *next;
struct ast_channel *chan;
uint64_t flags;
+ /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
struct ast_party_connected_line connected;
+ /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
+ unsigned int pending_connected_update:1;
};
static int detect_disconnect(struct ast_channel *chan, char code, struct ast_str *featurecode);
ast_channel_make_compatible(outgoing->chan, in);
}
- if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_NOCONNECTEDLINE)) {
+ if (!ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE) && !ast_test_flag64(outgoing, DIAL_CALLERID_ABSENT)) {
ast_channel_lock(outgoing->chan);
ast_connected_line_copy_from_caller(&connected_caller, &outgoing->chan->cid);
ast_channel_unlock(outgoing->chan);
if (!peer) {
ast_verb(3, "%s answered %s\n", c->name, in->name);
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
- if (o->connected.id.number) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected);
}
- } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
+ } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
ast_channel_lock(c);
ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
ast_channel_unlock(c);
if (!peer) {
ast_verb(3, "%s answered %s\n", c->name, in->name);
if (!single && !ast_test_flag64(peerflags, OPT_IGNORE_CONNECTEDLINE)) {
- if (o->connected.id.number) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(c, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected);
}
- } else if (!ast_test_flag64(o, DIAL_NOCONNECTEDLINE)) {
+ } else if (!ast_test_flag64(o, DIAL_CALLERID_ABSENT)) {
ast_channel_lock(c);
ast_connected_line_copy_from_caller(&connected_caller, &c->cid);
ast_channel_unlock(c);
ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
ast_party_connected_line_set(&o->connected, &connected);
ast_party_connected_line_free(&connected);
+ o->pending_connected_update = 1;
} else {
if (ast_channel_connected_line_macro(c, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
ast_channel_lock(chan);
datastore = ast_channel_datastore_find(chan, &dialed_interface_info, NULL);
- /* If the incoming channel has previously had connected line information
- * set on it (perhaps through the CONNECTED_LINE dialplan function) then
- * seed the calllist's connected line information with this previously
- * acquired info
+ /*
+ * Seed the chanlist's connected line information with previously
+ * acquired connected line info from the incoming channel. The
+ * previously acquired connected line info could have been set
+ * through the CONNECTED_LINE dialplan function.
*/
- if (chan->connected.id.number) {
- ast_party_connected_line_copy(&tmp->connected, &chan->connected);
- }
+ ast_party_connected_line_copy(&tmp->connected, &chan->connected);
ast_channel_unlock(chan);
if (datastore)
} else if (!ast_strlen_zero(S_OR(chan->macroexten, chan->exten))) {
ast_set_callerid(tc, S_OR(chan->macroexten, chan->exten), NULL, NULL);
}
- ast_set_flag64(tmp, DIAL_NOCONNECTEDLINE);
+ ast_set_flag64(tmp, DIAL_CALLERID_ABSENT);
}
if (ast_test_flag64(peerflags, OPT_FORCECLID) && !ast_strlen_zero(opt_args[OPT_ARG_FORCECLID])) {
time_t lastcall;
struct call_queue *lastqueue;
struct member *member;
- unsigned int update_connectedline:1;
+ /*! Saved connected party info from an AST_CONTROL_CONNECTED_LINE. */
struct ast_party_connected_line connected;
+ /*! TRUE if an AST_CONTROL_CONNECTED_LINE update was saved to the connected element. */
+ unsigned int pending_connected_update:1;
+ /*! TRUE if caller id is not available for connected line */
+ unsigned int dial_callerid_absent:1;
};
queue_t_unref(q, "Expire copied reference");
}
+/*!
+ * \internal
+ * \brief Destroy the given callattempt structure and free it.
+ * \since 1.8
+ *
+ * \param doomed callattempt structure to destroy.
+ *
+ * \return Nothing
+ */
+static void callattempt_free(struct callattempt *doomed)
+{
+ if (doomed->member) {
+ ao2_ref(doomed->member, -1);
+ }
+ ast_party_connected_line_free(&doomed->connected);
+ ast_free(doomed);
+}
+
/*! \brief Hang up a list of outgoing calls */
static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
{
}
oo = outgoing;
outgoing = outgoing->q_next;
- if (oo->member)
- ao2_ref(oo->member, -1);
- ast_free(oo);
+ callattempt_free(oo);
}
}
} else if (!ast_strlen_zero(S_OR(qe->chan->macroexten, qe->chan->exten))) {
ast_set_callerid(tmp->chan, S_OR(qe->chan->macroexten, qe->chan->exten), NULL, NULL);
}
- tmp->update_connectedline = 0;
+ tmp->dial_callerid_absent = 1;
}
ast_party_redirecting_copy(&tmp->chan->redirecting, &qe->chan->redirecting);
}
#define AST_MAX_WATCHERS 256
-/*! \brief Wait for a member to answer the call
+/*!
+ * \brief Wait for a member to answer the call
*
* \param[in] qe the queue_ent corresponding to the caller in the queue
* \param[in] outgoing the list of callattempts. Relevant ones will have their chan and stillgoing parameters non-zero
* \param[in] prebusies number of busy members calculated prior to calling wait_for_answer
* \param[in] caller_disconnect if the 'H' option is used when calling Queue(), this is used to detect if the caller pressed * to disconnect the call
* \param[in] forwardsallowed used to detect if we should allow call forwarding, based on the 'i' option to Queue()
+ * \param[in] update_connectedline Allow connected line and redirecting updates to pass through.
*
* \todo eventually all call forward logic should be intergerated into and replaced by ast_call_forward()
*/
if (!peer) {
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
- if (o->connected.id.number) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected);
}
- } else if (o->update_connectedline) {
+ } else if (!o->dial_callerid_absent) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
ast_channel_unlock(o->chan);
if (!peer) {
ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
if (update_connectedline) {
- if (o->connected.id.number) {
+ if (o->pending_connected_update) {
if (ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
ast_channel_update_connected_line(in, &o->connected);
}
- } else if (o->update_connectedline) {
+ } else if (!o->dial_callerid_absent) {
ast_channel_lock(o->chan);
ast_connected_line_copy_from_caller(&connected_caller, &o->chan->cid);
ast_channel_unlock(o->chan);
ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
ast_party_connected_line_set(&o->connected, &connected);
ast_party_connected_line_free(&connected);
+ o->pending_connected_update = 1;
} else {
if (ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
ao2_iterator_destroy(&memi);
if (need_weight)
ao2_unlock(queues);
- free(tmp);
+ callattempt_free(tmp);
goto out;
}
datastore->inheritance = DATASTORE_INHERIT_FOREVER;
ao2_iterator_destroy(&memi);
if (need_weight)
ao2_unlock(queues);
- free(tmp);
+ callattempt_free(tmp);
goto out;
}
datastore->data = dialed_interfaces;
}
AST_LIST_UNLOCK(dialed_interfaces);
- ast_channel_lock(qe->chan);
- /* If any pre-existing connected line information exists on this
- * channel, like from the CONNECTED_LINE dialplan function, use this
- * to seed the connected line information. It may, of course, be updated
- * during the call
- */
- if (qe->chan->connected.id.number) {
- ast_party_connected_line_copy(&tmp->connected, &qe->chan->connected);
- }
- ast_channel_unlock(qe->chan);
-
if (di) {
- free(tmp);
+ callattempt_free(tmp);
continue;
}
ao2_iterator_destroy(&memi);
if (need_weight)
ao2_unlock(queues);
- free(tmp);
+ callattempt_free(tmp);
goto out;
}
strcpy(di->interface, cur->interface);
AST_LIST_UNLOCK(dialed_interfaces);
}
+ ast_channel_lock(qe->chan);
+ /*
+ * Seed the callattempt's connected line information with previously
+ * acquired connected line info from the queued channel. The
+ * previously acquired connected line info could have been set
+ * through the CONNECTED_LINE dialplan function.
+ */
+ ast_party_connected_line_copy(&tmp->connected, &qe->chan->connected);
+ ast_channel_unlock(qe->chan);
+
tmp->stillgoing = -1;
- tmp->member = cur;
+ tmp->member = cur;/* Place the reference for cur into callattempt. */
tmp->lastcall = cur->lastcall;
tmp->lastqueue = cur->lastqueue;
- tmp->update_connectedline = 1;
ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
/* Special case: If we ring everyone, go ahead and ring them, otherwise
just calculate their metric for the appropriate strategy */
if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
break;
} else {
- ao2_ref(cur, -1);
- ast_free(tmp);
+ callattempt_free(tmp);
}
}
ao2_iterator_destroy(&memi);