Implement remaining queue strategies, ADSI fixes, and queue config updates

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1252 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 22 years ago
parent 7ab4290896
commit 1fb2eaabf3

@ -1,3 +1,5 @@
-- Merge voicemail enhancements (app_voicemail2)
-- Add multiple queueing strategies
-- Merge support for 'T' -- Merge support for 'T'
-- Allow pending agent calling (Agent/:1) -- Allow pending agent calling (Agent/:1)
-- Add groupings to agents.conf -- Add groupings to agents.conf

@ -111,7 +111,6 @@ struct localuser {
char numsubst[256]; char numsubst[256];
char tech[40]; char tech[40];
int stillgoing; int stillgoing;
int penalty;
int metric; int metric;
int allowredirect_in; int allowredirect_in;
int allowredirect_out; int allowredirect_out;
@ -119,6 +118,7 @@ struct localuser {
int musiconhold; int musiconhold;
int dataquality; int dataquality;
int allowdisconnect; int allowdisconnect;
struct member *member;
struct localuser *next; struct localuser *next;
}; };
@ -139,7 +139,8 @@ struct member {
char tech[80]; /* Technology */ char tech[80]; /* Technology */
char loc[256]; /* Location */ char loc[256]; /* Location */
int penalty; /* Are we a last resort? */ int penalty; /* Are we a last resort? */
struct timeval lastcall; /* When last successful call was hungup */ int calls;
time_t lastcall; /* When last successful call was hungup */
struct member *next; /* Next member */ struct member *next; /* Next member */
}; };
@ -429,7 +430,7 @@ static int valid_exit(struct queue_ent *qe, char digit)
#define MAX 256 #define MAX 256
static struct ast_channel *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, char *digit) static struct localuser *wait_for_answer(struct queue_ent *qe, struct localuser *outgoing, int *to, int *allowredir_in, int *allowredir_out, int *allowdisconnect, char *digit)
{ {
char *queue = qe->parent->name; char *queue = qe->parent->name;
struct localuser *o; struct localuser *o;
@ -439,7 +440,7 @@ static struct ast_channel *wait_for_answer(struct queue_ent *qe, struct localuse
int numbusies = 0; int numbusies = 0;
int orig = *to; int orig = *to;
struct ast_frame *f; struct ast_frame *f;
struct ast_channel *peer = NULL; struct localuser *peer = NULL;
struct ast_channel *watchers[MAX]; struct ast_channel *watchers[MAX];
int pos; int pos;
struct ast_channel *winner; struct ast_channel *winner;
@ -476,7 +477,7 @@ static struct ast_channel *wait_for_answer(struct queue_ent *qe, struct localuse
if (!peer) { if (!peer) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
peer = o->chan; peer = o;
*allowredir_in = o->allowredirect_in; *allowredir_in = o->allowredirect_in;
*allowredir_out = o->allowredirect_out; *allowredir_out = o->allowredirect_out;
*allowdisconnect = o->allowdisconnect; *allowdisconnect = o->allowdisconnect;
@ -491,7 +492,7 @@ static struct ast_channel *wait_for_answer(struct queue_ent *qe, struct localuse
if (!peer) { if (!peer) {
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name);
peer = o->chan; peer = o;
*allowredir_in = o->allowredirect_in; *allowredir_in = o->allowredirect_in;
*allowredir_out = o->allowredirect_out; *allowredir_out = o->allowredirect_out;
*allowdisconnect = o->allowdisconnect; *allowdisconnect = o->allowdisconnect;
@ -604,7 +605,26 @@ static int wait_our_turn(struct queue_ent *qe)
return res; return res;
} }
static int calc_metric(struct ast_call_queue *q, int pos, struct queue_ent *qe, struct localuser *tmp) static int update_queue(struct ast_call_queue *q, struct localuser *user)
{
struct member *cur;
/* Since a reload could have taken place, we have to traverse the list to
be sure it's still valid */
ast_pthread_mutex_lock(&q->lock);
cur = q->members;
while(cur) {
if (user->member == cur) {
time(&cur->lastcall);
cur->calls++;
break;
}
cur = cur->next;
}
ast_pthread_mutex_unlock(&q->lock);
return 0;
}
static int calc_metric(struct ast_call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct localuser *tmp)
{ {
switch (q->strategy) { switch (q->strategy) {
case QUEUE_STRATEGY_RINGALL: case QUEUE_STRATEGY_RINGALL:
@ -626,11 +646,22 @@ static int calc_metric(struct ast_call_queue *q, int pos, struct queue_ent *qe,
q->wrapped = 1; q->wrapped = 1;
tmp->metric = pos; tmp->metric = pos;
} }
tmp->metric += tmp->penalty * 1000000; tmp->metric += mem->penalty * 1000000;
break; break;
case QUEUE_STRATEGY_RANDOM: case QUEUE_STRATEGY_RANDOM:
tmp->metric = rand() % 1000; tmp->metric = rand() % 1000;
tmp->metric += tmp->penalty * 1000000; tmp->metric += mem->penalty * 1000000;
break;
case QUEUE_STRATEGY_FEWESTCALLS:
tmp->metric = mem->calls;
tmp->metric += mem->penalty * 1000000;
break;
case QUEUE_STRATEGY_LEASTRECENT:
if (!mem->lastcall)
tmp->metric = 0;
else
tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
tmp->metric += mem->penalty * 1000000;
break; break;
default: default:
ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy); ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
@ -650,6 +681,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
char restofit[AST_MAX_EXTENSION]; char restofit[AST_MAX_EXTENSION];
char *newnum; char *newnum;
struct ast_channel *peer; struct ast_channel *peer;
struct localuser *lpeer;
int res = 0, bridge = 0; int res = 0, bridge = 0;
int zapx = 2; int zapx = 2;
int x=0; int x=0;
@ -690,9 +722,9 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
} else } else
ast_log(LOG_DEBUG, "Simple queue (no URL)\n"); ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
tmp->member = cur; /* Never directly dereference! Could change on reload */
strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1); strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1);
strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1); strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1);
tmp->penalty = cur->penalty;
/* If we're dialing by extension, look at the extension to know what to dial */ /* If we're dialing by extension, look at the extension to know what to dial */
if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) { if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) {
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1); strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
@ -705,7 +737,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
if (!qe->parent->strategy) if (!qe->parent->strategy)
ring_entry(qe, tmp); ring_entry(qe, tmp);
else else
calc_metric(qe->parent, x++, qe, tmp); calc_metric(qe->parent, cur, x++, qe, tmp);
/* Put them in the list of outgoing thingies... We're ready now. /* Put them in the list of outgoing thingies... We're ready now.
XXX If we're forcibly removed, these outgoing calls won't get XXX If we're forcibly removed, these outgoing calls won't get
hung up XXX */ hung up XXX */
@ -724,7 +756,11 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
if (qe->parent->strategy) if (qe->parent->strategy)
ring_one(qe, outgoing); ring_one(qe, outgoing);
ast_pthread_mutex_unlock(&qe->parent->lock); ast_pthread_mutex_unlock(&qe->parent->lock);
peer = wait_for_answer(qe, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &digit); lpeer = wait_for_answer(qe, outgoing, &to, &allowredir_in, &allowredir_out, &allowdisconnect, &digit);
if (lpeer)
peer = lpeer->chan;
else
peer = NULL;
if (!peer) { if (!peer) {
if (to) { if (to) {
/* Musta gotten hung up */ /* Musta gotten hung up */
@ -750,6 +786,8 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
if (tmp->dataquality) zapx = 0; if (tmp->dataquality) zapx = 0;
ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0); ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&zapx,sizeof(char),0);
} }
/* Update parameters for the queue */
update_queue(qe->parent, lpeer);
hanguptree(outgoing, peer); hanguptree(outgoing, peer);
/* Stop music on hold */ /* Stop music on hold */
ast_moh_stop(qe->chan); ast_moh_stop(qe->chan);
@ -1270,6 +1308,7 @@ static int queues_show(int fd, int argc, char **argv)
int pos; int pos;
time_t now; time_t now;
char max[80]; char max[80];
char calls[80];
time(&now); time(&now);
if (argc != 2) if (argc != 2)
@ -1293,7 +1332,12 @@ static int queues_show(int fd, int argc, char **argv)
snprintf(max, sizeof(max), " with penalty %d", mem->penalty); snprintf(max, sizeof(max), " with penalty %d", mem->penalty);
else else
strcpy(max, ""); strcpy(max, "");
ast_cli(fd, " %s/%s%s\n", mem->tech, mem->loc, max); if (mem->calls) {
snprintf(calls, sizeof(calls), " has taken %d calls (last was %ld secs ago)",
mem->calls, time(NULL) - mem->lastcall);
} else
strcpy(calls, " has taken no calls yet");
ast_cli(fd, " %s/%s%s%s\n", mem->tech, mem->loc, max, calls);
} }
} else } else
ast_cli(fd, " No Members\n"); ast_cli(fd, " No Members\n");

@ -1303,7 +1303,7 @@ static int adsi_load_vmail(struct ast_channel *chan, int *useadsi)
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 0, "Listen", "Listen", "1", 1);
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 1, "Folder", "Folder", "2", 1);
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 2, "Advanced", "Advnced", "3", 1);
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "4", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 3, "Options", "Options", "0", 1);
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 4, "Help", "Help", "*", 1);
bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1); bytes += adsi_load_soft_key(buf + bytes, ADSI_KEY_APPS + 5, "Exit", "Exit", "#", 1);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DOWNLOAD);
@ -1446,6 +1446,7 @@ static void adsi_password(struct ast_channel *chan)
bytes += adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", ""); bytes += adsi_input_format(buf + bytes, 1, ADSI_DIR_FROM_LEFT, 0, "Password: ******", "");
bytes += adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT); bytes += adsi_input_control(buf + bytes, ADSI_COMM_PAGE, 4, 0, 1, ADSI_JUST_LEFT);
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1473,6 +1474,8 @@ static void adsi_folders(struct ast_channel *chan, int start, char *label)
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", ""); bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 2, ADSI_JUST_CENT, 0, " ", "");
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1); bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1559,6 +1562,8 @@ static void adsi_message(struct ast_channel *chan, char *folder, int msg, int la
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, ""); bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_LEFT, 0, datetime, "");
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1); bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1602,6 +1607,8 @@ static void adsi_delete(struct ast_channel *chan, int msg, int last, int deleted
/* Except "Exit" */ /* Except "Exit" */
keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5); keys[5] = ADSI_KEY_SKT | (ADSI_KEY_APPS + 5);
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1645,6 +1652,8 @@ static void adsi_status(struct ast_channel *chan, int new, int old, int lastmsg)
keys[0] = 1; keys[0] = 1;
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1683,6 +1692,8 @@ static void adsi_status2(struct ast_channel *chan, char *folder, int messages)
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1); bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_set_keys(buf + bytes, keys); bytes += adsi_set_keys(buf + bytes, keys);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1694,6 +1705,8 @@ static void adsi_clear(struct ast_channel *chan)
if (!adsi_available(chan)) if (!adsi_available(chan))
return; return;
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1); bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -1708,6 +1721,8 @@ static void adsi_goodbye(struct ast_channel *chan)
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", ""); bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_LEFT, 0, " ", "");
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", ""); bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Goodbye", "");
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1); bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY); adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
} }
@ -2399,6 +2414,18 @@ static int vm_options(struct ast_channel *chan, struct ast_vm_user *vmu, struct
char newpassword[80] = ""; char newpassword[80] = "";
char newpassword2[80] = ""; char newpassword2[80] = "";
char prefile[256]=""; char prefile[256]="";
char buf[256];
int bytes=0;
if (adsi_available(chan))
{
bytes += adsi_logo(buf + bytes);
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 3, ADSI_JUST_CENT, 0, "Options Menu", "");
bytes += adsi_display(buf + bytes, ADSI_COMM_PAGE, 4, ADSI_JUST_CENT, 0, "Not Done", "");
bytes += adsi_set_line(buf + bytes, ADSI_COMM_PAGE, 1);
bytes += adsi_voice_mode(buf + bytes, 0);
adsi_transmit_message(chan, buf, bytes, ADSI_MSG_DISPLAY);
}
while((cmd >= 0) && (cmd != 't')) { while((cmd >= 0) && (cmd != 't')) {
if (cmd) if (cmd)
retries = 0; retries = 0;
@ -2723,6 +2750,8 @@ static int vm_execmain(struct ast_channel *chan, void *data)
break; break;
case '0': case '0':
cmd = vm_options(chan, vmu, &vms, vmfmts); cmd = vm_options(chan, vmu, &vms, vmfmts);
if (useadsi)
adsi_status(chan, vms.newmessages, vms.oldmessages, vms.lastmsg);
break; break;
default: /* Nothing */ default: /* Nothing */
cmd = vm_instructions(chan, &vms); cmd = vm_instructions(chan, &vms);

@ -29,8 +29,8 @@
; ;
; ringall - ring all available channels until one answers (default) ; ringall - ring all available channels until one answers (default)
; roundrobin - take turns ringing each available interface ; roundrobin - take turns ringing each available interface
; leastrecent - ring interface which least recently had a call ; leastrecent - ring interface which was least recently called by this queue
; fewestcalls - ring interface which has had fewest completed calls ; fewestcalls - ring the one with fewest completed calls from this queue
; random - ring random interface ; random - ring random interface
; ;
;strategy = ringall ;strategy = ringall

Loading…
Cancel
Save