Start on queueing strategies

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1226 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 22 years ago
parent 70f306e8d8
commit 7a594ca15d

@ -37,6 +37,12 @@
#include <pthread.h>
#define QUEUE_STRATEGY_RINGALL 0
#define QUEUE_STRATEGY_ROUNDROBIN 1
#define QUEUE_STRATEGY_LEASTRECENT 2
#define QUEUE_STRATEGY_FEWESTCALLS 3
#define QUEUE_STRATEGY_RANDOM 4
#define DEFAULT_RETRY 5
#define DEFAULT_TIMEOUT 15
#define RECHECK 1 /* Recheck every second to see we we're at the top yet */
@ -91,7 +97,10 @@ static char *app_rqm_descrip =
struct localuser {
struct ast_channel *chan;
char numsubst[256];
char tech[40];
int stillgoing;
int metric;
int allowredirect_in;
int allowredirect_out;
int ringbackonly;
@ -117,6 +126,7 @@ struct queue_ent {
struct member {
char tech[80]; /* Technology */
char loc[256]; /* Location */
struct timeval lastcall; /* When last successful call was hungup */
struct member *next; /* Next member */
};
@ -126,6 +136,7 @@ struct ast_call_queue {
char moh[80]; /* Name of musiconhold to be used */
char announce[80]; /* Announcement to play */
char context[80]; /* Announcement to play */
int strategy; /* Queueing strategy */
int announcetimeout; /* How often to announce their position */
int count; /* How many entries are in the queue */
int maxlen; /* Max number of entries in queue */
@ -274,7 +285,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception
struct localuser *oo;
while(outgoing) {
/* Hangup any existing lines we have open */
if (outgoing->chan != exception)
if (outgoing->chan && (outgoing->chan != exception))
ast_hangup(outgoing->chan);
oo = outgoing;
outgoing=outgoing->next;
@ -306,7 +317,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu
watchers[0] = in;
while(o) {
/* Keep track of important channels */
if (o->stillgoing) {
if (o->stillgoing && o->chan) {
watchers[pos++] = o->chan;
found = 1;
}
@ -439,6 +450,65 @@ static int wait_our_turn(struct queue_ent *qe)
return res;
}
static int ring_entry(struct queue_ent *qe, struct localuser *tmp)
{
int res;
/* Request the peer */
tmp->chan = ast_request(tmp->tech, qe->chan->nativeformats, tmp->numsubst);
if (!tmp->chan) { /* If we can't, just go on to the next call */
#if 0
ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech);
#endif
if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr);
tmp->stillgoing = 0;
return 0;
}
tmp->chan->appl = "AppQueue";
tmp->chan->data = "(Outgoing Line)";
tmp->chan->whentohangup = 0;
if (tmp->chan->callerid)
free(tmp->chan->callerid);
if (tmp->chan->ani)
free(tmp->chan->ani);
if (qe->chan->callerid)
tmp->chan->callerid = strdup(qe->chan->callerid);
else
tmp->chan->callerid = NULL;
if (qe->chan->ani)
tmp->chan->ani = strdup(qe->chan->ani);
else
tmp->chan->ani = NULL;
/* Presense of ADSI CPE on outgoing channel follows ours */
tmp->chan->adsicpe = qe->chan->adsicpe;
/* Place the call, but don't wait on the answer */
res = ast_call(tmp->chan, tmp->numsubst, 0);
if (res) {
/* Again, keep going even if there's an error */
if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", tmp->numsubst);
ast_hangup(tmp->chan);
tmp->chan = NULL;
tmp->stillgoing = 0;
return 0;
} else
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", tmp->numsubst);
return 0;
}
static int calc_metric(struct ast_call_queue *q, struct queue_ent *qe, struct localuser *tmp)
{
switch (q->strategy) {
case QUEUE_STRATEGY_RINGALL:
ast_log(LOG_WARNING, "Can't calculate metric for ringall strategy\n");
break;
}
return 0;
}
static int try_calling(struct queue_ent *qe, char *options, char *announceoverride, char *url)
{
struct member *cur;
@ -447,7 +517,6 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
int allowredir_in=0;
int allowredir_out=0;
int allowdisconnect=0;
char numsubst[AST_MAX_EXTENSION];
char restofit[AST_MAX_EXTENSION];
char *newnum;
struct ast_channel *peer;
@ -469,6 +538,7 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
goto out;
}
memset(tmp, 0, sizeof(struct localuser));
tmp->stillgoing = -1;
if (options) {
if (strchr(options, 't'))
tmp->allowredirect_in = 1;
@ -488,83 +558,28 @@ static int try_calling(struct queue_ent *qe, char *options, char *announceoverri
} else
ast_log(LOG_DEBUG, "Simple queue (no URL)\n");
strncpy(numsubst, cur->loc, sizeof(numsubst)-1);
strncpy(tmp->tech, cur->tech, sizeof(tmp->tech)-1);
strncpy(tmp->numsubst, cur->loc, sizeof(tmp->numsubst)-1);
/* If we're dialing by extension, look at the extension to know what to dial */
if ((newnum = strstr(numsubst, "BYEXTENSION"))) {
if ((newnum = strstr(tmp->numsubst, "BYEXTENSION"))) {
strncpy(restofit, newnum + strlen("BYEXTENSION"), sizeof(restofit)-1);
snprintf(newnum, sizeof(numsubst) - (newnum - numsubst), "%s%s", qe->chan->exten,restofit);
snprintf(newnum, sizeof(tmp->numsubst) - (newnum - tmp->numsubst), "%s%s", qe->chan->exten,restofit);
if (option_debug)
ast_log(LOG_DEBUG, "Dialing by extension %s\n", numsubst);
}
/* Request the peer */
tmp->chan = ast_request(cur->tech, qe->chan->nativeformats, numsubst);
if (!tmp->chan) {
/* If we can't, just go on to the next call */
#if 0
ast_log(LOG_NOTICE, "Unable to create channel of type '%s'\n", cur->tech);
#endif
if (qe->chan->cdr)
ast_cdr_busy(qe->chan->cdr);
free(tmp);
cur = cur->next;
continue;
}
#if 0
/* Don't honor call forwarding on a queue! */
if (strlen(tmp->chan->call_forward)) {
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Forwarding call to '%s@%s'\n", tmp->chan->call_forward, tmp->chan->context);
/* Setup parameters */
strncpy(chan->exten, tmp->chan->call_forward, sizeof(chan->exten));
strncpy(chan->context, tmp->chan->context, sizeof(chan->context));
chan->priority = 0;
to = 0;
ast_hangup(tmp->chan);
free(tmp);
cur = rest;
break;
ast_log(LOG_DEBUG, "Dialing by extension %s\n", tmp->numsubst);
}
#endif
tmp->chan->appl = "AppQueue";
tmp->chan->data = "(Outgoing Line)";
tmp->chan->whentohangup = 0;
if (tmp->chan->callerid)
free(tmp->chan->callerid);
if (tmp->chan->ani)
free(tmp->chan->ani);
if (qe->chan->callerid)
tmp->chan->callerid = strdup(qe->chan->callerid);
else
tmp->chan->callerid = NULL;
if (qe->chan->ani)
tmp->chan->ani = strdup(qe->chan->ani);
/* Special case: If we ring everyone, go ahead and ring them, otherwise
just calculate their metric for the appropriate strategy */
if (!qe->parent->strategy)
ring_entry(qe, tmp);
else
tmp->chan->ani = NULL;
/* Presense of ADSI CPE on outgoing channel follows ours */
tmp->chan->adsicpe = qe->chan->adsicpe;
/* Place the call, but don't wait on the answer */
res = ast_call(tmp->chan, numsubst, 0);
if (res) {
/* Again, keep going even if there's an error */
if (option_debug)
ast_log(LOG_DEBUG, "ast call on peer returned %d\n", res);
else if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Couldn't call %s\n", numsubst);
ast_hangup(tmp->chan);
free(tmp);
cur = cur->next;
continue;
} else
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Called %s\n", numsubst);
calc_metric(qe->parent, qe, tmp);
/* Put them in the list of outgoing thingies... We're ready now.
XXX If we're forcibly removed, these outgoing calls won't get
hung up XXX */
tmp->stillgoing = -1;
tmp->next = outgoing;
outgoing = tmp;
/* If this line is up, don't try anybody else */
if (outgoing->chan->_state == AST_STATE_UP)
if (outgoing->chan && (outgoing->chan->_state == AST_STATE_UP))
break;
cur = cur->next;

Loading…
Cancel
Save