From 105b71e71066741528ca346dd88edc98355a06d2 Mon Sep 17 00:00:00 2001 From: Mark Spencer Date: Mon, 2 Sep 2002 15:20:28 +0000 Subject: [PATCH] Version 0.2.0 from FTP git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@512 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- Makefile | 18 +- apps/app_dial.c | 50 ++- channels/Makefile | 3 +- channels/chan_agent.c | 611 ++++++++++++++++++++++++++++++++++++ configs/agents.conf.sample | 11 + configs/manager.conf.sample | 12 + include/asterisk/manager.h | 52 +++ sounds/agent-alreadyon.gsm | Bin 0 -> 8349 bytes sounds/agent-incorrect.gsm | Bin 0 -> 6798 bytes sounds/agent-loginok.gsm | Bin 0 -> 5082 bytes sounds/agent-pass.gsm | Bin 0 -> 6930 bytes sounds/agent-user.gsm | Bin 0 -> 8580 bytes 12 files changed, 739 insertions(+), 18 deletions(-) create mode 100755 channels/chan_agent.c create mode 100755 configs/agents.conf.sample create mode 100755 configs/manager.conf.sample create mode 100755 include/asterisk/manager.h create mode 100755 sounds/agent-alreadyon.gsm create mode 100755 sounds/agent-incorrect.gsm create mode 100755 sounds/agent-loginok.gsm create mode 100755 sounds/agent-pass.gsm create mode 100755 sounds/agent-user.gsm diff --git a/Makefile b/Makefile index 0dc248632a..21d916b03c 100755 --- a/Makefile +++ b/Makefile @@ -28,8 +28,8 @@ PROC=$(shell uname -m) DEBUG=-g #-pg INCLUDE=-Iinclude -I../include -CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations -O6 $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE -#CFLAGS+=-Werror +CFLAGS=-pipe -Wall -Wmissing-prototypes -Wmissing-declarations $(DEBUG) $(INCLUDE) -D_REENTRANT -D_GNU_SOURCE #-DMAKE_VALGRIND_HAPPY +CFLAGS+=-O6 CFLAGS+=$(shell if $(CC) -march=$(PROC) -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then echo "-march=$(PROC)"; fi) CFLAGS+=$(shell if uname -m | grep -q ppc; then echo "-fsigned-char"; fi) @@ -42,12 +42,12 @@ CFLAGS+= -DDO_CRASH -DDEBUG_THREADS # Uncomment next one to enable ast_frame tracing (for debugging) #CLFAGS+= -DTRACE_FRAMES CFLAGS+=# -fomit-frame-pointer -SUBDIRS=res channels pbx apps codecs formats agi cdr +SUBDIRS=res channels pbx apps codecs formats agi cdr astman LIBS=-ldl -lpthread -lreadline -lncurses -lm #-lnjamd OBJS=io.o sched.o logger.o frame.o loader.o config.o channel.o \ translate.o file.o say.o pbx.o cli.o md5.o term.o \ ulaw.o alaw.o callerid.o fskmodem.o image.o app.o \ - cdr.o tdd.o acl.o rtp.o asterisk.o + cdr.o tdd.o acl.o rtp.o manager.o asterisk.o ast_expr.o chanvars.o CC=gcc INSTALL=install @@ -67,6 +67,11 @@ _version: .version: _version +.y.c: + bison $< --name-prefix=ast_yy -o $@ + +ast_expr.o: ast_expr.c + build.h: ./make_build_h @@ -79,14 +84,15 @@ subdirs: clean: for x in $(SUBDIRS); do $(MAKE) -C $$x clean || exit 1 ; done rm -f *.o *.so asterisk - rm -f build.h + rm -f build.h + rm -f ast_expr.c datafiles: all mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits for x in sounds/digits/*; do \ install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds/digits ; \ done - for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-*; do \ + for x in sounds/vm-* sounds/transfer* sounds/pbx-* sounds/ss-* sounds/beep* sounds/dir-* sounds/conf-* sounds/agent-*; do \ install $$x $(INSTALL_PREFIX)/var/lib/asterisk/sounds ; \ done mkdir -p $(INSTALL_PREFIX)/var/lib/asterisk/mohmp3 diff --git a/apps/app_dial.c b/apps/app_dial.c index 20db11b0f1..ee49dc2bd9 100755 --- a/apps/app_dial.c +++ b/apps/app_dial.c @@ -61,6 +61,8 @@ static char *descrip = " 'T' -- to allow the calling user to transfer the call.\n" " 'r' -- indicate ringing to the calling party, pass no audio until answered.\n" " 'm' -- provide hold music to the calling party until answered.\n" +" 'd' -- data-quality (modem) call (minimum delay).\n" +" 'H' -- allow caller to hang up by hitting *.\n" " In addition to transferring the call, a call may be parked and then picked\n" "up by another user.\n"; @@ -74,6 +76,8 @@ struct localuser { int allowredirect; int ringbackonly; int musiconhold; + int dataquality; + int allowdisconnect; struct localuser *next; }; @@ -95,7 +99,7 @@ static void hanguptree(struct localuser *outgoing, struct ast_channel *exception #define MAX 256 -static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir) +static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localuser *outgoing, int *to, int *allowredir, int *allowdisconnect) { struct localuser *o; int found; @@ -161,7 +165,15 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu winner = ast_waitfor_n(watchers, pos, to); o = outgoing; while(o) { - if (o->chan == winner) { + if (o->stillgoing && (o->chan->_state == AST_STATE_UP)) { + if (!peer) { + if (option_verbose > 2) + ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); + peer = o->chan; + *allowredir = o->allowredirect; + *allowdisconnect = o->allowdisconnect; + } + } else if (o->chan == winner) { f = ast_read(winner); if (f) { if (f->frametype == AST_FRAME_CONTROL) { @@ -173,6 +185,7 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu ast_verbose( VERBOSE_PREFIX_3 "%s answered %s\n", o->chan->name, in->name); peer = o->chan; *allowredir = o->allowredirect; + *allowdisconnect = o->allowdisconnect; } break; case AST_CONTROL_BUSY: @@ -234,6 +247,17 @@ static struct ast_channel *wait_for_answer(struct ast_channel *in, struct localu *to=-1; return NULL; } + if (f && (f->frametype == AST_FRAME_DTMF) && allowdisconnect && + (f->subclass == '*')) { + if (option_verbose > 3) + ast_verbose(VERBOSE_PREFIX_3 "User hit %c to disconnect call.\n", f->subclass); + *to=0; + return NULL; + } + if (single && ((f->frametype == AST_FRAME_VOICE) || (f->frametype == AST_FRAME_DTMF))) { + if (ast_write(outgoing->chan, f)) + ast_log(LOG_WARNING, "Unable to forward voice\n"); + } } if (!*to && (option_verbose > 2)) ast_verbose( VERBOSE_PREFIX_3 "Nobody picked up in %d ms\n", orig); @@ -252,11 +276,12 @@ static int dial_exec(struct ast_channel *chan, void *data) { int res=-1; struct localuser *u; - char *info, *peers, *timeout, *tech, *number, *rest, *cur; + char info[256], *peers, *timeout, *tech, *number, *rest, *cur; struct localuser *outgoing=NULL, *tmp; struct ast_channel *peer; int to; int allowredir=0; + int allowdisconnect=0; char numsubst[AST_MAX_EXTENSION]; char restofit[AST_MAX_EXTENSION]; char *transfer = NULL; @@ -270,11 +295,6 @@ static int dial_exec(struct ast_channel *chan, void *data) LOCAL_USER_ADD(u); /* Parse our arguments XXX Check for failure XXX */ - info = malloc(strlen((char *)data) + AST_MAX_EXTENSION); - if (!info) { - ast_log(LOG_WARNING, "Out of memory\n"); - return -1; - } strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1); peers = info; if (peers) { @@ -325,6 +345,10 @@ static int dial_exec(struct ast_channel *chan, void *data) tmp->ringbackonly = 1; if (strchr(transfer, 'm')) tmp->musiconhold = 1; + if (strchr(transfer, 'd')) + tmp->dataquality = 1; + if (strchr(transfer, 'H')) + tmp->allowdisconnect = 1; } strncpy(numsubst, number, sizeof(numsubst)-1); /* If we're dialing by extension, look at the extension to know what to dial */ @@ -396,6 +420,9 @@ static int dial_exec(struct ast_channel *chan, void *data) 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) + break; cur = rest; } while(cur); @@ -403,7 +430,7 @@ static int dial_exec(struct ast_channel *chan, void *data) to = atoi(timeout) * 1000; else to = -1; - peer = wait_for_answer(chan, outgoing, &to, &allowredir); + peer = wait_for_answer(chan, outgoing, &to, &allowredir, &allowdisconnect); if (!peer) { if (to) /* Musta gotten hung up */ @@ -432,18 +459,19 @@ static int dial_exec(struct ast_channel *chan, void *data) } if (!strcmp(chan->type,"Zap")) { int x = 2; + if (tmp->dataquality) x = 0; ast_channel_setoption(chan,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } if (!strcmp(peer->type,"Zap")) { int x = 2; + if (tmp->dataquality) x = 0; ast_channel_setoption(peer,AST_OPTION_TONE_VERIFY,&x,sizeof(char),0); } - res = ast_bridge_call(chan, peer, allowredir); + res = ast_bridge_call(chan, peer, allowredir, allowdisconnect); ast_hangup(peer); } out: hanguptree(outgoing, NULL); - free(info); LOCAL_USER_REMOVE(u); return res; } diff --git a/channels/Makefile b/channels/Makefile index dc5cabba42..7255f0e81a 100755 --- a/channels/Makefile +++ b/channels/Makefile @@ -13,7 +13,8 @@ CHANNEL_LIBS=chan_modem.so chan_iax.so chan_sip.so \ chan_modem_aopen.so chan_oss.so \ - chan_modem_bestdata.so chan_modem_i4l.so + chan_modem_bestdata.so chan_modem_i4l.so \ + chan_agent.so # # If you really want VoFR you can have it :-P diff --git a/channels/chan_agent.c b/channels/chan_agent.c new file mode 100755 index 0000000000..d9eef1c663 --- /dev/null +++ b/channels/chan_agent.c @@ -0,0 +1,611 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Implementation of Session Initiation Protocol + * + * Copyright (C) 1999, Mark Spencer + * + * Mark Spencer + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static char *desc = "Agent Proxy Channel"; +static char *type = "Agent"; +static char *tdesc = "Call Agent Proxy Channel"; +static char *config = "agents.conf"; + +static char *app = "AgentLogin"; + +static char *synopsis = "Call agent login"; + +static char *descrip = +" AgentLogin():\n" +"Asks the agent to login to the system. Always returns -1. While\n" +"logged in, the agent can receive calls and will hear a 'beep'\n" +"when a new call comes in. The agent can dump the call by pressing\n" +"the star key.\n"; + +static char moh[80] = "default"; + +#define AST_MAX_AGENT 80 /* Agent ID or Password max length */ + +static int capability = -1; + +static int usecnt =0; +static pthread_mutex_t usecnt_lock = AST_MUTEX_INITIALIZER; + +/* Protect the interface list (of sip_pvt's) */ +static pthread_mutex_t agentlock = AST_MUTEX_INITIALIZER; + +static struct agent_pvt { + pthread_mutex_t lock; /* Channel private lock */ + int dead; /* Poised for destruction? */ + char moh[80]; /* Which music on hold */ + char agent[AST_MAX_AGENT]; /* Agent ID */ + char password[AST_MAX_AGENT]; /* Password for Agent login */ + char name[AST_MAX_AGENT]; + struct ast_channel *owner; /* Agent */ + struct ast_channel *chan; /* Channel we use */ + struct agent_pvt *next; /* Agent */ +} *agents = NULL; + +#define CLEANUP(ast, p) do { \ + int x; \ + if (p->chan) { \ + for (x=0;xfds[x] = p->chan->fds[x]; \ + } \ +} while(0) + + +static int add_agent(struct ast_variable *var) +{ + char tmp[256]; + char *password=NULL, *name=NULL; + struct agent_pvt *p; + + strncpy(tmp, var->value, sizeof(tmp)); + if ((password = strchr(tmp, ','))) { + *password = '\0'; + password++; + while (*password < 33) password++; + } + if (password && (name = strchr(password, ','))) { + *name = '\0'; + name++; + while (*name < 33) name++; + } + p = agents; + while(p) { + if (!strcmp(p->agent, tmp)) + break; + p = p->next; + } + if (!p) { + p = malloc(sizeof(struct agent_pvt)); + if (p) { + memset(p, 0, sizeof(struct agent_pvt)); + strncpy(p->agent, tmp, sizeof(p->agent) -1); + p->next = agents; + agents = p; + + } + } + if (!p) + return -1; + 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->dead = 0; + return 0; +} + +static int agent_answer(struct ast_channel *ast) +{ + ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n"); + return -1; +} + +static struct ast_frame *agent_read(struct ast_channel *ast) +{ + struct agent_pvt *p = ast->pvt->pvt; + struct ast_frame *f = NULL; + ast_pthread_mutex_lock(&p->lock); + if (p->chan) + f = ast_read(p->chan); + if (!f) { + /* If there's a channel, make it NULL */ + if (p->chan) + p->chan = NULL; + } + if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) { + /* * terminates call */ + ast_frfree(f); + f = NULL; + } + CLEANUP(ast,p); + ast_pthread_mutex_unlock(&p->lock); + return f; +} + +static int agent_write(struct ast_channel *ast, struct ast_frame *f) +{ + struct agent_pvt *p = ast->pvt->pvt; + int res = -1; + ast_pthread_mutex_lock(&p->lock); + if (p->chan) + res = ast_write(p->chan, f); + CLEANUP(ast, p); + ast_pthread_mutex_unlock(&p->lock); + return res; +} + +static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan) +{ + struct agent_pvt *p = newchan->pvt->pvt; + ast_pthread_mutex_lock(&p->lock); + if (p->owner != oldchan) { + ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); + return -1; + } + p->owner = newchan; + ast_pthread_mutex_unlock(&p->lock); + return 0; +} + +static int agent_indicate(struct ast_channel *ast, int condition) +{ + struct agent_pvt *p = ast->pvt->pvt; + int res = -1; + ast_pthread_mutex_lock(&p->lock); + if (p->chan) + res = ast_indicate(p->chan, condition); + ast_pthread_mutex_unlock(&p->lock); + return res; +} + +static int agent_digit(struct ast_channel *ast, char digit) +{ + struct agent_pvt *p = ast->pvt->pvt; + int res = -1; + ast_pthread_mutex_lock(&p->lock); + if (p->chan) + res = p->chan->pvt->send_digit(p->chan, digit); + ast_pthread_mutex_unlock(&p->lock); + return res; +} + +static int agent_call(struct ast_channel *ast, char *dest, int timeout) +{ + struct agent_pvt *p = ast->pvt->pvt; + int res = -1; + ast_pthread_mutex_lock(&p->lock); + res = ast_streamfile(p->chan, "beep", p->chan->language); + if (!res) + res = ast_waitstream(p->chan, ""); + if (!res) { + res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); + if (res) + ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(p->chan->nativeformats)); + } + if (!res) { + ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); + if (res) + ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(p->chan->nativeformats)); + } + /* Call is immediately up */ + ast_setstate(ast, AST_STATE_UP); + ast_pthread_mutex_unlock(&p->lock); + return res; +} + +static int agent_hangup(struct ast_channel *ast) +{ + struct agent_pvt *p = ast->pvt->pvt; + ast_pthread_mutex_lock(&p->lock); + p->owner = NULL; + ast->pvt->pvt = NULL; + ast_pthread_mutex_unlock(&p->lock); + if (p->chan) { + /* If they're dead, go ahead and hang up on the agent now */ + if (p->dead) + ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); + ast_moh_start(p->chan, p->moh); + } else if (p->dead) + /* Go ahead and lose it */ + free(p); + return 0; +} + +static struct ast_channel *agent_new(struct agent_pvt *p, int state) +{ + struct ast_channel *tmp; + if (!p->chan) { + ast_log(LOG_WARNING, "No channel? :(\n"); + return NULL; + } + tmp = ast_channel_alloc(0); + if (tmp) { + tmp->nativeformats = p->chan->nativeformats; + snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent); + tmp->type = type; + ast_setstate(tmp, state); + tmp->writeformat = p->chan->writeformat; + tmp->pvt->rawwriteformat = p->chan->writeformat; + tmp->readformat = p->chan->readformat; + tmp->pvt->rawreadformat = p->chan->readformat; + tmp->pvt->pvt = p; + tmp->pvt->send_digit = agent_digit; + tmp->pvt->call = agent_call; + tmp->pvt->hangup = agent_hangup; + tmp->pvt->answer = agent_answer; + tmp->pvt->read = agent_read; + tmp->pvt->write = agent_write; + tmp->pvt->exception = agent_read; + tmp->pvt->indicate = agent_indicate; + tmp->pvt->fixup = agent_fixup; + strncpy(tmp->language, p->chan->language, sizeof(tmp->language)-1); + p->owner = tmp; + ast_pthread_mutex_lock(&usecnt_lock); + usecnt++; + ast_pthread_mutex_unlock(&usecnt_lock); + ast_update_use_count(); + strncpy(tmp->context, p->chan->context, sizeof(tmp->context)-1); + strncpy(tmp->exten, p->chan->exten, sizeof(tmp->exten)-1); + tmp->priority = 1; + /* Wake up any waiting blockers (by definition the login app) */ + if (p->chan->blocking) { + pthread_kill(p->chan->blocker, SIGURG); + /* Wait until the blocker releases it */ + while(p->chan->blocking) + usleep(1000); + } + ast_moh_stop(p->chan); + } else + ast_log(LOG_WARNING, "Unable to allocate channel structure\n"); + return tmp; +} + + +static int read_agent_config(void) +{ + struct ast_config *cfg; + struct ast_variable *v; + struct agent_pvt *p, *pl, *pn; + cfg = ast_load(config); + if (!cfg) { + ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); + return 0; + } + ast_pthread_mutex_lock(&agentlock); + p = agents; + while(p) { + p->dead = 1; + p = p->next; + } + strcpy(moh, "default"); + v = ast_variable_browse(cfg, "agents"); + while(v) { + /* Create the interface list */ + if (!strcasecmp(v->name, "agent")) { + add_agent(v); + } else if (!strcasecmp(v->name, "musiconhold")) { + strncpy(moh, v->value, sizeof(moh) - 1); + } + v = v->next; + } + p = agents; + pl = NULL; + while(p) { + pn = p->next; + if (p->dead) { + /* Unlink */ + if (pl) + pl->next = p->next; + else + agents = p->next; + /* Destroy if appropriate */ + if (!p->owner) { + if (!p->chan) { + free(p); + } else { + /* Cause them to hang up */ + ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); + } + } + } else + pl = p; + p = pn; + } + ast_pthread_mutex_unlock(&agentlock); + ast_destroy(cfg); + return 0; +} + +static struct ast_channel *agent_request(char *type, int format, void *data) +{ + struct agent_pvt *p; + struct ast_channel *chan = NULL; + ast_pthread_mutex_lock(&agentlock); + p = agents; + while(p) { + if (!strcmp(data, p->agent)) { + ast_pthread_mutex_lock(&p->lock); + /* Agent must be registered, but not have any active call */ + if (!p->owner && p->chan) { + chan = agent_new(p, AST_STATE_DOWN); + } + ast_pthread_mutex_unlock(&p->lock); + break; + } + p = p->next; + } + ast_pthread_mutex_unlock(&agentlock); + return chan; +} + +static int agents_show(int fd, int argc, char **argv) +{ + struct agent_pvt *p; + char username[256]; + char location[256]; + char talkingto[256]; + + if (argc != 2) + return RESULT_SHOWUSAGE; + ast_pthread_mutex_lock(&agentlock); + p = agents; + while(p) { + ast_pthread_mutex_lock(&p->lock); + if (strlen(p->name)) + snprintf(username, sizeof(username), "(%s) ", p->name); + else + strcpy(username, ""); + if (p->chan) { + snprintf(location, sizeof(location), "logged in on %s", p->chan->name); + if (p->owner && p->owner->bridge) { + snprintf(talkingto, sizeof(talkingto), " talking to %s", p->owner->bridge->name); + } else { + strcpy(talkingto, " is idle"); + } + } else { + strcpy(location, "not logged in"); + strcpy(talkingto, ""); + } + ast_pthread_mutex_unlock(&p->lock); + ast_cli(fd, "%-12.12s %s%s%s\n", p->agent, + username, location, talkingto); + p = p->next; + } + ast_pthread_mutex_unlock(&agentlock); + return RESULT_SUCCESS; +} + +static char show_agents_usage[] = +"Usage: show agents\n" +" Provides summary information on agents.\n"; + +static struct ast_cli_entry cli_show_agents = { + { "show", "agents", NULL }, agents_show, + "Show status of agents", show_agents_usage, NULL }; + +STANDARD_LOCAL_USER; +LOCAL_USER_DECL; + +static int login_exec(struct ast_channel *chan, void *data) +{ + int res=0; + int tries = 0; + struct agent_pvt *p; + struct localuser *u; + char user[AST_MAX_AGENT]; + char pass[AST_MAX_AGENT]; + char xpass[AST_MAX_AGENT] = ""; + char *errmsg; + LOCAL_USER_ADD(u); + if (chan->_state != AST_STATE_UP) + res = ast_answer(chan); + if (!res) + res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); + while (!res && (tries < 3)) { + /* Check for password */ + ast_pthread_mutex_lock(&agentlock); + p = agents; + while(p) { + if (!strcmp(p->agent, user)) + strncpy(xpass, p->password, sizeof(xpass) - 1); + p = p->next; + } + ast_pthread_mutex_unlock(&agentlock); + if (!res) { + if (strlen(xpass) || !p) + res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); + else + strcpy(pass, ""); + } + errmsg = "agent-incorrect"; + +#if 0 + ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); +#endif + + /* Check again for accuracy */ + ast_pthread_mutex_lock(&agentlock); + p = agents; + while(p) { + ast_pthread_mutex_lock(&p->lock); + if (!strcmp(p->agent, user) && + !strcmp(p->password, pass)) { + if (!p->chan) { + res = ast_streamfile(chan, "agent-loginok", chan->language); + if (!res) + ast_waitstream(chan, ""); + if (!res) { + res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); + if (res) + ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); + } + if (!res) { + ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); + if (res) + ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); + } + /* Check once more just in case */ + if (p->chan) + res = -1; + if (!res) { + ast_moh_start(chan, p->moh); + manager_event(EVENT_FLAG_AGENT, "Agentlogin", + "Agent: %s\r\n" + "Channel: %s\r\n", + p->agent, chan->name); + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged in (format %d/%d)\n", p->agent, + chan->readformat, chan->writeformat); + /* Login this channel and wait for it to + go away */ + p->chan = chan; + ast_pthread_mutex_unlock(&p->lock); + ast_pthread_mutex_unlock(&agentlock); + while ((res >= 0) && (p->chan == chan)) { + /* True sleep here, since we're being monitored + elsewhere instead */ + if (p->owner) + sleep(1); + else + res = ast_safe_sleep(chan, 1000); + } + if (res && p->owner) + ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); + /* Log us off if appropriate */ + if (p->chan == chan) + p->chan = NULL; + if (option_verbose > 2) + ast_verbose(VERBOSE_PREFIX_3 "Agent '%s' logged out\n", p->agent); + manager_event(EVENT_FLAG_AGENT, "Agentlogoff", + "Agent: %s\r\n", + p->agent); + /* If there is no owner, go ahead and kill it now */ + if (p->dead && !p->owner) + free(p); + } + res = -1; + } else { + ast_pthread_mutex_unlock(&p->lock); + errmsg = "agent-alreadyon"; + p = NULL; + } + break; + } + ast_pthread_mutex_unlock(&p->lock); + p = p->next; + } + if (!p) + ast_pthread_mutex_unlock(&agentlock); + + if (!res) + res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); + } + + LOCAL_USER_REMOVE(u); + /* Always hangup */ + return -1; +} + + +int load_module() +{ + /* Make sure we can register our sip channel type */ + if (ast_channel_register(type, tdesc, capability, agent_request)) { + ast_log(LOG_ERROR, "Unable to register channel class %s\n", type); + return -1; + } + ast_register_application(app, login_exec, synopsis, descrip); + ast_cli_register(&cli_show_agents); + /* Read in the config */ + read_agent_config(); + return 0; +} + +int reload() +{ + read_agent_config(); + return 0; +} + +int unload_module() +{ + struct agent_pvt *p; + /* First, take us out of the channel loop */ + ast_cli_unregister(&cli_show_agents); + ast_unregister_application(app); + ast_channel_unregister(type); + if (!ast_pthread_mutex_lock(&agentlock)) { + /* Hangup all interfaces if they have an owner */ + p = agents; + while(p) { + if (p->owner) + ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); + p = p->next; + } + agents = NULL; + ast_pthread_mutex_unlock(&agentlock); + } else { + ast_log(LOG_WARNING, "Unable to lock the monitor\n"); + return -1; + } + return 0; +} + +int usecount() +{ + int res; + ast_pthread_mutex_lock(&usecnt_lock); + res = usecnt; + ast_pthread_mutex_unlock(&usecnt_lock); + return res; +} + +char *key() +{ + return ASTERISK_GPL_KEY; +} + +char *description() +{ + return desc; +} + diff --git a/configs/agents.conf.sample b/configs/agents.conf.sample new file mode 100755 index 0000000000..83c2ddb3b3 --- /dev/null +++ b/configs/agents.conf.sample @@ -0,0 +1,11 @@ +; +; Agent configuration +; +; +[agents] +; +; This section contains the agent definitions, in the form: +; +; agent => agentid,agentpassword,name +; +;agent => 1234,4321,Mark Spencer diff --git a/configs/manager.conf.sample b/configs/manager.conf.sample new file mode 100755 index 0000000000..417730afb2 --- /dev/null +++ b/configs/manager.conf.sample @@ -0,0 +1,12 @@ +; +; Asterisk Call Management support +; +[general] +enabled = no +port = 5038 +bindaddr = 0.0.0.0 + +;[mark] +;secret = mysecret +;read = system,call,log,verbose,command,agent +;write = system,call,log,verbose,command,agent diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h new file mode 100755 index 0000000000..5eb4965d5a --- /dev/null +++ b/include/asterisk/manager.h @@ -0,0 +1,52 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * External call management support + * + * Copyright (C) 1999, Mark Spencer + * + * Mark Spencer + * + * This program is free software, distributed under the terms of + * the GNU General Public License. + * + * Includes code and algorithms from the Zapata library. + * + */ + +#ifndef _ASTERISK_MANAGER_H +#define _ASTERISK_MANAGER_H + +#include + +/* + * Call management packages are text fields of the form a: b. There is + * always exactly one space after the colon. + * + * The first header type is the "Event" header. Other headers vary from + * event to event. Headers end with standard \r\n termination. + * + * Some standard headers: + * + * Action: -- request or notification of a particular action + * Response: -- response code, like "200 OK" + * + */ + +#define DEFAULT_MANAGER_PORT 5038 /* Default port for Asterisk management via TCP */ + +#define EVENT_FLAG_SYSTEM (1 << 0) /* System events such as module load/unload */ +#define EVENT_FLAG_CALL (1 << 1) /* Call event, such as state change, etc */ +#define EVENT_FLAG_LOG (1 << 2) /* Log events */ +#define EVENT_FLAG_VERBOSE (1 << 3) /* Verbose messages */ +#define EVENT_FLAG_COMMAND (1 << 4) /* Ability to read/set commands */ +#define EVENT_FLAG_AGENT (1 << 5) /* Ability to read/set agent info */ + +/* External routines may send asterisk manager events this way */ +extern int manager_event(int category, char *event, char *contents, ...) + __attribute__ ((format (printf, 3,4))); + +/* Called by Asterisk initialization */ +extern int init_manager(void); +extern int reload_manager(void); +#endif diff --git a/sounds/agent-alreadyon.gsm b/sounds/agent-alreadyon.gsm new file mode 100755 index 0000000000000000000000000000000000000000..9cc3f1a10a6564381937252a90c0cf3c78adc06c GIT binary patch literal 8349 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 literal 0 HcmV?d00001 diff --git a/sounds/agent-incorrect.gsm b/sounds/agent-incorrect.gsm new file mode 100755 index 0000000000000000000000000000000000000000..3fcce85b3043d70d11cf24aa5f004b56c33dbffa GIT binary patch literal 6798 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 QXa?RlWGX>msF`W_Kl3CE0RR91 literal 0 HcmV?d00001 diff --git a/sounds/agent-pass.gsm b/sounds/agent-pass.gsm new file mode 100755 index 0000000000000000000000000000000000000000..210405d10165a5ae9742f0d89fbb67e6086fb3d7 GIT binary patch literal 6930 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 N@oh99-olnl{vYWB?veli literal 0 HcmV?d00001 diff --git a/sounds/agent-user.gsm b/sounds/agent-user.gsm new file mode 100755 index 0000000000000000000000000000000000000000..7f1615a331fe18e1596c34ffb73bdd424d29ae4f GIT binary patch literal 8580 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 B0@DBh literal 0 HcmV?d00001