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