You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
asterisk/patches/queue_atxfer_bug_14260.patch

183 lines
6.3 KiB

--- apps/app_queue.c (revisión: 131)
+++ apps/app_queue.c (copia de trabajo)
@@ -287,6 +287,8 @@
/*! \brief queues.conf [general] option */
static int montype_default = 0;
+
+
enum queue_result {
QUEUE_UNKNOWN = 0,
QUEUE_TIMEOUT = 1,
@@ -401,6 +403,7 @@
unsigned int leavewhenempty:2;
unsigned int ringinuse:1;
unsigned int setinterfacevar:1;
+ unsigned int setqueuevar:1;
unsigned int reportholdtime:1;
unsigned int wrapped:1;
unsigned int timeoutrestart:1;
@@ -459,8 +462,69 @@
static int set_member_paused(const char *queuename, const char *interface, int paused);
-static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
+static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
+static char *int2strat(int strategy);
+
+static inline struct call_queue *queue_ref(struct call_queue *q)
+{
+ ao2_ref(q, 1);
+ return q;
+}
+
+static inline struct call_queue *queue_unref(struct call_queue *q)
+{
+ ao2_ref(q, -1);
+ return q;
+}
+
+static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
+{
+
+ char interfacevar[256]="";
+ float sl = 0;
+
+ if (q->setqueuevar) {
+ sl = 0;
+ if (q->callscompleted > 0)
+ sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
+
+ snprintf(interfacevar, sizeof(interfacevar),
+ "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
+ q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
+
+ pbx_builtin_setvar_multiple(chan, interfacevar);
+ }
+}
+
+
+struct queue_end_bridge {
+ struct call_queue *q;
+ struct ast_channel *chan;
+};
+
+static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
+{
+ struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
+ ao2_ref(qeb, +1);
+ qeb->chan = originator;
+
+}
+ static void end_bridge_callback(void *data)
+ {
+ struct queue_end_bridge *qeb = data;
+ struct call_queue *q = qeb->q;
+ struct ast_channel *chan = qeb->chan;
+
+ if (ao2_ref(qeb, -1) == 1) {
+ ao2_lock(q);
+ set_queue_variables(q, chan);
+ ao2_unlock(q);
+ /* This unrefs the reference we made in try_calling when we allocated qeb */
+ queue_unref(q);
+ }
+ }
+
static void rr_dep_warning(void)
{
static unsigned int warned = 0;
@@ -2830,6 +2894,7 @@
int callcompletedinsl;
struct ao2_iterator memi;
struct ast_datastore *datastore, *transfer_ds;
+ struct queue_end_bridge *queue_end_bridge = NULL;
ast_channel_lock(qe->chan);
datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
@@ -3256,6 +3321,19 @@
if (member->status == AST_DEVICE_NOT_INUSE)
ast_log(LOG_WARNING, "The device state of this queue member, %s, is still 'Not in Use' when it probably should not be! Please check UPGRADE.txt for correct configuration settings.\n", member->membername);
+
+ if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
+ queue_end_bridge->q = qe->parent;
+ queue_end_bridge->chan = qe->chan;
+ bridge_config.end_bridge_callback = end_bridge_callback;
+ bridge_config.end_bridge_callback_data = queue_end_bridge;
+ bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
+ /* Since queue_end_bridge can survive beyond the life of this call to Queue, we need
+ * to make sure to increase the refcount of this queue so it cannot be freed until we
+ * are done with it. We remove this reference in end_bridge_callback.
+ */
+ queue_ref(qe->parent);
+ }
transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
--- include/asterisk/pbx.h (revisión: 131)
+++ include/asterisk/pbx.h (copia de trabajo)
@@ -886,6 +886,7 @@
* \note Will lock the channel.
*/
int pbx_builtin_setvar(struct ast_channel *chan, void *data);
+int pbx_builtin_setvar_multiple(struct ast_channel *chan, void *data);
void pbx_substitute_variables_helper(struct ast_channel *c,const char *cp1,char *cp2,int count);
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count);
--- main/pbx.c (revisión: 131)
+++ main/pbx.c (copia de trabajo)
@@ -236,6 +236,7 @@
static int pbx_builtin_saycharacters(struct ast_channel *, void *);
static int pbx_builtin_sayphonetic(struct ast_channel *, void *);
int pbx_builtin_setvar(struct ast_channel *, void *);
+int pbx_builtin_setvar_multiple(struct ast_channel *, void *);
static int pbx_builtin_importvar(struct ast_channel *, void *);
AST_MUTEX_DEFINE_STATIC(globalslock);
@@ -5938,6 +5939,43 @@
ast_mutex_unlock(&globalslock);
}
+int pbx_builtin_setvar_multiple(struct ast_channel *chan, void *vdata)
+{
+ char *data;
+ int x;
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(pair)[24];
+ );
+ AST_DECLARE_APP_ARGS(pair,
+ AST_APP_ARG(name);
+ AST_APP_ARG(value);
+ );
+
+ if (ast_strlen_zero(vdata)) {
+ ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
+ return 0;
+ }
+
+ data = ast_strdupa(vdata);
+ AST_STANDARD_APP_ARGS(args, data);
+
+ for (x = 0; x < args.argc; x++) {
+ AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
+ if (pair.argc == 2) {
+ pbx_builtin_setvar_helper(chan, pair.name, pair.value);
+ if (strchr(pair.name, ' '))
+ ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
+ } else if (!chan) {
+ ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
+ } else {
+ ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
+ }
+ }
+
+ return 0;
+}
+
+
void pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
{
struct ast_var_t *newvariable;