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