mirror of
https://github.com/asterisk/asterisk.git
synced 2025-10-21 12:30:41 +00:00
Ensure that CDRs for a caller in a Queue that is not answered is NO ANSWER.
When a caller enters a queue and no queue member answers the call, the current behaviour can be a little odd depending on the paused status of the queue members. If any queue member is paused, but not all, the CDR disposition will be BUSY. If all queue members are paused, then the CDR disposition is based instead on the disposition of the call prior to entering the Queue. This patch modifies the behaviour in the following ways: * If no queue members are paused, the CDR disposition is whatever the disposition was prior to going into Queue. If the call was answered this will be ANSWERED; otherwise, it is NO ANSWER. * If some queue members are pused, the CDR result is NO ANSWER. (This is a change in behaviour, as the result would previously have been BUSY) * If all queue members are paused, the CDR result is whatever the result was prior to going into Queue. This is the same as the behaviour prior to this patch. * If the caller hangs up, times out, or presses '*' with the 'h' option, the CDR disposition is again not set and is dependent on whether or not the caller was Answered prior to entering Queue. This patch was based on one provided by Thomas Arimont, but has been modified to accomodate findings by the reviewers. Review: https://reviewboard.asterisk.org/r/2064/ (closes issue AST-906) Reported by: Thomas Arimont (closes issue ASTERISK-17776) Reported by: Attila Megyeri git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@375416 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
@@ -28,12 +28,16 @@ AMI:
|
|||||||
a peer once a peer has been found to qualify. Once the qualify has been
|
a peer once a peer has been found to qualify. Once the qualify has been
|
||||||
completed it will now issue a SIPqualifypeerdone event.
|
completed it will now issue a SIPqualifypeerdone event.
|
||||||
|
|
||||||
Queue:
|
Queues:
|
||||||
- Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is
|
- Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is
|
||||||
performed on is a member of at least one queue.
|
performed on is a member of at least one queue.
|
||||||
- Queue strategy rrmemory now has a predictable order similar to strategy
|
- Queue strategy rrmemory now has a predictable order similar to strategy
|
||||||
rrordered. Members will be called in the order that they are added to the
|
rrordered. Members will be called in the order that they are added to the
|
||||||
queue.
|
queue.
|
||||||
|
- CDR behavior in app_queue has been modified slightly. The CDR record will
|
||||||
|
now only record a disposition of BUSY if all Queue members were actually
|
||||||
|
busy on a call or some Queue members were busy or paused. Previously, any
|
||||||
|
Queue member being paused would result in a disposition of BUSY.
|
||||||
|
|
||||||
Dial:
|
Dial:
|
||||||
- Now recognizes 'W' to pause sending DTMF for one second in addition to
|
- Now recognizes 'W' to pause sending DTMF for one second in addition to
|
||||||
|
@@ -3520,10 +3520,8 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
/* on entry here, we know that tmp->chan == NULL */
|
/* on entry here, we know that tmp->chan == NULL */
|
||||||
if (tmp->member->paused) {
|
if (tmp->member->paused) {
|
||||||
ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
|
ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
|
||||||
if (ast_channel_cdr(qe->chan)) {
|
|
||||||
ast_cdr_busy(ast_channel_cdr(qe->chan));
|
|
||||||
}
|
|
||||||
tmp->stillgoing = 0;
|
tmp->stillgoing = 0;
|
||||||
|
(*busies)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3531,9 +3529,6 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
(!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
|
(!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
|
||||||
ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
|
ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
|
||||||
(tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
|
(tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
|
||||||
if (ast_channel_cdr(qe->chan)) {
|
|
||||||
ast_cdr_busy(ast_channel_cdr(qe->chan));
|
|
||||||
}
|
|
||||||
tmp->stillgoing = 0;
|
tmp->stillgoing = 0;
|
||||||
(*busies)++;
|
(*busies)++;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3550,19 +3545,14 @@ static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies
|
|||||||
}
|
}
|
||||||
if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
|
if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
|
||||||
ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
|
ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
|
||||||
if (ast_channel_cdr(qe->chan)) {
|
|
||||||
ast_cdr_busy(ast_channel_cdr(qe->chan));
|
|
||||||
}
|
|
||||||
tmp->stillgoing = 0;
|
tmp->stillgoing = 0;
|
||||||
|
(*busies)++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_weight && compare_weight(qe->parent,tmp->member)) {
|
if (use_weight && compare_weight(qe->parent,tmp->member)) {
|
||||||
ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
|
ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
|
||||||
if (ast_channel_cdr(qe->chan)) {
|
|
||||||
ast_cdr_busy(ast_channel_cdr(qe->chan));
|
|
||||||
}
|
|
||||||
tmp->stillgoing = 0;
|
tmp->stillgoing = 0;
|
||||||
(*busies)++;
|
(*busies)++;
|
||||||
return 0;
|
return 0;
|
||||||
@@ -4077,7 +4067,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (*to && !peer) {
|
while (*to && !peer) {
|
||||||
int numlines, retry, pos = 1;
|
int numlines, retry, pos = 1;
|
||||||
struct ast_channel *watchers[AST_MAX_WATCHERS];
|
struct ast_channel *watchers[AST_MAX_WATCHERS];
|
||||||
@@ -4115,8 +4105,14 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
if (pos == 1 /* not found */) {
|
if (pos == 1 /* not found */) {
|
||||||
if (numlines == (numbusies + numnochan)) {
|
if (numlines == (numbusies + numnochan)) {
|
||||||
ast_debug(1, "Everyone is busy at this time\n");
|
ast_debug(1, "Everyone is busy at this time\n");
|
||||||
|
if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) {
|
||||||
|
ast_cdr_busy(ast_channel_cdr(in));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
|
ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
|
||||||
|
if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) {
|
||||||
|
ast_cdr_failed(ast_channel_cdr(in));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
*to = 0;
|
*to = 0;
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -4358,7 +4354,7 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
case AST_CONTROL_CONGESTION:
|
case AST_CONTROL_CONGESTION:
|
||||||
ast_verb(3, "%s is circuit-busy\n", ochan_name);
|
ast_verb(3, "%s is circuit-busy\n", ochan_name);
|
||||||
if (ast_channel_cdr(in)) {
|
if (ast_channel_cdr(in)) {
|
||||||
ast_cdr_busy(ast_channel_cdr(in));
|
ast_cdr_failed(ast_channel_cdr(in));
|
||||||
}
|
}
|
||||||
endtime = (long) time(NULL);
|
endtime = (long) time(NULL);
|
||||||
endtime -= starttime;
|
endtime -= starttime;
|
||||||
@@ -4491,6 +4487,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
|
ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
|
||||||
*to = 0;
|
*to = 0;
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
|
if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) {
|
||||||
|
ast_cdr_noanswer(ast_channel_cdr(in));
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
|
if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
|
||||||
@@ -4498,6 +4497,9 @@ static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callatte
|
|||||||
*to = 0;
|
*to = 0;
|
||||||
*digit = f->subclass.integer;
|
*digit = f->subclass.integer;
|
||||||
ast_frfree(f);
|
ast_frfree(f);
|
||||||
|
if (ast_channel_cdr(in) && ast_channel_state(in) != AST_STATE_UP) {
|
||||||
|
ast_cdr_noanswer(ast_channel_cdr(in));
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4541,6 +4543,12 @@ skip_frame:;
|
|||||||
rna(orig, qe, o->interface, o->member->membername, 1);
|
rna(orig, qe, o->interface, o->member->membername, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ast_channel_cdr(in)
|
||||||
|
&& ast_channel_state(in) != AST_STATE_UP
|
||||||
|
&& (!*to || ast_check_hangup(in))) {
|
||||||
|
ast_cdr_noanswer(ast_channel_cdr(in));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_EPOLL
|
#ifdef HAVE_EPOLL
|
||||||
|
Reference in New Issue
Block a user