#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.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"
Go to the source code of this file.
Data Structures | |
struct | agent_pvt |
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) |
#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 int | action_agent_callback_login (struct mansession *s, struct message *m) |
static int | action_agent_logoff (struct mansession *s, struct message *m) |
static int | action_agents (struct mansession *s, 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) |
static int | agent_digit (struct ast_channel *ast, char digit) |
static int | agent_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
static int | agent_hangup (struct ast_channel *ast) |
static int | agent_indicate (struct ast_channel *ast, int condition) |
static int | agent_logoff (char *agent, int soft) |
static int | agent_logoff_cmd (int fd, int argc, char **argv) |
static struct ast_channel * | agent_new (struct agent_pvt *p, int state) |
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) |
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_start_monitoring (struct ast_channel *ast, int needlock) |
static void | agent_unlink (struct agent_pvt *agent) |
static int | agent_write (struct ast_channel *ast, struct ast_frame *f) |
static int | agentmonitoroutgoing_exec (struct ast_channel *chan, void *data) |
static int | agents_show (int fd, int argc, char **argv) |
AST_MUTEX_DEFINE_STATIC (agentlock) | |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
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 (char *line, char *word, int pos, int state) |
char * | description () |
Provides a description of the module. | |
static void | dump_agents (void) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
static int | login_exec (struct ast_channel *chan, void *data) |
static int | powerof (unsigned int v) |
static int | read_agent_config (void) |
int | reload () |
Reload stuff. | |
static void | reload_agents (void) |
static void | set_agentbycallerid (const char *callerid, const char *agent) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
int | usecount () |
Provides a usecount. | |
Variables | |
static int | ackcall |
static char | agent_logoff_usage [] |
static struct ast_channel_tech | agent_tech |
static char | agentgoodbye [AST_MAX_FILENAME_LEN] = "vm-goodbye" |
static struct agent_pvt * | agents = NULL |
static const char | app [] = "AgentLogin" |
static const char | app2 [] = "AgentCallbackLogin" |
static const char | app3 [] = "AgentMonitorOutgoing" |
static int | autologoff |
static char | beep [AST_MAX_BUF] = "beep" |
static const char | channeltype [] = "Agent" |
static struct ast_cli_entry | cli_agent_logoff |
static struct ast_cli_entry | cli_show_agents |
static const char | config [] = "agents.conf" |
static int | createlink = 0 |
static const char | desc [] = "Agent Proxy Channel" |
static const char | descrip [] |
static const char | descrip2 [] |
static const char | descrip3 [] |
static ast_group_t | group |
LOCAL_USER_DECL | |
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 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_usage [] |
STANDARD_LOCAL_USER | |
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 | usecnt = 0 |
static int | wrapuptime |
This file is the implementation of Agents modules. It is a dynamic module that is loaded by Asterisk.
Definition in file chan_agent.c.
#define AST_MAX_AGENT 80 |
Agent ID or Password max length
Definition at line 141 of file chan_agent.c.
Referenced by __login_exec(), agent_hangup(), agentmonitoroutgoing_exec(), and complete_agent_logoff_cmd().
#define AST_MAX_BUF 256 |
Definition at line 142 of file chan_agent.c.
Referenced by __agent_start_monitoring(), __login_exec(), agentmonitoroutgoing_exec(), agents_show(), and set_agentbycallerid().
#define AST_MAX_FILENAME_LEN 256 |
#define CHECK_FORMATS | ( | ast, | |||
p | ) |
#define CLEANUP | ( | ast, | |||
p | ) |
Definition at line 231 of file chan_agent.c.
Referenced by agent_call(), agent_read(), and agent_write().
#define GETAGENTBYCALLERID "AGENTBYCALLERID" |
Definition at line 176 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 148 of file chan_agent.c.
static int __agent_start_monitoring | ( | struct ast_channel * | ast, | |
struct agent_pvt * | p, | |||
int | needlock | |||
) | [static] |
Definition at line 430 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().
00431 { 00432 char tmp[AST_MAX_BUF],tmp2[AST_MAX_BUF], *pointer; 00433 char filename[AST_MAX_BUF]; 00434 int res = -1; 00435 if (!p) 00436 return -1; 00437 if (!ast->monitor) { 00438 snprintf(filename, sizeof(filename), "agent-%s-%s",p->agent, ast->uniqueid); 00439 /* substitute . for - */ 00440 if ((pointer = strchr(filename, '.'))) 00441 *pointer = '-'; 00442 snprintf(tmp, sizeof(tmp), "%s%s",savecallsin ? savecallsin : "", filename); 00443 ast_monitor_start(ast, recordformat, tmp, needlock); 00444 ast_monitor_setjoinfiles(ast, 1); 00445 snprintf(tmp2, sizeof(tmp2), "%s%s.%s", urlprefix ? urlprefix : "", filename, recordformatext); 00446 #if 0 00447 ast_verbose("name is %s, link is %s\n",tmp, tmp2); 00448 #endif 00449 if (!ast->cdr) 00450 ast->cdr = ast_cdr_alloc(); 00451 ast_cdr_setuserfield(ast, tmp2); 00452 res = 0; 00453 } else 00454 ast_log(LOG_ERROR, "Recording already started on that call.\n"); 00455 return res; 00456 }
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 1681 of file chan_agent.c.
References ast_channel::_state, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_ack_sleep(), agent_cont_sleep(), agentgoodbye, agents, agent_pvt::app_lock, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_best_codec(), AST_DECLARE_APP_ARGS, ast_device_state_changed(), AST_DIGIT_ANY, ast_exists_extension(), ast_getformatname(), ast_log(), AST_MAX_AGENT, AST_MAX_BUF, AST_MAX_FILENAME_LEN, ast_moh_start(), 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_STANDARD_APP_ARGS, AST_STATE_UP, ast_strdupa, ast_streamfile(), ast_strlen_zero(), ast_true(), ast_verbose(), ast_waitstream(), agent_pvt::autologoff, ast_channel::cdr, agent_pvt::chan, localuser::chan, ast_cdr::channel, check_availability(), check_beep(), ast_channel::cid, ast_callerid::cid_num, context, agent_pvt::dead, dump_agents(), EVENT_FLAG_AGENT, free, ast_channel::language, agent_pvt::lastdisc, LOCAL_USER_ADD, LOCAL_USER_REMOVE, agent_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), maxlogintries, agent_pvt::moh, ast_channel::name, agent_pvt::next, option_debug, option_verbose, agent_pvt::owner, agent_pvt::owning_app, parse(), pass, agent_pvt::password, pbx_builtin_getvar_helper(), agent_pvt::pending, persistent_agents, set_agentbycallerid(), strsep(), updatecdr, user, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, and agent_pvt::wrapuptime.
Referenced by callback_exec(), and login_exec().
01682 { 01683 int res=0; 01684 int tries = 0; 01685 int max_login_tries = maxlogintries; 01686 struct agent_pvt *p; 01687 struct localuser *u; 01688 int login_state = 0; 01689 char user[AST_MAX_AGENT] = ""; 01690 char pass[AST_MAX_AGENT]; 01691 char agent[AST_MAX_AGENT] = ""; 01692 char xpass[AST_MAX_AGENT] = ""; 01693 char *errmsg; 01694 char *parse; 01695 AST_DECLARE_APP_ARGS(args, 01696 AST_APP_ARG(agent_id); 01697 AST_APP_ARG(options); 01698 AST_APP_ARG(extension); 01699 ); 01700 char *tmpoptions = NULL; 01701 char *context = NULL; 01702 int play_announcement = 1; 01703 char agent_goodbye[AST_MAX_FILENAME_LEN]; 01704 int update_cdr = updatecdr; 01705 char *filename = "agent-loginok"; 01706 char tmpchan[AST_MAX_BUF] = ""; 01707 01708 LOCAL_USER_ADD(u); 01709 01710 if (!(parse = ast_strdupa(data))) { 01711 ast_log(LOG_ERROR, "Out of memory!\n"); 01712 LOCAL_USER_REMOVE(u); 01713 return -1; 01714 } 01715 01716 AST_STANDARD_APP_ARGS(args, parse); 01717 01718 ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye)); 01719 01720 /* Set Channel Specific Login Overrides */ 01721 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { 01722 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); 01723 if (max_login_tries < 0) 01724 max_login_tries = 0; 01725 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); 01726 if (option_verbose > 2) 01727 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); 01728 } 01729 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { 01730 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) 01731 update_cdr = 1; 01732 else 01733 update_cdr = 0; 01734 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); 01735 if (option_verbose > 2) 01736 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); 01737 } 01738 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { 01739 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); 01740 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); 01741 if (option_verbose > 2) 01742 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); 01743 } 01744 /* End Channel Specific Login Overrides */ 01745 01746 if (callbackmode && args.extension) { 01747 parse = args.extension; 01748 args.extension = strsep(&parse, "@"); 01749 context = parse; 01750 } 01751 01752 if (!ast_strlen_zero(args.options)) { 01753 if (strchr(args.options, 's')) { 01754 play_announcement = 0; 01755 } 01756 } 01757 01758 if (chan->_state != AST_STATE_UP) 01759 res = ast_answer(chan); 01760 if (!res) { 01761 if (!ast_strlen_zero(args.agent_id)) 01762 ast_copy_string(user, args.agent_id, AST_MAX_AGENT); 01763 else 01764 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); 01765 } 01766 while (!res && (max_login_tries==0 || tries < max_login_tries)) { 01767 tries++; 01768 /* Check for password */ 01769 ast_mutex_lock(&agentlock); 01770 p = agents; 01771 while(p) { 01772 if (!strcmp(p->agent, user) && !p->pending) 01773 ast_copy_string(xpass, p->password, sizeof(xpass)); 01774 p = p->next; 01775 } 01776 ast_mutex_unlock(&agentlock); 01777 if (!res) { 01778 if (!ast_strlen_zero(xpass)) 01779 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); 01780 else 01781 pass[0] = '\0'; 01782 } 01783 errmsg = "agent-incorrect"; 01784 01785 #if 0 01786 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); 01787 #endif 01788 01789 /* Check again for accuracy */ 01790 ast_mutex_lock(&agentlock); 01791 p = agents; 01792 while(p) { 01793 ast_mutex_lock(&p->lock); 01794 if (!strcmp(p->agent, user) && 01795 !strcmp(p->password, pass) && !p->pending) { 01796 login_state = 1; /* Successful Login */ 01797 01798 /* Ensure we can't be gotten until we're done */ 01799 gettimeofday(&p->lastdisc, NULL); 01800 p->lastdisc.tv_sec++; 01801 01802 /* Set Channel Specific Agent Overrides */ 01803 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { 01804 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) 01805 p->ackcall = 2; 01806 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) 01807 p->ackcall = 1; 01808 else 01809 p->ackcall = 0; 01810 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); 01811 if (option_verbose > 2) 01812 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); 01813 } 01814 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { 01815 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); 01816 if (p->autologoff < 0) 01817 p->autologoff = 0; 01818 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); 01819 if (option_verbose > 2) 01820 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); 01821 } 01822 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { 01823 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); 01824 if (p->wrapuptime < 0) 01825 p->wrapuptime = 0; 01826 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); 01827 if (option_verbose > 2) 01828 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); 01829 } 01830 /* End Channel Specific Agent Overrides */ 01831 if (!p->chan) { 01832 char last_loginchan[80] = ""; 01833 long logintime; 01834 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 01835 01836 if (callbackmode) { 01837 int pos = 0; 01838 /* Retrieve login chan */ 01839 for (;;) { 01840 if (!ast_strlen_zero(args.extension)) { 01841 ast_copy_string(tmpchan, args.extension, sizeof(tmpchan)); 01842 res = 0; 01843 } else 01844 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0); 01845 if (ast_strlen_zero(tmpchan) || ast_exists_extension(chan, !ast_strlen_zero(context) ? context : "default", tmpchan, 01846 1, NULL)) 01847 break; 01848 if (args.extension) { 01849 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", args.extension, p->agent); 01850 args.extension = NULL; 01851 pos = 0; 01852 } else { 01853 ast_log(LOG_WARNING, "Extension '%s@%s' is not valid for automatic login of agent '%s'\n", tmpchan, !ast_strlen_zero(context) ? context : "default", p->agent); 01854 res = ast_streamfile(chan, "invalid", chan->language); 01855 if (!res) 01856 res = ast_waitstream(chan, AST_DIGIT_ANY); 01857 if (res > 0) { 01858 tmpchan[0] = res; 01859 tmpchan[1] = '\0'; 01860 pos = 1; 01861 } else { 01862 tmpchan[0] = '\0'; 01863 pos = 0; 01864 } 01865 } 01866 } 01867 args.extension = tmpchan; 01868 if (!res) { 01869 set_agentbycallerid(p->logincallerid, NULL); 01870 if (!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) 01871 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); 01872 else { 01873 ast_copy_string(last_loginchan, p->loginchan, sizeof(last_loginchan)); 01874 ast_copy_string(p->loginchan, tmpchan, sizeof(p->loginchan)); 01875 } 01876 p->acknowledged = 0; 01877 if (ast_strlen_zero(p->loginchan)) { 01878 login_state = 2; 01879 filename = "agent-loggedoff"; 01880 } else { 01881 if (chan->cid.cid_num) { 01882 ast_copy_string(p->logincallerid, chan->cid.cid_num, sizeof(p->logincallerid)); 01883 set_agentbycallerid(p->logincallerid, p->agent); 01884 } else 01885 p->logincallerid[0] = '\0'; 01886 } 01887 01888 if(update_cdr && chan->cdr) 01889 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01890 01891 } 01892 } else { 01893 p->loginchan[0] = '\0'; 01894 p->logincallerid[0] = '\0'; 01895 p->acknowledged = 0; 01896 } 01897 ast_mutex_unlock(&p->lock); 01898 ast_mutex_unlock(&agentlock); 01899 if( !res && play_announcement==1 ) 01900 res = ast_streamfile(chan, filename, chan->language); 01901 if (!res) 01902 ast_waitstream(chan, ""); 01903 ast_mutex_lock(&agentlock); 01904 ast_mutex_lock(&p->lock); 01905 if (!res) { 01906 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); 01907 if (res) 01908 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); 01909 } 01910 if (!res) { 01911 res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); 01912 if (res) 01913 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); 01914 } 01915 /* Check once more just in case */ 01916 if (p->chan) 01917 res = -1; 01918 if (callbackmode && !res) { 01919 /* Just say goodbye and be done with it */ 01920 if (!ast_strlen_zero(p->loginchan)) { 01921 if (p->loginstart == 0) 01922 time(&p->loginstart); 01923 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 01924 "Agent: %s\r\n" 01925 "Loginchan: %s\r\n" 01926 "Uniqueid: %s\r\n", 01927 p->agent, p->loginchan, chan->uniqueid); 01928 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 01929 if (option_verbose > 1) 01930 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 01931 ast_device_state_changed("Agent/%s", p->agent); 01932 } else { 01933 logintime = time(NULL) - p->loginstart; 01934 p->loginstart = 0; 01935 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01936 "Agent: %s\r\n" 01937 "Loginchan: %s\r\n" 01938 "Logintime: %ld\r\n" 01939 "Uniqueid: %s\r\n", 01940 p->agent, last_loginchan, logintime, chan->uniqueid); 01941 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|", last_loginchan, logintime); 01942 if (option_verbose > 1) 01943 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent); 01944 ast_device_state_changed("Agent/%s", p->agent); 01945 } 01946 ast_mutex_unlock(&agentlock); 01947 if (!res) 01948 res = ast_safe_sleep(chan, 500); 01949 ast_mutex_unlock(&p->lock); 01950 if (persistent_agents) 01951 dump_agents(); 01952 } else if (!res) { 01953 #ifdef HONOR_MUSIC_CLASS 01954 /* check if the moh class was changed with setmusiconhold */ 01955 if (*(chan->musicclass)) 01956 ast_copy_string(p->moh, chan->musicclass, sizeof(p->moh)); 01957 #endif 01958 ast_moh_start(chan, p->moh); 01959 if (p->loginstart == 0) 01960 time(&p->loginstart); 01961 manager_event(EVENT_FLAG_AGENT, "Agentlogin", 01962 "Agent: %s\r\n" 01963 "Channel: %s\r\n" 01964 "Uniqueid: %s\r\n", 01965 p->agent, chan->name, chan->uniqueid); 01966 if (update_cdr && chan->cdr) 01967 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01968 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); 01969 if (option_verbose > 1) 01970 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent, 01971 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); 01972 /* Login this channel and wait for it to 01973 go away */ 01974 p->chan = chan; 01975 if (p->ackcall > 1) 01976 check_beep(p, 0); 01977 else 01978 check_availability(p, 0); 01979 ast_mutex_unlock(&p->lock); 01980 ast_mutex_unlock(&agentlock); 01981 ast_device_state_changed("Agent/%s", p->agent); 01982 while (res >= 0) { 01983 ast_mutex_lock(&p->lock); 01984 if (p->chan != chan) 01985 res = -1; 01986 ast_mutex_unlock(&p->lock); 01987 /* Yield here so other interested threads can kick in. */ 01988 sched_yield(); 01989 if (res) 01990 break; 01991 01992 ast_mutex_lock(&agentlock); 01993 ast_mutex_lock(&p->lock); 01994 if (p->lastdisc.tv_sec) { 01995 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) { 01996 if (option_debug) 01997 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent); 01998 p->lastdisc = ast_tv(0, 0); 01999 if (p->ackcall > 1) 02000 check_beep(p, 0); 02001 else 02002 check_availability(p, 0); 02003 } 02004 } 02005 ast_mutex_unlock(&p->lock); 02006 ast_mutex_unlock(&agentlock); 02007 /* Synchronize channel ownership between call to agent and itself. */ 02008 ast_mutex_lock( &p->app_lock ); 02009 ast_mutex_lock(&p->lock); 02010 p->owning_app = pthread_self(); 02011 ast_mutex_unlock(&p->lock); 02012 if (p->ackcall > 1) 02013 res = agent_ack_sleep(p); 02014 else 02015 res = ast_safe_sleep_conditional( chan, 1000, 02016 agent_cont_sleep, p ); 02017 ast_mutex_unlock( &p->app_lock ); 02018 if ((p->ackcall > 1) && (res == 1)) { 02019 ast_mutex_lock(&agentlock); 02020 ast_mutex_lock(&p->lock); 02021 check_availability(p, 0); 02022 ast_mutex_unlock(&p->lock); 02023 ast_mutex_unlock(&agentlock); 02024 res = 0; 02025 } 02026 sched_yield(); 02027 } 02028 ast_mutex_lock(&p->lock); 02029 if (res && p->owner) 02030 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); 02031 /* Log us off if appropriate */ 02032 if (p->chan == chan) 02033 p->chan = NULL; 02034 p->acknowledged = 0; 02035 logintime = time(NULL) - p->loginstart; 02036 p->loginstart = 0; 02037 ast_mutex_unlock(&p->lock); 02038 manager_event(EVENT_FLAG_AGENT, "Agentlogoff", 02039 "Agent: %s\r\n" 02040 "Logintime: %ld\r\n" 02041 "Uniqueid: %s\r\n", 02042 p->agent, logintime, chan->uniqueid); 02043 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); 02044 if (option_verbose > 1) 02045 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent); 02046 /* If there is no owner, go ahead and kill it now */ 02047 ast_device_state_changed("Agent/%s", p->agent); 02048 if (p->dead && !p->owner) { 02049 ast_mutex_destroy(&p->lock); 02050 ast_mutex_destroy(&p->app_lock); 02051 free(p); 02052 } 02053 } 02054 else { 02055 ast_mutex_unlock(&p->lock); 02056 p = NULL; 02057 } 02058 res = -1; 02059 } else { 02060 ast_mutex_unlock(&p->lock); 02061 errmsg = "agent-alreadyon"; 02062 p = NULL; 02063 } 02064 break; 02065 } 02066 ast_mutex_unlock(&p->lock); 02067 p = p->next; 02068 } 02069 if (!p) 02070 ast_mutex_unlock(&agentlock); 02071 02072 if (!res && (max_login_tries==0 || tries < max_login_tries)) 02073 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); 02074 } 02075 02076 if (!res) 02077 res = ast_safe_sleep(chan, 500); 02078 02079 /* AgentLogin() exit */ 02080 if (!callbackmode) { 02081 LOCAL_USER_REMOVE(u); 02082 return -1; 02083 } 02084 /* AgentCallbackLogin() exit*/ 02085 else { 02086 /* Set variables */ 02087 if (login_state > 0) { 02088 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); 02089 if (login_state==1) { 02090 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); 02091 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", args.extension); 02092 } 02093 else { 02094 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); 02095 } 02096 } 02097 else { 02098 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); 02099 } 02100 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) { 02101 LOCAL_USER_REMOVE(u); 02102 return 0; 02103 } 02104 /* Do we need to play agent-goodbye now that we will be hanging up? */ 02105 if (play_announcement) { 02106 if (!res) 02107 res = ast_safe_sleep(chan, 1000); 02108 res = ast_streamfile(chan, agent_goodbye, chan->language); 02109 if (!res) 02110 res = ast_waitstream(chan, ""); 02111 if (!res) 02112 res = ast_safe_sleep(chan, 1000); 02113 } 02114 } 02115 02116 LOCAL_USER_REMOVE(u); 02117 02118 /* We should never get here if next priority exists when in callbackmode */ 02119 return -1; 02120 }
static int action_agent_callback_login | ( | struct mansession * | s, | |
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 2156 of file chan_agent.c.
References agent_pvt::ackcall, agent_pvt::agent, agents, ast_device_state_changed(), 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(), agent_pvt::chan, context, dump_agents(), EVENT_FLAG_AGENT, exten, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::next, option_verbose, agent_pvt::pending, persistent_agents, s, VERBOSE_PREFIX_2, and agent_pvt::wrapuptime.
Referenced by load_module().
02157 { 02158 char *agent = astman_get_header(m, "Agent"); 02159 char *exten = astman_get_header(m, "Exten"); 02160 char *context = astman_get_header(m, "Context"); 02161 char *wrapuptime_s = astman_get_header(m, "WrapupTime"); 02162 char *ackcall_s = astman_get_header(m, "AckCall"); 02163 struct agent_pvt *p; 02164 int login_state = 0; 02165 02166 if (ast_strlen_zero(agent)) { 02167 astman_send_error(s, m, "No agent specified"); 02168 return 0; 02169 } 02170 02171 if (ast_strlen_zero(exten)) { 02172 astman_send_error(s, m, "No extension specified"); 02173 return 0; 02174 } 02175 02176 ast_mutex_lock(&agentlock); 02177 p = agents; 02178 while(p) { 02179 if (strcmp(p->agent, agent) || p->pending) { 02180 p = p->next; 02181 continue; 02182 } 02183 if (p->chan) { 02184 login_state = 2; /* already logged in (and on the phone)*/ 02185 break; 02186 } 02187 ast_mutex_lock(&p->lock); 02188 login_state = 1; /* Successful Login */ 02189 02190 if (ast_strlen_zero(context)) 02191 ast_copy_string(p->loginchan, exten, sizeof(p->loginchan)); 02192 else 02193 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context); 02194 02195 if (!ast_strlen_zero(wrapuptime_s)) { 02196 p->wrapuptime = atoi(wrapuptime_s); 02197 if (p->wrapuptime < 0) 02198 p->wrapuptime = 0; 02199 } 02200 02201 if (ast_true(ackcall_s)) 02202 p->ackcall = 1; 02203 else 02204 p->ackcall = 0; 02205 02206 if (p->loginstart == 0) 02207 time(&p->loginstart); 02208 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02209 "Agent: %s\r\n" 02210 "Loginchan: %s\r\n", 02211 p->agent, p->loginchan); 02212 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02213 if (option_verbose > 1) 02214 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02215 ast_device_state_changed("Agent/%s", p->agent); 02216 ast_mutex_unlock(&p->lock); 02217 p = p->next; 02218 if (persistent_agents) 02219 dump_agents(); 02220 } 02221 ast_mutex_unlock(&agentlock); 02222 02223 if (login_state == 1) 02224 astman_send_ack(s, m, "Agent logged in"); 02225 else if (login_state == 0) 02226 astman_send_error(s, m, "No such agent"); 02227 else if (login_state == 2) 02228 astman_send_error(s, m, "Agent already logged in"); 02229 02230 return 0; 02231 }
static int action_agent_logoff | ( | struct mansession * | s, | |
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 1536 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().
01537 { 01538 char *agent = astman_get_header(m, "Agent"); 01539 char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */ 01540 int soft; 01541 int ret; /* return value of agent_logoff */ 01542 01543 if (ast_strlen_zero(agent)) { 01544 astman_send_error(s, m, "No agent specified"); 01545 return 0; 01546 } 01547 01548 if (ast_true(soft_s)) 01549 soft = 1; 01550 else 01551 soft = 0; 01552 01553 ret = agent_logoff(agent, soft); 01554 if (ret == 0) 01555 astman_send_ack(s, m, "Agent logged out"); 01556 else 01557 astman_send_error(s, m, "No such agent"); 01558 01559 return 0; 01560 }
static int action_agents | ( | struct mansession * | s, | |
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 1394 of file chan_agent.c.
References ast_channel::_bridge, agent_pvt::acknowledged, agent_pvt::agent, agents, ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strdupa, ast_strlen_zero(), astman_get_header(), astman_send_ack(), agent_pvt::chan, ast_channel::cid, ast_callerid::cid_num, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, ast_channel::name, agent_pvt::name, agent_pvt::next, agent_pvt::owner, s, and username.
Referenced by load_module().
01395 { 01396 char *id = astman_get_header(m,"ActionID"); 01397 char idText[256] = ""; 01398 char chanbuf[256]; 01399 struct agent_pvt *p; 01400 char *username = NULL; 01401 char *loginChan = NULL; 01402 char *talkingtoChan = NULL; 01403 char *status = NULL; 01404 01405 if (!ast_strlen_zero(id)) 01406 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); 01407 astman_send_ack(s, m, "Agents will follow"); 01408 ast_mutex_lock(&agentlock); 01409 p = agents; 01410 while(p) { 01411 ast_mutex_lock(&p->lock); 01412 01413 /* Status Values: 01414 AGENT_LOGGEDOFF - Agent isn't logged in 01415 AGENT_IDLE - Agent is logged in, and waiting for call 01416 AGENT_ONCALL - Agent is logged in, and on a call 01417 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */ 01418 01419 if(!ast_strlen_zero(p->name)) { 01420 username = p->name; 01421 } else { 01422 username = "None"; 01423 } 01424 01425 /* Set a default status. It 'should' get changed. */ 01426 status = "AGENT_UNKNOWN"; 01427 01428 if (!ast_strlen_zero(p->loginchan) && !p->chan) { 01429 loginChan = p->loginchan; 01430 talkingtoChan = "n/a"; 01431 status = "AGENT_IDLE"; 01432 if (p->acknowledged) { 01433 snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan); 01434 loginChan = chanbuf; 01435 } 01436 } else if (p->chan) { 01437 loginChan = ast_strdupa(p->chan->name); 01438 if (p->owner && p->owner->_bridge) { 01439 talkingtoChan = p->chan->cid.cid_num; 01440 status = "AGENT_ONCALL"; 01441 } else { 01442 talkingtoChan = "n/a"; 01443 status = "AGENT_IDLE"; 01444 } 01445 } else { 01446 loginChan = "n/a"; 01447 talkingtoChan = "n/a"; 01448 status = "AGENT_LOGGEDOFF"; 01449 } 01450 01451 ast_cli(s->fd, "Event: Agents\r\n" 01452 "Agent: %s\r\n" 01453 "Name: %s\r\n" 01454 "Status: %s\r\n" 01455 "LoggedInChan: %s\r\n" 01456 "LoggedInTime: %d\r\n" 01457 "TalkingTo: %s\r\n" 01458 "%s" 01459 "\r\n", 01460 p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText); 01461 ast_mutex_unlock(&p->lock); 01462 p = p->next; 01463 } 01464 ast_mutex_unlock(&agentlock); 01465 ast_cli(s->fd, "Event: AgentsComplete\r\n" 01466 "%s" 01467 "\r\n",idText); 01468 return 0; 01469 }
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 312 of file chan_agent.c.
References agent_pvt::ackcall, agent_pvt::agent, agents, ast_app_separate_args(), ast_log(), ast_mutex_init(), ast_strdupa, agent_pvt::autologoff, agent_pvt::dead, agent_pvt::lastdisc, LOG_WARNING, malloc, agent_pvt::moh, agent_pvt::name, name, agent_pvt::next, agent_pvt::password, password, and agent_pvt::wrapuptime.
Referenced by agent_request(), and read_agent_config().
00313 { 00314 int argc; 00315 char *argv[3]; 00316 char *args; 00317 char *password = NULL; 00318 char *name = NULL; 00319 char *agt = NULL; 00320 struct agent_pvt *p, *prev; 00321 00322 args = ast_strdupa(agent); 00323 00324 // Extract username (agt), password and name from agent (args). 00325 if ((argc = ast_app_separate_args(args, ',', argv, sizeof(argv) / sizeof(argv[0])))) { 00326 agt = argv[0]; 00327 if (argc > 1) { 00328 password = argv[1]; 00329 while (*password && *password < 33) password++; 00330 } 00331 if (argc > 2) { 00332 name = argv[2]; 00333 while (*name && *name < 33) name++; 00334 } 00335 } else { 00336 ast_log(LOG_WARNING, "A blank agent line!\n"); 00337 } 00338 00339 // Are we searching for the agent here ? to see if it exists already ? 00340 prev=NULL; 00341 p = agents; 00342 while(p) { 00343 if (!pending && !strcmp(p->agent, agt)) 00344 break; 00345 prev = p; 00346 p = p->next; 00347 } 00348 if (!p) { 00349 // Build the agent. 00350 p = malloc(sizeof(struct agent_pvt)); 00351 if (p) { 00352 memset(p, 0, sizeof(struct agent_pvt)); 00353 ast_copy_string(p->agent, agt, sizeof(p->agent)); 00354 ast_mutex_init(&p->lock); 00355 ast_mutex_init(&p->app_lock); 00356 p->owning_app = (pthread_t) -1; 00357 p->app_sleep_cond = 1; 00358 p->group = group; 00359 p->pending = pending; 00360 p->next = NULL; 00361 if (prev) 00362 prev->next = p; 00363 else 00364 agents = p; 00365 00366 } else { 00367 return NULL; 00368 } 00369 } 00370 00371 ast_copy_string(p->password, password ? password : "", sizeof(p->password)); 00372 ast_copy_string(p->name, name ? name : "", sizeof(p->name)); 00373 ast_copy_string(p->moh, moh, sizeof(p->moh)); 00374 p->ackcall = ackcall; 00375 p->autologoff = autologoff; 00376 00377 /* If someone reduces the wrapuptime and reloads, we want it 00378 * to change the wrapuptime immediately on all calls */ 00379 if (p->wrapuptime > wrapuptime) { 00380 struct timeval now = ast_tvnow(); 00381 /* XXX check what is this exactly */ 00382 00383 /* We won't be pedantic and check the tv_usec val */ 00384 if (p->lastdisc.tv_sec > (now.tv_sec + wrapuptime/1000)) { 00385 p->lastdisc.tv_sec = now.tv_sec + wrapuptime/1000; 00386 p->lastdisc.tv_usec = now.tv_usec; 00387 } 00388 } 00389 p->wrapuptime = wrapuptime; 00390 00391 if (pending) 00392 p->dead = 1; 00393 else 00394 p->dead = 0; 00395 return p; 00396 }
static int agent_ack_sleep | ( | void * | data | ) | [static] |
Definition at line 858 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, ast_frame::frametype, agent_pvt::lock, and ast_frame::subclass.
Referenced by __login_exec().
00859 { 00860 struct agent_pvt *p; 00861 int res=0; 00862 int to = 1000; 00863 struct ast_frame *f; 00864 00865 /* Wait a second and look for something */ 00866 00867 p = (struct agent_pvt *)data; 00868 if (p->chan) { 00869 for(;;) { 00870 to = ast_waitfor(p->chan, to); 00871 if (to < 0) { 00872 res = -1; 00873 break; 00874 } 00875 if (!to) { 00876 res = 0; 00877 break; 00878 } 00879 f = ast_read(p->chan); 00880 if (!f) { 00881 res = -1; 00882 break; 00883 } 00884 if (f->frametype == AST_FRAME_DTMF) 00885 res = f->subclass; 00886 else 00887 res = 0; 00888 ast_frfree(f); 00889 ast_mutex_lock(&p->lock); 00890 if (!p->app_sleep_cond) { 00891 ast_mutex_unlock(&p->lock); 00892 res = 0; 00893 break; 00894 } else if (res == '#') { 00895 ast_mutex_unlock(&p->lock); 00896 res = 1; 00897 break; 00898 } 00899 ast_mutex_unlock(&p->lock); 00900 res = 0; 00901 } 00902 } else 00903 res = -1; 00904 return res; 00905 }
static int agent_answer | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 424 of file chan_agent.c.
References ast_log(), and LOG_WARNING.
00425 { 00426 ast_log(LOG_WARNING, "Huh? Agent is being asked to answer?\n"); 00427 return -1; 00428 }
static struct ast_channel * agent_bridgedchannel | ( | struct ast_channel * | chan, | |
struct ast_channel * | bridge | |||
) | [static] |
Definition at line 907 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.
00908 { 00909 struct agent_pvt *p = bridge->tech_pvt; 00910 struct ast_channel *ret=NULL; 00911 00912 if (p) { 00913 if (chan == p->chan) 00914 ret = bridge->_bridge; 00915 else if (chan == bridge->_bridge) 00916 ret = p->chan; 00917 } 00918 00919 if (option_debug) 00920 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>"); 00921 return ret; 00922 }
static int agent_call | ( | struct ast_channel * | ast, | |
char * | dest, | |||
int | timeout | |||
) | [static] |
Definition at line 639 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_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, ast_channel::language, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, agent_pvt::loginchan, ast_channel::name, ast_channel::nativeformats, option_verbose, agent_pvt::pending, agent_pvt::start, ast_channel::tech_pvt, and VERBOSE_PREFIX_3.
00640 { 00641 struct agent_pvt *p = ast->tech_pvt; 00642 int res = -1; 00643 int newstate=0; 00644 ast_mutex_lock(&p->lock); 00645 p->acknowledged = 0; 00646 if (!p->chan) { 00647 if (p->pending) { 00648 ast_log(LOG_DEBUG, "Pretending to dial on pending agent\n"); 00649 newstate = AST_STATE_DIALING; 00650 res = 0; 00651 } else { 00652 ast_log(LOG_NOTICE, "Whoa, they hung up between alloc and call... what are the odds of that?\n"); 00653 res = -1; 00654 } 00655 ast_mutex_unlock(&p->lock); 00656 if (newstate) 00657 ast_setstate(ast, newstate); 00658 return res; 00659 } else if (!ast_strlen_zero(p->loginchan)) { 00660 time(&p->start); 00661 /* Call on this agent */ 00662 if (option_verbose > 2) 00663 ast_verbose(VERBOSE_PREFIX_3 "outgoing agentcall, to agent '%s', on '%s'\n", p->agent, p->chan->name); 00664 ast_set_callerid(p->chan, 00665 ast->cid.cid_num, ast->cid.cid_name, NULL); 00666 ast_channel_inherit_variables(ast, p->chan); 00667 res = ast_call(p->chan, p->loginchan, 0); 00668 CLEANUP(ast,p); 00669 ast_mutex_unlock(&p->lock); 00670 return res; 00671 } 00672 ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name); 00673 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language); 00674 res = ast_streamfile(p->chan, beep, p->chan->language); 00675 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 00676 if (!res) { 00677 res = ast_waitstream(p->chan, ""); 00678 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 00679 } 00680 if (!res) { 00681 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00682 ast_log( LOG_DEBUG, "Set read format, result '%d'\n", res); 00683 if (res) 00684 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00685 } else { 00686 /* Agent hung-up */ 00687 p->chan = NULL; 00688 } 00689 00690 if (!res) { 00691 ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00692 ast_log( LOG_DEBUG, "Set write format, result '%d'\n", res); 00693 if (res) 00694 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00695 } 00696 if( !res ) 00697 { 00698 /* Call is immediately up, or might need ack */ 00699 if (p->ackcall > 1) 00700 newstate = AST_STATE_RINGING; 00701 else { 00702 newstate = AST_STATE_UP; 00703 if (recordagentcalls) 00704 agent_start_monitoring(ast,0); 00705 p->acknowledged = 1; 00706 } 00707 res = 0; 00708 } 00709 CLEANUP(ast,p); 00710 ast_mutex_unlock(&p->lock); 00711 if (newstate) 00712 ast_setstate(ast, newstate); 00713 return res; 00714 }
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 404 of file chan_agent.c.
References agent_pvt::app_lock, agent_pvt::app_sleep_cond, ast_channel_free(), ast_mutex_destroy(), ast_mutex_unlock(), agent_pvt::dead, free, agent_pvt::lock, agent_pvt::owner, and ast_channel::tech_pvt.
Referenced by check_availability().
00405 { 00406 struct ast_channel *chan = p->owner; 00407 p->owner = NULL; 00408 chan->tech_pvt = NULL; 00409 p->app_sleep_cond = 1; 00410 /* Release ownership of the agent to other threads (presumably running the login app). */ 00411 ast_mutex_unlock(&p->app_lock); 00412 if (chan) 00413 ast_channel_free(chan); 00414 if (p->dead) { 00415 ast_mutex_destroy(&p->lock); 00416 ast_mutex_destroy(&p->app_lock); 00417 free(p); 00418 } 00419 return 0; 00420 }
static int agent_cont_sleep | ( | void * | data | ) | [static] |
Definition at line 837 of file chan_agent.c.
References agent_pvt::app_sleep_cond, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::lastdisc, agent_pvt::lock, LOG_DEBUG, and agent_pvt::wrapuptime.
Referenced by __login_exec().
00838 { 00839 struct agent_pvt *p; 00840 int res; 00841 00842 p = (struct agent_pvt *)data; 00843 00844 ast_mutex_lock(&p->lock); 00845 res = p->app_sleep_cond; 00846 if (p->lastdisc.tv_sec) { 00847 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) 00848 res = 1; 00849 } 00850 ast_mutex_unlock(&p->lock); 00851 #if 0 00852 if( !res ) 00853 ast_log( LOG_DEBUG, "agent_cont_sleep() returning %d\n", res ); 00854 #endif 00855 return res; 00856 }
static int agent_devicestate | ( | void * | data | ) | [static] |
Definition at line 2379 of file chan_agent.c.
References agent_pvt::agent, agents, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, agent_pvt::group, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::next, agent_pvt::owner, agent_pvt::pending, and s.
02380 { 02381 struct agent_pvt *p; 02382 char *s; 02383 ast_group_t groupmatch; 02384 int groupoff; 02385 int waitforagent=0; 02386 int res = AST_DEVICE_INVALID; 02387 02388 s = data; 02389 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02390 groupmatch = (1 << groupoff); 02391 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02392 groupmatch = (1 << groupoff); 02393 waitforagent = 1; 02394 } else { 02395 groupmatch = 0; 02396 } 02397 02398 /* Check actual logged in agents first */ 02399 ast_mutex_lock(&agentlock); 02400 p = agents; 02401 while(p) { 02402 ast_mutex_lock(&p->lock); 02403 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 02404 if (p->owner) { 02405 if (res != AST_DEVICE_INUSE) 02406 res = AST_DEVICE_BUSY; 02407 } else { 02408 if (res == AST_DEVICE_BUSY) 02409 res = AST_DEVICE_INUSE; 02410 if (p->chan || !ast_strlen_zero(p->loginchan)) { 02411 if (res == AST_DEVICE_INVALID) 02412 res = AST_DEVICE_UNKNOWN; 02413 } else if (res == AST_DEVICE_INVALID) 02414 res = AST_DEVICE_UNAVAILABLE; 02415 } 02416 if (!strcmp(data, p->agent)) { 02417 ast_mutex_unlock(&p->lock); 02418 break; 02419 } 02420 } 02421 ast_mutex_unlock(&p->lock); 02422 p = p->next; 02423 } 02424 ast_mutex_unlock(&agentlock); 02425 return res; 02426 }
static int agent_digit | ( | struct ast_channel * | ast, | |
char | digit | |||
) | [static] |
Definition at line 626 of file chan_agent.c.
References ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, agent_pvt::lock, ast_channel_tech::send_digit, ast_channel::tech, and ast_channel::tech_pvt.
00627 { 00628 struct agent_pvt *p = ast->tech_pvt; 00629 int res = -1; 00630 ast_mutex_lock(&p->lock); 00631 if (p->chan) 00632 res = p->chan->tech->send_digit(p->chan, digit); 00633 else 00634 res = 0; 00635 ast_mutex_unlock(&p->lock); 00636 return res; 00637 }
static int agent_fixup | ( | struct ast_channel * | oldchan, | |
struct ast_channel * | newchan | |||
) | [static] |
Definition at line 599 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.
00600 { 00601 struct agent_pvt *p = newchan->tech_pvt; 00602 ast_mutex_lock(&p->lock); 00603 if (p->owner != oldchan) { 00604 ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner); 00605 ast_mutex_unlock(&p->lock); 00606 return -1; 00607 } 00608 p->owner = newchan; 00609 ast_mutex_unlock(&p->lock); 00610 return 0; 00611 }
static int agent_hangup | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 729 of file chan_agent.c.
References ast_channel::_bridge, ast_channel::_state, agent_pvt::abouttograb, agent_pvt::acknowledged, agent_pvt::agent, agent_unlink(), agent_pvt::app_lock, agent_pvt::app_sleep_cond, ast_device_state_changed(), ast_hangup(), ast_log(), AST_MAX_AGENT, ast_moh_start(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_log(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_state2str(), AST_STATE_RESERVED, AST_STATE_UP, ast_strlen_zero(), ast_tvadd(), agent_pvt::autologoff, agent_pvt::chan, agent_pvt::dead, dump_agents(), EVENT_FLAG_AGENT, free, agent_pvt::lastdisc, ast_channel::lock, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::moh, agent_pvt::name, agent_pvt::owner, agent_pvt::pending, set_agentbycallerid(), agent_pvt::start, ast_channel::tech_pvt, ast_channel::uniqueid, usecnt_lock, and agent_pvt::wrapuptime.
00730 { 00731 struct agent_pvt *p = ast->tech_pvt; 00732 int howlong = 0; 00733 ast_mutex_lock(&p->lock); 00734 p->owner = NULL; 00735 ast->tech_pvt = NULL; 00736 p->app_sleep_cond = 1; 00737 p->acknowledged = 0; 00738 00739 /* if they really are hung up then set start to 0 so the test 00740 * later if we're called on an already downed channel 00741 * doesn't cause an agent to be logged out like when 00742 * agent_request() is followed immediately by agent_hangup() 00743 * as in apps/app_chanisavail.c:chanavail_exec() 00744 */ 00745 00746 ast_mutex_lock(&usecnt_lock); 00747 usecnt--; 00748 ast_mutex_unlock(&usecnt_lock); 00749 00750 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state)); 00751 if (p->start && (ast->_state != AST_STATE_UP)) { 00752 howlong = time(NULL) - p->start; 00753 p->start = 0; 00754 } else if (ast->_state == AST_STATE_RESERVED) { 00755 howlong = 0; 00756 } else 00757 p->start = 0; 00758 if (p->chan) { 00759 p->chan->_bridge = NULL; 00760 /* If they're dead, go ahead and hang up on the agent now */ 00761 if (!ast_strlen_zero(p->loginchan)) { 00762 /* Store last disconnect time */ 00763 if (p->wrapuptime) 00764 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00765 else 00766 p->lastdisc = ast_tv(0,0); 00767 if (p->chan) { 00768 /* Recognize the hangup and pass it along immediately */ 00769 ast_hangup(p->chan); 00770 p->chan = NULL; 00771 } 00772 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff); 00773 if (howlong && p->autologoff && (howlong > p->autologoff)) { 00774 char agent[AST_MAX_AGENT] = ""; 00775 long logintime = time(NULL) - p->loginstart; 00776 p->loginstart = 0; 00777 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00778 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 00779 "Agent: %s\r\n" 00780 "Loginchan: %s\r\n" 00781 "Logintime: %ld\r\n" 00782 "Reason: Autologoff\r\n" 00783 "Uniqueid: %s\r\n", 00784 p->agent, p->loginchan, logintime, ast->uniqueid); 00785 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 00786 ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Autologoff"); 00787 set_agentbycallerid(p->logincallerid, NULL); 00788 ast_device_state_changed("Agent/%s", p->agent); 00789 p->loginchan[0] = '\0'; 00790 p->logincallerid[0] = '\0'; 00791 if (persistent_agents) 00792 dump_agents(); 00793 } 00794 } else if (p->dead) { 00795 ast_mutex_lock(&p->chan->lock); 00796 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 00797 ast_mutex_unlock(&p->chan->lock); 00798 } else if (p->loginstart) { 00799 ast_mutex_lock(&p->chan->lock); 00800 ast_moh_start(p->chan, p->moh); 00801 ast_mutex_unlock(&p->chan->lock); 00802 } 00803 } 00804 ast_mutex_unlock(&p->lock); 00805 /* Only register a device state change if the agent is still logged in */ 00806 if (p->loginstart) 00807 ast_device_state_changed("Agent/%s", p->agent); 00808 00809 if (p->pending) { 00810 ast_mutex_lock(&agentlock); 00811 agent_unlink(p); 00812 ast_mutex_unlock(&agentlock); 00813 } 00814 if (p->abouttograb) { 00815 /* Let the "about to grab" thread know this isn't valid anymore, and let it 00816 kill it later */ 00817 p->abouttograb = 0; 00818 } else if (p->dead) { 00819 ast_mutex_destroy(&p->lock); 00820 ast_mutex_destroy(&p->app_lock); 00821 free(p); 00822 } else { 00823 if (p->chan) { 00824 /* Not dead -- check availability now */ 00825 ast_mutex_lock(&p->lock); 00826 /* Store last disconnect time */ 00827 p->lastdisc = ast_tvnow(); 00828 ast_mutex_unlock(&p->lock); 00829 } 00830 /* Release ownership of the agent to other threads (presumably running the login app). */ 00831 if (ast_strlen_zero(p->loginchan)) 00832 ast_mutex_unlock(&p->app_lock); 00833 } 00834 return 0; 00835 }
static int agent_indicate | ( | struct ast_channel * | ast, | |
int | condition | |||
) | [static] |
Definition at line 613 of file chan_agent.c.
References ast_indicate(), ast_mutex_lock(), ast_mutex_unlock(), agent_pvt::chan, agent_pvt::lock, and ast_channel::tech_pvt.
00614 { 00615 struct agent_pvt *p = ast->tech_pvt; 00616 int res = -1; 00617 ast_mutex_lock(&p->lock); 00618 if (p->chan) 00619 res = ast_indicate(p->chan, condition); 00620 else 00621 res = 0; 00622 ast_mutex_unlock(&p->lock); 00623 return res; 00624 }
static int agent_logoff | ( | char * | agent, | |
int | soft | |||
) | [static] |
Definition at line 1471 of file chan_agent.c.
References agent_pvt::agent, agents, ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agent_pvt::chan, agent_pvt::next, and agent_pvt::owner.
Referenced by action_agent_logoff(), and agent_logoff_cmd().
01472 { 01473 struct agent_pvt *p; 01474 long logintime; 01475 int ret = -1; /* Return -1 if no agent if found */ 01476 01477 for (p=agents; p; p=p->next) { 01478 if (!strcasecmp(p->agent, agent)) { 01479 if (!soft) { 01480 if (p->owner) { 01481 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 01482 } 01483 if (p->chan) { 01484 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01485 } 01486 } 01487 ret = 0; /* found an agent => return 0 */ 01488 logintime = time(NULL) - p->loginstart; 01489 p->loginstart = 0; 01490 01491 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01492 "Agent: %s\r\n" 01493 "Loginchan: %s\r\n" 01494 "Logintime: %ld\r\n", 01495 p->agent, p->loginchan, logintime); 01496 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "CommandLogoff"); 01497 set_agentbycallerid(p->logincallerid, NULL); 01498 p->loginchan[0] = '\0'; 01499 p->logincallerid[0] = '\0'; 01500 ast_device_state_changed("Agent/%s", p->agent); 01501 if (persistent_agents) 01502 dump_agents(); 01503 break; 01504 } 01505 } 01506 01507 return ret; 01508 }
static int agent_logoff_cmd | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Definition at line 1510 of file chan_agent.c.
References agent_pvt::agent, agent_logoff(), ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.
01511 { 01512 int ret; 01513 char *agent; 01514 01515 if (argc < 3 || argc > 4) 01516 return RESULT_SHOWUSAGE; 01517 if (argc == 4 && strcasecmp(argv[3], "soft")) 01518 return RESULT_SHOWUSAGE; 01519 01520 agent = argv[2] + 6; 01521 ret = agent_logoff(agent, argc == 4); 01522 if (ret == 0) 01523 ast_cli(fd, "Logging out %s\n", agent); 01524 01525 return RESULT_SUCCESS; 01526 }
static struct ast_channel* agent_new | ( | struct agent_pvt * | p, | |
int | state | |||
) | [static] |
Definition at line 925 of file chan_agent.c.
References agent_pvt::agent, agent_tech, agent_pvt::app_lock, agent_pvt::app_sleep_cond, ast_channel_alloc(), ast_channel_free(), AST_FLAG_BLOCKING, AST_FORMAT_SLINEAR, AST_FRAME_NULL, ast_log(), ast_moh_stop(), ast_mutex_lock(), ast_mutex_trylock(), ast_mutex_unlock(), ast_queue_frame(), ast_setstate(), ast_strlen_zero(), ast_test_flag, ast_update_use_count(), agent_pvt::chan, ast_channel::context, CRASH, ast_channel::exten, ast_channel::language, agent_pvt::lock, LOG_ERROR, LOG_WARNING, agent_pvt::loginchan, ast_channel::name, ast_channel::nativeformats, agent_pvt::owner, agent_pvt::owning_app, agent_pvt::pending, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt_lock, and ast_channel::writeformat.
Referenced by agent_request(), and check_availability().
00926 { 00927 struct ast_channel *tmp; 00928 struct ast_frame null_frame = { AST_FRAME_NULL }; 00929 #if 0 00930 if (!p->chan) { 00931 ast_log(LOG_WARNING, "No channel? :(\n"); 00932 return NULL; 00933 } 00934 #endif 00935 tmp = ast_channel_alloc(0); 00936 if (tmp) { 00937 tmp->tech = &agent_tech; 00938 if (p->chan) { 00939 tmp->nativeformats = p->chan->nativeformats; 00940 tmp->writeformat = p->chan->writeformat; 00941 tmp->rawwriteformat = p->chan->writeformat; 00942 tmp->readformat = p->chan->readformat; 00943 tmp->rawreadformat = p->chan->readformat; 00944 ast_copy_string(tmp->language, p->chan->language, sizeof(tmp->language)); 00945 ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); 00946 ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); 00947 } else { 00948 tmp->nativeformats = AST_FORMAT_SLINEAR; 00949 tmp->writeformat = AST_FORMAT_SLINEAR; 00950 tmp->rawwriteformat = AST_FORMAT_SLINEAR; 00951 tmp->readformat = AST_FORMAT_SLINEAR; 00952 tmp->rawreadformat = AST_FORMAT_SLINEAR; 00953 } 00954 if (p->pending) 00955 snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff); 00956 else 00957 snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent); 00958 tmp->type = channeltype; 00959 /* Safe, agentlock already held */ 00960 ast_setstate(tmp, state); 00961 tmp->tech_pvt = p; 00962 p->owner = tmp; 00963 ast_mutex_lock(&usecnt_lock); 00964 usecnt++; 00965 ast_mutex_unlock(&usecnt_lock); 00966 ast_update_use_count(); 00967 tmp->priority = 1; 00968 /* Wake up and wait for other applications (by definition the login app) 00969 * to release this channel). Takes ownership of the agent channel 00970 * to this thread only. 00971 * For signalling the other thread, ast_queue_frame is used until we 00972 * can safely use signals for this purpose. The pselect() needs to be 00973 * implemented in the kernel for this. 00974 */ 00975 p->app_sleep_cond = 0; 00976 if( ast_strlen_zero(p->loginchan) && ast_mutex_trylock(&p->app_lock) ) 00977 { 00978 if (p->chan) { 00979 ast_queue_frame(p->chan, &null_frame); 00980 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00981 ast_mutex_lock(&p->app_lock); 00982 ast_mutex_lock(&p->lock); 00983 } 00984 if( !p->chan ) 00985 { 00986 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 00987 p->owner = NULL; 00988 tmp->tech_pvt = NULL; 00989 p->app_sleep_cond = 1; 00990 ast_channel_free( tmp ); 00991 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00992 ast_mutex_unlock(&p->app_lock); 00993 return NULL; 00994 } 00995 } else if (!ast_strlen_zero(p->loginchan)) { 00996 if (p->chan) 00997 ast_queue_frame(p->chan, &null_frame); 00998 if (!p->chan) { 00999 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 01000 p->owner = NULL; 01001 tmp->tech_pvt = NULL; 01002 p->app_sleep_cond = 1; 01003 ast_channel_free( tmp ); 01004 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 01005 return NULL; 01006 } 01007 } 01008 p->owning_app = pthread_self(); 01009 /* After the above step, there should not be any blockers. */ 01010 if (p->chan) { 01011 if (ast_test_flag(p->chan, AST_FLAG_BLOCKING)) { 01012 ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" ); 01013 CRASH; 01014 } 01015 ast_moh_stop(p->chan); 01016 } 01017 } else 01018 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); 01019 return tmp; 01020 }
static struct ast_frame * agent_read | ( | struct ast_channel * | ast | ) | [static] |
Definition at line 463 of file chan_agent.c.
References ast_channel::_bridge, ast_channel::_state, agent_pvt::ackcall, agent_pvt::acknowledged, agent_start_monitoring(), AST_CONTROL_ANSWER, ast_copy_flags, AST_FLAG_EXCEPTION, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_NULL, AST_FRAME_VOICE, ast_frfree(), ast_hangup(), ast_log(), AST_MAX_FDS, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), AST_STATE_UP, ast_strlen_zero(), ast_tvadd(), ast_verbose(), agent_pvt::chan, CHECK_FORMATS, CLEANUP, ast_channel::fdno, ast_frame::frametype, agent_pvt::lastdisc, agent_pvt::lock, LOG_DEBUG, agent_pvt::loginchan, ast_channel::name, option_verbose, ast_frame::subclass, ast_channel::tech_pvt, ast_channel::type, VERBOSE_PREFIX_3, and agent_pvt::wrapuptime.
00464 { 00465 struct agent_pvt *p = ast->tech_pvt; 00466 struct ast_frame *f = NULL; 00467 static struct ast_frame null_frame = { AST_FRAME_NULL, }; 00468 static struct ast_frame answer_frame = { AST_FRAME_CONTROL, AST_CONTROL_ANSWER }; 00469 ast_mutex_lock(&p->lock); 00470 CHECK_FORMATS(ast, p); 00471 if (p->chan) { 00472 ast_copy_flags(p->chan, ast, AST_FLAG_EXCEPTION); 00473 if (ast->fdno == AST_MAX_FDS - 3) 00474 p->chan->fdno = AST_MAX_FDS - 2; 00475 else 00476 p->chan->fdno = ast->fdno; 00477 f = ast_read(p->chan); 00478 } else 00479 f = &null_frame; 00480 if (!f) { 00481 /* If there's a channel, hang it up (if it's on a callback) make it NULL */ 00482 if (p->chan) { 00483 p->chan->_bridge = NULL; 00484 /* Note that we don't hangup if it's not a callback because Asterisk will do it 00485 for us when the PBX instance that called login finishes */ 00486 if (!ast_strlen_zero(p->loginchan)) { 00487 if (p->chan) 00488 ast_log(LOG_DEBUG, "Bridge on '%s' being cleared (2)\n", p->chan->name); 00489 ast_hangup(p->chan); 00490 if (p->wrapuptime && p->acknowledged) 00491 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00492 } 00493 p->chan = NULL; 00494 p->acknowledged = 0; 00495 } 00496 } else { 00497 /* if acknowledgement is not required, and the channel is up, we may have missed 00498 an AST_CONTROL_ANSWER (if there was one), so mark the call acknowledged anyway */ 00499 if (!p->ackcall && !p->acknowledged && p->chan && (p->chan->_state == AST_STATE_UP)) 00500 p->acknowledged = 1; 00501 switch (f->frametype) { 00502 case AST_FRAME_CONTROL: 00503 if (f->subclass == AST_CONTROL_ANSWER) { 00504 if (p->ackcall) { 00505 if (option_verbose > 2) 00506 ast_verbose(VERBOSE_PREFIX_3 "%s answered, waiting for '#' to acknowledge\n", p->chan->name); 00507 /* Don't pass answer along */ 00508 ast_frfree(f); 00509 f = &null_frame; 00510 } else { 00511 p->acknowledged = 1; 00512 /* Use the builtin answer frame for the 00513 recording start check below. */ 00514 ast_frfree(f); 00515 f = &answer_frame; 00516 } 00517 } 00518 break; 00519 case AST_FRAME_DTMF: 00520 if (!p->acknowledged && (f->subclass == '#')) { 00521 if (option_verbose > 2) 00522 ast_verbose(VERBOSE_PREFIX_3 "%s acknowledged\n", p->chan->name); 00523 p->acknowledged = 1; 00524 ast_frfree(f); 00525 f = &answer_frame; 00526 } else if (f->subclass == '*') { 00527 /* terminates call */ 00528 ast_frfree(f); 00529 f = NULL; 00530 } 00531 break; 00532 case AST_FRAME_VOICE: 00533 /* don't pass voice until the call is acknowledged */ 00534 if (!p->acknowledged) { 00535 ast_frfree(f); 00536 f = &null_frame; 00537 } 00538 break; 00539 } 00540 } 00541 00542 CLEANUP(ast,p); 00543 if (p->chan && !p->chan->_bridge) { 00544 if (strcasecmp(p->chan->type, "Local")) { 00545 p->chan->_bridge = ast; 00546 if (p->chan) 00547 ast_log(LOG_DEBUG, "Bridge on '%s' being set to '%s' (3)\n", p->chan->name, p->chan->_bridge->name); 00548 } 00549 } 00550 ast_mutex_unlock(&p->lock); 00551 if (recordagentcalls && f == &answer_frame) 00552 agent_start_monitoring(ast,0); 00553 return f; 00554 }
static struct ast_channel * agent_request | ( | const char * | type, | |
int | format, | |||
void * | data, | |||
int * | cause | |||
) | [static] |
Definition at line 1275 of file chan_agent.c.
References add_agent(), agent_pvt::agent, agent_new(), agents, AST_CAUSE_BUSY, AST_CAUSE_UNREGISTERED, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_request(), AST_STATE_DOWN, ast_strlen_zero(), agent_pvt::chan, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, agent_pvt::loginchan, agent_pvt::next, option_debug, agent_pvt::owner, agent_pvt::pending, and s.
01276 { 01277 struct agent_pvt *p; 01278 struct ast_channel *chan = NULL; 01279 char *s; 01280 ast_group_t groupmatch; 01281 int groupoff; 01282 int waitforagent=0; 01283 int hasagent = 0; 01284 struct timeval tv; 01285 01286 s = data; 01287 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01288 groupmatch = (1 << groupoff); 01289 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01290 groupmatch = (1 << groupoff); 01291 waitforagent = 1; 01292 } else { 01293 groupmatch = 0; 01294 } 01295 01296 /* Check actual logged in agents first */ 01297 ast_mutex_lock(&agentlock); 01298 p = agents; 01299 while(p) { 01300 ast_mutex_lock(&p->lock); 01301 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) && 01302 ast_strlen_zero(p->loginchan)) { 01303 if (p->chan) 01304 hasagent++; 01305 if (!p->lastdisc.tv_sec) { 01306 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01307 if (!p->owner && p->chan) { 01308 /* Fixed agent */ 01309 chan = agent_new(p, AST_STATE_DOWN); 01310 } 01311 if (chan) { 01312 ast_mutex_unlock(&p->lock); 01313 break; 01314 } 01315 } 01316 } 01317 ast_mutex_unlock(&p->lock); 01318 p = p->next; 01319 } 01320 if (!p) { 01321 p = agents; 01322 while(p) { 01323 ast_mutex_lock(&p->lock); 01324 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 01325 if (p->chan || !ast_strlen_zero(p->loginchan)) 01326 hasagent++; 01327 tv = ast_tvnow(); 01328 #if 0 01329 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec); 01330 #endif 01331 if (!p->lastdisc.tv_sec || (tv.tv_sec > p->lastdisc.tv_sec)) { 01332 p->lastdisc = ast_tv(0, 0); 01333 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01334 if (!p->owner && p->chan) { 01335 /* Could still get a fixed agent */ 01336 chan = agent_new(p, AST_STATE_DOWN); 01337 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { 01338 /* Adjustable agent */ 01339 p->chan = ast_request("Local", format, p->loginchan, cause); 01340 if (p->chan) 01341 chan = agent_new(p, AST_STATE_DOWN); 01342 } 01343 if (chan) { 01344 ast_mutex_unlock(&p->lock); 01345 break; 01346 } 01347 } 01348 } 01349 ast_mutex_unlock(&p->lock); 01350 p = p->next; 01351 } 01352 } 01353 01354 if (!chan && waitforagent) { 01355 /* No agent available -- but we're requesting to wait for one. 01356 Allocate a place holder */ 01357 if (hasagent) { 01358 if (option_debug) 01359 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s); 01360 p = add_agent(data, 1); 01361 p->group = groupmatch; 01362 chan = agent_new(p, AST_STATE_DOWN); 01363 if (!chan) { 01364 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); 01365 } 01366 } else 01367 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); 01368 } 01369 if (hasagent) 01370 *cause = AST_CAUSE_BUSY; 01371 else 01372 *cause = AST_CAUSE_UNREGISTERED; 01373 ast_mutex_unlock(&agentlock); 01374 return chan; 01375 }
static int agent_sendhtml | ( | struct ast_channel * | ast, | |
int | subclass, | |||
const char * | data, | |||
int | datalen | |||
) | [static] |
Definition at line 556 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.
00557 { 00558 struct agent_pvt *p = ast->tech_pvt; 00559 int res = -1; 00560 ast_mutex_lock(&p->lock); 00561 if (p->chan) 00562 res = ast_channel_sendhtml(p->chan, subclass, data, datalen); 00563 ast_mutex_unlock(&p->lock); 00564 return res; 00565 }
static int agent_sendtext | ( | struct ast_channel * | ast, | |
const char * | text | |||
) | [static] |
Definition at line 567 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.
00568 { 00569 struct agent_pvt *p = ast->tech_pvt; 00570 int res = -1; 00571 ast_mutex_lock(&p->lock); 00572 if (p->chan) 00573 res = ast_sendtext(p->chan, text); 00574 ast_mutex_unlock(&p->lock); 00575 return res; 00576 }
static int agent_start_monitoring | ( | struct ast_channel * | ast, | |
int | needlock | |||
) | [static] |
Definition at line 458 of file chan_agent.c.
References __agent_start_monitoring(), and ast_channel::tech_pvt.
Referenced by agent_call(), and agent_read().
00459 { 00460 return __agent_start_monitoring(ast, ast->tech_pvt, needlock); 00461 }
static void agent_unlink | ( | struct agent_pvt * | agent | ) | [static] |
Unlink (that is, take outside of the linked list) an agent.
agent | Agent to be unlinked. |
Definition at line 281 of file chan_agent.c.
References agent_pvt::agent, agents, and agent_pvt::next.
Referenced by agent_hangup().
00282 { 00283 struct agent_pvt *p, *prev; 00284 prev = NULL; 00285 p = agents; 00286 // Iterate over all agents looking for the one. 00287 while(p) { 00288 if (p == agent) { 00289 // Once it wal found, check if it is the first one. 00290 if (prev) 00291 // If it is not, tell the previous agent that the next one is the next one of the current (jumping the current). 00292 prev->next = agent->next; 00293 else 00294 // If it is the first one, just change the general pointer to point to the second one. 00295 agents = agent->next; 00296 // We are done. 00297 break; 00298 } 00299 prev = p; 00300 p = p->next; 00301 } 00302 }
static int agent_write | ( | struct ast_channel * | ast, | |
struct ast_frame * | f | |||
) | [static] |
Definition at line 578 of file chan_agent.c.
References AST_FRAME_VOICE, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_write(), agent_pvt::chan, CHECK_FORMATS, CLEANUP, ast_frame::frametype, agent_pvt::lock, LOG_DEBUG, ast_channel::name, ast_frame::subclass, ast_channel::tech_pvt, and ast_channel::writeformat.
00579 { 00580 struct agent_pvt *p = ast->tech_pvt; 00581 int res = -1; 00582 CHECK_FORMATS(ast, p); 00583 ast_mutex_lock(&p->lock); 00584 if (p->chan) { 00585 if ((f->frametype != AST_FRAME_VOICE) || 00586 (f->subclass == p->chan->writeformat)) { 00587 res = ast_write(p->chan, f); 00588 } else { 00589 ast_log(LOG_DEBUG, "Dropping one incompatible voice frame on '%s' to '%s'\n", ast->name, p->chan->name); 00590 res = 0; 00591 } 00592 } else 00593 res = 0; 00594 CLEANUP(ast, p); 00595 ast_mutex_unlock(&p->lock); 00596 return res; 00597 }
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 2241 of file chan_agent.c.
References __agent_start_monitoring(), agent_pvt::agent, agents, ast_exists_extension(), ast_log(), AST_MAX_AGENT, AST_MAX_BUF, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_channel::cdr, agent_pvt::chan, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, GETAGENTBYCALLERID, LOG_WARNING, agent_pvt::next, option_verbose, pbx_builtin_getvar_helper(), and VERBOSE_PREFIX_3.
Referenced by load_module().
02242 { 02243 int exitifnoagentid = 0; 02244 int nowarnings = 0; 02245 int changeoutgoing = 0; 02246 int res = 0; 02247 char agent[AST_MAX_AGENT], *tmp; 02248 02249 if (data) { 02250 if (strchr(data, 'd')) 02251 exitifnoagentid = 1; 02252 if (strchr(data, 'n')) 02253 nowarnings = 1; 02254 if (strchr(data, 'c')) 02255 changeoutgoing = 1; 02256 } 02257 if (chan->cid.cid_num) { 02258 char agentvar[AST_MAX_BUF]; 02259 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num); 02260 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) { 02261 struct agent_pvt *p = agents; 02262 ast_copy_string(agent, tmp, sizeof(agent)); 02263 ast_mutex_lock(&agentlock); 02264 while (p) { 02265 if (!strcasecmp(p->agent, tmp)) { 02266 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02267 __agent_start_monitoring(chan, p, 1); 02268 break; 02269 } 02270 p = p->next; 02271 } 02272 ast_mutex_unlock(&agentlock); 02273 02274 } else { 02275 res = -1; 02276 if (!nowarnings) 02277 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); 02278 } 02279 } else { 02280 res = -1; 02281 if (!nowarnings) 02282 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"); 02283 } 02284 /* check if there is n + 101 priority */ 02285 if (res) { 02286 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) { 02287 chan->priority+=100; 02288 if (option_verbose > 2) 02289 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority); 02290 } 02291 else if (exitifnoagentid) 02292 return res; 02293 } 02294 return 0; 02295 }
static int agents_show | ( | int | fd, | |
int | argc, | |||
char ** | argv | |||
) | [static] |
Show agents in cli.
Definition at line 1586 of file chan_agent.c.
References agent_pvt::acknowledged, agent_pvt::agent, agents, ast_bridged_channel(), ast_cli(), AST_MAX_BUF, ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, config, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::moh, moh, ast_channel::name, agent_pvt::name, agent_pvt::next, agent_pvt::owner, agent_pvt::pending, powerof(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and username.
01587 { 01588 struct agent_pvt *p; 01589 char username[AST_MAX_BUF]; 01590 char location[AST_MAX_BUF] = ""; 01591 char talkingto[AST_MAX_BUF] = ""; 01592 char moh[AST_MAX_BUF]; 01593 int count_agents = 0; /* Number of agents configured */ 01594 int online_agents = 0; /* Number of online agents */ 01595 int offline_agents = 0; /* Number of offline agents */ 01596 if (argc != 2) 01597 return RESULT_SHOWUSAGE; 01598 ast_mutex_lock(&agentlock); 01599 p = agents; 01600 while(p) { 01601 ast_mutex_lock(&p->lock); 01602 if (p->pending) { 01603 if (p->group) 01604 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group)); 01605 else 01606 ast_cli(fd, "-- Pending call to agent %s\n", p->agent); 01607 } else { 01608 if (!ast_strlen_zero(p->name)) 01609 snprintf(username, sizeof(username), "(%s) ", p->name); 01610 else 01611 username[0] = '\0'; 01612 if (p->chan) { 01613 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01614 if (p->owner && ast_bridged_channel(p->owner)) { 01615 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01616 } else { 01617 strcpy(talkingto, " is idle"); 01618 } 01619 online_agents++; 01620 } else if (!ast_strlen_zero(p->loginchan)) { 01621 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec)) 01622 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01623 else 01624 snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan); 01625 talkingto[0] = '\0'; 01626 online_agents++; 01627 if (p->acknowledged) 01628 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01629 } else { 01630 strcpy(location, "not logged in"); 01631 talkingto[0] = '\0'; 01632 offline_agents++; 01633 } 01634 if (!ast_strlen_zero(p->moh)) 01635 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01636 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, 01637 username, location, talkingto, moh); 01638 count_agents++; 01639 } 01640 ast_mutex_unlock(&p->lock); 01641 p = p->next; 01642 } 01643 ast_mutex_unlock(&agentlock); 01644 if ( !count_agents ) { 01645 ast_cli(fd, "No Agents are configured in %s\n",config); 01646 } else { 01647 ast_cli(fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents); 01648 } 01649 ast_cli(fd, "\n"); 01650 01651 return RESULT_SUCCESS; 01652 }
AST_MUTEX_DEFINE_STATIC | ( | agentlock | ) |
AST_MUTEX_DEFINE_STATIC | ( | usecnt_lock | ) |
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 2143 of file chan_agent.c.
References __login_exec(), and localuser::chan.
Referenced by load_module().
02144 { 02145 return __login_exec(chan, data, 1); 02146 }
static int check_availability | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1155 of file chan_agent.c.
References agent_pvt::abouttograb, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_cleanup(), agent_new(), agents, ast_channel_masquerade(), AST_FLAG_ZOMBIE, 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::lock, LOG_DEBUG, ast_channel::name, agent_pvt::next, option_debug, agent_pvt::owner, and agent_pvt::pending.
Referenced by __login_exec().
01156 { 01157 struct ast_channel *chan=NULL, *parent=NULL; 01158 struct agent_pvt *p; 01159 int res; 01160 01161 if (option_debug) 01162 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent); 01163 if (needlock) 01164 ast_mutex_lock(&agentlock); 01165 p = agents; 01166 while(p) { 01167 if (p == newlyavailable) { 01168 p = p->next; 01169 continue; 01170 } 01171 ast_mutex_lock(&p->lock); 01172 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01173 if (option_debug) 01174 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01175 /* We found a pending call, time to merge */ 01176 chan = agent_new(newlyavailable, AST_STATE_DOWN); 01177 parent = p->owner; 01178 p->abouttograb = 1; 01179 ast_mutex_unlock(&p->lock); 01180 break; 01181 } 01182 ast_mutex_unlock(&p->lock); 01183 p = p->next; 01184 } 01185 if (needlock) 01186 ast_mutex_unlock(&agentlock); 01187 if (parent && chan) { 01188 if (newlyavailable->ackcall > 1) { 01189 /* Don't do beep here */ 01190 res = 0; 01191 } else { 01192 if (option_debug > 2) 01193 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01194 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01195 if (option_debug > 2) 01196 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01197 if (!res) { 01198 res = ast_waitstream(newlyavailable->chan, ""); 01199 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01200 } 01201 } 01202 if (!res) { 01203 /* Note -- parent may have disappeared */ 01204 if (p->abouttograb) { 01205 newlyavailable->acknowledged = 1; 01206 /* Safe -- agent lock already held */ 01207 ast_setstate(parent, AST_STATE_UP); 01208 ast_setstate(chan, AST_STATE_UP); 01209 ast_copy_string(parent->context, chan->context, sizeof(parent->context)); 01210 /* Go ahead and mark the channel as a zombie so that masquerade will 01211 destroy it for us, and we need not call ast_hangup */ 01212 ast_mutex_lock(&parent->lock); 01213 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01214 ast_channel_masquerade(parent, chan); 01215 ast_mutex_unlock(&parent->lock); 01216 p->abouttograb = 0; 01217 } else { 01218 if (option_debug) 01219 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n"); 01220 agent_cleanup(newlyavailable); 01221 } 01222 } else { 01223 if (option_debug) 01224 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n"); 01225 agent_cleanup(newlyavailable); 01226 } 01227 } 01228 return 0; 01229 }
static int check_beep | ( | struct agent_pvt * | newlyavailable, | |
int | needlock | |||
) | [static] |
Definition at line 1231 of file chan_agent.c.
References agent_pvt::abouttograb, agent_pvt::agent, agents, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_streamfile(), ast_waitstream(), agent_pvt::chan, agent_pvt::group, ast_channel::language, agent_pvt::lock, LOG_DEBUG, ast_channel::name, agent_pvt::next, option_debug, agent_pvt::owner, and agent_pvt::pending.
Referenced by __login_exec().
01232 { 01233 struct agent_pvt *p; 01234 int res=0; 01235 01236 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent); 01237 if (needlock) 01238 ast_mutex_lock(&agentlock); 01239 p = agents; 01240 while(p) { 01241 if (p == newlyavailable) { 01242 p = p->next; 01243 continue; 01244 } 01245 ast_mutex_lock(&p->lock); 01246 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01247 if (option_debug) 01248 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01249 ast_mutex_unlock(&p->lock); 01250 break; 01251 } 01252 ast_mutex_unlock(&p->lock); 01253 p = p->next; 01254 } 01255 if (needlock) 01256 ast_mutex_unlock(&agentlock); 01257 if (p) { 01258 ast_mutex_unlock(&newlyavailable->lock); 01259 if (option_debug > 2) 01260 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01261 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01262 if (option_debug > 2) 01263 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01264 if (!res) { 01265 res = ast_waitstream(newlyavailable->chan, ""); 01266 if (option_debug) 01267 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01268 } 01269 ast_mutex_lock(&newlyavailable->lock); 01270 } 01271 return res; 01272 }
static char* complete_agent_logoff_cmd | ( | char * | line, | |
char * | word, | |||
int | pos, | |||
int | state | |||
) | [static] |
Definition at line 1562 of file chan_agent.c.
References agent_pvt::agent, agents, AST_MAX_AGENT, name, agent_pvt::next, and strdup.
01563 { 01564 struct agent_pvt *p; 01565 char name[AST_MAX_AGENT]; 01566 int which = 0; 01567 01568 if (pos == 2) { 01569 for (p=agents; p; p=p->next) { 01570 snprintf(name, sizeof(name), "Agent/%s", p->agent); 01571 if (!strncasecmp(word, name, strlen(word))) { 01572 if (++which > state) { 01573 return strdup(name); 01574 } 01575 } 01576 } 01577 } else if (pos == 3 && state == 0) { 01578 return strdup("soft"); 01579 } 01580 return NULL; 01581 }
char* description | ( | void | ) |
Provides a description of the module.
Definition at line 2511 of file chan_agent.c.
References desc.
02512 { 02513 return (char *) desc; 02514 }
static void dump_agents | ( | void | ) | [static] |
Dump AgentCallbackLogin agents to the database for persistence
Definition at line 2300 of file chan_agent.c.
References agent_pvt::agent, agents, ast_db_del(), ast_db_put(), ast_log(), ast_strlen_zero(), agent_pvt::chan, LOG_DEBUG, LOG_WARNING, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::next, option_debug, and pa_family.
Referenced by __login_exec(), action_agent_callback_login(), and agent_hangup().
02301 { 02302 struct agent_pvt *cur_agent = NULL; 02303 char buf[256]; 02304 02305 for (cur_agent = agents; cur_agent; cur_agent = cur_agent->next) { 02306 if (cur_agent->chan) 02307 continue; 02308 02309 if (!ast_strlen_zero(cur_agent->loginchan)) { 02310 snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid); 02311 if (ast_db_put(pa_family, cur_agent->agent, buf)) 02312 ast_log(LOG_WARNING, "failed to create persistent entry!\n"); 02313 else if (option_debug) 02314 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan); 02315 } else { 02316 /* Delete - no agent or there is an error */ 02317 ast_db_del(pa_family, cur_agent->agent); 02318 } 02319 } 02320 }
char* key | ( | void | ) |
Returns the ASTERISK_GPL_KEY.
This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:
char *key(void) { return ASTERISK_GPL_KEY; }
Definition at line 2506 of file chan_agent.c.
References ASTERISK_GPL_KEY.
02507 { 02508 return ASTERISK_GPL_KEY; 02509 }
int load_module | ( | void | ) |
Initialize the module.
Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 2434 of file chan_agent.c.
References action_agent_callback_login(), action_agent_logoff(), action_agents(), agent_tech, agentmonitoroutgoing_exec(), app, app2, app3, ast_channel_register(), ast_cli_register(), ast_log(), ast_manager_register2(), ast_register_application(), callback_exec(), channeltype, cli_agent_logoff, cli_show_agents, descrip, descrip2, descrip3, EVENT_FLAG_AGENT, LOG_ERROR, login_exec(), mandescr_agent_callback_login, mandescr_agent_logoff, mandescr_agents, persistent_agents, read_agent_config(), reload_agents(), synopsis, synopsis2, and synopsis3.
02435 { 02436 /* Make sure we can register our agent channel type */ 02437 if (ast_channel_register(&agent_tech)) { 02438 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channeltype); 02439 return -1; 02440 } 02441 /* Dialplan applications */ 02442 ast_register_application(app, login_exec, synopsis, descrip); 02443 ast_register_application(app2, callback_exec, synopsis2, descrip2); 02444 ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3); 02445 /* Manager commands */ 02446 ast_manager_register2("Agents", EVENT_FLAG_AGENT, action_agents, "Lists agents and their status", mandescr_agents); 02447 ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff); 02448 ast_manager_register2("AgentCallbackLogin", EVENT_FLAG_AGENT, action_agent_callback_login, "Sets an agent as logged in by callback", mandescr_agent_callback_login); 02449 /* CLI Application */ 02450 ast_cli_register(&cli_show_agents); 02451 ast_cli_register(&cli_agent_logoff); 02452 /* Read in the config */ 02453 read_agent_config(); 02454 if (persistent_agents) 02455 reload_agents(); 02456 return 0; 02457 }
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 2130 of file chan_agent.c.
References __login_exec(), and localuser::chan.
Referenced by load_module().
02131 { 02132 return __login_exec(chan, data, 0); 02133 }
static int powerof | ( | unsigned int | v | ) | [static] |
Definition at line 1377 of file chan_agent.c.
01378 { 01379 int x; 01380 for (x=0;x<32;x++) { 01381 if (v & (1 << x)) return x; 01382 } 01383 return 0; 01384 }
static int read_agent_config | ( | void | ) | [static] |
Read configuration data. The file named agents.conf.
Definition at line 1028 of file chan_agent.c.
References add_agent(), agents, agent_pvt::app_lock, ast_config_destroy(), ast_config_load(), ast_get_group(), ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), cfg, agent_pvt::chan, agent_pvt::dead, free, agent_pvt::lock, LOG_NOTICE, ast_variable::name, ast_variable::next, agent_pvt::next, agent_pvt::owner, and ast_variable::value.
Referenced by load_module(), and reload().
01029 { 01030 struct ast_config *cfg; 01031 struct ast_variable *v; 01032 struct agent_pvt *p, *pl, *pn; 01033 char *general_val; 01034 01035 group = 0; 01036 autologoff = 0; 01037 wrapuptime = 0; 01038 ackcall = 0; 01039 cfg = ast_config_load(config); 01040 if (!cfg) { 01041 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); 01042 return 0; 01043 } 01044 ast_mutex_lock(&agentlock); 01045 p = agents; 01046 while(p) { 01047 p->dead = 1; 01048 p = p->next; 01049 } 01050 strcpy(moh, "default"); 01051 /* set the default recording values */ 01052 recordagentcalls = 0; 01053 createlink = 0; 01054 strcpy(recordformat, "wav"); 01055 strcpy(recordformatext, "wav"); 01056 urlprefix[0] = '\0'; 01057 savecallsin[0] = '\0'; 01058 01059 /* Read in [general] section for persistence */ 01060 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents"))) 01061 persistent_agents = ast_true(general_val); 01062 01063 /* Read in the [agents] section */ 01064 v = ast_variable_browse(cfg, "agents"); 01065 while(v) { 01066 /* Create the interface list */ 01067 if (!strcasecmp(v->name, "agent")) { 01068 add_agent(v->value, 0); 01069 } else if (!strcasecmp(v->name, "group")) { 01070 group = ast_get_group(v->value); 01071 } else if (!strcasecmp(v->name, "autologoff")) { 01072 autologoff = atoi(v->value); 01073 if (autologoff < 0) 01074 autologoff = 0; 01075 } else if (!strcasecmp(v->name, "ackcall")) { 01076 if (!strcasecmp(v->value, "always")) 01077 ackcall = 2; 01078 else if (ast_true(v->value)) 01079 ackcall = 1; 01080 else 01081 ackcall = 0; 01082 } else if (!strcasecmp(v->name, "wrapuptime")) { 01083 wrapuptime = atoi(v->value); 01084 if (wrapuptime < 0) 01085 wrapuptime = 0; 01086 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { 01087 maxlogintries = atoi(v->value); 01088 if (maxlogintries < 0) 01089 maxlogintries = 0; 01090 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { 01091 strcpy(agentgoodbye,v->value); 01092 } else if (!strcasecmp(v->name, "musiconhold")) { 01093 ast_copy_string(moh, v->value, sizeof(moh)); 01094 } else if (!strcasecmp(v->name, "updatecdr")) { 01095 if (ast_true(v->value)) 01096 updatecdr = 1; 01097 else 01098 updatecdr = 0; 01099 } else if (!strcasecmp(v->name, "recordagentcalls")) { 01100 recordagentcalls = ast_true(v->value); 01101 } else if (!strcasecmp(v->name, "createlink")) { 01102 createlink = ast_true(v->value); 01103 } else if (!strcasecmp(v->name, "recordformat")) { 01104 ast_copy_string(recordformat, v->value, sizeof(recordformat)); 01105 if (!strcasecmp(v->value, "wav49")) 01106 strcpy(recordformatext, "WAV"); 01107 else 01108 ast_copy_string(recordformatext, v->value, sizeof(recordformatext)); 01109 } else if (!strcasecmp(v->name, "urlprefix")) { 01110 ast_copy_string(urlprefix, v->value, sizeof(urlprefix)); 01111 if (urlprefix[strlen(urlprefix) - 1] != '/') 01112 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1); 01113 } else if (!strcasecmp(v->name, "savecallsin")) { 01114 if (v->value[0] == '/') 01115 ast_copy_string(savecallsin, v->value, sizeof(savecallsin)); 01116 else 01117 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value); 01118 if (savecallsin[strlen(savecallsin) - 1] != '/') 01119 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); 01120 } else if (!strcasecmp(v->name, "custom_beep")) { 01121 ast_copy_string(beep, v->value, sizeof(beep)); 01122 } 01123 v = v->next; 01124 } 01125 p = agents; 01126 pl = NULL; 01127 while(p) { 01128 pn = p->next; 01129 if (p->dead) { 01130 /* Unlink */ 01131 if (pl) 01132 pl->next = p->next; 01133 else 01134 agents = p->next; 01135 /* Destroy if appropriate */ 01136 if (!p->owner) { 01137 if (!p->chan) { 01138 ast_mutex_destroy(&p->lock); 01139 ast_mutex_destroy(&p->app_lock); 01140 free(p); 01141 } else { 01142 /* Cause them to hang up */ 01143 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01144 } 01145 } 01146 } else 01147 pl = p; 01148 p = pn; 01149 } 01150 ast_mutex_unlock(&agentlock); 01151 ast_config_destroy(cfg); 01152 return 0; 01153 }
int reload | ( | void | ) |
Reload stuff.
This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.
Definition at line 2459 of file chan_agent.c.
References persistent_agents, read_agent_config(), and reload_agents().
02460 { 02461 read_agent_config(); 02462 if (persistent_agents) 02463 reload_agents(); 02464 return 0; 02465 }
static void reload_agents | ( | void | ) | [static] |
Reload the persistent agents from astdb.
Definition at line 2325 of file chan_agent.c.
References agent_pvt::agent, agents, ast_db_del(), ast_db_freetree(), ast_db_get(), ast_db_gettree(), ast_device_state_changed(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_db_entry::key, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, agent_pvt::next, ast_db_entry::next, option_debug, pa_family, parse(), set_agentbycallerid(), and strsep().
Referenced by load_module(), and reload().
02326 { 02327 char *agent_num; 02328 struct ast_db_entry *db_tree; 02329 struct ast_db_entry *entry; 02330 struct agent_pvt *cur_agent; 02331 char agent_data[256]; 02332 char *parse; 02333 char *agent_chan; 02334 char *agent_callerid; 02335 02336 db_tree = ast_db_gettree(pa_family, NULL); 02337 02338 ast_mutex_lock(&agentlock); 02339 for (entry = db_tree; entry; entry = entry->next) { 02340 agent_num = entry->key + strlen(pa_family) + 2; 02341 cur_agent = agents; 02342 while (cur_agent) { 02343 ast_mutex_lock(&cur_agent->lock); 02344 if (strcmp(agent_num, cur_agent->agent) == 0) 02345 break; 02346 ast_mutex_unlock(&cur_agent->lock); 02347 cur_agent = cur_agent->next; 02348 } 02349 if (!cur_agent) { 02350 ast_db_del(pa_family, agent_num); 02351 continue; 02352 } else 02353 ast_mutex_unlock(&cur_agent->lock); 02354 if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) { 02355 if (option_debug) 02356 ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", cur_agent->agent, agent_data); 02357 parse = agent_data; 02358 agent_chan = strsep(&parse, ";"); 02359 agent_callerid = strsep(&parse, ";"); 02360 ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan)); 02361 if (agent_callerid) { 02362 ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid)); 02363 set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent); 02364 } else 02365 cur_agent->logincallerid[0] = '\0'; 02366 if (cur_agent->loginstart == 0) 02367 time(&cur_agent->loginstart); 02368 ast_device_state_changed("Agent/%s", cur_agent->agent); 02369 } 02370 } 02371 ast_mutex_unlock(&agentlock); 02372 if (db_tree) { 02373 ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n"); 02374 ast_db_freetree(db_tree); 02375 } 02376 }
static void set_agentbycallerid | ( | const char * | callerid, | |
const char * | agent | |||
) | [static] |
Definition at line 717 of file chan_agent.c.
References AST_MAX_BUF, ast_strlen_zero(), GETAGENTBYCALLERID, and pbx_builtin_setvar_helper().
Referenced by __login_exec(), agent_hangup(), and reload_agents().
00718 { 00719 char buf[AST_MAX_BUF]; 00720 00721 /* if there is no Caller ID, nothing to do */ 00722 if (ast_strlen_zero(callerid)) 00723 return; 00724 00725 snprintf(buf, sizeof(buf), "%s_%s",GETAGENTBYCALLERID, callerid); 00726 pbx_builtin_setvar_helper(NULL, buf, agent); 00727 }
int unload_module | ( | void | ) |
Cleanup all module structures, sockets, etc.
This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).
Definition at line 2467 of file chan_agent.c.
References agent_tech, agents, app, app2, app3, ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), cli_agent_logoff, cli_show_agents, LOG_WARNING, agent_pvt::next, and agent_pvt::owner.
02468 { 02469 struct agent_pvt *p; 02470 /* First, take us out of the channel loop */ 02471 /* Unregister CLI application */ 02472 ast_cli_unregister(&cli_show_agents); 02473 ast_cli_unregister(&cli_agent_logoff); 02474 /* Unregister dialplan applications */ 02475 ast_unregister_application(app); 02476 ast_unregister_application(app2); 02477 ast_unregister_application(app3); 02478 /* Unregister manager command */ 02479 ast_manager_unregister("Agents"); 02480 ast_manager_unregister("AgentLogoff"); 02481 ast_manager_unregister("AgentCallbackLogin"); 02482 /* Unregister channel */ 02483 ast_channel_unregister(&agent_tech); 02484 if (!ast_mutex_lock(&agentlock)) { 02485 /* Hangup all interfaces if they have an owner */ 02486 p = agents; 02487 while(p) { 02488 if (p->owner) 02489 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 02490 p = p->next; 02491 } 02492 agents = NULL; 02493 ast_mutex_unlock(&agentlock); 02494 } else { 02495 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02496 return -1; 02497 } 02498 return 0; 02499 }
int usecount | ( | void | ) |
Provides a usecount.
This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.
Definition at line 2501 of file chan_agent.c.
References usecnt.
02502 { 02503 return usecnt; 02504 }
int ackcall [static] |
Definition at line 156 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 1658 of file chan_agent.c.
struct ast_channel_tech agent_tech [static] |
Definition at line 256 of file chan_agent.c.
Referenced by agent_new(), load_module(), and unload_module().
char agentgoodbye[AST_MAX_FILENAME_LEN] = "vm-goodbye" [static] |
Holds the list of agents (loaded form agents.conf).
Definition at line 208 of file chan_agent.c.
Referenced by __login_exec(), action_agent_callback_login(), action_agents(), add_agent(), agent_devicestate(), agent_logoff(), agent_request(), agent_unlink(), agentmonitoroutgoing_exec(), agents_show(), check_availability(), check_beep(), complete_agent_logoff_cmd(), dump_agents(), read_agent_config(), reload_agents(), and unload_module().
const char app[] = "AgentLogin" [static] |
Definition at line 77 of file chan_agent.c.
Referenced by __build_step(), action_originate(), ast_pbx_run_app(), async_wait(), conf_run(), dial_exec_full(), exec_exec(), execif_exec(), feature_exec_app(), fillin_process(), forward_message(), handle_context_add_extension(), handle_exec(), load_config(), load_module(), page_exec(), pbx_builtin_execiftime(), pbx_exec(), pbx_extension_helper(), realtime_exec(), and unload_module().
const char app2[] = "AgentCallbackLogin" [static] |
const char app3[] = "AgentMonitorOutgoing" [static] |
int autologoff [static] |
Definition at line 154 of file chan_agent.c.
char beep[AST_MAX_BUF] = "beep" [static] |
Definition at line 174 of file chan_agent.c.
const char channeltype[] = "Agent" [static] |
Definition at line 73 of file chan_agent.c.
Referenced by func_header_read(), function_sipchaninfo_read(), load_module(), reload_config(), sip_dtmfmode(), and sip_getheader().
struct ast_cli_entry cli_agent_logoff [static] |
Initial value:
{ { "agent", "logoff", NULL }, agent_logoff_cmd, "Sets an agent offline", agent_logoff_usage, complete_agent_logoff_cmd }
Definition at line 1667 of file chan_agent.c.
Referenced by load_module(), and unload_module().
struct ast_cli_entry cli_show_agents [static] |
Initial value:
{ { "show", "agents", NULL }, agents_show, "Show status of agents", show_agents_usage, NULL }
Definition at line 1663 of file chan_agent.c.
Referenced by load_module(), and unload_module().
const char config[] = "agents.conf" [static] |
Definition at line 75 of file chan_agent.c.
int createlink = 0 [static] |
Definition at line 170 of file chan_agent.c.
const char desc[] = "Agent Proxy Channel" [static] |
Definition at line 72 of file chan_agent.c.
Referenced by ast_cause2str(), ast_codec2str(), and description().
const char descrip[] [static] |
const char descrip2[] [static] |
const char descrip3[] [static] |
ast_group_t group [static] |
Definition at line 153 of file chan_agent.c.
Referenced by ast_app_group_set_channel(), ast_get_group(), ast_makesocket(), chanspy_exec(), get_group(), group_count_exec(), group_count_function_read(), group_function_read(), group_match_count_exec(), group_match_count_function_read(), load_module(), main(), misdn_request(), modem_request(), and vpb_request().
Definition at line 1672 of file chan_agent.c.
const char mandescr_agent_callback_login[] [static] |
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 124 of file chan_agent.c.
Referenced by load_module().
const char mandescr_agents[] [static] |
Initial value:
"Description: Will list info about all possible agents.\n" "Variables: NONE\n"
Definition at line 120 of file chan_agent.c.
Referenced by load_module().
int maxlogintries = 3 [static] |
char moh[80] = "default" [static] |
Definition at line 139 of file chan_agent.c.
Referenced by agents_show(), ast_moh_destroy(), dial_exec_full(), get_mohbyname(), init_classes(), moh_generate(), moh_register(), moh_release(), mohalloc(), and monmp3thread().
const char pa_family[] = "/Agents" [static] |
Persistent Agents astdb family
Definition at line 146 of file chan_agent.c.
Referenced by dump_agents(), and reload_agents().
int persistent_agents = 0 [static] |
queues.conf [general] option
Definition at line 150 of file chan_agent.c.
Referenced by __login_exec(), action_agent_callback_login(), load_module(), and reload().
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 172 of file chan_agent.c.
char show_agents_usage[] [static] |
Initial value:
"Usage: show agents\n" " Provides summary information on agents.\n"
Definition at line 1654 of file chan_agent.c.
Definition at line 1671 of file chan_agent.c.
Definition at line 81 of file chan_agent.c.
Referenced by function_enum(), handle_show_application(), handle_show_function(), load_module(), and load_pbx().
const char tdesc[] = "Call Agent Proxy Channel" [static] |
int updatecdr = 0 [static] |
char urlprefix[AST_MAX_BUF] = "" [static] |
int usecnt = 0 [static] |
Definition at line 161 of file chan_agent.c.
Referenced by mgcp_hangup(), mgcp_new(), and usecount().
int wrapuptime [static] |
Definition at line 155 of file chan_agent.c.