#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"
Include dependency graph for chan_agent.c:
Go to the source code of this file.
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 const 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.
|
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(). |
|
Definition at line 142 of file chan_agent.c. Referenced by __agent_start_monitoring(), __login_exec(), agentmonitoroutgoing_exec(), agents_show(), and set_agentbycallerid(). |
|
Definition at line 143 of file chan_agent.c. Referenced by __login_exec(). |
|
Definition at line 210 of file chan_agent.c. Referenced by agent_read(), and agent_write(). |
|
Definition at line 231 of file chan_agent.c. Referenced by agent_call(), agent_read(), and agent_write(). |
|
Definition at line 176 of file chan_agent.c. Referenced by agentmonitoroutgoing_exec(), and set_agentbycallerid(). |
|
The maximum length of each persistent member agent database entry Definition at line 148 of file chan_agent.c. |
|
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, recordformat, recordformatext, savecallsin, ast_channel::uniqueid, and urlprefix. 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 }
|
|
Log in agent application.
Definition at line 1668 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, 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, agent_pvt::chan, check_availability(), check_beep(), context, agent_pvt::dead, dump_agents(), EVENT_FLAG_AGENT, free, 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(), pbx_builtin_setvar_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(). 01669 { 01670 int res=0; 01671 int tries = 0; 01672 int max_login_tries = maxlogintries; 01673 struct agent_pvt *p; 01674 struct localuser *u; 01675 int login_state = 0; 01676 char user[AST_MAX_AGENT] = ""; 01677 char pass[AST_MAX_AGENT]; 01678 char agent[AST_MAX_AGENT] = ""; 01679 char xpass[AST_MAX_AGENT] = ""; 01680 char *errmsg; 01681 char *parse; 01682 AST_DECLARE_APP_ARGS(args, 01683 AST_APP_ARG(agent_id); 01684 AST_APP_ARG(options); 01685 AST_APP_ARG(extension); 01686 ); 01687 char *tmpoptions = NULL; 01688 char *context = NULL; 01689 int play_announcement = 1; 01690 char agent_goodbye[AST_MAX_FILENAME_LEN]; 01691 int update_cdr = updatecdr; 01692 char *filename = "agent-loginok"; 01693 char tmpchan[AST_MAX_BUF] = ""; 01694 01695 LOCAL_USER_ADD(u); 01696 01697 if (!(parse = ast_strdupa(data))) { 01698 ast_log(LOG_ERROR, "Out of memory!\n"); 01699 LOCAL_USER_REMOVE(u); 01700 return -1; 01701 } 01702 01703 AST_STANDARD_APP_ARGS(args, parse); 01704 01705 ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye)); 01706 01707 /* Set Channel Specific Login Overrides */ 01708 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { 01709 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); 01710 if (max_login_tries < 0) 01711 max_login_tries = 0; 01712 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); 01713 if (option_verbose > 2) 01714 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); 01715 } 01716 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { 01717 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) 01718 update_cdr = 1; 01719 else 01720 update_cdr = 0; 01721 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); 01722 if (option_verbose > 2) 01723 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); 01724 } 01725 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { 01726 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); 01727 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); 01728 if (option_verbose > 2) 01729 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); 01730 } 01731 /* End Channel Specific Login Overrides */ 01732 01733 if (callbackmode && args.extension) { 01734 parse = args.extension; 01735 args.extension = strsep(&parse, "@"); 01736 context = parse; 01737 } 01738 01739 if (!ast_strlen_zero(args.options)) { 01740 if (strchr(args.options, 's')) { 01741 play_announcement = 0; 01742 } 01743 } 01744 01745 if (chan->_state != AST_STATE_UP) 01746 res = ast_answer(chan); 01747 if (!res) { 01748 if (!ast_strlen_zero(args.agent_id)) 01749 ast_copy_string(user, args.agent_id, AST_MAX_AGENT); 01750 else 01751 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); 01752 } 01753 while (!res && (max_login_tries==0 || tries < max_login_tries)) { 01754 tries++; 01755 /* Check for password */ 01756 ast_mutex_lock(&agentlock); 01757 p = agents; 01758 while(p) { 01759 if (!strcmp(p->agent, user) && !p->pending) 01760 ast_copy_string(xpass, p->password, sizeof(xpass)); 01761 p = p->next; 01762 } 01763 ast_mutex_unlock(&agentlock); 01764 if (!res) { 01765 if (!ast_strlen_zero(xpass)) 01766 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); 01767 else 01768 pass[0] = '\0'; 01769 } 01770 errmsg = "agent-incorrect"; 01771 01772 #if 0 01773 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); 01774 #endif 01775 01776 /* Check again for accuracy */ 01777 ast_mutex_lock(&agentlock); 01778 p = agents; 01779 while(p) { 01780 ast_mutex_lock(&p->lock); 01781 if (!strcmp(p->agent, user) && 01782 !strcmp(p->password, pass) && !p->pending) { 01783 login_state = 1; /* Successful Login */ 01784 01785 /* Ensure we can't be gotten until we're done */ 01786 gettimeofday(&p->lastdisc, NULL); 01787 p->lastdisc.tv_sec++; 01788 01789 /* Set Channel Specific Agent Overrides */ 01790 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { 01791 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) 01792 p->ackcall = 2; 01793 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) 01794 p->ackcall = 1; 01795 else 01796 p->ackcall = 0; 01797 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); 01798 if (option_verbose > 2) 01799 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); 01800 } 01801 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { 01802 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); 01803 if (p->autologoff < 0) 01804 p->autologoff = 0; 01805 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); 01806 if (option_verbose > 2) 01807 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); 01808 } 01809 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { 01810 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); 01811 if (p->wrapuptime < 0) 01812 p->wrapuptime = 0; 01813 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); 01814 if (option_verbose > 2) 01815 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); 01816 } 01817 /* End Channel Specific Agent Overrides */ 01818 if (!p->chan) { 01819 char last_loginchan[80] = ""; 01820 long logintime; 01821 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 01822 01823 if (callbackmode) { 01824 int pos = 0; 01825 /* Retrieve login chan */ 01826 for (;;) { 01827 if (!ast_strlen_zero(args.extension)) { 01828 ast_copy_string(tmpchan, args.extension, sizeof(tmpchan)); 01829 res = 0; 01830 } else 01831 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0); 01832 if (ast_strlen_zero(tmpchan) || ast_exists_extension(chan, !ast_strlen_zero(context) ? context : "default", tmpchan, 01833 1, NULL)) 01834 break; 01835 if (args.extension) { 01836 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", args.extension, p->agent); 01837 args.extension = NULL; 01838 pos = 0; 01839 } else { 01840 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); 01841 res = ast_streamfile(chan, "invalid", chan->language); 01842 if (!res) 01843 res = ast_waitstream(chan, AST_DIGIT_ANY); 01844 if (res > 0) { 01845 tmpchan[0] = res; 01846 tmpchan[1] = '\0'; 01847 pos = 1; 01848 } else { 01849 tmpchan[0] = '\0'; 01850 pos = 0; 01851 } 01852 } 01853 } 01854 args.extension = tmpchan; 01855 if (!res) { 01856 set_agentbycallerid(p->logincallerid, NULL); 01857 if (!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) 01858 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); 01859 else { 01860 ast_copy_string(last_loginchan, p->loginchan, sizeof(last_loginchan)); 01861 ast_copy_string(p->loginchan, tmpchan, sizeof(p->loginchan)); 01862 } 01863 p->acknowledged = 0; 01864 if (ast_strlen_zero(p->loginchan)) { 01865 login_state = 2; 01866 filename = "agent-loggedoff"; 01867 } else { 01868 if (chan->cid.cid_num) { 01869 ast_copy_string(p->logincallerid, chan->cid.cid_num, sizeof(p->logincallerid)); 01870 set_agentbycallerid(p->logincallerid, p->agent); 01871 } else 01872 p->logincallerid[0] = '\0'; 01873 } 01874 01875 if(update_cdr && chan->cdr) 01876 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01877 01878 } 01879 } else { 01880 p->loginchan[0] = '\0'; 01881 p->logincallerid[0] = '\0'; 01882 p->acknowledged = 0; 01883 } 01884 ast_mutex_unlock(&p->lock); 01885 ast_mutex_unlock(&agentlock); 01886 if( !res && play_announcement==1 ) 01887 res = ast_streamfile(chan, filename, chan->language); 01888 if (!res) 01889 ast_waitstream(chan, ""); 01890 ast_mutex_lock(&agentlock); 01891 ast_mutex_lock(&p->lock); 01892 if (!res) { 01893 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); 01894 if (res) 01895 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); 01896 } 01897 if (!res) { 01898 res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); 01899 if (res) 01900 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); 01901 } 01902 /* Check once more just in case */ 01903 if (p->chan) 01904 res = -1; 01905 if (callbackmode && !res) { 01906 /* Just say goodbye and be done with it */ 01907 if (!ast_strlen_zero(p->loginchan)) { 01908 if (p->loginstart == 0) 01909 time(&p->loginstart); 01910 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 01911 "Agent: %s\r\n" 01912 "Loginchan: %s\r\n" 01913 "Uniqueid: %s\r\n", 01914 p->agent, p->loginchan, chan->uniqueid); 01915 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 01916 if (option_verbose > 1) 01917 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 01918 ast_device_state_changed("Agent/%s", p->agent); 01919 } else { 01920 logintime = time(NULL) - p->loginstart; 01921 p->loginstart = 0; 01922 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01923 "Agent: %s\r\n" 01924 "Loginchan: %s\r\n" 01925 "Logintime: %ld\r\n" 01926 "Uniqueid: %s\r\n", 01927 p->agent, last_loginchan, logintime, chan->uniqueid); 01928 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|", last_loginchan, logintime); 01929 if (option_verbose > 1) 01930 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent); 01931 ast_device_state_changed("Agent/%s", p->agent); 01932 } 01933 ast_mutex_unlock(&agentlock); 01934 if (!res) 01935 res = ast_safe_sleep(chan, 500); 01936 ast_mutex_unlock(&p->lock); 01937 if (persistent_agents) 01938 dump_agents(); 01939 } else if (!res) { 01940 #ifdef HONOR_MUSIC_CLASS 01941 /* check if the moh class was changed with setmusiconhold */ 01942 if (*(chan->musicclass)) 01943 ast_copy_string(p->moh, chan->musicclass, sizeof(p->moh)); 01944 #endif 01945 ast_moh_start(chan, p->moh); 01946 if (p->loginstart == 0) 01947 time(&p->loginstart); 01948 manager_event(EVENT_FLAG_AGENT, "Agentlogin", 01949 "Agent: %s\r\n" 01950 "Channel: %s\r\n" 01951 "Uniqueid: %s\r\n", 01952 p->agent, chan->name, chan->uniqueid); 01953 if (update_cdr && chan->cdr) 01954 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01955 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); 01956 if (option_verbose > 1) 01957 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent, 01958 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); 01959 /* Login this channel and wait for it to 01960 go away */ 01961 p->chan = chan; 01962 if (p->ackcall > 1) 01963 check_beep(p, 0); 01964 else 01965 check_availability(p, 0); 01966 ast_mutex_unlock(&p->lock); 01967 ast_mutex_unlock(&agentlock); 01968 ast_device_state_changed("Agent/%s", p->agent); 01969 while (res >= 0) { 01970 ast_mutex_lock(&p->lock); 01971 if (p->chan != chan) 01972 res = -1; 01973 ast_mutex_unlock(&p->lock); 01974 /* Yield here so other interested threads can kick in. */ 01975 sched_yield(); 01976 if (res) 01977 break; 01978 01979 ast_mutex_lock(&agentlock); 01980 ast_mutex_lock(&p->lock); 01981 if (p->lastdisc.tv_sec) { 01982 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) { 01983 if (option_debug) 01984 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent); 01985 p->lastdisc = ast_tv(0, 0); 01986 if (p->ackcall > 1) 01987 check_beep(p, 0); 01988 else 01989 check_availability(p, 0); 01990 } 01991 } 01992 ast_mutex_unlock(&p->lock); 01993 ast_mutex_unlock(&agentlock); 01994 /* Synchronize channel ownership between call to agent and itself. */ 01995 ast_mutex_lock( &p->app_lock ); 01996 ast_mutex_lock(&p->lock); 01997 p->owning_app = pthread_self(); 01998 ast_mutex_unlock(&p->lock); 01999 if (p->ackcall > 1) 02000 res = agent_ack_sleep(p); 02001 else 02002 res = ast_safe_sleep_conditional( chan, 1000, 02003 agent_cont_sleep, p ); 02004 ast_mutex_unlock( &p->app_lock ); 02005 if ((p->ackcall > 1) && (res == 1)) { 02006 ast_mutex_lock(&agentlock); 02007 ast_mutex_lock(&p->lock); 02008 check_availability(p, 0); 02009 ast_mutex_unlock(&p->lock); 02010 ast_mutex_unlock(&agentlock); 02011 res = 0; 02012 } 02013 sched_yield(); 02014 } 02015 ast_mutex_lock(&p->lock); 02016 if (res && p->owner) 02017 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); 02018 /* Log us off if appropriate */ 02019 if (p->chan == chan) 02020 p->chan = NULL; 02021 p->acknowledged = 0; 02022 logintime = time(NULL) - p->loginstart; 02023 p->loginstart = 0; 02024 ast_mutex_unlock(&p->lock); 02025 manager_event(EVENT_FLAG_AGENT, "Agentlogoff", 02026 "Agent: %s\r\n" 02027 "Logintime: %ld\r\n" 02028 "Uniqueid: %s\r\n", 02029 p->agent, logintime, chan->uniqueid); 02030 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); 02031 if (option_verbose > 1) 02032 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent); 02033 /* If there is no owner, go ahead and kill it now */ 02034 ast_device_state_changed("Agent/%s", p->agent); 02035 if (p->dead && !p->owner) { 02036 ast_mutex_destroy(&p->lock); 02037 ast_mutex_destroy(&p->app_lock); 02038 free(p); 02039 } 02040 } 02041 else { 02042 ast_mutex_unlock(&p->lock); 02043 p = NULL; 02044 } 02045 res = -1; 02046 } else { 02047 ast_mutex_unlock(&p->lock); 02048 errmsg = "agent-alreadyon"; 02049 p = NULL; 02050 } 02051 break; 02052 } 02053 ast_mutex_unlock(&p->lock); 02054 p = p->next; 02055 } 02056 if (!p) 02057 ast_mutex_unlock(&agentlock); 02058 02059 if (!res && (max_login_tries==0 || tries < max_login_tries)) 02060 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); 02061 } 02062 02063 if (!res) 02064 res = ast_safe_sleep(chan, 500); 02065 02066 /* AgentLogin() exit */ 02067 if (!callbackmode) { 02068 LOCAL_USER_REMOVE(u); 02069 return -1; 02070 } 02071 /* AgentCallbackLogin() exit*/ 02072 else { 02073 /* Set variables */ 02074 if (login_state > 0) { 02075 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); 02076 if (login_state==1) { 02077 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); 02078 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", args.extension); 02079 } 02080 else { 02081 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); 02082 } 02083 } 02084 else { 02085 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); 02086 } 02087 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) { 02088 LOCAL_USER_REMOVE(u); 02089 return 0; 02090 } 02091 /* Do we need to play agent-goodbye now that we will be hanging up? */ 02092 if (play_announcement) { 02093 if (!res) 02094 res = ast_safe_sleep(chan, 1000); 02095 res = ast_streamfile(chan, agent_goodbye, chan->language); 02096 if (!res) 02097 res = ast_waitstream(chan, ""); 02098 if (!res) 02099 res = ast_safe_sleep(chan, 1000); 02100 } 02101 } 02102 02103 LOCAL_USER_REMOVE(u); 02104 02105 /* We should never get here if next priority exists when in callbackmode */ 02106 return -1; 02107 }
|
|
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.
Definition at line 2143 of file chan_agent.c. References agent_pvt::ackcall, agent_pvt::agent, 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, VERBOSE_PREFIX_2, and agent_pvt::wrapuptime. Referenced by load_module(). 02144 { 02145 char *agent = astman_get_header(m, "Agent"); 02146 char *exten = astman_get_header(m, "Exten"); 02147 char *context = astman_get_header(m, "Context"); 02148 char *wrapuptime_s = astman_get_header(m, "WrapupTime"); 02149 char *ackcall_s = astman_get_header(m, "AckCall"); 02150 struct agent_pvt *p; 02151 int login_state = 0; 02152 02153 if (ast_strlen_zero(agent)) { 02154 astman_send_error(s, m, "No agent specified"); 02155 return 0; 02156 } 02157 02158 if (ast_strlen_zero(exten)) { 02159 astman_send_error(s, m, "No extension specified"); 02160 return 0; 02161 } 02162 02163 ast_mutex_lock(&agentlock); 02164 p = agents; 02165 while(p) { 02166 if (strcmp(p->agent, agent) || p->pending) { 02167 p = p->next; 02168 continue; 02169 } 02170 if (p->chan) { 02171 login_state = 2; /* already logged in (and on the phone)*/ 02172 break; 02173 } 02174 ast_mutex_lock(&p->lock); 02175 login_state = 1; /* Successful Login */ 02176 02177 if (ast_strlen_zero(context)) 02178 ast_copy_string(p->loginchan, exten, sizeof(p->loginchan)); 02179 else 02180 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context); 02181 02182 if (!ast_strlen_zero(wrapuptime_s)) { 02183 p->wrapuptime = atoi(wrapuptime_s); 02184 if (p->wrapuptime < 0) 02185 p->wrapuptime = 0; 02186 } 02187 02188 if (ast_true(ackcall_s)) 02189 p->ackcall = 1; 02190 else 02191 p->ackcall = 0; 02192 02193 if (p->loginstart == 0) 02194 time(&p->loginstart); 02195 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02196 "Agent: %s\r\n" 02197 "Loginchan: %s\r\n", 02198 p->agent, p->loginchan); 02199 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02200 if (option_verbose > 1) 02201 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02202 ast_device_state_changed("Agent/%s", p->agent); 02203 ast_mutex_unlock(&p->lock); 02204 p = p->next; 02205 if (persistent_agents) 02206 dump_agents(); 02207 } 02208 ast_mutex_unlock(&agentlock); 02209 02210 if (login_state == 1) 02211 astman_send_ack(s, m, "Agent logged in"); 02212 else if (login_state == 0) 02213 astman_send_error(s, m, "No such agent"); 02214 else if (login_state == 2) 02215 astman_send_error(s, m, "Agent already logged in"); 02216 02217 return 0; 02218 }
|
|
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.
Definition at line 1523 of file chan_agent.c. References agent_pvt::agent, agent_logoff(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), and astman_send_error(). Referenced by load_module(). 01524 { 01525 char *agent = astman_get_header(m, "Agent"); 01526 char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */ 01527 int soft; 01528 int ret; /* return value of agent_logoff */ 01529 01530 if (ast_strlen_zero(agent)) { 01531 astman_send_error(s, m, "No agent specified"); 01532 return 0; 01533 } 01534 01535 if (ast_true(soft_s)) 01536 soft = 1; 01537 else 01538 soft = 0; 01539 01540 ret = agent_logoff(agent, soft); 01541 if (ret == 0) 01542 astman_send_ack(s, m, "Agent logged out"); 01543 else 01544 astman_send_error(s, m, "No such agent"); 01545 01546 return 0; 01547 }
|
|
Lists agents and their status to the Manager API. It is registered on load_module() and it gets called by the manager backend.
Definition at line 1381 of file chan_agent.c. References ast_channel::_bridge, agent_pvt::acknowledged, agent_pvt::agent, 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, and username. Referenced by load_module(). 01382 { 01383 char *id = astman_get_header(m,"ActionID"); 01384 char idText[256] = ""; 01385 char chanbuf[256]; 01386 struct agent_pvt *p; 01387 char *username = NULL; 01388 char *loginChan = NULL; 01389 char *talkingtoChan = NULL; 01390 char *status = NULL; 01391 01392 if (!ast_strlen_zero(id)) 01393 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); 01394 astman_send_ack(s, m, "Agents will follow"); 01395 ast_mutex_lock(&agentlock); 01396 p = agents; 01397 while(p) { 01398 ast_mutex_lock(&p->lock); 01399 01400 /* Status Values: 01401 AGENT_LOGGEDOFF - Agent isn't logged in 01402 AGENT_IDLE - Agent is logged in, and waiting for call 01403 AGENT_ONCALL - Agent is logged in, and on a call 01404 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */ 01405 01406 if(!ast_strlen_zero(p->name)) { 01407 username = p->name; 01408 } else { 01409 username = "None"; 01410 } 01411 01412 /* Set a default status. It 'should' get changed. */ 01413 status = "AGENT_UNKNOWN"; 01414 01415 if (!ast_strlen_zero(p->loginchan) && !p->chan) { 01416 loginChan = p->loginchan; 01417 talkingtoChan = "n/a"; 01418 status = "AGENT_IDLE"; 01419 if (p->acknowledged) { 01420 snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan); 01421 loginChan = chanbuf; 01422 } 01423 } else if (p->chan) { 01424 loginChan = ast_strdupa(p->chan->name); 01425 if (p->owner && p->owner->_bridge) { 01426 talkingtoChan = p->chan->cid.cid_num; 01427 status = "AGENT_ONCALL"; 01428 } else { 01429 talkingtoChan = "n/a"; 01430 status = "AGENT_IDLE"; 01431 } 01432 } else { 01433 loginChan = "n/a"; 01434 talkingtoChan = "n/a"; 01435 status = "AGENT_LOGGEDOFF"; 01436 } 01437 01438 ast_cli(s->fd, "Event: Agents\r\n" 01439 "Agent: %s\r\n" 01440 "Name: %s\r\n" 01441 "Status: %s\r\n" 01442 "LoggedInChan: %s\r\n" 01443 "LoggedInTime: %d\r\n" 01444 "TalkingTo: %s\r\n" 01445 "%s" 01446 "\r\n", 01447 p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText); 01448 ast_mutex_unlock(&p->lock); 01449 p = p->next; 01450 } 01451 ast_mutex_unlock(&agentlock); 01452 ast_cli(s->fd, "Event: AgentsComplete\r\n" 01453 "%s" 01454 "\r\n",idText); 01455 return 0; 01456 }
|
|
Adds an agent to the global list of agents.
Definition at line 312 of file chan_agent.c. References ackcall, agent_pvt::ackcall, agent_pvt::agent, ast_app_separate_args(), ast_log(), ast_mutex_init(), ast_strdupa, autologoff, agent_pvt::autologoff, agent_pvt::dead, group, agent_pvt::lastdisc, LOG_WARNING, malloc, moh, agent_pvt::moh, agent_pvt::name, name, agent_pvt::next, agent_pvt::password, password, wrapuptime, 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 }
|
|
Definition at line 857 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(). 00858 { 00859 struct agent_pvt *p; 00860 int res=0; 00861 int to = 1000; 00862 struct ast_frame *f; 00863 00864 /* Wait a second and look for something */ 00865 00866 p = (struct agent_pvt *)data; 00867 if (p->chan) { 00868 for(;;) { 00869 to = ast_waitfor(p->chan, to); 00870 if (to < 0) { 00871 res = -1; 00872 break; 00873 } 00874 if (!to) { 00875 res = 0; 00876 break; 00877 } 00878 f = ast_read(p->chan); 00879 if (!f) { 00880 res = -1; 00881 break; 00882 } 00883 if (f->frametype == AST_FRAME_DTMF) 00884 res = f->subclass; 00885 else 00886 res = 0; 00887 ast_frfree(f); 00888 ast_mutex_lock(&p->lock); 00889 if (!p->app_sleep_cond) { 00890 ast_mutex_unlock(&p->lock); 00891 res = 0; 00892 break; 00893 } else if (res == '#') { 00894 ast_mutex_unlock(&p->lock); 00895 res = 1; 00896 break; 00897 } 00898 ast_mutex_unlock(&p->lock); 00899 res = 0; 00900 } 00901 } else 00902 res = -1; 00903 return res; 00904 }
|
|
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 }
|
|
Definition at line 906 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. 00907 { 00908 struct agent_pvt *p = bridge->tech_pvt; 00909 struct ast_channel *ret=NULL; 00910 00911 if (p) { 00912 if (chan == p->chan) 00913 ret = bridge->_bridge; 00914 else if (chan == bridge->_bridge) 00915 ret = p->chan; 00916 } 00917 00918 if (option_debug) 00919 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>"); 00920 return ret; 00921 }
|
|
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(), beep, 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, recordagentcalls, 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 }
|
|
Deletes an agent after doing some clean up. Further documentation: How safe is this function ? What state should the agent be to be cleaned.
Definition at line 404 of file chan_agent.c. References ast_channel_free(), ast_mutex_destroy(), ast_mutex_unlock(), free, 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 }
|
|
Definition at line 836 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(). 00837 { 00838 struct agent_pvt *p; 00839 int res; 00840 00841 p = (struct agent_pvt *)data; 00842 00843 ast_mutex_lock(&p->lock); 00844 res = p->app_sleep_cond; 00845 if (p->lastdisc.tv_sec) { 00846 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) 00847 res = 1; 00848 } 00849 ast_mutex_unlock(&p->lock); 00850 #if 0 00851 if( !res ) 00852 ast_log( LOG_DEBUG, "agent_cont_sleep() returning %d\n", res ); 00853 #endif 00854 return res; 00855 }
|
|
Definition at line 2366 of file chan_agent.c. References agent_pvt::agent, AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, ast_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. 02367 { 02368 struct agent_pvt *p; 02369 char *s; 02370 ast_group_t groupmatch; 02371 int groupoff; 02372 int waitforagent=0; 02373 int res = AST_DEVICE_INVALID; 02374 02375 s = data; 02376 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02377 groupmatch = (1 << groupoff); 02378 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02379 groupmatch = (1 << groupoff); 02380 waitforagent = 1; 02381 } else { 02382 groupmatch = 0; 02383 } 02384 02385 /* Check actual logged in agents first */ 02386 ast_mutex_lock(&agentlock); 02387 p = agents; 02388 while(p) { 02389 ast_mutex_lock(&p->lock); 02390 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 02391 if (p->owner) { 02392 if (res != AST_DEVICE_INUSE) 02393 res = AST_DEVICE_BUSY; 02394 } else { 02395 if (res == AST_DEVICE_BUSY) 02396 res = AST_DEVICE_INUSE; 02397 if (p->chan || !ast_strlen_zero(p->loginchan)) { 02398 if (res == AST_DEVICE_INVALID) 02399 res = AST_DEVICE_UNKNOWN; 02400 } else if (res == AST_DEVICE_INVALID) 02401 res = AST_DEVICE_UNAVAILABLE; 02402 } 02403 if (!strcmp(data, p->agent)) { 02404 ast_mutex_unlock(&p->lock); 02405 break; 02406 } 02407 } 02408 ast_mutex_unlock(&p->lock); 02409 p = p->next; 02410 } 02411 ast_mutex_unlock(&agentlock); 02412 return res; 02413 }
|
|
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 }
|
|
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 }
|
|
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, persistent_agents, set_agentbycallerid(), agent_pvt::start, ast_channel::tech_pvt, ast_channel::uniqueid, usecnt, 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 ast_mutex_unlock(&p->app_lock); 00832 } 00833 return 0; 00834 }
|
|
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 }
|
|
Definition at line 1458 of file chan_agent.c. References agent_pvt::agent, ast_device_state_changed(), ast_queue_log(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, agent_pvt::chan, dump_agents(), EVENT_FLAG_AGENT, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::next, agent_pvt::owner, persistent_agents, and set_agentbycallerid(). Referenced by action_agent_logoff(), and agent_logoff_cmd(). 01459 { 01460 struct agent_pvt *p; 01461 long logintime; 01462 int ret = -1; /* Return -1 if no agent if found */ 01463 01464 for (p=agents; p; p=p->next) { 01465 if (!strcasecmp(p->agent, agent)) { 01466 if (!soft) { 01467 if (p->owner) { 01468 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 01469 } 01470 if (p->chan) { 01471 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01472 } 01473 } 01474 ret = 0; /* found an agent => return 0 */ 01475 logintime = time(NULL) - p->loginstart; 01476 p->loginstart = 0; 01477 01478 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01479 "Agent: %s\r\n" 01480 "Loginchan: %s\r\n" 01481 "Logintime: %ld\r\n", 01482 p->agent, p->loginchan, logintime); 01483 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "CommandLogoff"); 01484 set_agentbycallerid(p->logincallerid, NULL); 01485 p->loginchan[0] = '\0'; 01486 p->logincallerid[0] = '\0'; 01487 ast_device_state_changed("Agent/%s", p->agent); 01488 if (persistent_agents) 01489 dump_agents(); 01490 break; 01491 } 01492 } 01493 01494 return ret; 01495 }
|
|
Definition at line 1497 of file chan_agent.c. References agent_pvt::agent, agent_logoff(), ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS. 01498 { 01499 int ret; 01500 char *agent; 01501 01502 if (argc < 3 || argc > 4) 01503 return RESULT_SHOWUSAGE; 01504 if (argc == 4 && strcasecmp(argv[3], "soft")) 01505 return RESULT_SHOWUSAGE; 01506 01507 agent = argv[2] + 6; 01508 ret = agent_logoff(agent, argc == 4); 01509 if (ret == 0) 01510 ast_cli(fd, "Logging out %s\n", agent); 01511 01512 return RESULT_SUCCESS; 01513 }
|
|
Definition at line 924 of file chan_agent.c. References agent_pvt::agent, 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_test_flag, ast_update_use_count(), agent_pvt::chan, channeltype, ast_channel::context, CRASH, ast_channel::exten, ast_channel::language, agent_pvt::lock, LOG_ERROR, LOG_WARNING, 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, usecnt_lock, and ast_channel::writeformat. Referenced by agent_request(), and check_availability(). 00925 { 00926 struct ast_channel *tmp; 00927 struct ast_frame null_frame = { AST_FRAME_NULL }; 00928 #if 0 00929 if (!p->chan) { 00930 ast_log(LOG_WARNING, "No channel? :(\n"); 00931 return NULL; 00932 } 00933 #endif 00934 tmp = ast_channel_alloc(0); 00935 if (tmp) { 00936 tmp->tech = &agent_tech; 00937 if (p->chan) { 00938 tmp->nativeformats = p->chan->nativeformats; 00939 tmp->writeformat = p->chan->writeformat; 00940 tmp->rawwriteformat = p->chan->writeformat; 00941 tmp->readformat = p->chan->readformat; 00942 tmp->rawreadformat = p->chan->readformat; 00943 ast_copy_string(tmp->language, p->chan->language, sizeof(tmp->language)); 00944 ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); 00945 ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); 00946 } else { 00947 tmp->nativeformats = AST_FORMAT_SLINEAR; 00948 tmp->writeformat = AST_FORMAT_SLINEAR; 00949 tmp->rawwriteformat = AST_FORMAT_SLINEAR; 00950 tmp->readformat = AST_FORMAT_SLINEAR; 00951 tmp->rawreadformat = AST_FORMAT_SLINEAR; 00952 } 00953 if (p->pending) 00954 snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff); 00955 else 00956 snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent); 00957 tmp->type = channeltype; 00958 /* Safe, agentlock already held */ 00959 ast_setstate(tmp, state); 00960 tmp->tech_pvt = p; 00961 p->owner = tmp; 00962 ast_mutex_lock(&usecnt_lock); 00963 usecnt++; 00964 ast_mutex_unlock(&usecnt_lock); 00965 ast_update_use_count(); 00966 tmp->priority = 1; 00967 /* Wake up and wait for other applications (by definition the login app) 00968 * to release this channel). Takes ownership of the agent channel 00969 * to this thread only. 00970 * For signalling the other thread, ast_queue_frame is used until we 00971 * can safely use signals for this purpose. The pselect() needs to be 00972 * implemented in the kernel for this. 00973 */ 00974 p->app_sleep_cond = 0; 00975 if( ast_mutex_trylock(&p->app_lock) ) 00976 { 00977 if (p->chan) { 00978 ast_queue_frame(p->chan, &null_frame); 00979 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00980 ast_mutex_lock(&p->app_lock); 00981 ast_mutex_lock(&p->lock); 00982 } 00983 if( !p->chan ) 00984 { 00985 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 00986 p->owner = NULL; 00987 tmp->tech_pvt = NULL; 00988 p->app_sleep_cond = 1; 00989 ast_channel_free( tmp ); 00990 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00991 ast_mutex_unlock(&p->app_lock); 00992 return NULL; 00993 } 00994 } 00995 p->owning_app = pthread_self(); 00996 /* After the above step, there should not be any blockers. */ 00997 if (p->chan) { 00998 if (ast_test_flag(p->chan, AST_FLAG_BLOCKING)) { 00999 ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" ); 01000 CRASH; 01001 } 01002 ast_moh_stop(p->chan); 01003 } 01004 } else 01005 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); 01006 return tmp; 01007 }
|
|
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, recordagentcalls, 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 }
|
|
Definition at line 1262 of file chan_agent.c. References add_agent(), agent_pvt::agent, agent_new(), 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. 01263 { 01264 struct agent_pvt *p; 01265 struct ast_channel *chan = NULL; 01266 char *s; 01267 ast_group_t groupmatch; 01268 int groupoff; 01269 int waitforagent=0; 01270 int hasagent = 0; 01271 struct timeval tv; 01272 01273 s = data; 01274 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01275 groupmatch = (1 << groupoff); 01276 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01277 groupmatch = (1 << groupoff); 01278 waitforagent = 1; 01279 } else { 01280 groupmatch = 0; 01281 } 01282 01283 /* Check actual logged in agents first */ 01284 ast_mutex_lock(&agentlock); 01285 p = agents; 01286 while(p) { 01287 ast_mutex_lock(&p->lock); 01288 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) && 01289 ast_strlen_zero(p->loginchan)) { 01290 if (p->chan) 01291 hasagent++; 01292 if (!p->lastdisc.tv_sec) { 01293 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01294 if (!p->owner && p->chan) { 01295 /* Fixed agent */ 01296 chan = agent_new(p, AST_STATE_DOWN); 01297 } 01298 if (chan) { 01299 ast_mutex_unlock(&p->lock); 01300 break; 01301 } 01302 } 01303 } 01304 ast_mutex_unlock(&p->lock); 01305 p = p->next; 01306 } 01307 if (!p) { 01308 p = agents; 01309 while(p) { 01310 ast_mutex_lock(&p->lock); 01311 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 01312 if (p->chan || !ast_strlen_zero(p->loginchan)) 01313 hasagent++; 01314 tv = ast_tvnow(); 01315 #if 0 01316 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec); 01317 #endif 01318 if (!p->lastdisc.tv_sec || (tv.tv_sec > p->lastdisc.tv_sec)) { 01319 p->lastdisc = ast_tv(0, 0); 01320 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01321 if (!p->owner && p->chan) { 01322 /* Could still get a fixed agent */ 01323 chan = agent_new(p, AST_STATE_DOWN); 01324 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { 01325 /* Adjustable agent */ 01326 p->chan = ast_request("Local", format, p->loginchan, cause); 01327 if (p->chan) 01328 chan = agent_new(p, AST_STATE_DOWN); 01329 } 01330 if (chan) { 01331 ast_mutex_unlock(&p->lock); 01332 break; 01333 } 01334 } 01335 } 01336 ast_mutex_unlock(&p->lock); 01337 p = p->next; 01338 } 01339 } 01340 01341 if (!chan && waitforagent) { 01342 /* No agent available -- but we're requesting to wait for one. 01343 Allocate a place holder */ 01344 if (hasagent) { 01345 if (option_debug) 01346 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s); 01347 p = add_agent(data, 1); 01348 p->group = groupmatch; 01349 chan = agent_new(p, AST_STATE_DOWN); 01350 if (!chan) { 01351 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); 01352 } 01353 } else 01354 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); 01355 } 01356 if (hasagent) 01357 *cause = AST_CAUSE_BUSY; 01358 else 01359 *cause = AST_CAUSE_UNREGISTERED; 01360 ast_mutex_unlock(&agentlock); 01361 return chan; 01362 }
|
|
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 }
|
|
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 }
|
|
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 }
|
|
Unlink (that is, take outside of the linked list) an agent.
Definition at line 281 of file chan_agent.c. References 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 }
|
|
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 }
|
|
Called by the AgentMonitorOutgoing application (from the dial plan).
Definition at line 2228 of file chan_agent.c. References __agent_start_monitoring(), agent_pvt::agent, ast_exists_extension(), ast_log(), AST_MAX_AGENT, AST_MAX_BUF, ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_channel::cdr, 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(). 02229 { 02230 int exitifnoagentid = 0; 02231 int nowarnings = 0; 02232 int changeoutgoing = 0; 02233 int res = 0; 02234 char agent[AST_MAX_AGENT], *tmp; 02235 02236 if (data) { 02237 if (strchr(data, 'd')) 02238 exitifnoagentid = 1; 02239 if (strchr(data, 'n')) 02240 nowarnings = 1; 02241 if (strchr(data, 'c')) 02242 changeoutgoing = 1; 02243 } 02244 if (chan->cid.cid_num) { 02245 char agentvar[AST_MAX_BUF]; 02246 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num); 02247 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) { 02248 struct agent_pvt *p = agents; 02249 ast_copy_string(agent, tmp, sizeof(agent)); 02250 ast_mutex_lock(&agentlock); 02251 while (p) { 02252 if (!strcasecmp(p->agent, tmp)) { 02253 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02254 __agent_start_monitoring(chan, p, 1); 02255 break; 02256 } 02257 p = p->next; 02258 } 02259 ast_mutex_unlock(&agentlock); 02260 02261 } else { 02262 res = -1; 02263 if (!nowarnings) 02264 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); 02265 } 02266 } else { 02267 res = -1; 02268 if (!nowarnings) 02269 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"); 02270 } 02271 /* check if there is n + 101 priority */ 02272 if (res) { 02273 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) { 02274 chan->priority+=100; 02275 if (option_verbose > 2) 02276 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority); 02277 } 02278 else if (exitifnoagentid) 02279 return res; 02280 } 02281 return 0; 02282 }
|
|
Show agents in cli. Definition at line 1573 of file chan_agent.c. References agent_pvt::acknowledged, agent_pvt::agent, 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. 01574 { 01575 struct agent_pvt *p; 01576 char username[AST_MAX_BUF]; 01577 char location[AST_MAX_BUF] = ""; 01578 char talkingto[AST_MAX_BUF] = ""; 01579 char moh[AST_MAX_BUF]; 01580 int count_agents = 0; /* Number of agents configured */ 01581 int online_agents = 0; /* Number of online agents */ 01582 int offline_agents = 0; /* Number of offline agents */ 01583 if (argc != 2) 01584 return RESULT_SHOWUSAGE; 01585 ast_mutex_lock(&agentlock); 01586 p = agents; 01587 while(p) { 01588 ast_mutex_lock(&p->lock); 01589 if (p->pending) { 01590 if (p->group) 01591 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group)); 01592 else 01593 ast_cli(fd, "-- Pending call to agent %s\n", p->agent); 01594 } else { 01595 if (!ast_strlen_zero(p->name)) 01596 snprintf(username, sizeof(username), "(%s) ", p->name); 01597 else 01598 username[0] = '\0'; 01599 if (p->chan) { 01600 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01601 if (p->owner && ast_bridged_channel(p->owner)) { 01602 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01603 } else { 01604 strcpy(talkingto, " is idle"); 01605 } 01606 online_agents++; 01607 } else if (!ast_strlen_zero(p->loginchan)) { 01608 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > 0 || !(p->lastdisc.tv_sec)) 01609 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01610 else 01611 snprintf(location, sizeof(location) - 20, "wrapping up at '%s'", p->loginchan); 01612 talkingto[0] = '\0'; 01613 online_agents++; 01614 if (p->acknowledged) 01615 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01616 } else { 01617 strcpy(location, "not logged in"); 01618 talkingto[0] = '\0'; 01619 offline_agents++; 01620 } 01621 if (!ast_strlen_zero(p->moh)) 01622 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01623 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, 01624 username, location, talkingto, moh); 01625 count_agents++; 01626 } 01627 ast_mutex_unlock(&p->lock); 01628 p = p->next; 01629 } 01630 ast_mutex_unlock(&agentlock); 01631 if ( !count_agents ) { 01632 ast_cli(fd, "No Agents are configured in %s\n",config); 01633 } else { 01634 ast_cli(fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents); 01635 } 01636 ast_cli(fd, "\n"); 01637 01638 return RESULT_SUCCESS; 01639 }
|
|
|
|
|
|
Called by the AgentCallbackLogin application (from the dial plan).
Definition at line 2130 of file chan_agent.c. References __login_exec(). Referenced by load_module(). 02131 { 02132 return __login_exec(chan, data, 1); 02133 }
|
|
Definition at line 1142 of file chan_agent.c. References agent_pvt::abouttograb, agent_pvt::ackcall, agent_pvt::acknowledged, agent_pvt::agent, agent_cleanup(), agent_new(), ast_channel_masquerade(), AST_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(), beep, 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(). 01143 { 01144 struct ast_channel *chan=NULL, *parent=NULL; 01145 struct agent_pvt *p; 01146 int res; 01147 01148 if (option_debug) 01149 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent); 01150 if (needlock) 01151 ast_mutex_lock(&agentlock); 01152 p = agents; 01153 while(p) { 01154 if (p == newlyavailable) { 01155 p = p->next; 01156 continue; 01157 } 01158 ast_mutex_lock(&p->lock); 01159 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01160 if (option_debug) 01161 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01162 /* We found a pending call, time to merge */ 01163 chan = agent_new(newlyavailable, AST_STATE_DOWN); 01164 parent = p->owner; 01165 p->abouttograb = 1; 01166 ast_mutex_unlock(&p->lock); 01167 break; 01168 } 01169 ast_mutex_unlock(&p->lock); 01170 p = p->next; 01171 } 01172 if (needlock) 01173 ast_mutex_unlock(&agentlock); 01174 if (parent && chan) { 01175 if (newlyavailable->ackcall > 1) { 01176 /* Don't do beep here */ 01177 res = 0; 01178 } else { 01179 if (option_debug > 2) 01180 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01181 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01182 if (option_debug > 2) 01183 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01184 if (!res) { 01185 res = ast_waitstream(newlyavailable->chan, ""); 01186 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01187 } 01188 } 01189 if (!res) { 01190 /* Note -- parent may have disappeared */ 01191 if (p->abouttograb) { 01192 newlyavailable->acknowledged = 1; 01193 /* Safe -- agent lock already held */ 01194 ast_setstate(parent, AST_STATE_UP); 01195 ast_setstate(chan, AST_STATE_UP); 01196 ast_copy_string(parent->context, chan->context, sizeof(parent->context)); 01197 /* Go ahead and mark the channel as a zombie so that masquerade will 01198 destroy it for us, and we need not call ast_hangup */ 01199 ast_mutex_lock(&parent->lock); 01200 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01201 ast_channel_masquerade(parent, chan); 01202 ast_mutex_unlock(&parent->lock); 01203 p->abouttograb = 0; 01204 } else { 01205 if (option_debug) 01206 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n"); 01207 agent_cleanup(newlyavailable); 01208 } 01209 } else { 01210 if (option_debug) 01211 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n"); 01212 agent_cleanup(newlyavailable); 01213 } 01214 } 01215 return 0; 01216 }
|
|
Definition at line 1218 of file chan_agent.c. References agent_pvt::abouttograb, agent_pvt::agent, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_streamfile(), ast_waitstream(), beep, 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(). 01219 { 01220 struct agent_pvt *p; 01221 int res=0; 01222 01223 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent); 01224 if (needlock) 01225 ast_mutex_lock(&agentlock); 01226 p = agents; 01227 while(p) { 01228 if (p == newlyavailable) { 01229 p = p->next; 01230 continue; 01231 } 01232 ast_mutex_lock(&p->lock); 01233 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01234 if (option_debug) 01235 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01236 ast_mutex_unlock(&p->lock); 01237 break; 01238 } 01239 ast_mutex_unlock(&p->lock); 01240 p = p->next; 01241 } 01242 if (needlock) 01243 ast_mutex_unlock(&agentlock); 01244 if (p) { 01245 ast_mutex_unlock(&newlyavailable->lock); 01246 if (option_debug > 2) 01247 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01248 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01249 if (option_debug > 2) 01250 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01251 if (!res) { 01252 res = ast_waitstream(newlyavailable->chan, ""); 01253 if (option_debug) 01254 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01255 } 01256 ast_mutex_lock(&newlyavailable->lock); 01257 } 01258 return res; 01259 }
|
|
Definition at line 1549 of file chan_agent.c. References agent_pvt::agent, AST_MAX_AGENT, name, agent_pvt::next, and strdup. 01550 { 01551 struct agent_pvt *p; 01552 char name[AST_MAX_AGENT]; 01553 int which = 0; 01554 01555 if (pos == 2) { 01556 for (p=agents; p; p=p->next) { 01557 snprintf(name, sizeof(name), "Agent/%s", p->agent); 01558 if (!strncasecmp(word, name, strlen(word))) { 01559 if (++which > state) { 01560 return strdup(name); 01561 } 01562 } 01563 } 01564 } else if (pos == 3 && state == 0) { 01565 return strdup("soft"); 01566 } 01567 return NULL; 01568 }
|
|
Provides a description of the module.
Definition at line 2498 of file chan_agent.c. References desc. 02499 { 02500 return (char *) desc; 02501 }
|
|
Dump AgentCallbackLogin agents to the database for persistence Definition at line 2287 of file chan_agent.c. References agent_pvt::agent, 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(), agent_hangup(), and agent_logoff(). 02288 { 02289 struct agent_pvt *cur_agent = NULL; 02290 char buf[256]; 02291 02292 for (cur_agent = agents; cur_agent; cur_agent = cur_agent->next) { 02293 if (cur_agent->chan) 02294 continue; 02295 02296 if (!ast_strlen_zero(cur_agent->loginchan)) { 02297 snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid); 02298 if (ast_db_put(pa_family, cur_agent->agent, buf)) 02299 ast_log(LOG_WARNING, "failed to create persistent entry!\n"); 02300 else if (option_debug) 02301 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan); 02302 } else { 02303 /* Delete - no agent or there is an error */ 02304 ast_db_del(pa_family, cur_agent->agent); 02305 } 02306 } 02307 }
|
|
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 2493 of file chan_agent.c. References ASTERISK_GPL_KEY. 02494 { 02495 return ASTERISK_GPL_KEY; 02496 }
|
|
|
Called by the AgentLogin application (from the dial plan).
Definition at line 2117 of file chan_agent.c. References __login_exec(). Referenced by load_module(). 02118 { 02119 return __login_exec(chan, data, 0); 02120 }
|
|
Definition at line 1364 of file chan_agent.c. 01365 { 01366 int x; 01367 for (x=0;x<32;x++) { 01368 if (v & (1 << x)) return x; 01369 } 01370 return 0; 01371 }
|
|
Read configuration data. The file named agents.conf.
Definition at line 1015 of file chan_agent.c. References ackcall, add_agent(), agentgoodbye, 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(), autologoff, beep, cfg, agent_pvt::chan, config, createlink, agent_pvt::dead, free, group, agent_pvt::lock, LOG_NOTICE, maxlogintries, moh, ast_variable::name, ast_variable::next, agent_pvt::next, agent_pvt::owner, persistent_agents, recordagentcalls, recordformat, recordformatext, savecallsin, updatecdr, urlprefix, ast_variable::value, and wrapuptime. Referenced by load_module(), and reload(). 01016 { 01017 struct ast_config *cfg; 01018 struct ast_variable *v; 01019 struct agent_pvt *p, *pl, *pn; 01020 char *general_val; 01021 01022 group = 0; 01023 autologoff = 0; 01024 wrapuptime = 0; 01025 ackcall = 0; 01026 cfg = ast_config_load(config); 01027 if (!cfg) { 01028 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); 01029 return 0; 01030 } 01031 ast_mutex_lock(&agentlock); 01032 p = agents; 01033 while(p) { 01034 p->dead = 1; 01035 p = p->next; 01036 } 01037 strcpy(moh, "default"); 01038 /* set the default recording values */ 01039 recordagentcalls = 0; 01040 createlink = 0; 01041 strcpy(recordformat, "wav"); 01042 strcpy(recordformatext, "wav"); 01043 urlprefix[0] = '\0'; 01044 savecallsin[0] = '\0'; 01045 01046 /* Read in [general] section for persistence */ 01047 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents"))) 01048 persistent_agents = ast_true(general_val); 01049 01050 /* Read in the [agents] section */ 01051 v = ast_variable_browse(cfg, "agents"); 01052 while(v) { 01053 /* Create the interface list */ 01054 if (!strcasecmp(v->name, "agent")) { 01055 add_agent(v->value, 0); 01056 } else if (!strcasecmp(v->name, "group")) { 01057 group = ast_get_group(v->value); 01058 } else if (!strcasecmp(v->name, "autologoff")) { 01059 autologoff = atoi(v->value); 01060 if (autologoff < 0) 01061 autologoff = 0; 01062 } else if (!strcasecmp(v->name, "ackcall")) { 01063 if (!strcasecmp(v->value, "always")) 01064 ackcall = 2; 01065 else if (ast_true(v->value)) 01066 ackcall = 1; 01067 else 01068 ackcall = 0; 01069 } else if (!strcasecmp(v->name, "wrapuptime")) { 01070 wrapuptime = atoi(v->value); 01071 if (wrapuptime < 0) 01072 wrapuptime = 0; 01073 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { 01074 maxlogintries = atoi(v->value); 01075 if (maxlogintries < 0) 01076 maxlogintries = 0; 01077 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { 01078 strcpy(agentgoodbye,v->value); 01079 } else if (!strcasecmp(v->name, "musiconhold")) { 01080 ast_copy_string(moh, v->value, sizeof(moh)); 01081 } else if (!strcasecmp(v->name, "updatecdr")) { 01082 if (ast_true(v->value)) 01083 updatecdr = 1; 01084 else 01085 updatecdr = 0; 01086 } else if (!strcasecmp(v->name, "recordagentcalls")) { 01087 recordagentcalls = ast_true(v->value); 01088 } else if (!strcasecmp(v->name, "createlink")) { 01089 createlink = ast_true(v->value); 01090 } else if (!strcasecmp(v->name, "recordformat")) { 01091 ast_copy_string(recordformat, v->value, sizeof(recordformat)); 01092 if (!strcasecmp(v->value, "wav49")) 01093 strcpy(recordformatext, "WAV"); 01094 else 01095 ast_copy_string(recordformatext, v->value, sizeof(recordformatext)); 01096 } else if (!strcasecmp(v->name, "urlprefix")) { 01097 ast_copy_string(urlprefix, v->value, sizeof(urlprefix)); 01098 if (urlprefix[strlen(urlprefix) - 1] != '/') 01099 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1); 01100 } else if (!strcasecmp(v->name, "savecallsin")) { 01101 if (v->value[0] == '/') 01102 ast_copy_string(savecallsin, v->value, sizeof(savecallsin)); 01103 else 01104 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value); 01105 if (savecallsin[strlen(savecallsin) - 1] != '/') 01106 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); 01107 } else if (!strcasecmp(v->name, "custom_beep")) { 01108 ast_copy_string(beep, v->value, sizeof(beep)); 01109 } 01110 v = v->next; 01111 } 01112 p = agents; 01113 pl = NULL; 01114 while(p) { 01115 pn = p->next; 01116 if (p->dead) { 01117 /* Unlink */ 01118 if (pl) 01119 pl->next = p->next; 01120 else 01121 agents = p->next; 01122 /* Destroy if appropriate */ 01123 if (!p->owner) { 01124 if (!p->chan) { 01125 ast_mutex_destroy(&p->lock); 01126 ast_mutex_destroy(&p->app_lock); 01127 free(p); 01128 } else { 01129 /* Cause them to hang up */ 01130 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01131 } 01132 } 01133 } else 01134 pl = p; 01135 p = pn; 01136 } 01137 ast_mutex_unlock(&agentlock); 01138 ast_config_destroy(cfg); 01139 return 0; 01140 }
|
|
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 2446 of file chan_agent.c. References persistent_agents, read_agent_config(), and reload_agents(). 02447 { 02448 read_agent_config(); 02449 if (persistent_agents) 02450 reload_agents(); 02451 return 0; 02452 }
|
|
Reload the persistent agents from astdb. Definition at line 2312 of file chan_agent.c. References agent_pvt::agent, 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(). 02313 { 02314 char *agent_num; 02315 struct ast_db_entry *db_tree; 02316 struct ast_db_entry *entry; 02317 struct agent_pvt *cur_agent; 02318 char agent_data[256]; 02319 char *parse; 02320 char *agent_chan; 02321 char *agent_callerid; 02322 02323 db_tree = ast_db_gettree(pa_family, NULL); 02324 02325 ast_mutex_lock(&agentlock); 02326 for (entry = db_tree; entry; entry = entry->next) { 02327 agent_num = entry->key + strlen(pa_family) + 2; 02328 cur_agent = agents; 02329 while (cur_agent) { 02330 ast_mutex_lock(&cur_agent->lock); 02331 if (strcmp(agent_num, cur_agent->agent) == 0) 02332 break; 02333 ast_mutex_unlock(&cur_agent->lock); 02334 cur_agent = cur_agent->next; 02335 } 02336 if (!cur_agent) { 02337 ast_db_del(pa_family, agent_num); 02338 continue; 02339 } else 02340 ast_mutex_unlock(&cur_agent->lock); 02341 if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) { 02342 if (option_debug) 02343 ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", cur_agent->agent, agent_data); 02344 parse = agent_data; 02345 agent_chan = strsep(&parse, ";"); 02346 agent_callerid = strsep(&parse, ";"); 02347 ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan)); 02348 if (agent_callerid) { 02349 ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid)); 02350 set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent); 02351 } else 02352 cur_agent->logincallerid[0] = '\0'; 02353 if (cur_agent->loginstart == 0) 02354 time(&cur_agent->loginstart); 02355 ast_device_state_changed("Agent/%s", cur_agent->agent); 02356 } 02357 } 02358 ast_mutex_unlock(&agentlock); 02359 if (db_tree) { 02360 ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n"); 02361 ast_db_freetree(db_tree); 02362 } 02363 }
|
|
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(), agent_logoff(), 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 }
|
|
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 2454 of file chan_agent.c. References 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(), LOG_WARNING, agent_pvt::next, and agent_pvt::owner. 02455 { 02456 struct agent_pvt *p; 02457 /* First, take us out of the channel loop */ 02458 /* Unregister CLI application */ 02459 ast_cli_unregister(&cli_show_agents); 02460 ast_cli_unregister(&cli_agent_logoff); 02461 /* Unregister dialplan applications */ 02462 ast_unregister_application(app); 02463 ast_unregister_application(app2); 02464 ast_unregister_application(app3); 02465 /* Unregister manager command */ 02466 ast_manager_unregister("Agents"); 02467 ast_manager_unregister("AgentLogoff"); 02468 ast_manager_unregister("AgentCallbackLogin"); 02469 /* Unregister channel */ 02470 ast_channel_unregister(&agent_tech); 02471 if (!ast_mutex_lock(&agentlock)) { 02472 /* Hangup all interfaces if they have an owner */ 02473 p = agents; 02474 while(p) { 02475 if (p->owner) 02476 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 02477 p = p->next; 02478 } 02479 agents = NULL; 02480 ast_mutex_unlock(&agentlock); 02481 } else { 02482 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02483 return -1; 02484 } 02485 return 0; 02486 }
|
|
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 2488 of file chan_agent.c. References usecnt. 02489 { 02490 return usecnt; 02491 }
|
|
Definition at line 156 of file chan_agent.c. Referenced by add_agent(), and read_agent_config(). |
|
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 1645 of file chan_agent.c. |
|
Definition at line 256 of file chan_agent.c. |
|
Definition at line 159 of file chan_agent.c. Referenced by __login_exec(), and read_agent_config(). |
|
Holds the list of agents (loaded form agents.conf). Definition at line 208 of file chan_agent.c. |
|
Definition at line 77 of file chan_agent.c. Referenced by __build_step(), action_originate(), app_exec(), conf_run(), dial_exec_full(), exec_exec(), execif_exec(), feature_exec_app(), fillin_process(), handle_context_add_extension(), handle_exec(), load_config(), load_module(), page_exec(), pbx_extension_helper(), realtime_exec(), and unload_module(). |
|
Definition at line 78 of file chan_agent.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 79 of file chan_agent.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 154 of file chan_agent.c. Referenced by add_agent(), and read_agent_config(). |
|
Definition at line 174 of file chan_agent.c. Referenced by agent_call(), check_availability(), check_beep(), and read_agent_config(). |
|
Definition at line 73 of file chan_agent.c. Referenced by agent_new(), ast_iax2_new(), func_header_read(), function_sipchaninfo_read(), iax2_bridge(), iax2_prov_app(), load_module(), register_peer_exten(), reload_config(), set_config(), sip_dtmfmode(), sip_getheader(), and sip_new(). |
|
Initial value: { { "agent", "logoff", NULL }, agent_logoff_cmd, "Sets an agent offline", agent_logoff_usage, complete_agent_logoff_cmd } Definition at line 1654 of file chan_agent.c. |
|
Initial value: { { "show", "agents", NULL }, agents_show, "Show status of agents", show_agents_usage, NULL } Definition at line 1650 of file chan_agent.c. |
|
Definition at line 75 of file chan_agent.c. |
|
Definition at line 170 of file chan_agent.c. Referenced by read_agent_config(). |
|
Definition at line 72 of file chan_agent.c. Referenced by description(), load_module(), odbc_load_module(), process_my_load_module(), and tds_load_module(). |
|
Definition at line 85 of file chan_agent.c. Referenced by load_module(). |
|
Definition at line 94 of file chan_agent.c. Referenced by load_module(). |
|
Definition at line 102 of file chan_agent.c. Referenced by load_module(). |
|
Definition at line 153 of file chan_agent.c. Referenced by add_agent(), 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(), read_agent_config(), and vpb_request(). |
|
Definition at line 1659 of file chan_agent.c. |
|
Definition at line 130 of file chan_agent.c. Referenced by load_module(). |
|
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(). |
|
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(). |
|
Definition at line 158 of file chan_agent.c. Referenced by __login_exec(), and read_agent_config(). |
|
Definition at line 139 of file chan_agent.c. Referenced by add_agent(), agents_show(), ast_moh_destroy(), dial_exec_full(), get_mohbyname(), init_classes(), moh_generate(), moh_release(), mohalloc(), monmp3thread(), and read_agent_config(). |
|
Persistent Agents astdb family Definition at line 146 of file chan_agent.c. Referenced by dump_agents(), and reload_agents(). |
|
queues.conf [general] option Definition at line 150 of file chan_agent.c. Referenced by __login_exec(), action_agent_callback_login(), agent_hangup(), agent_logoff(), load_module(), read_agent_config(), and reload(). |
|
Definition at line 167 of file chan_agent.c. Referenced by agent_call(), agent_read(), and read_agent_config(). |
|
Definition at line 168 of file chan_agent.c. Referenced by __agent_start_monitoring(), and read_agent_config(). |
|
Definition at line 169 of file chan_agent.c. Referenced by __agent_start_monitoring(), and read_agent_config(). |
|
Definition at line 172 of file chan_agent.c. Referenced by __agent_start_monitoring(), and read_agent_config(). |
|
Initial value: "Usage: show agents\n" " Provides summary information on agents.\n" Definition at line 1641 of file chan_agent.c. |
|
Definition at line 1658 of file chan_agent.c. |
|
Definition at line 81 of file chan_agent.c. Referenced by description(), function_enum(), handle_show_application(), handle_show_function(), load_module(), and load_pbx(). |
|
Definition at line 82 of file chan_agent.c. Referenced by load_module(). |
|
Definition at line 83 of file chan_agent.c. Referenced by load_module(). |
|
Definition at line 74 of file chan_agent.c. Referenced by description(), load_module(), and rpt_tele_thread(). |
|
Definition at line 173 of file chan_agent.c. Referenced by __login_exec(), and read_agent_config(). |
|
Definition at line 171 of file chan_agent.c. Referenced by __agent_start_monitoring(), read_agent_config(), and start_monitor_exec(). |
|
|
Definition at line 155 of file chan_agent.c. Referenced by add_agent(), and read_agent_config(). |