#include "asterisk.h"
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astdb.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
#include "asterisk/stringfields.h"
Go to the source code of this file.
Data Structures | |
struct | agent_pvt |
Structure representing an agent. More... | |
struct | agents |
Defines | |
#define | AST_MAX_AGENT 80 |
#define | AST_MAX_BUF 256 |
#define | AST_MAX_FILENAME_LEN 256 |
#define | CHECK_FORMATS(ast, p) |
#define | CLEANUP(ast, p) |
Cleanup moves all the relevant FD's from the 2nd to the first, but retains things properly for a timingfd XXX This might need more work if agents were logged in as agents or other totally impractical combinations XXX. | |
#define | GETAGENTBYCALLERID "AGENTBYCALLERID" |
#define | PA_MAX_LEN 2048 |
Functions | |
static int | __agent_start_monitoring (struct ast_channel *ast, struct agent_pvt *p, int needlock) |
static int | __login_exec (struct ast_channel *chan, void *data, int callbackmode) |
Log in agent application. | |
static void | __reg_module (void) |
static void | __unreg_module (void) |
static int | action_agent_callback_login (struct mansession *s, const struct message *m) |
static int | action_agent_logoff (struct mansession *s, const struct message *m) |
static int | action_agents (struct mansession *s, const struct message *m) |
static struct agent_pvt * | add_agent (char *agent, int pending) |
static int | agent_ack_sleep (void *data) |
static int | agent_answer (struct ast_channel *ast) |
static struct ast_channel * | agent_bridgedchannel (struct ast_channel *chan, struct ast_channel *bridge) |
static int | agent_call (struct ast_channel *ast, char *dest, int timeout) |
static int | agent_cleanup (struct agent_pvt *p) |
static int | agent_cont_sleep (void *data) |
static int | agent_devicestate (void *data) |
Part of PBX channel interface. | |
static int | agent_devicestate_cb (const char *dev, int state, void *data) |
static int | agent_digit_begin (struct ast_channel *ast, char digit) |
static int | agent_digit_end (struct ast_channel *ast, char digit, unsigned int duration) |
static int | agent_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static struct ast_channel * | agent_get_base_channel (struct ast_channel *chan) |
return the channel or base channel if one exists. This function assumes the channel it is called on is already locked | |
static int | agent_hangup (struct ast_channel *ast) |
static int | agent_indicate (struct ast_channel *ast, int condition, const void *data, size_t datalen) |
static int | agent_logoff (const char *agent, int soft) |
static int | agent_logoff_cmd (int fd, int argc, char **argv) |
static void | agent_logoff_maintenance (struct agent_pvt *p, char *loginchan, long logintime, const char *uniqueid, char *logcommand) |
static struct ast_channel * | agent_new (struct agent_pvt *p, int state) |
Create new agent channel. | |
static struct ast_frame * | agent_read (struct ast_channel *ast) |
static struct ast_channel * | agent_request (const char *type, int format, void *data, int *cause) |
Part of the Asterisk PBX interface. | |
static int | agent_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
static int | agent_sendtext (struct ast_channel *ast, const char *text) |
static int | agent_set_base_channel (struct ast_channel *chan, struct ast_channel *base) |
static int | agent_start_monitoring (struct ast_channel *ast, int needlock) |
static int | agent_write (struct ast_channel *ast, struct ast_frame *f) |
static int | agentmonitoroutgoing_exec (struct ast_channel *chan, void *data) |
Called by the AgentMonitorOutgoing application (from the dial plan). | |
static int | agents_show (int fd, int argc, char **argv) |
static int | agents_show_online (int fd, int argc, char **argv) |
static int | allow_multiple_login (char *chan, char *context) |
static void | callback_deprecated (void) |
static int | callback_exec (struct ast_channel *chan, void *data) |
static int | check_availability (struct agent_pvt *newlyavailable, int needlock) |
static int | check_beep (struct agent_pvt *newlyavailable, int needlock) |
static char * | complete_agent_logoff_cmd (const char *line, const char *word, int pos, int state) |
static void | dump_agents (void) |
Dump AgentCallbackLogin agents to the ASTdb database for persistence. | |
static struct agent_pvt * | find_agent (char *agentid) |
static int | function_agent (struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) |
static int | load_module (void) |
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other things it registers applications, cli commands and reads the cofiguration file. | |
static int | login_exec (struct ast_channel *chan, void *data) |
static force_inline int | powerof (unsigned int d) |
static int | read_agent_config (void) |
static int | reload (void) |
static void | reload_agents (void) |
Reload the persistent agents from astdb. | |
static void | set_agentbycallerid (const char *callerid, const char *agent) |
store/clear the global variable that stores agentid based on the callerid | |
static int | unload_module (void) |
Variables | |
static struct ast_module_info | __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Agent Proxy Channel" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } |
static int | ackcall |
ast_custom_function | agent_function |
static char | agent_logoff_usage [] |
static struct ast_channel_tech | agent_tech |
Channel interface description for PBX integration. | |
static char | agentgoodbye [AST_MAX_FILENAME_LEN] = "vm-goodbye" |
static const char | app [] = "AgentLogin" |
static const char | app2 [] = "AgentCallbackLogin" |
static const char | app3 [] = "AgentMonitorOutgoing" |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static int | autologoff |
static int | autologoffunavail = 0 |
static char | beep [AST_MAX_BUF] = "beep" |
static struct ast_cli_entry | cli_agents [] |
static struct ast_cli_entry | cli_show_agents_deprecated |
static struct ast_cli_entry | cli_show_agents_online_deprecated |
static const char | config [] = "agents.conf" |
static const char | descrip [] |
static const char | descrip2 [] |
static const char | descrip3 [] |
static int | endcall |
static ast_group_t | group |
static const char | mandescr_agent_callback_login [] |
static const char | mandescr_agent_logoff [] |
static const char | mandescr_agents [] |
static int | maxlogintries = 3 |
static char | moh [80] = "default" |
static int | multiplelogin = 1 |
static const char | pa_family [] = "Agents" |
static int | persistent_agents = 0 |
static int | recordagentcalls = 0 |
static char | recordformat [AST_MAX_BUF] = "" |
static char | recordformatext [AST_MAX_BUF] = "" |
static char | savecallsin [AST_MAX_BUF] = "" |
static char | show_agents_online_usage [] |
static char | show_agents_usage [] |
static const char | synopsis [] = "Call agent login" |
static const char | synopsis2 [] = "Call agent callback login" |
static const char | synopsis3 [] = "Record agent's outgoing call" |
static const char | tdesc [] = "Call Agent Proxy Channel" |
static int | updatecdr = 0 |
static char | urlprefix [AST_MAX_BUF] = "" |
static int | wrapuptime |
Definition in file chan_agent.c.
#define AST_MAX_AGENT 80 |
Agent ID or Password max length
Definition at line 146 of file chan_agent.c.
Referenced by __login_exec(), agent_logoff_maintenance(), agentmonitoroutgoing_exec(), and complete_agent_logoff_cmd().
#define AST_MAX_BUF 256 |
Definition at line 147 of file chan_agent.c.
Referenced by __agent_start_monitoring(), __login_exec(), agentmonitoroutgoing_exec(), agents_show(), agents_show_online(), and set_agentbycallerid().
#define AST_MAX_FILENAME_LEN 256 |
Definition at line 148 of file chan_agent.c.
Referenced by __login_exec(), and ael2_semantic_check().
#define CHECK_FORMATS | ( | ast, | |||
p | ) |
#define CLEANUP | ( | ast, | |||
p | ) |
Cleanup moves all the relevant FD's from the 2nd to the first, but retains things properly for a timingfd XXX This might need more work if agents were logged in as agents or other totally impractical combinations XXX.
Definition at line 234 of file chan_agent.c.
Referenced by agent_call(), agent_read(), and agent_write().
#define GETAGENTBYCALLERID "AGENTBYCALLERID" |
Definition at line 175 of file chan_agent.c.
Referenced by agentmonitoroutgoing_exec(), and set_agentbycallerid().
#define PA_MAX_LEN 2048 |
The maximum length of each persistent member agent database entry
Definition at line 151 of file chan_agent.c.
static int __agent_start_monitoring | ( | struct ast_channel * | ast, | |
struct agent_pvt * | p, | |||
int | needlock | |||
) | [static] |
Definition at line 463 of file chan_agent.c.
References agent_pvt::agent, ast_cdr_alloc(), ast_cdr_setuserfield(), ast_log(), AST_MAX_BUF, ast_monitor_setjoinfiles(), ast_monitor_start(), ast_verbose(), ast_channel::cdr, LOG_ERROR, ast_channel::monitor, and ast_channel::uniqueid.
Referenced by agent_start_monitoring(), and agentmonitoroutgoing_exec().
00464 { 00465 char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer; 00466 char filename[AST_MAX_BUF]; 00467 int res = -1; 00468 if (!p) 00469 return -1; 00470 if (!ast->monitor) { 00471 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid); 00472 /* substitute . for - */ 00473 if ((pointer = strchr(filename, '.'))) 00474 *pointer = '-'; 00475 snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename); 00476 ast_monitor_start(ast, recordformat, tmp, needlock); 00477 ast_monitor_setjoinfiles(ast, 1); 00478 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext); 00479 #if 0 00480 ast_verbose("name is %s, link is %s\n",tmp, tmp2); 00481 #endif 00482 if (!ast->cdr) 00483 ast->cdr = ast_cdr_alloc(); 00484 ast_cdr_setuserfield(ast, tmp2); 00485 res = 0; 00486 } else 00487 ast_log(LOG_ERROR, "Recording already started on that call.\n"); 00488 return res; 00489 }
static int __login_exec | ( | struct ast_channel * | chan, | |
void * | data, | |||
int | callbackmode | |||
) | [static] |
Log in agent application.
chan | ||
data | ||
callbackmode | non-zero for AgentCallbackLogin |
Definition at line 1989 of file chan_agent.c.
References ast_channel::_state, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_ack_sleep(), agent_cont_sleep(), agent_logoff_maintenance(), allow_multiple_login(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_best_codec(), ast_channel_lock, ast_channel_unlock, ast_cond_destroy(), ast_cond_signal(), ast_cond_wait(), AST_CONTROL_HOLD, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_device_state_changed(), AST_DIGIT_ANY, ast_exists_extension(), ast_getformatname(), ast_indicate_data(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_AGENT, AST_MAX_BUF, AST_MAX_FILENAME_LEN, ast_module_user_add, ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_log(), ast_safe_sleep(), ast_safe_sleep_conditional(), ast_set_read_format(), ast_set_write_format(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_true(), ast_tv(), ast_tvdiff_ms(), ast_tvnow(), ast_verbose(), ast_waitstream(), agent_pvt::autologoff, ast_channel::cdr, agent_pvt::chan, ast_cdr::channel, check_availability(), check_beep(), ast_channel::cid, ast_callerid::cid_num, context, agent_pvt::dead, agent_pvt::deferlogoff, dump_agents(), EVENT_FLAG_AGENT, free, agent_pvt::inherited_devicestate, ast_channel::language, agent_pvt::lastdisc, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, agent_pvt::login_wait_cond, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::moh, ast_channel::name, option_debug, option_verbose, agent_pvt::owner, parse(), agent_pvt::password, pbx_builtin_getvar_helper(), agent_pvt::pending, S_OR, set_agentbycallerid(), VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and agent_pvt::wrapuptime.
Referenced by callback_exec(), and login_exec().
01990 { 01991 int res=0; 01992 int tries = 0; 01993 int max_login_tries = maxlogintries; 01994 struct agent_pvt *p; 01995 struct ast_module_user *u; 01996 int login_state = 0; 01997 char user[AST_MAX_AGENT] = ""; 01998 char pass[AST_MAX_AGENT]; 01999 char agent[AST_MAX_AGENT] = ""; 02000 char xpass[AST_MAX_AGENT] = ""; 02001 char *errmsg; 02002 char *parse; 02003 AST_DECLARE_APP_ARGS(args, 02004 AST_APP_ARG(agent_id); 02005 AST_APP_ARG(options); 02006 AST_APP_ARG(extension); 02007 ); 02008 const char *tmpoptions = NULL; 02009 char *context = NULL; 02010 int play_announcement = 1; 02011 char agent_goodbye[AST_MAX_FILENAME_LEN]; 02012 int update_cdr = updatecdr; 02013 char *filename = "agent-loginok"; 02014 char tmpchan[AST_MAX_BUF] = ""; 02015 02016 u = ast_module_user_add(chan); 02017 02018 parse = ast_strdupa(data); 02019 02020 AST_STANDARD_APP_ARGS(args, parse); 02021 02022 ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye)); 02023 02024 ast_channel_lock(chan); 02025 /* Set Channel Specific Login Overrides */ 02026 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { 02027 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); 02028 if (max_login_tries < 0) 02029 max_login_tries = 0; 02030 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); 02031 if (option_verbose > 2) 02032 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTMAXLOGINTRIES=%s, setting max_login_tries to: %d on Channel '%s'.\n",tmpoptions,max_login_tries,chan->name); 02033 } 02034 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { 02035 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) 02036 update_cdr = 1; 02037 else 02038 update_cdr = 0; 02039 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); 02040 if (option_verbose > 2) 02041 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); 02042 } 02043 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { 02044 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); 02045 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); 02046 if (option_verbose > 2) 02047 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); 02048 } 02049 ast_channel_unlock(chan); 02050 /* End Channel Specific Login Overrides */ 02051 02052 if (callbackmode && args.extension) { 02053 parse = args.extension; 02054 args.extension = strsep(&parse, "@"); 02055 context = parse; 02056 } 02057 02058 if (!ast_strlen_zero(args.options)) { 02059 if (strchr(args.options, 's')) { 02060 play_announcement = 0; 02061 } 02062 } 02063 02064 if (chan->_state != AST_STATE_UP) 02065 res = ast_answer(chan); 02066 if (!res) { 02067 if (!ast_strlen_zero(args.agent_id)) 02068 ast_copy_string(user, args.agent_id, AST_MAX_AGENT); 02069 else 02070 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); 02071 } 02072 while (!res && (max_login_tries==0 || tries < max_login_tries)) { 02073 tries++; 02074 /* Check for password */ 02075 AST_LIST_LOCK(&agents); 02076 AST_LIST_TRAVERSE(&agents, p, list) { 02077 if (!strcmp(p->agent, user) && !p->pending) 02078 ast_copy_string(xpass, p->password, sizeof(xpass)); 02079 } 02080 AST_LIST_UNLOCK(&agents); 02081 if (!res) { 02082 if (!ast_strlen_zero(xpass)) 02083 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); 02084 else 02085 pass[0] = '\0'; 02086 } 02087 errmsg = "agent-incorrect"; 02088 02089 #if 0 02090 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); 02091 #endif 02092 02093 /* Check again for accuracy */ 02094 AST_LIST_LOCK(&agents); 02095 AST_LIST_TRAVERSE(&agents, p, list) { 02096 int unlock_channel = 1; 02097 ast_channel_lock(chan); 02098 ast_mutex_lock(&p->lock); 02099 if (!strcmp(p->agent, user) && 02100 !strcmp(p->password, pass) && !p->pending) { 02101 login_state = 1; /* Successful Login */ 02102 02103 /* Ensure we can't be gotten until we're done */ 02104 gettimeofday(&p->lastdisc, NULL); 02105 p->lastdisc.tv_sec++; 02106 02107 /* Set Channel Specific Agent Overrides */ 02108 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { 02109 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) 02110 p->ackcall = 2; 02111 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) 02112 p->ackcall = 1; 02113 else 02114 p->ackcall = 0; 02115 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); 02116 if (option_verbose > 2) 02117 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); 02118 } else { 02119 p->ackcall = ackcall; 02120 } 02121 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { 02122 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); 02123 if (p->autologoff < 0) 02124 p->autologoff = 0; 02125 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); 02126 if (option_verbose > 2) 02127 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); 02128 } else { 02129 p->autologoff = autologoff; 02130 } 02131 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { 02132 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); 02133 if (p->wrapuptime < 0) 02134 p->wrapuptime = 0; 02135 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); 02136 if (option_verbose > 2) 02137 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); 02138 } else { 02139 p->wrapuptime = wrapuptime; 02140 } 02141 ast_channel_unlock(chan); 02142 unlock_channel = 0; 02143 /* End Channel Specific Agent Overrides */ 02144 if (!p->chan) { 02145 char last_loginchan[80] = ""; 02146 long logintime; 02147 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 02148 02149 if (callbackmode) { 02150 int pos = 0; 02151 /* Retrieve login chan */ 02152 for (;;) { 02153 if (!ast_strlen_zero(args.extension)) { 02154 ast_copy_string(tmpchan, args.extension, sizeof(tmpchan)); 02155 res = 0; 02156 } else 02157 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0); 02158 if (ast_strlen_zero(tmpchan) ) 02159 break; 02160 if(ast_exists_extension(chan, S_OR(context,"default"), tmpchan,1, NULL) ) { 02161 if(!allow_multiple_login(tmpchan,context) ) { 02162 args.extension = NULL; 02163 pos = 0; 02164 } else 02165 break; 02166 } 02167 if (args.extension) { 02168 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", args.extension, p->agent); 02169 args.extension = NULL; 02170 pos = 0; 02171 } else { 02172 ast_log(LOG_WARNING, "Extension '%s@%s' is not valid for automatic login of agent '%s'\n", tmpchan, S_OR(context, "default"), p->agent); 02173 res = ast_streamfile(chan, "invalid", chan->language); 02174 if (!res) 02175 res = ast_waitstream(chan, AST_DIGIT_ANY); 02176 if (res > 0) { 02177 tmpchan[0] = res; 02178 tmpchan[1] = '\0'; 02179 pos = 1; 02180 } else { 02181 tmpchan[0] = '\0'; 02182 pos = 0; 02183 } 02184 } 02185 } 02186 args.extension = tmpchan; 02187 if (!res) { 02188 set_agentbycallerid(p->logincallerid, NULL); 02189 if (!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) 02190 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); 02191 else { 02192 ast_copy_string(last_loginchan, p->loginchan, sizeof(last_loginchan)); 02193 ast_copy_string(p->loginchan, tmpchan, sizeof(p->loginchan)); 02194 } 02195 p->acknowledged = 0; 02196 if (ast_strlen_zero(p->loginchan)) { 02197 login_state = 2; 02198 filename = "agent-loggedoff"; 02199 } else { 02200 if (chan->cid.cid_num) { 02201 ast_copy_string(p->logincallerid, chan->cid.cid_num, sizeof(p->logincallerid)); 02202 set_agentbycallerid(p->logincallerid, p->agent); 02203 } else 02204 p->logincallerid[0] = '\0'; 02205 } 02206 02207 if(update_cdr && chan->cdr) 02208 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02209 02210 } 02211 } else { 02212 p->loginchan[0] = '\0'; 02213 p->logincallerid[0] = '\0'; 02214 p->acknowledged = 0; 02215 } 02216 ast_mutex_unlock(&p->lock); 02217 AST_LIST_UNLOCK(&agents); 02218 if( !res && play_announcement==1 ) 02219 res = ast_streamfile(chan, filename, chan->language); 02220 if (!res) 02221 ast_waitstream(chan, ""); 02222 AST_LIST_LOCK(&agents); 02223 ast_mutex_lock(&p->lock); 02224 if (!res) { 02225 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); 02226 if (res) 02227 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); 02228 } 02229 if (!res) { 02230 res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); 02231 if (res) 02232 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); 02233 } 02234 /* Check once more just in case */ 02235 if (p->chan) 02236 res = -1; 02237 if (callbackmode && !res) { 02238 /* Just say goodbye and be done with it */ 02239 if (!ast_strlen_zero(p->loginchan)) { 02240 if (p->loginstart == 0) 02241 time(&p->loginstart); 02242 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02243 "Agent: %s\r\n" 02244 "Loginchan: %s\r\n" 02245 "Uniqueid: %s\r\n", 02246 p->agent, p->loginchan, chan->uniqueid); 02247 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02248 if (option_verbose > 1) 02249 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02250 ast_device_state_changed("Agent/%s", p->agent); 02251 if (persistent_agents) 02252 dump_agents(); 02253 } else { 02254 logintime = time(NULL) - p->loginstart; 02255 p->loginstart = 0; 02256 02257 agent_logoff_maintenance(p, last_loginchan, logintime, chan->uniqueid, NULL); 02258 if (option_verbose > 1) 02259 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent); 02260 } 02261 AST_LIST_UNLOCK(&agents); 02262 if (!res) 02263 res = ast_safe_sleep(chan, 500); 02264 ast_mutex_unlock(&p->lock); 02265 } else if (!res) { 02266 ast_indicate_data(chan, AST_CONTROL_HOLD, 02267 S_OR(p->moh, NULL), 02268 !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0); 02269 if (p->loginstart == 0) 02270 time(&p->loginstart); 02271 manager_event(EVENT_FLAG_AGENT, "Agentlogin", 02272 "Agent: %s\r\n" 02273 "Channel: %s\r\n" 02274 "Uniqueid: %s\r\n", 02275 p->agent, chan->name, chan->uniqueid); 02276 if (update_cdr && chan->cdr) 02277 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02278 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); 02279 if (option_verbose > 1) 02280 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent, 02281 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); 02282 /* Login this channel and wait for it to go away */ 02283 p->chan = chan; 02284 if (p->ackcall > 1) 02285 check_beep(p, 0); 02286 else 02287 check_availability(p, 0); 02288 ast_mutex_unlock(&p->lock); 02289 AST_LIST_UNLOCK(&agents); 02290 ast_device_state_changed("Agent/%s", p->agent); 02291 while (res >= 0) { 02292 ast_mutex_lock(&p->lock); 02293 if (p->deferlogoff && p->chan) { 02294 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 02295 p->deferlogoff = 0; 02296 } 02297 if (p->chan != chan) 02298 res = -1; 02299 ast_mutex_unlock(&p->lock); 02300 /* Yield here so other interested threads can kick in. */ 02301 sched_yield(); 02302 if (res) 02303 break; 02304 02305 AST_LIST_LOCK(&agents); 02306 ast_mutex_lock(&p->lock); 02307 if (p->lastdisc.tv_sec) { 02308 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) { 02309 if (option_debug) 02310 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent); 02311 p->lastdisc = ast_tv(0, 0); 02312 ast_device_state_changed("Agent/%s", p->agent); 02313 if (p->ackcall > 1) 02314 check_beep(p, 0); 02315 else 02316 check_availability(p, 0); 02317 } 02318 } 02319 ast_mutex_unlock(&p->lock); 02320 AST_LIST_UNLOCK(&agents); 02321 02322 /* Synchronize channel ownership between call to agent and itself. */ 02323 ast_mutex_lock(&p->lock); 02324 if (p->app_lock_flag == 1) { 02325 ast_cond_signal(&p->login_wait_cond); 02326 ast_cond_wait(&p->app_complete_cond, &p->lock); 02327 } 02328 ast_mutex_unlock(&p->lock); 02329 02330 if (p->ackcall > 1) 02331 res = agent_ack_sleep(p); 02332 else 02333 res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p ); 02334 if ((p->ackcall > 1) && (res == 1)) { 02335 AST_LIST_LOCK(&agents); 02336 ast_mutex_lock(&p->lock); 02337 check_availability(p, 0); 02338 ast_mutex_unlock(&p->lock); 02339 AST_LIST_UNLOCK(&agents); 02340 res = 0; 02341 } 02342 sched_yield(); 02343 } 02344 ast_mutex_lock(&p->lock); 02345 /* Log us off if appropriate */ 02346 if (p->chan == chan) { 02347 p->chan = NULL; 02348 p->inherited_devicestate = -1; 02349 } 02350 02351 /* Synchronize channel ownership between call to agent and itself. */ 02352 if (p->app_lock_flag == 1) { 02353 ast_cond_signal(&p->login_wait_cond); 02354 ast_cond_wait(&p->app_complete_cond, &p->lock); 02355 } 02356 02357 if (res && p->owner) 02358 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); 02359 02360 p->acknowledged = 0; 02361 logintime = time(NULL) - p->loginstart; 02362 p->loginstart = 0; 02363 ast_mutex_unlock(&p->lock); 02364 manager_event(EVENT_FLAG_AGENT, "Agentlogoff", 02365 "Agent: %s\r\n" 02366 "Logintime: %ld\r\n" 02367 "Uniqueid: %s\r\n", 02368 p->agent, logintime, chan->uniqueid); 02369 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); 02370 if (option_verbose > 1) 02371 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent); 02372 /* If there is no owner, go ahead and kill it now */ 02373 ast_device_state_changed("Agent/%s", p->agent); 02374 if (p->dead && !p->owner) { 02375 ast_mutex_destroy(&p->lock); 02376 ast_cond_destroy(&p->app_complete_cond); 02377 ast_cond_destroy(&p->login_wait_cond); 02378 free(p); 02379 } 02380 } 02381 else { 02382 ast_mutex_unlock(&p->lock); 02383 p = NULL; 02384 } 02385 res = -1; 02386 } else { 02387 ast_mutex_unlock(&p->lock); 02388 errmsg = "agent-alreadyon"; 02389 p = NULL; 02390 } 02391 break; 02392 } 02393 ast_mutex_unlock(&p->lock); 02394 if (unlock_channel) { 02395 ast_channel_unlock(chan); 02396 } 02397 } 02398 if (!p) 02399 AST_LIST_UNLOCK(&agents); 02400 02401 if (!res && (max_login_tries==0 || tries < max_login_tries)) 02402 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); 02403 } 02404 02405 if (!res) 02406 res = ast_safe_sleep(chan, 500); 02407 02408 /* AgentLogin() exit */ 02409 if (!callbackmode) { 02410 ast_module_user_remove(u); 02411 return -1; 02412 } else { /* AgentCallbackLogin() exit*/ 02413 /* Set variables */ 02414 if (login_state > 0) { 02415 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); 02416 if (login_state==1) { 02417 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); 02418 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", args.extension); 02419 } else 02420 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); 02421 } else { 02422 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); 02423 } 02424 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) { 02425 ast_module_user_remove(u); 02426 return 0; 02427 } 02428 /* Do we need to play agent-goodbye now that we will be hanging up? */ 02429 if (play_announcement) { 02430 if (!res) 02431 res = ast_safe_sleep(chan, 1000); 02432 res = ast_streamfile(chan, agent_goodbye, chan->language); 02433 if (!res) 02434 res = ast_waitstream(chan, ""); 02435 if (!res) 02436 res = ast_safe_sleep(chan, 1000); 02437 } 02438 } 02439 02440 ast_module_user_remove(u); 02441 02442 /* We should never get here if next priority exists when in callbackmode */ 02443 return -1; 02444 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 2937 of file chan_agent.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2937 of file chan_agent.c.
static int action_agent_callback_login | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Sets an agent as logged in by callback in the Manager API. It is registered on load_module() and it gets called by the manager backend.
s | ||
m |
Definition at line 2495 of file chan_agent.c.
References agent_pvt::ackcall, agent_pvt::agent, ast_copy_string(), ast_device_state_changed(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_queue_log(), ast_strlen_zero(), ast_true(), ast_verbose(), astman_get_header(), astman_send_ack(), astman_send_error(), callback_deprecated(), agent_pvt::chan, context, dump_agents(), EVENT_FLAG_AGENT, exten, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), option_verbose, agent_pvt::pending, s, VERBOSE_PREFIX_2, and agent_pvt::wrapuptime.
Referenced by load_module().
02496 { 02497 const char *agent = astman_get_header(m, "Agent"); 02498 const char *exten = astman_get_header(m, "Exten"); 02499 const char *context = astman_get_header(m, "Context"); 02500 const char *wrapuptime_s = astman_get_header(m, "WrapupTime"); 02501 const char *ackcall_s = astman_get_header(m, "AckCall"); 02502 struct agent_pvt *p; 02503 int login_state = 0; 02504 02505 callback_deprecated(); 02506 02507 if (ast_strlen_zero(agent)) { 02508 astman_send_error(s, m, "No agent specified"); 02509 return 0; 02510 } 02511 02512 if (ast_strlen_zero(exten)) { 02513 astman_send_error(s, m, "No extension specified"); 02514 return 0; 02515 } 02516 02517 AST_LIST_LOCK(&agents); 02518 AST_LIST_TRAVERSE(&agents, p, list) { 02519 if (strcmp(p->agent, agent) || p->pending) 02520 continue; 02521 if (p->chan) { 02522 login_state = 2; /* already logged in (and on the phone)*/ 02523 break; 02524 } 02525 ast_mutex_lock(&p->lock); 02526 login_state = 1; /* Successful Login */ 02527 02528 if (ast_strlen_zero(context)) 02529 ast_copy_string(p->loginchan, exten, sizeof(p->loginchan)); 02530 else 02531 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context); 02532 02533 if (!ast_strlen_zero(wrapuptime_s)) { 02534 p->wrapuptime = atoi(wrapuptime_s); 02535 if (p->wrapuptime < 0) 02536 p->wrapuptime = 0; 02537 } 02538 02539 if (!strcasecmp(ackcall_s, "always")) 02540 p->ackcall = 2; 02541 else if (ast_true(ackcall_s)) 02542 p->ackcall = 1; 02543 else 02544 p->ackcall = 0; 02545 02546 if (p->loginstart == 0) 02547 time(&p->loginstart); 02548 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02549 "Agent: %s\r\n" 02550 "Loginchan: %s\r\n", 02551 p->agent, p->loginchan); 02552 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02553 if (option_verbose > 1) 02554 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02555 ast_device_state_changed("Agent/%s", p->agent); 02556 ast_mutex_unlock(&p->lock); 02557 if (persistent_agents) 02558 dump_agents(); 02559 } 02560 AST_LIST_UNLOCK(&agents); 02561 02562 if (login_state == 1) 02563 astman_send_ack(s, m, "Agent logged in"); 02564 else if (login_state == 0) 02565 astman_send_error(s, m, "No such agent"); 02566 else if (login_state == 2) 02567 astman_send_error(s, m, "Agent already logged in"); 02568 02569 return 0; 02570 }
static int action_agent_logoff | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Sets an agent as no longer logged in in the Manager API. It is registered on load_module() and it gets called by the manager backend.
s | ||
m |
Definition at line 1777 of file chan_agent.c.
References agent_pvt::agent, agent_logoff(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), and s.
Referenced by load_module().
01778 { 01779 const char *agent = astman_get_header(m, "Agent"); 01780 const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */ 01781 int soft; 01782 int ret; /* return value of agent_logoff */ 01783 01784 if (ast_strlen_zero(agent)) { 01785 astman_send_error(s, m, "No agent specified"); 01786 return 0; 01787 } 01788 01789 soft = ast_true(soft_s) ? 1 : 0; 01790 ret = agent_logoff(agent, soft); 01791 if (ret == 0) 01792 astman_send_ack(s, m, "Agent logged out"); 01793 else 01794 astman_send_error(s, m, "No such agent"); 01795 01796 return 0; 01797 }
static int action_agents | ( | struct mansession * | s, | |
const struct message * | m | |||
) | [static] |
Lists agents and their status to the Manager API. It is registered on load_module() and it gets called by the manager backend.
s | ||
m |
Definition at line 1590 of file chan_agent.c.
References ast_channel::_bridge, agent_pvt::acknowledged, agent_pvt::agent, ast_bridged_channel(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), astman_append(), astman_get_header(), astman_send_ack(), agent_pvt::chan, ast_channel::cid, ast_callerid::cid_num, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, ast_channel::name, agent_pvt::name, agent_pvt::owner, s, S_OR, and username.
Referenced by load_module().
01591 { 01592 const char *id = astman_get_header(m,"ActionID"); 01593 char idText[256] = ""; 01594 char chanbuf[256]; 01595 struct agent_pvt *p; 01596 char *username = NULL; 01597 char *loginChan = NULL; 01598 char *talkingtoChan = NULL; 01599 char *status = NULL; 01600 01601 if (!ast_strlen_zero(id)) 01602 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); 01603 astman_send_ack(s, m, "Agents will follow"); 01604 AST_LIST_LOCK(&agents); 01605 AST_LIST_TRAVERSE(&agents, p, list) { 01606 ast_mutex_lock(&p->lock); 01607 01608 /* Status Values: 01609 AGENT_LOGGEDOFF - Agent isn't logged in 01610 AGENT_IDLE - Agent is logged in, and waiting for call 01611 AGENT_ONCALL - Agent is logged in, and on a call 01612 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */ 01613 01614 username = S_OR(p->name, "None"); 01615 01616 /* Set a default status. It 'should' get changed. */ 01617 status = "AGENT_UNKNOWN"; 01618 01619 if (!ast_strlen_zero(p->loginchan) && !p->chan) { 01620 loginChan = p->loginchan; 01621 talkingtoChan = "n/a"; 01622 status = "AGENT_IDLE"; 01623 if (p->acknowledged) { 01624 snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan); 01625 loginChan = chanbuf; 01626 } 01627 } else if (p->chan) { 01628 loginChan = ast_strdupa(p->chan->name); 01629 if (p->owner && p->owner->_bridge) { 01630 if (ast_bridged_channel(p->owner)) { 01631 talkingtoChan = ast_strdupa(S_OR(ast_bridged_channel(p->owner)->cid.cid_num, "")); 01632 } else { 01633 talkingtoChan = "n/a"; 01634 } 01635 status = "AGENT_ONCALL"; 01636 } else { 01637 talkingtoChan = "n/a"; 01638 status = "AGENT_IDLE"; 01639 } 01640 } else { 01641 loginChan = "n/a"; 01642 talkingtoChan = "n/a"; 01643 status = "AGENT_LOGGEDOFF"; 01644 } 01645 01646 astman_append(s, "Event: Agents\r\n" 01647 "Agent: %s\r\n" 01648 "Name: %s\r\n" 01649 "Status: %s\r\n" 01650 "LoggedInChan: %s\r\n" 01651 "LoggedInTime: %d\r\n" 01652 "TalkingTo: %s\r\n" 01653 "%s" 01654 "\r\n", 01655 p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText); 01656 ast_mutex_unlock(&p->lock); 01657 } 01658 AST_LIST_UNLOCK(&agents); 01659 astman_append(s, "Event: AgentsComplete\r\n" 01660 "%s" 01661 "\r\n",idText); 01662 return 0; 01663 }
static struct agent_pvt* add_agent | ( | char * | agent, | |
int | pending | |||
) | [static] |
Adds an agent to the global list of agents.
agent | A string with the username, password and real name of an agent. As defined in agents.conf. Example: "13,169,John Smith" | |
pending | If it is pending or not. |
Definition at line 338 of file chan_agent.c.
References agent_pvt::ackcall, agent_pvt::agent, AST_APP_ARG, ast_calloc, ast_cond_init(), ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, ast_log(), ast_mutex_init(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_tvnow(), agent_pvt::autologoff, agent_pvt::dead, agent_pvt::lastdisc, agent_pvt::list, LOG_WARNING, agent_pvt::moh, agent_pvt::name, parse(), agent_pvt::password, and agent_pvt::wrapuptime.
Referenced by agent_request(), and read_agent_config().
00339 { 00340 char *parse; 00341 AST_DECLARE_APP_ARGS(args, 00342 AST_APP_ARG(agt); 00343 AST_APP_ARG(password); 00344 AST_APP_ARG(name); 00345 ); 00346 char *password = NULL; 00347 char *name = NULL; 00348 char *agt = NULL; 00349 struct agent_pvt *p; 00350 00351 parse = ast_strdupa(agent); 00352 00353 /* Extract username (agt), password and name from agent (args). */ 00354 AST_NONSTANDARD_APP_ARGS(args, parse, ','); 00355 00356 if(args.argc == 0) { 00357 ast_log(LOG_WARNING, "A blank agent line!\n"); 00358 return NULL; 00359 } 00360 00361 if(ast_strlen_zero(args.agt) ) { 00362 ast_log(LOG_WARNING, "An agent line with no agentid!\n"); 00363 return NULL; 00364 } else 00365 agt = args.agt; 00366 00367 if(!ast_strlen_zero(args.password)) { 00368 password = args.password; 00369 while (*password && *password < 33) password++; 00370 } 00371 if(!ast_strlen_zero(args.name)) { 00372 name = args.name; 00373 while (*name && *name < 33) name++; 00374 } 00375 00376 /* Are we searching for the agent here ? To see if it exists already ? */ 00377 AST_LIST_TRAVERSE(&agents, p, list) { 00378 if (!pending && !strcmp(p->agent, agt)) 00379 break; 00380 } 00381 if (!p) { 00382 // Build the agent. 00383 if (!(p = ast_calloc(1, sizeof(*p)))) 00384 return NULL; 00385 ast_copy_string(p->agent, agt, sizeof(p->agent)); 00386 ast_mutex_init(&p->lock); 00387 ast_cond_init(&p->app_complete_cond, NULL); 00388 ast_cond_init(&p->login_wait_cond, NULL); 00389 p->app_lock_flag = 0; 00390 p->app_sleep_cond = 1; 00391 p->group = group; 00392 p->pending = pending; 00393 p->inherited_devicestate = -1; 00394 AST_LIST_INSERT_TAIL(&agents, p, list); 00395 } 00396 00397 ast_copy_string(p->password, password ? password : "", sizeof(p->password)); 00398 ast_copy_string(p->name, name ? name : "", sizeof(p->name)); 00399 ast_copy_string(p->moh, moh, sizeof(p->moh)); 00400 p->ackcall = ackcall; 00401 p->autologoff = autologoff; 00402 00403 /* If someone reduces the wrapuptime and reloads, we want it 00404 * to change the wrapuptime immediately on all calls */ 00405 if (p->wrapuptime > wrapuptime) { 00406 struct timeval now = ast_tvnow(); 00407 /* XXX check what is this exactly */ 00408 00409 /* We won't be pedantic and check the tv_usec val */ 00410 if (p->lastdisc.tv_sec > (now.tv_sec + wrapuptime/1000)) { 00411 p->lastdisc.tv_sec = now.tv_sec + wrapuptime/1000; 00412 p->lastdisc.tv_usec = now.tv_usec; 00413 } 00414 } 00415 p->wrapuptime = wrapuptime; 00416 00417 if (pending) 00418 p->dead = 1; 00419 else 00420 p->dead = 0; 00421 return p; 00422 }
static int agent_ack_sleep | ( | void * | data | ) | [static] |
Definition at line 1037 of file chan_agent.c.
References agent_pvt::app_sleep_cond, AST_FRAME_DTMF, ast_frfree, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), ast_waitfor(), agent_pvt::chan, f, and agent_pvt::lock.
Referenced by __login_exec().
01038 { 01039 struct agent_pvt *p; 01040 int res=0; 01041 int to = 1000; 01042 struct ast_frame *f; 01043 01044 /* Wait a second and look for something */ 01045 01046 p = (struct agent_pvt *) data; 01047 if (!p->chan) 01048 return -1; 01049 01050 for(;;) { 01051 to = ast_waitfor(p->chan, to); 01052 if (to < 0) 01053 return -1; 01054 if (!to) 01055 return 0; 01056 f = ast_read(p->chan); 01057 if (!f) 01058 return -1; 01059 if (f->frametype == AST_FRAME_DTMF) 01060 res = f->subclass; 01061 else 01062 res = 0; 01063 ast_frfree(f); 01064 ast_mutex_lock(&p->lock); 01065 if (!p->app_sleep_cond) { 01066 ast_mutex_unlock(&p->lock); 01067 return 0; 01068 } else if (res == '#') { 01069 ast_mutex_unlock(&p->lock); 01070 return 1; 01071 } 01072 ast_mutex_unlock(&p->lock); 01073 res = 0; 01074 } 01075 return res; 01076 }
static int agent_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 457 of file chan_agent.c.
References ast_log(), and LOG_WARNING.
00458 { 00459 ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n"); 00460 return -1; 00461 }
static struct ast_channel * agent_bridgedchannel | ( | struct ast_channel * | chan, | |
struct ast_channel * | bridge | |||
) | [static] |
Definition at line 1078 of file chan_agent.c.
References ast_channel::_bridge, ast_log(), agent_pvt::chan, LOG_DEBUG, ast_channel::name, option_debug, and ast_channel::tech_pvt.
01079 { 01080 struct agent_pvt *p = bridge->tech_pvt; 01081 struct ast_channel *ret = NULL; 01082 01083 if (p) { 01084 if (chan == p->chan) 01085 ret = bridge->_bridge; 01086 else if (chan == bridge->_bridge) 01087 ret = p->chan; 01088 } 01089 01090 if (option_debug) 01091 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>"); 01092 return ret; 01093 }
static int agent_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 754 of file chan_agent.c.
References agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_start_monitoring(), ast_best_codec(), ast_call(), ast_channel_inherit_variables(), ast_device_state_changed(), ast_getformatname(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_callerid(), ast_set_read_format(), ast_set_write_format(), ast_setstate(), AST_STATE_DIALING, AST_STATE_RINGING, AST_STATE_UP, ast_streamfile(), ast_strlen_zero(), ast_verbose(), ast_waitstream(), agent_pvt::chan, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, CLEANUP, agent_pvt::inherited_devicestate, ast_channel::language, agent_pvt::lock, LOG_DEBUG, LOG_WARNING, agent_pvt::loginchan, ast_channel::name, ast_channel::nativeformats, option_debug, option_verbose, agent_pvt::pending, agent_pvt::start, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
00755 { 00756 struct agent_pvt *p = ast->tech_pvt; 00757 int res = -1; 00758 int newstate=0; 00759 struct ast_channel *chan; 00760 00761 ast_mutex_lock(&p->lock); 00762 p->acknowledged = 0; 00763 00764 if (p->pending) { 00765 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n"); 00766 ast_mutex_unlock(&p->lock); 00767 ast_setstate(ast, AST_STATE_DIALING); 00768 return 0; 00769 } 00770 00771 if (!p->chan) { 00772 ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n"); 00773 ast_mutex_unlock(&p->lock); 00774 return res; 00775 } 00776 00777 if (!ast_strlen_zero(p->loginchan)) { 00778 time(&p->start); 00779 /* Call on this agent */ 00780 if (option_verbose > 2) 00781 ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name); 00782 ast_set_callerid(p->chan, 00783 ast->cid.cid_num, ast->cid.cid_name, NULL); 00784 ast_channel_inherit_variables(ast, p->chan); 00785 res = ast_call(p->chan, p->loginchan, 0); 00786 CLEANUP(ast,p); 00787 ast_mutex_unlock(&p->lock); 00788 return res; 00789 } 00790 if (option_verbose > 2) 00791 ast_verbose(VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name); 00792 if (option_debug > 2) 00793 ast_log(LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language); 00794 00795 chan = p->chan; 00796 ast_mutex_unlock(&p->lock); 00797 00798 res = ast_streamfile(chan, beep, chan->language); 00799 if (option_debug > 2) 00800 ast_log(LOG_DEBUG, "Played beep, result '%d'\n", res); 00801 if (!res) { 00802 res = ast_waitstream(chan, ""); 00803 if (option_debug > 2) 00804 ast_log(LOG_DEBUG, "Waited for stream, result '%d'\n", res); 00805 } 00806 00807 ast_mutex_lock(&p->lock); 00808 if (!p->chan) { 00809 /* chan went away while we were streaming, this shouldn't be possible */ 00810 res = -1; 00811 } 00812 00813 if (!res) { 00814 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00815 if (option_debug > 2) 00816 ast_log(LOG_DEBUG, "Set read format, result '%d'\n", res); 00817 if (res) 00818 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00819 } else { 00820 /* Agent hung-up */ 00821 p->chan = NULL; 00822 p->inherited_devicestate = -1; 00823 ast_device_state_changed("Agent/%s", p->agent); 00824 } 00825 00826 if (!res) { 00827 res = ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00828 if (option_debug > 2) 00829 ast_log(LOG_DEBUG, "Set write format, result '%d'\n", res); 00830 if (res) 00831 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00832 } 00833 if(!res) { 00834 /* Call is immediately up, or might need ack */ 00835 if (p->ackcall > 1) 00836 newstate = AST_STATE_RINGING; 00837 else { 00838 newstate = AST_STATE_UP; 00839 if (recordagentcalls) 00840 agent_start_monitoring(ast, 0); 00841 p->acknowledged = 1; 00842 } 00843 res = 0; 00844 } 00845 CLEANUP(ast, p); 00846 ast_mutex_unlock(&p->lock); 00847 if (newstate) 00848 ast_setstate(ast, newstate); 00849 return res; 00850 }
static int agent_cleanup | ( | struct agent_pvt * | p | ) | [static] |
Deletes an agent after doing some clean up. Further documentation: How safe is this function ? What state should the agent be to be cleaned.
p | Agent to be deleted. |
Definition at line 430 of file chan_agent.c.
References agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_channel_free(), ast_cond_destroy(), ast_cond_signal(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, agent_pvt::dead, free, agent_pvt::lock, agent_pvt::login_wait_cond, agent_pvt::owner, and ast_channel::tech_pvt.
Referenced by check_availability().
00431 { 00432 struct ast_channel *chan = NULL; 00433 ast_mutex_lock(&p->lock); 00434 chan = p->owner; 00435 p->owner = NULL; 00436 chan->tech_pvt = NULL; 00437 /* Release ownership of the agent to other threads (presumably running the login app). */ 00438 p->app_sleep_cond = 1; 00439 p->app_lock_flag = 0; 00440 ast_cond_signal(&p->app_complete_cond); 00441 if (chan) 00442 ast_channel_free(chan); 00443 if (p->dead) { 00444 ast_mutex_unlock(&p->lock); 00445 ast_mutex_destroy(&p->lock); 00446 ast_cond_destroy(&p->app_complete_cond); 00447 ast_cond_destroy(&p->login_wait_cond); 00448 free(p); 00449 } else { 00450 ast_mutex_unlock(&p->lock); 00451 } 00452 return 0; 00453 }
static int agent_cont_sleep | ( | void * | data | ) | [static] |
Definition at line 1016 of file chan_agent.c.
References agent_pvt::app_sleep_cond, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_tvdiff_ms(), ast_tvnow(), agent_pvt::lastdisc, agent_pvt::lock, LOG_DEBUG, and option_debug.
Referenced by __login_exec().
01017 { 01018 struct agent_pvt *p; 01019 int res; 01020 01021 p = (struct agent_pvt *)data; 01022 01023 ast_mutex_lock(&p->lock); 01024 res = p->app_sleep_cond; 01025 if (p->lastdisc.tv_sec) { 01026 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) 01027 res = 1; 01028 } 01029 ast_mutex_unlock(&p->lock); 01030 01031 if(option_debug > 4 && !res ) 01032 ast_log(LOG_DEBUG, "agent_cont_sleep() returning %d\n", res ); 01033 01034 return res; 01035 }
static int agent_devicestate | ( | void * | data | ) | [static] |
Part of PBX channel interface.
Definition at line 2716 of file chan_agent.c.
References agent_pvt::agent, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, agent_pvt::group, agent_pvt::inherited_devicestate, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::owner, agent_pvt::pending, and s.
02717 { 02718 struct agent_pvt *p; 02719 char *s; 02720 ast_group_t groupmatch; 02721 int groupoff; 02722 int waitforagent=0; 02723 int res = AST_DEVICE_INVALID; 02724 02725 s = data; 02726 if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) 02727 groupmatch = (1 << groupoff); 02728 else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 02729 groupmatch = (1 << groupoff); 02730 waitforagent = 1; 02731 } else 02732 groupmatch = 0; 02733 02734 /* Check actual logged in agents first */ 02735 AST_LIST_LOCK(&agents); 02736 AST_LIST_TRAVERSE(&agents, p, list) { 02737 ast_mutex_lock(&p->lock); 02738 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 02739 if (p->owner) { 02740 if (res != AST_DEVICE_INUSE) 02741 res = AST_DEVICE_BUSY; 02742 } else if (p->inherited_devicestate > -1) { 02743 res = p->inherited_devicestate; 02744 } else { 02745 if (res == AST_DEVICE_BUSY) 02746 res = AST_DEVICE_INUSE; 02747 if (p->chan || !ast_strlen_zero(p->loginchan)) { 02748 if (res == AST_DEVICE_INVALID) 02749 res = AST_DEVICE_UNKNOWN; 02750 } else if (res == AST_DEVICE_INVALID) 02751 res = AST_DEVICE_UNAVAILABLE; 02752 } 02753 if (!strcmp(data, p->agent)) { 02754 ast_mutex_unlock(&p->lock); 02755 break; 02756 } 02757 } 02758 ast_mutex_unlock(&p->lock); 02759 } 02760 AST_LIST_UNLOCK(&agents); 02761 return res; 02762 }
static int agent_devicestate_cb | ( | const char * | dev, | |
int | state, | |||
void * | data | |||
) | [static] |
Definition at line 291 of file chan_agent.c.
References agent_pvt::agent, AST_CHANNEL_NAME, ast_copy_string(), ast_device_state_changed(), AST_LIST_TRAVERSE, AST_LIST_TRYLOCK, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, agent_pvt::inherited_devicestate, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, and ast_channel::name.
Referenced by load_module(), and unload_module().
00292 { 00293 int res, i; 00294 struct agent_pvt *p; 00295 char basename[AST_CHANNEL_NAME], *tmp; 00296 00297 /* Skip Agent status */ 00298 if (!strncasecmp(dev, "Agent/", 6)) { 00299 return 0; 00300 } 00301 00302 /* Try to be safe, but don't deadlock */ 00303 for (i = 0; i < 10; i++) { 00304 if ((res = AST_LIST_TRYLOCK(&agents)) == 0) { 00305 break; 00306 } 00307 } 00308 if (res) { 00309 return -1; 00310 } 00311 00312 AST_LIST_TRAVERSE(&agents, p, list) { 00313 ast_mutex_lock(&p->lock); 00314 if (p->chan && !ast_strlen_zero(p->loginchan)) { 00315 ast_copy_string(basename, p->chan->name, sizeof(basename)); 00316 if ((tmp = strrchr(basename, '-'))) { 00317 *tmp = '\0'; 00318 } 00319 if (strcasecmp(p->chan->name, dev) == 0 || strcasecmp(basename, dev) == 0) { 00320 p->inherited_devicestate = state; 00321 ast_device_state_changed("Agent/%s", p->agent); 00322 } 00323 } 00324 ast_mutex_unlock(&p->lock); 00325 } 00326 AST_LIST_UNLOCK(&agents); 00327 return 0; 00328 }
static int agent_digit_begin | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 732 of file chan_agent.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_senddigit_begin(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.
00733 { 00734 struct agent_pvt *p = ast->tech_pvt; 00735 ast_mutex_lock(&p->lock); 00736 if (p->chan) { 00737 ast_senddigit_begin(p->chan, digit); 00738 } 00739 ast_mutex_unlock(&p->lock); 00740 return 0; 00741 }
static int agent_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 743 of file chan_agent.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_senddigit_end(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.
00744 { 00745 struct agent_pvt *p = ast->tech_pvt; 00746 ast_mutex_lock(&p->lock); 00747 if (p->chan) { 00748 ast_senddigit_end(p->chan, digit, duration); 00749 } 00750 ast_mutex_unlock(&p->lock); 00751 return 0; 00752 }
static int agent_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 694 of file chan_agent.c.
References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::lock, LOG_WARNING, agent_pvt::owner, and ast_channel::tech_pvt.
00695 { 00696 struct agent_pvt *p = newchan->tech_pvt; 00697 ast_mutex_lock(&p->lock); 00698 if (p->owner != oldchan) { 00699 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 00700 ast_mutex_unlock(&p->lock); 00701 return -1; 00702 } 00703 p->owner = newchan; 00704 ast_mutex_unlock(&p->lock); 00705 return 0; 00706 }
struct ast_channel * agent_get_base_channel | ( | struct ast_channel * | chan | ) | [static] |
return the channel or base channel if one exists. This function assumes the channel it is called on is already locked
Definition at line 866 of file chan_agent.c.
References ast_log(), agent_pvt::chan, LOG_ERROR, and ast_channel::tech_pvt.
00867 { 00868 struct agent_pvt *p = NULL; 00869 struct ast_channel *base = chan; 00870 00871 /* chan is locked by the calling function */ 00872 if (!chan || !chan->tech_pvt) { 00873 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)chan->tech_pvt:(long)NULL); 00874 return NULL; 00875 } 00876 p = chan->tech_pvt; 00877 if (p->chan) 00878 base = p->chan; 00879 return base; 00880 }
static int agent_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 899 of file chan_agent.c.
References ast_channel::_bridge, ast_channel::_state, agent_pvt::abouttograb, agent_pvt::acknowledged, agent_pvt::agent, agent_logoff_maintenance(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_channel_lock, ast_channel_unlock, ast_cond_destroy(), ast_cond_signal(), AST_CONTROL_HOLD, ast_device_state_changed(), ast_hangup(), ast_indicate_data(), AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_samp2tv(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_state2str(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_tv(), ast_tvadd(), ast_tvnow(), agent_pvt::autologoff, agent_pvt::chan, agent_pvt::dead, agent_pvt::deferlogoff, dump_agents(), free, agent_pvt::inherited_devicestate, agent_pvt::lastdisc, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::login_wait_cond, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, agent_pvt::moh, agent_pvt::name, option_debug, agent_pvt::owner, pbx_builtin_getvar_helper(), agent_pvt::pending, S_OR, agent_pvt::start, ast_channel::tech_pvt, ast_channel::uniqueid, and agent_pvt::wrapuptime.
Referenced by agent_request().
00900 { 00901 struct agent_pvt *p = ast->tech_pvt; 00902 int howlong = 0; 00903 const char *status; 00904 ast_mutex_lock(&p->lock); 00905 p->owner = NULL; 00906 ast->tech_pvt = NULL; 00907 p->app_sleep_cond = 1; 00908 p->acknowledged = 0; 00909 00910 /* Release ownership of the agent to other threads (presumably running the login app). */ 00911 if (ast_strlen_zero(p->loginchan)) { 00912 p->app_lock_flag = 0; 00913 ast_cond_signal(&p->app_complete_cond); 00914 } 00915 00916 /* if they really are hung up then set start to 0 so the test 00917 * later if we're called on an already downed channel 00918 * doesn't cause an agent to be logged out like when 00919 * agent_request() is followed immediately by agent_hangup() 00920 * as in apps/app_chanisavail.c:chanavail_exec() 00921 */ 00922 00923 if (option_debug) 00924 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state)); 00925 if (p->start && (ast->_state != AST_STATE_UP)) { 00926 howlong = time(NULL) - p->start; 00927 p->start = 0; 00928 } else if (ast->_state == AST_STATE_RESERVED) 00929 howlong = 0; 00930 else 00931 p->start = 0; 00932 if (p->chan) { 00933 p->chan->_bridge = NULL; 00934 /* If they're dead, go ahead and hang up on the agent now */ 00935 if (!ast_strlen_zero(p->loginchan)) { 00936 /* Store last disconnect time */ 00937 if (p->wrapuptime) 00938 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00939 else 00940 p->lastdisc = ast_tv(0,0); 00941 if (p->chan) { 00942 status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); 00943 if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { 00944 long logintime = time(NULL) - p->loginstart; 00945 p->loginstart = 0; 00946 ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name); 00947 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail"); 00948 } 00949 /* Recognize the hangup and pass it along immediately */ 00950 ast_hangup(p->chan); 00951 p->chan = NULL; 00952 p->inherited_devicestate = -1; 00953 ast_device_state_changed("Agent/%s", p->agent); 00954 } 00955 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff); 00956 if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) { 00957 long logintime = time(NULL) - p->loginstart; 00958 p->loginstart = 0; 00959 if (!p->deferlogoff) 00960 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00961 p->deferlogoff = 0; 00962 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff"); 00963 if (persistent_agents) 00964 dump_agents(); 00965 } 00966 } else if (p->dead) { 00967 ast_channel_lock(p->chan); 00968 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 00969 ast_channel_unlock(p->chan); 00970 } else if (p->loginstart) { 00971 ast_channel_lock(p->chan); 00972 ast_indicate_data(p->chan, AST_CONTROL_HOLD, 00973 S_OR(p->moh, NULL), 00974 !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0); 00975 ast_channel_unlock(p->chan); 00976 } 00977 } 00978 ast_mutex_unlock(&p->lock); 00979 00980 /* Only register a device state change if the agent is still logged in */ 00981 if (!p->loginstart) { 00982 p->loginchan[0] = '\0'; 00983 p->logincallerid[0] = '\0'; 00984 if (persistent_agents) 00985 dump_agents(); 00986 } else { 00987 ast_device_state_changed("Agent/%s", p->agent); 00988 } 00989 00990 if (p->pending) { 00991 AST_LIST_LOCK(&agents); 00992 AST_LIST_REMOVE(&agents, p, list); 00993 AST_LIST_UNLOCK(&agents); 00994 } 00995 if (p->abouttograb) { 00996 /* Let the "about to grab" thread know this isn't valid anymore, and let it 00997 kill it later */ 00998 p->abouttograb = 0; 00999 } else if (p->dead) { 01000 ast_mutex_destroy(&p->lock); 01001 ast_cond_destroy(&p->app_complete_cond); 01002 ast_cond_destroy(&p->login_wait_cond); 01003 free(p); 01004 } else { 01005 if (p->chan) { 01006 /* Not dead -- check availability now */ 01007 ast_mutex_lock(&p->lock); 01008 /* Store last disconnect time */ 01009 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 01010 ast_mutex_unlock(&p->lock); 01011 } 01012 } 01013 return 0; 01014 }
static int agent_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 708 of file chan_agent.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, ast_channel_tech::indicate, agent_pvt::lock, LOG_ERROR, ast_channel::tech, and ast_channel::tech_pvt.
00709 { 00710 struct agent_pvt *p = ast->tech_pvt; 00711 int res = -1; 00712 ast_mutex_lock(&p->lock); 00713 if (p->chan && !ast_check_hangup(p->chan)) { 00714 while (ast_channel_trylock(p->chan)) { 00715 int res; 00716 if ((res = ast_channel_unlock(ast))) { 00717 ast_log(LOG_ERROR, "chan_agent bug! Channel was not locked upon entry to agent_indicate: %s\n", strerror(res)); 00718 ast_mutex_unlock(&p->lock); 00719 return -1; 00720 } 00721 usleep(1); 00722 ast_channel_lock(ast); 00723 } 00724 res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition, data, datalen) : -1; 00725 ast_channel_unlock(p->chan); 00726 } else 00727 res = 0; 00728 ast_mutex_unlock(&p->lock); 00729 return res; 00730 }
static int agent_logoff | ( | const char * | agent, | |
int | soft | |||
) | [static] |
Definition at line 1705 of file chan_agent.c.
References agent_pvt::agent, agent_logoff_maintenance(), ast_channel_trylock, ast_channel_unlock, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agent_pvt::chan, DEADLOCK_AVOIDANCE, agent_pvt::deferlogoff, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, and agent_pvt::owner.
Referenced by action_agent_logoff(), and agent_logoff_cmd().
01706 { 01707 struct agent_pvt *p; 01708 long logintime; 01709 int ret = -1; /* Return -1 if no agent if found */ 01710 01711 AST_LIST_LOCK(&agents); 01712 AST_LIST_TRAVERSE(&agents, p, list) { 01713 if (!strcasecmp(p->agent, agent)) { 01714 ret = 0; 01715 if (p->owner || p->chan) { 01716 if (!soft) { 01717 ast_mutex_lock(&p->lock); 01718 01719 while (p->owner && ast_channel_trylock(p->owner)) { 01720 DEADLOCK_AVOIDANCE(&p->lock); 01721 } 01722 if (p->owner) { 01723 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 01724 ast_channel_unlock(p->owner); 01725 } 01726 01727 while (p->chan && ast_channel_trylock(p->chan)) { 01728 DEADLOCK_AVOIDANCE(&p->lock); 01729 } 01730 if (p->chan) { 01731 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01732 ast_channel_unlock(p->chan); 01733 } 01734 01735 ast_mutex_unlock(&p->lock); 01736 } else 01737 p->deferlogoff = 1; 01738 } else { 01739 logintime = time(NULL) - p->loginstart; 01740 p->loginstart = 0; 01741 agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff"); 01742 } 01743 break; 01744 } 01745 } 01746 AST_LIST_UNLOCK(&agents); 01747 01748 return ret; 01749 }
static int agent_logoff_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1751 of file chan_agent.c.
References agent_pvt::agent, agent_logoff(), ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01752 { 01753 int ret; 01754 char *agent; 01755 01756 if (argc < 3 || argc > 4) 01757 return RESULT_SHOWUSAGE; 01758 if (argc == 4 && strcasecmp(argv[3], "soft")) 01759 return RESULT_SHOWUSAGE; 01760 01761 agent = argv[2] + 6; 01762 ret = agent_logoff(agent, argc == 4); 01763 if (ret == 0) 01764 ast_cli(fd, "Logging out %s\n", agent); 01765 01766 return RESULT_SUCCESS; 01767 }
static void agent_logoff_maintenance | ( | struct agent_pvt * | p, | |
char * | loginchan, | |||
long | logintime, | |||
const char * | uniqueid, | |||
char * | logcommand | |||
) | [static] |
Definition at line 1665 of file chan_agent.c.
References agent_pvt::agent, ast_device_state_changed(), AST_MAX_AGENT, ast_queue_log(), ast_strdupa, ast_strlen_zero(), dump_agents(), EVENT_FLAG_AGENT, agent_pvt::inherited_devicestate, agent_pvt::logincallerid, agent_pvt::loginchan, manager_event(), and set_agentbycallerid().
Referenced by __login_exec(), agent_hangup(), agent_logoff(), and agent_read().
01666 { 01667 char *tmp = NULL; 01668 char agent[AST_MAX_AGENT]; 01669 01670 if (!ast_strlen_zero(logcommand)) 01671 tmp = logcommand; 01672 else 01673 tmp = ast_strdupa(""); 01674 01675 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 01676 01677 if (!ast_strlen_zero(uniqueid)) { 01678 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01679 "Agent: %s\r\n" 01680 "Reason: %s\r\n" 01681 "Loginchan: %s\r\n" 01682 "Logintime: %ld\r\n" 01683 "Uniqueid: %s\r\n", 01684 p->agent, tmp, loginchan, logintime, uniqueid); 01685 } else { 01686 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01687 "Agent: %s\r\n" 01688 "Reason: %s\r\n" 01689 "Loginchan: %s\r\n" 01690 "Logintime: %ld\r\n", 01691 p->agent, tmp, loginchan, logintime); 01692 } 01693 01694 ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp); 01695 set_agentbycallerid(p->logincallerid, NULL); 01696 p->loginchan[0] ='\0'; 01697 p->logincallerid[0] = '\0'; 01698 p->inherited_devicestate = -1; 01699 ast_device_state_changed("Agent/%s", p->agent); 01700 if (persistent_agents) 01701 dump_agents(); 01702 01703 }
static struct ast_channel* agent_new | ( | struct agent_pvt * | p, | |
int | state | |||
) | [static] |
Create new agent channel.
Definition at line 1096 of file chan_agent.c.
References agent_pvt::agent, agent_tech, ast_atomic_fetchadd_int(), ast_channel_alloc(), ast_copy_string(), AST_FORMAT_SLINEAR, ast_log(), ast_random(), ast_string_field_set, ast_update_use_count(), agent_pvt::chan, ast_channel::context, ast_channel::exten, ast_channel::language, language, LOG_WARNING, ast_channel::nativeformats, agent_pvt::owner, agent_pvt::pending, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.
Referenced by agent_request(), and check_availability().
01097 { 01098 struct ast_channel *tmp; 01099 #if 0 01100 if (!p->chan) { 01101 ast_log(LOG_WARNING, "No channel? :(\n"); 01102 return NULL; 01103 } 01104 #endif 01105 if (p->pending) 01106 tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/P%s-%d", p->agent, (int) ast_random() & 0xffff); 01107 else 01108 tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/%s", p->agent); 01109 if (!tmp) { 01110 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); 01111 return NULL; 01112 } 01113 01114 tmp->tech = &agent_tech; 01115 if (p->chan) { 01116 tmp->nativeformats = p->chan->nativeformats; 01117 tmp->writeformat = p->chan->writeformat; 01118 tmp->rawwriteformat = p->chan->writeformat; 01119 tmp->readformat = p->chan->readformat; 01120 tmp->rawreadformat = p->chan->readformat; 01121 ast_string_field_set(tmp, language, p->chan->language); 01122 ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); 01123 ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); 01124 /* XXX Is this really all we copy form the originating channel?? */ 01125 } else { 01126 tmp->nativeformats = AST_FORMAT_SLINEAR; 01127 tmp->writeformat = AST_FORMAT_SLINEAR; 01128 tmp->rawwriteformat = AST_FORMAT_SLINEAR; 01129 tmp->readformat = AST_FORMAT_SLINEAR; 01130 tmp->rawreadformat = AST_FORMAT_SLINEAR; 01131 } 01132 /* Safe, agentlock already held */ 01133 tmp->tech_pvt = p; 01134 p->owner = tmp; 01135 /* XXX: this needs fixing */ 01136 #if 0 01137 ast_atomic_fetchadd_int(&__mod_desc->usecnt, +1); 01138 #endif 01139 ast_update_use_count(); 01140 tmp->priority = 1; 01141 return tmp; 01142 }
static struct ast_frame * agent_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 496 of file chan_agent.c.
References ast_channel::_bridge, ast_channel::_state, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_logoff_maintenance(), agent_start_monitoring(), AST_AGENT_FD, ast_channel_trylock, ast_channel_unlock, AST_CONTROL_ANSWER, ast_copy_flags, ast_device_state_changed(), AST_FLAG_EXCEPTION, AST_FRAME_CONTROL, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_read(), ast_samp2tv(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, AST_STATE_UP, ast_strlen_zero(), AST_TIMING_FD, ast_tvadd(), ast_tvnow(), ast_verbose(), agent_pvt::autologoff, agent_pvt::chan, CHECK_FORMATS, CLEANUP, DEADLOCK_AVOIDANCE, f, ast_channel::fdno, agent_pvt::inherited_devicestate, agent_pvt::lastdisc, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::loginchan, agent_pvt::loginstart, agent_pvt::name, ast_channel::name, option_verbose, agent_pvt::owner, pbx_builtin_getvar_helper(), agent_pvt::start, ast_channel::tech, ast_channel::tech_pvt, ast_channel_tech::type, ast_channel::uniqueid, VERBOSE_PREFIX_3, and agent_pvt::wrapuptime.
00497 { 00498 struct agent_pvt *p = ast->tech_pvt; 00499 struct ast_frame *f = NULL; 00500 static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00501 const char *status; 00502 int cur_time = time(NULL); 00503 ast_mutex_lock(&p->lock); 00504 CHECK_FORMATS(ast, p); 00505 if (!p->start) { 00506 p->start = cur_time; 00507 } 00508 if (p->chan) { 00509 ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION); 00510 p->chan->fdno = (ast->fdno == AST_AGENT_FD) ? AST_TIMING_FD : ast->fdno; 00511 f = ast_read(p->chan); 00512 } else 00513 f = &ast_null_frame; 00514 if (!f) { 00515 /* If there's a channel, hang it up (if it's on a callback) make it NULL */ 00516 if (p->chan) { 00517 p->chan->_bridge = NULL; 00518 /* Note that we don't hangup if it's not a callback because Asterisk will do it 00519 for us when the PBX instance that called login finishes */ 00520 if (!ast_strlen_zero(p->loginchan)) { 00521 if (p->chan) 00522 ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name); 00523 if (p->owner->_state != AST_STATE_UP) { 00524 int howlong = cur_time - p->start; 00525 if (p->autologoff && howlong >= p->autologoff) { 00526 p->loginstart = 0; 00527 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00528 agent_logoff_maintenance(p, p->loginchan, (cur_time = p->loginstart), ast->uniqueid, "Autologoff"); 00529 } 00530 } 00531 status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); 00532 if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { 00533 long logintime = cur_time - p->loginstart; 00534 p->loginstart = 0; 00535 ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name); 00536 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail"); 00537 } 00538 ast_hangup(p->chan); 00539 if (p->wrapuptime && p->acknowledged) 00540 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00541 } 00542 p->chan = NULL; 00543 p->inherited_devicestate = -1; 00544 ast_device_state_changed("Agent/%s", p->agent); 00545 p->acknowledged = 0; 00546 } 00547 } else { 00548 /* if acknowledgement is not required, and the channel is up, we may have missed 00549 an AST_CONTROL_ANSWER (if there was one), so mark the call acknowledged anyway */ 00550 if (!p->ackcall && !p->acknowledged && p->chan && (p->chan->_state == AST_STATE_UP)) { 00551 p->acknowledged = 1; 00552 } 00553 if (!p->acknowledged) { 00554 int howlong = cur_time - p->start; 00555 if (p->autologoff && (howlong >= p->autologoff)) { 00556 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00557 agent_logoff_maintenance(p, p->loginchan, (cur_time - p->loginstart), ast->uniqueid, "Autologoff"); 00558 if (p->owner || p->chan) { 00559 while (p->owner && ast_channel_trylock(p->owner)) { 00560 DEADLOCK_AVOIDANCE(&p->lock); 00561 } 00562 if (p->owner) { 00563 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 00564 ast_channel_unlock(p->owner); 00565 } 00566 00567 while (p->chan && ast_channel_trylock(p->chan)) { 00568 DEADLOCK_AVOIDANCE(&p->lock); 00569 } 00570 if (p->chan) { 00571 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 00572 ast_channel_unlock(p->chan); 00573 } 00574 } else { 00575 long logintime; 00576 logintime = time(NULL) - p->loginstart; 00577 p->loginstart = 0; 00578 agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff"); 00579 } 00580 } 00581 } 00582 switch (f->frametype) { 00583 case AST_FRAME_CONTROL: 00584 if (f->subclass == AST_CONTROL_ANSWER) { 00585 if (p->ackcall) { 00586 if (option_verbose > 2) 00587 ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name); 00588 /* Don't pass answer along */ 00589 ast_frfree(f); 00590 f = &ast_null_frame; 00591 } else { 00592 p->acknowledged = 1; 00593 /* Use the builtin answer frame for the 00594 recording start check below. */ 00595 ast_frfree(f); 00596 f = &answer_frame; 00597 } 00598 } 00599 break; 00600 case AST_FRAME_DTMF_BEGIN: 00601 /*ignore DTMF begin's as it can cause issues with queue announce files*/ 00602 if((!p->acknowledged && f->subclass == '#') || (f->subclass == '*' && endcall)){ 00603 ast_frfree(f); 00604 f = &ast_null_frame; 00605 } 00606 break; 00607 case AST_FRAME_DTMF_END: 00608 if (!p->acknowledged && (f->subclass == '#')) { 00609 if (option_verbose > 2) 00610 ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); 00611 p->acknowledged = 1; 00612 ast_frfree(f); 00613 f = &answer_frame; 00614 } else if (f->subclass == '*' && endcall) { 00615 /* terminates call */ 00616 ast_frfree(f); 00617 f = NULL; 00618 } 00619 break; 00620 case AST_FRAME_VOICE: 00621 case AST_FRAME_VIDEO: 00622 /* don't pass voice or video until the call is acknowledged */ 00623 if (!p->acknowledged) { 00624 ast_frfree(f); 00625 f = &ast_null_frame; 00626 } 00627 default: 00628 /* pass everything else on through */ 00629 break; 00630 } 00631 } 00632 00633 CLEANUP(ast,p); 00634 if (p->chan && !p->chan->_bridge) { 00635 if (strcasecmp(p->chan->tech->type, "Local")) { 00636 p->chan->_bridge = ast; 00637 if (p->chan) 00638 ast_log(LOG_DEBUG, "Bridge on '%s' being set to '%s' (3)\n", p->chan->name, p->chan->_bridge->name); 00639 } 00640 } 00641 ast_mutex_unlock(&p->lock); 00642 if (recordagentcalls && f == &answer_frame) 00643 agent_start_monitoring(ast,0); 00644 return f; 00645 }
static struct ast_channel * agent_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Part of the Asterisk PBX interface.
Definition at line 1436 of file chan_agent.c.
References add_agent(), agent_pvt::agent, agent_hangup(), agent_new(), agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_cond_signal(), ast_cond_wait(), AST_CONTROL_UNHOLD, ast_indicate(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_request(), AST_STATE_DOWN, ast_strlen_zero(), ast_tv(), ast_tvnow(), agent_pvt::chan, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, agent_pvt::login_wait_cond, agent_pvt::loginchan, option_debug, agent_pvt::owner, agent_pvt::pending, and s.
01437 { 01438 struct agent_pvt *p; 01439 struct ast_channel *chan = NULL; 01440 char *s; 01441 ast_group_t groupmatch; 01442 int groupoff; 01443 int waitforagent=0; 01444 int hasagent = 0; 01445 struct timeval tv; 01446 01447 s = data; 01448 if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 01449 groupmatch = (1 << groupoff); 01450 } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 01451 groupmatch = (1 << groupoff); 01452 waitforagent = 1; 01453 } else 01454 groupmatch = 0; 01455 01456 /* Check actual logged in agents first */ 01457 AST_LIST_LOCK(&agents); 01458 AST_LIST_TRAVERSE(&agents, p, list) { 01459 ast_mutex_lock(&p->lock); 01460 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) && 01461 ast_strlen_zero(p->loginchan)) { 01462 if (p->chan) 01463 hasagent++; 01464 tv = ast_tvnow(); 01465 if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) { 01466 p->lastdisc = ast_tv(0, 0); 01467 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01468 if (!p->owner && p->chan) { 01469 /* Fixed agent */ 01470 chan = agent_new(p, AST_STATE_DOWN); 01471 } 01472 if (chan) { 01473 ast_mutex_unlock(&p->lock); 01474 break; 01475 } 01476 } 01477 } 01478 ast_mutex_unlock(&p->lock); 01479 } 01480 if (!p) { 01481 AST_LIST_TRAVERSE(&agents, p, list) { 01482 ast_mutex_lock(&p->lock); 01483 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 01484 if (p->chan || !ast_strlen_zero(p->loginchan)) 01485 hasagent++; 01486 tv = ast_tvnow(); 01487 #if 0 01488 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec); 01489 #endif 01490 if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) { 01491 p->lastdisc = ast_tv(0, 0); 01492 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01493 if (!p->owner && p->chan) { 01494 /* Could still get a fixed agent */ 01495 chan = agent_new(p, AST_STATE_DOWN); 01496 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { 01497 /* Adjustable agent */ 01498 p->chan = ast_request("Local", format, p->loginchan, cause); 01499 if (p->chan) 01500 chan = agent_new(p, AST_STATE_DOWN); 01501 } 01502 if (chan) { 01503 ast_mutex_unlock(&p->lock); 01504 break; 01505 } 01506 } 01507 } 01508 ast_mutex_unlock(&p->lock); 01509 } 01510 } 01511 01512 if (!chan && waitforagent) { 01513 /* No agent available -- but we're requesting to wait for one. 01514 Allocate a place holder */ 01515 if (hasagent) { 01516 if (option_debug) 01517 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s); 01518 p = add_agent(data, 1); 01519 p->group = groupmatch; 01520 chan = agent_new(p, AST_STATE_DOWN); 01521 if (!chan) 01522 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); 01523 } else 01524 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); 01525 } 01526 *cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED; 01527 AST_LIST_UNLOCK(&agents); 01528 01529 if (chan) { 01530 ast_mutex_lock(&p->lock); 01531 if (p->pending) { 01532 ast_mutex_unlock(&p->lock); 01533 return chan; 01534 } 01535 01536 if (!p->chan) { 01537 ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n"); 01538 *cause = AST_CAUSE_UNREGISTERED; 01539 ast_mutex_unlock(&p->lock); 01540 agent_hangup(chan); 01541 return NULL; 01542 } 01543 01544 /* when not in callback mode we need to take control of the channel 01545 * from the login app thread */ 01546 if(ast_strlen_zero(p->loginchan)) { 01547 p->app_sleep_cond = 0; 01548 p->app_lock_flag = 1; 01549 01550 ast_queue_frame(p->chan, &ast_null_frame); 01551 ast_cond_wait(&p->login_wait_cond, &p->lock); 01552 01553 if (!p->chan) { 01554 ast_log(LOG_DEBUG, "Agent disconnected while we were connecting the call\n"); 01555 p->app_sleep_cond = 1; 01556 p->app_lock_flag = 0; 01557 ast_cond_signal(&p->app_complete_cond); 01558 ast_mutex_unlock(&p->lock); 01559 *cause = AST_CAUSE_UNREGISTERED; 01560 agent_hangup(chan); 01561 return NULL; 01562 } 01563 01564 ast_indicate(p->chan, AST_CONTROL_UNHOLD); 01565 } 01566 ast_mutex_unlock(&p->lock); 01567 } 01568 01569 return chan; 01570 }
static int agent_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 647 of file chan_agent.c.
References ast_channel_sendhtml(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.
00648 { 00649 struct agent_pvt *p = ast->tech_pvt; 00650 int res = -1; 00651 ast_mutex_lock(&p->lock); 00652 if (p->chan) 00653 res = ast_channel_sendhtml(p->chan, subclass, data, datalen); 00654 ast_mutex_unlock(&p->lock); 00655 return res; 00656 }
static int agent_sendtext | ( | struct ast_channel * | ast, | |
const char * | text | |||
) | [static] |
Definition at line 658 of file chan_agent.c.
References ast_mutex_lock(), ast_mutex_unlock(), ast_sendtext(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.
00659 { 00660 struct agent_pvt *p = ast->tech_pvt; 00661 int res = -1; 00662 ast_mutex_lock(&p->lock); 00663 if (p->chan) 00664 res = ast_sendtext(p->chan, text); 00665 ast_mutex_unlock(&p->lock); 00666 return res; 00667 }
int agent_set_base_channel | ( | struct ast_channel * | chan, | |
struct ast_channel * | base | |||
) | [static] |
Definition at line 882 of file chan_agent.c.
References ast_log(), agent_pvt::chan, LOG_ERROR, ast_channel::name, and ast_channel::tech_pvt.
00883 { 00884 struct agent_pvt *p = NULL; 00885 00886 if (!chan || !base) { 00887 ast_log(LOG_ERROR, "whoa, you need a channel (0x%ld) and a base channel (0x%ld) for setting.\n", (long)chan, (long)base); 00888 return -1; 00889 } 00890 p = chan->tech_pvt; 00891 if (!p) { 00892 ast_log(LOG_ERROR, "whoa, channel %s is missing his tech_pvt structure!!.\n", chan->name); 00893 return -1; 00894 } 00895 p->chan = base; 00896 return 0; 00897 }
static int agent_start_monitoring | ( | struct ast_channel * | ast, | |
int | needlock | |||
) | [static] |
Definition at line 491 of file chan_agent.c.
References __agent_start_monitoring(), and ast_channel::tech_pvt.
Referenced by agent_call(), and agent_read().
00492 { 00493 return __agent_start_monitoring(ast, ast->tech_pvt, needlock); 00494 }
static int agent_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 669 of file chan_agent.c.
References AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_write(), agent_pvt::chan, CHECK_FORMATS, CLEANUP, f, agent_pvt::lock, LOG_DEBUG, ast_channel::name, ast_channel::tech_pvt, and ast_channel::writeformat.
00670 { 00671 struct agent_pvt *p = ast->tech_pvt; 00672 int res = -1; 00673 CHECK_FORMATS(ast, p); 00674 ast_mutex_lock(&p->lock); 00675 if (!p->chan) 00676 res = 0; 00677 else { 00678 if ((f->frametype != AST_FRAME_VOICE) || 00679 (f->frametype != AST_FRAME_VIDEO) || 00680 (f->subclass == p->chan->writeformat)) { 00681 res = ast_write(p->chan, f); 00682 } else { 00683 ast_log(LOG_DEBUG, "Dropping one incompatible %s frame on '%s' to '%s'\n", 00684 f->frametype == AST_FRAME_VOICE ? "audio" : "video", 00685 ast->name, p->chan->name); 00686 res = 0; 00687 } 00688 } 00689 CLEANUP(ast, p); 00690 ast_mutex_unlock(&p->lock); 00691 return res; 00692 }
static int agentmonitoroutgoing_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Called by the AgentMonitorOutgoing application (from the dial plan).
chan | ||
data |
Definition at line 2580 of file chan_agent.c.
References __agent_start_monitoring(), agent_pvt::agent, ast_copy_string(), ast_exists_extension(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), AST_MAX_AGENT, AST_MAX_BUF, ast_verbose(), ast_channel::cdr, agent_pvt::chan, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, GETAGENTBYCALLERID, agent_pvt::list, LOG_WARNING, option_verbose, pbx_builtin_getvar_helper(), and VERBOSE_PREFIX_3.
Referenced by load_module().
02581 { 02582 int exitifnoagentid = 0; 02583 int nowarnings = 0; 02584 int changeoutgoing = 0; 02585 int res = 0; 02586 char agent[AST_MAX_AGENT]; 02587 02588 if (data) { 02589 if (strchr(data, 'd')) 02590 exitifnoagentid = 1; 02591 if (strchr(data, 'n')) 02592 nowarnings = 1; 02593 if (strchr(data, 'c')) 02594 changeoutgoing = 1; 02595 } 02596 if (chan->cid.cid_num) { 02597 const char *tmp; 02598 char agentvar[AST_MAX_BUF]; 02599 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num); 02600 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) { 02601 struct agent_pvt *p; 02602 ast_copy_string(agent, tmp, sizeof(agent)); 02603 AST_LIST_LOCK(&agents); 02604 AST_LIST_TRAVERSE(&agents, p, list) { 02605 if (!strcasecmp(p->agent, tmp)) { 02606 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02607 __agent_start_monitoring(chan, p, 1); 02608 break; 02609 } 02610 } 02611 AST_LIST_UNLOCK(&agents); 02612 02613 } else { 02614 res = -1; 02615 if (!nowarnings) 02616 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); 02617 } 02618 } else { 02619 res = -1; 02620 if (!nowarnings) 02621 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"); 02622 } 02623 /* check if there is n + 101 priority */ 02624 /*! \todo XXX Needs to check option priorityjump etc etc */ 02625 if (res) { 02626 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) { 02627 chan->priority+=100; 02628 if (option_verbose > 2) 02629 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority); 02630 } else if (exitifnoagentid) 02631 return res; 02632 } 02633 return 0; 02634 }
static int agents_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Show agents in cli.
< Number of agents configured
< Number of online agents
< Number of offline agents
Definition at line 1826 of file chan_agent.c.
References agent_pvt::acknowledged, agent_pvt::agent, ast_bridged_channel(), ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_BUF, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), ast_tvdiff_ms(), ast_tvnow(), agent_pvt::chan, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::moh, ast_channel::name, agent_pvt::name, agent_pvt::owner, agent_pvt::pending, powerof(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and username.
01827 { 01828 struct agent_pvt *p; 01829 char username[AST_MAX_BUF]; 01830 char location[AST_MAX_BUF] = ""; 01831 char talkingto[AST_MAX_BUF] = ""; 01832 char moh[AST_MAX_BUF]; 01833 int count_agents = 0; /*!< Number of agents configured */ 01834 int online_agents = 0; /*!< Number of online agents */ 01835 int offline_agents = 0; /*!< Number of offline agents */ 01836 if (argc != 2) 01837 return RESULT_SHOWUSAGE; 01838 AST_LIST_LOCK(&agents); 01839 AST_LIST_TRAVERSE(&agents, p, list) { 01840 ast_mutex_lock(&p->lock); 01841 if (p->pending) { 01842 if (p->group) 01843 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group)); 01844 else 01845 ast_cli(fd, "-- Pending call to agent %s\n", p->agent); 01846 } else { 01847 if (!ast_strlen_zero(p->name)) 01848 snprintf(username, sizeof(username), "(%s) ", p->name); 01849 else 01850 username[0] = '\0'; 01851 if (p->chan) { 01852 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01853 if (p->owner && ast_bridged_channel(p->owner)) 01854 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01855 else 01856 strcpy(talkingto, " is idle"); 01857 online_agents++; 01858 } else if (!ast_strlen_zero(p->loginchan)) { 01859 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec)) 01860 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01861 else 01862 snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan); 01863 talkingto[0] = '\0'; 01864 online_agents++; 01865 if (p->acknowledged) 01866 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01867 } else { 01868 strcpy(location, "not logged in"); 01869 talkingto[0] = '\0'; 01870 offline_agents++; 01871 } 01872 if (!ast_strlen_zero(p->moh)) 01873 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01874 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, 01875 username, location, talkingto, moh); 01876 count_agents++; 01877 } 01878 ast_mutex_unlock(&p->lock); 01879 } 01880 AST_LIST_UNLOCK(&agents); 01881 if ( !count_agents ) 01882 ast_cli(fd, "No Agents are configured in %s\n",config); 01883 else 01884 ast_cli(fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents); 01885 ast_cli(fd, "\n"); 01886 01887 return RESULT_SUCCESS; 01888 }
static int agents_show_online | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1891 of file chan_agent.c.
References agent_pvt::acknowledged, agent_pvt::agent, ast_bridged_channel(), ast_cli(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_BUF, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, agent_pvt::list, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::moh, ast_channel::name, agent_pvt::name, agent_pvt::owner, RESULT_SHOWUSAGE, RESULT_SUCCESS, and username.
01892 { 01893 struct agent_pvt *p; 01894 char username[AST_MAX_BUF]; 01895 char location[AST_MAX_BUF] = ""; 01896 char talkingto[AST_MAX_BUF] = ""; 01897 char moh[AST_MAX_BUF]; 01898 int count_agents = 0; /* Number of agents configured */ 01899 int online_agents = 0; /* Number of online agents */ 01900 int agent_status = 0; /* 0 means offline, 1 means online */ 01901 if (argc != 3) 01902 return RESULT_SHOWUSAGE; 01903 AST_LIST_LOCK(&agents); 01904 AST_LIST_TRAVERSE(&agents, p, list) { 01905 agent_status = 0; /* reset it to offline */ 01906 ast_mutex_lock(&p->lock); 01907 if (!ast_strlen_zero(p->name)) 01908 snprintf(username, sizeof(username), "(%s) ", p->name); 01909 else 01910 username[0] = '\0'; 01911 if (p->chan) { 01912 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01913 if (p->owner && ast_bridged_channel(p->owner)) 01914 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01915 else 01916 strcpy(talkingto, " is idle"); 01917 agent_status = 1; 01918 online_agents++; 01919 } else if (!ast_strlen_zero(p->loginchan)) { 01920 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01921 talkingto[0] = '\0'; 01922 agent_status = 1; 01923 online_agents++; 01924 if (p->acknowledged) 01925 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01926 } 01927 if (!ast_strlen_zero(p->moh)) 01928 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01929 if (agent_status) 01930 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, moh); 01931 count_agents++; 01932 ast_mutex_unlock(&p->lock); 01933 } 01934 AST_LIST_UNLOCK(&agents); 01935 if (!count_agents) 01936 ast_cli(fd, "No Agents are configured in %s\n", config); 01937 else 01938 ast_cli(fd, "%d agents online\n", online_agents); 01939 ast_cli(fd, "\n"); 01940 return RESULT_SUCCESS; 01941 }
static int allow_multiple_login | ( | char * | chan, | |
char * | context | |||
) | [static] |
Definition at line 1414 of file chan_agent.c.
References AST_LIST_TRAVERSE, agent_pvt::list, agent_pvt::loginchan, and S_OR.
Referenced by __login_exec().
01415 { 01416 struct agent_pvt *p; 01417 char loginchan[80]; 01418 01419 if (multiplelogin) { 01420 return 1; 01421 } 01422 if (!chan) { 01423 return 0; 01424 } 01425 01426 snprintf(loginchan, sizeof(loginchan), "%s@%s", chan, S_OR(context, "default")); 01427 01428 AST_LIST_TRAVERSE(&agents, p, list) { 01429 if(!strcasecmp(loginchan, p->loginchan)) 01430 return 0; 01431 } 01432 return -1; 01433 }
static void callback_deprecated | ( | void | ) | [static] |
Definition at line 2459 of file chan_agent.c.
References ast_log(), depwarning, and LOG_WARNING.
Referenced by action_agent_callback_login(), and callback_exec().
02460 { 02461 static int depwarning = 0; 02462 02463 if (!depwarning) { 02464 depwarning = 1; 02465 02466 ast_log(LOG_WARNING, "AgentCallbackLogin is deprecated and will be removed in a future release.\n"); 02467 ast_log(LOG_WARNING, "See doc/queues-with-callback-members.txt for an example of how to achieve\n"); 02468 ast_log(LOG_WARNING, "the same functionality using only dialplan logic.\n"); 02469 } 02470 }
static int callback_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Called by the AgentCallbackLogin application (from the dial plan).
chan | ||
data |
Definition at line 2480 of file chan_agent.c.
References __login_exec(), callback_deprecated(), and ast_module_user::chan.
Referenced by load_module().
02481 { 02482 callback_deprecated(); 02483 02484 return __login_exec(chan, data, 1); 02485 }
static int check_availability | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1300 of file chan_agent.c.
References agent_pvt::abouttograb, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_cleanup(), agent_new(), ast_channel_masquerade(), ast_copy_string(), AST_FLAG_ZOMBIE, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_set_flag, ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_streamfile(), ast_waitstream(), agent_pvt::chan, ast_channel::context, agent_pvt::group, ast_channel::language, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, ast_channel::name, option_debug, agent_pvt::owner, and agent_pvt::pending.
Referenced by __login_exec().
01301 { 01302 struct ast_channel *chan=NULL, *parent=NULL; 01303 struct agent_pvt *p; 01304 int res; 01305 01306 if (option_debug) 01307 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent); 01308 if (needlock) 01309 AST_LIST_LOCK(&agents); 01310 AST_LIST_TRAVERSE(&agents, p, list) { 01311 if (p == newlyavailable) { 01312 continue; 01313 } 01314 ast_mutex_lock(&p->lock); 01315 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01316 if (option_debug) 01317 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01318 /* We found a pending call, time to merge */ 01319 chan = agent_new(newlyavailable, AST_STATE_DOWN); 01320 parent = p->owner; 01321 p->abouttograb = 1; 01322 ast_mutex_unlock(&p->lock); 01323 break; 01324 } 01325 ast_mutex_unlock(&p->lock); 01326 } 01327 if (needlock) 01328 AST_LIST_UNLOCK(&agents); 01329 if (parent && chan) { 01330 if (newlyavailable->ackcall > 1) { 01331 /* Don't do beep here */ 01332 res = 0; 01333 } else { 01334 if (option_debug > 2) 01335 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01336 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01337 if (option_debug > 2) 01338 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01339 if (!res) { 01340 res = ast_waitstream(newlyavailable->chan, ""); 01341 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01342 } 01343 } 01344 if (!res) { 01345 /* Note -- parent may have disappeared */ 01346 if (p->abouttograb) { 01347 newlyavailable->acknowledged = 1; 01348 /* Safe -- agent lock already held */ 01349 ast_setstate(parent, AST_STATE_UP); 01350 ast_setstate(chan, AST_STATE_UP); 01351 ast_copy_string(parent->context, chan->context, sizeof(parent->context)); 01352 /* Go ahead and mark the channel as a zombie so that masquerade will 01353 destroy it for us, and we need not call ast_hangup */ 01354 ast_mutex_lock(&parent->lock); 01355 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01356 ast_channel_masquerade(parent, chan); 01357 ast_mutex_unlock(&parent->lock); 01358 p->abouttograb = 0; 01359 } else { 01360 if (option_debug) 01361 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n"); 01362 agent_cleanup(newlyavailable); 01363 } 01364 } else { 01365 if (option_debug) 01366 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n"); 01367 agent_cleanup(newlyavailable); 01368 } 01369 } 01370 return 0; 01371 }
static int check_beep | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1373 of file chan_agent.c.
References agent_pvt::abouttograb, agent_pvt::agent, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_streamfile(), ast_waitstream(), agent_pvt::chan, agent_pvt::group, ast_channel::language, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, ast_channel::name, option_debug, agent_pvt::owner, and agent_pvt::pending.
Referenced by __login_exec().
01374 { 01375 struct agent_pvt *p; 01376 int res=0; 01377 01378 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent); 01379 if (needlock) 01380 AST_LIST_LOCK(&agents); 01381 AST_LIST_TRAVERSE(&agents, p, list) { 01382 if (p == newlyavailable) { 01383 continue; 01384 } 01385 ast_mutex_lock(&p->lock); 01386 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01387 if (option_debug) 01388 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01389 ast_mutex_unlock(&p->lock); 01390 break; 01391 } 01392 ast_mutex_unlock(&p->lock); 01393 } 01394 if (needlock) 01395 AST_LIST_UNLOCK(&agents); 01396 if (p) { 01397 ast_mutex_unlock(&newlyavailable->lock); 01398 if (option_debug > 2) 01399 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01400 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01401 if (option_debug > 2) 01402 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01403 if (!res) { 01404 res = ast_waitstream(newlyavailable->chan, ""); 01405 if (option_debug) 01406 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01407 } 01408 ast_mutex_lock(&newlyavailable->lock); 01409 } 01410 return res; 01411 }
static char* complete_agent_logoff_cmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1799 of file chan_agent.c.
References agent_pvt::agent, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, AST_MAX_AGENT, ast_strdup, len(), agent_pvt::list, and agent_pvt::name.
01800 { 01801 char *ret = NULL; 01802 01803 if (pos == 2) { 01804 struct agent_pvt *p; 01805 char name[AST_MAX_AGENT]; 01806 int which = 0, len = strlen(word); 01807 01808 AST_LIST_LOCK(&agents); 01809 AST_LIST_TRAVERSE(&agents, p, list) { 01810 snprintf(name, sizeof(name), "Agent/%s", p->agent); 01811 if (!strncasecmp(word, name, len) && ++which > state) { 01812 ret = ast_strdup(name); 01813 break; 01814 } 01815 } 01816 AST_LIST_UNLOCK(&agents); 01817 } else if (pos == 3 && state == 0) 01818 return ast_strdup("soft"); 01819 01820 return ret; 01821 }
static void dump_agents | ( | void | ) | [static] |
Dump AgentCallbackLogin agents to the ASTdb database for persistence.
Definition at line 2639 of file chan_agent.c.
References agent_pvt::agent, ast_db_del(), ast_db_put(), AST_LIST_TRAVERSE, ast_log(), ast_strlen_zero(), agent_pvt::chan, agent_pvt::list, LOG_DEBUG, LOG_WARNING, agent_pvt::logincallerid, agent_pvt::loginchan, and option_debug.
Referenced by __login_exec(), action_agent_callback_login(), agent_hangup(), and agent_logoff_maintenance().
02640 { 02641 struct agent_pvt *cur_agent = NULL; 02642 char buf[256]; 02643 02644 AST_LIST_TRAVERSE(&agents, cur_agent, list) { 02645 if (cur_agent->chan) 02646 continue; 02647 02648 if (!ast_strlen_zero(cur_agent->loginchan)) { 02649 snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid); 02650 if (ast_db_put(pa_family, cur_agent->agent, buf)) 02651 ast_log(LOG_WARNING, "failed to create persistent entry in ASTdb for %s!\n", buf); 02652 else if (option_debug) 02653 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan); 02654 } else { 02655 /* Delete - no agent or there is an error */ 02656 ast_db_del(pa_family, cur_agent->agent); 02657 } 02658 } 02659 }
static struct agent_pvt* find_agent | ( | char * | agentid | ) | [static] |
Definition at line 2767 of file chan_agent.c.
References agent_pvt::agent, AST_LIST_TRAVERSE, and agent_pvt::list.
Referenced by function_agent().
02768 { 02769 struct agent_pvt *cur; 02770 02771 AST_LIST_TRAVERSE(&agents, cur, list) { 02772 if (!strcmp(cur->agent, agentid)) 02773 break; 02774 } 02775 02776 return cur; 02777 }
static int function_agent | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 2779 of file chan_agent.c.
References agent_pvt::agent, AST_APP_ARG, ast_channel_lock, ast_channel_unlock, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_LIST_LOCK, AST_LIST_UNLOCK, ast_log(), AST_NONSTANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), find_agent(), LOG_WARNING, and parse().
02780 { 02781 char *parse; 02782 AST_DECLARE_APP_ARGS(args, 02783 AST_APP_ARG(agentid); 02784 AST_APP_ARG(item); 02785 ); 02786 char *tmp; 02787 struct agent_pvt *agent; 02788 02789 buf[0] = '\0'; 02790 02791 if (ast_strlen_zero(data)) { 02792 ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n"); 02793 return -1; 02794 } 02795 02796 parse = ast_strdupa(data); 02797 02798 AST_NONSTANDARD_APP_ARGS(args, parse, ':'); 02799 if (!args.item) 02800 args.item = "status"; 02801 02802 AST_LIST_LOCK(&agents); 02803 02804 if (!(agent = find_agent(args.agentid))) { 02805 AST_LIST_UNLOCK(&agents); 02806 ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid); 02807 return -1; 02808 } 02809 02810 if (!strcasecmp(args.item, "status")) { 02811 char *status = "LOGGEDOUT"; 02812 if (agent->chan || !ast_strlen_zero(agent->loginchan)) 02813 status = "LOGGEDIN"; 02814 ast_copy_string(buf, status, len); 02815 } else if (!strcasecmp(args.item, "password")) 02816 ast_copy_string(buf, agent->password, len); 02817 else if (!strcasecmp(args.item, "name")) 02818 ast_copy_string(buf, agent->name, len); 02819 else if (!strcasecmp(args.item, "mohclass")) 02820 ast_copy_string(buf, agent->moh, len); 02821 else if (!strcasecmp(args.item, "channel")) { 02822 if (agent->chan) { 02823 ast_channel_lock(agent->chan); 02824 ast_copy_string(buf, agent->chan->name, len); 02825 ast_channel_unlock(agent->chan); 02826 tmp = strrchr(buf, '-'); 02827 if (tmp) 02828 *tmp = '\0'; 02829 } 02830 } else if (!strcasecmp(args.item, "exten")) 02831 ast_copy_string(buf, agent->loginchan, len); 02832 02833 AST_LIST_UNLOCK(&agents); 02834 02835 return 0; 02836 }
static int load_module | ( | void | ) | [static] |
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other things it registers applications, cli commands and reads the cofiguration file.
Definition at line 2861 of file chan_agent.c.
References action_agent_callback_login(), action_agent_logoff(), action_agents(), agent_devicestate_cb(), agent_function, agent_tech, agentmonitoroutgoing_exec(), ast_channel_register(), ast_cli_register_multiple(), ast_custom_function_register(), ast_devstate_add(), ast_log(), ast_manager_register2(), AST_MODULE_LOAD_DECLINE, ast_register_application(), callback_exec(), cli_agents, EVENT_FLAG_AGENT, LOG_ERROR, login_exec(), read_agent_config(), and reload_agents().
02862 { 02863 /* Make sure we can register our agent channel type */ 02864 if (ast_channel_register(&agent_tech)) { 02865 ast_log(LOG_ERROR, "Unable to register channel class 'Agent'\n"); 02866 return -1; 02867 } 02868 /* Read in the config */ 02869 if (!read_agent_config()) 02870 return AST_MODULE_LOAD_DECLINE; 02871 if (persistent_agents) 02872 reload_agents(); 02873 /* Dialplan applications */ 02874 ast_register_application(app, login_exec, synopsis, descrip); 02875 ast_register_application(app2, callback_exec, synopsis2, descrip2); 02876 ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3); 02877 02878 /* Manager commands */ 02879 ast_manager_register2("Agents", EVENT_FLAG_AGENT, action_agents, "Lists agents and their status", mandescr_agents); 02880 ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff); 02881 ast_manager_register2("AgentCallbackLogin", EVENT_FLAG_AGENT, action_agent_callback_login, "Sets an agent as logged in by callback", mandescr_agent_callback_login); 02882 02883 /* CLI Commands */ 02884 ast_cli_register_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry)); 02885 02886 /* Dialplan Functions */ 02887 ast_custom_function_register(&agent_function); 02888 02889 ast_devstate_add(agent_devicestate_cb, NULL); 02890 02891 return 0; 02892 }
static int login_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Called by the AgentLogin application (from the dial plan).
chan | ||
data |
Definition at line 2454 of file chan_agent.c.
References __login_exec(), and ast_module_user::chan.
Referenced by load_module().
02455 { 02456 return __login_exec(chan, data, 0); 02457 }
static force_inline int powerof | ( | unsigned int | d | ) | [static] |
static int read_agent_config | ( | void | ) | [static] |
Read configuration data. The file named agents.conf.
Definition at line 1150 of file chan_agent.c.
References add_agent(), agent_pvt::app_complete_cond, ast_category_browse(), ast_cond_destroy(), ast_config_destroy(), ast_config_load(), ast_copy_string(), ast_get_group(), AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), agent_pvt::chan, agent_pvt::dead, free, agent_pvt::list, agent_pvt::lock, LOG_NOTICE, agent_pvt::login_wait_cond, ast_variable::name, ast_variable::next, agent_pvt::owner, secret, and ast_variable::value.
Referenced by load_module(), and reload().
01151 { 01152 struct ast_config *cfg; 01153 struct ast_config *ucfg; 01154 struct ast_variable *v; 01155 struct agent_pvt *p; 01156 const char *general_val; 01157 const char *catname; 01158 const char *hasagent; 01159 int genhasagent; 01160 01161 group = 0; 01162 autologoff = 0; 01163 wrapuptime = 0; 01164 ackcall = 0; 01165 endcall = 1; 01166 cfg = ast_config_load(config); 01167 if (!cfg) { 01168 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); 01169 return 0; 01170 } 01171 AST_LIST_LOCK(&agents); 01172 AST_LIST_TRAVERSE(&agents, p, list) { 01173 p->dead = 1; 01174 } 01175 strcpy(moh, "default"); 01176 /* set the default recording values */ 01177 recordagentcalls = 0; 01178 strcpy(recordformat, "wav"); 01179 strcpy(recordformatext, "wav"); 01180 urlprefix[0] = '\0'; 01181 savecallsin[0] = '\0'; 01182 01183 /* Read in [general] section for persistence */ 01184 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents"))) 01185 persistent_agents = ast_true(general_val); 01186 multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin")); 01187 01188 /* Read in the [agents] section */ 01189 v = ast_variable_browse(cfg, "agents"); 01190 while(v) { 01191 /* Create the interface list */ 01192 if (!strcasecmp(v->name, "agent")) { 01193 add_agent(v->value, 0); 01194 } else if (!strcasecmp(v->name, "group")) { 01195 group = ast_get_group(v->value); 01196 } else if (!strcasecmp(v->name, "autologoff")) { 01197 autologoff = atoi(v->value); 01198 if (autologoff < 0) 01199 autologoff = 0; 01200 } else if (!strcasecmp(v->name, "ackcall")) { 01201 if (!strcasecmp(v->value, "always")) 01202 ackcall = 2; 01203 else if (ast_true(v->value)) 01204 ackcall = 1; 01205 else 01206 ackcall = 0; 01207 } else if (!strcasecmp(v->name, "endcall")) { 01208 endcall = ast_true(v->value); 01209 } else if (!strcasecmp(v->name, "wrapuptime")) { 01210 wrapuptime = atoi(v->value); 01211 if (wrapuptime < 0) 01212 wrapuptime = 0; 01213 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { 01214 maxlogintries = atoi(v->value); 01215 if (maxlogintries < 0) 01216 maxlogintries = 0; 01217 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { 01218 strcpy(agentgoodbye,v->value); 01219 } else if (!strcasecmp(v->name, "musiconhold")) { 01220 ast_copy_string(moh, v->value, sizeof(moh)); 01221 } else if (!strcasecmp(v->name, "updatecdr")) { 01222 if (ast_true(v->value)) 01223 updatecdr = 1; 01224 else 01225 updatecdr = 0; 01226 } else if (!strcasecmp(v->name, "autologoffunavail")) { 01227 if (ast_true(v->value)) 01228 autologoffunavail = 1; 01229 else 01230 autologoffunavail = 0; 01231 } else if (!strcasecmp(v->name, "recordagentcalls")) { 01232 recordagentcalls = ast_true(v->value); 01233 } else if (!strcasecmp(v->name, "recordformat")) { 01234 ast_copy_string(recordformat, v->value, sizeof(recordformat)); 01235 if (!strcasecmp(v->value, "wav49")) 01236 strcpy(recordformatext, "WAV"); 01237 else 01238 ast_copy_string(recordformatext, v->value, sizeof(recordformatext)); 01239 } else if (!strcasecmp(v->name, "urlprefix")) { 01240 ast_copy_string(urlprefix, v->value, sizeof(urlprefix)); 01241 if (urlprefix[strlen(urlprefix) - 1] != '/') 01242 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1); 01243 } else if (!strcasecmp(v->name, "savecallsin")) { 01244 if (v->value[0] == '/') 01245 ast_copy_string(savecallsin, v->value, sizeof(savecallsin)); 01246 else 01247 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value); 01248 if (savecallsin[strlen(savecallsin) - 1] != '/') 01249 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); 01250 } else if (!strcasecmp(v->name, "custom_beep")) { 01251 ast_copy_string(beep, v->value, sizeof(beep)); 01252 } 01253 v = v->next; 01254 } 01255 if ((ucfg = ast_config_load("users.conf"))) { 01256 genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent")); 01257 catname = ast_category_browse(ucfg, NULL); 01258 while(catname) { 01259 if (strcasecmp(catname, "general")) { 01260 hasagent = ast_variable_retrieve(ucfg, catname, "hasagent"); 01261 if (ast_true(hasagent) || (!hasagent && genhasagent)) { 01262 char tmp[256]; 01263 const char *fullname = ast_variable_retrieve(ucfg, catname, "fullname"); 01264 const char *secret = ast_variable_retrieve(ucfg, catname, "secret"); 01265 if (!fullname) 01266 fullname = ""; 01267 if (!secret) 01268 secret = ""; 01269 snprintf(tmp, sizeof(tmp), "%s,%s,%s", catname, secret,fullname); 01270 add_agent(tmp, 0); 01271 } 01272 } 01273 catname = ast_category_browse(ucfg, catname); 01274 } 01275 ast_config_destroy(ucfg); 01276 } 01277 AST_LIST_TRAVERSE_SAFE_BEGIN(&agents, p, list) { 01278 if (p->dead) { 01279 AST_LIST_REMOVE_CURRENT(&agents, list); 01280 /* Destroy if appropriate */ 01281 if (!p->owner) { 01282 if (!p->chan) { 01283 ast_mutex_destroy(&p->lock); 01284 ast_cond_destroy(&p->app_complete_cond); 01285 ast_cond_destroy(&p->login_wait_cond); 01286 free(p); 01287 } else { 01288 /* Cause them to hang up */ 01289 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01290 } 01291 } 01292 } 01293 } 01294 AST_LIST_TRAVERSE_SAFE_END 01295 AST_LIST_UNLOCK(&agents); 01296 ast_config_destroy(cfg); 01297 return 1; 01298 }
static int reload | ( | void | ) | [static] |
Definition at line 2894 of file chan_agent.c.
References read_agent_config(), and reload_agents().
Referenced by moh_cli(), reload(), rpt_do_reload(), and show_console().
02895 { 02896 read_agent_config(); 02897 if (persistent_agents) 02898 reload_agents(); 02899 return 0; 02900 }
static void reload_agents | ( | void | ) | [static] |
Reload the persistent agents from astdb.
Definition at line 2664 of file chan_agent.c.
References agent_pvt::agent, ast_copy_string(), ast_db_del(), ast_db_freetree(), ast_db_get(), ast_db_gettree(), ast_device_state_changed(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_db_entry::key, agent_pvt::list, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, ast_db_entry::next, option_debug, parse(), and set_agentbycallerid().
Referenced by load_module(), and reload().
02665 { 02666 char *agent_num; 02667 struct ast_db_entry *db_tree; 02668 struct ast_db_entry *entry; 02669 struct agent_pvt *cur_agent; 02670 char agent_data[256]; 02671 char *parse; 02672 char *agent_chan; 02673 char *agent_callerid; 02674 02675 db_tree = ast_db_gettree(pa_family, NULL); 02676 02677 AST_LIST_LOCK(&agents); 02678 for (entry = db_tree; entry; entry = entry->next) { 02679 agent_num = entry->key + strlen(pa_family) + 2; 02680 AST_LIST_TRAVERSE(&agents, cur_agent, list) { 02681 ast_mutex_lock(&cur_agent->lock); 02682 if (strcmp(agent_num, cur_agent->agent) == 0) 02683 break; 02684 ast_mutex_unlock(&cur_agent->lock); 02685 } 02686 if (!cur_agent) { 02687 ast_db_del(pa_family, agent_num); 02688 continue; 02689 } else 02690 ast_mutex_unlock(&cur_agent->lock); 02691 if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) { 02692 if (option_debug) 02693 ast_log(LOG_DEBUG, "Reload Agent from AstDB: %s on %s\n", cur_agent->agent, agent_data); 02694 parse = agent_data; 02695 agent_chan = strsep(&parse, ";"); 02696 agent_callerid = strsep(&parse, ";"); 02697 ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan)); 02698 if (agent_callerid) { 02699 ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid)); 02700 set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent); 02701 } else 02702 cur_agent->logincallerid[0] = '\0'; 02703 if (cur_agent->loginstart == 0) 02704 time(&cur_agent->loginstart); 02705 ast_device_state_changed("Agent/%s", cur_agent->agent); 02706 } 02707 } 02708 AST_LIST_UNLOCK(&agents); 02709 if (db_tree) { 02710 ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n"); 02711 ast_db_freetree(db_tree); 02712 } 02713 }
static void set_agentbycallerid | ( | const char * | callerid, | |
const char * | agent | |||
) | [static] |
store/clear the global variable that stores agentid based on the callerid
Definition at line 853 of file chan_agent.c.
References AST_MAX_BUF, ast_strlen_zero(), GETAGENTBYCALLERID, and pbx_builtin_setvar_helper().
Referenced by __login_exec(), agent_logoff_maintenance(), and reload_agents().
00854 { 00855 char buf[AST_MAX_BUF]; 00856 00857 /* if there is no Caller ID, nothing to do */ 00858 if (ast_strlen_zero(callerid)) 00859 return; 00860 00861 snprintf(buf, sizeof(buf), "%s_%s", GETAGENTBYCALLERID, callerid); 00862 pbx_builtin_setvar_helper(NULL, buf, agent); 00863 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2902 of file chan_agent.c.
References agent_devicestate_cb(), agent_function, agent_tech, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_custom_function_unregister(), ast_devstate_del(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_manager_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), cli_agents, free, agent_pvt::list, and agent_pvt::owner.
Referenced by load_module().
02903 { 02904 struct agent_pvt *p; 02905 /* First, take us out of the channel loop */ 02906 ast_channel_unregister(&agent_tech); 02907 /* Delete devicestate subscription */ 02908 ast_devstate_del(agent_devicestate_cb, NULL); 02909 /* Unregister dialplan functions */ 02910 ast_custom_function_unregister(&agent_function); 02911 /* Unregister CLI commands */ 02912 ast_cli_unregister_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry)); 02913 /* Unregister dialplan applications */ 02914 ast_unregister_application(app); 02915 ast_unregister_application(app2); 02916 ast_unregister_application(app3); 02917 /* Unregister manager command */ 02918 ast_manager_unregister("Agents"); 02919 ast_manager_unregister("AgentLogoff"); 02920 ast_manager_unregister("AgentCallbackLogin"); 02921 /* Unregister channel */ 02922 AST_LIST_LOCK(&agents); 02923 /* Hangup all interfaces if they have an owner */ 02924 while ((p = AST_LIST_REMOVE_HEAD(&agents, list))) { 02925 if (p->owner) 02926 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 02927 free(p); 02928 } 02929 AST_LIST_UNLOCK(&agents); 02930 return 0; 02931 }
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .description = "Agent Proxy Channel" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static] |
Definition at line 2937 of file chan_agent.c.
int ackcall [static] |
Definition at line 159 of file chan_agent.c.
char agent_logoff_usage[] [static] |
Initial value:
"Usage: agent logoff <channel> [soft]\n" " Sets an agent as no longer logged in.\n" " If 'soft' is specified, do not hangup existing calls.\n"
Definition at line 1953 of file chan_agent.c.
struct ast_channel_tech agent_tech [static] |
Channel interface description for PBX integration.
Definition at line 267 of file chan_agent.c.
Referenced by agent_new(), load_module(), and unload_module().
char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye" [static] |
Definition at line 165 of file chan_agent.c.
const char app[] = "AgentLogin" [static] |
Definition at line 82 of file chan_agent.c.
Referenced by action_originate(), add_extensions(), ael2_semantic_check(), answer_exec_enable(), ast_pbx_run_app(), async_wait(), check_app_args(), check_pval_item(), conf_run(), exec_exec(), execif_exec(), feature_exec_app(), forward_message(), handle_context_add_extension(), handle_context_add_extension_deprecated(), handle_exec(), load_module(), page_exec(), pbx_builtin_execiftime(), pbx_exec(), pbx_extension_helper(), realtime_exec(), tryexec_exec(), and unload_module().
const char app2[] = "AgentCallbackLogin" [static] |
const char app3[] = "AgentMonitorOutgoing" [static] |
Definition at line 84 of file chan_agent.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 2937 of file chan_agent.c.
int autologoff [static] |
Definition at line 157 of file chan_agent.c.
int autologoffunavail = 0 [static] |
Definition at line 162 of file chan_agent.c.
char beep[AST_MAX_BUF] = "beep" [static] |
Definition at line 173 of file chan_agent.c.
struct ast_cli_entry cli_agents[] [static] |
struct ast_cli_entry cli_show_agents_deprecated [static] |
Initial value:
{ { "show", "agents", NULL }, agents_show, NULL, NULL, NULL }
Definition at line 1958 of file chan_agent.c.
struct ast_cli_entry cli_show_agents_online_deprecated [static] |
Initial value:
{ { "show", "agents", "online" }, agents_show_online, NULL, NULL, NULL }
Definition at line 1963 of file chan_agent.c.
const char config[] = "agents.conf" [static] |
Definition at line 80 of file chan_agent.c.
Referenced by add_features_datastores(), app_exec(), ast_bridge_call(), ast_category_append(), ast_category_browse(), ast_category_exist(), ast_category_get(), ast_category_root(), ast_channel_bridge(), ast_config_new(), ast_generic_bridge(), ast_readconfig(), ast_variable_browse(), ast_variable_next(), ast_variable_retrieve(), builtin_atxfer(), category_get(), do_reload(), feature_interpret(), feature_interpret_helper(), load_module(), load_odbc_config(), misdn_cfg_init(), park_exec(), parse_config(), pbx_load_module(), read_config_maps(), reload(), reload_config(), set_bridge_features_on_config(), and set_config_flags().
const char descrip[] [static] |
const char descrip2[] [static] |
Definition at line 99 of file chan_agent.c.
const char descrip3[] [static] |
Definition at line 107 of file chan_agent.c.
int endcall [static] |
Definition at line 160 of file chan_agent.c.
ast_group_t group [static] |
Definition at line 156 of file chan_agent.c.
Referenced by ast_app_group_set_channel(), ast_get_group(), ast_makesocket(), common_exec(), group_count_function_read(), group_match_count_function_read(), main(), misdn_check_l2l1(), and misdn_request().
const char mandescr_agent_callback_login[] [static] |
Definition at line 135 of file chan_agent.c.
const char mandescr_agent_logoff[] [static] |
Initial value:
"Description: Sets an agent as no longer logged in.\n" "Variables: (Names marked with * are required)\n" " *Agent: Agent ID of the agent to log off\n" " Soft: Set to 'true' to not hangup existing calls\n"
Definition at line 129 of file chan_agent.c.
const char mandescr_agents[] [static] |
Initial value:
"Description: Will list info about all possible agents.\n" "Variables: NONE\n"
Definition at line 125 of file chan_agent.c.
int maxlogintries = 3 [static] |
Definition at line 164 of file chan_agent.c.
char moh[80] = "default" [static] |
Definition at line 144 of file chan_agent.c.
Referenced by get_mohbyname(), moh_generate(), moh_register(), moh_release(), mohalloc(), and monmp3thread().
int multiplelogin = 1 [static] |
Definition at line 161 of file chan_agent.c.
const char pa_family[] = "Agents" [static] |
Persistent Agents astdb family
Definition at line 150 of file chan_agent.c.
int persistent_agents = 0 [static] |
queues.conf [general] option
Definition at line 153 of file chan_agent.c.
int recordagentcalls = 0 [static] |
Definition at line 167 of file chan_agent.c.
char recordformat[AST_MAX_BUF] = "" [static] |
Definition at line 168 of file chan_agent.c.
char recordformatext[AST_MAX_BUF] = "" [static] |
Definition at line 169 of file chan_agent.c.
char savecallsin[AST_MAX_BUF] = "" [static] |
Definition at line 171 of file chan_agent.c.
char show_agents_online_usage[] [static] |
Initial value:
"Usage: agent show online\n" " Provides a list of all online agents.\n"
Definition at line 1949 of file chan_agent.c.
char show_agents_usage[] [static] |
Initial value:
"Usage: agent show\n" " Provides summary information on agents.\n"
Definition at line 1945 of file chan_agent.c.
Definition at line 87 of file chan_agent.c.
Definition at line 88 of file chan_agent.c.
const char tdesc[] = "Call Agent Proxy Channel" [static] |
Definition at line 79 of file chan_agent.c.
int updatecdr = 0 [static] |
Definition at line 172 of file chan_agent.c.
char urlprefix[AST_MAX_BUF] = "" [static] |
int wrapuptime [static] |
Definition at line 158 of file chan_agent.c.