Try immediately logged in agents first, then callbacklogin ones
[asterisk/asterisk.git] / channels / chan_agent.c
index 8142387..466181c 100755 (executable)
@@ -78,6 +78,7 @@ static int capability = -1;
 static unsigned int group;
 static int autologoff;
 static int wrapuptime;
+static int ackcall;
 
 static int usecnt =0;
 static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER;
@@ -91,6 +92,7 @@ static struct agent_pvt {
        int pending;                                            /* Not a real agent -- just pending a match */
        int abouttograb;                                        /* About to grab */
        int autologoff;                                 /* Auto timeout time */
+       int ackcall;                                    /* ackcall */
        time_t start;                                           /* When call started */
        struct timeval lastdisc;                        /* When last disconnected */
        int wrapuptime;                                         /* Wrapup time in ms */
@@ -185,6 +187,7 @@ static struct agent_pvt *add_agent(char *agent, int pending)
        strncpy(p->password, password ? password : "", sizeof(p->password) - 1);
        strncpy(p->name, name ? name : "", sizeof(p->name) - 1);
        strncpy(p->moh, moh, sizeof(p->moh) - 1);
+       p->ackcall = ackcall;
        p->autologoff = autologoff;
        p->wrapuptime = wrapuptime;
        if (pending)
@@ -234,14 +237,22 @@ static struct ast_frame  *agent_read(struct ast_channel *ast)
                        if (strlen(p->loginchan))
                                ast_hangup(p->chan);
                        p->chan = NULL;
+                       p->acknowledged = 0;
                }
        }
        if (f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
+/* TC */
+       if (p->ackcall) {
                if (option_verbose > 2)
                        ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
                /* Don't pass answer along */
                ast_frfree(f);
                f = &null_frame;
+        }
+        else {
+               p->acknowledged = 1;
+               f = &answer_frame;
+        }
        }
        if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
                if (!p->acknowledged) {
@@ -575,6 +586,7 @@ static int read_agent_config(void)
        group = 0;
        autologoff = 0;
        wrapuptime = 0;
+       ackcall = 1;
        cfg = ast_load(config);
        if (!cfg) {
                ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");
@@ -598,6 +610,8 @@ static int read_agent_config(void)
                        autologoff = atoi(v->value);
                        if (autologoff < 0)
                                autologoff = 0;
+               } else if (!strcasecmp(v->name, "ackcall")) {
+                        ackcall = ast_true(v->value);
                } else if (!strcasecmp(v->name, "wrapuptime")) {
                        wrapuptime = atoi(v->value);
                        if (wrapuptime < 0)
@@ -712,12 +726,14 @@ static struct ast_channel *agent_request(char *type, int format, void *data)
        } else {
                groupmatch = 0;
        }
+
+       /* Check actual logged in agents first */
        ast_pthread_mutex_lock(&agentlock);
        p = agents;
        while(p) {
                ast_pthread_mutex_lock(&p->lock);
                if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
-                               !p->lastdisc.tv_sec) {
+                               !p->lastdisc.tv_sec && !strlen(p->loginchan)) {
                        /* Agent must be registered, but not have any active call, and not be in a waiting state */
                        if (!p->owner && p->chan) {
                                /* Fixed agent */
@@ -736,6 +752,32 @@ static struct ast_channel *agent_request(char *type, int format, void *data)
                ast_pthread_mutex_unlock(&p->lock);
                p = p->next;
        }
+       if (!p) {
+               p = agents;
+               while(p) {
+                       ast_pthread_mutex_lock(&p->lock);
+                       if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
+                                       !p->lastdisc.tv_sec) {
+                               /* Agent must be registered, but not have any active call, and not be in a waiting state */
+                               if (!p->owner && p->chan) {
+                                       /* Fixed agent */
+                                       chan = agent_new(p, AST_STATE_DOWN);
+                               } else if (!p->owner && strlen(p->loginchan)) {
+                                       /* Adjustable agent */
+                                       p->chan = ast_request("Local", format, p->loginchan);
+                                       if (p->chan)
+                                               chan = agent_new(p, AST_STATE_DOWN);
+                               }
+                               if (chan) {
+                                       ast_pthread_mutex_unlock(&p->lock);
+                                       break;
+                               }
+                       }
+                       ast_pthread_mutex_unlock(&p->lock);
+                       p = p->next;
+               }
+       }
+
        if (!chan && waitforagent) {
                /* No agent available -- but we're requesting to wait for one.
                   Allocate a place holder */
@@ -904,7 +946,7 @@ static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
                                                        /* Retrieve login chan */
                                                        res = ast_app_getdata(chan, "agent-newlocation", tmpchan, sizeof(tmpchan) - 1, 0);
                                                        if (!res) {
-                                                               if (context && strlen(context))
+                                                               if (context && strlen(context) && strlen(tmpchan))
                                                                        snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context);
                                                                else
                                                                        strncpy(p->loginchan, tmpchan, sizeof(p->loginchan) - 1);