Index: asterisk/channels/chan_agent.c =================================================================== RCS file: /usr/cvsroot/asterisk/channels/chan_agent.c,v retrieving revision 1.83 diff -u -r1.83 chan_agent.c --- asterisk/channels/chan_agent.c 3 Oct 2004 04:19:58 -0000 1.83 +++ asterisk/channels/chan_agent.c 14 Oct 2004 13:07:11 -0000 @@ -63,13 +63,17 @@ "when a new call comes in. The agent can dump the call by pressing\n" "the star key.\n" "The option string may contain zero or more of the following characters:\n" -" 's' -- silent login - do not announce the login ok segment\n"; +" 's' -- silent login - do not announce the login ok segment after agent logged in/off\n"; static char *descrip2 = " AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n" -"Asks the agent to login to the system with callback. Always returns -1.\n" +"Asks the agent to login to the system with callback.\n" "The agent's callback extension is called (optionally with the specified\n" -"context. \n"; +"context). \n" +"The option string may contain zero or more of the following characters:\n" +" 's' -- silent login - do not announce the login ok segment agent logged in/off\n"; + + static char *descrip3 = " AgentMonitorOutgoing([options]):\n" @@ -81,6 +85,7 @@ #define AST_MAX_AGENT 80 /* Agent ID or Password max length */ #define AST_MAX_BUF 256 +#define AST_MAX_FILENAME_LEN 256 static int capability = -1; @@ -89,6 +94,9 @@ static int wrapuptime; static int ackcall; +static int maxlogintries = 3; +static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye"; + static int usecnt =0; AST_MUTEX_DEFINE_STATIC(usecnt_lock); @@ -835,6 +843,12 @@ wrapuptime = atoi(v->value); if (wrapuptime < 0) wrapuptime = 0; + } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { + maxlogintries = atoi(v->value); + if (maxlogintries < 0) + maxlogintries = 0; + } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { + strcpy(agentgoodbye,v->value); } else if (!strcasecmp(v->name, "musiconhold")) { strncpy(moh, v->value, sizeof(moh) - 1); } else if (!strcasecmp(v->name, "updatecdr")) { @@ -1172,9 +1186,11 @@ { int res=0; int tries = 0; + int max_login_tries = maxlogintries; struct agent_pvt *p; struct localuser *u; struct timeval tv; + int login_state = 0; char user[AST_MAX_AGENT] = ""; char pass[AST_MAX_AGENT]; char agent[AST_MAX_AGENT] = ""; @@ -1183,9 +1199,15 @@ char info[512]; char *opt_user = NULL; char *options = NULL; + char option; + char badoption[2]; + char *tmpoptions = NULL; char *context = NULL; char *exten = NULL; - int play_announcement; + int play_announcement = 1; + char agent_goodbye[AST_MAX_FILENAME_LEN]; + strcpy(agent_goodbye, agentgoodbye); + int update_cdr = updatecdr; char *filename = "agent-loginok"; LOCAL_USER_ADD(u); @@ -1193,7 +1215,30 @@ /* Parse the arguments XXX Check for failure XXX */ strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1); opt_user = info; - if( opt_user ) { + /* Set Channel Specific Login Overrides */ + if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { + max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); + if (max_login_tries < 0) + max_login_tries = 0; + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTMAXLOGINTRIES=%s, setting max_login_tries to: %d on Channel '%s'.\n",tmpoptions,max_login_tries,chan->name); + } + if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && strlen(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { + if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) + update_cdr = 1; + else + update_cdr = 0; + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); + } + if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && strlen(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { + strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); + } + /* End Channel Specific Login Overrides */ + /* Read command line options */ + if( opt_user ) { options = strchr(opt_user, '|'); if (options) { *options = '\0'; @@ -1210,7 +1255,22 @@ exten = NULL; } } + if ( options ) { + while (*options) { + option = (char)options[0]; + if (option=='s') + play_announcement = 0; + else { + badoption[0] = option; + badoption[1] = '\0'; + tmpoptions=badoption; + ast_verbose(VERBOSE_PREFIX_3 "Warning: option %s is unknown.\n",tmpoptions); + } + options++; + } + } } + /* End command line options */ if (chan->_state != AST_STATE_UP) res = ast_answer(chan); @@ -1220,7 +1280,8 @@ else res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); } - while (!res && (tries < 3)) { + while (!res && (max_login_tries==0 || tries < max_login_tries)) { + tries++; /* Check for password */ ast_mutex_lock(&agentlock); p = agents; @@ -1249,6 +1310,33 @@ ast_mutex_lock(&p->lock); if (!strcmp(p->agent, user) && !strcmp(p->password, pass) && !p->pending) { + login_state = 1; /* Successful Login */ + /* Set Channel Specific Agent Overides */ + if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { + if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) + p->ackcall = 2; + else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) + p->ackcall = 1; + else + p->ackcall = 0; + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); + } + if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { + p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); + if (p->autologoff < 0) + p->autologoff = 0; + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); + } + if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { + p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); + if (p->wrapuptime < 0) + p->wrapuptime = 0; + tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); + ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); + } + /* End Channel Specific Agent Overides */ if (!p->chan) { char last_loginchan[80] = ""; long logintime; @@ -1285,6 +1373,7 @@ } } } + exten = tmpchan; if (!res) { if (context && !ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); @@ -1292,8 +1381,10 @@ strncpy(last_loginchan, p->loginchan, sizeof(last_loginchan) - 1); strncpy(p->loginchan, tmpchan, sizeof(p->loginchan) - 1); } - if (ast_strlen_zero(p->loginchan)) + if (ast_strlen_zero(p->loginchan)) { + login_state = 2; filename = "agent-loggedoff"; + } p->acknowledged = 0; /* store/clear the global variable that stores agentid based on the callerid */ if (chan->cid.cid_num) { @@ -1304,7 +1395,7 @@ else pbx_builtin_setvar_helper(NULL, agentvar, p->agent); } - if(updatecdr && chan->cdr) + if(update_cdr && chan->cdr) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); } @@ -1312,13 +1403,9 @@ p->loginchan[0] = '\0'; p->acknowledged = 0; } - play_announcement = 1; - if( options ) - if( strchr( options, 's' ) ) - play_announcement = 0; ast_mutex_unlock(&p->lock); ast_mutex_unlock(&agentlock); - if( !res && play_announcement ) + if( !res && play_announcement==1 ) res = ast_streamfile(chan, filename, chan->language); if (!res) ast_waitstream(chan, ""); @@ -1366,11 +1453,6 @@ ast_mutex_unlock(&agentlock); if (!res) res = ast_safe_sleep(chan, 500); - res = ast_streamfile(chan, "vm-goodbye", chan->language); - if (!res) - res = ast_waitstream(chan, ""); - if (!res) - res = ast_safe_sleep(chan, 1000); ast_mutex_unlock(&p->lock); } else if (!res) { #ifdef HONOR_MUSIC_CLASS @@ -1386,7 +1468,7 @@ "Channel: %s\r\n" "Uniqueid: %s\r\n", p->agent, chan->name, chan->uniqueid); - if (updatecdr && chan->cdr) + if (update_cdr && chan->cdr) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); if (option_verbose > 2) @@ -1491,13 +1573,49 @@ if (!p) ast_mutex_unlock(&agentlock); - if (!res) + if (!res && (max_login_tries==0 || tries < max_login_tries)) res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); } LOCAL_USER_REMOVE(u); - /* Always hangup */ - return -1; + if (!res) + res = ast_safe_sleep(chan, 500); + + /* AgentLogin() exit */ + if (!callbackmode) { + return -1; + } + /* AgentCallbackLogin() exit*/ + else { + /* Set variables */ + if (login_state > 0) { + pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); + if (login_state==1) { + pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); + pbx_builtin_setvar_helper(chan, "AGENTEXTEN", exten); + } + else { + pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); + } + } + else { + pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); + } + if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) + return 0; + /* Do we need to play agent-goodbye now that we will be hanging up? */ + if (play_announcement==1) { + if (!res) + res = ast_safe_sleep(chan, 1000); + res = ast_streamfile(chan, agent_goodbye, chan->language); + if (!res) + res = ast_waitstream(chan, ""); + if (!res) + res = ast_safe_sleep(chan, 1000); + } + } + /* We should never get here if next priority exists when in callbackmode */ + return -1; } static int login_exec(struct ast_channel *chan, void *data)