2 * Asterisk -- A telephony toolkit for Linux.
4 * Implementation of Agents
6 * Copyright (C) 1999 - 2005, Digium Inc.
8 * Mark Spencer <markster@digium.com>
10 * This program is free software, distributed under the terms of
11 * the GNU General Public License
16 #include <asterisk/lock.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/channel_pvt.h>
19 #include <asterisk/config.h>
20 #include <asterisk/logger.h>
21 #include <asterisk/module.h>
22 #include <asterisk/pbx.h>
23 #include <asterisk/options.h>
24 #include <asterisk/lock.h>
25 #include <asterisk/sched.h>
26 #include <asterisk/io.h>
27 #include <asterisk/rtp.h>
28 #include <asterisk/acl.h>
29 #include <asterisk/callerid.h>
30 #include <asterisk/file.h>
31 #include <asterisk/cli.h>
32 #include <asterisk/app.h>
33 #include <asterisk/musiconhold.h>
34 #include <asterisk/manager.h>
35 #include <asterisk/features.h>
36 #include <asterisk/utils.h>
37 #include <asterisk/causes.h>
38 #include <asterisk/astdb.h>
39 #include <sys/socket.h>
45 #include <arpa/inet.h>
46 #include <sys/signal.h>
48 static char *desc = "Agent Proxy Channel";
49 static char *channeltype = "Agent";
50 static char *tdesc = "Call Agent Proxy Channel";
51 static char *config = "agents.conf";
53 static char *app = "AgentLogin";
54 static char *app2 = "AgentCallbackLogin";
55 static char *app3 = "AgentMonitorOutgoing";
57 static char *synopsis = "Call agent login";
58 static char *synopsis2 = "Call agent callback login";
59 static char *synopsis3 = "Record agent's outgoing call";
61 static char *descrip =
62 " AgentLogin([AgentNo][|options]):\n"
63 "Asks the agent to login to the system. Always returns -1. While\n"
64 "logged in, the agent can receive calls and will hear a 'beep'\n"
65 "when a new call comes in. The agent can dump the call by pressing\n"
67 "The option string may contain zero or more of the following characters:\n"
68 " 's' -- silent login - do not announce the login ok segment after agent logged in/off\n";
70 static char *descrip2 =
71 " AgentCallbackLogin([AgentNo][|[options][exten]@context]):\n"
72 "Asks the agent to login to the system with callback.\n"
73 "The agent's callback extension is called (optionally with the specified\n"
75 "The option string may contain zero or more of the following characters:\n"
76 " 's' -- silent login - do not announce the login ok segment agent logged in/off\n";
80 static char *descrip3 =
81 " AgentMonitorOutgoing([options]):\n"
82 "Tries to figure out the id of the agent who is placing outgoing call based on\n"
83 "comparision of the callerid of the current interface and the global variable \n"
84 "placed by the AgentCallbackLogin application. That's why it should be used only\n"
85 "with the AgentCallbackLogin app. Uses the monitoring functions in chan_agent \n"
86 "instead of Monitor application. That have to be configured in the agents.conf file.\n"
88 "Normally the app returns 0 unless the options are passed. Also if the callerid or\n"
89 "the agentid are not specified it'll look for n+101 priority.\n"
91 " 'd' - make the app return -1 if there is an error condition and there is\n"
92 " no extension n+101\n"
93 " 'c' - change the CDR so that the source of the call is 'Agent/agent_id'\n"
94 " 'n' - don't generate the warnings when there is no callerid or the\n"
95 " agentid is not known.\n"
96 " It's handy if you want to have one context for agent and non-agent calls.\n";
98 static char mandescr_agents[] =
99 "Description: Will list info about all possible agents.\n"
102 static char moh[80] = "default";
104 #define AST_MAX_AGENT 80 /* Agent ID or Password max length */
105 #define AST_MAX_BUF 256
106 #define AST_MAX_FILENAME_LEN 256
108 /* Persistent Agents astdb family */
109 static const char *pa_family = "/Agents";
110 /* The maximum lengh of each persistent member agent database entry */
111 #define PA_MAX_LEN 2048
112 /* queues.conf [general] option */
113 static int persistent_agents = 0;
114 static void dump_agents(void);
116 static int capability = -1;
118 static ast_group_t group;
119 static int autologoff;
120 static int wrapuptime;
123 static int maxlogintries = 3;
124 static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye";
126 static int usecnt =0;
127 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
129 /* Protect the interface list (of pvt's) */
130 AST_MUTEX_DEFINE_STATIC(agentlock);
132 static int recordagentcalls = 0;
133 static char recordformat[AST_MAX_BUF] = "";
134 static char recordformatext[AST_MAX_BUF] = "";
135 static int createlink = 0;
136 static char urlprefix[AST_MAX_BUF] = "";
137 static char savecallsin[AST_MAX_BUF] = "";
138 static int updatecdr = 0;
139 static char beep[AST_MAX_BUF] = "beep";
141 #define GETAGENTBYCALLERID "AGENTBYCALLERID"
143 static struct agent_pvt {
144 ast_mutex_t lock; /* Channel private lock */
145 int dead; /* Poised for destruction? */
146 int pending; /* Not a real agent -- just pending a match */
147 int abouttograb; /* About to grab */
148 int autologoff; /* Auto timeout time */
149 int ackcall; /* ackcall */
150 time_t loginstart; /* When agent first logged in (0 when logged off) */
151 time_t start; /* When call started */
152 struct timeval lastdisc; /* When last disconnected */
153 int wrapuptime; /* Wrapup time in ms */
154 ast_group_t group; /* Group memberships */
155 int acknowledged; /* Acknowledged */
156 char moh[80]; /* Which music on hold */
157 char agent[AST_MAX_AGENT]; /* Agent ID */
158 char password[AST_MAX_AGENT]; /* Password for Agent login */
159 char name[AST_MAX_AGENT];
160 ast_mutex_t app_lock; /* Synchronization between owning applications */
161 volatile pthread_t owning_app; /* Owning application thread id */
162 volatile int app_sleep_cond; /* Sleep condition for the login app */
163 struct ast_channel *owner; /* Agent */
165 struct ast_channel *chan; /* Channel we use */
166 struct agent_pvt *next; /* Agent */
169 #define CHECK_FORMATS(ast, p) do { \
171 if (ast->nativeformats != p->chan->nativeformats) { \
172 ast_log(LOG_DEBUG, "Native formats changing from %d to %d\n", ast->nativeformats, p->chan->nativeformats); \
173 /* Native formats changed, reset things */ \
174 ast->nativeformats = p->chan->nativeformats; \
175 ast_log(LOG_DEBUG, "Resetting read to %d and write to %d\n", ast->readformat, ast->writeformat);\
176 ast_set_read_format(ast, ast->readformat); \
177 ast_set_write_format(ast, ast->writeformat); \
179 if (p->chan->readformat != ast->pvt->rawreadformat) \
180 ast_set_read_format(p->chan, ast->pvt->rawreadformat); \
181 if (p->chan->writeformat != ast->pvt->rawwriteformat) \
182 ast_set_write_format(p->chan, ast->pvt->rawwriteformat); \
186 /* Cleanup moves all the relevant FD's from the 2nd to the first, but retains things
187 properly for a timingfd XXX This might need more work if agents were logged in as agents or other
188 totally impractical combinations XXX */
190 #define CLEANUP(ast, p) do { \
193 for (x=0;x<AST_MAX_FDS;x++) {\
194 if (x != AST_MAX_FDS - 2) \
195 ast->fds[x] = p->chan->fds[x]; \
197 ast->fds[AST_MAX_FDS - 3] = p->chan->fds[AST_MAX_FDS - 2]; \
203 static void agent_unlink(struct agent_pvt *agent)
205 struct agent_pvt *p, *prev;
211 prev->next = agent->next;
213 agents = agent->next;
221 static struct agent_pvt *add_agent(char *agent, int pending)
223 char tmp[AST_MAX_BUF] = "";
224 char *password=NULL, *name=NULL;
225 struct agent_pvt *p, *prev;
227 strncpy(tmp, agent, sizeof(tmp) - 1);
228 if ((password = strchr(tmp, ','))) {
231 while (*password < 33) password++;
233 if (password && (name = strchr(password, ','))) {
236 while (*name < 33) name++;
241 if (!pending && !strcmp(p->agent, tmp))
247 p = malloc(sizeof(struct agent_pvt));
249 memset(p, 0, sizeof(struct agent_pvt));
250 strncpy(p->agent, tmp, sizeof(p->agent) -1);
251 ast_mutex_init(&p->lock);
252 ast_mutex_init(&p->app_lock);
253 p->owning_app = (pthread_t) -1;
254 p->app_sleep_cond = 1;
256 p->pending = pending;
267 strncpy(p->password, password ? password : "", sizeof(p->password) - 1);
268 strncpy(p->name, name ? name : "", sizeof(p->name) - 1);
269 strncpy(p->moh, moh, sizeof(p->moh) - 1);
270 p->ackcall = ackcall;
271 p->autologoff = autologoff;
272 p->wrapuptime = wrapuptime;
280 static int agent_cleanup(struct agent_pvt *p)
282 struct ast_channel *chan = p->owner;
284 chan->pvt->pvt = NULL;
285 p->app_sleep_cond = 1;
286 /* Release ownership of the agent to other threads (presumably running the login app). */
287 ast_mutex_unlock(&p->app_lock);
289 ast_channel_free(chan);
291 ast_mutex_destroy(&p->lock);
292 ast_mutex_destroy(&p->app_lock);
298 static int check_availability(struct agent_pvt *newlyavailable, int needlock);
300 static int agent_answer(struct ast_channel *ast)
302 ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n");
306 static int __agent_start_monitoring(struct ast_channel *ast, struct agent_pvt *p, int needlock)
308 char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer;
309 char filename[AST_MAX_BUF];
314 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid);
315 /* substitute . for - */
316 if ((pointer = strchr(filename, '.')))
318 snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename);
319 ast_monitor_start(ast, recordformat, tmp, needlock);
320 ast_monitor_setjoinfiles(ast, 1);
321 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext);
323 ast_verbose("name is %s, link is %s\n",tmp, tmp2);
326 ast->cdr = ast_cdr_alloc();
327 ast_cdr_setuserfield(ast, tmp2);
330 ast_log(LOG_ERROR, "Recording already started on that call.\n");
334 static int agent_start_monitoring(struct ast_channel *ast, int needlock)
336 return __agent_start_monitoring(ast, ast->pvt->pvt, needlock);
339 static struct ast_frame *agent_read(struct ast_channel *ast)
341 struct agent_pvt *p = ast->pvt->pvt;
342 struct ast_frame *f = NULL;
343 static struct ast_frame null_frame = { AST_FRAME_NULL, };
344 static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER };
345 ast_mutex_lock(&p->lock);
346 CHECK_FORMATS(ast, p);
348 ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION);
349 if (ast->fdno == AST_MAX_FDS - 3)
350 p->chan->fdno = AST_MAX_FDS - 2;
352 p->chan->fdno = ast->fdno;
353 f = ast_read(p->chan);
357 /* If there's a channel, hang it up (if it's on a callback) make it NULL */
359 /* Note that we don't hangup if it's not a callback because Asterisk will do it
360 for us when the PBX instance that called login finishes */
361 if (!ast_strlen_zero(p->loginchan)) {
362 p->chan->_bridge = NULL;
365 gettimeofday(&p->lastdisc, NULL);
366 p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000;
367 if (p->lastdisc.tv_usec > 1000000) {
368 p->lastdisc.tv_usec -= 1000000;
369 p->lastdisc.tv_sec++;
371 p->lastdisc.tv_sec += (p->wrapuptime / 1000);
378 if ((p->chan && (p->chan->_state != AST_STATE_UP)) && f && (f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_ANSWER)) {
381 if (option_verbose > 2)
382 ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name);
383 /* Don't pass answer along */
391 p->chan->_bridge = ast;
395 if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '#')) {
396 if (!p->acknowledged) {
397 if (option_verbose > 2)
398 ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name);
403 p->chan->_bridge = ast;
406 if (f && (f->frametype == AST_FRAME_DTMF) && (f->subclass == '*')) {
407 /* * terminates call */
412 ast_mutex_unlock(&p->lock);
413 if (recordagentcalls && f == &answer_frame)
414 agent_start_monitoring(ast,0);
418 static int agent_write(struct ast_channel *ast, struct ast_frame *f)
420 struct agent_pvt *p = ast->pvt->pvt;
422 CHECK_FORMATS(ast, p);
423 ast_mutex_lock(&p->lock);
425 if ((f->frametype != AST_FRAME_VOICE) ||
426 (f->subclass == p->chan->writeformat)) {
427 res = ast_write(p->chan, f);
429 ast_log(LOG_DEBUG, "Dropping one incompatible voice frame on '%s' to '%s'\n", ast->name, p->chan->name);
435 ast_mutex_unlock(&p->lock);
439 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
441 struct agent_pvt *p = newchan->pvt->pvt;
442 ast_mutex_lock(&p->lock);
443 if (p->owner != oldchan) {
444 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
445 ast_mutex_unlock(&p->lock);
449 ast_mutex_unlock(&p->lock);
453 static int agent_indicate(struct ast_channel *ast, int condition)
455 struct agent_pvt *p = ast->pvt->pvt;
457 ast_mutex_lock(&p->lock);
459 res = ast_indicate(p->chan, condition);
462 ast_mutex_unlock(&p->lock);
466 static int agent_digit(struct ast_channel *ast, char digit)
468 struct agent_pvt *p = ast->pvt->pvt;
470 ast_mutex_lock(&p->lock);
472 res = p->chan->pvt->send_digit(p->chan, digit);
475 ast_mutex_unlock(&p->lock);
479 static int agent_call(struct ast_channel *ast, char *dest, int timeout)
481 struct agent_pvt *p = ast->pvt->pvt;
484 ast_mutex_lock(&p->lock);
488 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n");
489 newstate = AST_STATE_DIALING;
492 ast_log(LOG_NOTICE, "Whoa, they hung up between alloc and call... what are the odds of that?\n");
495 ast_mutex_unlock(&p->lock);
497 ast_setstate(ast, newstate);
499 } else if (!ast_strlen_zero(p->loginchan)) {
501 /* Call on this agent */
502 if (option_verbose > 2)
503 ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name);
504 if (p->chan->cid.cid_num)
505 free(p->chan->cid.cid_num);
506 if (ast->cid.cid_num)
507 p->chan->cid.cid_num = strdup(ast->cid.cid_num);
509 p->chan->cid.cid_num = NULL;
510 if (p->chan->cid.cid_name)
511 free(p->chan->cid.cid_name);
512 if (ast->cid.cid_name)
513 p->chan->cid.cid_name = strdup(ast->cid.cid_name);
515 p->chan->cid.cid_name = NULL;
516 ast_channel_inherit_variables(ast, p->chan);
517 res = ast_call(p->chan, p->loginchan, 0);
519 ast_mutex_unlock(&p->lock);
522 ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name);
523 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language);
524 res = ast_streamfile(p->chan, beep, p->chan->language);
525 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
527 res = ast_waitstream(p->chan, "");
528 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
531 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats));
532 ast_log( LOG_DEBUG, "Set read format, result '%d'\n", res);
534 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
541 ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats));
542 ast_log( LOG_DEBUG, "Set write format, result '%d'\n", res);
544 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats)));
548 /* Call is immediately up, or might need ack */
550 newstate = AST_STATE_RINGING;
552 newstate = AST_STATE_UP;
553 if (recordagentcalls)
554 agent_start_monitoring(ast,0);
557 p->chan->_bridge = ast;
562 ast_mutex_unlock(&p->lock);
564 ast_setstate(ast, newstate);
568 static int agent_hangup(struct ast_channel *ast)
570 struct agent_pvt *p = ast->pvt->pvt;
572 ast_mutex_lock(&p->lock);
574 ast->pvt->pvt = NULL;
575 p->app_sleep_cond = 1;
578 /* if they really are hung up then set start to 0 so the test
579 * later if we're called on an already downed channel
580 * doesn't cause an agent to be logged out like when
581 * agent_request() is followed immediately by agent_hangup()
582 * as in apps/app_chanisavail.c:chanavail_exec()
585 ast_mutex_lock(&usecnt_lock);
587 ast_mutex_unlock(&usecnt_lock);
589 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state));
590 if (p->start && (ast->_state != AST_STATE_UP)) {
591 howlong = time(NULL) - p->start;
593 } else if (ast->_state == AST_STATE_RESERVED) {
598 /* If they're dead, go ahead and hang up on the agent now */
599 if (!ast_strlen_zero(p->loginchan)) {
600 /* Store last disconnect time */
602 gettimeofday(&p->lastdisc, NULL);
603 p->lastdisc.tv_usec += (p->wrapuptime % 1000) * 1000;
604 if (p->lastdisc.tv_usec >= 1000000) {
605 p->lastdisc.tv_usec -= 1000000;
606 p->lastdisc.tv_sec++;
608 p->lastdisc.tv_sec += (p->wrapuptime / 1000);
610 memset(&p->lastdisc, 0, sizeof(p->lastdisc));
612 /* Recognize the hangup and pass it along immediately */
616 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff);
617 if (howlong && p->autologoff && (howlong > p->autologoff)) {
618 char agent[AST_MAX_AGENT] = "";
619 long logintime = time(NULL) - p->loginstart;
621 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
622 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",
626 "Reason: Autologoff\r\n"
628 p->agent, p->loginchan, logintime, ast->uniqueid);
629 snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
630 ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Autologoff");
631 p->loginchan[0] = '\0';
632 ast_device_state_changed("Agent/%s", p->agent);
634 } else if (p->dead) {
635 ast_mutex_lock(&p->chan->lock);
636 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
637 ast_mutex_unlock(&p->chan->lock);
639 ast_mutex_lock(&p->chan->lock);
640 ast_moh_start(p->chan, p->moh);
641 ast_mutex_unlock(&p->chan->lock);
645 ast_mutex_unlock(&p->lock);
646 /* Release ownership of the agent to other threads (presumably running the login app). */
647 ast_mutex_unlock(&p->app_lock);
648 } else if (p->dead) {
649 /* Go ahead and lose it */
650 ast_mutex_unlock(&p->lock);
651 /* Release ownership of the agent to other threads (presumably running the login app). */
652 ast_mutex_unlock(&p->app_lock);
654 ast_mutex_unlock(&p->lock);
655 /* Release ownership of the agent to other threads (presumably running the login app). */
656 ast_mutex_unlock(&p->app_lock);
659 ast_mutex_unlock(&p->lock);
662 ast_mutex_lock(&agentlock);
664 ast_mutex_unlock(&agentlock);
666 if (p->abouttograb) {
667 /* Let the "about to grab" thread know this isn't valid anymore, and let it
670 } else if (p->dead) {
671 ast_mutex_destroy(&p->lock);
672 ast_mutex_destroy(&p->app_lock);
676 /* Not dead -- check availability now */
677 ast_mutex_lock(&p->lock);
678 /* Store last disconnect time */
679 gettimeofday(&p->lastdisc, NULL);
680 ast_mutex_unlock(&p->lock);
682 /* Release ownership of the agent to other threads (presumably running the login app). */
683 ast_mutex_unlock(&p->app_lock);
688 static int agent_cont_sleep( void *data )
694 p = (struct agent_pvt *)data;
696 ast_mutex_lock(&p->lock);
697 res = p->app_sleep_cond;
698 if (p->lastdisc.tv_sec) {
699 gettimeofday(&tv, NULL);
700 if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 +
701 (tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime)
704 ast_mutex_unlock(&p->lock);
707 ast_log( LOG_DEBUG, "agent_cont_sleep() returning %d\n", res );
712 static int agent_ack_sleep( void *data )
719 /* Wait a second and look for something */
721 p = (struct agent_pvt *)data;
724 to = ast_waitfor(p->chan, to);
733 f = ast_read(p->chan);
738 if (f->frametype == AST_FRAME_DTMF)
743 ast_mutex_lock(&p->lock);
744 if (!p->app_sleep_cond) {
745 ast_mutex_unlock(&p->lock);
748 } else if (res == '#') {
749 ast_mutex_unlock(&p->lock);
753 ast_mutex_unlock(&p->lock);
761 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
764 struct ast_channel *ret=NULL;
767 p = bridge->pvt->pvt;
769 ret = bridge->_bridge;
770 else if (chan == bridge->_bridge)
773 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>");
777 /*--- agent_new: Create new agent channel ---*/
778 static struct ast_channel *agent_new(struct agent_pvt *p, int state)
780 struct ast_channel *tmp;
781 struct ast_frame null_frame = { AST_FRAME_NULL };
784 ast_log(LOG_WARNING, "No channel? :(\n");
788 tmp = ast_channel_alloc(0);
791 tmp->nativeformats = p->chan->nativeformats;
792 tmp->writeformat = p->chan->writeformat;
793 tmp->pvt->rawwriteformat = p->chan->writeformat;
794 tmp->readformat = p->chan->readformat;
795 tmp->pvt->rawreadformat = p->chan->readformat;
796 strncpy(tmp->language, p->chan->language, sizeof(tmp->language)-1);
797 strncpy(tmp->context, p->chan->context, sizeof(tmp->context)-1);
798 strncpy(tmp->exten, p->chan->exten, sizeof(tmp->exten)-1);
800 tmp->nativeformats = AST_FORMAT_SLINEAR;
801 tmp->writeformat = AST_FORMAT_SLINEAR;
802 tmp->pvt->rawwriteformat = AST_FORMAT_SLINEAR;
803 tmp->readformat = AST_FORMAT_SLINEAR;
804 tmp->pvt->rawreadformat = AST_FORMAT_SLINEAR;
807 snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff);
809 snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent);
810 tmp->type = channeltype;
811 /* Safe, agentlock already held */
812 ast_setstate(tmp, state);
814 tmp->pvt->send_digit = agent_digit;
815 tmp->pvt->call = agent_call;
816 tmp->pvt->hangup = agent_hangup;
817 tmp->pvt->answer = agent_answer;
818 tmp->pvt->read = agent_read;
819 tmp->pvt->write = agent_write;
820 tmp->pvt->exception = agent_read;
821 tmp->pvt->indicate = agent_indicate;
822 tmp->pvt->fixup = agent_fixup;
823 tmp->pvt->bridged_channel = agent_bridgedchannel;
825 ast_mutex_lock(&usecnt_lock);
827 ast_mutex_unlock(&usecnt_lock);
828 ast_update_use_count();
830 /* Wake up and wait for other applications (by definition the login app)
831 * to release this channel). Takes ownership of the agent channel
832 * to this thread only.
833 * For signalling the other thread, ast_queue_frame is used until we
834 * can safely use signals for this purpose. The pselect() needs to be
835 * implemented in the kernel for this.
837 p->app_sleep_cond = 0;
838 if( ast_mutex_trylock(&p->app_lock) )
841 ast_queue_frame(p->chan, &null_frame);
842 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
843 ast_mutex_lock(&p->app_lock);
844 ast_mutex_lock(&p->lock);
848 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n");
850 tmp->pvt->pvt = NULL;
851 p->app_sleep_cond = 1;
852 ast_channel_free( tmp );
853 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */
854 ast_mutex_unlock(&p->app_lock);
858 p->owning_app = pthread_self();
859 /* After the above step, there should not be any blockers. */
861 if (ast_test_flag(p->chan, AST_FLAG_BLOCKING)) {
862 ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" );
865 ast_moh_stop(p->chan);
868 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
873 /*--- read_agent_config: Read configuration data (agents.conf) ---*/
874 static int read_agent_config(void)
876 struct ast_config *cfg;
877 struct ast_variable *v;
878 struct agent_pvt *p, *pl, *pn;
885 cfg = ast_config_load(config);
887 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");
890 ast_mutex_lock(&agentlock);
896 strncpy(moh, "default", sizeof(moh) - 1);
897 /* set the default recording values */
898 recordagentcalls = 0;
900 strncpy(recordformat, "wav", sizeof(recordformat) - 1);
901 strncpy(recordformatext, "wav", sizeof(recordformatext) - 1);
903 savecallsin[0] = '\0';
905 /* Read in [general] section for persistance */
906 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents")))
907 persistent_agents = ast_true(general_val);
909 /* Read in the [agents] section */
910 v = ast_variable_browse(cfg, "agents");
912 /* Create the interface list */
913 if (!strcasecmp(v->name, "agent")) {
914 add_agent(v->value, 0);
915 } else if (!strcasecmp(v->name, "group")) {
916 group = ast_get_group(v->value);
917 } else if (!strcasecmp(v->name, "autologoff")) {
918 autologoff = atoi(v->value);
921 } else if (!strcasecmp(v->name, "ackcall")) {
922 if (!strcasecmp(v->value, "always"))
924 else if (ast_true(v->value))
928 } else if (!strcasecmp(v->name, "wrapuptime")) {
929 wrapuptime = atoi(v->value);
932 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) {
933 maxlogintries = atoi(v->value);
934 if (maxlogintries < 0)
936 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) {
937 strcpy(agentgoodbye,v->value);
938 } else if (!strcasecmp(v->name, "musiconhold")) {
939 strncpy(moh, v->value, sizeof(moh) - 1);
940 } else if (!strcasecmp(v->name, "updatecdr")) {
941 if (ast_true(v->value))
945 } else if (!strcasecmp(v->name, "recordagentcalls")) {
946 recordagentcalls = ast_true(v->value);
947 } else if (!strcasecmp(v->name, "createlink")) {
948 createlink = ast_true(v->value);
949 } else if (!strcasecmp(v->name, "recordformat")) {
950 strncpy(recordformat, v->value, sizeof(recordformat) - 1);
951 if (!strcasecmp(v->value, "wav49"))
952 strncpy(recordformatext, "WAV", sizeof(recordformatext) - 1);
954 strncpy(recordformatext, v->value, sizeof(recordformatext) - 1);
955 } else if (!strcasecmp(v->name, "urlprefix")) {
956 strncpy(urlprefix, v->value, sizeof(urlprefix) - 2);
957 if (urlprefix[strlen(urlprefix) - 1] != '/')
958 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1);
959 } else if (!strcasecmp(v->name, "savecallsin")) {
960 if (v->value[0] == '/')
961 strncpy(savecallsin, v->value, sizeof(savecallsin) - 2);
963 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value);
964 if (savecallsin[strlen(savecallsin) - 1] != '/')
965 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1);
966 } else if (!strcasecmp(v->name, "custom_beep")) {
967 strncpy(beep, v->value, sizeof(beep) - 1);
981 /* Destroy if appropriate */
984 ast_mutex_destroy(&p->lock);
985 ast_mutex_destroy(&p->app_lock);
988 /* Cause them to hang up */
989 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
996 ast_mutex_unlock(&agentlock);
997 ast_config_destroy(cfg);
1001 static int check_availability(struct agent_pvt *newlyavailable, int needlock)
1003 struct ast_channel *chan=NULL, *parent=NULL;
1004 struct agent_pvt *p;
1008 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent);
1010 ast_mutex_lock(&agentlock);
1013 if (p == newlyavailable) {
1017 ast_mutex_lock(&p->lock);
1018 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1020 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
1021 /* We found a pending call, time to merge */
1022 chan = agent_new(newlyavailable, AST_STATE_DOWN);
1025 ast_mutex_unlock(&p->lock);
1028 ast_mutex_unlock(&p->lock);
1032 ast_mutex_unlock(&agentlock);
1033 if (parent && chan) {
1034 if (newlyavailable->ackcall > 1) {
1035 /* Don't do beep here */
1038 if (option_debug > 2)
1039 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1040 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
1041 if (option_debug > 2)
1042 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
1044 res = ast_waitstream(newlyavailable->chan, "");
1045 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
1049 /* Note -- parent may have disappeared */
1050 if (p->abouttograb) {
1051 newlyavailable->acknowledged = 1;
1052 /* Safe -- agent lock already held */
1053 ast_setstate(parent, AST_STATE_UP);
1054 ast_setstate(chan, AST_STATE_UP);
1055 strncpy(parent->context, chan->context, sizeof(parent->context) - 1);
1056 /* Go ahead and mark the channel as a zombie so that masquerade will
1057 destroy it for us, and we need not call ast_hangup */
1058 ast_mutex_lock(&parent->lock);
1059 ast_set_flag(chan, AST_FLAG_ZOMBIE);
1060 ast_channel_masquerade(parent, chan);
1061 ast_mutex_unlock(&parent->lock);
1065 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n");
1066 agent_cleanup(newlyavailable);
1070 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n");
1071 agent_cleanup(newlyavailable);
1077 static int check_beep(struct agent_pvt *newlyavailable, int needlock)
1079 struct agent_pvt *p;
1082 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent);
1084 ast_mutex_lock(&agentlock);
1087 if (p == newlyavailable) {
1091 ast_mutex_lock(&p->lock);
1092 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1094 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent);
1095 ast_mutex_unlock(&p->lock);
1098 ast_mutex_unlock(&p->lock);
1102 ast_mutex_unlock(&agentlock);
1104 ast_mutex_unlock(&newlyavailable->lock);
1105 if (option_debug > 2)
1106 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language);
1107 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language);
1108 if (option_debug > 2)
1109 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res);
1111 res = ast_waitstream(newlyavailable->chan, "");
1113 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res);
1115 ast_mutex_lock(&newlyavailable->lock);
1120 /*--- agent_request: Part of the Asterisk PBX interface ---*/
1121 static struct ast_channel *agent_request(const char *type, int format, void *data, int *cause)
1123 struct agent_pvt *p;
1124 struct ast_channel *chan = NULL;
1126 ast_group_t groupmatch;
1133 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) {
1134 groupmatch = (1 << groupoff);
1135 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) {
1136 groupmatch = (1 << groupoff);
1142 /* Check actual logged in agents first */
1143 ast_mutex_lock(&agentlock);
1146 ast_mutex_lock(&p->lock);
1147 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) &&
1148 ast_strlen_zero(p->loginchan)) {
1151 if (!p->lastdisc.tv_sec) {
1152 /* Agent must be registered, but not have any active call, and not be in a waiting state */
1153 if (!p->owner && p->chan) {
1155 chan = agent_new(p, AST_STATE_DOWN);
1158 ast_mutex_unlock(&p->lock);
1163 ast_mutex_unlock(&p->lock);
1169 ast_mutex_lock(&p->lock);
1170 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1171 if (p->chan || !ast_strlen_zero(p->loginchan))
1173 gettimeofday(&tv, NULL);
1175 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec);
1177 if (!p->lastdisc.tv_sec || (tv.tv_sec > p->lastdisc.tv_sec)) {
1178 memset(&p->lastdisc, 0, sizeof(p->lastdisc));
1179 /* Agent must be registered, but not have any active call, and not be in a waiting state */
1180 if (!p->owner && p->chan) {
1181 /* Could still get a fixed agent */
1182 chan = agent_new(p, AST_STATE_DOWN);
1183 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) {
1184 /* Adjustable agent */
1185 p->chan = ast_request("Local", format, p->loginchan, cause);
1187 chan = agent_new(p, AST_STATE_DOWN);
1190 ast_mutex_unlock(&p->lock);
1195 ast_mutex_unlock(&p->lock);
1200 if (!chan && waitforagent) {
1201 /* No agent available -- but we're requesting to wait for one.
1202 Allocate a place holder */
1205 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s);
1206 p = add_agent(data, 1);
1207 p->group = groupmatch;
1208 chan = agent_new(p, AST_STATE_DOWN);
1210 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n");
1213 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s);
1216 *cause = AST_CAUSE_BUSY;
1218 *cause = AST_CAUSE_UNREGISTERED;
1219 ast_mutex_unlock(&agentlock);
1223 static int powerof(unsigned int v)
1226 for (x=0;x<32;x++) {
1227 if (v & (1 << x)) return x;
1232 static int action_agents(struct mansession *s, struct message *m)
1234 struct agent_pvt *p;
1235 char *username = NULL;
1236 char *loginChan = NULL;
1237 char *talkingtoChan = NULL;
1238 char *status = NULL;
1240 ast_mutex_lock(&agentlock);
1243 ast_mutex_lock(&p->lock);
1246 AGENT_LOGGEDOFF - Agent isn't logged in
1247 AGENT_IDLE - Agent is logged in, and waiting for call
1248 AGENT_ONCALL - Agent is logged in, and on a call
1249 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */
1251 if(!ast_strlen_zero(p->name)) {
1257 /* Set a default status. It 'should' get changed. */
1258 status = "AGENT_UNKNOWN";
1261 loginChan = p->loginchan;
1262 if(p->owner && p->owner->_bridge) {
1263 talkingtoChan = p->chan->cid.cid_num;
1264 status = "AGENT_ONCALL";
1266 talkingtoChan = "n/a";
1267 status = "AGENT_IDLE";
1269 } else if(!ast_strlen_zero(p->loginchan)) {
1270 loginChan = p->loginchan;
1271 talkingtoChan = "n/a";
1272 status = "AGENT_IDLE";
1273 if(p->acknowledged) {
1274 sprintf(loginChan, " %s (Confirmed)", loginChan);
1278 talkingtoChan = "n/a";
1279 status = "AGENT_LOGGEDOFF";
1282 ast_cli(s->fd, "Event: Agents\r\n"
1286 "LoggedInChan: %s\r\n"
1287 "LoggedInTime: %ld\r\n"
1290 p->agent,p->name,status,loginChan,p->loginstart,talkingtoChan);
1291 ast_mutex_unlock(&p->lock);
1294 ast_mutex_unlock(&agentlock);
1298 static int agent_logoff_cmd(int fd, int argc, char **argv)
1300 struct agent_pvt *p;
1301 char *agent = argv[2] + 6;
1303 if (argc < 3 || argc > 4)
1304 return RESULT_SHOWUSAGE;
1305 if (argc == 4 && strcasecmp(argv[3], "soft"))
1306 return RESULT_SHOWUSAGE;
1308 for (p=agents; p; p=p->next) {
1309 if (!strcasecmp(p->agent, agent)) {
1312 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT);
1315 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
1318 p->loginchan[0] = '\0';
1319 ast_cli(fd, "Logging out %s\n", agent);
1323 return RESULT_SUCCESS;
1326 static char *complete_agent_logoff_cmd(char *line, char *word, int pos, int state)
1328 struct agent_pvt *p;
1329 char name[AST_MAX_AGENT];
1333 for (p=agents; p; p=p->next) {
1334 snprintf(name, sizeof(name), "Agent/%s", p->agent);
1335 if (!strncasecmp(word, name, strlen(word))) {
1336 if (++which > state) {
1337 return strdup(name);
1341 } else if (pos == 3 && state == 0) {
1342 return strdup("soft");
1347 /*--- agents_show: Show agents in cli ---*/
1348 static int agents_show(int fd, int argc, char **argv)
1350 struct agent_pvt *p;
1351 char username[AST_MAX_BUF];
1352 char location[AST_MAX_BUF] = "";
1353 char talkingto[AST_MAX_BUF] = "";
1354 char moh[AST_MAX_BUF];
1357 return RESULT_SHOWUSAGE;
1358 ast_mutex_lock(&agentlock);
1361 ast_mutex_lock(&p->lock);
1364 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group));
1366 ast_cli(fd, "-- Pending call to agent %s\n", p->agent);
1368 if (!ast_strlen_zero(p->name))
1369 snprintf(username, sizeof(username), "(%s) ", p->name);
1373 snprintf(location, sizeof(location), "logged in on %s", p->chan->name);
1374 if (p->owner && ast_bridged_channel(p->owner)) {
1375 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name);
1377 strncpy(talkingto, " is idle", sizeof(talkingto) - 1);
1379 } else if (!ast_strlen_zero(p->loginchan)) {
1380 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan);
1381 talkingto[0] = '\0';
1382 if (p->acknowledged)
1383 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1);
1385 strncpy(location, "not logged in", sizeof(location) - 1);
1386 talkingto[0] = '\0';
1388 if (!ast_strlen_zero(p->moh))
1389 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh);
1390 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent,
1391 username, location, talkingto, moh);
1393 ast_mutex_unlock(&p->lock);
1396 ast_mutex_unlock(&agentlock);
1397 return RESULT_SUCCESS;
1400 static char show_agents_usage[] =
1401 "Usage: show agents\n"
1402 " Provides summary information on agents.\n";
1404 static char agent_logoff_usage[] =
1405 "Usage: agent logoff <channel> [soft]\n"
1406 " Sets an agent as no longer logged in.\n"
1407 " If 'soft' is specified, do not hangup existing calls.\n";
1409 static struct ast_cli_entry cli_show_agents = {
1410 { "show", "agents", NULL }, agents_show,
1411 "Show status of agents", show_agents_usage, NULL };
1413 static struct ast_cli_entry cli_agent_logoff = {
1414 { "agent", "logoff", NULL }, agent_logoff_cmd,
1415 "Sets an agent offline", agent_logoff_usage, complete_agent_logoff_cmd };
1417 STANDARD_LOCAL_USER;
1420 /*--- __login_exec: Log in agent application ---*/
1421 static int __login_exec(struct ast_channel *chan, void *data, int callbackmode)
1425 int max_login_tries = maxlogintries;
1426 struct agent_pvt *p;
1427 struct localuser *u;
1429 int login_state = 0;
1430 char user[AST_MAX_AGENT] = "";
1431 char pass[AST_MAX_AGENT];
1432 char agent[AST_MAX_AGENT] = "";
1433 char xpass[AST_MAX_AGENT] = "";
1436 char *opt_user = NULL;
1437 char *options = NULL;
1440 char *tmpoptions = NULL;
1441 char *context = NULL;
1443 int play_announcement = 1;
1444 char agent_goodbye[AST_MAX_FILENAME_LEN];
1445 int update_cdr = updatecdr;
1446 char *filename = "agent-loginok";
1448 strcpy(agent_goodbye, agentgoodbye);
1451 /* Parse the arguments XXX Check for failure XXX */
1452 strncpy(info, (char *)data, strlen((char *)data) + AST_MAX_EXTENSION-1);
1454 /* Set Channel Specific Login Overrides */
1455 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) {
1456 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"));
1457 if (max_login_tries < 0)
1458 max_login_tries = 0;
1459 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES");
1460 if (option_verbose > 2)
1461 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);
1463 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) {
1464 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR")))
1468 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR");
1469 if (option_verbose > 2)
1470 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name);
1472 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) {
1473 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"));
1474 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE");
1475 if (option_verbose > 2)
1476 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name);
1478 /* End Channel Specific Login Overrides */
1479 /* Read command line options */
1481 options = strchr(opt_user, '|');
1486 context = strchr(options, '@');
1492 while(*exten && ((*exten < '0') || (*exten > '9'))) exten++;
1499 option = (char)options[0];
1500 if ((option >= 0) && (option <= '9'))
1506 play_announcement = 0;
1508 badoption[0] = option;
1509 badoption[1] = '\0';
1510 tmpoptions=badoption;
1511 if (option_verbose > 2)
1512 ast_verbose(VERBOSE_PREFIX_3 "Warning: option %s is unknown.\n",tmpoptions);
1518 /* End command line options */
1520 if (chan->_state != AST_STATE_UP)
1521 res = ast_answer(chan);
1523 if( opt_user && !ast_strlen_zero(opt_user))
1524 strncpy( user, opt_user, AST_MAX_AGENT - 1);
1526 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
1528 while (!res && (max_login_tries==0 || tries < max_login_tries)) {
1530 /* Check for password */
1531 ast_mutex_lock(&agentlock);
1534 if (!strcmp(p->agent, user) && !p->pending)
1535 strncpy(xpass, p->password, sizeof(xpass) - 1);
1538 ast_mutex_unlock(&agentlock);
1540 if (!ast_strlen_zero(xpass))
1541 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0);
1545 errmsg = "agent-incorrect";
1548 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass);
1551 /* Check again for accuracy */
1552 ast_mutex_lock(&agentlock);
1555 ast_mutex_lock(&p->lock);
1556 if (!strcmp(p->agent, user) &&
1557 !strcmp(p->password, pass) && !p->pending) {
1558 login_state = 1; /* Successful Login */
1559 /* Set Channel Specific Agent Overides */
1560 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
1561 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always"))
1563 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL")))
1567 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
1568 if (option_verbose > 2)
1569 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent);
1571 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) {
1572 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"));
1573 if (p->autologoff < 0)
1575 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
1576 if (option_verbose > 2)
1577 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent);
1579 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) {
1580 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"));
1581 if (p->wrapuptime < 0)
1583 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
1584 if (option_verbose > 2)
1585 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent);
1587 /* End Channel Specific Agent Overides */
1589 char last_loginchan[80] = "";
1591 snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
1594 char tmpchan[AST_MAX_BUF] = "";
1596 /* Retrieve login chan */
1599 strncpy(tmpchan, exten, sizeof(tmpchan) - 1);
1602 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0);
1603 if (ast_strlen_zero(tmpchan) || ast_exists_extension(chan, context && !ast_strlen_zero(context) ? context : "default", tmpchan,
1607 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", exten, p->agent);
1611 ast_log(LOG_WARNING, "Extension '%s@%s' is not valid for automatic login of agent '%s'\n", tmpchan, context && !ast_strlen_zero(context) ? context : "default", p->agent);
1612 res = ast_streamfile(chan, "invalid", chan->language);
1614 res = ast_waitstream(chan, AST_DIGIT_ANY);
1627 if (context && !ast_strlen_zero(context) && !ast_strlen_zero(tmpchan))
1628 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context);
1630 strncpy(last_loginchan, p->loginchan, sizeof(last_loginchan) - 1);
1631 strncpy(p->loginchan, tmpchan, sizeof(p->loginchan) - 1);
1633 if (ast_strlen_zero(p->loginchan)) {
1635 filename = "agent-loggedoff";
1637 p->acknowledged = 0;
1638 /* store/clear the global variable that stores agentid based on the callerid */
1639 if (chan->cid.cid_num) {
1640 char agentvar[AST_MAX_BUF];
1641 snprintf(agentvar, sizeof(agentvar), "%s_%s",GETAGENTBYCALLERID, chan->cid.cid_num);
1642 if (ast_strlen_zero(p->loginchan))
1643 pbx_builtin_setvar_helper(NULL, agentvar, NULL);
1645 pbx_builtin_setvar_helper(NULL, agentvar, p->agent);
1647 if(update_cdr && chan->cdr)
1648 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent);
1652 p->loginchan[0] = '\0';
1653 p->acknowledged = 0;
1655 ast_mutex_unlock(&p->lock);
1656 ast_mutex_unlock(&agentlock);
1657 if( !res && play_announcement==1 )
1658 res = ast_streamfile(chan, filename, chan->language);
1660 ast_waitstream(chan, "");
1661 ast_mutex_lock(&agentlock);
1662 ast_mutex_lock(&p->lock);
1664 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats));
1666 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats));
1669 ast_set_write_format(chan, ast_best_codec(chan->nativeformats));
1671 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats));
1673 /* Check once more just in case */
1676 if (callbackmode && !res) {
1677 /* Just say goodbye and be done with it */
1678 if (!ast_strlen_zero(p->loginchan)) {
1679 if (p->loginstart == 0)
1680 time(&p->loginstart);
1681 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin",
1685 p->agent, p->loginchan, chan->uniqueid);
1686 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan);
1687 if (option_verbose > 1)
1688 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan);
1689 ast_device_state_changed("Agent/%s", p->agent);
1691 logintime = time(NULL) - p->loginstart;
1693 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff",
1696 "Logintime: %ld\r\n"
1698 p->agent, last_loginchan, logintime, chan->uniqueid);
1699 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|", last_loginchan, logintime);
1700 if (option_verbose > 1)
1701 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent);
1702 ast_device_state_changed("Agent/%s", p->agent);
1704 ast_mutex_unlock(&agentlock);
1706 res = ast_safe_sleep(chan, 500);
1707 ast_mutex_unlock(&p->lock);
1708 if (persistent_agents)
1711 #ifdef HONOR_MUSIC_CLASS
1712 /* check if the moh class was changed with setmusiconhold */
1713 if (*(chan->musicclass))
1714 strncpy(p->moh, chan->musicclass, sizeof(p->moh) - 1);
1716 ast_moh_start(chan, p->moh);
1717 if (p->loginstart == 0)
1718 time(&p->loginstart);
1719 manager_event(EVENT_FLAG_AGENT, "Agentlogin",
1723 p->agent, chan->name, chan->uniqueid);
1724 if (update_cdr && chan->cdr)
1725 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent);
1726 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name);
1727 if (option_verbose > 1)
1728 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent,
1729 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat));
1730 /* Login this channel and wait for it to
1736 check_availability(p, 0);
1737 ast_mutex_unlock(&p->lock);
1738 ast_mutex_unlock(&agentlock);
1739 ast_device_state_changed("Agent/%s", p->agent);
1741 ast_mutex_lock(&p->lock);
1742 if (p->chan != chan)
1744 ast_mutex_unlock(&p->lock);
1745 /* Yield here so other interested threads can kick in. */
1750 ast_mutex_lock(&agentlock);
1751 ast_mutex_lock(&p->lock);
1752 if (p->lastdisc.tv_sec) {
1753 gettimeofday(&tv, NULL);
1754 if ((tv.tv_sec - p->lastdisc.tv_sec) * 1000 +
1755 (tv.tv_usec - p->lastdisc.tv_usec) / 1000 > p->wrapuptime) {
1757 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent);
1758 memset(&p->lastdisc, 0, sizeof(p->lastdisc));
1762 check_availability(p, 0);
1765 ast_mutex_unlock(&p->lock);
1766 ast_mutex_unlock(&agentlock);
1767 /* Synchronize channel ownership between call to agent and itself. */
1768 ast_mutex_lock( &p->app_lock );
1769 ast_mutex_lock(&p->lock);
1770 p->owning_app = pthread_self();
1771 ast_mutex_unlock(&p->lock);
1773 res = agent_ack_sleep(p);
1775 res = ast_safe_sleep_conditional( chan, 1000,
1776 agent_cont_sleep, p );
1777 ast_mutex_unlock( &p->app_lock );
1778 if ((p->ackcall > 1) && (res == 1)) {
1779 ast_mutex_lock(&agentlock);
1780 ast_mutex_lock(&p->lock);
1781 check_availability(p, 0);
1782 ast_mutex_unlock(&p->lock);
1783 ast_mutex_unlock(&agentlock);
1788 ast_mutex_lock(&p->lock);
1789 if (res && p->owner)
1790 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n");
1791 /* Log us off if appropriate */
1792 if (p->chan == chan)
1794 p->acknowledged = 0;
1795 logintime = time(NULL) - p->loginstart;
1797 ast_mutex_unlock(&p->lock);
1798 manager_event(EVENT_FLAG_AGENT, "Agentlogoff",
1800 "Logintime: %ld\r\n"
1802 p->agent, logintime, chan->uniqueid);
1803 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime);
1804 if (option_verbose > 1)
1805 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent);
1806 /* If there is no owner, go ahead and kill it now */
1807 ast_device_state_changed("Agent/%s", p->agent);
1808 if (p->dead && !p->owner) {
1809 ast_mutex_destroy(&p->lock);
1810 ast_mutex_destroy(&p->app_lock);
1815 ast_mutex_unlock(&p->lock);
1820 ast_mutex_unlock(&p->lock);
1821 errmsg = "agent-alreadyon";
1826 ast_mutex_unlock(&p->lock);
1830 ast_mutex_unlock(&agentlock);
1832 if (!res && (max_login_tries==0 || tries < max_login_tries))
1833 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
1836 LOCAL_USER_REMOVE(u);
1838 res = ast_safe_sleep(chan, 500);
1840 /* AgentLogin() exit */
1841 if (!callbackmode) {
1844 /* AgentCallbackLogin() exit*/
1847 if (login_state > 0) {
1848 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user);
1849 if (login_state==1) {
1850 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on");
1851 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", exten);
1854 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off");
1858 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail");
1860 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num))
1862 /* Do we need to play agent-goodbye now that we will be hanging up? */
1863 if (play_announcement==1) {
1865 res = ast_safe_sleep(chan, 1000);
1866 res = ast_streamfile(chan, agent_goodbye, chan->language);
1868 res = ast_waitstream(chan, "");
1870 res = ast_safe_sleep(chan, 1000);
1873 /* We should never get here if next priority exists when in callbackmode */
1877 static int login_exec(struct ast_channel *chan, void *data)
1879 return __login_exec(chan, data, 0);
1882 static int callback_exec(struct ast_channel *chan, void *data)
1884 return __login_exec(chan, data, 1);
1887 static int agentmonitoroutgoing_exec(struct ast_channel *chan, void *data)
1889 int exitifnoagentid = 0;
1891 int changeoutgoing = 0;
1893 char agent[AST_MAX_AGENT], *tmp;
1896 if (strchr(data, 'd'))
1897 exitifnoagentid = 1;
1898 if (strchr(data, 'n'))
1900 if (strchr(data, 'c'))
1903 if (chan->cid.cid_num) {
1904 char agentvar[AST_MAX_BUF];
1905 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num);
1906 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) {
1907 struct agent_pvt *p = agents;
1908 strncpy(agent, tmp, sizeof(agent) - 1);
1909 ast_mutex_lock(&agentlock);
1911 if (!strcasecmp(p->agent, tmp)) {
1912 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent);
1913 __agent_start_monitoring(chan, p, 1);
1918 ast_mutex_unlock(&agentlock);
1923 ast_log(LOG_WARNING, "Couldn't find the global variable %s, so I can't figure out which agent (if it's an agent) is placing outgoing call.\n", agentvar);
1928 ast_log(LOG_WARNING, "There is no callerid on that call, so I can't figure out which agent (if it's an agent) is placing outgoing call.\n");
1930 /* check if there is n + 101 priority */
1932 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) {
1933 chan->priority+=100;
1934 if (option_verbose > 2)
1935 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority);
1937 else if (exitifnoagentid)
1943 /* Dump AgentCallbackLogin agents to the database for persistence
1944 * (basically copied from dump_queue_members() in apps/app_queue.c)
1947 static void dump_agents(void)
1949 struct agent_pvt *cur_agent = NULL;
1952 if (cur_agent->chan != NULL) {
1953 cur_agent = cur_agent->next;
1956 if (!ast_strlen_zero(cur_agent->loginchan)) {
1957 if (ast_db_put(pa_family, cur_agent->agent, cur_agent->loginchan)) {
1958 ast_log(LOG_WARNING, "failed to create persistent entry!\n");
1961 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n",
1962 cur_agent->agent, cur_agent->loginchan);
1967 /* Delete - no agent or there is an error */
1968 ast_db_del(pa_family, cur_agent->agent);
1970 cur_agent = cur_agent->next;
1974 /* Reload the persistent agents from astdb */
1975 static void reload_agents(void)
1978 struct ast_db_entry *pa_db_tree = NULL;
1979 int pa_family_len = 0;
1980 struct agent_pvt *cur_agent = NULL;
1981 char agent_data[80];
1983 pa_db_tree = ast_db_gettree(pa_family, NULL);
1985 pa_family_len = strlen(pa_family);
1986 ast_mutex_lock(&agentlock);
1987 while (pa_db_tree) {
1988 pa_agent_num = pa_db_tree->key + pa_family_len + 2;
1991 ast_mutex_lock(&cur_agent->lock);
1993 if (strcmp(pa_agent_num, cur_agent->agent) == 0)
1996 ast_mutex_unlock(&cur_agent->lock);
1997 cur_agent = cur_agent->next;
2000 ast_db_del(pa_family, pa_agent_num);
2001 pa_db_tree = pa_db_tree->next;
2004 ast_mutex_unlock(&cur_agent->lock);
2005 if (!ast_db_get(pa_family, pa_agent_num, agent_data, 80)) {
2007 ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n",
2008 cur_agent->agent, agent_data);
2010 strncpy(cur_agent->loginchan,agent_data,80);
2011 if (cur_agent->loginstart == 0)
2012 time(&cur_agent->loginstart);
2013 ast_device_state_changed("Agent/%s", cur_agent->agent);
2015 pa_db_tree = pa_db_tree->next;
2017 ast_log(LOG_NOTICE, "Agents sucessfully reloaded from database.\n");
2018 ast_mutex_unlock(&agentlock);
2020 ast_db_freetree(pa_db_tree);
2026 /*--- agent_devicestate: Part of PBX channel interface ---*/
2027 static int agent_devicestate(void *data)
2029 struct agent_pvt *p;
2031 ast_group_t groupmatch;
2034 int res = AST_DEVICE_INVALID;
2037 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) {
2038 groupmatch = (1 << groupoff);
2039 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) {
2040 groupmatch = (1 << groupoff);
2046 /* Check actual logged in agents first */
2047 ast_mutex_lock(&agentlock);
2050 ast_mutex_lock(&p->lock);
2051 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
2053 if (res != AST_DEVICE_INUSE)
2054 res = AST_DEVICE_BUSY;
2056 if (res == AST_DEVICE_BUSY)
2057 res = AST_DEVICE_INUSE;
2058 if (p->chan || !ast_strlen_zero(p->loginchan)) {
2059 if (res == AST_DEVICE_INVALID)
2060 res = AST_DEVICE_UNKNOWN;
2061 } else if (res == AST_DEVICE_INVALID)
2062 res = AST_DEVICE_UNAVAILABLE;
2064 if (!strcmp(data, p->agent)) {
2065 ast_mutex_unlock(&p->lock);
2069 ast_mutex_unlock(&p->lock);
2072 ast_mutex_unlock(&agentlock);
2076 /*--- load_module: Initialize channel module ---*/
2079 /* Make sure we can register our agent channel type */
2080 if (ast_channel_register_ex(channeltype, tdesc, capability, agent_request, agent_devicestate)) {
2081 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channeltype);
2084 /* Dialplan applications */
2085 ast_register_application(app, login_exec, synopsis, descrip);
2086 ast_register_application(app2, callback_exec, synopsis2, descrip2);
2087 ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3);
2088 /* Manager command */
2089 ast_manager_register2("Agents", 0, action_agents, "Agents", mandescr_agents);
2090 /* CLI Application */
2091 ast_cli_register(&cli_show_agents);
2092 ast_cli_register(&cli_agent_logoff);
2093 /* Read in the config */
2094 read_agent_config();
2095 if (persistent_agents)
2102 read_agent_config();
2103 if (persistent_agents)
2110 struct agent_pvt *p;
2111 /* First, take us out of the channel loop */
2112 /* Unregister CLI application */
2113 ast_cli_unregister(&cli_show_agents);
2114 ast_cli_unregister(&cli_agent_logoff);
2115 /* Unregister dialplan applications */
2116 ast_unregister_application(app);
2117 ast_unregister_application(app2);
2118 ast_unregister_application(app3);
2119 /* Unregister manager command */
2120 ast_manager_unregister("Agents");
2121 /* Unregister channel */
2122 ast_channel_unregister(channeltype);
2123 if (!ast_mutex_lock(&agentlock)) {
2124 /* Hangup all interfaces if they have an owner */
2128 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
2132 ast_mutex_unlock(&agentlock);
2134 ast_log(LOG_WARNING, "Unable to lock the monitor\n");
2143 ast_mutex_lock(&usecnt_lock);
2145 ast_mutex_unlock(&usecnt_lock);
2151 return ASTERISK_GPL_KEY;