Add dynamic agent stuff, still missing audio files

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@1178 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.0
Mark Spencer 23 years ago
parent 29aeb9d959
commit d0e69f8c6e

@ -49,8 +49,10 @@ static char *tdesc = "Call Agent Proxy Channel";
static char *config = "agents.conf"; static char *config = "agents.conf";
static char *app = "AgentLogin"; static char *app = "AgentLogin";
static char *app2 = "AgentCallbackLogin";
static char *synopsis = "Call agent login"; static char *synopsis = "Call agent login";
static char *synopsis2 = "Call agent callback login";
static char *descrip = static char *descrip =
" AgentLogin([AgentNo][|options]):\n" " AgentLogin([AgentNo][|options]):\n"
@ -61,6 +63,12 @@ static char *descrip =
"The option string may contain zero or more of the following characters:\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\n";
static char *descrip2 =
" AgentCallbackLogin([AgentNo][|@context]):\n"
"Asks the agent to login to the system with callback. Always returns -1.\n"
"The agent's callback extension is called (optionally with the specified\n"
"context. \n";
static char moh[80] = "default"; static char moh[80] = "default";
#define AST_MAX_AGENT 80 /* Agent ID or Password max length */ #define AST_MAX_AGENT 80 /* Agent ID or Password max length */
@ -81,6 +89,7 @@ static struct agent_pvt {
int pending; /* Not a real agent -- just pending a match */ int pending; /* Not a real agent -- just pending a match */
int abouttograb; /* About to grab */ int abouttograb; /* About to grab */
unsigned int group; /* Group memberships */ unsigned int group; /* Group memberships */
int acknowledged; /* Acknowledged */
char moh[80]; /* Which music on hold */ char moh[80]; /* Which music on hold */
char agent[AST_MAX_AGENT]; /* Agent ID */ char agent[AST_MAX_AGENT]; /* Agent ID */
char password[AST_MAX_AGENT]; /* Password for Agent login */ char password[AST_MAX_AGENT]; /* Password for Agent login */
@ -89,6 +98,7 @@ static struct agent_pvt {
volatile pthread_t owning_app; /* Owning application thread id */ volatile pthread_t owning_app; /* Owning application thread id */
volatile int app_sleep_cond; /* Sleep condition for the login app */ volatile int app_sleep_cond; /* Sleep condition for the login app */
struct ast_channel *owner; /* Agent */ struct ast_channel *owner; /* Agent */
char loginchan[80];
struct ast_channel *chan; /* Channel we use */ struct ast_channel *chan; /* Channel we use */
struct agent_pvt *next; /* Agent */ struct agent_pvt *next; /* Agent */
} *agents = NULL; } *agents = NULL;
@ -204,6 +214,7 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
struct agent_pvt *p = ast->pvt->pvt; struct agent_pvt *p = ast->pvt->pvt;
struct ast_frame *f = NULL; struct ast_frame *f = NULL;
static struct ast_frame null_frame = { AST_FRAME_NULL, }; static struct ast_frame null_frame = { AST_FRAME_NULL, };
static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
ast_pthread_mutex_lock(&p->lock); ast_pthread_mutex_lock(&p->lock);
if (p->chan) if (p->chan)
f = ast_read(p->chan); f = ast_read(p->chan);
@ -214,6 +225,18 @@ static struct ast_frame *agent_read(struct ast_channel *ast)
if (p->chan) if (p->chan)
p->chan = NULL; p->chan = NULL;
} }
if (f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
/* Don't pass answer along */
ast_frfree(f);
f = &null_frame;
}
if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
if (!p->acknowledged) {
p->acknowledged = 1;
ast_frfree(f);
f = &answer_frame;
}
}
if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
/* * terminates call */ /* * terminates call */
ast_frfree(f); ast_frfree(f);
@ -294,6 +317,14 @@ static int agent_call(struct ast_channel *ast, char *dest, int timeout)
} }
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
return res; return res;
} else if (strlen(p->loginchan)) {
/* Call on this agent */
if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
res = ast_call(p->chan, p->loginchan, 0);
CLEANUP(ast,p);
ast_pthread_mutex_unlock(&p->lock);
return res;
} }
ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name); ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language); ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language);
@ -338,11 +369,21 @@ static int agent_hangup(struct ast_channel *ast)
p->app_sleep_cond = 1; p->app_sleep_cond = 1;
if (p->chan) { if (p->chan) {
/* If they're dead, go ahead and hang up on the agent now */ /* If they're dead, go ahead and hang up on the agent now */
ast_pthread_mutex_lock(&p->chan->lock); if (strlen(p->loginchan)) {
if (p->dead) if (p->chan) {
/* Recognize the hangup and pass it along immediately */
ast_hangup(p->chan);
p->chan = NULL;
}
} else if (p->dead) {
ast_pthread_mutex_lock(&p->chan->lock);
ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
ast_moh_start(p->chan, p->moh); ast_pthread_mutex_unlock(&p->chan->lock);
ast_pthread_mutex_unlock(&p->chan->lock); } else {
ast_pthread_mutex_lock(&p->chan->lock);
ast_moh_start(p->chan, p->moh);
ast_pthread_mutex_unlock(&p->chan->lock);
}
} }
#if 0 #if 0
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
@ -629,10 +670,18 @@ static struct ast_channel *agent_request(char *type, int format, void *data)
if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
/* Agent must be registered, but not have any active call */ /* Agent must be registered, but not have any active call */
if (!p->owner && p->chan) { if (!p->owner && p->chan) {
/* Fixed agent */
chan = agent_new(p, AST_STATE_DOWN); 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);
break;
} }
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
p = p->next; p = p->next;
@ -691,6 +740,11 @@ static int agents_show(int fd, int argc, char **argv)
} else { } else {
strcpy(talkingto, " is idle"); strcpy(talkingto, " is idle");
} }
} else if (strlen(p->loginchan)) {
snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
strcpy(talkingto, "");
if (p->acknowledged)
strcat(location, " (Confirmed)");
} else { } else {
strcpy(location, "not logged in"); strcpy(location, "not logged in");
strcpy(talkingto, ""); strcpy(talkingto, "");
@ -716,7 +770,7 @@ static struct ast_cli_entry cli_show_agents = {
STANDARD_LOCAL_USER; STANDARD_LOCAL_USER;
LOCAL_USER_DECL; LOCAL_USER_DECL;
static int login_exec(struct ast_channel *chan, void *data) static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
{ {
int res=0; int res=0;
int tries = 0; int tries = 0;
@ -730,6 +784,7 @@ static int login_exec(struct ast_channel *chan, void *data)
char *opt_user = NULL; char *opt_user = NULL;
char *options = NULL; char *options = NULL;
int play_announcement; int play_announcement;
char *filename = "agent-loginok";
LOCAL_USER_ADD(u); LOCAL_USER_ADD(u);
@ -782,12 +837,26 @@ static int login_exec(struct ast_channel *chan, void *data)
if (!strcmp(p->agent, user) && if (!strcmp(p->agent, user) &&
!strcmp(p->password, pass) && !p->pending) { !strcmp(p->password, pass) && !p->pending) {
if (!p->chan) { if (!p->chan) {
if (callbackmode) {
char tmpchan[256] = "";
/* Retrieve login chan */
res = ast_app_getdata(chan, "agent-newlocation", tmpchan, sizeof(tmpchan) - 1, 0);
if (!res) {
strncpy(p->loginchan, tmpchan, sizeof(p->loginchan) - 1);
if (!strlen(p->loginchan))
filename = "agent-loggedoff";
p->acknowledged = 0;
}
} else {
strcpy(p->loginchan, "");
p->acknowledged = 0;
}
play_announcement = 1; play_announcement = 1;
if( options ) if( options )
if( strchr( options, 's' ) ) if( strchr( options, 's' ) )
play_announcement = 0; play_announcement = 0;
if( play_announcement ) if( play_announcement )
res = ast_streamfile(chan, "agent-loginok", chan->language); res = ast_streamfile(chan, filename, chan->language);
if (!res) if (!res)
ast_waitstream(chan, ""); ast_waitstream(chan, "");
if (!res) { if (!res) {
@ -803,7 +872,18 @@ static int login_exec(struct ast_channel *chan, void *data)
/* Check once more just in case */ /* Check once more just in case */
if (p->chan) if (p->chan)
res = -1; res = -1;
if (!res) { if (callbackmode && !res) {
/* Just say goodbye and be done with it */
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_pthread_mutex_unlock(&p->lock);
ast_pthread_mutex_unlock(&agentlock);
} else if (!res) {
/* check if the moh class was changed with setmusiconhold */ /* check if the moh class was changed with setmusiconhold */
if (*(chan->musicclass)) if (*(chan->musicclass))
strncpy(p->moh, chan->musicclass, sizeof(p->moh) - 1); strncpy(p->moh, chan->musicclass, sizeof(p->moh) - 1);
@ -818,6 +898,7 @@ static int login_exec(struct ast_channel *chan, void *data)
/* Login this channel and wait for it to /* Login this channel and wait for it to
go away */ go away */
p->chan = chan; p->chan = chan;
p->acknowledged = 1;
check_availability(p, 0); check_availability(p, 0);
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
ast_pthread_mutex_unlock(&agentlock); ast_pthread_mutex_unlock(&agentlock);
@ -847,6 +928,7 @@ static int login_exec(struct ast_channel *chan, void *data)
/* Log us off if appropriate */ /* Log us off if appropriate */
if (p->chan == chan) if (p->chan == chan)
p->chan = NULL; p->chan = NULL;
p->acknowledged = 0;
ast_pthread_mutex_unlock(&p->lock); ast_pthread_mutex_unlock(&p->lock);
if (option_verbose > 2) if (option_verbose > 2)
ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent); ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent);
@ -884,6 +966,15 @@ static int login_exec(struct ast_channel *chan, void *data)
return -1; return -1;
} }
static int login_exec(struct ast_channel *chan, void *data)
{
return __login_exec(chan, data, 0);
}
static int callback_exec(struct ast_channel *chan, void *data)
{
return __login_exec(chan, data, 1);
}
int load_module() int load_module()
{ {
@ -893,6 +984,7 @@ int load_module()
return -1; return -1;
} }
ast_register_application(app, login_exec, synopsis, descrip); ast_register_application(app, login_exec, synopsis, descrip);
ast_register_application(app2, callback_exec, synopsis2, descrip2);
ast_cli_register(&cli_show_agents); ast_cli_register(&cli_show_agents);
/* Read in the config */ /* Read in the config */
read_agent_config(); read_agent_config();
@ -911,6 +1003,7 @@ int unload_module()
/* First, take us out of the channel loop */ /* First, take us out of the channel loop */
ast_cli_unregister(&cli_show_agents); ast_cli_unregister(&cli_show_agents);
ast_unregister_application(app); ast_unregister_application(app);
ast_unregister_application(app2);
ast_channel_unregister(type); ast_channel_unregister(type);
if (!ast_pthread_mutex_lock(&agentlock)) { if (!ast_pthread_mutex_lock(&agentlock)) {
/* Hangup all interfaces if they have an owner */ /* Hangup all interfaces if they have an owner */

@ -8,6 +8,10 @@
%agent-incorrect.gsm%Login incorrect. Please enter your agent number followed by the pound key. %agent-incorrect.gsm%Login incorrect. Please enter your agent number followed by the pound key.
%agent-newlocation.gsm%Please enter new extension followed by pound, or just press pound for immediate service.
%agent-loggedoff.gsm%Agent Logged off.
%agent-loginok.gsm%Agent logged in. %agent-loginok.gsm%Agent logged in.
%agent-pass.gsm%Please enter your password followed by the pound key. %agent-pass.gsm%Please enter your password followed by the pound key.

Loading…
Cancel
Save