01938396d0b44595d17aeacfa82c206d12b9cdb7
[asterisk/asterisk.git] / channels / chan_agent.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19
20 /*! \file
21  * 
22  * \brief Implementation of Agents (proxy channel)
23  *
24  * \author Mark Spencer <markster@digium.com>
25  *
26  * This file is the implementation of Agents modules.
27  * It is a dynamic module that is loaded by Asterisk. 
28  * \par See also
29  * \arg \ref Config_agent
30  *
31  * \ingroup channel_drivers
32  */
33 /*** MODULEINFO
34         <depend>chan_local</depend>
35         <depend>res_monitor</depend>
36         <support_level>core</support_level>
37  ***/
38
39 #include "asterisk.h"
40
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
42
43 #include <sys/socket.h>
44 #include <fcntl.h>
45 #include <netdb.h>
46 #include <netinet/in.h>
47 #include <arpa/inet.h>
48 #include <sys/signal.h>
49
50 #include "asterisk/lock.h"
51 #include "asterisk/channel.h"
52 #include "asterisk/config.h"
53 #include "asterisk/module.h"
54 #include "asterisk/pbx.h"
55 #include "asterisk/sched.h"
56 #include "asterisk/io.h"
57 #include "asterisk/acl.h"
58 #include "asterisk/callerid.h"
59 #include "asterisk/file.h"
60 #include "asterisk/cli.h"
61 #include "asterisk/app.h"
62 #include "asterisk/musiconhold.h"
63 #include "asterisk/manager.h"
64 #include "asterisk/features.h"
65 #include "asterisk/utils.h"
66 #include "asterisk/causes.h"
67 #include "asterisk/astdb.h"
68 #include "asterisk/devicestate.h"
69 #include "asterisk/monitor.h"
70 #include "asterisk/stringfields.h"
71 #include "asterisk/event.h"
72 #include "asterisk/data.h"
73
74 /*** DOCUMENTATION
75         <application name="AgentLogin" language="en_US">
76                 <synopsis>
77                         Call agent login.
78                 </synopsis>
79                 <syntax>
80                         <parameter name="AgentNo" />
81                         <parameter name="options">
82                                 <optionlist>
83                                         <option name="s">
84                                                 <para>silent login - do not announce the login ok segment after
85                                                 agent logged on/off</para>
86                                         </option>
87                                 </optionlist>
88                         </parameter>
89                 </syntax>
90                 <description>
91                         <para>Asks the agent to login to the system. Always returns <literal>-1</literal>.
92                         While logged in, the agent can receive calls and will hear a <literal>beep</literal>
93                         when a new call comes in. The agent can dump the call by pressing the star key.</para>
94                 </description>
95                 <see-also>
96                         <ref type="application">Queue</ref>
97                         <ref type="application">AddQueueMember</ref>
98                         <ref type="application">RemoveQueueMember</ref>
99                         <ref type="application">PauseQueueMember</ref>
100                         <ref type="application">UnpauseQueueMember</ref>
101                         <ref type="function">AGENT</ref>
102                         <ref type="filename">agents.conf</ref>
103                         <ref type="filename">queues.conf</ref>
104                 </see-also>
105         </application>
106         <application name="AgentMonitorOutgoing" language="en_US">
107                 <synopsis>
108                         Record agent's outgoing call.
109                 </synopsis>
110                 <syntax>
111                         <parameter name="options">
112                                 <optionlist>
113                                         <option name="d">
114                                                 <para>make the app return <literal>-1</literal> if there is an error condition.</para>
115                                         </option>
116                                         <option name="c">
117                                                 <para>change the CDR so that the source of the call is
118                                                 <literal>Agent/agent_id</literal></para>
119                                         </option>
120                                         <option name="n">
121                                                 <para>don't generate the warnings when there is no callerid or the
122                                                 agentid is not known. It's handy if you want to have one context
123                                                 for agent and non-agent calls.</para>
124                                         </option>
125                                 </optionlist>
126                         </parameter>
127                 </syntax>
128                 <description>
129                         <para>Tries to figure out the id of the agent who is placing outgoing call based on
130                         comparison of the callerid of the current interface and the global variable
131                         placed by the AgentCallbackLogin application. That's why it should be used only
132                         with the AgentCallbackLogin app. Uses the monitoring functions in chan_agent
133                         instead of Monitor application. That has to be configured in the
134                         <filename>agents.conf</filename> file.</para>
135                         <para>Normally the app returns <literal>0</literal> unless the options are passed.</para>
136                 </description>
137                 <see-also>
138                         <ref type="filename">agents.conf</ref>
139                 </see-also>
140         </application>
141         <function name="AGENT" language="en_US">
142                 <synopsis>
143                         Gets information about an Agent
144                 </synopsis>
145                 <syntax argsep=":">
146                         <parameter name="agentid" required="true" />
147                         <parameter name="item">
148                                 <para>The valid items to retrieve are:</para>
149                                 <enumlist>
150                                         <enum name="status">
151                                                 <para>(default) The status of the agent (LOGGEDIN | LOGGEDOUT)</para>
152                                         </enum>
153                                         <enum name="password">
154                                                 <para>The password of the agent</para>
155                                         </enum>
156                                         <enum name="name">
157                                                 <para>The name of the agent</para>
158                                         </enum>
159                                         <enum name="mohclass">
160                                                 <para>MusicOnHold class</para>
161                                         </enum>
162                                         <enum name="channel">
163                                                 <para>The name of the active channel for the Agent (AgentLogin)</para>
164                                         </enum>
165                                         <enum name="fullchannel">
166                                                 <para>The untruncated name of the active channel for the Agent (AgentLogin)</para>
167                                         </enum>
168                                 </enumlist>
169                         </parameter>
170                 </syntax>
171                 <description></description>
172         </function>
173         <manager name="Agents" language="en_US">
174                 <synopsis>
175                         Lists agents and their status.
176                 </synopsis>
177                 <syntax>
178                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
179                 </syntax>
180                 <description>
181                         <para>Will list info about all possible agents.</para>
182                 </description>
183         </manager>
184         <manager name="AgentLogoff" language="en_US">
185                 <synopsis>
186                         Sets an agent as no longer logged in.
187                 </synopsis>
188                 <syntax>
189                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
190                         <parameter name="Agent" required="true">
191                                 <para>Agent ID of the agent to log off.</para>
192                         </parameter>
193                         <parameter name="Soft">
194                                 <para>Set to <literal>true</literal> to not hangup existing calls.</para>
195                         </parameter>
196                 </syntax>
197                 <description>
198                         <para>Sets an agent as no longer logged in.</para>
199                 </description>
200         </manager>
201  ***/
202
203 static const char tdesc[] = "Call Agent Proxy Channel";
204 static const char config[] = "agents.conf";
205
206 static const char app[] = "AgentLogin";
207 static const char app3[] = "AgentMonitorOutgoing";
208
209 static char moh[80] = "default";
210
211 #define AST_MAX_AGENT   80                          /*!< Agent ID or Password max length */
212 #define AST_MAX_BUF     256
213 #define AST_MAX_FILENAME_LEN    256
214
215 static const char pa_family[] = "Agents";          /*!< Persistent Agents astdb family */
216 #define PA_MAX_LEN 2048                             /*!< The maximum length of each persistent member agent database entry */
217
218 #define DEFAULT_ACCEPTDTMF '#'
219 #define DEFAULT_ENDDTMF '*'
220
221 static ast_group_t group;
222 static int autologoff;
223 static int wrapuptime;
224 static int ackcall;
225 static int endcall;
226 static int multiplelogin = 1;
227 static int autologoffunavail = 0;
228 static char acceptdtmf = DEFAULT_ACCEPTDTMF;
229 static char enddtmf = DEFAULT_ENDDTMF;
230
231 static int maxlogintries = 3;
232 static char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye";
233
234 static int recordagentcalls = 0;
235 static char recordformat[AST_MAX_BUF] = "";
236 static char recordformatext[AST_MAX_BUF] = "";
237 static char urlprefix[AST_MAX_BUF] = "";
238 static char savecallsin[AST_MAX_BUF] = "";
239 static int updatecdr = 0;
240 static char beep[AST_MAX_BUF] = "beep";
241
242 #define GETAGENTBYCALLERID      "AGENTBYCALLERID"
243
244 enum {
245         AGENT_FLAG_ACKCALL = (1 << 0),
246         AGENT_FLAG_AUTOLOGOFF = (1 << 1),
247         AGENT_FLAG_WRAPUPTIME = (1 << 2),
248         AGENT_FLAG_ACCEPTDTMF = (1 << 3),
249         AGENT_FLAG_ENDDTMF = (1 << 4),
250 };
251
252 /*! \brief Structure representing an agent.  */
253 struct agent_pvt {
254         ast_mutex_t lock;              /*!< Channel private lock */
255         int dead;                      /*!< Poised for destruction? */
256         int pending;                   /*!< Not a real agent -- just pending a match */
257         int abouttograb;               /*!< About to grab */
258         int autologoff;                /*!< Auto timeout time */
259         int ackcall;                   /*!< ackcall */
260         int deferlogoff;               /*!< Defer logoff to hangup */
261         char acceptdtmf;
262         char enddtmf;
263         time_t loginstart;             /*!< When agent first logged in (0 when logged off) */
264         time_t start;                  /*!< When call started */
265         struct timeval lastdisc;       /*!< When last disconnected */
266         int wrapuptime;                /*!< Wrapup time in ms */
267         ast_group_t group;             /*!< Group memberships */
268         int acknowledged;              /*!< Acknowledged */
269         char moh[80];                  /*!< Which music on hold */
270         char agent[AST_MAX_AGENT];     /*!< Agent ID */
271         char password[AST_MAX_AGENT];  /*!< Password for Agent login */
272         char name[AST_MAX_AGENT];
273         int app_lock_flag;
274         ast_cond_t app_complete_cond;
275         ast_cond_t login_wait_cond;
276         volatile int app_sleep_cond;   /**< Sleep condition for the login app */
277         struct ast_channel *owner;     /**< Agent */
278         char logincallerid[80];        /**< Caller ID they had when they logged in */
279         struct ast_channel *chan;      /**< Channel we use */
280         unsigned int flags;            /**< Flags show if settings were applied with channel vars */
281         AST_LIST_ENTRY(agent_pvt) list; /**< Next Agent in the linked list. */
282 };
283
284 #define DATA_EXPORT_AGENT(MEMBER)                               \
285         MEMBER(agent_pvt, autologoff, AST_DATA_INTEGER)         \
286         MEMBER(agent_pvt, ackcall, AST_DATA_BOOLEAN)            \
287         MEMBER(agent_pvt, deferlogoff, AST_DATA_BOOLEAN)        \
288         MEMBER(agent_pvt, wrapuptime, AST_DATA_MILLISECONDS)    \
289         MEMBER(agent_pvt, acknowledged, AST_DATA_BOOLEAN)       \
290         MEMBER(agent_pvt, name, AST_DATA_STRING)                \
291         MEMBER(agent_pvt, password, AST_DATA_PASSWORD)          \
292         MEMBER(agent_pvt, acceptdtmf, AST_DATA_CHARACTER)       \
293         MEMBER(agent_pvt, logincallerid, AST_DATA_STRING)
294
295 AST_DATA_STRUCTURE(agent_pvt, DATA_EXPORT_AGENT);
296
297 static AST_LIST_HEAD_STATIC(agents, agent_pvt); /*!< Holds the list of agents (loaded form agents.conf). */
298
299 #define CHECK_FORMATS(ast, p) do { \
300         if (p->chan) {\
301                 if (!(ast_format_cap_identical(ast_channel_nativeformats(ast), ast_channel_nativeformats(p->chan)))) { \
302                         char tmp1[256], tmp2[256]; \
303                         ast_debug(1, "Native formats changing from '%s' to '%s'\n", ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(ast)), ast_getformatname_multiple(tmp2, sizeof(tmp2), ast_channel_nativeformats(p->chan))); \
304                         /* Native formats changed, reset things */ \
305                         ast_format_cap_copy(ast_channel_nativeformats(ast), ast_channel_nativeformats(p->chan)); \
306                         ast_debug(1, "Resetting read to '%s' and write to '%s'\n", ast_getformatname(ast_channel_readformat(ast)), ast_getformatname(ast_channel_writeformat(ast)));\
307                         ast_set_read_format(ast, ast_channel_readformat(ast)); \
308                         ast_set_write_format(ast, ast_channel_writeformat(ast)); \
309                 } \
310                 if ((ast_format_cmp(ast_channel_readformat(p->chan), ast_channel_rawreadformat(ast)) != AST_FORMAT_CMP_EQUAL) && !ast_channel_generator(p->chan))  \
311                         ast_set_read_format(p->chan, ast_channel_rawreadformat(ast)); \
312                 if ((ast_format_cmp(ast_channel_writeformat(p->chan), ast_channel_rawwriteformat(ast)) != AST_FORMAT_CMP_EQUAL) && !ast_channel_generator(p->chan)) \
313                         ast_set_write_format(p->chan, ast_channel_rawwriteformat(ast)); \
314         } \
315 } while(0)
316
317 /*! \brief Cleanup moves all the relevant FD's from the 2nd to the first, but retains things
318    properly for a timingfd XXX This might need more work if agents were logged in as agents or other
319    totally impractical combinations XXX */
320
321 #define CLEANUP(ast, p) do { \
322         int x; \
323         if (p->chan) { \
324                 for (x = 0; x < AST_MAX_FDS; x++) { \
325                         if (x != AST_TIMING_FD) { \
326                                 ast_channel_set_fd(ast, x, ast_channel_fd(p->chan, x)); \
327                         } \
328                 } \
329                 ast_channel_set_fd(ast, AST_AGENT_FD, ast_channel_fd(p->chan, AST_TIMING_FD)); \
330         } \
331 } while(0)
332
333 /*--- Forward declarations */
334 static struct ast_channel *agent_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause);
335 static int agent_devicestate(const char *data);
336 static int agent_digit_begin(struct ast_channel *ast, char digit);
337 static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration);
338 static int agent_call(struct ast_channel *ast, const char *dest, int timeout);
339 static int agent_hangup(struct ast_channel *ast);
340 static int agent_answer(struct ast_channel *ast);
341 static struct ast_frame *agent_read(struct ast_channel *ast);
342 static int agent_write(struct ast_channel *ast, struct ast_frame *f);
343 static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen);
344 static int agent_sendtext(struct ast_channel *ast, const char *text);
345 static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
346 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
347 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge);
348 static char *complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state);
349 static struct ast_channel* agent_get_base_channel(struct ast_channel *chan);
350 static int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base);
351 static int agent_logoff(const char *agent, int soft);
352
353 /*! \brief Channel interface description for PBX integration */
354 static struct ast_channel_tech agent_tech = {
355         .type = "Agent",
356         .description = tdesc,
357         .requester = agent_request,
358         .devicestate = agent_devicestate,
359         .send_digit_begin = agent_digit_begin,
360         .send_digit_end = agent_digit_end,
361         .call = agent_call,
362         .hangup = agent_hangup,
363         .answer = agent_answer,
364         .read = agent_read,
365         .write = agent_write,
366         .write_video = agent_write,
367         .send_html = agent_sendhtml,
368         .send_text = agent_sendtext,
369         .exception = agent_read,
370         .indicate = agent_indicate,
371         .fixup = agent_fixup,
372         .bridged_channel = agent_bridgedchannel,
373         .get_base_channel = agent_get_base_channel,
374         .set_base_channel = agent_set_base_channel,
375 };
376
377 /*!
378  * \brief Locks the owning channel for a LOCKED pvt while obeying locking order. The pvt
379  * must enter this function locked and will be returned locked, but this function will
380  * unlock the pvt for a short time, so it can't be used while expecting the pvt to remain
381  * static. If function returns a non NULL channel, it will need to be unlocked and
382  * unrefed once it is no longer needed.
383  *
384  * \param pvt Pointer to the LOCKED agent_pvt for which the owner is needed
385  * \ret locked channel which owns the pvt at the time of completion. NULL if not available.
386  */
387 static struct ast_channel *agent_lock_owner(struct agent_pvt *pvt)
388 {
389         struct ast_channel *owner;
390
391         for (;;) {
392                 if (!pvt->owner) { /* No owner. Nothing to do. */
393                         return NULL;
394                 }
395
396                 /* If we don't ref the owner, it could be killed when we unlock the pvt. */
397                 owner = ast_channel_ref(pvt->owner);
398
399                 /* Locking order requires us to lock channel, then pvt. */
400                 ast_mutex_unlock(&pvt->lock);
401                 ast_channel_lock(owner);
402                 ast_mutex_lock(&pvt->lock);
403
404                 /* Check if owner changed during pvt unlock period */
405                 if (owner != pvt->owner) { /* Channel changed. Unref and do another pass. */
406                         ast_channel_unlock(owner);
407                         owner = ast_channel_unref(owner);
408                 } else { /* Channel stayed the same. Return it. */
409                         return owner;
410                 }
411         }
412 }
413
414 /*!
415  * Adds an agent to the global list of agents.
416  *
417  * \param agent A string with the username, password and real name of an agent. As defined in agents.conf. Example: "13,169,John Smith"
418  * \param pending If it is pending or not.
419  * @return The just created agent.
420  * \sa agent_pvt, agents.
421  */
422 static struct agent_pvt *add_agent(const char *agent, int pending)
423 {
424         char *parse;
425         AST_DECLARE_APP_ARGS(args,
426                 AST_APP_ARG(agt);
427                 AST_APP_ARG(password);
428                 AST_APP_ARG(name);
429         );
430         char *password = NULL;
431         char *name = NULL;
432         char *agt = NULL;
433         struct agent_pvt *p;
434
435         parse = ast_strdupa(agent);
436
437         /* Extract username (agt), password and name from agent (args). */
438         AST_STANDARD_APP_ARGS(args, parse);
439
440         if(args.argc == 0) {
441                 ast_log(LOG_WARNING, "A blank agent line!\n");
442                 return NULL;
443         }
444
445         if(ast_strlen_zero(args.agt) ) {
446                 ast_log(LOG_WARNING, "An agent line with no agentid!\n");
447                 return NULL;
448         } else
449                 agt = args.agt;
450
451         if(!ast_strlen_zero(args.password)) {
452                 password = args.password;
453                 while (*password && *password < 33) password++;
454         }
455         if(!ast_strlen_zero(args.name)) {
456                 name = args.name;
457                 while (*name && *name < 33) name++;
458         }
459         
460         /* Are we searching for the agent here ? To see if it exists already ? */
461         AST_LIST_TRAVERSE(&agents, p, list) {
462                 if (!pending && !strcmp(p->agent, agt))
463                         break;
464         }
465         if (!p) {
466                 // Build the agent.
467                 if (!(p = ast_calloc(1, sizeof(*p))))
468                         return NULL;
469                 ast_copy_string(p->agent, agt, sizeof(p->agent));
470                 ast_mutex_init(&p->lock);
471                 ast_cond_init(&p->app_complete_cond, NULL);
472                 ast_cond_init(&p->login_wait_cond, NULL);
473                 p->app_lock_flag = 0;
474                 p->app_sleep_cond = 1;
475                 p->group = group;
476                 p->pending = pending;
477                 AST_LIST_INSERT_TAIL(&agents, p, list);
478         }
479         
480         ast_copy_string(p->password, password ? password : "", sizeof(p->password));
481         ast_copy_string(p->name, name ? name : "", sizeof(p->name));
482         ast_copy_string(p->moh, moh, sizeof(p->moh));
483         if (!ast_test_flag(p, AGENT_FLAG_ACKCALL)) {
484                 p->ackcall = ackcall;
485         }
486         if (!ast_test_flag(p, AGENT_FLAG_AUTOLOGOFF)) {
487                 p->autologoff = autologoff;
488         }
489         if (!ast_test_flag(p, AGENT_FLAG_ACCEPTDTMF)) {
490                 p->acceptdtmf = acceptdtmf;
491         }
492         if (!ast_test_flag(p, AGENT_FLAG_ENDDTMF)) {
493                 p->enddtmf = enddtmf;
494         }
495
496         /* If someone reduces the wrapuptime and reloads, we want it
497          * to change the wrapuptime immediately on all calls */
498         if (!ast_test_flag(p, AGENT_FLAG_WRAPUPTIME) && p->wrapuptime > wrapuptime) {
499                 struct timeval now = ast_tvnow();
500                 /* XXX check what is this exactly */
501
502                 /* We won't be pedantic and check the tv_usec val */
503                 if (p->lastdisc.tv_sec > (now.tv_sec + wrapuptime/1000)) {
504                         p->lastdisc.tv_sec = now.tv_sec + wrapuptime/1000;
505                         p->lastdisc.tv_usec = now.tv_usec;
506                 }
507         }
508         p->wrapuptime = wrapuptime;
509
510         if (pending)
511                 p->dead = 1;
512         else
513                 p->dead = 0;
514         return p;
515 }
516
517 /*!
518  * Deletes an agent after doing some clean up.
519  * Further documentation: How safe is this function ? What state should the agent be to be cleaned.
520  * \param p Agent to be deleted.
521  * \returns Always 0.
522  */
523 static int agent_cleanup(struct agent_pvt *p)
524 {
525         struct ast_channel *chan = NULL;
526         ast_mutex_lock(&p->lock);
527         chan = p->owner;
528         p->owner = NULL;
529         ast_channel_tech_pvt_set(chan, NULL);
530         /* Release ownership of the agent to other threads (presumably running the login app). */
531         p->app_sleep_cond = 1;
532         p->app_lock_flag = 0;
533         ast_cond_signal(&p->app_complete_cond);
534         if (chan) {
535                 chan = ast_channel_release(chan);
536         }
537         if (p->dead) {
538                 ast_mutex_unlock(&p->lock);
539                 ast_mutex_destroy(&p->lock);
540                 ast_cond_destroy(&p->app_complete_cond);
541                 ast_cond_destroy(&p->login_wait_cond);
542                 ast_free(p);
543         }
544         return 0;
545 }
546
547 static int check_availability(struct agent_pvt *newlyavailable, int needlock);
548
549 static int agent_answer(struct ast_channel *ast)
550 {
551         ast_log(LOG_WARNING, "Huh?  Agent is being asked to answer?\n");
552         return -1;
553 }
554
555 static int __agent_start_monitoring(struct ast_channel *ast, struct agent_pvt *p, int needlock)
556 {
557         char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer;
558         char filename[AST_MAX_BUF];
559         int res = -1;
560         if (!p)
561                 return -1;
562         if (!ast_channel_monitor(ast)) {
563                 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast_channel_uniqueid(ast));
564                 /* substitute . for - */
565                 if ((pointer = strchr(filename, '.')))
566                         *pointer = '-';
567                 snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename);
568                 ast_monitor_start(ast, recordformat, tmp, needlock, X_REC_IN | X_REC_OUT);
569                 ast_monitor_setjoinfiles(ast, 1);
570                 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext);
571 #if 0
572                 ast_verbose("name is %s, link is %s\n",tmp, tmp2);
573 #endif
574                 if (!ast_channel_cdr(ast))
575                         ast_channel_cdr_set(ast, ast_cdr_alloc());
576                 ast_cdr_setuserfield(ast, tmp2);
577                 res = 0;
578         } else
579                 ast_log(LOG_ERROR, "Recording already started on that call.\n");
580         return res;
581 }
582
583 static int agent_start_monitoring(struct ast_channel *ast, int needlock)
584 {
585         return __agent_start_monitoring(ast, ast_channel_tech_pvt(ast), needlock);
586 }
587
588 static struct ast_frame *agent_read(struct ast_channel *ast)
589 {
590         struct agent_pvt *p = ast_channel_tech_pvt(ast);
591         struct ast_frame *f = NULL;
592         static struct ast_frame answer_frame = { AST_FRAME_CONTROL, { AST_CONTROL_ANSWER } };
593         int cur_time = time(NULL);
594         struct ast_channel *owner;
595
596         ast_mutex_lock(&p->lock);
597         owner = agent_lock_owner(p);
598
599         CHECK_FORMATS(ast, p);
600         if (!p->start) {
601                 p->start = cur_time;
602         }
603         if (p->chan) {
604                 ast_copy_flags(ast_channel_flags(p->chan), ast_channel_flags(ast), AST_FLAG_EXCEPTION);
605                 ast_channel_fdno_set(p->chan, (ast_channel_fdno(ast) == AST_AGENT_FD) ? AST_TIMING_FD : ast_channel_fdno(ast));
606                 f = ast_read(p->chan);
607         } else
608                 f = &ast_null_frame;
609         if (!f) {
610                 /* If there's a channel, make it NULL */
611                 if (p->chan) {
612                         ast_channel_internal_bridged_channel_set(p->chan, NULL);
613                         p->chan = NULL;
614                         ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
615                         p->acknowledged = 0;
616                 }
617         } else {
618                 /* if acknowledgement is not required, and the channel is up, we may have missed
619                         an AST_CONTROL_ANSWER (if there was one), so mark the call acknowledged anyway */
620                 if (!p->ackcall && !p->acknowledged && p->chan && (ast_channel_state(p->chan) == AST_STATE_UP)) {
621                         p->acknowledged = 1;
622                 }
623
624                 if (!p->acknowledged) {
625                         int howlong = cur_time - p->start;
626                         if (p->autologoff && (howlong >= p->autologoff)) {
627                                 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong);
628                                 if (owner || p->chan) {
629                                         if (owner) {
630                                                 ast_softhangup(owner, AST_SOFTHANGUP_EXPLICIT);
631                                                 ast_channel_unlock(owner);
632                                                 owner = ast_channel_unref(owner);
633                                         }
634
635                                         while (p->chan && ast_channel_trylock(p->chan)) {
636                                                 DEADLOCK_AVOIDANCE(&p->lock);
637                                         }
638                                         if (p->chan) {
639                                                 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
640                                                 ast_channel_unlock(p->chan);
641                                         }
642                                 }
643                         }
644                 }
645                 switch (f->frametype) {
646                 case AST_FRAME_CONTROL:
647                         if (f->subclass.integer == AST_CONTROL_ANSWER) {
648                                 if (p->ackcall) {
649                                         ast_verb(3, "%s answered, waiting for '%c' to acknowledge\n", ast_channel_name(p->chan), p->acceptdtmf);
650                                         /* Don't pass answer along */
651                                         ast_frfree(f);
652                                         f = &ast_null_frame;
653                                 } else {
654                                         p->acknowledged = 1;
655                                         /* Use the builtin answer frame for the 
656                                            recording start check below. */
657                                         ast_frfree(f);
658                                         f = &answer_frame;
659                                 }
660                         }
661                         break;
662                 case AST_FRAME_DTMF_BEGIN:
663                         /*ignore DTMF begin's as it can cause issues with queue announce files*/
664                         if((!p->acknowledged && f->subclass.integer == p->acceptdtmf) || (f->subclass.integer == p->enddtmf && endcall)){
665                                 ast_frfree(f);
666                                 f = &ast_null_frame;
667                         }
668                         break;
669                 case AST_FRAME_DTMF_END:
670                         if (!p->acknowledged && (f->subclass.integer == p->acceptdtmf)) {
671                                 ast_verb(3, "%s acknowledged\n", ast_channel_name(p->chan));
672                                 p->acknowledged = 1;
673                                 ast_frfree(f);
674                                 f = &answer_frame;
675                         } else if (f->subclass.integer == p->enddtmf && endcall) {
676                                 /* terminates call */
677                                 ast_frfree(f);
678                                 f = NULL;
679                         }
680                         break;
681                 case AST_FRAME_VOICE:
682                 case AST_FRAME_VIDEO:
683                         /* don't pass voice or video until the call is acknowledged */
684                         if (!p->acknowledged) {
685                                 ast_frfree(f);
686                                 f = &ast_null_frame;
687                         }
688                 default:
689                         /* pass everything else on through */
690                         break;
691                 }
692         }
693
694         if (owner) {
695                 ast_channel_unlock(owner);
696                 owner = ast_channel_unref(owner);
697         }
698
699         CLEANUP(ast,p);
700         if (p->chan && !ast_channel_internal_bridged_channel(p->chan)) {
701                 if (strcasecmp(ast_channel_tech(p->chan)->type, "Local")) {
702                         ast_channel_internal_bridged_channel_set(p->chan, ast);
703                         if (p->chan)
704                                 ast_debug(1, "Bridge on '%s' being set to '%s' (3)\n", ast_channel_name(p->chan), ast_channel_name(ast_channel_internal_bridged_channel(p->chan)));
705                 }
706         }
707         ast_mutex_unlock(&p->lock);
708         if (recordagentcalls && f == &answer_frame)
709                 agent_start_monitoring(ast,0);
710         return f;
711 }
712
713 static int agent_sendhtml(struct ast_channel *ast, int subclass, const char *data, int datalen)
714 {
715         struct agent_pvt *p = ast_channel_tech_pvt(ast);
716         int res = -1;
717         ast_mutex_lock(&p->lock);
718         if (p->chan) 
719                 res = ast_channel_sendhtml(p->chan, subclass, data, datalen);
720         ast_mutex_unlock(&p->lock);
721         return res;
722 }
723
724 static int agent_sendtext(struct ast_channel *ast, const char *text)
725 {
726         struct agent_pvt *p = ast_channel_tech_pvt(ast);
727         int res = -1;
728         ast_mutex_lock(&p->lock);
729         if (p->chan) 
730                 res = ast_sendtext(p->chan, text);
731         ast_mutex_unlock(&p->lock);
732         return res;
733 }
734
735 static int agent_write(struct ast_channel *ast, struct ast_frame *f)
736 {
737         struct agent_pvt *p = ast_channel_tech_pvt(ast);
738         int res = -1;
739         CHECK_FORMATS(ast, p);
740         ast_mutex_lock(&p->lock);
741         if (!p->chan) 
742                 res = 0;
743         else {
744                 if ((f->frametype != AST_FRAME_VOICE) ||
745                     (f->frametype != AST_FRAME_VIDEO) ||
746                     (ast_format_cmp(&f->subclass.format, ast_channel_writeformat(p->chan)) != AST_FORMAT_CMP_NOT_EQUAL)) {
747                         res = ast_write(p->chan, f);
748                 } else {
749                         ast_debug(1, "Dropping one incompatible %s frame on '%s' to '%s'\n", 
750                                 f->frametype == AST_FRAME_VOICE ? "audio" : "video",
751                                 ast_channel_name(ast), ast_channel_name(p->chan));
752                         res = 0;
753                 }
754         }
755         CLEANUP(ast, p);
756         ast_mutex_unlock(&p->lock);
757         return res;
758 }
759
760 static int agent_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
761 {
762         struct agent_pvt *p = ast_channel_tech_pvt(newchan);
763         ast_mutex_lock(&p->lock);
764         if (p->owner != oldchan) {
765                 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
766                 ast_mutex_unlock(&p->lock);
767                 return -1;
768         }
769         p->owner = newchan;
770         ast_mutex_unlock(&p->lock);
771         return 0;
772 }
773
774 static int agent_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
775 {
776         struct agent_pvt *p = ast_channel_tech_pvt(ast);
777         int res = -1;
778         ast_mutex_lock(&p->lock);
779         if (p->chan && !ast_check_hangup(p->chan)) {
780                 while (ast_channel_trylock(p->chan)) {
781                         if ((res = ast_channel_unlock(ast))) {
782                                 ast_log(LOG_ERROR, "chan_agent bug! Channel was not locked upon entry to agent_indicate: %s\n", strerror(res));
783                                 ast_mutex_unlock(&p->lock);
784                                 return -1;
785                         }
786                         usleep(1);
787                         ast_channel_lock(ast);
788                 }
789                 res = ast_channel_tech(p->chan)->indicate ? ast_channel_tech(p->chan)->indicate(p->chan, condition, data, datalen) : -1;
790                 ast_channel_unlock(p->chan);
791         } else
792                 res = 0;
793         ast_mutex_unlock(&p->lock);
794         return res;
795 }
796
797 static int agent_digit_begin(struct ast_channel *ast, char digit)
798 {
799         struct agent_pvt *p = ast_channel_tech_pvt(ast);
800         ast_mutex_lock(&p->lock);
801         if (p->chan) {
802                 ast_senddigit_begin(p->chan, digit);
803         }
804         ast_mutex_unlock(&p->lock);
805         return 0;
806 }
807
808 static int agent_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
809 {
810         struct agent_pvt *p = ast_channel_tech_pvt(ast);
811         ast_mutex_lock(&p->lock);
812         if (p->chan) {
813                 ast_senddigit_end(p->chan, digit, duration);
814         }
815         ast_mutex_unlock(&p->lock);
816         return 0;
817 }
818
819 static int agent_call(struct ast_channel *ast, const char *dest, int timeout)
820 {
821         struct agent_pvt *p = ast_channel_tech_pvt(ast);
822         int res = -1;
823         int newstate=0;
824         struct ast_channel *chan;
825
826         ast_mutex_lock(&p->lock);
827         p->acknowledged = 0;
828
829         if (p->pending) {
830                 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n");
831                 ast_mutex_unlock(&p->lock);
832                 ast_setstate(ast, AST_STATE_DIALING);
833                 return 0;
834         }
835
836         if (!p->chan) {
837                 ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n");
838                 ast_mutex_unlock(&p->lock);
839                 return res;
840         }
841         ast_verb(3, "agent_call, call to agent '%s' call on '%s'\n", p->agent, ast_channel_name(p->chan));
842         ast_debug(3, "Playing beep, lang '%s'\n", ast_channel_language(p->chan));
843         
844         chan = p->chan;
845         ast_mutex_unlock(&p->lock);
846
847         res = ast_streamfile(chan, beep, ast_channel_language(chan));
848         ast_debug(3, "Played beep, result '%d'\n", res);
849         if (!res) {
850                 res = ast_waitstream(chan, "");
851                 ast_debug(3, "Waited for stream, result '%d'\n", res);
852         }
853         
854         ast_mutex_lock(&p->lock);
855         if (!p->chan) {
856                 /* chan went away while we were streaming, this shouldn't be possible */
857                 res = -1;
858         }
859
860         if (!res) {
861                 struct ast_format tmpfmt;
862                 res = ast_set_read_format_from_cap(p->chan, ast_channel_nativeformats(p->chan));
863                 ast_debug(3, "Set read format, result '%d'\n", res);
864                 if (res)
865                         ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(&tmpfmt));
866         } else {
867                 /* Agent hung-up */
868                 p->chan = NULL;
869                 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
870         }
871
872         if (!res) {
873                 struct ast_format tmpfmt;
874                 res = ast_set_write_format_from_cap(p->chan, ast_channel_nativeformats(p->chan));
875                 ast_debug(3, "Set write format, result '%d'\n", res);
876                 if (res)
877                         ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(&tmpfmt));
878         }
879         if(!res) {
880                 /* Call is immediately up, or might need ack */
881                 if (p->ackcall) {
882                         newstate = AST_STATE_RINGING;
883                 } else {
884                         newstate = AST_STATE_UP;
885                         if (recordagentcalls)
886                                 agent_start_monitoring(ast, 0);
887                         p->acknowledged = 1;
888                 }
889                 res = 0;
890         }
891         CLEANUP(ast, p);
892         ast_mutex_unlock(&p->lock);
893         if (newstate)
894                 ast_setstate(ast, newstate);
895         return res;
896 }
897
898 /*! \brief return the channel or base channel if one exists.  This function assumes the channel it is called on is already locked */
899 struct ast_channel* agent_get_base_channel(struct ast_channel *chan)
900 {
901         struct agent_pvt *p = NULL;
902         struct ast_channel *base = chan;
903
904         /* chan is locked by the calling function */
905         if (!chan || !ast_channel_tech_pvt(chan)) {
906                 ast_log(LOG_ERROR, "whoa, you need a channel (0x%ld) with a tech_pvt (0x%ld) to get a base channel.\n", (long)chan, (chan)?(long)ast_channel_tech_pvt(chan):(long)NULL);
907                 return NULL;
908         }
909         p = ast_channel_tech_pvt(chan);
910         if (p->chan) 
911                 base = p->chan;
912         return base;
913 }
914
915 int agent_set_base_channel(struct ast_channel *chan, struct ast_channel *base)
916 {
917         struct agent_pvt *p = NULL;
918         
919         if (!chan || !base) {
920                 ast_log(LOG_ERROR, "whoa, you need a channel (0x%ld) and a base channel (0x%ld) for setting.\n", (long)chan, (long)base);
921                 return -1;
922         }
923         p = ast_channel_tech_pvt(chan);
924         if (!p) {
925                 ast_log(LOG_ERROR, "whoa, channel %s is missing his tech_pvt structure!!.\n", ast_channel_name(chan));
926                 return -1;
927         }
928         p->chan = base;
929         return 0;
930 }
931
932 static int agent_hangup(struct ast_channel *ast)
933 {
934         struct agent_pvt *p = ast_channel_tech_pvt(ast);
935         struct ast_channel *indicate_chan = NULL;
936         char *tmp_moh; /* moh buffer for indicating after unlocking p */
937
938         if (p->pending) {
939                 AST_LIST_LOCK(&agents);
940                 AST_LIST_REMOVE(&agents, p, list);
941                 AST_LIST_UNLOCK(&agents);
942         }
943
944         ast_mutex_lock(&p->lock);
945         p->owner = NULL;
946         ast_channel_tech_pvt_set(ast, NULL);
947         p->app_sleep_cond = 1;
948         p->acknowledged = 0;
949
950         /* Release ownership of the agent to other threads (presumably running the login app). */
951         p->app_lock_flag = 0;
952         ast_cond_signal(&p->app_complete_cond);
953
954         /* if they really are hung up then set start to 0 so the test
955          * later if we're called on an already downed channel
956          * doesn't cause an agent to be logged out like when
957          * agent_request() is followed immediately by agent_hangup()
958          * as in apps/app_chanisavail.c:chanavail_exec()
959          */
960
961         ast_debug(1, "Hangup called for state %s\n", ast_state2str(ast_channel_state(ast)));
962         if (p->start && (ast_channel_state(ast) != AST_STATE_UP)) {
963                 p->start = 0;
964         } else
965                 p->start = 0;
966         if (p->chan) {
967                 ast_channel_internal_bridged_channel_set(p->chan, NULL);
968                 /* If they're dead, go ahead and hang up on the agent now */
969                 if (p->dead) {
970                         ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
971                 } else if (p->loginstart) {
972                         indicate_chan = ast_channel_ref(p->chan);
973                         tmp_moh = ast_strdupa(p->moh);
974                 }
975         }
976         ast_mutex_unlock(&p->lock);
977
978         if (indicate_chan) {
979                 ast_indicate_data(indicate_chan, AST_CONTROL_HOLD,
980                         S_OR(tmp_moh, NULL),
981                         !ast_strlen_zero(tmp_moh) ? strlen(tmp_moh) + 1 : 0);
982                 indicate_chan = ast_channel_unref(indicate_chan);
983         }
984
985         /* Only register a device state change if the agent is still logged in */
986         if (!p->loginstart) {
987                 p->logincallerid[0] = '\0';
988         } else {
989                 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
990         }
991
992         if (p->abouttograb) {
993                 /* Let the "about to grab" thread know this isn't valid anymore, and let it
994                    kill it later */
995                 p->abouttograb = 0;
996         } else if (p->dead) {
997                 ast_mutex_destroy(&p->lock);
998                 ast_cond_destroy(&p->app_complete_cond);
999                 ast_cond_destroy(&p->login_wait_cond);
1000                 ast_free(p);
1001         } else {
1002                 if (p->chan) {
1003                         /* Not dead -- check availability now */
1004                         ast_mutex_lock(&p->lock);
1005                         /* Store last disconnect time */
1006                         p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000));
1007                         ast_mutex_unlock(&p->lock);
1008                 }
1009         }
1010         return 0;
1011 }
1012
1013 static int agent_cont_sleep( void *data )
1014 {
1015         struct agent_pvt *p;
1016         int res;
1017
1018         p = (struct agent_pvt *)data;
1019
1020         ast_mutex_lock(&p->lock);
1021         res = p->app_sleep_cond;
1022         if (p->lastdisc.tv_sec) {
1023                 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) 
1024                         res = 1;
1025         }
1026         ast_mutex_unlock(&p->lock);
1027
1028         if (!res)
1029                 ast_debug(5, "agent_cont_sleep() returning %d\n", res );
1030
1031         return res;
1032 }
1033
1034 static int agent_ack_sleep(void *data)
1035 {
1036         struct agent_pvt *p;
1037         int res=0;
1038         int to = 1000;
1039         struct ast_frame *f;
1040
1041         /* Wait a second and look for something */
1042
1043         p = (struct agent_pvt *) data;
1044         if (!p->chan) 
1045                 return -1;
1046
1047         for(;;) {
1048                 to = ast_waitfor(p->chan, to);
1049                 if (to < 0) 
1050                         return -1;
1051                 if (!to) 
1052                         return 0;
1053                 f = ast_read(p->chan);
1054                 if (!f) 
1055                         return -1;
1056                 if (f->frametype == AST_FRAME_DTMF)
1057                         res = f->subclass.integer;
1058                 else
1059                         res = 0;
1060                 ast_frfree(f);
1061                 ast_mutex_lock(&p->lock);
1062                 if (!p->app_sleep_cond) {
1063                         ast_mutex_unlock(&p->lock);
1064                         return 0;
1065                 } else if (res == p->acceptdtmf) {
1066                         ast_mutex_unlock(&p->lock);
1067                         return 1;
1068                 }
1069                 ast_mutex_unlock(&p->lock);
1070                 res = 0;
1071         }
1072         return res;
1073 }
1074
1075 static struct ast_channel *agent_bridgedchannel(struct ast_channel *chan, struct ast_channel *bridge)
1076 {
1077         struct agent_pvt *p = ast_channel_tech_pvt(bridge);
1078         struct ast_channel *ret = NULL;
1079
1080         if (p) {
1081                 if (chan == p->chan)
1082                         ret = ast_channel_internal_bridged_channel(bridge);
1083                 else if (chan == ast_channel_internal_bridged_channel(bridge))
1084                         ret = p->chan;
1085         }
1086
1087         ast_debug(1, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", ast_channel_name(chan), ast_channel_name(bridge), ret ? ast_channel_name(ret) : "<none>");
1088         return ret;
1089 }
1090
1091 /*! \brief Create new agent channel */
1092 static struct ast_channel *agent_new(struct agent_pvt *p, int state, const char *linkedid)
1093 {
1094         struct ast_channel *tmp;
1095 #if 0
1096         if (!p->chan) {
1097                 ast_log(LOG_WARNING, "No channel? :(\n");
1098                 return NULL;
1099         }
1100 #endif  
1101         if (p->pending)
1102                 tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? ast_channel_exten(p->chan):"", p->chan ? ast_channel_context(p->chan):"", linkedid, 0, "Agent/P%s-%d", p->agent, (int) ast_random() & 0xffff);
1103         else
1104                 tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? ast_channel_exten(p->chan):"", p->chan ? ast_channel_context(p->chan):"", linkedid, 0, "Agent/%s", p->agent);
1105         if (!tmp) {
1106                 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n");
1107                 return NULL;
1108         }
1109
1110         ast_channel_tech_set(tmp, &agent_tech);
1111         if (p->chan) {
1112                 ast_format_cap_copy(ast_channel_nativeformats(tmp), ast_channel_nativeformats(p->chan));
1113                 ast_format_copy(ast_channel_writeformat(tmp), ast_channel_writeformat(p->chan));
1114                 ast_format_copy(ast_channel_rawwriteformat(tmp), ast_channel_writeformat(p->chan));
1115                 ast_format_copy(ast_channel_readformat(tmp), ast_channel_readformat(p->chan));
1116                 ast_format_copy(ast_channel_rawreadformat(tmp), ast_channel_readformat(p->chan));
1117                 ast_channel_language_set(tmp, ast_channel_language(p->chan));
1118                 ast_channel_context_set(tmp, ast_channel_context(p->chan));
1119                 ast_channel_exten_set(tmp, ast_channel_exten(p->chan));
1120                 /* XXX Is this really all we copy form the originating channel?? */
1121         } else {
1122                 ast_format_set(ast_channel_writeformat(tmp), AST_FORMAT_SLINEAR, 0);
1123                 ast_format_set(ast_channel_rawwriteformat(tmp), AST_FORMAT_SLINEAR, 0);
1124                 ast_format_set(ast_channel_readformat(tmp), AST_FORMAT_SLINEAR, 0);
1125                 ast_format_set(ast_channel_rawreadformat(tmp), AST_FORMAT_SLINEAR, 0);
1126                 ast_format_cap_add(ast_channel_nativeformats(tmp), ast_channel_writeformat(tmp));
1127         }
1128         /* Safe, agentlock already held */
1129         ast_channel_tech_pvt_set(tmp, p);
1130         p->owner = tmp;
1131         ast_channel_priority_set(tmp, 1);
1132         return tmp;
1133 }
1134
1135
1136 /*!
1137  * Read configuration data. The file named agents.conf.
1138  *
1139  * \returns Always 0, or so it seems.
1140  */
1141 static int read_agent_config(int reload)
1142 {
1143         struct ast_config *cfg;
1144         struct ast_config *ucfg;
1145         struct ast_variable *v;
1146         struct agent_pvt *p;
1147         const char *catname;
1148         const char *hasagent;
1149         int genhasagent;
1150         struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
1151
1152         group = 0;
1153         autologoff = 0;
1154         wrapuptime = 0;
1155         ackcall = 0;
1156         endcall = 1;
1157         cfg = ast_config_load(config, config_flags);
1158         if (!cfg) {
1159                 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n");
1160                 return 0;
1161         } else if (cfg == CONFIG_STATUS_FILEUNCHANGED) {
1162                 return -1;
1163         } else if (cfg == CONFIG_STATUS_FILEINVALID) {
1164                 ast_log(LOG_ERROR, "%s contains a parsing error.  Aborting\n", config);
1165                 return 0;
1166         }
1167         if ((ucfg = ast_config_load("users.conf", config_flags))) {
1168                 if (ucfg == CONFIG_STATUS_FILEUNCHANGED) {
1169                         ucfg = NULL;
1170                 } else if (ucfg == CONFIG_STATUS_FILEINVALID) {
1171                         ast_log(LOG_ERROR, "users.conf contains a parsing error.  Aborting\n");
1172                         return 0;
1173                 }
1174         }
1175
1176         AST_LIST_LOCK(&agents);
1177         AST_LIST_TRAVERSE(&agents, p, list) {
1178                 p->dead = 1;
1179         }
1180         strcpy(moh, "default");
1181         /* set the default recording values */
1182         recordagentcalls = 0;
1183         strcpy(recordformat, "wav");
1184         strcpy(recordformatext, "wav");
1185         urlprefix[0] = '\0';
1186         savecallsin[0] = '\0';
1187
1188         /* Read in [general] section for persistence */
1189         multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin"));
1190
1191         /* Read in the [agents] section */
1192         v = ast_variable_browse(cfg, "agents");
1193         while(v) {
1194                 /* Create the interface list */
1195                 if (!strcasecmp(v->name, "agent")) {
1196                         add_agent(v->value, 0);
1197                 } else if (!strcasecmp(v->name, "group")) {
1198                         group = ast_get_group(v->value);
1199                 } else if (!strcasecmp(v->name, "autologoff")) {
1200                         autologoff = atoi(v->value);
1201                         if (autologoff < 0)
1202                                 autologoff = 0;
1203                 } else if (!strcasecmp(v->name, "ackcall")) {
1204                         if (ast_true(v->value) || !strcasecmp(v->value, "always")) {
1205                                 ackcall = 1;
1206                         }
1207                 } else if (!strcasecmp(v->name, "endcall")) {
1208                         endcall = ast_true(v->value);
1209                 } else if (!strcasecmp(v->name, "acceptdtmf")) {
1210                         acceptdtmf = *(v->value);
1211                         ast_log(LOG_NOTICE, "Set acceptdtmf to %c\n", acceptdtmf);
1212                 } else if (!strcasecmp(v->name, "enddtmf")) {
1213                         enddtmf = *(v->value);
1214                 } else if (!strcasecmp(v->name, "wrapuptime")) {
1215                         wrapuptime = atoi(v->value);
1216                         if (wrapuptime < 0)
1217                                 wrapuptime = 0;
1218                 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) {
1219                         maxlogintries = atoi(v->value);
1220                         if (maxlogintries < 0)
1221                                 maxlogintries = 0;
1222                 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) {
1223                         strcpy(agentgoodbye,v->value);
1224                 } else if (!strcasecmp(v->name, "musiconhold")) {
1225                         ast_copy_string(moh, v->value, sizeof(moh));
1226                 } else if (!strcasecmp(v->name, "updatecdr")) {
1227                         if (ast_true(v->value))
1228                                 updatecdr = 1;
1229                         else
1230                                 updatecdr = 0;
1231                 } else if (!strcasecmp(v->name, "autologoffunavail")) {
1232                         if (ast_true(v->value))
1233                                 autologoffunavail = 1;
1234                         else
1235                                 autologoffunavail = 0;
1236                 } else if (!strcasecmp(v->name, "recordagentcalls")) {
1237                         recordagentcalls = ast_true(v->value);
1238                 } else if (!strcasecmp(v->name, "recordformat")) {
1239                         ast_copy_string(recordformat, v->value, sizeof(recordformat));
1240                         if (!strcasecmp(v->value, "wav49"))
1241                                 strcpy(recordformatext, "WAV");
1242                         else
1243                                 ast_copy_string(recordformatext, v->value, sizeof(recordformatext));
1244                 } else if (!strcasecmp(v->name, "urlprefix")) {
1245                         ast_copy_string(urlprefix, v->value, sizeof(urlprefix));
1246                         if (urlprefix[strlen(urlprefix) - 1] != '/')
1247                                 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1);
1248                 } else if (!strcasecmp(v->name, "savecallsin")) {
1249                         if (v->value[0] == '/')
1250                                 ast_copy_string(savecallsin, v->value, sizeof(savecallsin));
1251                         else
1252                                 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value);
1253                         if (savecallsin[strlen(savecallsin) - 1] != '/')
1254                                 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1);
1255                 } else if (!strcasecmp(v->name, "custom_beep")) {
1256                         ast_copy_string(beep, v->value, sizeof(beep));
1257                 }
1258                 v = v->next;
1259         }
1260         if (ucfg) {
1261                 genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent"));
1262                 catname = ast_category_browse(ucfg, NULL);
1263                 while(catname) {
1264                         if (strcasecmp(catname, "general")) {
1265                                 hasagent = ast_variable_retrieve(ucfg, catname, "hasagent");
1266                                 if (ast_true(hasagent) || (!hasagent && genhasagent)) {
1267                                         char tmp[256];
1268                                         const char *fullname = ast_variable_retrieve(ucfg, catname, "fullname");
1269                                         const char *secret = ast_variable_retrieve(ucfg, catname, "secret");
1270                                         if (!fullname)
1271                                                 fullname = "";
1272                                         if (!secret)
1273                                                 secret = "";
1274                                         snprintf(tmp, sizeof(tmp), "%s,%s,%s", catname, secret,fullname);
1275                                         add_agent(tmp, 0);
1276                                 }
1277                         }
1278                         catname = ast_category_browse(ucfg, catname);
1279                 }
1280                 ast_config_destroy(ucfg);
1281         }
1282         AST_LIST_TRAVERSE_SAFE_BEGIN(&agents, p, list) {
1283                 if (p->dead) {
1284                         AST_LIST_REMOVE_CURRENT(list);
1285                         /* Destroy if  appropriate */
1286                         if (!p->owner) {
1287                                 if (!p->chan) {
1288                                         ast_mutex_destroy(&p->lock);
1289                                         ast_cond_destroy(&p->app_complete_cond);
1290                                         ast_cond_destroy(&p->login_wait_cond);
1291                                         ast_free(p);
1292                                 } else {
1293                                         /* Cause them to hang up */
1294                                         ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
1295                                 }
1296                         }
1297                 }
1298         }
1299         AST_LIST_TRAVERSE_SAFE_END;
1300         AST_LIST_UNLOCK(&agents);
1301         ast_config_destroy(cfg);
1302         return 1;
1303 }
1304
1305 static int check_availability(struct agent_pvt *newlyavailable, int needlock)
1306 {
1307         struct ast_channel *chan=NULL, *parent=NULL;
1308         struct agent_pvt *p;
1309         int res;
1310
1311         ast_debug(1, "Checking availability of '%s'\n", newlyavailable->agent);
1312         if (needlock)
1313                 AST_LIST_LOCK(&agents);
1314         AST_LIST_TRAVERSE(&agents, p, list) {
1315                 if (p == newlyavailable) {
1316                         continue;
1317                 }
1318                 ast_mutex_lock(&p->lock);
1319                 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1320                         ast_debug(1, "Call '%s' looks like a winner for agent '%s'\n", ast_channel_name(p->owner), newlyavailable->agent);
1321                         /* We found a pending call, time to merge */
1322                         chan = agent_new(newlyavailable, AST_STATE_DOWN, p->owner ? ast_channel_linkedid(p->owner) : NULL);
1323                         parent = p->owner;
1324                         p->abouttograb = 1;
1325                         ast_mutex_unlock(&p->lock);
1326                         break;
1327                 }
1328                 ast_mutex_unlock(&p->lock);
1329         }
1330         if (needlock)
1331                 AST_LIST_UNLOCK(&agents);
1332         if (parent && chan)  {
1333                 if (newlyavailable->ackcall) {
1334                         /* Don't do beep here */
1335                         res = 0;
1336                 } else {
1337                         ast_debug(3, "Playing beep, lang '%s'\n", ast_channel_language(newlyavailable->chan));
1338                         res = ast_streamfile(newlyavailable->chan, beep, ast_channel_language(newlyavailable->chan));
1339                         ast_debug(3, "Played beep, result '%d'\n", res);
1340                         if (!res) {
1341                                 res = ast_waitstream(newlyavailable->chan, "");
1342                                 ast_debug(1, "Waited for stream, result '%d'\n", res);
1343                         }
1344                 }
1345                 if (!res) {
1346                         /* Note -- parent may have disappeared */
1347                         if (p->abouttograb) {
1348                                 newlyavailable->acknowledged = 1;
1349                                 /* Safe -- agent lock already held */
1350                                 ast_setstate(parent, AST_STATE_UP);
1351                                 ast_setstate(chan, AST_STATE_UP);
1352                                 ast_channel_context_set(parent, ast_channel_context(chan));
1353                                 ast_channel_masquerade(parent, chan);
1354                                 ast_hangup(chan);
1355                                 p->abouttograb = 0;
1356                         } else {
1357                                 ast_debug(1, "Sneaky, parent disappeared in the mean time...\n");
1358                                 agent_cleanup(newlyavailable);
1359                         }
1360                 } else {
1361                         ast_debug(1, "Ugh...  Agent hung up at exactly the wrong time\n");
1362                         agent_cleanup(newlyavailable);
1363                 }
1364         }
1365         return 0;
1366 }
1367
1368 static int check_beep(struct agent_pvt *newlyavailable, int needlock)
1369 {
1370         struct agent_pvt *p;
1371         int res=0;
1372
1373         ast_debug(1, "Checking beep availability of '%s'\n", newlyavailable->agent);
1374         if (needlock)
1375                 AST_LIST_LOCK(&agents);
1376         AST_LIST_TRAVERSE(&agents, p, list) {
1377                 if (p == newlyavailable) {
1378                         continue;
1379                 }
1380                 ast_mutex_lock(&p->lock);
1381                 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) {
1382                         ast_debug(1, "Call '%s' looks like a would-be winner for agent '%s'\n", ast_channel_name(p->owner), newlyavailable->agent);
1383                         ast_mutex_unlock(&p->lock);
1384                         break;
1385                 }
1386                 ast_mutex_unlock(&p->lock);
1387         }
1388         if (needlock)
1389                 AST_LIST_UNLOCK(&agents);
1390         if (p) {
1391                 ast_mutex_unlock(&newlyavailable->lock);
1392                 ast_debug(3, "Playing beep, lang '%s'\n", ast_channel_language(newlyavailable->chan));
1393                 res = ast_streamfile(newlyavailable->chan, beep, ast_channel_language(newlyavailable->chan));
1394                 ast_debug(1, "Played beep, result '%d'\n", res);
1395                 if (!res) {
1396                         res = ast_waitstream(newlyavailable->chan, "");
1397                         ast_debug(1, "Waited for stream, result '%d'\n", res);
1398                 }
1399                 ast_mutex_lock(&newlyavailable->lock);
1400         }
1401         return res;
1402 }
1403
1404 /*! \brief Part of the Asterisk PBX interface */
1405 static struct ast_channel *agent_request(const char *type, struct ast_format_cap *cap, const struct ast_channel* requestor, const char *data, int *cause)
1406 {
1407         struct agent_pvt *p;
1408         struct ast_channel *chan = NULL;
1409         const char *s;
1410         ast_group_t groupmatch;
1411         int groupoff;
1412         int waitforagent=0;
1413         int hasagent = 0;
1414         struct timeval now;
1415
1416         s = data;
1417         if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
1418                 groupmatch = (1 << groupoff);
1419         } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
1420                 groupmatch = (1 << groupoff);
1421                 waitforagent = 1;
1422         } else 
1423                 groupmatch = 0;
1424
1425         /* Check actual logged in agents first */
1426         AST_LIST_LOCK(&agents);
1427         AST_LIST_TRAVERSE(&agents, p, list) {
1428                 ast_mutex_lock(&p->lock);
1429                 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1430                         if (p->chan)
1431                                 hasagent++;
1432                         now = ast_tvnow();
1433                         if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1434                                 p->lastdisc = ast_tv(0, 0);
1435                                 /* Agent must be registered, but not have any active call, and not be in a waiting state */
1436                                 if (!p->owner && p->chan) {
1437                                         /* Fixed agent */
1438                                         chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
1439                                 }
1440                                 if (chan) {
1441                                         ast_mutex_unlock(&p->lock);
1442                                         break;
1443                                 }
1444                         }
1445                 }
1446                 ast_mutex_unlock(&p->lock);
1447         }
1448         if (!p) {
1449                 AST_LIST_TRAVERSE(&agents, p, list) {
1450                         ast_mutex_lock(&p->lock);
1451                         if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
1452                                 if (p->chan) {
1453                                         hasagent++;
1454                                 }
1455                                 now = ast_tvnow();
1456                                 if (!p->lastdisc.tv_sec || (now.tv_sec >= p->lastdisc.tv_sec)) {
1457                                         p->lastdisc = ast_tv(0, 0);
1458                                         /* Agent must be registered, but not have any active call, and not be in a waiting state */
1459                                         if (!p->owner && p->chan) {
1460                                                 /* Could still get a fixed agent */
1461                                                 chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
1462                                         }
1463                                         if (chan) {
1464                                                 ast_mutex_unlock(&p->lock);
1465                                                 break;
1466                                         }
1467                                 }
1468                         }
1469                         ast_mutex_unlock(&p->lock);
1470                 }
1471         }
1472
1473         if (!chan && waitforagent) {
1474                 /* No agent available -- but we're requesting to wait for one.
1475                    Allocate a place holder */
1476                 if (hasagent) {
1477                         ast_debug(1, "Creating place holder for '%s'\n", s);
1478                         p = add_agent(data, 1);
1479                         p->group = groupmatch;
1480                         chan = agent_new(p, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
1481                         if (!chan) 
1482                                 ast_log(LOG_WARNING, "Weird...  Fix this to drop the unused pending agent\n");
1483                 } else {
1484                         ast_debug(1, "Not creating place holder for '%s' since nobody logged in\n", s);
1485                 }
1486         }
1487         *cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED;
1488         AST_LIST_UNLOCK(&agents);
1489
1490         if (chan) {
1491                 ast_mutex_lock(&p->lock);
1492                 if (p->pending) {
1493                         ast_mutex_unlock(&p->lock);
1494                         return chan;
1495                 }
1496
1497                 if (!p->chan) {
1498                         ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n");
1499                         *cause = AST_CAUSE_UNREGISTERED;
1500                         ast_mutex_unlock(&p->lock);
1501                         agent_hangup(chan);
1502                         return NULL;
1503                 }
1504
1505                 /* we need to take control of the channel from the login app
1506                  * thread */
1507                 p->app_sleep_cond = 0;
1508                 p->app_lock_flag = 1;
1509
1510                 ast_queue_frame(p->chan, &ast_null_frame);
1511                 ast_cond_wait(&p->login_wait_cond, &p->lock);
1512
1513                 if (!p->chan) {
1514                         ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n");
1515                         p->app_sleep_cond = 1;
1516                         p->app_lock_flag = 0;
1517                         ast_cond_signal(&p->app_complete_cond);
1518                         ast_mutex_unlock(&p->lock);
1519                         *cause = AST_CAUSE_UNREGISTERED;
1520                         agent_hangup(chan);
1521                         return NULL;
1522                 }
1523
1524                 ast_indicate(p->chan, AST_CONTROL_UNHOLD);
1525                 ast_mutex_unlock(&p->lock);
1526         }
1527
1528         return chan;
1529 }
1530
1531 static force_inline int powerof(unsigned int d)
1532 {
1533         int x = ffs(d);
1534
1535         if (x)
1536                 return x - 1;
1537
1538         return 0;
1539 }
1540
1541 /*!
1542  * Lists agents and their status to the Manager API.
1543  * It is registered on load_module() and it gets called by the manager backend.
1544  * This function locks both the pvt and the channel that owns it for a while, but
1545  * does not keep these locks.
1546  * \param s
1547  * \param m
1548  * \returns 
1549  * \sa action_agent_logoff(), load_module().
1550  */
1551 static int action_agents(struct mansession *s, const struct message *m)
1552 {
1553         const char *id = astman_get_header(m,"ActionID");
1554         char idText[256] = "";
1555         struct agent_pvt *p;
1556         char *username = NULL;
1557         char *loginChan = NULL;
1558         char *talkingto = NULL;
1559         char *talkingtoChan = NULL;
1560         char *status = NULL;
1561         struct ast_channel *bridge;
1562
1563         if (!ast_strlen_zero(id))
1564                 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id);
1565         astman_send_ack(s, m, "Agents will follow");
1566         AST_LIST_LOCK(&agents);
1567         AST_LIST_TRAVERSE(&agents, p, list) {
1568                 struct ast_channel *owner;
1569                 ast_mutex_lock(&p->lock);
1570                 owner = agent_lock_owner(p);
1571
1572                 /* Status Values:
1573                    AGENT_LOGGEDOFF - Agent isn't logged in
1574                    AGENT_IDLE      - Agent is logged in, and waiting for call
1575                    AGENT_ONCALL    - Agent is logged in, and on a call
1576                    AGENT_UNKNOWN   - Don't know anything about agent. Shouldn't ever get this. */
1577
1578                 username = S_OR(p->name, "None");
1579
1580                 /* Set a default status. It 'should' get changed. */
1581                 status = "AGENT_UNKNOWN";
1582
1583                 if (p->chan) {
1584                         loginChan = ast_strdupa(ast_channel_name(p->chan));
1585                         if (owner && ast_channel_internal_bridged_channel(owner)) {
1586                                 talkingto = S_COR(ast_channel_caller(p->chan)->id.number.valid,
1587                                         ast_channel_caller(p->chan)->id.number.str, "n/a");
1588                                 if ((bridge = ast_bridged_channel(owner))) {
1589                                         talkingtoChan = ast_strdupa(ast_channel_name(bridge));
1590                                 } else {
1591                                         talkingtoChan = "n/a";
1592                                 }
1593                                 status = "AGENT_ONCALL";
1594                         } else {
1595                                 talkingto = "n/a";
1596                                 talkingtoChan = "n/a";
1597                                 status = "AGENT_IDLE";
1598                         }
1599                 } else {
1600                         loginChan = "n/a";
1601                         talkingto = "n/a";
1602                         talkingtoChan = "n/a";
1603                         status = "AGENT_LOGGEDOFF";
1604                 }
1605
1606                 if (owner) {
1607                         ast_channel_unlock(owner);
1608                         owner = ast_channel_unref(owner);
1609                 }
1610
1611                 astman_append(s, "Event: Agents\r\n"
1612                         "Agent: %s\r\n"
1613                         "Name: %s\r\n"
1614                         "Status: %s\r\n"
1615                         "LoggedInChan: %s\r\n"
1616                         "LoggedInTime: %d\r\n"
1617                         "TalkingTo: %s\r\n"
1618                         "TalkingToChan: %s\r\n"
1619                         "%s"
1620                         "\r\n",
1621                         p->agent, username, status, loginChan, (int)p->loginstart, talkingto, talkingtoChan, idText);
1622                 ast_mutex_unlock(&p->lock);
1623         }
1624         AST_LIST_UNLOCK(&agents);
1625         astman_append(s, "Event: AgentsComplete\r\n"
1626                 "%s"
1627                 "\r\n",idText);
1628         return 0;
1629 }
1630
1631 static int agent_logoff(const char *agent, int soft)
1632 {
1633         struct agent_pvt *p;
1634         int ret = -1; /* Return -1 if no agent if found */
1635
1636         AST_LIST_LOCK(&agents);
1637         AST_LIST_TRAVERSE(&agents, p, list) {
1638                 if (!strcasecmp(p->agent, agent)) {
1639                         ret = 0;
1640                         if (p->owner || p->chan) {
1641                                 if (!soft) {
1642                                         struct ast_channel *owner;
1643                                         ast_mutex_lock(&p->lock);
1644                                         owner = agent_lock_owner(p);
1645
1646                                         if (owner) {
1647                                                 ast_softhangup(owner, AST_SOFTHANGUP_EXPLICIT);
1648                                                 ast_channel_unlock(owner);
1649                                                 owner = ast_channel_unref(owner);
1650                                         }
1651
1652                                         while (p->chan && ast_channel_trylock(p->chan)) {
1653                                                 DEADLOCK_AVOIDANCE(&p->lock);
1654                                         }
1655                                         if (p->chan) {
1656                                                 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
1657                                                 ast_channel_unlock(p->chan);
1658                                         }
1659
1660                                         ast_mutex_unlock(&p->lock);
1661                                 } else
1662                                         p->deferlogoff = 1;
1663                         }
1664                         break;
1665                 }
1666         }
1667         AST_LIST_UNLOCK(&agents);
1668
1669         return ret;
1670 }
1671
1672 static char *agent_logoff_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1673 {
1674         int ret;
1675         const char *agent;
1676
1677         switch (cmd) {
1678         case CLI_INIT:
1679                 e->command = "agent logoff";
1680                 e->usage =
1681                         "Usage: agent logoff <channel> [soft]\n"
1682                         "       Sets an agent as no longer logged in.\n"
1683                         "       If 'soft' is specified, do not hangup existing calls.\n";
1684                 return NULL;
1685         case CLI_GENERATE:
1686                 return complete_agent_logoff_cmd(a->line, a->word, a->pos, a->n); 
1687         }
1688
1689         if (a->argc < 3 || a->argc > 4)
1690                 return CLI_SHOWUSAGE;
1691         if (a->argc == 4 && strcasecmp(a->argv[3], "soft"))
1692                 return CLI_SHOWUSAGE;
1693
1694         agent = a->argv[2] + 6;
1695         ret = agent_logoff(agent, a->argc == 4);
1696         if (ret == 0)
1697                 ast_cli(a->fd, "Logging out %s\n", agent);
1698
1699         return CLI_SUCCESS;
1700 }
1701
1702 /*!
1703  * Sets an agent as no longer logged in in the Manager API.
1704  * It is registered on load_module() and it gets called by the manager backend.
1705  * \param s
1706  * \param m
1707  * \returns 
1708  * \sa action_agents(), load_module().
1709  */
1710 static int action_agent_logoff(struct mansession *s, const struct message *m)
1711 {
1712         const char *agent = astman_get_header(m, "Agent");
1713         const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */
1714         int soft;
1715         int ret; /* return value of agent_logoff */
1716
1717         if (ast_strlen_zero(agent)) {
1718                 astman_send_error(s, m, "No agent specified");
1719                 return 0;
1720         }
1721
1722         soft = ast_true(soft_s) ? 1 : 0;
1723         ret = agent_logoff(agent, soft);
1724         if (ret == 0)
1725                 astman_send_ack(s, m, "Agent logged out");
1726         else
1727                 astman_send_error(s, m, "No such agent");
1728
1729         return 0;
1730 }
1731
1732 static char *complete_agent_logoff_cmd(const char *line, const char *word, int pos, int state)
1733 {
1734         char *ret = NULL;
1735
1736         if (pos == 2) {
1737                 struct agent_pvt *p;
1738                 char name[AST_MAX_AGENT];
1739                 int which = 0, len = strlen(word);
1740
1741                 AST_LIST_LOCK(&agents);
1742                 AST_LIST_TRAVERSE(&agents, p, list) {
1743                         snprintf(name, sizeof(name), "Agent/%s", p->agent);
1744                         if (!strncasecmp(word, name, len) && p->loginstart && ++which > state) {
1745                                 ret = ast_strdup(name);
1746                                 break;
1747                         }
1748                 }
1749                 AST_LIST_UNLOCK(&agents);
1750         } else if (pos == 3 && state == 0) 
1751                 return ast_strdup("soft");
1752         
1753         return ret;
1754 }
1755
1756 /*!
1757  * Show agents in cli.
1758  */
1759 static char *agents_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1760 {
1761         struct agent_pvt *p;
1762         char username[AST_MAX_BUF];
1763         char location[AST_MAX_BUF] = "";
1764         char talkingto[AST_MAX_BUF] = "";
1765         char music[AST_MAX_BUF];
1766         int count_agents = 0;           /*!< Number of agents configured */
1767         int online_agents = 0;          /*!< Number of online agents */
1768         int offline_agents = 0;         /*!< Number of offline agents */
1769
1770         switch (cmd) {
1771         case CLI_INIT:
1772                 e->command = "agent show";
1773                 e->usage =
1774                         "Usage: agent show\n"
1775                         "       Provides summary information on agents.\n";
1776                 return NULL;
1777         case CLI_GENERATE:
1778                 return NULL;
1779         }
1780
1781         if (a->argc != 2)
1782                 return CLI_SHOWUSAGE;
1783
1784         AST_LIST_LOCK(&agents);
1785         AST_LIST_TRAVERSE(&agents, p, list) {
1786                 struct ast_channel *owner;
1787                 ast_mutex_lock(&p->lock);
1788                 owner = agent_lock_owner(p);
1789                 if (p->pending) {
1790                         if (p->group)
1791                                 ast_cli(a->fd, "-- Pending call to group %d\n", powerof(p->group));
1792                         else
1793                                 ast_cli(a->fd, "-- Pending call to agent %s\n", p->agent);
1794                 } else {
1795                         if (!ast_strlen_zero(p->name))
1796                                 snprintf(username, sizeof(username), "(%s) ", p->name);
1797                         else
1798                                 username[0] = '\0';
1799                         if (p->chan) {
1800                                 snprintf(location, sizeof(location), "logged in on %s", ast_channel_name(p->chan));
1801                                 if (owner && ast_bridged_channel(owner)) {
1802                                         snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_channel_name(ast_bridged_channel(p->owner)));
1803                                 } else {
1804                                         strcpy(talkingto, " is idle");
1805                                 }
1806                                 online_agents++;
1807                         } else {
1808                                 strcpy(location, "not logged in");
1809                                 talkingto[0] = '\0';
1810                                 offline_agents++;
1811                         }
1812                         if (!ast_strlen_zero(p->moh))
1813                                 snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1814                         ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent, 
1815                                 username, location, talkingto, music);
1816                         count_agents++;
1817                 }
1818
1819                 if (owner) {
1820                         ast_channel_unlock(owner);
1821                         owner = ast_channel_unref(owner);
1822                 }
1823                 ast_mutex_unlock(&p->lock);
1824         }
1825         AST_LIST_UNLOCK(&agents);
1826         if ( !count_agents ) 
1827                 ast_cli(a->fd, "No Agents are configured in %s\n",config);
1828         else 
1829                 ast_cli(a->fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents);
1830         ast_cli(a->fd, "\n");
1831                         
1832         return CLI_SUCCESS;
1833 }
1834
1835
1836 static char *agents_show_online(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1837 {
1838         struct agent_pvt *p;
1839         char username[AST_MAX_BUF];
1840         char location[AST_MAX_BUF] = "";
1841         char talkingto[AST_MAX_BUF] = "";
1842         char music[AST_MAX_BUF];
1843         int count_agents = 0;           /* Number of agents configured */
1844         int online_agents = 0;          /* Number of online agents */
1845         int agent_status = 0;           /* 0 means offline, 1 means online */
1846
1847         switch (cmd) {
1848         case CLI_INIT:
1849                 e->command = "agent show online";
1850                 e->usage =
1851                         "Usage: agent show online\n"
1852                         "       Provides a list of all online agents.\n";
1853                 return NULL;
1854         case CLI_GENERATE:
1855                 return NULL;
1856         }
1857
1858         if (a->argc != 3)
1859                 return CLI_SHOWUSAGE;
1860
1861         AST_LIST_LOCK(&agents);
1862         AST_LIST_TRAVERSE(&agents, p, list) {
1863                 struct ast_channel *owner;
1864
1865                 agent_status = 0;       /* reset it to offline */
1866                 ast_mutex_lock(&p->lock);
1867                 owner = agent_lock_owner(p);
1868
1869                 if (!ast_strlen_zero(p->name))
1870                         snprintf(username, sizeof(username), "(%s) ", p->name);
1871                 else
1872                         username[0] = '\0';
1873                 if (p->chan) {
1874                         snprintf(location, sizeof(location), "logged in on %s", ast_channel_name(p->chan));
1875                         if (p->owner && ast_bridged_channel(p->owner)) {
1876                                 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_channel_name(ast_bridged_channel(p->owner)));
1877                         } else {
1878                                 strcpy(talkingto, " is idle");
1879                         }
1880                         agent_status = 1;
1881                         online_agents++;
1882                 }
1883
1884                 if (owner) {
1885                         ast_channel_unlock(owner);
1886                         owner = ast_channel_unref(owner);
1887                 }
1888
1889                 if (!ast_strlen_zero(p->moh))
1890                         snprintf(music, sizeof(music), " (musiconhold is '%s')", p->moh);
1891                 if (agent_status)
1892                         ast_cli(a->fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, music);
1893                 count_agents++;
1894                 ast_mutex_unlock(&p->lock);
1895         }
1896         AST_LIST_UNLOCK(&agents);
1897         if (!count_agents) 
1898                 ast_cli(a->fd, "No Agents are configured in %s\n", config);
1899         else
1900                 ast_cli(a->fd, "%d agents online\n", online_agents);
1901         ast_cli(a->fd, "\n");
1902         return CLI_SUCCESS;
1903 }
1904
1905 static const char agent_logoff_usage[] =
1906 "Usage: agent logoff <channel> [soft]\n"
1907 "       Sets an agent as no longer logged in.\n"
1908 "       If 'soft' is specified, do not hangup existing calls.\n";
1909
1910 static struct ast_cli_entry cli_agents[] = {
1911         AST_CLI_DEFINE(agents_show, "Show status of agents"),
1912         AST_CLI_DEFINE(agents_show_online, "Show all online agents"),
1913         AST_CLI_DEFINE(agent_logoff_cmd, "Sets an agent offline"),
1914 };
1915
1916 /*!
1917  * Called by the AgentLogin application (from the dial plan).
1918  * 
1919  * \brief Log in agent application.
1920  *
1921  * \param chan
1922  * \param data
1923  * \returns
1924  * \sa agentmonitoroutgoing_exec(), load_module().
1925  */
1926 static int login_exec(struct ast_channel *chan, const char *data)
1927 {
1928         int res=0;
1929         int tries = 0;
1930         int max_login_tries = maxlogintries;
1931         struct agent_pvt *p;
1932         struct ast_module_user *u;
1933         char user[AST_MAX_AGENT] = "";
1934         char pass[AST_MAX_AGENT];
1935         char agent[AST_MAX_AGENT] = "";
1936         char xpass[AST_MAX_AGENT] = "";
1937         char *errmsg;
1938         char *parse;
1939         AST_DECLARE_APP_ARGS(args,
1940                              AST_APP_ARG(agent_id);
1941                              AST_APP_ARG(options);
1942                              AST_APP_ARG(extension);
1943                 );
1944         const char *tmpoptions = NULL;
1945         int play_announcement = 1;
1946         char agent_goodbye[AST_MAX_FILENAME_LEN];
1947         int update_cdr = updatecdr;
1948         char *filename = "agent-loginok";
1949
1950         u = ast_module_user_add(chan);
1951
1952         parse = ast_strdupa(data);
1953
1954         AST_STANDARD_APP_ARGS(args, parse);
1955
1956         ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye));
1957
1958         ast_channel_lock(chan);
1959         /* Set Channel Specific Login Overrides */
1960         if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) {
1961                 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"));
1962                 if (max_login_tries < 0)
1963                         max_login_tries = 0;
1964                 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES");
1965                 ast_verb(3, "Saw variable AGENTMAXLOGINTRIES=%s, setting max_login_tries to: %d on Channel '%s'.\n",tmpoptions,max_login_tries,ast_channel_name(chan));
1966         }
1967         if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) {
1968                 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR")))
1969                         update_cdr = 1;
1970                 else
1971                         update_cdr = 0;
1972                 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR");
1973                 ast_verb(3, "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,ast_channel_name(chan));
1974         }
1975         if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) {
1976                 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"));
1977                 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE");
1978                 ast_verb(3, "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,ast_channel_name(chan));
1979         }
1980         ast_channel_unlock(chan);
1981         /* End Channel Specific Login Overrides */
1982         
1983         if (!ast_strlen_zero(args.options)) {
1984                 if (strchr(args.options, 's')) {
1985                         play_announcement = 0;
1986                 }
1987         }
1988
1989         if (ast_channel_state(chan) != AST_STATE_UP)
1990                 res = ast_answer(chan);
1991         if (!res) {
1992                 if (!ast_strlen_zero(args.agent_id))
1993                         ast_copy_string(user, args.agent_id, AST_MAX_AGENT);
1994                 else
1995                         res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0);
1996         }
1997         while (!res && (max_login_tries==0 || tries < max_login_tries)) {
1998                 tries++;
1999                 /* Check for password */
2000                 AST_LIST_LOCK(&agents);
2001                 AST_LIST_TRAVERSE(&agents, p, list) {
2002                         if (!strcmp(p->agent, user) && !p->pending)
2003                                 ast_copy_string(xpass, p->password, sizeof(xpass));
2004                 }
2005                 AST_LIST_UNLOCK(&agents);
2006                 if (!res) {
2007                         if (!ast_strlen_zero(xpass))
2008                                 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0);
2009                         else
2010                                 pass[0] = '\0';
2011                 }
2012                 errmsg = "agent-incorrect";
2013
2014 #if 0
2015                 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass);
2016 #endif          
2017
2018                 /* Check again for accuracy */
2019                 AST_LIST_LOCK(&agents);
2020                 AST_LIST_TRAVERSE(&agents, p, list) {
2021                         int unlock_channel = 1;
2022                         ast_channel_lock(chan);
2023                         ast_mutex_lock(&p->lock);
2024                         if (!strcmp(p->agent, user) &&
2025                             !strcmp(p->password, pass) && !p->pending) {
2026
2027                                 /* Ensure we can't be gotten until we're done */
2028                                 p->lastdisc = ast_tvnow();
2029                                 p->lastdisc.tv_sec++;
2030
2031                                 /* Set Channel Specific Agent Overrides */
2032                                 if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
2033                                         if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) {
2034                                                 p->ackcall = 1;
2035                                         } else {
2036                                                 p->ackcall = 0;
2037                                         }
2038                                         tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL");
2039                                         ast_verb(3, "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n", tmpoptions, p->ackcall, p->agent);
2040                                         ast_set_flag(p, AGENT_FLAG_ACKCALL);
2041                                 } else {
2042                                         p->ackcall = ackcall;
2043                                 }
2044                                 if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) {
2045                                         p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"));
2046                                         if (p->autologoff < 0)
2047                                                 p->autologoff = 0;
2048                                         tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF");
2049                                         ast_verb(3, "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n", tmpoptions, p->autologoff, p->agent);
2050                                         ast_set_flag(p, AGENT_FLAG_AUTOLOGOFF);
2051                                 } else {
2052                                         p->autologoff = autologoff;
2053                                 }
2054                                 if (!ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) {
2055                                         p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"));
2056                                         if (p->wrapuptime < 0)
2057                                                 p->wrapuptime = 0;
2058                                         tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME");
2059                                         ast_verb(3, "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n", tmpoptions, p->wrapuptime, p->agent);
2060                                         ast_set_flag(p, AGENT_FLAG_WRAPUPTIME);
2061                                 } else {
2062                                         p->wrapuptime = wrapuptime;
2063                                 }
2064                                 tmpoptions = pbx_builtin_getvar_helper(chan, "AGENTACCEPTDTMF");
2065                                 if (!ast_strlen_zero(tmpoptions)) {
2066                                         p->acceptdtmf = *tmpoptions;
2067                                         ast_verb(3, "Saw variable AGENTACCEPTDTMF=%s, setting acceptdtmf to: %c for Agent '%s'.\n", tmpoptions, p->acceptdtmf, p->agent);
2068                                         ast_set_flag(p, AGENT_FLAG_ACCEPTDTMF);
2069                                 }
2070                                 tmpoptions = pbx_builtin_getvar_helper(chan, "AGENTENDDTMF");
2071                                 if (!ast_strlen_zero(tmpoptions)) {
2072                                         p->enddtmf = *tmpoptions;
2073                                         ast_verb(3, "Saw variable AGENTENDDTMF=%s, setting enddtmf to: %c for Agent '%s'.\n", tmpoptions, p->enddtmf, p->agent);
2074                                         ast_set_flag(p, AGENT_FLAG_ENDDTMF);
2075                                 }
2076                                 ast_channel_unlock(chan);
2077                                 unlock_channel = 0;
2078                                 /* End Channel Specific Agent Overrides */
2079                                 if (!p->chan) {
2080                                         long logintime;
2081                                         snprintf(agent, sizeof(agent), "Agent/%s", p->agent);
2082
2083                                         p->logincallerid[0] = '\0';
2084                                         p->acknowledged = 0;
2085                                         
2086                                         ast_mutex_unlock(&p->lock);
2087                                         AST_LIST_UNLOCK(&agents);
2088                                         if( !res && play_announcement==1 )
2089                                                 res = ast_streamfile(chan, filename, ast_channel_language(chan));
2090                                         if (!res)
2091                                                 ast_waitstream(chan, "");
2092                                         AST_LIST_LOCK(&agents);
2093                                         ast_mutex_lock(&p->lock);
2094                                         if (!res) {
2095                                                 struct ast_format tmpfmt;
2096                                                 res = ast_set_read_format_from_cap(chan, ast_channel_nativeformats(chan));
2097                                                 if (res) {
2098                                                         ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(&tmpfmt));
2099                                                 }
2100                                         }
2101                                         if (!res) {
2102                                                 struct ast_format tmpfmt;
2103                                                 res = ast_set_write_format_from_cap(chan, ast_channel_nativeformats(chan));
2104                                                 if (res) {
2105                                                         ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(&tmpfmt));
2106                                                 }
2107                                         }
2108                                         /* Check once more just in case */
2109                                         if (p->chan)
2110                                                 res = -1;
2111                                         if (!res) {
2112                                                 ast_indicate_data(chan, AST_CONTROL_HOLD, 
2113                                                         S_OR(p->moh, NULL), 
2114                                                         !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0);
2115                                                 if (p->loginstart == 0)
2116                                                         time(&p->loginstart);
2117                                                 manager_event(EVENT_FLAG_AGENT, "Agentlogin",
2118                                                               "Agent: %s\r\n"
2119                                                               "Channel: %s\r\n"
2120                                                               "Uniqueid: %s\r\n",
2121                                                               p->agent, ast_channel_name(chan), ast_channel_uniqueid(chan));
2122                                                 if (update_cdr && ast_channel_cdr(chan))
2123                                                         snprintf(ast_channel_cdr(chan)->channel, sizeof(ast_channel_cdr(chan)->channel), "Agent/%s", p->agent);
2124                                                 ast_queue_log("NONE", ast_channel_uniqueid(chan), agent, "AGENTLOGIN", "%s", ast_channel_name(chan));
2125                                                 ast_verb(2, "Agent '%s' logged in (format %s/%s)\n", p->agent,
2126                                                                     ast_getformatname(ast_channel_readformat(chan)), ast_getformatname(ast_channel_writeformat(chan)));
2127                                                 /* Login this channel and wait for it to go away */
2128                                                 p->chan = chan;
2129                                                 if (p->ackcall) {
2130                                                         check_beep(p, 0);
2131                                                 } else {
2132                                                         check_availability(p, 0);
2133                                                 }
2134                                                 ast_mutex_unlock(&p->lock);
2135                                                 AST_LIST_UNLOCK(&agents);
2136                                                 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
2137                                                 while (res >= 0) {
2138                                                         ast_mutex_lock(&p->lock);
2139                                                         if (p->deferlogoff && p->chan) {
2140                                                                 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT);
2141                                                                 p->deferlogoff = 0;
2142                                                         }
2143                                                         if (p->chan != chan)
2144                                                                 res = -1;
2145                                                         ast_mutex_unlock(&p->lock);
2146                                                         /* Yield here so other interested threads can kick in. */
2147                                                         sched_yield();
2148                                                         if (res)
2149                                                                 break;
2150
2151                                                         AST_LIST_LOCK(&agents);
2152                                                         ast_mutex_lock(&p->lock);
2153                                                         if (p->lastdisc.tv_sec) {
2154                                                                 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) {
2155                                                                         ast_debug(1, "Wrapup time for %s expired!\n", p->agent);
2156                                                                         p->lastdisc = ast_tv(0, 0);
2157                                                                         ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Agent/%s", p->agent);
2158                                                                         if (p->ackcall) {
2159                                                                                 check_beep(p, 0);
2160                                                                         } else {
2161                                                                                 check_availability(p, 0);
2162                                                                         }
2163                                                                 }
2164                                                         }
2165                                                         ast_mutex_unlock(&p->lock);
2166                                                         AST_LIST_UNLOCK(&agents);
2167
2168                                                         /*      Synchronize channel ownership between call to agent and itself. */
2169                                                         ast_mutex_lock(&p->lock);
2170                                                         if (p->app_lock_flag == 1) {
2171                                                                 ast_cond_signal(&p->login_wait_cond);
2172                                                                 ast_cond_wait(&p->app_complete_cond, &p->lock);
2173                                                         }
2174                                                         ast_mutex_unlock(&p->lock);
2175                                                         if (p->ackcall) {
2176                                                                 res = agent_ack_sleep(p);
2177                                                         } else {
2178                                                                 res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p );
2179                                                         }
2180                                                         if (p->ackcall && (res == 1)) {
2181                                                                 AST_LIST_LOCK(&agents);
2182                                                                 ast_mutex_lock(&p->lock);
2183                                                                 check_availability(p, 0);
2184                                                                 ast_mutex_unlock(&p->lock);
2185                                                                 AST_LIST_UNLOCK(&agents);
2186                                                                 res = 0;
2187                                                         }
2188                                                         sched_yield();
2189                                                 }
2190                                                 ast_mutex_lock(&p->lock);
2191                                                 /* Log us off if appropriate */
2192                                                 if (p->chan == chan) {
2193                                                         p->chan = NULL;
2194                                                 }
2195
2196                                                 /* Synchronize channel ownership between call to agent and itself. */
2197                                                 if (p->app_lock_flag == 1) {
2198                                                         ast_cond_signal(&p->login_wait_cond);
2199                                                         ast_cond_wait(&p->app_complete_cond, &p->lock);
2200                                                 }
2201
2202                                                 if (res && p->owner)
2203                                                         ast_log(LOG_WARNING, "Huh?  We broke out when there was still an owner?\n");
2204
2205                                                 p->acknowledged = 0;
2206                                                 logintime = time(NULL) - p->loginstart;
2207                                                 p->loginstart = 0;
2208                                                 ast_mutex_unlock(&p->lock);
2209                                                 manager_event(EVENT_FLAG_AGENT, "Agentlogoff",
2210                                                               "Agent: %s\r\n"
2211                                                               "Logintime: %ld\r\n"
2212                                                               "Uniqueid: %s\r\n",
2213                                                               p->agent, logintime, ast_channel_uniqueid(chan));
2214                                                 ast_queue_log("NONE", ast_channel_uniqueid(chan), agent, "AGENTLOGOFF", "%s|%ld", ast_channel_name(chan), logintime);
2215                                                 ast_verb(2, "Agent '%s' logged out\n", p->agent);
2216                                                 /* If there is no owner, go ahead and kill it now */
2217                                                 ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Agent/%s", p->agent);
2218                                                 if (p->dead && !p->owner) {
2219                                                         ast_mutex_destroy(&p->lock);
2220                                                         ast_cond_destroy(&p->app_complete_cond);
2221                                                         ast_cond_destroy(&p->login_wait_cond);
2222                                                         ast_free(p);
2223                                                 }
2224                                         }
2225                                         else {
2226                                                 ast_mutex_unlock(&p->lock);
2227                                                 p = NULL;
2228                                         }
2229                                         res = -1;
2230                                 } else {
2231                                         ast_mutex_unlock(&p->lock);
2232                                         errmsg = "agent-alreadyon";
2233                                         p = NULL;
2234                                 }
2235                                 break;
2236                         }
2237                         ast_mutex_unlock(&p->lock);
2238                         if (unlock_channel) {
2239                                 ast_channel_unlock(chan);
2240                         }
2241                 }
2242                 if (!p)
2243                         AST_LIST_UNLOCK(&agents);
2244
2245                 if (!res && (max_login_tries==0 || tries < max_login_tries))
2246                         res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0);
2247         }
2248                 
2249         if (!res)
2250                 res = ast_safe_sleep(chan, 500);
2251
2252         ast_module_user_remove(u);
2253         
2254         return -1;
2255 }
2256
2257 /*!
2258  *  \brief Called by the AgentMonitorOutgoing application (from the dial plan).
2259  *
2260  * \param chan
2261  * \param data
2262  * \returns
2263  * \sa login_exec(), load_module().
2264  */
2265 static int agentmonitoroutgoing_exec(struct ast_channel *chan, const char *data)
2266 {
2267         int exitifnoagentid = 0;
2268         int nowarnings = 0;
2269         int changeoutgoing = 0;
2270         int res = 0;
2271         char agent[AST_MAX_AGENT];
2272
2273         if (data) {
2274                 if (strchr(data, 'd'))
2275                         exitifnoagentid = 1;
2276                 if (strchr(data, 'n'))
2277                         nowarnings = 1;
2278                 if (strchr(data, 'c'))
2279                         changeoutgoing = 1;
2280         }
2281         if (ast_channel_caller(chan)->id.number.valid
2282                 && !ast_strlen_zero(ast_channel_caller(chan)->id.number.str)) {
2283                 const char *tmp;
2284                 char agentvar[AST_MAX_BUF];
2285                 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID,
2286                         ast_channel_caller(chan)->id.number.str);
2287                 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) {
2288                         struct agent_pvt *p;
2289                         ast_copy_string(agent, tmp, sizeof(agent));
2290                         AST_LIST_LOCK(&agents);
2291                         AST_LIST_TRAVERSE(&agents, p, list) {
2292                                 if (!strcasecmp(p->agent, tmp)) {
2293                                         if (changeoutgoing) snprintf(ast_channel_cdr(chan)->channel, sizeof(ast_channel_cdr(chan)->channel), "Agent/%s", p->agent);
2294                                         __agent_start_monitoring(chan, p, 1);
2295                                         break;
2296                                 }
2297                         }
2298                         AST_LIST_UNLOCK(&agents);
2299                         
2300                 } else {
2301                         res = -1;
2302                         if (!nowarnings)
2303                                 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);
2304                 }
2305         } else {
2306                 res = -1;
2307                 if (!nowarnings)
2308                         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");
2309         }
2310         if (res) {
2311                 if (exitifnoagentid)
2312                         return res;
2313         }
2314         return 0;
2315 }
2316
2317 /*! \brief Part of PBX channel interface */
2318 static int agent_devicestate(const char *data)
2319 {
2320         struct agent_pvt *p;
2321         const char *s;
2322         ast_group_t groupmatch;
2323         int groupoff;
2324         int res = AST_DEVICE_INVALID;
2325         
2326         s = data;
2327         if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1))
2328                 groupmatch = (1 << groupoff);
2329         else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) {
2330                 groupmatch = (1 << groupoff);
2331         } else 
2332                 groupmatch = 0;
2333
2334         /* Check actual logged in agents first */
2335         AST_LIST_LOCK(&agents);
2336         AST_LIST_TRAVERSE(&agents, p, list) {
2337                 ast_mutex_lock(&p->lock);
2338                 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) {
2339                         if (p->owner) {
2340                                 if (res != AST_DEVICE_INUSE)
2341                                         res = AST_DEVICE_BUSY;
2342                         } else {
2343                                 if (res == AST_DEVICE_BUSY)
2344                                         res = AST_DEVICE_INUSE;
2345                                 if (p->chan) {
2346                                         if (res == AST_DEVICE_INVALID)
2347                                                 res = AST_DEVICE_UNKNOWN;
2348                                 } else if (res == AST_DEVICE_INVALID)   
2349                                         res = AST_DEVICE_UNAVAILABLE;
2350                         }
2351                         if (!strcmp(data, p->agent)) {
2352                                 ast_mutex_unlock(&p->lock);
2353                                 break;
2354                         }
2355                 }
2356                 ast_mutex_unlock(&p->lock);
2357         }
2358         AST_LIST_UNLOCK(&agents);
2359         return res;
2360 }
2361
2362 /*!
2363  * \note This function expects the agent list to be locked
2364  */
2365 static struct agent_pvt *find_agent(char *agentid)
2366 {
2367         struct agent_pvt *cur;
2368
2369         AST_LIST_TRAVERSE(&agents, cur, list) {
2370                 if (!strcmp(cur->agent, agentid))
2371                         break;  
2372         }
2373
2374         return cur;     
2375 }
2376
2377 static int function_agent(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
2378 {
2379         char *parse;    
2380         AST_DECLARE_APP_ARGS(args,
2381                 AST_APP_ARG(agentid);
2382                 AST_APP_ARG(item);
2383         );
2384         char *tmp;
2385         struct agent_pvt *agent;
2386
2387         buf[0] = '\0';
2388
2389         if (ast_strlen_zero(data)) {
2390                 ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n");
2391                 return -1;
2392         }
2393
2394         parse = ast_strdupa(data);
2395
2396         AST_NONSTANDARD_APP_ARGS(args, parse, ':');
2397         if (!args.item)
2398                 args.item = "status";
2399
2400         AST_LIST_LOCK(&agents);
2401
2402         if (!(agent = find_agent(args.agentid))) {
2403                 AST_LIST_UNLOCK(&agents);
2404                 ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid);
2405                 return -1;
2406         }
2407
2408         if (!strcasecmp(args.item, "status")) {
2409                 char *status = "LOGGEDOUT";
2410                 if (agent->chan) {
2411                         status = "LOGGEDIN";
2412                 }
2413                 ast_copy_string(buf, status, len);
2414         } else if (!strcasecmp(args.item, "password")) 
2415                 ast_copy_string(buf, agent->password, len);
2416         else if (!strcasecmp(args.item, "name"))
2417                 ast_copy_string(buf, agent->name, len);
2418         else if (!strcasecmp(args.item, "mohclass"))
2419                 ast_copy_string(buf, agent->moh, len);
2420         else if (!strcasecmp(args.item, "channel")) {
2421                 if (agent->chan) {
2422                         ast_channel_lock(agent->chan);
2423                         ast_copy_string(buf, ast_channel_name(agent->chan), len);
2424                         ast_channel_unlock(agent->chan);
2425                         tmp = strrchr(buf, '-');
2426                         if (tmp)
2427                                 *tmp = '\0';
2428                 } 
2429         } else if (!strcasecmp(args.item, "fullchannel")) {
2430                 if (agent->chan) {
2431                         ast_channel_lock(agent->chan);
2432                         ast_copy_string(buf, ast_channel_name(agent->chan), len);
2433                         ast_channel_unlock(agent->chan);
2434                 } 
2435         } else if (!strcasecmp(args.item, "exten")) {
2436                 buf[0] = '\0';
2437         }
2438
2439         AST_LIST_UNLOCK(&agents);
2440
2441         return 0;
2442 }
2443
2444 static struct ast_custom_function agent_function = {
2445         .name = "AGENT",
2446         .read = function_agent,
2447 };
2448
2449 /*!
2450  * \internal
2451  * \brief Callback used to generate the agents tree.
2452  * \param[in] search The search pattern tree.
2453  * \retval NULL on error.
2454  * \retval non-NULL The generated tree.
2455  */
2456 static int agents_data_provider_get(const struct ast_data_search *search,
2457         struct ast_data *data_root)
2458 {
2459         struct agent_pvt *p;
2460         struct ast_data *data_agent, *data_channel, *data_talkingto;
2461
2462         AST_LIST_LOCK(&agents);
2463         AST_LIST_TRAVERSE(&agents, p, list) {
2464                 struct ast_channel *owner;
2465
2466                 data_agent = ast_data_add_node(data_root, "agent");
2467                 if (!data_agent) {
2468                         continue;
2469                 }
2470
2471                 ast_mutex_lock(&p->lock);
2472                 owner = agent_lock_owner(p);
2473
2474                 if (!(p->pending)) {
2475                         ast_data_add_str(data_agent, "id", p->agent);
2476                         ast_data_add_structure(agent_pvt, data_agent, p);
2477
2478                         ast_data_add_bool(data_agent, "logged", p->chan ? 1 : 0);
2479                         if (p->chan) {
2480                                 data_channel = ast_data_add_node(data_agent, "loggedon");
2481                                 if (!data_channel) {
2482                                         ast_mutex_unlock(&p->lock);
2483                                         ast_data_remove_node(data_root, data_agent);
2484                                         if (owner) {
2485                                                 ast_channel_unlock(owner);
2486                                                 owner = ast_channel_unref(owner);
2487                                         }
2488                                         continue;
2489                                 }
2490                                 ast_channel_data_add_structure(data_channel, p->chan, 0);
2491                                 if (owner && ast_bridged_channel(owner)) {
2492                                         data_talkingto = ast_data_add_node(data_agent, "talkingto");
2493                                         if (!data_talkingto) {
2494                                                 ast_mutex_unlock(&p->lock);
2495                                                 ast_data_remove_node(data_root, data_agent);
2496                                                 if (owner) {
2497                                                         ast_channel_unlock(owner);
2498                                                         owner = ast_channel_unref(owner);
2499                                                 }
2500                                                 continue;
2501                                         }
2502                                         ast_channel_data_add_structure(data_talkingto, ast_bridged_channel(owner), 0);
2503                                 }
2504                         } else {
2505                                 ast_data_add_node(data_agent, "talkingto");
2506                                 ast_data_add_node(data_agent, "loggedon");
2507                         }
2508                         ast_data_add_str(data_agent, "musiconhold", p->moh);
2509                 }
2510
2511                 if (owner) {
2512                         ast_channel_unlock(owner);
2513                         owner = ast_channel_unref(owner);
2514                 }
2515
2516                 ast_mutex_unlock(&p->lock);
2517
2518                 /* if this agent doesn't match remove the added agent. */
2519                 if (!ast_data_search_match(search, data_agent)) {
2520                         ast_data_remove_node(data_root, data_agent);
2521                 }
2522         }
2523         AST_LIST_UNLOCK(&agents);
2524
2525         return 0;
2526 }
2527
2528 static const struct ast_data_handler agents_data_provider = {
2529         .version = AST_DATA_HANDLER_VERSION,
2530         .get = agents_data_provider_get
2531 };
2532
2533 static const struct ast_data_entry agents_data_providers[] = {
2534         AST_DATA_ENTRY("asterisk/channel/agent/list", &agents_data_provider),
2535 };
2536
2537 /*!
2538  * \brief Initialize the Agents module.
2539  * This function is being called by Asterisk when loading the module. 
2540  * Among other things it registers applications, cli commands and reads the cofiguration file.
2541  *
2542  * \returns int Always 0.
2543  */
2544 static int load_module(void)
2545 {
2546         if (!(agent_tech.capabilities = ast_format_cap_alloc())) {
2547                 ast_log(LOG_ERROR, "ast_format_cap_alloc_nolock fail.\n");
2548                 return AST_MODULE_LOAD_FAILURE;
2549         }
2550         ast_format_cap_add_all(agent_tech.capabilities);
2551         /* Make sure we can register our agent channel type */
2552         if (ast_channel_register(&agent_tech)) {
2553                 ast_log(LOG_ERROR, "Unable to register channel class 'Agent'\n");
2554                 return AST_MODULE_LOAD_FAILURE;
2555         }
2556         /* Read in the config */
2557         if (!read_agent_config(0))
2558                 return AST_MODULE_LOAD_DECLINE;
2559         /* Dialplan applications */
2560         ast_register_application_xml(app, login_exec);
2561         ast_register_application_xml(app3, agentmonitoroutgoing_exec);
2562
2563         /* data tree */
2564         ast_data_register_multiple(agents_data_providers, ARRAY_LEN(agents_data_providers));
2565
2566         /* Manager commands */
2567         ast_manager_register_xml("Agents", EVENT_FLAG_AGENT, action_agents);
2568         ast_manager_register_xml("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff);
2569
2570         /* CLI Commands */
2571         ast_cli_register_multiple(cli_agents, ARRAY_LEN(cli_agents));
2572
2573         /* Dialplan Functions */
2574         ast_custom_function_register(&agent_function);
2575
2576         return AST_MODULE_LOAD_SUCCESS;
2577 }
2578
2579 static int reload(void)
2580 {
2581         return read_agent_config(1);
2582 }
2583
2584 static int unload_module(void)
2585 {
2586         struct agent_pvt *p;
2587         /* First, take us out of the channel loop */
2588         ast_channel_unregister(&agent_tech);
2589         /* Unregister dialplan functions */
2590         ast_custom_function_unregister(&agent_function);        
2591         /* Unregister CLI commands */
2592         ast_cli_unregister_multiple(cli_agents, ARRAY_LEN(cli_agents));
2593         /* Unregister dialplan applications */
2594         ast_unregister_application(app);
2595         ast_unregister_application(app3);
2596         /* Unregister manager command */
2597         ast_manager_unregister("Agents");
2598         ast_manager_unregister("AgentLogoff");
2599         /* Unregister the data tree */
2600         ast_data_unregister(NULL);
2601         /* Unregister channel */
2602         AST_LIST_LOCK(&agents);
2603         /* Hangup all interfaces if they have an owner */
2604         while ((p = AST_LIST_REMOVE_HEAD(&agents, list))) {
2605                 if (p->owner)
2606                         ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD);
2607                 ast_free(p);
2608         }
2609         AST_LIST_UNLOCK(&agents);
2610
2611         agent_tech.capabilities = ast_format_cap_destroy(agent_tech.capabilities);
2612         return 0;
2613 }
2614
2615 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Agent Proxy Channel",
2616                 .load = load_module,
2617                 .unload = unload_module,
2618                 .reload = reload,
2619                 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
2620                 .nonoptreq = "res_monitor,chan_local",
2621                );