#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 458 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().
00459 { 00460 char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer; 00461 char filename[AST_MAX_BUF]; 00462 int res = -1; 00463 if (!p) 00464 return -1; 00465 if (!ast->monitor) { 00466 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid); 00467 /* substitute . for - */ 00468 if ((pointer = strchr(filename, '.'))) 00469 *pointer = '-'; 00470 snprintf(tmp, sizeof(tmp), "%s%s", savecallsin, filename); 00471 ast_monitor_start(ast, recordformat, tmp, needlock); 00472 ast_monitor_setjoinfiles(ast, 1); 00473 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix, filename, recordformatext); 00474 #if 0 00475 ast_verbose("name is %s, link is %s\n",tmp, tmp2); 00476 #endif 00477 if (!ast->cdr) 00478 ast->cdr = ast_cdr_alloc(); 00479 ast_cdr_setuserfield(ast, tmp2); 00480 res = 0; 00481 } else 00482 ast_log(LOG_ERROR, "Recording already started on that call.\n"); 00483 return res; 00484 }
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 1947 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, 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_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::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().
01948 { 01949 int res=0; 01950 int tries = 0; 01951 int max_login_tries = maxlogintries; 01952 struct agent_pvt *p; 01953 struct ast_module_user *u; 01954 int login_state = 0; 01955 char user[AST_MAX_AGENT] = ""; 01956 char pass[AST_MAX_AGENT]; 01957 char agent[AST_MAX_AGENT] = ""; 01958 char xpass[AST_MAX_AGENT] = ""; 01959 char *errmsg; 01960 char *parse; 01961 AST_DECLARE_APP_ARGS(args, 01962 AST_APP_ARG(agent_id); 01963 AST_APP_ARG(options); 01964 AST_APP_ARG(extension); 01965 ); 01966 const char *tmpoptions = NULL; 01967 char *context = NULL; 01968 int play_announcement = 1; 01969 char agent_goodbye[AST_MAX_FILENAME_LEN]; 01970 int update_cdr = updatecdr; 01971 char *filename = "agent-loginok"; 01972 char tmpchan[AST_MAX_BUF] = ""; 01973 01974 u = ast_module_user_add(chan); 01975 01976 parse = ast_strdupa(data); 01977 01978 AST_STANDARD_APP_ARGS(args, parse); 01979 01980 ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye)); 01981 01982 ast_channel_lock(chan); 01983 /* Set Channel Specific Login Overrides */ 01984 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { 01985 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); 01986 if (max_login_tries < 0) 01987 max_login_tries = 0; 01988 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); 01989 if (option_verbose > 2) 01990 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); 01991 } 01992 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { 01993 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) 01994 update_cdr = 1; 01995 else 01996 update_cdr = 0; 01997 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); 01998 if (option_verbose > 2) 01999 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); 02000 } 02001 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { 02002 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); 02003 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); 02004 if (option_verbose > 2) 02005 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); 02006 } 02007 ast_channel_unlock(chan); 02008 /* End Channel Specific Login Overrides */ 02009 02010 if (callbackmode && args.extension) { 02011 parse = args.extension; 02012 args.extension = strsep(&parse, "@"); 02013 context = parse; 02014 } 02015 02016 if (!ast_strlen_zero(args.options)) { 02017 if (strchr(args.options, 's')) { 02018 play_announcement = 0; 02019 } 02020 } 02021 02022 if (chan->_state != AST_STATE_UP) 02023 res = ast_answer(chan); 02024 if (!res) { 02025 if (!ast_strlen_zero(args.agent_id)) 02026 ast_copy_string(user, args.agent_id, AST_MAX_AGENT); 02027 else 02028 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); 02029 } 02030 while (!res && (max_login_tries==0 || tries < max_login_tries)) { 02031 tries++; 02032 /* Check for password */ 02033 AST_LIST_LOCK(&agents); 02034 AST_LIST_TRAVERSE(&agents, p, list) { 02035 if (!strcmp(p->agent, user) && !p->pending) 02036 ast_copy_string(xpass, p->password, sizeof(xpass)); 02037 } 02038 AST_LIST_UNLOCK(&agents); 02039 if (!res) { 02040 if (!ast_strlen_zero(xpass)) 02041 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); 02042 else 02043 pass[0] = '\0'; 02044 } 02045 errmsg = "agent-incorrect"; 02046 02047 #if 0 02048 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); 02049 #endif 02050 02051 /* Check again for accuracy */ 02052 AST_LIST_LOCK(&agents); 02053 AST_LIST_TRAVERSE(&agents, p, list) { 02054 int unlock_channel = 1; 02055 ast_channel_lock(chan); 02056 ast_mutex_lock(&p->lock); 02057 if (!strcmp(p->agent, user) && 02058 !strcmp(p->password, pass) && !p->pending) { 02059 login_state = 1; /* Successful Login */ 02060 02061 /* Ensure we can't be gotten until we're done */ 02062 gettimeofday(&p->lastdisc, NULL); 02063 p->lastdisc.tv_sec++; 02064 02065 /* Set Channel Specific Agent Overrides */ 02066 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { 02067 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) 02068 p->ackcall = 2; 02069 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) 02070 p->ackcall = 1; 02071 else 02072 p->ackcall = 0; 02073 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); 02074 if (option_verbose > 2) 02075 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); 02076 } else { 02077 p->ackcall = ackcall; 02078 } 02079 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { 02080 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); 02081 if (p->autologoff < 0) 02082 p->autologoff = 0; 02083 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); 02084 if (option_verbose > 2) 02085 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); 02086 } else { 02087 p->autologoff = autologoff; 02088 } 02089 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { 02090 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); 02091 if (p->wrapuptime < 0) 02092 p->wrapuptime = 0; 02093 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); 02094 if (option_verbose > 2) 02095 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); 02096 } else { 02097 p->wrapuptime = wrapuptime; 02098 } 02099 ast_channel_unlock(chan); 02100 unlock_channel = 0; 02101 /* End Channel Specific Agent Overrides */ 02102 if (!p->chan) { 02103 char last_loginchan[80] = ""; 02104 long logintime; 02105 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 02106 02107 if (callbackmode) { 02108 int pos = 0; 02109 /* Retrieve login chan */ 02110 for (;;) { 02111 if (!ast_strlen_zero(args.extension)) { 02112 ast_copy_string(tmpchan, args.extension, sizeof(tmpchan)); 02113 res = 0; 02114 } else 02115 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0); 02116 if (ast_strlen_zero(tmpchan) ) 02117 break; 02118 if(ast_exists_extension(chan, S_OR(context,"default"), tmpchan,1, NULL) ) { 02119 if(!allow_multiple_login(tmpchan,context) ) { 02120 args.extension = NULL; 02121 pos = 0; 02122 } else 02123 break; 02124 } 02125 if (args.extension) { 02126 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", args.extension, p->agent); 02127 args.extension = NULL; 02128 pos = 0; 02129 } else { 02130 ast_log(LOG_WARNING, "Extension '%s@%s' is not valid for automatic login of agent '%s'\n", tmpchan, S_OR(context, "default"), p->agent); 02131 res = ast_streamfile(chan, "invalid", chan->language); 02132 if (!res) 02133 res = ast_waitstream(chan, AST_DIGIT_ANY); 02134 if (res > 0) { 02135 tmpchan[0] = res; 02136 tmpchan[1] = '\0'; 02137 pos = 1; 02138 } else { 02139 tmpchan[0] = '\0'; 02140 pos = 0; 02141 } 02142 } 02143 } 02144 args.extension = tmpchan; 02145 if (!res) { 02146 set_agentbycallerid(p->logincallerid, NULL); 02147 if (!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) 02148 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); 02149 else { 02150 ast_copy_string(last_loginchan, p->loginchan, sizeof(last_loginchan)); 02151 ast_copy_string(p->loginchan, tmpchan, sizeof(p->loginchan)); 02152 } 02153 p->acknowledged = 0; 02154 if (ast_strlen_zero(p->loginchan)) { 02155 login_state = 2; 02156 filename = "agent-loggedoff"; 02157 } else { 02158 if (chan->cid.cid_num) { 02159 ast_copy_string(p->logincallerid, chan->cid.cid_num, sizeof(p->logincallerid)); 02160 set_agentbycallerid(p->logincallerid, p->agent); 02161 } else 02162 p->logincallerid[0] = '\0'; 02163 } 02164 02165 if(update_cdr && chan->cdr) 02166 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02167 02168 } 02169 } else { 02170 p->loginchan[0] = '\0'; 02171 p->logincallerid[0] = '\0'; 02172 p->acknowledged = 0; 02173 } 02174 ast_mutex_unlock(&p->lock); 02175 AST_LIST_UNLOCK(&agents); 02176 if( !res && play_announcement==1 ) 02177 res = ast_streamfile(chan, filename, chan->language); 02178 if (!res) 02179 ast_waitstream(chan, ""); 02180 AST_LIST_LOCK(&agents); 02181 ast_mutex_lock(&p->lock); 02182 if (!res) { 02183 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); 02184 if (res) 02185 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); 02186 } 02187 if (!res) { 02188 res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); 02189 if (res) 02190 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); 02191 } 02192 /* Check once more just in case */ 02193 if (p->chan) 02194 res = -1; 02195 if (callbackmode && !res) { 02196 /* Just say goodbye and be done with it */ 02197 if (!ast_strlen_zero(p->loginchan)) { 02198 if (p->loginstart == 0) 02199 time(&p->loginstart); 02200 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02201 "Agent: %s\r\n" 02202 "Loginchan: %s\r\n" 02203 "Uniqueid: %s\r\n", 02204 p->agent, p->loginchan, chan->uniqueid); 02205 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02206 if (option_verbose > 1) 02207 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02208 ast_device_state_changed("Agent/%s", p->agent); 02209 if (persistent_agents) 02210 dump_agents(); 02211 } else { 02212 logintime = time(NULL) - p->loginstart; 02213 p->loginstart = 0; 02214 02215 agent_logoff_maintenance(p, last_loginchan, logintime, chan->uniqueid, NULL); 02216 if (option_verbose > 1) 02217 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent); 02218 } 02219 AST_LIST_UNLOCK(&agents); 02220 if (!res) 02221 res = ast_safe_sleep(chan, 500); 02222 ast_mutex_unlock(&p->lock); 02223 } else if (!res) { 02224 ast_indicate_data(chan, AST_CONTROL_HOLD, 02225 S_OR(p->moh, NULL), 02226 !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0); 02227 if (p->loginstart == 0) 02228 time(&p->loginstart); 02229 manager_event(EVENT_FLAG_AGENT, "Agentlogin", 02230 "Agent: %s\r\n" 02231 "Channel: %s\r\n" 02232 "Uniqueid: %s\r\n", 02233 p->agent, chan->name, chan->uniqueid); 02234 if (update_cdr && chan->cdr) 02235 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02236 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); 02237 if (option_verbose > 1) 02238 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent, 02239 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); 02240 /* Login this channel and wait for it to go away */ 02241 p->chan = chan; 02242 if (p->ackcall > 1) 02243 check_beep(p, 0); 02244 else 02245 check_availability(p, 0); 02246 ast_mutex_unlock(&p->lock); 02247 AST_LIST_UNLOCK(&agents); 02248 ast_device_state_changed("Agent/%s", p->agent); 02249 while (res >= 0) { 02250 ast_mutex_lock(&p->lock); 02251 if (p->deferlogoff && p->chan) { 02252 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 02253 p->deferlogoff = 0; 02254 } 02255 if (p->chan != chan) 02256 res = -1; 02257 ast_mutex_unlock(&p->lock); 02258 /* Yield here so other interested threads can kick in. */ 02259 sched_yield(); 02260 if (res) 02261 break; 02262 02263 AST_LIST_LOCK(&agents); 02264 ast_mutex_lock(&p->lock); 02265 if (p->lastdisc.tv_sec) { 02266 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) { 02267 if (option_debug) 02268 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent); 02269 p->lastdisc = ast_tv(0, 0); 02270 ast_device_state_changed("Agent/%s", p->agent); 02271 if (p->ackcall > 1) 02272 check_beep(p, 0); 02273 else 02274 check_availability(p, 0); 02275 } 02276 } 02277 ast_mutex_unlock(&p->lock); 02278 AST_LIST_UNLOCK(&agents); 02279 /* Synchronize channel ownership between call to agent and itself. */ 02280 ast_mutex_lock(&p->app_lock); 02281 if (p->app_lock_flag == 1) { 02282 ast_cond_wait(&p->app_complete_cond, &p->app_lock); 02283 } 02284 ast_mutex_unlock(&p->app_lock); 02285 ast_mutex_lock(&p->lock); 02286 ast_mutex_unlock(&p->lock); 02287 if (p->ackcall > 1) 02288 res = agent_ack_sleep(p); 02289 else 02290 res = ast_safe_sleep_conditional( chan, 1000, agent_cont_sleep, p ); 02291 if ((p->ackcall > 1) && (res == 1)) { 02292 AST_LIST_LOCK(&agents); 02293 ast_mutex_lock(&p->lock); 02294 check_availability(p, 0); 02295 ast_mutex_unlock(&p->lock); 02296 AST_LIST_UNLOCK(&agents); 02297 res = 0; 02298 } 02299 sched_yield(); 02300 } 02301 ast_mutex_lock(&p->lock); 02302 if (res && p->owner) 02303 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); 02304 /* Log us off if appropriate */ 02305 if (p->chan == chan) { 02306 p->chan = NULL; 02307 p->inherited_devicestate = -1; 02308 } 02309 p->acknowledged = 0; 02310 logintime = time(NULL) - p->loginstart; 02311 p->loginstart = 0; 02312 ast_mutex_unlock(&p->lock); 02313 manager_event(EVENT_FLAG_AGENT, "Agentlogoff", 02314 "Agent: %s\r\n" 02315 "Logintime: %ld\r\n" 02316 "Uniqueid: %s\r\n", 02317 p->agent, logintime, chan->uniqueid); 02318 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); 02319 if (option_verbose > 1) 02320 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent); 02321 /* If there is no owner, go ahead and kill it now */ 02322 ast_device_state_changed("Agent/%s", p->agent); 02323 if (p->dead && !p->owner) { 02324 ast_mutex_destroy(&p->lock); 02325 ast_mutex_destroy(&p->app_lock); 02326 ast_cond_destroy(&p->app_complete_cond); 02327 free(p); 02328 } 02329 } 02330 else { 02331 ast_mutex_unlock(&p->lock); 02332 p = NULL; 02333 } 02334 res = -1; 02335 } else { 02336 ast_mutex_unlock(&p->lock); 02337 errmsg = "agent-alreadyon"; 02338 p = NULL; 02339 } 02340 break; 02341 } 02342 ast_mutex_unlock(&p->lock); 02343 if (unlock_channel) { 02344 ast_channel_unlock(chan); 02345 } 02346 } 02347 if (!p) 02348 AST_LIST_UNLOCK(&agents); 02349 02350 if (!res && (max_login_tries==0 || tries < max_login_tries)) 02351 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); 02352 } 02353 02354 if (!res) 02355 res = ast_safe_sleep(chan, 500); 02356 02357 /* AgentLogin() exit */ 02358 if (!callbackmode) { 02359 ast_module_user_remove(u); 02360 return -1; 02361 } else { /* AgentCallbackLogin() exit*/ 02362 /* Set variables */ 02363 if (login_state > 0) { 02364 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); 02365 if (login_state==1) { 02366 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); 02367 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", args.extension); 02368 } else 02369 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); 02370 } else { 02371 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); 02372 } 02373 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) { 02374 ast_module_user_remove(u); 02375 return 0; 02376 } 02377 /* Do we need to play agent-goodbye now that we will be hanging up? */ 02378 if (play_announcement) { 02379 if (!res) 02380 res = ast_safe_sleep(chan, 1000); 02381 res = ast_streamfile(chan, agent_goodbye, chan->language); 02382 if (!res) 02383 res = ast_waitstream(chan, ""); 02384 if (!res) 02385 res = ast_safe_sleep(chan, 1000); 02386 } 02387 } 02388 02389 ast_module_user_remove(u); 02390 02391 /* We should never get here if next priority exists when in callbackmode */ 02392 return -1; 02393 }
static void __reg_module | ( | void | ) | [static] |
Definition at line 2884 of file chan_agent.c.
static void __unreg_module | ( | void | ) | [static] |
Definition at line 2884 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 2444 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().
02445 { 02446 const char *agent = astman_get_header(m, "Agent"); 02447 const char *exten = astman_get_header(m, "Exten"); 02448 const char *context = astman_get_header(m, "Context"); 02449 const char *wrapuptime_s = astman_get_header(m, "WrapupTime"); 02450 const char *ackcall_s = astman_get_header(m, "AckCall"); 02451 struct agent_pvt *p; 02452 int login_state = 0; 02453 02454 callback_deprecated(); 02455 02456 if (ast_strlen_zero(agent)) { 02457 astman_send_error(s, m, "No agent specified"); 02458 return 0; 02459 } 02460 02461 if (ast_strlen_zero(exten)) { 02462 astman_send_error(s, m, "No extension specified"); 02463 return 0; 02464 } 02465 02466 AST_LIST_LOCK(&agents); 02467 AST_LIST_TRAVERSE(&agents, p, list) { 02468 if (strcmp(p->agent, agent) || p->pending) 02469 continue; 02470 if (p->chan) { 02471 login_state = 2; /* already logged in (and on the phone)*/ 02472 break; 02473 } 02474 ast_mutex_lock(&p->lock); 02475 login_state = 1; /* Successful Login */ 02476 02477 if (ast_strlen_zero(context)) 02478 ast_copy_string(p->loginchan, exten, sizeof(p->loginchan)); 02479 else 02480 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context); 02481 02482 if (!ast_strlen_zero(wrapuptime_s)) { 02483 p->wrapuptime = atoi(wrapuptime_s); 02484 if (p->wrapuptime < 0) 02485 p->wrapuptime = 0; 02486 } 02487 02488 if (!strcasecmp(ackcall_s, "always")) 02489 p->ackcall = 2; 02490 else if (ast_true(ackcall_s)) 02491 p->ackcall = 1; 02492 else 02493 p->ackcall = 0; 02494 02495 if (p->loginstart == 0) 02496 time(&p->loginstart); 02497 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02498 "Agent: %s\r\n" 02499 "Loginchan: %s\r\n", 02500 p->agent, p->loginchan); 02501 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02502 if (option_verbose > 1) 02503 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02504 ast_device_state_changed("Agent/%s", p->agent); 02505 ast_mutex_unlock(&p->lock); 02506 if (persistent_agents) 02507 dump_agents(); 02508 } 02509 AST_LIST_UNLOCK(&agents); 02510 02511 if (login_state == 1) 02512 astman_send_ack(s, m, "Agent logged in"); 02513 else if (login_state == 0) 02514 astman_send_error(s, m, "No such agent"); 02515 else if (login_state == 2) 02516 astman_send_error(s, m, "Agent already logged in"); 02517 02518 return 0; 02519 }
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 1735 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().
01736 { 01737 const char *agent = astman_get_header(m, "Agent"); 01738 const char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */ 01739 int soft; 01740 int ret; /* return value of agent_logoff */ 01741 01742 if (ast_strlen_zero(agent)) { 01743 astman_send_error(s, m, "No agent specified"); 01744 return 0; 01745 } 01746 01747 soft = ast_true(soft_s) ? 1 : 0; 01748 ret = agent_logoff(agent, soft); 01749 if (ret == 0) 01750 astman_send_ack(s, m, "Agent logged out"); 01751 else 01752 astman_send_error(s, m, "No such agent"); 01753 01754 return 0; 01755 }
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 1548 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().
01549 { 01550 const char *id = astman_get_header(m,"ActionID"); 01551 char idText[256] = ""; 01552 char chanbuf[256]; 01553 struct agent_pvt *p; 01554 char *username = NULL; 01555 char *loginChan = NULL; 01556 char *talkingtoChan = NULL; 01557 char *status = NULL; 01558 01559 if (!ast_strlen_zero(id)) 01560 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); 01561 astman_send_ack(s, m, "Agents will follow"); 01562 AST_LIST_LOCK(&agents); 01563 AST_LIST_TRAVERSE(&agents, p, list) { 01564 ast_mutex_lock(&p->lock); 01565 01566 /* Status Values: 01567 AGENT_LOGGEDOFF - Agent isn't logged in 01568 AGENT_IDLE - Agent is logged in, and waiting for call 01569 AGENT_ONCALL - Agent is logged in, and on a call 01570 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */ 01571 01572 username = S_OR(p->name, "None"); 01573 01574 /* Set a default status. It 'should' get changed. */ 01575 status = "AGENT_UNKNOWN"; 01576 01577 if (!ast_strlen_zero(p->loginchan) && !p->chan) { 01578 loginChan = p->loginchan; 01579 talkingtoChan = "n/a"; 01580 status = "AGENT_IDLE"; 01581 if (p->acknowledged) { 01582 snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan); 01583 loginChan = chanbuf; 01584 } 01585 } else if (p->chan) { 01586 loginChan = ast_strdupa(p->chan->name); 01587 if (p->owner && p->owner->_bridge) { 01588 if (ast_bridged_channel(p->owner)) { 01589 talkingtoChan = ast_strdupa(S_OR(ast_bridged_channel(p->owner)->cid.cid_num, "")); 01590 } else { 01591 talkingtoChan = "n/a"; 01592 } 01593 status = "AGENT_ONCALL"; 01594 } else { 01595 talkingtoChan = "n/a"; 01596 status = "AGENT_IDLE"; 01597 } 01598 } else { 01599 loginChan = "n/a"; 01600 talkingtoChan = "n/a"; 01601 status = "AGENT_LOGGEDOFF"; 01602 } 01603 01604 astman_append(s, "Event: Agents\r\n" 01605 "Agent: %s\r\n" 01606 "Name: %s\r\n" 01607 "Status: %s\r\n" 01608 "LoggedInChan: %s\r\n" 01609 "LoggedInTime: %d\r\n" 01610 "TalkingTo: %s\r\n" 01611 "%s" 01612 "\r\n", 01613 p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText); 01614 ast_mutex_unlock(&p->lock); 01615 } 01616 AST_LIST_UNLOCK(&agents); 01617 astman_append(s, "Event: AgentsComplete\r\n" 01618 "%s" 01619 "\r\n",idText); 01620 return 0; 01621 }
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_mutex_init(&p->app_lock); 00388 ast_cond_init(&p->app_complete_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 991 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().
00992 { 00993 struct agent_pvt *p; 00994 int res=0; 00995 int to = 1000; 00996 struct ast_frame *f; 00997 00998 /* Wait a second and look for something */ 00999 01000 p = (struct agent_pvt *) data; 01001 if (!p->chan) 01002 return -1; 01003 01004 for(;;) { 01005 to = ast_waitfor(p->chan, to); 01006 if (to < 0) 01007 return -1; 01008 if (!to) 01009 return 0; 01010 f = ast_read(p->chan); 01011 if (!f) 01012 return -1; 01013 if (f->frametype == AST_FRAME_DTMF) 01014 res = f->subclass; 01015 else 01016 res = 0; 01017 ast_frfree(f); 01018 ast_mutex_lock(&p->lock); 01019 if (!p->app_sleep_cond) { 01020 ast_mutex_unlock(&p->lock); 01021 return 0; 01022 } else if (res == '#') { 01023 ast_mutex_unlock(&p->lock); 01024 return 1; 01025 } 01026 ast_mutex_unlock(&p->lock); 01027 res = 0; 01028 } 01029 return res; 01030 }
static int agent_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 452 of file chan_agent.c.
References ast_log(), and LOG_WARNING.
00453 { 00454 ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n"); 00455 return -1; 00456 }
static struct ast_channel * agent_bridgedchannel | ( | struct ast_channel * | chan, | |
struct ast_channel * | bridge | |||
) | [static] |
Definition at line 1032 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.
01033 { 01034 struct agent_pvt *p = bridge->tech_pvt; 01035 struct ast_channel *ret = NULL; 01036 01037 if (p) { 01038 if (chan == p->chan) 01039 ret = bridge->_bridge; 01040 else if (chan == bridge->_bridge) 01041 ret = p->chan; 01042 } 01043 01044 if (option_debug) 01045 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>"); 01046 return ret; 01047 }
static int agent_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 723 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_NOTICE, 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.
00724 { 00725 struct agent_pvt *p = ast->tech_pvt; 00726 int res = -1; 00727 int newstate=0; 00728 ast_mutex_lock(&p->lock); 00729 p->acknowledged = 0; 00730 if (!p->chan) { 00731 if (p->pending) { 00732 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n"); 00733 newstate = AST_STATE_DIALING; 00734 res = 0; 00735 } else { 00736 ast_log(LOG_NOTICE, "Whoa, they hung up between alloc and call... what are the odds of that?\n"); 00737 res = -1; 00738 } 00739 ast_mutex_unlock(&p->lock); 00740 if (newstate) 00741 ast_setstate(ast, newstate); 00742 return res; 00743 } else if (!ast_strlen_zero(p->loginchan)) { 00744 time(&p->start); 00745 /* Call on this agent */ 00746 if (option_verbose > 2) 00747 ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name); 00748 ast_set_callerid(p->chan, 00749 ast->cid.cid_num, ast->cid.cid_name, NULL); 00750 ast_channel_inherit_variables(ast, p->chan); 00751 res = ast_call(p->chan, p->loginchan, 0); 00752 CLEANUP(ast,p); 00753 ast_mutex_unlock(&p->lock); 00754 return res; 00755 } 00756 if (option_verbose > 2) 00757 ast_verbose(VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name); 00758 if (option_debug > 2) 00759 ast_log(LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language); 00760 res = ast_streamfile(p->chan, beep, p->chan->language); 00761 if (option_debug > 2) 00762 ast_log(LOG_DEBUG, "Played beep, result '%d'\n", res); 00763 if (!res) { 00764 res = ast_waitstream(p->chan, ""); 00765 if (option_debug > 2) 00766 ast_log(LOG_DEBUG, "Waited for stream, result '%d'\n", res); 00767 } 00768 if (!res) { 00769 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00770 if (option_debug > 2) 00771 ast_log(LOG_DEBUG, "Set read format, result '%d'\n", res); 00772 if (res) 00773 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00774 } else { 00775 /* Agent hung-up */ 00776 p->chan = NULL; 00777 p->inherited_devicestate = -1; 00778 ast_device_state_changed("Agent/%s", p->agent); 00779 } 00780 00781 if (!res) { 00782 res = ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00783 if (option_debug > 2) 00784 ast_log(LOG_DEBUG, "Set write format, result '%d'\n", res); 00785 if (res) 00786 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00787 } 00788 if(!res) { 00789 /* Call is immediately up, or might need ack */ 00790 if (p->ackcall > 1) 00791 newstate = AST_STATE_RINGING; 00792 else { 00793 newstate = AST_STATE_UP; 00794 if (recordagentcalls) 00795 agent_start_monitoring(ast, 0); 00796 p->acknowledged = 1; 00797 } 00798 res = 0; 00799 } 00800 CLEANUP(ast, p); 00801 ast_mutex_unlock(&p->lock); 00802 if (newstate) 00803 ast_setstate(ast, newstate); 00804 return res; 00805 }
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, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_channel_free(), ast_cond_destroy(), ast_cond_signal(), ast_mutex_destroy(), agent_pvt::chan, agent_pvt::dead, free, agent_pvt::lock, agent_pvt::owner, and ast_channel::tech_pvt.
Referenced by check_availability().
00431 { 00432 struct ast_channel *chan = p->owner; 00433 p->owner = NULL; 00434 chan->tech_pvt = NULL; 00435 p->app_sleep_cond = 1; 00436 /* Release ownership of the agent to other threads (presumably running the login app). */ 00437 p->app_lock_flag = 0; 00438 ast_cond_signal(&p->app_complete_cond); 00439 if (chan) 00440 ast_channel_free(chan); 00441 if (p->dead) { 00442 ast_mutex_destroy(&p->lock); 00443 ast_mutex_destroy(&p->app_lock); 00444 ast_cond_destroy(&p->app_complete_cond); 00445 free(p); 00446 } 00447 return 0; 00448 }
static int agent_cont_sleep | ( | void * | data | ) | [static] |
Definition at line 970 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().
00971 { 00972 struct agent_pvt *p; 00973 int res; 00974 00975 p = (struct agent_pvt *)data; 00976 00977 ast_mutex_lock(&p->lock); 00978 res = p->app_sleep_cond; 00979 if (p->lastdisc.tv_sec) { 00980 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0) 00981 res = 1; 00982 } 00983 ast_mutex_unlock(&p->lock); 00984 00985 if(option_debug > 4 && !res ) 00986 ast_log(LOG_DEBUG, "agent_cont_sleep() returning %d\n", res ); 00987 00988 return res; 00989 }
static int agent_devicestate | ( | void * | data | ) | [static] |
Part of PBX channel interface.
Definition at line 2665 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.
02666 { 02667 struct agent_pvt *p; 02668 char *s; 02669 ast_group_t groupmatch; 02670 int groupoff; 02671 int waitforagent=0; 02672 int res = AST_DEVICE_INVALID; 02673 02674 s = data; 02675 if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) 02676 groupmatch = (1 << groupoff); 02677 else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 02678 groupmatch = (1 << groupoff); 02679 waitforagent = 1; 02680 } else 02681 groupmatch = 0; 02682 02683 /* Check actual logged in agents first */ 02684 AST_LIST_LOCK(&agents); 02685 AST_LIST_TRAVERSE(&agents, p, list) { 02686 ast_mutex_lock(&p->lock); 02687 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 02688 if (p->owner) { 02689 if (res != AST_DEVICE_INUSE) 02690 res = AST_DEVICE_BUSY; 02691 } else if (p->inherited_devicestate > -1) { 02692 res = p->inherited_devicestate; 02693 } else { 02694 if (res == AST_DEVICE_BUSY) 02695 res = AST_DEVICE_INUSE; 02696 if (p->chan || !ast_strlen_zero(p->loginchan)) { 02697 if (res == AST_DEVICE_INVALID) 02698 res = AST_DEVICE_UNKNOWN; 02699 } else if (res == AST_DEVICE_INVALID) 02700 res = AST_DEVICE_UNAVAILABLE; 02701 } 02702 if (!strcmp(data, p->agent)) { 02703 ast_mutex_unlock(&p->lock); 02704 break; 02705 } 02706 } 02707 ast_mutex_unlock(&p->lock); 02708 } 02709 AST_LIST_UNLOCK(&agents); 02710 return res; 02711 }
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 701 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.
00702 { 00703 struct agent_pvt *p = ast->tech_pvt; 00704 ast_mutex_lock(&p->lock); 00705 if (p->chan) { 00706 ast_senddigit_begin(p->chan, digit); 00707 } 00708 ast_mutex_unlock(&p->lock); 00709 return 0; 00710 }
static int agent_digit_end | ( | struct ast_channel * | ast, | |
char | digit, | |||
unsigned int | duration | |||
) | [static] |
Definition at line 712 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.
00713 { 00714 struct agent_pvt *p = ast->tech_pvt; 00715 ast_mutex_lock(&p->lock); 00716 if (p->chan) { 00717 ast_senddigit_end(p->chan, digit, duration); 00718 } 00719 ast_mutex_unlock(&p->lock); 00720 return 0; 00721 }
static int agent_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 668 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.
00669 { 00670 struct agent_pvt *p = newchan->tech_pvt; 00671 ast_mutex_lock(&p->lock); 00672 if (p->owner != oldchan) { 00673 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 00674 ast_mutex_unlock(&p->lock); 00675 return -1; 00676 } 00677 p->owner = newchan; 00678 ast_mutex_unlock(&p->lock); 00679 return 0; 00680 }
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 821 of file chan_agent.c.
References ast_log(), agent_pvt::chan, LOG_ERROR, and ast_channel::tech_pvt.
00822 { 00823 struct agent_pvt *p = NULL; 00824 struct ast_channel *base = chan; 00825 00826 /* chan is locked by the calling function */ 00827 if (!chan || !chan->tech_pvt) { 00828 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); 00829 return NULL; 00830 } 00831 p = chan->tech_pvt; 00832 if (p->chan) 00833 base = p->chan; 00834 return base; 00835 }
static int agent_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 854 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, 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::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.
00855 { 00856 struct agent_pvt *p = ast->tech_pvt; 00857 int howlong = 0; 00858 const char *status; 00859 ast_mutex_lock(&p->lock); 00860 p->owner = NULL; 00861 ast->tech_pvt = NULL; 00862 p->app_sleep_cond = 1; 00863 p->acknowledged = 0; 00864 00865 /* if they really are hung up then set start to 0 so the test 00866 * later if we're called on an already downed channel 00867 * doesn't cause an agent to be logged out like when 00868 * agent_request() is followed immediately by agent_hangup() 00869 * as in apps/app_chanisavail.c:chanavail_exec() 00870 */ 00871 00872 if (option_debug) 00873 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state)); 00874 if (p->start && (ast->_state != AST_STATE_UP)) { 00875 howlong = time(NULL) - p->start; 00876 p->start = 0; 00877 } else if (ast->_state == AST_STATE_RESERVED) 00878 howlong = 0; 00879 else 00880 p->start = 0; 00881 if (p->chan) { 00882 p->chan->_bridge = NULL; 00883 /* If they're dead, go ahead and hang up on the agent now */ 00884 if (!ast_strlen_zero(p->loginchan)) { 00885 /* Store last disconnect time */ 00886 if (p->wrapuptime) 00887 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00888 else 00889 p->lastdisc = ast_tv(0,0); 00890 if (p->chan) { 00891 status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); 00892 if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { 00893 long logintime = time(NULL) - p->loginstart; 00894 p->loginstart = 0; 00895 ast_log(LOG_NOTICE, "Agent hangup: '%s' is not available now, auto logoff\n", p->name); 00896 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail"); 00897 } 00898 /* Recognize the hangup and pass it along immediately */ 00899 ast_hangup(p->chan); 00900 p->chan = NULL; 00901 p->inherited_devicestate = -1; 00902 ast_device_state_changed("Agent/%s", p->agent); 00903 } 00904 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff); 00905 if ((p->deferlogoff) || (howlong && p->autologoff && (howlong > p->autologoff))) { 00906 long logintime = time(NULL) - p->loginstart; 00907 p->loginstart = 0; 00908 if (!p->deferlogoff) 00909 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00910 p->deferlogoff = 0; 00911 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Autologoff"); 00912 if (persistent_agents) 00913 dump_agents(); 00914 } 00915 } else if (p->dead) { 00916 ast_channel_lock(p->chan); 00917 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 00918 ast_channel_unlock(p->chan); 00919 } else if (p->loginstart) { 00920 ast_channel_lock(p->chan); 00921 ast_indicate_data(p->chan, AST_CONTROL_HOLD, 00922 S_OR(p->moh, NULL), 00923 !ast_strlen_zero(p->moh) ? strlen(p->moh) + 1 : 0); 00924 ast_channel_unlock(p->chan); 00925 } 00926 } 00927 ast_mutex_unlock(&p->lock); 00928 00929 /* Only register a device state change if the agent is still logged in */ 00930 if (!p->loginstart) { 00931 p->loginchan[0] = '\0'; 00932 p->logincallerid[0] = '\0'; 00933 if (persistent_agents) 00934 dump_agents(); 00935 } else { 00936 ast_device_state_changed("Agent/%s", p->agent); 00937 } 00938 00939 if (p->pending) { 00940 AST_LIST_LOCK(&agents); 00941 AST_LIST_REMOVE(&agents, p, list); 00942 AST_LIST_UNLOCK(&agents); 00943 } 00944 if (p->abouttograb) { 00945 /* Let the "about to grab" thread know this isn't valid anymore, and let it 00946 kill it later */ 00947 p->abouttograb = 0; 00948 } else if (p->dead) { 00949 ast_mutex_destroy(&p->lock); 00950 ast_mutex_destroy(&p->app_lock); 00951 ast_cond_destroy(&p->app_complete_cond); 00952 free(p); 00953 } else { 00954 if (p->chan) { 00955 /* Not dead -- check availability now */ 00956 ast_mutex_lock(&p->lock); 00957 /* Store last disconnect time */ 00958 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00959 ast_mutex_unlock(&p->lock); 00960 } 00961 /* Release ownership of the agent to other threads (presumably running the login app). */ 00962 if (ast_strlen_zero(p->loginchan)) { 00963 p->app_lock_flag = 0; 00964 ast_cond_signal(&p->app_complete_cond); 00965 } 00966 } 00967 return 0; 00968 }
static int agent_indicate | ( | struct ast_channel * | ast, | |
int | condition, | |||
const void * | data, | |||
size_t | datalen | |||
) | [static] |
Definition at line 682 of file chan_agent.c.
References ast_channel_lock, ast_channel_trylock, ast_channel_unlock, ast_check_hangup(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, ast_channel_tech::indicate, agent_pvt::lock, ast_channel::tech, and ast_channel::tech_pvt.
00683 { 00684 struct agent_pvt *p = ast->tech_pvt; 00685 int res = -1; 00686 ast_mutex_lock(&p->lock); 00687 if (p->chan && !ast_check_hangup(p->chan)) { 00688 while (ast_channel_trylock(p->chan)) { 00689 ast_channel_unlock(ast); 00690 usleep(1); 00691 ast_channel_lock(ast); 00692 } 00693 res = p->chan->tech->indicate ? p->chan->tech->indicate(p->chan, condition, data, datalen) : -1; 00694 ast_channel_unlock(p->chan); 00695 } else 00696 res = 0; 00697 ast_mutex_unlock(&p->lock); 00698 return res; 00699 }
static int agent_logoff | ( | const char * | agent, | |
int | soft | |||
) | [static] |
Definition at line 1663 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(), agent_logoff_cmd(), and agent_read().
01664 { 01665 struct agent_pvt *p; 01666 long logintime; 01667 int ret = -1; /* Return -1 if no agent if found */ 01668 01669 AST_LIST_LOCK(&agents); 01670 AST_LIST_TRAVERSE(&agents, p, list) { 01671 if (!strcasecmp(p->agent, agent)) { 01672 ret = 0; 01673 if (p->owner || p->chan) { 01674 if (!soft) { 01675 ast_mutex_lock(&p->lock); 01676 01677 while (p->owner && ast_channel_trylock(p->owner)) { 01678 DEADLOCK_AVOIDANCE(&p->lock); 01679 } 01680 if (p->owner) { 01681 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 01682 ast_channel_unlock(p->owner); 01683 } 01684 01685 while (p->chan && ast_channel_trylock(p->chan)) { 01686 DEADLOCK_AVOIDANCE(&p->lock); 01687 } 01688 if (p->chan) { 01689 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01690 ast_channel_unlock(p->chan); 01691 } 01692 01693 ast_mutex_unlock(&p->lock); 01694 } else 01695 p->deferlogoff = 1; 01696 } else { 01697 logintime = time(NULL) - p->loginstart; 01698 p->loginstart = 0; 01699 agent_logoff_maintenance(p, p->loginchan, logintime, NULL, "CommandLogoff"); 01700 } 01701 break; 01702 } 01703 } 01704 AST_LIST_UNLOCK(&agents); 01705 01706 return ret; 01707 }
static int agent_logoff_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1709 of file chan_agent.c.
References agent_pvt::agent, agent_logoff(), ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01710 { 01711 int ret; 01712 char *agent; 01713 01714 if (argc < 3 || argc > 4) 01715 return RESULT_SHOWUSAGE; 01716 if (argc == 4 && strcasecmp(argv[3], "soft")) 01717 return RESULT_SHOWUSAGE; 01718 01719 agent = argv[2] + 6; 01720 ret = agent_logoff(agent, argc == 4); 01721 if (ret == 0) 01722 ast_cli(fd, "Logging out %s\n", agent); 01723 01724 return RESULT_SUCCESS; 01725 }
static void agent_logoff_maintenance | ( | struct agent_pvt * | p, | |
char * | loginchan, | |||
long | logintime, | |||
const char * | uniqueid, | |||
char * | logcommand | |||
) | [static] |
Definition at line 1623 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().
01624 { 01625 char *tmp = NULL; 01626 char agent[AST_MAX_AGENT]; 01627 01628 if (!ast_strlen_zero(logcommand)) 01629 tmp = logcommand; 01630 else 01631 tmp = ast_strdupa(""); 01632 01633 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 01634 01635 if (!ast_strlen_zero(uniqueid)) { 01636 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01637 "Agent: %s\r\n" 01638 "Reason: %s\r\n" 01639 "Loginchan: %s\r\n" 01640 "Logintime: %ld\r\n" 01641 "Uniqueid: %s\r\n", 01642 p->agent, tmp, loginchan, logintime, uniqueid); 01643 } else { 01644 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01645 "Agent: %s\r\n" 01646 "Reason: %s\r\n" 01647 "Loginchan: %s\r\n" 01648 "Logintime: %ld\r\n", 01649 p->agent, tmp, loginchan, logintime); 01650 } 01651 01652 ast_queue_log("NONE", ast_strlen_zero(uniqueid) ? "NONE" : uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", loginchan, logintime, tmp); 01653 set_agentbycallerid(p->logincallerid, NULL); 01654 p->loginchan[0] ='\0'; 01655 p->logincallerid[0] = '\0'; 01656 p->inherited_devicestate = -1; 01657 ast_device_state_changed("Agent/%s", p->agent); 01658 if (persistent_agents) 01659 dump_agents(); 01660 01661 }
static struct ast_channel* agent_new | ( | struct agent_pvt * | p, | |
int | state | |||
) | [static] |
Create new agent channel.
Definition at line 1050 of file chan_agent.c.
References agent_pvt::agent, agent_tech, agent_pvt::app_complete_cond, agent_pvt::app_lock_flag, agent_pvt::app_sleep_cond, ast_atomic_fetchadd_int(), ast_channel_alloc(), ast_channel_free(), ast_cond_signal(), AST_CONTROL_UNHOLD, ast_copy_string(), AST_FORMAT_SLINEAR, ast_indicate(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_null_frame, ast_queue_frame(), ast_random(), ast_string_field_set, ast_strlen_zero(), ast_update_use_count(), agent_pvt::chan, ast_channel::context, ast_channel::exten, ast_channel::language, language, agent_pvt::lock, LOG_WARNING, agent_pvt::loginchan, 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().
01051 { 01052 struct ast_channel *tmp; 01053 int alreadylocked; 01054 #if 0 01055 if (!p->chan) { 01056 ast_log(LOG_WARNING, "No channel? :(\n"); 01057 return NULL; 01058 } 01059 #endif 01060 if (p->pending) 01061 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); 01062 else 01063 tmp = ast_channel_alloc(0, state, 0, 0, "", p->chan ? p->chan->exten:"", p->chan ? p->chan->context:"", 0, "Agent/%s", p->agent); 01064 if (!tmp) { 01065 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); 01066 return NULL; 01067 } 01068 01069 tmp->tech = &agent_tech; 01070 if (p->chan) { 01071 tmp->nativeformats = p->chan->nativeformats; 01072 tmp->writeformat = p->chan->writeformat; 01073 tmp->rawwriteformat = p->chan->writeformat; 01074 tmp->readformat = p->chan->readformat; 01075 tmp->rawreadformat = p->chan->readformat; 01076 ast_string_field_set(tmp, language, p->chan->language); 01077 ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); 01078 ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); 01079 /* XXX Is this really all we copy form the originating channel?? */ 01080 } else { 01081 tmp->nativeformats = AST_FORMAT_SLINEAR; 01082 tmp->writeformat = AST_FORMAT_SLINEAR; 01083 tmp->rawwriteformat = AST_FORMAT_SLINEAR; 01084 tmp->readformat = AST_FORMAT_SLINEAR; 01085 tmp->rawreadformat = AST_FORMAT_SLINEAR; 01086 } 01087 /* Safe, agentlock already held */ 01088 tmp->tech_pvt = p; 01089 p->owner = tmp; 01090 /* XXX: this needs fixing */ 01091 #if 0 01092 ast_atomic_fetchadd_int(&__mod_desc->usecnt, +1); 01093 #endif 01094 ast_update_use_count(); 01095 tmp->priority = 1; 01096 /* Wake up and wait for other applications (by definition the login app) 01097 * to release this channel). Takes ownership of the agent channel 01098 * to this thread only. 01099 * For signalling the other thread, ast_queue_frame is used until we 01100 * can safely use signals for this purpose. The pselect() needs to be 01101 * implemented in the kernel for this. 01102 */ 01103 p->app_sleep_cond = 0; 01104 01105 alreadylocked = p->app_lock_flag; 01106 p->app_lock_flag = 1; 01107 01108 if(ast_strlen_zero(p->loginchan) && alreadylocked) { 01109 if (p->chan) { 01110 ast_queue_frame(p->chan, &ast_null_frame); 01111 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 01112 p->app_lock_flag = 1; 01113 ast_mutex_lock(&p->lock); 01114 } else { 01115 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 01116 p->owner = NULL; 01117 tmp->tech_pvt = NULL; 01118 p->app_sleep_cond = 1; 01119 ast_channel_free( tmp ); 01120 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 01121 p->app_lock_flag = 0; 01122 ast_cond_signal(&p->app_complete_cond); 01123 return NULL; 01124 } 01125 } else if (!ast_strlen_zero(p->loginchan)) { 01126 if (p->chan) 01127 ast_queue_frame(p->chan, &ast_null_frame); 01128 if (!p->chan) { 01129 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 01130 p->owner = NULL; 01131 tmp->tech_pvt = NULL; 01132 p->app_sleep_cond = 1; 01133 ast_channel_free( tmp ); 01134 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 01135 return NULL; 01136 } 01137 } 01138 if (p->chan) 01139 ast_indicate(p->chan, AST_CONTROL_UNHOLD); 01140 return tmp; 01141 }
static struct ast_frame * agent_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 491 of file chan_agent.c.
References ast_channel::_bridge, ast_channel::_state, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_logoff(), agent_logoff_maintenance(), agent_start_monitoring(), AST_AGENT_FD, 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_STATE_UP, ast_strlen_zero(), AST_TIMING_FD, ast_tvadd(), ast_tvnow(), ast_verbose(), agent_pvt::autologoff, agent_pvt::chan, CHECK_FORMATS, CLEANUP, 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.
00492 { 00493 struct agent_pvt *p = ast->tech_pvt; 00494 struct ast_frame *f = NULL; 00495 static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00496 const char *status; 00497 int cur_time = time(NULL); 00498 ast_mutex_lock(&p->lock); 00499 CHECK_FORMATS(ast, p); 00500 if (!p->start) { 00501 p->start = cur_time; 00502 } 00503 if (p->chan) { 00504 ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION); 00505 p->chan->fdno = (ast->fdno == AST_AGENT_FD) ? AST_TIMING_FD : ast->fdno; 00506 f = ast_read(p->chan); 00507 } else 00508 f = &ast_null_frame; 00509 if (!f) { 00510 /* If there's a channel, hang it up (if it's on a callback) make it NULL */ 00511 if (p->chan) { 00512 p->chan->_bridge = NULL; 00513 /* Note that we don't hangup if it's not a callback because Asterisk will do it 00514 for us when the PBX instance that called login finishes */ 00515 if (!ast_strlen_zero(p->loginchan)) { 00516 if (p->chan) 00517 ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name); 00518 if (p->owner->_state != AST_STATE_UP) { 00519 int howlong = cur_time - p->start; 00520 if (p->autologoff && howlong >= p->autologoff) { 00521 p->loginstart = 0; 00522 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00523 agent_logoff_maintenance(p, p->loginchan, (cur_time = p->loginstart), ast->uniqueid, "Autologoff"); 00524 } 00525 } 00526 status = pbx_builtin_getvar_helper(p->chan, "CHANLOCALSTATUS"); 00527 if (autologoffunavail && status && !strcasecmp(status, "CHANUNAVAIL")) { 00528 long logintime = cur_time - p->loginstart; 00529 p->loginstart = 0; 00530 ast_log(LOG_NOTICE, "Agent read: '%s' is not available now, auto logoff\n", p->name); 00531 agent_logoff_maintenance(p, p->loginchan, logintime, ast->uniqueid, "Chanunavail"); 00532 } 00533 ast_hangup(p->chan); 00534 if (p->wrapuptime && p->acknowledged) 00535 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00536 } 00537 p->chan = NULL; 00538 p->inherited_devicestate = -1; 00539 ast_device_state_changed("Agent/%s", p->agent); 00540 p->acknowledged = 0; 00541 } 00542 } else { 00543 /* if acknowledgement is not required, and the channel is up, we may have missed 00544 an AST_CONTROL_ANSWER (if there was one), so mark the call acknowledged anyway */ 00545 if (!p->ackcall && !p->acknowledged && p->chan && (p->chan->_state == AST_STATE_UP)) { 00546 p->acknowledged = 1; 00547 } 00548 if (!p->acknowledged) { 00549 int howlong = cur_time - p->start; 00550 if (p->autologoff && (howlong >= p->autologoff)) { 00551 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00552 agent_logoff_maintenance(p, p->loginchan, (cur_time - p->loginstart), ast->uniqueid, "Autologoff"); 00553 agent_logoff(p->agent, 0); 00554 } 00555 } 00556 switch (f->frametype) { 00557 case AST_FRAME_CONTROL: 00558 if (f->subclass == AST_CONTROL_ANSWER) { 00559 if (p->ackcall) { 00560 if (option_verbose > 2) 00561 ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name); 00562 /* Don't pass answer along */ 00563 ast_frfree(f); 00564 f = &ast_null_frame; 00565 } else { 00566 p->acknowledged = 1; 00567 /* Use the builtin answer frame for the 00568 recording start check below. */ 00569 ast_frfree(f); 00570 f = &answer_frame; 00571 } 00572 } 00573 break; 00574 case AST_FRAME_DTMF_BEGIN: 00575 /*ignore DTMF begin's as it can cause issues with queue announce files*/ 00576 if((!p->acknowledged && f->subclass == '#') || (f->subclass == '*' && endcall)){ 00577 ast_frfree(f); 00578 f = &ast_null_frame; 00579 } 00580 break; 00581 case AST_FRAME_DTMF_END: 00582 if (!p->acknowledged && (f->subclass == '#')) { 00583 if (option_verbose > 2) 00584 ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); 00585 p->acknowledged = 1; 00586 ast_frfree(f); 00587 f = &answer_frame; 00588 } else if (f->subclass == '*' && endcall) { 00589 /* terminates call */ 00590 ast_frfree(f); 00591 f = NULL; 00592 } 00593 break; 00594 case AST_FRAME_VOICE: 00595 case AST_FRAME_VIDEO: 00596 /* don't pass voice or video until the call is acknowledged */ 00597 if (!p->acknowledged) { 00598 ast_frfree(f); 00599 f = &ast_null_frame; 00600 } 00601 default: 00602 /* pass everything else on through */ 00603 break; 00604 } 00605 } 00606 00607 CLEANUP(ast,p); 00608 if (p->chan && !p->chan->_bridge) { 00609 if (strcasecmp(p->chan->tech->type, "Local")) { 00610 p->chan->_bridge = ast; 00611 if (p->chan) 00612 ast_log(LOG_DEBUG, "Bridge on '%s' being set to '%s' (3)\n", p->chan->name, p->chan->_bridge->name); 00613 } 00614 } 00615 ast_mutex_unlock(&p->lock); 00616 if (recordagentcalls && f == &answer_frame) 00617 agent_start_monitoring(ast,0); 00618 return f; 00619 }
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 1435 of file chan_agent.c.
References add_agent(), agent_pvt::agent, agent_new(), AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), 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::loginchan, option_debug, agent_pvt::owner, agent_pvt::pending, and s.
01436 { 01437 struct agent_pvt *p; 01438 struct ast_channel *chan = NULL; 01439 char *s; 01440 ast_group_t groupmatch; 01441 int groupoff; 01442 int waitforagent=0; 01443 int hasagent = 0; 01444 struct timeval tv; 01445 01446 s = data; 01447 if ((s[0] == '@') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 01448 groupmatch = (1 << groupoff); 01449 } else if ((s[0] == ':') && (sscanf(s + 1, "%30d", &groupoff) == 1)) { 01450 groupmatch = (1 << groupoff); 01451 waitforagent = 1; 01452 } else 01453 groupmatch = 0; 01454 01455 /* Check actual logged in agents first */ 01456 AST_LIST_LOCK(&agents); 01457 AST_LIST_TRAVERSE(&agents, p, list) { 01458 ast_mutex_lock(&p->lock); 01459 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) && 01460 ast_strlen_zero(p->loginchan)) { 01461 if (p->chan) 01462 hasagent++; 01463 tv = ast_tvnow(); 01464 if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) { 01465 p->lastdisc = ast_tv(0, 0); 01466 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01467 if (!p->owner && p->chan) { 01468 /* Fixed agent */ 01469 chan = agent_new(p, AST_STATE_DOWN); 01470 } 01471 if (chan) { 01472 ast_mutex_unlock(&p->lock); 01473 break; 01474 } 01475 } 01476 } 01477 ast_mutex_unlock(&p->lock); 01478 } 01479 if (!p) { 01480 AST_LIST_TRAVERSE(&agents, p, list) { 01481 ast_mutex_lock(&p->lock); 01482 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 01483 if (p->chan || !ast_strlen_zero(p->loginchan)) 01484 hasagent++; 01485 tv = ast_tvnow(); 01486 #if 0 01487 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec); 01488 #endif 01489 if (!p->lastdisc.tv_sec || (tv.tv_sec >= p->lastdisc.tv_sec)) { 01490 p->lastdisc = ast_tv(0, 0); 01491 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01492 if (!p->owner && p->chan) { 01493 /* Could still get a fixed agent */ 01494 chan = agent_new(p, AST_STATE_DOWN); 01495 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { 01496 /* Adjustable agent */ 01497 p->chan = ast_request("Local", format, p->loginchan, cause); 01498 if (p->chan) 01499 chan = agent_new(p, AST_STATE_DOWN); 01500 } 01501 if (chan) { 01502 ast_mutex_unlock(&p->lock); 01503 break; 01504 } 01505 } 01506 } 01507 ast_mutex_unlock(&p->lock); 01508 } 01509 } 01510 01511 if (!chan && waitforagent) { 01512 /* No agent available -- but we're requesting to wait for one. 01513 Allocate a place holder */ 01514 if (hasagent) { 01515 if (option_debug) 01516 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s); 01517 p = add_agent(data, 1); 01518 p->group = groupmatch; 01519 chan = agent_new(p, AST_STATE_DOWN); 01520 if (!chan) 01521 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); 01522 } else 01523 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); 01524 } 01525 *cause = hasagent ? AST_CAUSE_BUSY : AST_CAUSE_UNREGISTERED; 01526 AST_LIST_UNLOCK(&agents); 01527 return chan; 01528 }
static int agent_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 621 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.
00622 { 00623 struct agent_pvt *p = ast->tech_pvt; 00624 int res = -1; 00625 ast_mutex_lock(&p->lock); 00626 if (p->chan) 00627 res = ast_channel_sendhtml(p->chan, subclass, data, datalen); 00628 ast_mutex_unlock(&p->lock); 00629 return res; 00630 }
static int agent_sendtext | ( | struct ast_channel * | ast, | |
const char * | text | |||
) | [static] |
Definition at line 632 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.
00633 { 00634 struct agent_pvt *p = ast->tech_pvt; 00635 int res = -1; 00636 ast_mutex_lock(&p->lock); 00637 if (p->chan) 00638 res = ast_sendtext(p->chan, text); 00639 ast_mutex_unlock(&p->lock); 00640 return res; 00641 }
int agent_set_base_channel | ( | struct ast_channel * | chan, | |
struct ast_channel * | base | |||
) | [static] |
Definition at line 837 of file chan_agent.c.
References ast_log(), agent_pvt::chan, LOG_ERROR, ast_channel::name, and ast_channel::tech_pvt.
00838 { 00839 struct agent_pvt *p = NULL; 00840 00841 if (!chan || !base) { 00842 ast_log(LOG_ERROR, "whoa, you need a channel (0x%ld) and a base channel (0x%ld) for setting.\n", (long)chan, (long)base); 00843 return -1; 00844 } 00845 p = chan->tech_pvt; 00846 if (!p) { 00847 ast_log(LOG_ERROR, "whoa, channel %s is missing his tech_pvt structure!!.\n", chan->name); 00848 return -1; 00849 } 00850 p->chan = base; 00851 return 0; 00852 }
static int agent_start_monitoring | ( | struct ast_channel * | ast, | |
int | needlock | |||
) | [static] |
Definition at line 486 of file chan_agent.c.
References __agent_start_monitoring(), and ast_channel::tech_pvt.
Referenced by agent_call(), and agent_read().
00487 { 00488 return __agent_start_monitoring(ast, ast->tech_pvt, needlock); 00489 }
static int agent_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 643 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.
00644 { 00645 struct agent_pvt *p = ast->tech_pvt; 00646 int res = -1; 00647 CHECK_FORMATS(ast, p); 00648 ast_mutex_lock(&p->lock); 00649 if (!p->chan) 00650 res = 0; 00651 else { 00652 if ((f->frametype != AST_FRAME_VOICE) || 00653 (f->frametype != AST_FRAME_VIDEO) || 00654 (f->subclass == p->chan->writeformat)) { 00655 res = ast_write(p->chan, f); 00656 } else { 00657 ast_log(LOG_DEBUG, "Dropping one incompatible %s frame on '%s' to '%s'\n", 00658 f->frametype == AST_FRAME_VOICE ? "audio" : "video", 00659 ast->name, p->chan->name); 00660 res = 0; 00661 } 00662 } 00663 CLEANUP(ast, p); 00664 ast_mutex_unlock(&p->lock); 00665 return res; 00666 }
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 2529 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().
02530 { 02531 int exitifnoagentid = 0; 02532 int nowarnings = 0; 02533 int changeoutgoing = 0; 02534 int res = 0; 02535 char agent[AST_MAX_AGENT]; 02536 02537 if (data) { 02538 if (strchr(data, 'd')) 02539 exitifnoagentid = 1; 02540 if (strchr(data, 'n')) 02541 nowarnings = 1; 02542 if (strchr(data, 'c')) 02543 changeoutgoing = 1; 02544 } 02545 if (chan->cid.cid_num) { 02546 const char *tmp; 02547 char agentvar[AST_MAX_BUF]; 02548 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num); 02549 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) { 02550 struct agent_pvt *p; 02551 ast_copy_string(agent, tmp, sizeof(agent)); 02552 AST_LIST_LOCK(&agents); 02553 AST_LIST_TRAVERSE(&agents, p, list) { 02554 if (!strcasecmp(p->agent, tmp)) { 02555 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02556 __agent_start_monitoring(chan, p, 1); 02557 break; 02558 } 02559 } 02560 AST_LIST_UNLOCK(&agents); 02561 02562 } else { 02563 res = -1; 02564 if (!nowarnings) 02565 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); 02566 } 02567 } else { 02568 res = -1; 02569 if (!nowarnings) 02570 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"); 02571 } 02572 /* check if there is n + 101 priority */ 02573 /*! \todo XXX Needs to check option priorityjump etc etc */ 02574 if (res) { 02575 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) { 02576 chan->priority+=100; 02577 if (option_verbose > 2) 02578 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority); 02579 } else if (exitifnoagentid) 02580 return res; 02581 } 02582 return 0; 02583 }
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 1784 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.
01785 { 01786 struct agent_pvt *p; 01787 char username[AST_MAX_BUF]; 01788 char location[AST_MAX_BUF] = ""; 01789 char talkingto[AST_MAX_BUF] = ""; 01790 char moh[AST_MAX_BUF]; 01791 int count_agents = 0; /*!< Number of agents configured */ 01792 int online_agents = 0; /*!< Number of online agents */ 01793 int offline_agents = 0; /*!< Number of offline agents */ 01794 if (argc != 2) 01795 return RESULT_SHOWUSAGE; 01796 AST_LIST_LOCK(&agents); 01797 AST_LIST_TRAVERSE(&agents, p, list) { 01798 ast_mutex_lock(&p->lock); 01799 if (p->pending) { 01800 if (p->group) 01801 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group)); 01802 else 01803 ast_cli(fd, "-- Pending call to agent %s\n", p->agent); 01804 } else { 01805 if (!ast_strlen_zero(p->name)) 01806 snprintf(username, sizeof(username), "(%s) ", p->name); 01807 else 01808 username[0] = '\0'; 01809 if (p->chan) { 01810 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01811 if (p->owner && ast_bridged_channel(p->owner)) 01812 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01813 else 01814 strcpy(talkingto, " is idle"); 01815 online_agents++; 01816 } else if (!ast_strlen_zero(p->loginchan)) { 01817 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec)) 01818 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01819 else 01820 snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan); 01821 talkingto[0] = '\0'; 01822 online_agents++; 01823 if (p->acknowledged) 01824 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01825 } else { 01826 strcpy(location, "not logged in"); 01827 talkingto[0] = '\0'; 01828 offline_agents++; 01829 } 01830 if (!ast_strlen_zero(p->moh)) 01831 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01832 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, 01833 username, location, talkingto, moh); 01834 count_agents++; 01835 } 01836 ast_mutex_unlock(&p->lock); 01837 } 01838 AST_LIST_UNLOCK(&agents); 01839 if ( !count_agents ) 01840 ast_cli(fd, "No Agents are configured in %s\n",config); 01841 else 01842 ast_cli(fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents); 01843 ast_cli(fd, "\n"); 01844 01845 return RESULT_SUCCESS; 01846 }
static int agents_show_online | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1849 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.
01850 { 01851 struct agent_pvt *p; 01852 char username[AST_MAX_BUF]; 01853 char location[AST_MAX_BUF] = ""; 01854 char talkingto[AST_MAX_BUF] = ""; 01855 char moh[AST_MAX_BUF]; 01856 int count_agents = 0; /* Number of agents configured */ 01857 int online_agents = 0; /* Number of online agents */ 01858 int agent_status = 0; /* 0 means offline, 1 means online */ 01859 if (argc != 3) 01860 return RESULT_SHOWUSAGE; 01861 AST_LIST_LOCK(&agents); 01862 AST_LIST_TRAVERSE(&agents, p, list) { 01863 agent_status = 0; /* reset it to offline */ 01864 ast_mutex_lock(&p->lock); 01865 if (!ast_strlen_zero(p->name)) 01866 snprintf(username, sizeof(username), "(%s) ", p->name); 01867 else 01868 username[0] = '\0'; 01869 if (p->chan) { 01870 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01871 if (p->owner && ast_bridged_channel(p->owner)) 01872 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01873 else 01874 strcpy(talkingto, " is idle"); 01875 agent_status = 1; 01876 online_agents++; 01877 } else if (!ast_strlen_zero(p->loginchan)) { 01878 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01879 talkingto[0] = '\0'; 01880 agent_status = 1; 01881 online_agents++; 01882 if (p->acknowledged) 01883 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01884 } 01885 if (!ast_strlen_zero(p->moh)) 01886 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01887 if (agent_status) 01888 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, username, location, talkingto, moh); 01889 count_agents++; 01890 ast_mutex_unlock(&p->lock); 01891 } 01892 AST_LIST_UNLOCK(&agents); 01893 if (!count_agents) 01894 ast_cli(fd, "No Agents are configured in %s\n", config); 01895 else 01896 ast_cli(fd, "%d agents online\n", online_agents); 01897 ast_cli(fd, "\n"); 01898 return RESULT_SUCCESS; 01899 }
static int allow_multiple_login | ( | char * | chan, | |
char * | context | |||
) | [static] |
Definition at line 1413 of file chan_agent.c.
References AST_LIST_TRAVERSE, agent_pvt::list, agent_pvt::loginchan, and S_OR.
Referenced by __login_exec().
01414 { 01415 struct agent_pvt *p; 01416 char loginchan[80]; 01417 01418 if (multiplelogin) { 01419 return 1; 01420 } 01421 if (!chan) { 01422 return 0; 01423 } 01424 01425 snprintf(loginchan, sizeof(loginchan), "%s@%s", chan, S_OR(context, "default")); 01426 01427 AST_LIST_TRAVERSE(&agents, p, list) { 01428 if(!strcasecmp(loginchan, p->loginchan)) 01429 return 0; 01430 } 01431 return -1; 01432 }
static void callback_deprecated | ( | void | ) | [static] |
Definition at line 2408 of file chan_agent.c.
References ast_log(), depwarning, and LOG_WARNING.
Referenced by action_agent_callback_login(), and callback_exec().
02409 { 02410 static int depwarning = 0; 02411 02412 if (!depwarning) { 02413 depwarning = 1; 02414 02415 ast_log(LOG_WARNING, "AgentCallbackLogin is deprecated and will be removed in a future release.\n"); 02416 ast_log(LOG_WARNING, "See doc/queues-with-callback-members.txt for an example of how to achieve\n"); 02417 ast_log(LOG_WARNING, "the same functionality using only dialplan logic.\n"); 02418 } 02419 }
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 2429 of file chan_agent.c.
References __login_exec(), callback_deprecated(), and ast_module_user::chan.
Referenced by load_module().
02430 { 02431 callback_deprecated(); 02432 02433 return __login_exec(chan, data, 1); 02434 }
static int check_availability | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1299 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().
01300 { 01301 struct ast_channel *chan=NULL, *parent=NULL; 01302 struct agent_pvt *p; 01303 int res; 01304 01305 if (option_debug) 01306 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent); 01307 if (needlock) 01308 AST_LIST_LOCK(&agents); 01309 AST_LIST_TRAVERSE(&agents, p, list) { 01310 if (p == newlyavailable) { 01311 continue; 01312 } 01313 ast_mutex_lock(&p->lock); 01314 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01315 if (option_debug) 01316 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01317 /* We found a pending call, time to merge */ 01318 chan = agent_new(newlyavailable, AST_STATE_DOWN); 01319 parent = p->owner; 01320 p->abouttograb = 1; 01321 ast_mutex_unlock(&p->lock); 01322 break; 01323 } 01324 ast_mutex_unlock(&p->lock); 01325 } 01326 if (needlock) 01327 AST_LIST_UNLOCK(&agents); 01328 if (parent && chan) { 01329 if (newlyavailable->ackcall > 1) { 01330 /* Don't do beep here */ 01331 res = 0; 01332 } else { 01333 if (option_debug > 2) 01334 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01335 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01336 if (option_debug > 2) 01337 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01338 if (!res) { 01339 res = ast_waitstream(newlyavailable->chan, ""); 01340 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01341 } 01342 } 01343 if (!res) { 01344 /* Note -- parent may have disappeared */ 01345 if (p->abouttograb) { 01346 newlyavailable->acknowledged = 1; 01347 /* Safe -- agent lock already held */ 01348 ast_setstate(parent, AST_STATE_UP); 01349 ast_setstate(chan, AST_STATE_UP); 01350 ast_copy_string(parent->context, chan->context, sizeof(parent->context)); 01351 /* Go ahead and mark the channel as a zombie so that masquerade will 01352 destroy it for us, and we need not call ast_hangup */ 01353 ast_mutex_lock(&parent->lock); 01354 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01355 ast_channel_masquerade(parent, chan); 01356 ast_mutex_unlock(&parent->lock); 01357 p->abouttograb = 0; 01358 } else { 01359 if (option_debug) 01360 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n"); 01361 agent_cleanup(newlyavailable); 01362 } 01363 } else { 01364 if (option_debug) 01365 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n"); 01366 agent_cleanup(newlyavailable); 01367 } 01368 } 01369 return 0; 01370 }
static int check_beep | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1372 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().
01373 { 01374 struct agent_pvt *p; 01375 int res=0; 01376 01377 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent); 01378 if (needlock) 01379 AST_LIST_LOCK(&agents); 01380 AST_LIST_TRAVERSE(&agents, p, list) { 01381 if (p == newlyavailable) { 01382 continue; 01383 } 01384 ast_mutex_lock(&p->lock); 01385 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01386 if (option_debug) 01387 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01388 ast_mutex_unlock(&p->lock); 01389 break; 01390 } 01391 ast_mutex_unlock(&p->lock); 01392 } 01393 if (needlock) 01394 AST_LIST_UNLOCK(&agents); 01395 if (p) { 01396 ast_mutex_unlock(&newlyavailable->lock); 01397 if (option_debug > 2) 01398 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01399 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01400 if (option_debug > 2) 01401 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01402 if (!res) { 01403 res = ast_waitstream(newlyavailable->chan, ""); 01404 if (option_debug) 01405 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01406 } 01407 ast_mutex_lock(&newlyavailable->lock); 01408 } 01409 return res; 01410 }
static char* complete_agent_logoff_cmd | ( | const char * | line, | |
const char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1757 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.
01758 { 01759 char *ret = NULL; 01760 01761 if (pos == 2) { 01762 struct agent_pvt *p; 01763 char name[AST_MAX_AGENT]; 01764 int which = 0, len = strlen(word); 01765 01766 AST_LIST_LOCK(&agents); 01767 AST_LIST_TRAVERSE(&agents, p, list) { 01768 snprintf(name, sizeof(name), "Agent/%s", p->agent); 01769 if (!strncasecmp(word, name, len) && ++which > state) { 01770 ret = ast_strdup(name); 01771 break; 01772 } 01773 } 01774 AST_LIST_UNLOCK(&agents); 01775 } else if (pos == 3 && state == 0) 01776 return ast_strdup("soft"); 01777 01778 return ret; 01779 }
static void dump_agents | ( | void | ) | [static] |
Dump AgentCallbackLogin agents to the ASTdb database for persistence.
Definition at line 2588 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().
02589 { 02590 struct agent_pvt *cur_agent = NULL; 02591 char buf[256]; 02592 02593 AST_LIST_TRAVERSE(&agents, cur_agent, list) { 02594 if (cur_agent->chan) 02595 continue; 02596 02597 if (!ast_strlen_zero(cur_agent->loginchan)) { 02598 snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid); 02599 if (ast_db_put(pa_family, cur_agent->agent, buf)) 02600 ast_log(LOG_WARNING, "failed to create persistent entry in ASTdb for %s!\n", buf); 02601 else if (option_debug) 02602 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan); 02603 } else { 02604 /* Delete - no agent or there is an error */ 02605 ast_db_del(pa_family, cur_agent->agent); 02606 } 02607 } 02608 }
static struct agent_pvt* find_agent | ( | char * | agentid | ) | [static] |
Definition at line 2716 of file chan_agent.c.
References agent_pvt::agent, AST_LIST_TRAVERSE, and agent_pvt::list.
Referenced by function_agent().
02717 { 02718 struct agent_pvt *cur; 02719 02720 AST_LIST_TRAVERSE(&agents, cur, list) { 02721 if (!strcmp(cur->agent, agentid)) 02722 break; 02723 } 02724 02725 return cur; 02726 }
static int function_agent | ( | struct ast_channel * | chan, | |
char * | cmd, | |||
char * | data, | |||
char * | buf, | |||
size_t | len | |||
) | [static] |
Definition at line 2728 of file chan_agent.c.
References agent_pvt::agent, AST_APP_ARG, 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().
02729 { 02730 char *parse; 02731 AST_DECLARE_APP_ARGS(args, 02732 AST_APP_ARG(agentid); 02733 AST_APP_ARG(item); 02734 ); 02735 char *tmp; 02736 struct agent_pvt *agent; 02737 02738 buf[0] = '\0'; 02739 02740 if (ast_strlen_zero(data)) { 02741 ast_log(LOG_WARNING, "The AGENT function requires an argument - agentid!\n"); 02742 return -1; 02743 } 02744 02745 parse = ast_strdupa(data); 02746 02747 AST_NONSTANDARD_APP_ARGS(args, parse, ':'); 02748 if (!args.item) 02749 args.item = "status"; 02750 02751 AST_LIST_LOCK(&agents); 02752 02753 if (!(agent = find_agent(args.agentid))) { 02754 AST_LIST_UNLOCK(&agents); 02755 ast_log(LOG_WARNING, "Agent '%s' not found!\n", args.agentid); 02756 return -1; 02757 } 02758 02759 if (!strcasecmp(args.item, "status")) { 02760 char *status = "LOGGEDOUT"; 02761 if (agent->chan || !ast_strlen_zero(agent->loginchan)) 02762 status = "LOGGEDIN"; 02763 ast_copy_string(buf, status, len); 02764 } else if (!strcasecmp(args.item, "password")) 02765 ast_copy_string(buf, agent->password, len); 02766 else if (!strcasecmp(args.item, "name")) 02767 ast_copy_string(buf, agent->name, len); 02768 else if (!strcasecmp(args.item, "mohclass")) 02769 ast_copy_string(buf, agent->moh, len); 02770 else if (!strcasecmp(args.item, "channel")) { 02771 if (agent->chan) { 02772 ast_copy_string(buf, agent->chan->name, len); 02773 tmp = strrchr(buf, '-'); 02774 if (tmp) 02775 *tmp = '\0'; 02776 } 02777 } else if (!strcasecmp(args.item, "exten")) 02778 ast_copy_string(buf, agent->loginchan, len); 02779 02780 AST_LIST_UNLOCK(&agents); 02781 02782 return 0; 02783 }
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 2808 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().
02809 { 02810 /* Make sure we can register our agent channel type */ 02811 if (ast_channel_register(&agent_tech)) { 02812 ast_log(LOG_ERROR, "Unable to register channel class 'Agent'\n"); 02813 return -1; 02814 } 02815 /* Read in the config */ 02816 if (!read_agent_config()) 02817 return AST_MODULE_LOAD_DECLINE; 02818 if (persistent_agents) 02819 reload_agents(); 02820 /* Dialplan applications */ 02821 ast_register_application(app, login_exec, synopsis, descrip); 02822 ast_register_application(app2, callback_exec, synopsis2, descrip2); 02823 ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3); 02824 02825 /* Manager commands */ 02826 ast_manager_register2("Agents", EVENT_FLAG_AGENT, action_agents, "Lists agents and their status", mandescr_agents); 02827 ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff); 02828 ast_manager_register2("AgentCallbackLogin", EVENT_FLAG_AGENT, action_agent_callback_login, "Sets an agent as logged in by callback", mandescr_agent_callback_login); 02829 02830 /* CLI Commands */ 02831 ast_cli_register_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry)); 02832 02833 /* Dialplan Functions */ 02834 ast_custom_function_register(&agent_function); 02835 02836 ast_devstate_add(agent_devicestate_cb, NULL); 02837 02838 return 0; 02839 }
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 2403 of file chan_agent.c.
References __login_exec(), and ast_module_user::chan.
Referenced by load_module().
02404 { 02405 return __login_exec(chan, data, 0); 02406 }
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 1149 of file chan_agent.c.
References add_agent(), agent_pvt::app_complete_cond, agent_pvt::app_lock, 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, ast_variable::name, ast_variable::next, agent_pvt::owner, secret, and ast_variable::value.
Referenced by load_module(), and reload().
01150 { 01151 struct ast_config *cfg; 01152 struct ast_config *ucfg; 01153 struct ast_variable *v; 01154 struct agent_pvt *p; 01155 const char *general_val; 01156 const char *catname; 01157 const char *hasagent; 01158 int genhasagent; 01159 01160 group = 0; 01161 autologoff = 0; 01162 wrapuptime = 0; 01163 ackcall = 0; 01164 endcall = 1; 01165 cfg = ast_config_load(config); 01166 if (!cfg) { 01167 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); 01168 return 0; 01169 } 01170 AST_LIST_LOCK(&agents); 01171 AST_LIST_TRAVERSE(&agents, p, list) { 01172 p->dead = 1; 01173 } 01174 strcpy(moh, "default"); 01175 /* set the default recording values */ 01176 recordagentcalls = 0; 01177 strcpy(recordformat, "wav"); 01178 strcpy(recordformatext, "wav"); 01179 urlprefix[0] = '\0'; 01180 savecallsin[0] = '\0'; 01181 01182 /* Read in [general] section for persistence */ 01183 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents"))) 01184 persistent_agents = ast_true(general_val); 01185 multiplelogin = ast_true(ast_variable_retrieve(cfg, "general", "multiplelogin")); 01186 01187 /* Read in the [agents] section */ 01188 v = ast_variable_browse(cfg, "agents"); 01189 while(v) { 01190 /* Create the interface list */ 01191 if (!strcasecmp(v->name, "agent")) { 01192 add_agent(v->value, 0); 01193 } else if (!strcasecmp(v->name, "group")) { 01194 group = ast_get_group(v->value); 01195 } else if (!strcasecmp(v->name, "autologoff")) { 01196 autologoff = atoi(v->value); 01197 if (autologoff < 0) 01198 autologoff = 0; 01199 } else if (!strcasecmp(v->name, "ackcall")) { 01200 if (!strcasecmp(v->value, "always")) 01201 ackcall = 2; 01202 else if (ast_true(v->value)) 01203 ackcall = 1; 01204 else 01205 ackcall = 0; 01206 } else if (!strcasecmp(v->name, "endcall")) { 01207 endcall = ast_true(v->value); 01208 } else if (!strcasecmp(v->name, "wrapuptime")) { 01209 wrapuptime = atoi(v->value); 01210 if (wrapuptime < 0) 01211 wrapuptime = 0; 01212 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { 01213 maxlogintries = atoi(v->value); 01214 if (maxlogintries < 0) 01215 maxlogintries = 0; 01216 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { 01217 strcpy(agentgoodbye,v->value); 01218 } else if (!strcasecmp(v->name, "musiconhold")) { 01219 ast_copy_string(moh, v->value, sizeof(moh)); 01220 } else if (!strcasecmp(v->name, "updatecdr")) { 01221 if (ast_true(v->value)) 01222 updatecdr = 1; 01223 else 01224 updatecdr = 0; 01225 } else if (!strcasecmp(v->name, "autologoffunavail")) { 01226 if (ast_true(v->value)) 01227 autologoffunavail = 1; 01228 else 01229 autologoffunavail = 0; 01230 } else if (!strcasecmp(v->name, "recordagentcalls")) { 01231 recordagentcalls = ast_true(v->value); 01232 } else if (!strcasecmp(v->name, "recordformat")) { 01233 ast_copy_string(recordformat, v->value, sizeof(recordformat)); 01234 if (!strcasecmp(v->value, "wav49")) 01235 strcpy(recordformatext, "WAV"); 01236 else 01237 ast_copy_string(recordformatext, v->value, sizeof(recordformatext)); 01238 } else if (!strcasecmp(v->name, "urlprefix")) { 01239 ast_copy_string(urlprefix, v->value, sizeof(urlprefix)); 01240 if (urlprefix[strlen(urlprefix) - 1] != '/') 01241 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1); 01242 } else if (!strcasecmp(v->name, "savecallsin")) { 01243 if (v->value[0] == '/') 01244 ast_copy_string(savecallsin, v->value, sizeof(savecallsin)); 01245 else 01246 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value); 01247 if (savecallsin[strlen(savecallsin) - 1] != '/') 01248 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); 01249 } else if (!strcasecmp(v->name, "custom_beep")) { 01250 ast_copy_string(beep, v->value, sizeof(beep)); 01251 } 01252 v = v->next; 01253 } 01254 if ((ucfg = ast_config_load("users.conf"))) { 01255 genhasagent = ast_true(ast_variable_retrieve(ucfg, "general", "hasagent")); 01256 catname = ast_category_browse(ucfg, NULL); 01257 while(catname) { 01258 if (strcasecmp(catname, "general")) { 01259 hasagent = ast_variable_retrieve(ucfg, catname, "hasagent"); 01260 if (ast_true(hasagent) || (!hasagent && genhasagent)) { 01261 char tmp[256]; 01262 const char *fullname = ast_variable_retrieve(ucfg, catname, "fullname"); 01263 const char *secret = ast_variable_retrieve(ucfg, catname, "secret"); 01264 if (!fullname) 01265 fullname = ""; 01266 if (!secret) 01267 secret = ""; 01268 snprintf(tmp, sizeof(tmp), "%s,%s,%s", catname, secret,fullname); 01269 add_agent(tmp, 0); 01270 } 01271 } 01272 catname = ast_category_browse(ucfg, catname); 01273 } 01274 ast_config_destroy(ucfg); 01275 } 01276 AST_LIST_TRAVERSE_SAFE_BEGIN(&agents, p, list) { 01277 if (p->dead) { 01278 AST_LIST_REMOVE_CURRENT(&agents, list); 01279 /* Destroy if appropriate */ 01280 if (!p->owner) { 01281 if (!p->chan) { 01282 ast_mutex_destroy(&p->lock); 01283 ast_mutex_destroy(&p->app_lock); 01284 ast_cond_destroy(&p->app_complete_cond); 01285 free(p); 01286 } else { 01287 /* Cause them to hang up */ 01288 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01289 } 01290 } 01291 } 01292 } 01293 AST_LIST_TRAVERSE_SAFE_END 01294 AST_LIST_UNLOCK(&agents); 01295 ast_config_destroy(cfg); 01296 return 1; 01297 }
static int reload | ( | void | ) | [static] |
Definition at line 2841 of file chan_agent.c.
References read_agent_config(), and reload_agents().
Referenced by moh_cli(), reload(), rpt_do_reload(), and show_console().
02842 { 02843 read_agent_config(); 02844 if (persistent_agents) 02845 reload_agents(); 02846 return 0; 02847 }
static void reload_agents | ( | void | ) | [static] |
Reload the persistent agents from astdb.
Definition at line 2613 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().
02614 { 02615 char *agent_num; 02616 struct ast_db_entry *db_tree; 02617 struct ast_db_entry *entry; 02618 struct agent_pvt *cur_agent; 02619 char agent_data[256]; 02620 char *parse; 02621 char *agent_chan; 02622 char *agent_callerid; 02623 02624 db_tree = ast_db_gettree(pa_family, NULL); 02625 02626 AST_LIST_LOCK(&agents); 02627 for (entry = db_tree; entry; entry = entry->next) { 02628 agent_num = entry->key + strlen(pa_family) + 2; 02629 AST_LIST_TRAVERSE(&agents, cur_agent, list) { 02630 ast_mutex_lock(&cur_agent->lock); 02631 if (strcmp(agent_num, cur_agent->agent) == 0) 02632 break; 02633 ast_mutex_unlock(&cur_agent->lock); 02634 } 02635 if (!cur_agent) { 02636 ast_db_del(pa_family, agent_num); 02637 continue; 02638 } else 02639 ast_mutex_unlock(&cur_agent->lock); 02640 if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) { 02641 if (option_debug) 02642 ast_log(LOG_DEBUG, "Reload Agent from AstDB: %s on %s\n", cur_agent->agent, agent_data); 02643 parse = agent_data; 02644 agent_chan = strsep(&parse, ";"); 02645 agent_callerid = strsep(&parse, ";"); 02646 ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan)); 02647 if (agent_callerid) { 02648 ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid)); 02649 set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent); 02650 } else 02651 cur_agent->logincallerid[0] = '\0'; 02652 if (cur_agent->loginstart == 0) 02653 time(&cur_agent->loginstart); 02654 ast_device_state_changed("Agent/%s", cur_agent->agent); 02655 } 02656 } 02657 AST_LIST_UNLOCK(&agents); 02658 if (db_tree) { 02659 ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n"); 02660 ast_db_freetree(db_tree); 02661 } 02662 }
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 808 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().
00809 { 00810 char buf[AST_MAX_BUF]; 00811 00812 /* if there is no Caller ID, nothing to do */ 00813 if (ast_strlen_zero(callerid)) 00814 return; 00815 00816 snprintf(buf, sizeof(buf), "%s_%s", GETAGENTBYCALLERID, callerid); 00817 pbx_builtin_setvar_helper(NULL, buf, agent); 00818 }
static int unload_module | ( | void | ) | [static] |
Definition at line 2849 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().
02850 { 02851 struct agent_pvt *p; 02852 /* First, take us out of the channel loop */ 02853 ast_channel_unregister(&agent_tech); 02854 /* Delete devicestate subscription */ 02855 ast_devstate_del(agent_devicestate_cb, NULL); 02856 /* Unregister dialplan functions */ 02857 ast_custom_function_unregister(&agent_function); 02858 /* Unregister CLI commands */ 02859 ast_cli_unregister_multiple(cli_agents, sizeof(cli_agents) / sizeof(struct ast_cli_entry)); 02860 /* Unregister dialplan applications */ 02861 ast_unregister_application(app); 02862 ast_unregister_application(app2); 02863 ast_unregister_application(app3); 02864 /* Unregister manager command */ 02865 ast_manager_unregister("Agents"); 02866 ast_manager_unregister("AgentLogoff"); 02867 ast_manager_unregister("AgentCallbackLogin"); 02868 /* Unregister channel */ 02869 AST_LIST_LOCK(&agents); 02870 /* Hangup all interfaces if they have an owner */ 02871 while ((p = AST_LIST_REMOVE_HEAD(&agents, list))) { 02872 if (p->owner) 02873 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 02874 free(p); 02875 } 02876 AST_LIST_UNLOCK(&agents); 02877 return 0; 02878 }
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 2884 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 1911 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 2884 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 1916 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 1921 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_atxfer(), 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] |
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 1907 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 1903 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.