#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/file.h"
#include "asterisk/cli.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/manager.h"
#include "asterisk/features.h"
#include "asterisk/utils.h"
#include "asterisk/causes.h"
#include "asterisk/astdb.h"
#include "asterisk/devicestate.h"
#include "asterisk/monitor.h"
Go to the source code of this file.
Data Structures | |
struct | agent_pvt |
Defines | |
#define | AST_MAX_AGENT 80 |
#define | AST_MAX_BUF 256 |
#define | AST_MAX_FILENAME_LEN 256 |
#define | CHECK_FORMATS(ast, p) |
#define | CLEANUP(ast, p) |
#define | GETAGENTBYCALLERID "AGENTBYCALLERID" |
#define | PA_MAX_LEN 2048 |
Functions | |
int | __agent_start_monitoring (struct ast_channel *ast, struct agent_pvt *p, int needlock) |
int | __login_exec (struct ast_channel *chan, void *data, int callbackmode) |
Log in agent application. | |
int | action_agent_callback_login (struct mansession *s, struct message *m) |
int | action_agent_logoff (struct mansession *s, struct message *m) |
int | action_agents (struct mansession *s, struct message *m) |
agent_pvt * | add_agent (char *agent, int pending) |
int | agent_ack_sleep (void *data) |
int | agent_answer (struct ast_channel *ast) |
ast_channel * | agent_bridgedchannel (struct ast_channel *chan, struct ast_channel *bridge) |
int | agent_call (struct ast_channel *ast, char *dest, int timeout) |
int | agent_cleanup (struct agent_pvt *p) |
int | agent_cont_sleep (void *data) |
int | agent_devicestate (void *data) |
int | agent_digit (struct ast_channel *ast, char digit) |
int | agent_fixup (struct ast_channel *oldchan, struct ast_channel *newchan) |
int | agent_hangup (struct ast_channel *ast) |
int | agent_indicate (struct ast_channel *ast, int condition) |
int | agent_logoff (char *agent, int soft) |
int | agent_logoff_cmd (int fd, int argc, char **argv) |
ast_channel * | agent_new (struct agent_pvt *p, int state) |
ast_frame * | agent_read (struct ast_channel *ast) |
ast_channel * | agent_request (const char *type, int format, void *data, int *cause) |
int | agent_sendhtml (struct ast_channel *ast, int subclass, const char *data, int datalen) |
int | agent_sendtext (struct ast_channel *ast, const char *text) |
int | agent_start_monitoring (struct ast_channel *ast, int needlock) |
void | agent_unlink (struct agent_pvt *agent) |
int | agent_write (struct ast_channel *ast, struct ast_frame *f) |
int | agentmonitoroutgoing_exec (struct ast_channel *chan, void *data) |
int | agents_show (int fd, int argc, char **argv) |
AST_MUTEX_DEFINE_STATIC (agentlock) | |
AST_MUTEX_DEFINE_STATIC (usecnt_lock) | |
int | callback_exec (struct ast_channel *chan, void *data) |
int | check_availability (struct agent_pvt *newlyavailable, int needlock) |
int | check_beep (struct agent_pvt *newlyavailable, int needlock) |
char * | complete_agent_logoff_cmd (char *line, char *word, int pos, int state) |
char * | description () |
Provides a description of the module. | |
void | dump_agents (void) |
char * | key () |
Returns the ASTERISK_GPL_KEY. | |
int | load_module () |
Initialize the module. | |
int | login_exec (struct ast_channel *chan, void *data) |
int | powerof (unsigned int v) |
int | read_agent_config (void) |
int | reload () |
Reload stuff. | |
void | reload_agents (void) |
void | set_agentbycallerid (const char *callerid, const char *agent) |
int | unload_module () |
Cleanup all module structures, sockets, etc. | |
int | usecount () |
Provides a usecount. | |
Variables | |
int | ackcall |
char | agent_logoff_usage [] |
const struct ast_channel_tech | agent_tech |
char | agentgoodbye [AST_MAX_FILENAME_LEN] = "vm-goodbye" |
agent_pvt * | agents = NULL |
const char | app [] = "AgentLogin" |
const char | app2 [] = "AgentCallbackLogin" |
const char | app3 [] = "AgentMonitorOutgoing" |
int | autologoff |
char | beep [AST_MAX_BUF] = "beep" |
const char | channeltype [] = "Agent" |
ast_cli_entry | cli_agent_logoff |
ast_cli_entry | cli_show_agents |
const char | config [] = "agents.conf" |
int | createlink = 0 |
const char | desc [] = "Agent Proxy Channel" |
const char | descrip [] |
const char | descrip2 [] |
const char | descrip3 [] |
ast_group_t | group |
LOCAL_USER_DECL | |
const char | mandescr_agent_callback_login [] |
const char | mandescr_agent_logoff [] |
const char | mandescr_agents [] |
int | maxlogintries = 3 |
char | moh [80] = "default" |
const char | pa_family [] = "/Agents" |
int | persistent_agents = 0 |
int | recordagentcalls = 0 |
char | recordformat [AST_MAX_BUF] = "" |
char | recordformatext [AST_MAX_BUF] = "" |
char | savecallsin [AST_MAX_BUF] = "" |
char | show_agents_usage [] |
STANDARD_LOCAL_USER | |
const char | synopsis [] = "Call agent login" |
const char | synopsis2 [] = "Call agent callback login" |
const char | synopsis3 [] = "Record agent's outgoing call" |
const char | tdesc [] = "Call Agent Proxy Channel" |
int | updatecdr = 0 |
char | urlprefix [AST_MAX_BUF] = "" |
int | usecnt = 0 |
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(). |
|
Definition at line 142 of file chan_agent.c. |
|
Definition at line 143 of file chan_agent.c. |
|
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_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 1673 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_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_strdupa, ast_streamfile(), ast_strlen_zero(), ast_true(), ast_verbose(), ast_waitstream(), agent_pvt::autologoff, ast_channel::cdr, agent_pvt::chan, ast_cdr::channel, check_availability(), check_beep(), ast_channel::cid, ast_callerid::cid_num, ast_channel::context, agent_pvt::dead, dump_agents(), EVENT_FLAG_AGENT, ast_channel::exten, free, ast_channel::language, agent_pvt::lastdisc, LOCAL_USER_ADD, LOCAL_USER_REMOVE, agent_pvt::lock, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::moh, ast_channel::musicclass, ast_channel::name, ast_channel::nativeformats, agent_pvt::next, option_verbose, agent_pvt::owner, agent_pvt::owning_app, agent_pvt::password, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), agent_pvt::pending, ast_channel::priority, ast_channel::readformat, set_agentbycallerid(), strsep(), ast_channel::uniqueid, VERBOSE_PREFIX_2, VERBOSE_PREFIX_3, agent_pvt::wrapuptime, and ast_channel::writeformat. Referenced by callback_exec(), and login_exec(). 01674 { 01675 int res=0; 01676 int tries = 0; 01677 int max_login_tries = maxlogintries; 01678 struct agent_pvt *p; 01679 struct localuser *u; 01680 int login_state = 0; 01681 char user[AST_MAX_AGENT] = ""; 01682 char pass[AST_MAX_AGENT]; 01683 char agent[AST_MAX_AGENT] = ""; 01684 char xpass[AST_MAX_AGENT] = ""; 01685 char *errmsg; 01686 char *parse; 01687 AST_DECLARE_APP_ARGS(args, 01688 AST_APP_ARG(agent_id); 01689 AST_APP_ARG(options); 01690 AST_APP_ARG(extension); 01691 ); 01692 char *tmpoptions = NULL; 01693 char *context = NULL; 01694 int play_announcement = 1; 01695 char agent_goodbye[AST_MAX_FILENAME_LEN]; 01696 int update_cdr = updatecdr; 01697 char *filename = "agent-loginok"; 01698 char tmpchan[AST_MAX_BUF] = ""; 01699 01700 LOCAL_USER_ADD(u); 01701 01702 if (!(parse = ast_strdupa(data))) { 01703 ast_log(LOG_ERROR, "Out of memory!\n"); 01704 LOCAL_USER_REMOVE(u); 01705 return -1; 01706 } 01707 01708 AST_STANDARD_APP_ARGS(args, parse); 01709 01710 ast_copy_string(agent_goodbye, agentgoodbye, sizeof(agent_goodbye)); 01711 01712 /* Set Channel Specific Login Overrides */ 01713 if (pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES") && strlen(pbx_builtin_getvar_helper(chan, "AGENTLMAXLOGINTRIES"))) { 01714 max_login_tries = atoi(pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES")); 01715 if (max_login_tries < 0) 01716 max_login_tries = 0; 01717 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTMAXLOGINTRIES"); 01718 if (option_verbose > 2) 01719 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); 01720 } 01721 if (pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) { 01722 if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"))) 01723 update_cdr = 1; 01724 else 01725 update_cdr = 0; 01726 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTUPDATECDR"); 01727 if (option_verbose > 2) 01728 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTUPDATECDR=%s, setting update_cdr to: %d on Channel '%s'.\n",tmpoptions,update_cdr,chan->name); 01729 } 01730 if (pbx_builtin_getvar_helper(chan, "AGENTGOODBYE") && !ast_strlen_zero(pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"))) { 01731 strcpy(agent_goodbye, pbx_builtin_getvar_helper(chan, "AGENTGOODBYE")); 01732 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTGOODBYE"); 01733 if (option_verbose > 2) 01734 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTGOODBYE=%s, setting agent_goodbye to: %s on Channel '%s'.\n",tmpoptions,agent_goodbye,chan->name); 01735 } 01736 /* End Channel Specific Login Overrides */ 01737 01738 if (callbackmode && args.extension) { 01739 parse = args.extension; 01740 args.extension = strsep(&parse, "@"); 01741 context = parse; 01742 } 01743 01744 if (!ast_strlen_zero(args.options)) { 01745 if (strchr(args.options, 's')) { 01746 play_announcement = 0; 01747 } 01748 } 01749 01750 if (chan->_state != AST_STATE_UP) 01751 res = ast_answer(chan); 01752 if (!res) { 01753 if (!ast_strlen_zero(args.agent_id)) 01754 ast_copy_string(user, args.agent_id, AST_MAX_AGENT); 01755 else 01756 res = ast_app_getdata(chan, "agent-user", user, sizeof(user) - 1, 0); 01757 } 01758 while (!res && (max_login_tries==0 || tries < max_login_tries)) { 01759 tries++; 01760 /* Check for password */ 01761 ast_mutex_lock(&agentlock); 01762 p = agents; 01763 while(p) { 01764 if (!strcmp(p->agent, user) && !p->pending) 01765 ast_copy_string(xpass, p->password, sizeof(xpass)); 01766 p = p->next; 01767 } 01768 ast_mutex_unlock(&agentlock); 01769 if (!res) { 01770 if (!ast_strlen_zero(xpass)) 01771 res = ast_app_getdata(chan, "agent-pass", pass, sizeof(pass) - 1, 0); 01772 else 01773 pass[0] = '\0'; 01774 } 01775 errmsg = "agent-incorrect"; 01776 01777 #if 0 01778 ast_log(LOG_NOTICE, "user: %s, pass: %s\n", user, pass); 01779 #endif 01780 01781 /* Check again for accuracy */ 01782 ast_mutex_lock(&agentlock); 01783 p = agents; 01784 while(p) { 01785 ast_mutex_lock(&p->lock); 01786 if (!strcmp(p->agent, user) && 01787 !strcmp(p->password, pass) && !p->pending) { 01788 login_state = 1; /* Successful Login */ 01789 01790 /* Ensure we can't be gotten until we're done */ 01791 gettimeofday(&p->lastdisc, NULL); 01792 p->lastdisc.tv_sec++; 01793 01794 /* Set Channel Specific Agent Overrides */ 01795 if (pbx_builtin_getvar_helper(chan, "AGENTACKCALL") && strlen(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) { 01796 if (!strcasecmp(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"), "always")) 01797 p->ackcall = 2; 01798 else if (ast_true(pbx_builtin_getvar_helper(chan, "AGENTACKCALL"))) 01799 p->ackcall = 1; 01800 else 01801 p->ackcall = 0; 01802 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTACKCALL"); 01803 if (option_verbose > 2) 01804 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTACKCALL=%s, setting ackcall to: %d for Agent '%s'.\n",tmpoptions,p->ackcall,p->agent); 01805 } 01806 if (pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF") && strlen(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"))) { 01807 p->autologoff = atoi(pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF")); 01808 if (p->autologoff < 0) 01809 p->autologoff = 0; 01810 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTAUTOLOGOFF"); 01811 if (option_verbose > 2) 01812 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTAUTOLOGOFF=%s, setting autologff to: %d for Agent '%s'.\n",tmpoptions,p->autologoff,p->agent); 01813 } 01814 if (pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME") && strlen(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"))) { 01815 p->wrapuptime = atoi(pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME")); 01816 if (p->wrapuptime < 0) 01817 p->wrapuptime = 0; 01818 tmpoptions=pbx_builtin_getvar_helper(chan, "AGENTWRAPUPTIME"); 01819 if (option_verbose > 2) 01820 ast_verbose(VERBOSE_PREFIX_3 "Saw variable AGENTWRAPUPTIME=%s, setting wrapuptime to: %d for Agent '%s'.\n",tmpoptions,p->wrapuptime,p->agent); 01821 } 01822 /* End Channel Specific Agent Overrides */ 01823 if (!p->chan) { 01824 char last_loginchan[80] = ""; 01825 long logintime; 01826 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 01827 01828 if (callbackmode) { 01829 int pos = 0; 01830 /* Retrieve login chan */ 01831 for (;;) { 01832 if (!ast_strlen_zero(args.extension)) { 01833 ast_copy_string(tmpchan, args.extension, sizeof(tmpchan)); 01834 res = 0; 01835 } else 01836 res = ast_app_getdata(chan, "agent-newlocation", tmpchan+pos, sizeof(tmpchan) - 2, 0); 01837 if (ast_strlen_zero(tmpchan) || ast_exists_extension(chan, !ast_strlen_zero(context) ? context : "default", tmpchan, 01838 1, NULL)) 01839 break; 01840 if (args.extension) { 01841 ast_log(LOG_WARNING, "Extension '%s' is not valid for automatic login of agent '%s'\n", args.extension, p->agent); 01842 args.extension = NULL; 01843 pos = 0; 01844 } else { 01845 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); 01846 res = ast_streamfile(chan, "invalid", chan->language); 01847 if (!res) 01848 res = ast_waitstream(chan, AST_DIGIT_ANY); 01849 if (res > 0) { 01850 tmpchan[0] = res; 01851 tmpchan[1] = '\0'; 01852 pos = 1; 01853 } else { 01854 tmpchan[0] = '\0'; 01855 pos = 0; 01856 } 01857 } 01858 } 01859 args.extension = tmpchan; 01860 if (!res) { 01861 set_agentbycallerid(p->logincallerid, NULL); 01862 if (!ast_strlen_zero(context) && !ast_strlen_zero(tmpchan)) 01863 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", tmpchan, context); 01864 else { 01865 ast_copy_string(last_loginchan, p->loginchan, sizeof(last_loginchan)); 01866 ast_copy_string(p->loginchan, tmpchan, sizeof(p->loginchan)); 01867 } 01868 p->acknowledged = 0; 01869 if (ast_strlen_zero(p->loginchan)) { 01870 login_state = 2; 01871 filename = "agent-loggedoff"; 01872 } else { 01873 if (chan->cid.cid_num) { 01874 ast_copy_string(p->logincallerid, chan->cid.cid_num, sizeof(p->logincallerid)); 01875 set_agentbycallerid(p->logincallerid, p->agent); 01876 } else 01877 p->logincallerid[0] = '\0'; 01878 } 01879 01880 if(update_cdr && chan->cdr) 01881 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01882 01883 } 01884 } else { 01885 p->loginchan[0] = '\0'; 01886 p->logincallerid[0] = '\0'; 01887 p->acknowledged = 0; 01888 } 01889 ast_mutex_unlock(&p->lock); 01890 ast_mutex_unlock(&agentlock); 01891 if( !res && play_announcement==1 ) 01892 res = ast_streamfile(chan, filename, chan->language); 01893 if (!res) 01894 ast_waitstream(chan, ""); 01895 ast_mutex_lock(&agentlock); 01896 ast_mutex_lock(&p->lock); 01897 if (!res) { 01898 res = ast_set_read_format(chan, ast_best_codec(chan->nativeformats)); 01899 if (res) 01900 ast_log(LOG_WARNING, "Unable to set read format to %d\n", ast_best_codec(chan->nativeformats)); 01901 } 01902 if (!res) { 01903 res = ast_set_write_format(chan, ast_best_codec(chan->nativeformats)); 01904 if (res) 01905 ast_log(LOG_WARNING, "Unable to set write format to %d\n", ast_best_codec(chan->nativeformats)); 01906 } 01907 /* Check once more just in case */ 01908 if (p->chan) 01909 res = -1; 01910 if (callbackmode && !res) { 01911 /* Just say goodbye and be done with it */ 01912 if (!ast_strlen_zero(p->loginchan)) { 01913 if (p->loginstart == 0) 01914 time(&p->loginstart); 01915 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 01916 "Agent: %s\r\n" 01917 "Loginchan: %s\r\n" 01918 "Uniqueid: %s\r\n", 01919 p->agent, p->loginchan, chan->uniqueid); 01920 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 01921 if (option_verbose > 1) 01922 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 01923 ast_device_state_changed("Agent/%s", p->agent); 01924 } else { 01925 logintime = time(NULL) - p->loginstart; 01926 p->loginstart = 0; 01927 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01928 "Agent: %s\r\n" 01929 "Loginchan: %s\r\n" 01930 "Logintime: %ld\r\n" 01931 "Uniqueid: %s\r\n", 01932 p->agent, last_loginchan, logintime, chan->uniqueid); 01933 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|", last_loginchan, logintime); 01934 if (option_verbose > 1) 01935 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged out\n", p->agent); 01936 ast_device_state_changed("Agent/%s", p->agent); 01937 } 01938 ast_mutex_unlock(&agentlock); 01939 if (!res) 01940 res = ast_safe_sleep(chan, 500); 01941 ast_mutex_unlock(&p->lock); 01942 if (persistent_agents) 01943 dump_agents(); 01944 } else if (!res) { 01945 #ifdef HONOR_MUSIC_CLASS 01946 /* check if the moh class was changed with setmusiconhold */ 01947 if (*(chan->musicclass)) 01948 ast_copy_string(p->moh, chan->musicclass, sizeof(p->moh)); 01949 #endif 01950 ast_moh_start(chan, p->moh); 01951 if (p->loginstart == 0) 01952 time(&p->loginstart); 01953 manager_event(EVENT_FLAG_AGENT, "Agentlogin", 01954 "Agent: %s\r\n" 01955 "Channel: %s\r\n" 01956 "Uniqueid: %s\r\n", 01957 p->agent, chan->name, chan->uniqueid); 01958 if (update_cdr && chan->cdr) 01959 snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 01960 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGIN", "%s", chan->name); 01961 if (option_verbose > 1) 01962 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged in (format %s/%s)\n", p->agent, 01963 ast_getformatname(chan->readformat), ast_getformatname(chan->writeformat)); 01964 /* Login this channel and wait for it to 01965 go away */ 01966 p->chan = chan; 01967 if (p->ackcall > 1) 01968 check_beep(p, 0); 01969 else 01970 check_availability(p, 0); 01971 ast_mutex_unlock(&p->lock); 01972 ast_mutex_unlock(&agentlock); 01973 ast_device_state_changed("Agent/%s", p->agent); 01974 while (res >= 0) { 01975 ast_mutex_lock(&p->lock); 01976 if (p->chan != chan) 01977 res = -1; 01978 ast_mutex_unlock(&p->lock); 01979 /* Yield here so other interested threads can kick in. */ 01980 sched_yield(); 01981 if (res) 01982 break; 01983 01984 ast_mutex_lock(&agentlock); 01985 ast_mutex_lock(&p->lock); 01986 if (p->lastdisc.tv_sec) { 01987 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) { 01988 if (option_debug) 01989 ast_log(LOG_DEBUG, "Wrapup time for %s expired!\n", p->agent); 01990 p->lastdisc = ast_tv(0, 0); 01991 if (p->ackcall > 1) 01992 check_beep(p, 0); 01993 else 01994 check_availability(p, 0); 01995 } 01996 } 01997 ast_mutex_unlock(&p->lock); 01998 ast_mutex_unlock(&agentlock); 01999 /* Synchronize channel ownership between call to agent and itself. */ 02000 ast_mutex_lock( &p->app_lock ); 02001 ast_mutex_lock(&p->lock); 02002 p->owning_app = pthread_self(); 02003 ast_mutex_unlock(&p->lock); 02004 if (p->ackcall > 1) 02005 res = agent_ack_sleep(p); 02006 else 02007 res = ast_safe_sleep_conditional( chan, 1000, 02008 agent_cont_sleep, p ); 02009 ast_mutex_unlock( &p->app_lock ); 02010 if ((p->ackcall > 1) && (res == 1)) { 02011 ast_mutex_lock(&agentlock); 02012 ast_mutex_lock(&p->lock); 02013 check_availability(p, 0); 02014 ast_mutex_unlock(&p->lock); 02015 ast_mutex_unlock(&agentlock); 02016 res = 0; 02017 } 02018 sched_yield(); 02019 } 02020 ast_mutex_lock(&p->lock); 02021 if (res && p->owner) 02022 ast_log(LOG_WARNING, "Huh? We broke out when there was still an owner?\n"); 02023 /* Log us off if appropriate */ 02024 if (p->chan == chan) 02025 p->chan = NULL; 02026 p->acknowledged = 0; 02027 logintime = time(NULL) - p->loginstart; 02028 p->loginstart = 0; 02029 ast_mutex_unlock(&p->lock); 02030 manager_event(EVENT_FLAG_AGENT, "Agentlogoff", 02031 "Agent: %s\r\n" 02032 "Logintime: %ld\r\n" 02033 "Uniqueid: %s\r\n", 02034 p->agent, logintime, chan->uniqueid); 02035 ast_queue_log("NONE", chan->uniqueid, agent, "AGENTLOGOFF", "%s|%ld", chan->name, logintime); 02036 if (option_verbose > 1) 02037 ast_verbose(VERBOSE_PREFIX_2 "Agent '%s' logged out\n", p->agent); 02038 /* If there is no owner, go ahead and kill it now */ 02039 ast_device_state_changed("Agent/%s", p->agent); 02040 if (p->dead && !p->owner) { 02041 ast_mutex_destroy(&p->lock); 02042 ast_mutex_destroy(&p->app_lock); 02043 free(p); 02044 } 02045 } 02046 else { 02047 ast_mutex_unlock(&p->lock); 02048 p = NULL; 02049 } 02050 res = -1; 02051 } else { 02052 ast_mutex_unlock(&p->lock); 02053 errmsg = "agent-alreadyon"; 02054 p = NULL; 02055 } 02056 break; 02057 } 02058 ast_mutex_unlock(&p->lock); 02059 p = p->next; 02060 } 02061 if (!p) 02062 ast_mutex_unlock(&agentlock); 02063 02064 if (!res && (max_login_tries==0 || tries < max_login_tries)) 02065 res = ast_app_getdata(chan, errmsg, user, sizeof(user) - 1, 0); 02066 } 02067 02068 if (!res) 02069 res = ast_safe_sleep(chan, 500); 02070 02071 /* AgentLogin() exit */ 02072 if (!callbackmode) { 02073 LOCAL_USER_REMOVE(u); 02074 return -1; 02075 } 02076 /* AgentCallbackLogin() exit*/ 02077 else { 02078 /* Set variables */ 02079 if (login_state > 0) { 02080 pbx_builtin_setvar_helper(chan, "AGENTNUMBER", user); 02081 if (login_state==1) { 02082 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "on"); 02083 pbx_builtin_setvar_helper(chan, "AGENTEXTEN", args.extension); 02084 } 02085 else { 02086 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "off"); 02087 } 02088 } 02089 else { 02090 pbx_builtin_setvar_helper(chan, "AGENTSTATUS", "fail"); 02091 } 02092 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1, chan->cid.cid_num)) { 02093 LOCAL_USER_REMOVE(u); 02094 return 0; 02095 } 02096 /* Do we need to play agent-goodbye now that we will be hanging up? */ 02097 if (play_announcement) { 02098 if (!res) 02099 res = ast_safe_sleep(chan, 1000); 02100 res = ast_streamfile(chan, agent_goodbye, chan->language); 02101 if (!res) 02102 res = ast_waitstream(chan, ""); 02103 if (!res) 02104 res = ast_safe_sleep(chan, 1000); 02105 } 02106 } 02107 02108 LOCAL_USER_REMOVE(u); 02109 02110 /* We should never get here if next priority exists when in callbackmode */ 02111 return -1; 02112 }
|
|
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 2148 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, dump_agents(), EVENT_FLAG_AGENT, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::next, option_verbose, agent_pvt::pending, s, VERBOSE_PREFIX_2, and agent_pvt::wrapuptime. Referenced by load_module(). 02149 { 02150 char *agent = astman_get_header(m, "Agent"); 02151 char *exten = astman_get_header(m, "Exten"); 02152 char *context = astman_get_header(m, "Context"); 02153 char *wrapuptime_s = astman_get_header(m, "WrapupTime"); 02154 char *ackcall_s = astman_get_header(m, "AckCall"); 02155 struct agent_pvt *p; 02156 int login_state = 0; 02157 02158 if (ast_strlen_zero(agent)) { 02159 astman_send_error(s, m, "No agent specified"); 02160 return 0; 02161 } 02162 02163 if (ast_strlen_zero(exten)) { 02164 astman_send_error(s, m, "No extension specified"); 02165 return 0; 02166 } 02167 02168 ast_mutex_lock(&agentlock); 02169 p = agents; 02170 while(p) { 02171 if (strcmp(p->agent, agent) || p->pending) { 02172 p = p->next; 02173 continue; 02174 } 02175 if (p->chan) { 02176 login_state = 2; /* already logged in (and on the phone)*/ 02177 break; 02178 } 02179 ast_mutex_lock(&p->lock); 02180 login_state = 1; /* Successful Login */ 02181 02182 if (ast_strlen_zero(context)) 02183 ast_copy_string(p->loginchan, exten, sizeof(p->loginchan)); 02184 else 02185 snprintf(p->loginchan, sizeof(p->loginchan), "%s@%s", exten, context); 02186 02187 if (!ast_strlen_zero(wrapuptime_s)) { 02188 p->wrapuptime = atoi(wrapuptime_s); 02189 if (p->wrapuptime < 0) 02190 p->wrapuptime = 0; 02191 } 02192 02193 if (ast_true(ackcall_s)) 02194 p->ackcall = 1; 02195 else 02196 p->ackcall = 0; 02197 02198 if (p->loginstart == 0) 02199 time(&p->loginstart); 02200 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogin", 02201 "Agent: %s\r\n" 02202 "Loginchan: %s\r\n", 02203 p->agent, p->loginchan); 02204 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGIN", "%s", p->loginchan); 02205 if (option_verbose > 1) 02206 ast_verbose(VERBOSE_PREFIX_2 "Callback Agent '%s' logged in on %s\n", p->agent, p->loginchan); 02207 ast_device_state_changed("Agent/%s", p->agent); 02208 ast_mutex_unlock(&p->lock); 02209 p = p->next; 02210 if (persistent_agents) 02211 dump_agents(); 02212 } 02213 ast_mutex_unlock(&agentlock); 02214 02215 if (login_state == 1) 02216 astman_send_ack(s, m, "Agent logged in"); 02217 else if (login_state == 0) 02218 astman_send_error(s, m, "No such agent"); 02219 else if (login_state == 2) 02220 astman_send_error(s, m, "Agent already logged in"); 02221 02222 return 0; 02223 }
|
|
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 1531 of file chan_agent.c. References agent_logoff(), ast_strlen_zero(), ast_true(), astman_get_header(), astman_send_ack(), astman_send_error(), and s. Referenced by load_module(). 01532 { 01533 char *agent = astman_get_header(m, "Agent"); 01534 char *soft_s = astman_get_header(m, "Soft"); /* "true" is don't hangup */ 01535 int soft; 01536 int ret; /* return value of agent_logoff */ 01537 01538 if (ast_strlen_zero(agent)) { 01539 astman_send_error(s, m, "No agent specified"); 01540 return 0; 01541 } 01542 01543 if (ast_true(soft_s)) 01544 soft = 1; 01545 else 01546 soft = 0; 01547 01548 ret = agent_logoff(agent, soft); 01549 if (ret == 0) 01550 astman_send_ack(s, m, "Agent logged out"); 01551 else 01552 astman_send_error(s, m, "No such agent"); 01553 01554 return 0; 01555 }
|
|
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 1389 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, mansession::fd, agent_pvt::lock, agent_pvt::loginchan, agent_pvt::loginstart, ast_channel::name, agent_pvt::name, agent_pvt::next, agent_pvt::owner, and s. Referenced by load_module(). 01390 { 01391 char *id = astman_get_header(m,"ActionID"); 01392 char idText[256] = ""; 01393 char chanbuf[256]; 01394 struct agent_pvt *p; 01395 char *username = NULL; 01396 char *loginChan = NULL; 01397 char *talkingtoChan = NULL; 01398 char *status = NULL; 01399 01400 if (!ast_strlen_zero(id)) 01401 snprintf(idText, sizeof(idText) ,"ActionID: %s\r\n", id); 01402 astman_send_ack(s, m, "Agents will follow"); 01403 ast_mutex_lock(&agentlock); 01404 p = agents; 01405 while(p) { 01406 ast_mutex_lock(&p->lock); 01407 01408 /* Status Values: 01409 AGENT_LOGGEDOFF - Agent isn't logged in 01410 AGENT_IDLE - Agent is logged in, and waiting for call 01411 AGENT_ONCALL - Agent is logged in, and on a call 01412 AGENT_UNKNOWN - Don't know anything about agent. Shouldn't ever get this. */ 01413 01414 if(!ast_strlen_zero(p->name)) { 01415 username = p->name; 01416 } else { 01417 username = "None"; 01418 } 01419 01420 /* Set a default status. It 'should' get changed. */ 01421 status = "AGENT_UNKNOWN"; 01422 01423 if (!ast_strlen_zero(p->loginchan) && !p->chan) { 01424 loginChan = p->loginchan; 01425 talkingtoChan = "n/a"; 01426 status = "AGENT_IDLE"; 01427 if (p->acknowledged) { 01428 snprintf(chanbuf, sizeof(chanbuf), " %s (Confirmed)", p->loginchan); 01429 loginChan = chanbuf; 01430 } 01431 } else if (p->chan) { 01432 loginChan = ast_strdupa(p->chan->name); 01433 if (p->owner && p->owner->_bridge) { 01434 talkingtoChan = p->chan->cid.cid_num; 01435 status = "AGENT_ONCALL"; 01436 } else { 01437 talkingtoChan = "n/a"; 01438 status = "AGENT_IDLE"; 01439 } 01440 } else { 01441 loginChan = "n/a"; 01442 talkingtoChan = "n/a"; 01443 status = "AGENT_LOGGEDOFF"; 01444 } 01445 01446 ast_cli(s->fd, "Event: Agents\r\n" 01447 "Agent: %s\r\n" 01448 "Name: %s\r\n" 01449 "Status: %s\r\n" 01450 "LoggedInChan: %s\r\n" 01451 "LoggedInTime: %d\r\n" 01452 "TalkingTo: %s\r\n" 01453 "%s" 01454 "\r\n", 01455 p->agent, username, status, loginChan, (int)p->loginstart, talkingtoChan, idText); 01456 ast_mutex_unlock(&p->lock); 01457 p = p->next; 01458 } 01459 ast_mutex_unlock(&agentlock); 01460 ast_cli(s->fd, "Event: AgentsComplete\r\n" 01461 "%s" 01462 "\r\n",idText); 01463 return 0; 01464 }
|
|
Adds an agent to the global list of agents.
Definition at line 312 of file chan_agent.c. References agent_pvt::ackcall, agent_pvt::agent, agents, agent_pvt::app_lock, agent_pvt::app_sleep_cond, ast_app_separate_args(), ast_log(), ast_mutex_init(), ast_strdupa, agent_pvt::autologoff, agent_pvt::dead, agent_pvt::group, agent_pvt::lastdisc, agent_pvt::lock, LOG_WARNING, malloc, moh, agent_pvt::moh, agent_pvt::name, name, agent_pvt::next, agent_pvt::owning_app, agent_pvt::password, agent_pvt::pending, 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 865 of file chan_agent.c. References agent_pvt::app_sleep_cond, 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(). 00866 { 00867 struct agent_pvt *p; 00868 int res=0; 00869 int to = 1000; 00870 struct ast_frame *f; 00871 00872 /* Wait a second and look for something */ 00873 00874 p = (struct agent_pvt *)data; 00875 if (p->chan) { 00876 for(;;) { 00877 to = ast_waitfor(p->chan, to); 00878 if (to < 0) { 00879 res = -1; 00880 break; 00881 } 00882 if (!to) { 00883 res = 0; 00884 break; 00885 } 00886 f = ast_read(p->chan); 00887 if (!f) { 00888 res = -1; 00889 break; 00890 } 00891 if (f->frametype == AST_FRAME_DTMF) 00892 res = f->subclass; 00893 else 00894 res = 0; 00895 ast_frfree(f); 00896 ast_mutex_lock(&p->lock); 00897 if (!p->app_sleep_cond) { 00898 ast_mutex_unlock(&p->lock); 00899 res = 0; 00900 break; 00901 } else if (res == '#') { 00902 ast_mutex_unlock(&p->lock); 00903 res = 1; 00904 break; 00905 } 00906 ast_mutex_unlock(&p->lock); 00907 res = 0; 00908 } 00909 } else 00910 res = -1; 00911 return res; 00912 }
|
|
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 914 of file chan_agent.c. References ast_channel::_bridge, ast_log(), agent_pvt::chan, LOG_DEBUG, ast_channel::name, and ast_channel::tech_pvt. 00915 { 00916 struct agent_pvt *p = bridge->tech_pvt; 00917 struct ast_channel *ret=NULL; 00918 00919 if (p) { 00920 if (chan == p->chan) 00921 ret = bridge->_bridge; 00922 else if (chan == bridge->_bridge) 00923 ret = p->chan; 00924 } 00925 00926 if (option_debug) 00927 ast_log(LOG_DEBUG, "Asked for bridged channel on '%s'/'%s', returning '%s'\n", chan->name, bridge->name, ret ? ret->name : "<none>"); 00928 return ret; 00929 }
|
|
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_read_format(), ast_set_write_format(), ast_setstate(), 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, free, ast_channel::language, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, LOG_WARNING, agent_pvt::loginchan, ast_channel::name, ast_channel::nativeformats, option_verbose, agent_pvt::pending, agent_pvt::start, strdup, 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 if (p->chan->cid.cid_num) 00665 free(p->chan->cid.cid_num); 00666 if (ast->cid.cid_num) 00667 p->chan->cid.cid_num = strdup(ast->cid.cid_num); 00668 else 00669 p->chan->cid.cid_num = NULL; 00670 if (p->chan->cid.cid_name) 00671 free(p->chan->cid.cid_name); 00672 if (ast->cid.cid_name) 00673 p->chan->cid.cid_name = strdup(ast->cid.cid_name); 00674 else 00675 p->chan->cid.cid_name = NULL; 00676 ast_channel_inherit_variables(ast, p->chan); 00677 res = ast_call(p->chan, p->loginchan, 0); 00678 CLEANUP(ast,p); 00679 ast_mutex_unlock(&p->lock); 00680 return res; 00681 } 00682 ast_verbose( VERBOSE_PREFIX_3 "agent_call, call to agent '%s' call on '%s'\n", p->agent, p->chan->name); 00683 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", p->chan->language); 00684 res = ast_streamfile(p->chan, beep, p->chan->language); 00685 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 00686 if (!res) { 00687 res = ast_waitstream(p->chan, ""); 00688 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 00689 } 00690 if (!res) { 00691 res = ast_set_read_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00692 ast_log( LOG_DEBUG, "Set read format, result '%d'\n", res); 00693 if (res) 00694 ast_log(LOG_WARNING, "Unable to set read format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00695 } else { 00696 /* Agent hung-up */ 00697 p->chan = NULL; 00698 } 00699 00700 if (!res) { 00701 ast_set_write_format(p->chan, ast_best_codec(p->chan->nativeformats)); 00702 ast_log( LOG_DEBUG, "Set write format, result '%d'\n", res); 00703 if (res) 00704 ast_log(LOG_WARNING, "Unable to set write format to %s\n", ast_getformatname(ast_best_codec(p->chan->nativeformats))); 00705 } 00706 if( !res ) 00707 { 00708 /* Call is immediately up, or might need ack */ 00709 if (p->ackcall > 1) 00710 newstate = AST_STATE_RINGING; 00711 else { 00712 newstate = AST_STATE_UP; 00713 if (recordagentcalls) 00714 agent_start_monitoring(ast,0); 00715 p->acknowledged = 1; 00716 } 00717 res = 0; 00718 } 00719 CLEANUP(ast,p); 00720 ast_mutex_unlock(&p->lock); 00721 if (newstate) 00722 ast_setstate(ast, newstate); 00723 return res; 00724 }
|
|
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 agent_pvt::app_lock, agent_pvt::app_sleep_cond, ast_channel_free(), ast_mutex_destroy(), ast_mutex_unlock(), agent_pvt::dead, free, agent_pvt::lock, agent_pvt::owner, and ast_channel::tech_pvt. Referenced by check_availability(). 00405 { 00406 struct ast_channel *chan = p->owner; 00407 p->owner = NULL; 00408 chan->tech_pvt = NULL; 00409 p->app_sleep_cond = 1; 00410 /* Release ownership of the agent to other threads (presumably running the login app). */ 00411 ast_mutex_unlock(&p->app_lock); 00412 if (chan) 00413 ast_channel_free(chan); 00414 if (p->dead) { 00415 ast_mutex_destroy(&p->lock); 00416 ast_mutex_destroy(&p->app_lock); 00417 free(p); 00418 } 00419 return 0; 00420 }
|
|
Definition at line 844 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(). 00845 { 00846 struct agent_pvt *p; 00847 int res; 00848 00849 p = (struct agent_pvt *)data; 00850 00851 ast_mutex_lock(&p->lock); 00852 res = p->app_sleep_cond; 00853 if (p->lastdisc.tv_sec) { 00854 if (ast_tvdiff_ms(ast_tvnow(), p->lastdisc) > p->wrapuptime) 00855 res = 1; 00856 } 00857 ast_mutex_unlock(&p->lock); 00858 #if 0 00859 if( !res ) 00860 ast_log( LOG_DEBUG, "agent_cont_sleep() returning %d\n", res ); 00861 #endif 00862 return res; 00863 }
|
|
Definition at line 2371 of file chan_agent.c. References agent_pvt::agent, ast_group_t, 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. 02372 { 02373 struct agent_pvt *p; 02374 char *s; 02375 ast_group_t groupmatch; 02376 int groupoff; 02377 int waitforagent=0; 02378 int res = AST_DEVICE_INVALID; 02379 02380 s = data; 02381 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02382 groupmatch = (1 << groupoff); 02383 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 02384 groupmatch = (1 << groupoff); 02385 waitforagent = 1; 02386 } else { 02387 groupmatch = 0; 02388 } 02389 02390 /* Check actual logged in agents first */ 02391 ast_mutex_lock(&agentlock); 02392 p = agents; 02393 while(p) { 02394 ast_mutex_lock(&p->lock); 02395 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 02396 if (p->owner) { 02397 if (res != AST_DEVICE_INUSE) 02398 res = AST_DEVICE_BUSY; 02399 } else { 02400 if (res == AST_DEVICE_BUSY) 02401 res = AST_DEVICE_INUSE; 02402 if (p->chan || !ast_strlen_zero(p->loginchan)) { 02403 if (res == AST_DEVICE_INVALID) 02404 res = AST_DEVICE_UNKNOWN; 02405 } else if (res == AST_DEVICE_INVALID) 02406 res = AST_DEVICE_UNAVAILABLE; 02407 } 02408 if (!strcmp(data, p->agent)) { 02409 ast_mutex_unlock(&p->lock); 02410 break; 02411 } 02412 } 02413 ast_mutex_unlock(&p->lock); 02414 p = p->next; 02415 } 02416 ast_mutex_unlock(&agentlock); 02417 return res; 02418 }
|
|
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 739 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_moh_start(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_queue_log(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_state2str(), ast_strlen_zero(), ast_tvadd(), agent_pvt::autologoff, agent_pvt::chan, agent_pvt::dead, dump_agents(), EVENT_FLAG_AGENT, free, agent_pvt::lastdisc, ast_channel::lock, agent_pvt::lock, LOG_DEBUG, LOG_NOTICE, agent_pvt::logincallerid, agent_pvt::loginchan, agent_pvt::loginstart, manager_event(), agent_pvt::moh, agent_pvt::name, agent_pvt::owner, agent_pvt::pending, set_agentbycallerid(), agent_pvt::start, ast_channel::tech_pvt, ast_channel::uniqueid, usecnt, and agent_pvt::wrapuptime. 00740 { 00741 struct agent_pvt *p = ast->tech_pvt; 00742 int howlong = 0; 00743 ast_mutex_lock(&p->lock); 00744 p->owner = NULL; 00745 ast->tech_pvt = NULL; 00746 p->app_sleep_cond = 1; 00747 p->acknowledged = 0; 00748 00749 /* if they really are hung up then set start to 0 so the test 00750 * later if we're called on an already downed channel 00751 * doesn't cause an agent to be logged out like when 00752 * agent_request() is followed immediately by agent_hangup() 00753 * as in apps/app_chanisavail.c:chanavail_exec() 00754 */ 00755 00756 ast_mutex_lock(&usecnt_lock); 00757 usecnt--; 00758 ast_mutex_unlock(&usecnt_lock); 00759 00760 ast_log(LOG_DEBUG, "Hangup called for state %s\n", ast_state2str(ast->_state)); 00761 if (p->start && (ast->_state != AST_STATE_UP)) { 00762 howlong = time(NULL) - p->start; 00763 p->start = 0; 00764 } else if (ast->_state == AST_STATE_RESERVED) { 00765 howlong = 0; 00766 } else 00767 p->start = 0; 00768 if (p->chan) { 00769 p->chan->_bridge = NULL; 00770 /* If they're dead, go ahead and hang up on the agent now */ 00771 if (!ast_strlen_zero(p->loginchan)) { 00772 /* Store last disconnect time */ 00773 if (p->wrapuptime) 00774 p->lastdisc = ast_tvadd(ast_tvnow(), ast_samp2tv(p->wrapuptime, 1000)); 00775 else 00776 p->lastdisc = ast_tv(0,0); 00777 if (p->chan) { 00778 /* Recognize the hangup and pass it along immediately */ 00779 ast_hangup(p->chan); 00780 p->chan = NULL; 00781 } 00782 ast_log(LOG_DEBUG, "Hungup, howlong is %d, autologoff is %d\n", howlong, p->autologoff); 00783 if (howlong && p->autologoff && (howlong > p->autologoff)) { 00784 char agent[AST_MAX_AGENT] = ""; 00785 long logintime = time(NULL) - p->loginstart; 00786 p->loginstart = 0; 00787 ast_log(LOG_NOTICE, "Agent '%s' didn't answer/confirm within %d seconds (waited %d)\n", p->name, p->autologoff, howlong); 00788 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 00789 "Agent: %s\r\n" 00790 "Loginchan: %s\r\n" 00791 "Logintime: %ld\r\n" 00792 "Reason: Autologoff\r\n" 00793 "Uniqueid: %s\r\n", 00794 p->agent, p->loginchan, logintime, ast->uniqueid); 00795 snprintf(agent, sizeof(agent), "Agent/%s", p->agent); 00796 ast_queue_log("NONE", ast->uniqueid, agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "Autologoff"); 00797 set_agentbycallerid(p->logincallerid, NULL); 00798 ast_device_state_changed("Agent/%s", p->agent); 00799 p->loginchan[0] = '\0'; 00800 p->logincallerid[0] = '\0'; 00801 if (persistent_agents) 00802 dump_agents(); 00803 } 00804 } else if (p->dead) { 00805 ast_mutex_lock(&p->chan->lock); 00806 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 00807 ast_mutex_unlock(&p->chan->lock); 00808 } else { 00809 ast_mutex_lock(&p->chan->lock); 00810 ast_moh_start(p->chan, p->moh); 00811 ast_mutex_unlock(&p->chan->lock); 00812 } 00813 } 00814 ast_mutex_unlock(&p->lock); 00815 ast_device_state_changed("Agent/%s", p->agent); 00816 00817 if (p->pending) { 00818 ast_mutex_lock(&agentlock); 00819 agent_unlink(p); 00820 ast_mutex_unlock(&agentlock); 00821 } 00822 if (p->abouttograb) { 00823 /* Let the "about to grab" thread know this isn't valid anymore, and let it 00824 kill it later */ 00825 p->abouttograb = 0; 00826 } else if (p->dead) { 00827 ast_mutex_destroy(&p->lock); 00828 ast_mutex_destroy(&p->app_lock); 00829 free(p); 00830 } else { 00831 if (p->chan) { 00832 /* Not dead -- check availability now */ 00833 ast_mutex_lock(&p->lock); 00834 /* Store last disconnect time */ 00835 p->lastdisc = ast_tvnow(); 00836 ast_mutex_unlock(&p->lock); 00837 } 00838 /* Release ownership of the agent to other threads (presumably running the login app). */ 00839 ast_mutex_unlock(&p->app_lock); 00840 } 00841 return 0; 00842 }
|
|
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 1466 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, and set_agentbycallerid(). Referenced by action_agent_logoff(), and agent_logoff_cmd(). 01467 { 01468 struct agent_pvt *p; 01469 long logintime; 01470 int ret = -1; /* Return -1 if no agent if found */ 01471 01472 for (p=agents; p; p=p->next) { 01473 if (!strcasecmp(p->agent, agent)) { 01474 if (!soft) { 01475 if (p->owner) { 01476 ast_softhangup(p->owner, AST_SOFTHANGUP_EXPLICIT); 01477 } 01478 if (p->chan) { 01479 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01480 } 01481 } 01482 ret = 0; /* found an agent => return 0 */ 01483 logintime = time(NULL) - p->loginstart; 01484 p->loginstart = 0; 01485 01486 manager_event(EVENT_FLAG_AGENT, "Agentcallbacklogoff", 01487 "Agent: %s\r\n" 01488 "Loginchan: %s\r\n" 01489 "Logintime: %ld\r\n", 01490 p->agent, p->loginchan, logintime); 01491 ast_queue_log("NONE", "NONE", agent, "AGENTCALLBACKLOGOFF", "%s|%ld|%s", p->loginchan, logintime, "CommandLogoff"); 01492 set_agentbycallerid(p->logincallerid, NULL); 01493 p->loginchan[0] = '\0'; 01494 p->logincallerid[0] = '\0'; 01495 ast_device_state_changed("Agent/%s", p->agent); 01496 if (persistent_agents) 01497 dump_agents(); 01498 break; 01499 } 01500 } 01501 01502 return ret; 01503 }
|
|
Definition at line 1505 of file chan_agent.c. References agent_logoff(), and ast_cli(). 01506 { 01507 int ret; 01508 char *agent; 01509 01510 if (argc < 3 || argc > 4) 01511 return RESULT_SHOWUSAGE; 01512 if (argc == 4 && strcasecmp(argv[3], "soft")) 01513 return RESULT_SHOWUSAGE; 01514 01515 agent = argv[2] + 6; 01516 ret = agent_logoff(agent, argc == 4); 01517 if (ret == 0) 01518 ast_cli(fd, "Logging out %s\n", agent); 01519 01520 return RESULT_SUCCESS; 01521 }
|
|
Definition at line 932 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_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, ast_channel::context, 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, and ast_channel::writeformat. Referenced by agent_request(), and check_availability(). 00933 { 00934 struct ast_channel *tmp; 00935 struct ast_frame null_frame = { AST_FRAME_NULL }; 00936 #if 0 00937 if (!p->chan) { 00938 ast_log(LOG_WARNING, "No channel? :(\n"); 00939 return NULL; 00940 } 00941 #endif 00942 tmp = ast_channel_alloc(0); 00943 if (tmp) { 00944 tmp->tech = &agent_tech; 00945 if (p->chan) { 00946 tmp->nativeformats = p->chan->nativeformats; 00947 tmp->writeformat = p->chan->writeformat; 00948 tmp->rawwriteformat = p->chan->writeformat; 00949 tmp->readformat = p->chan->readformat; 00950 tmp->rawreadformat = p->chan->readformat; 00951 ast_copy_string(tmp->language, p->chan->language, sizeof(tmp->language)); 00952 ast_copy_string(tmp->context, p->chan->context, sizeof(tmp->context)); 00953 ast_copy_string(tmp->exten, p->chan->exten, sizeof(tmp->exten)); 00954 } else { 00955 tmp->nativeformats = AST_FORMAT_SLINEAR; 00956 tmp->writeformat = AST_FORMAT_SLINEAR; 00957 tmp->rawwriteformat = AST_FORMAT_SLINEAR; 00958 tmp->readformat = AST_FORMAT_SLINEAR; 00959 tmp->rawreadformat = AST_FORMAT_SLINEAR; 00960 } 00961 if (p->pending) 00962 snprintf(tmp->name, sizeof(tmp->name), "Agent/P%s-%d", p->agent, rand() & 0xffff); 00963 else 00964 snprintf(tmp->name, sizeof(tmp->name), "Agent/%s", p->agent); 00965 tmp->type = channeltype; 00966 /* Safe, agentlock already held */ 00967 ast_setstate(tmp, state); 00968 tmp->tech_pvt = p; 00969 p->owner = tmp; 00970 ast_mutex_lock(&usecnt_lock); 00971 usecnt++; 00972 ast_mutex_unlock(&usecnt_lock); 00973 ast_update_use_count(); 00974 tmp->priority = 1; 00975 /* Wake up and wait for other applications (by definition the login app) 00976 * to release this channel). Takes ownership of the agent channel 00977 * to this thread only. 00978 * For signalling the other thread, ast_queue_frame is used until we 00979 * can safely use signals for this purpose. The pselect() needs to be 00980 * implemented in the kernel for this. 00981 */ 00982 p->app_sleep_cond = 0; 00983 if( ast_mutex_trylock(&p->app_lock) ) 00984 { 00985 if (p->chan) { 00986 ast_queue_frame(p->chan, &null_frame); 00987 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00988 ast_mutex_lock(&p->app_lock); 00989 ast_mutex_lock(&p->lock); 00990 } 00991 if( !p->chan ) 00992 { 00993 ast_log(LOG_WARNING, "Agent disconnected while we were connecting the call\n"); 00994 p->owner = NULL; 00995 tmp->tech_pvt = NULL; 00996 p->app_sleep_cond = 1; 00997 ast_channel_free( tmp ); 00998 ast_mutex_unlock(&p->lock); /* For other thread to read the condition. */ 00999 ast_mutex_unlock(&p->app_lock); 01000 return NULL; 01001 } 01002 } 01003 p->owning_app = pthread_self(); 01004 /* After the above step, there should not be any blockers. */ 01005 if (p->chan) { 01006 if (ast_test_flag(p->chan, AST_FLAG_BLOCKING)) { 01007 ast_log( LOG_ERROR, "A blocker exists after agent channel ownership acquired\n" ); 01008 CRASH; 01009 } 01010 ast_moh_stop(p->chan); 01011 } 01012 } else 01013 ast_log(LOG_WARNING, "Unable to allocate agent channel structure\n"); 01014 return tmp; 01015 }
|
|
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_VOICE, ast_frfree(), ast_hangup(), ast_log(), AST_MAX_FDS, ast_mutex_lock(), ast_mutex_unlock(), ast_read(), 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 1270 of file chan_agent.c. References add_agent(), agent_pvt::agent, agent_new(), ast_group_t, 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, agent_pvt::owner, agent_pvt::pending, s, and tv. 01271 { 01272 struct agent_pvt *p; 01273 struct ast_channel *chan = NULL; 01274 char *s; 01275 ast_group_t groupmatch; 01276 int groupoff; 01277 int waitforagent=0; 01278 int hasagent = 0; 01279 struct timeval tv; 01280 01281 s = data; 01282 if ((s[0] == '@') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01283 groupmatch = (1 << groupoff); 01284 } else if ((s[0] == ':') && (sscanf(s + 1, "%d", &groupoff) == 1)) { 01285 groupmatch = (1 << groupoff); 01286 waitforagent = 1; 01287 } else { 01288 groupmatch = 0; 01289 } 01290 01291 /* Check actual logged in agents first */ 01292 ast_mutex_lock(&agentlock); 01293 p = agents; 01294 while(p) { 01295 ast_mutex_lock(&p->lock); 01296 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent)) && 01297 ast_strlen_zero(p->loginchan)) { 01298 if (p->chan) 01299 hasagent++; 01300 if (!p->lastdisc.tv_sec) { 01301 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01302 if (!p->owner && p->chan) { 01303 /* Fixed agent */ 01304 chan = agent_new(p, AST_STATE_DOWN); 01305 } 01306 if (chan) { 01307 ast_mutex_unlock(&p->lock); 01308 break; 01309 } 01310 } 01311 } 01312 ast_mutex_unlock(&p->lock); 01313 p = p->next; 01314 } 01315 if (!p) { 01316 p = agents; 01317 while(p) { 01318 ast_mutex_lock(&p->lock); 01319 if (!p->pending && ((groupmatch && (p->group & groupmatch)) || !strcmp(data, p->agent))) { 01320 if (p->chan || !ast_strlen_zero(p->loginchan)) 01321 hasagent++; 01322 tv = ast_tvnow(); 01323 #if 0 01324 ast_log(LOG_NOTICE, "Time now: %ld, Time of lastdisc: %ld\n", tv.tv_sec, p->lastdisc.tv_sec); 01325 #endif 01326 if (!p->lastdisc.tv_sec || (tv.tv_sec > p->lastdisc.tv_sec)) { 01327 p->lastdisc = ast_tv(0, 0); 01328 /* Agent must be registered, but not have any active call, and not be in a waiting state */ 01329 if (!p->owner && p->chan) { 01330 /* Could still get a fixed agent */ 01331 chan = agent_new(p, AST_STATE_DOWN); 01332 } else if (!p->owner && !ast_strlen_zero(p->loginchan)) { 01333 /* Adjustable agent */ 01334 p->chan = ast_request("Local", format, p->loginchan, cause); 01335 if (p->chan) 01336 chan = agent_new(p, AST_STATE_DOWN); 01337 } 01338 if (chan) { 01339 ast_mutex_unlock(&p->lock); 01340 break; 01341 } 01342 } 01343 } 01344 ast_mutex_unlock(&p->lock); 01345 p = p->next; 01346 } 01347 } 01348 01349 if (!chan && waitforagent) { 01350 /* No agent available -- but we're requesting to wait for one. 01351 Allocate a place holder */ 01352 if (hasagent) { 01353 if (option_debug) 01354 ast_log(LOG_DEBUG, "Creating place holder for '%s'\n", s); 01355 p = add_agent(data, 1); 01356 p->group = groupmatch; 01357 chan = agent_new(p, AST_STATE_DOWN); 01358 if (!chan) { 01359 ast_log(LOG_WARNING, "Weird... Fix this to drop the unused pending agent\n"); 01360 } 01361 } else 01362 ast_log(LOG_DEBUG, "Not creating place holder for '%s' since nobody logged in\n", s); 01363 } 01364 if (hasagent) 01365 *cause = AST_CAUSE_BUSY; 01366 else 01367 *cause = AST_CAUSE_UNREGISTERED; 01368 ast_mutex_unlock(&agentlock); 01369 return chan; 01370 }
|
|
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, ast_channel::tech_pvt, and text. 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 agents, and agent_pvt::next. Referenced by agent_hangup(). 00282 { 00283 struct agent_pvt *p, *prev; 00284 prev = NULL; 00285 p = agents; 00286 // Iterate over all agents looking for the one. 00287 while(p) { 00288 if (p == agent) { 00289 // Once it wal found, check if it is the first one. 00290 if (prev) 00291 // If it is not, tell the previous agent that the next one is the next one of the current (jumping the current). 00292 prev->next = agent->next; 00293 else 00294 // If it is the first one, just change the general pointer to point to the second one. 00295 agents = agent->next; 00296 // We are done. 00297 break; 00298 } 00299 prev = p; 00300 p = p->next; 00301 } 00302 }
|
|
Definition at line 578 of file chan_agent.c. References 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 2233 of file chan_agent.c. References __agent_start_monitoring(), agent_pvt::agent, ast_exists_extension(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), ast_channel::cdr, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, ast_channel::exten, GETAGENTBYCALLERID, LOG_WARNING, agent_pvt::next, option_verbose, pbx_builtin_getvar_helper(), ast_channel::priority, and VERBOSE_PREFIX_3. Referenced by load_module(). 02234 { 02235 int exitifnoagentid = 0; 02236 int nowarnings = 0; 02237 int changeoutgoing = 0; 02238 int res = 0; 02239 char agent[AST_MAX_AGENT], *tmp; 02240 02241 if (data) { 02242 if (strchr(data, 'd')) 02243 exitifnoagentid = 1; 02244 if (strchr(data, 'n')) 02245 nowarnings = 1; 02246 if (strchr(data, 'c')) 02247 changeoutgoing = 1; 02248 } 02249 if (chan->cid.cid_num) { 02250 char agentvar[AST_MAX_BUF]; 02251 snprintf(agentvar, sizeof(agentvar), "%s_%s", GETAGENTBYCALLERID, chan->cid.cid_num); 02252 if ((tmp = pbx_builtin_getvar_helper(NULL, agentvar))) { 02253 struct agent_pvt *p = agents; 02254 ast_copy_string(agent, tmp, sizeof(agent)); 02255 ast_mutex_lock(&agentlock); 02256 while (p) { 02257 if (!strcasecmp(p->agent, tmp)) { 02258 if (changeoutgoing) snprintf(chan->cdr->channel, sizeof(chan->cdr->channel), "Agent/%s", p->agent); 02259 __agent_start_monitoring(chan, p, 1); 02260 break; 02261 } 02262 p = p->next; 02263 } 02264 ast_mutex_unlock(&agentlock); 02265 02266 } else { 02267 res = -1; 02268 if (!nowarnings) 02269 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); 02270 } 02271 } else { 02272 res = -1; 02273 if (!nowarnings) 02274 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"); 02275 } 02276 /* check if there is n + 101 priority */ 02277 if (res) { 02278 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num)) { 02279 chan->priority+=100; 02280 if (option_verbose > 2) 02281 ast_verbose(VERBOSE_PREFIX_3 "Going to %d priority because there is no callerid or the agentid cannot be found.\n",chan->priority); 02282 } 02283 else if (exitifnoagentid) 02284 return res; 02285 } 02286 return 0; 02287 }
|
|
Show agents in cli. Definition at line 1581 of file chan_agent.c. References agent_pvt::acknowledged, agent_pvt::agent, ast_bridged_channel(), ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), agent_pvt::chan, config, agent_pvt::group, 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, and powerof(). 01582 { 01583 struct agent_pvt *p; 01584 char username[AST_MAX_BUF]; 01585 char location[AST_MAX_BUF] = ""; 01586 char talkingto[AST_MAX_BUF] = ""; 01587 char moh[AST_MAX_BUF]; 01588 int count_agents = 0; /* Number of agents configured */ 01589 int online_agents = 0; /* Number of online agents */ 01590 int offline_agents = 0; /* Number of offline agents */ 01591 if (argc != 2) 01592 return RESULT_SHOWUSAGE; 01593 ast_mutex_lock(&agentlock); 01594 p = agents; 01595 while(p) { 01596 ast_mutex_lock(&p->lock); 01597 if (p->pending) { 01598 if (p->group) 01599 ast_cli(fd, "-- Pending call to group %d\n", powerof(p->group)); 01600 else 01601 ast_cli(fd, "-- Pending call to agent %s\n", p->agent); 01602 } else { 01603 if (!ast_strlen_zero(p->name)) 01604 snprintf(username, sizeof(username), "(%s) ", p->name); 01605 else 01606 username[0] = '\0'; 01607 if (p->chan) { 01608 snprintf(location, sizeof(location), "logged in on %s", p->chan->name); 01609 if (p->owner && ast_bridged_channel(p->owner)) { 01610 snprintf(talkingto, sizeof(talkingto), " talking to %s", ast_bridged_channel(p->owner)->name); 01611 } else { 01612 strcpy(talkingto, " is idle"); 01613 } 01614 online_agents++; 01615 } else if (!ast_strlen_zero(p->loginchan)) { 01616 snprintf(location, sizeof(location) - 20, "available at '%s'", p->loginchan); 01617 talkingto[0] = '\0'; 01618 online_agents++; 01619 if (p->acknowledged) 01620 strncat(location, " (Confirmed)", sizeof(location) - strlen(location) - 1); 01621 } else { 01622 strcpy(location, "not logged in"); 01623 talkingto[0] = '\0'; 01624 offline_agents++; 01625 } 01626 if (!ast_strlen_zero(p->moh)) 01627 snprintf(moh, sizeof(moh), " (musiconhold is '%s')", p->moh); 01628 ast_cli(fd, "%-12.12s %s%s%s%s\n", p->agent, 01629 username, location, talkingto, moh); 01630 count_agents++; 01631 } 01632 ast_mutex_unlock(&p->lock); 01633 p = p->next; 01634 } 01635 ast_mutex_unlock(&agentlock); 01636 if ( !count_agents ) { 01637 ast_cli(fd, "No Agents are configured in %s\n",config); 01638 } else { 01639 ast_cli(fd, "%d agents configured [%d online , %d offline]\n",count_agents, online_agents, offline_agents); 01640 } 01641 ast_cli(fd, "\n"); 01642 01643 return RESULT_SUCCESS; 01644 }
|
|
|
|
|
|
Called by the AgentCallbackLogin application (from the dial plan).
Definition at line 2135 of file chan_agent.c. References __login_exec(). Referenced by load_module(). 02136 { 02137 return __login_exec(chan, data, 1); 02138 }
|
|
Definition at line 1150 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(). 01151 { 01152 struct ast_channel *chan=NULL, *parent=NULL; 01153 struct agent_pvt *p; 01154 int res; 01155 01156 if (option_debug) 01157 ast_log(LOG_DEBUG, "Checking availability of '%s'\n", newlyavailable->agent); 01158 if (needlock) 01159 ast_mutex_lock(&agentlock); 01160 p = agents; 01161 while(p) { 01162 if (p == newlyavailable) { 01163 p = p->next; 01164 continue; 01165 } 01166 ast_mutex_lock(&p->lock); 01167 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01168 if (option_debug) 01169 ast_log(LOG_DEBUG, "Call '%s' looks like a winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01170 /* We found a pending call, time to merge */ 01171 chan = agent_new(newlyavailable, AST_STATE_DOWN); 01172 parent = p->owner; 01173 p->abouttograb = 1; 01174 ast_mutex_unlock(&p->lock); 01175 break; 01176 } 01177 ast_mutex_unlock(&p->lock); 01178 p = p->next; 01179 } 01180 if (needlock) 01181 ast_mutex_unlock(&agentlock); 01182 if (parent && chan) { 01183 if (newlyavailable->ackcall > 1) { 01184 /* Don't do beep here */ 01185 res = 0; 01186 } else { 01187 if (option_debug > 2) 01188 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01189 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01190 if (option_debug > 2) 01191 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01192 if (!res) { 01193 res = ast_waitstream(newlyavailable->chan, ""); 01194 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01195 } 01196 } 01197 if (!res) { 01198 /* Note -- parent may have disappeared */ 01199 if (p->abouttograb) { 01200 newlyavailable->acknowledged = 1; 01201 /* Safe -- agent lock already held */ 01202 ast_setstate(parent, AST_STATE_UP); 01203 ast_setstate(chan, AST_STATE_UP); 01204 ast_copy_string(parent->context, chan->context, sizeof(parent->context)); 01205 /* Go ahead and mark the channel as a zombie so that masquerade will 01206 destroy it for us, and we need not call ast_hangup */ 01207 ast_mutex_lock(&parent->lock); 01208 ast_set_flag(chan, AST_FLAG_ZOMBIE); 01209 ast_channel_masquerade(parent, chan); 01210 ast_mutex_unlock(&parent->lock); 01211 p->abouttograb = 0; 01212 } else { 01213 if (option_debug) 01214 ast_log(LOG_DEBUG, "Sneaky, parent disappeared in the mean time...\n"); 01215 agent_cleanup(newlyavailable); 01216 } 01217 } else { 01218 if (option_debug) 01219 ast_log(LOG_DEBUG, "Ugh... Agent hung up at exactly the wrong time\n"); 01220 agent_cleanup(newlyavailable); 01221 } 01222 } 01223 return 0; 01224 }
|
|
Definition at line 1226 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(). 01227 { 01228 struct agent_pvt *p; 01229 int res=0; 01230 01231 ast_log(LOG_DEBUG, "Checking beep availability of '%s'\n", newlyavailable->agent); 01232 if (needlock) 01233 ast_mutex_lock(&agentlock); 01234 p = agents; 01235 while(p) { 01236 if (p == newlyavailable) { 01237 p = p->next; 01238 continue; 01239 } 01240 ast_mutex_lock(&p->lock); 01241 if (!p->abouttograb && p->pending && ((p->group && (newlyavailable->group & p->group)) || !strcmp(p->agent, newlyavailable->agent))) { 01242 if (option_debug) 01243 ast_log(LOG_DEBUG, "Call '%s' looks like a would-be winner for agent '%s'\n", p->owner->name, newlyavailable->agent); 01244 ast_mutex_unlock(&p->lock); 01245 break; 01246 } 01247 ast_mutex_unlock(&p->lock); 01248 p = p->next; 01249 } 01250 if (needlock) 01251 ast_mutex_unlock(&agentlock); 01252 if (p) { 01253 ast_mutex_unlock(&newlyavailable->lock); 01254 if (option_debug > 2) 01255 ast_log( LOG_DEBUG, "Playing beep, lang '%s'\n", newlyavailable->chan->language); 01256 res = ast_streamfile(newlyavailable->chan, beep, newlyavailable->chan->language); 01257 if (option_debug > 2) 01258 ast_log( LOG_DEBUG, "Played beep, result '%d'\n", res); 01259 if (!res) { 01260 res = ast_waitstream(newlyavailable->chan, ""); 01261 if (option_debug) 01262 ast_log( LOG_DEBUG, "Waited for stream, result '%d'\n", res); 01263 } 01264 ast_mutex_lock(&newlyavailable->lock); 01265 } 01266 return res; 01267 }
|
|
Definition at line 1557 of file chan_agent.c. References agent_pvt::agent, name, agent_pvt::next, and strdup. 01558 { 01559 struct agent_pvt *p; 01560 char name[AST_MAX_AGENT]; 01561 int which = 0; 01562 01563 if (pos == 2) { 01564 for (p=agents; p; p=p->next) { 01565 snprintf(name, sizeof(name), "Agent/%s", p->agent); 01566 if (!strncasecmp(word, name, strlen(word))) { 01567 if (++which > state) { 01568 return strdup(name); 01569 } 01570 } 01571 } 01572 } else if (pos == 3 && state == 0) { 01573 return strdup("soft"); 01574 } 01575 return NULL; 01576 }
|
|
Provides a description of the module.
Definition at line 2503 of file chan_agent.c. 02504 { 02505 return (char *) desc; 02506 }
|
|
Dump AgentCallbackLogin agents to the database for persistence Definition at line 2292 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, and pa_family. Referenced by __login_exec(), action_agent_callback_login(), agent_hangup(), and agent_logoff(). 02293 { 02294 struct agent_pvt *cur_agent = NULL; 02295 char buf[256]; 02296 02297 for (cur_agent = agents; cur_agent; cur_agent = cur_agent->next) { 02298 if (cur_agent->chan) 02299 continue; 02300 02301 if (!ast_strlen_zero(cur_agent->loginchan)) { 02302 snprintf(buf, sizeof(buf), "%s;%s", cur_agent->loginchan, cur_agent->logincallerid); 02303 if (ast_db_put(pa_family, cur_agent->agent, buf)) 02304 ast_log(LOG_WARNING, "failed to create persistent entry!\n"); 02305 else if (option_debug) 02306 ast_log(LOG_DEBUG, "Saved Agent: %s on %s\n", cur_agent->agent, cur_agent->loginchan); 02307 } else { 02308 /* Delete - no agent or there is an error */ 02309 ast_db_del(pa_family, cur_agent->agent); 02310 } 02311 } 02312 }
|
|
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 2498 of file chan_agent.c. 02499 {
02500 return ASTERISK_GPL_KEY;
02501 }
|
|
Initialize the module. Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.
Definition at line 2426 of file chan_agent.c. References action_agent_callback_login(), action_agent_logoff(), action_agents(), agent_tech, agentmonitoroutgoing_exec(), app, app2, app3, ast_channel_register(), ast_cli_register(), ast_log(), ast_manager_register2(), ast_register_application(), callback_exec(), channeltype, cli_agent_logoff, cli_show_agents, descrip, descrip2, descrip3, EVENT_FLAG_AGENT, LOG_ERROR, login_exec(), mandescr_agent_callback_login, mandescr_agent_logoff, mandescr_agents, read_agent_config(), reload_agents(), synopsis, synopsis2, and synopsis3. 02427 { 02428 /* Make sure we can register our agent channel type */ 02429 if (ast_channel_register(&agent_tech)) { 02430 ast_log(LOG_ERROR, "Unable to register channel class %s\n", channeltype); 02431 return -1; 02432 } 02433 /* Dialplan applications */ 02434 ast_register_application(app, login_exec, synopsis, descrip); 02435 ast_register_application(app2, callback_exec, synopsis2, descrip2); 02436 ast_register_application(app3, agentmonitoroutgoing_exec, synopsis3, descrip3); 02437 /* Manager commands */ 02438 ast_manager_register2("Agents", EVENT_FLAG_AGENT, action_agents, "Lists agents and their status", mandescr_agents); 02439 ast_manager_register2("AgentLogoff", EVENT_FLAG_AGENT, action_agent_logoff, "Sets an agent as no longer logged in", mandescr_agent_logoff); 02440 ast_manager_register2("AgentCallbackLogin", EVENT_FLAG_AGENT, action_agent_callback_login, "Sets an agent as logged in by callback", mandescr_agent_callback_login); 02441 /* CLI Application */ 02442 ast_cli_register(&cli_show_agents); 02443 ast_cli_register(&cli_agent_logoff); 02444 /* Read in the config */ 02445 read_agent_config(); 02446 if (persistent_agents) 02447 reload_agents(); 02448 return 0; 02449 }
|
|
Called by the AgentLogin application (from the dial plan).
Definition at line 2122 of file chan_agent.c. References __login_exec(). Referenced by load_module(). 02123 { 02124 return __login_exec(chan, data, 0); 02125 }
|
|
Definition at line 1372 of file chan_agent.c. Referenced by agents_show(), ast_register_translator(), and ast_translator_build_path(). 01373 { 01374 int x; 01375 for (x=0;x<32;x++) { 01376 if (v & (1 << x)) return x; 01377 } 01378 return 0; 01379 }
|
|
Read configuration data. The file named agents.conf.
Definition at line 1023 of file chan_agent.c. References ackcall, add_agent(), agentgoodbye, agents, agent_pvt::app_lock, ast_config_destroy(), ast_config_load(), ast_get_group(), ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_EXPLICIT, ast_strlen_zero(), ast_true(), ast_variable_browse(), ast_variable_retrieve(), 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(). 01024 { 01025 struct ast_config *cfg; 01026 struct ast_variable *v; 01027 struct agent_pvt *p, *pl, *pn; 01028 char *general_val; 01029 01030 group = 0; 01031 autologoff = 0; 01032 wrapuptime = 0; 01033 ackcall = 0; 01034 cfg = ast_config_load(config); 01035 if (!cfg) { 01036 ast_log(LOG_NOTICE, "No agent configuration found -- agent support disabled\n"); 01037 return 0; 01038 } 01039 ast_mutex_lock(&agentlock); 01040 p = agents; 01041 while(p) { 01042 p->dead = 1; 01043 p = p->next; 01044 } 01045 strcpy(moh, "default"); 01046 /* set the default recording values */ 01047 recordagentcalls = 0; 01048 createlink = 0; 01049 strcpy(recordformat, "wav"); 01050 strcpy(recordformatext, "wav"); 01051 urlprefix[0] = '\0'; 01052 savecallsin[0] = '\0'; 01053 01054 /* Read in [general] section for persistence */ 01055 if ((general_val = ast_variable_retrieve(cfg, "general", "persistentagents"))) 01056 persistent_agents = ast_true(general_val); 01057 01058 /* Read in the [agents] section */ 01059 v = ast_variable_browse(cfg, "agents"); 01060 while(v) { 01061 /* Create the interface list */ 01062 if (!strcasecmp(v->name, "agent")) { 01063 add_agent(v->value, 0); 01064 } else if (!strcasecmp(v->name, "group")) { 01065 group = ast_get_group(v->value); 01066 } else if (!strcasecmp(v->name, "autologoff")) { 01067 autologoff = atoi(v->value); 01068 if (autologoff < 0) 01069 autologoff = 0; 01070 } else if (!strcasecmp(v->name, "ackcall")) { 01071 if (!strcasecmp(v->value, "always")) 01072 ackcall = 2; 01073 else if (ast_true(v->value)) 01074 ackcall = 1; 01075 else 01076 ackcall = 0; 01077 } else if (!strcasecmp(v->name, "wrapuptime")) { 01078 wrapuptime = atoi(v->value); 01079 if (wrapuptime < 0) 01080 wrapuptime = 0; 01081 } else if (!strcasecmp(v->name, "maxlogintries") && !ast_strlen_zero(v->value)) { 01082 maxlogintries = atoi(v->value); 01083 if (maxlogintries < 0) 01084 maxlogintries = 0; 01085 } else if (!strcasecmp(v->name, "goodbye") && !ast_strlen_zero(v->value)) { 01086 strcpy(agentgoodbye,v->value); 01087 } else if (!strcasecmp(v->name, "musiconhold")) { 01088 ast_copy_string(moh, v->value, sizeof(moh)); 01089 } else if (!strcasecmp(v->name, "updatecdr")) { 01090 if (ast_true(v->value)) 01091 updatecdr = 1; 01092 else 01093 updatecdr = 0; 01094 } else if (!strcasecmp(v->name, "recordagentcalls")) { 01095 recordagentcalls = ast_true(v->value); 01096 } else if (!strcasecmp(v->name, "createlink")) { 01097 createlink = ast_true(v->value); 01098 } else if (!strcasecmp(v->name, "recordformat")) { 01099 ast_copy_string(recordformat, v->value, sizeof(recordformat)); 01100 if (!strcasecmp(v->value, "wav49")) 01101 strcpy(recordformatext, "WAV"); 01102 else 01103 ast_copy_string(recordformatext, v->value, sizeof(recordformatext)); 01104 } else if (!strcasecmp(v->name, "urlprefix")) { 01105 ast_copy_string(urlprefix, v->value, sizeof(urlprefix)); 01106 if (urlprefix[strlen(urlprefix) - 1] != '/') 01107 strncat(urlprefix, "/", sizeof(urlprefix) - strlen(urlprefix) - 1); 01108 } else if (!strcasecmp(v->name, "savecallsin")) { 01109 if (v->value[0] == '/') 01110 ast_copy_string(savecallsin, v->value, sizeof(savecallsin)); 01111 else 01112 snprintf(savecallsin, sizeof(savecallsin) - 2, "/%s", v->value); 01113 if (savecallsin[strlen(savecallsin) - 1] != '/') 01114 strncat(savecallsin, "/", sizeof(savecallsin) - strlen(savecallsin) - 1); 01115 } else if (!strcasecmp(v->name, "custom_beep")) { 01116 ast_copy_string(beep, v->value, sizeof(beep)); 01117 } 01118 v = v->next; 01119 } 01120 p = agents; 01121 pl = NULL; 01122 while(p) { 01123 pn = p->next; 01124 if (p->dead) { 01125 /* Unlink */ 01126 if (pl) 01127 pl->next = p->next; 01128 else 01129 agents = p->next; 01130 /* Destroy if appropriate */ 01131 if (!p->owner) { 01132 if (!p->chan) { 01133 ast_mutex_destroy(&p->lock); 01134 ast_mutex_destroy(&p->app_lock); 01135 free(p); 01136 } else { 01137 /* Cause them to hang up */ 01138 ast_softhangup(p->chan, AST_SOFTHANGUP_EXPLICIT); 01139 } 01140 } 01141 } else 01142 pl = p; 01143 p = pn; 01144 } 01145 ast_mutex_unlock(&agentlock); 01146 ast_config_destroy(cfg); 01147 return 0; 01148 }
|
|
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 2451 of file chan_agent.c. References read_agent_config(), and reload_agents(). 02452 { 02453 read_agent_config(); 02454 if (persistent_agents) 02455 reload_agents(); 02456 return 0; 02457 }
|
|
Reload the persistent agents from astdb. Definition at line 2317 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, pa_family, set_agentbycallerid(), and strsep(). Referenced by load_module(), and reload(). 02318 { 02319 char *agent_num; 02320 struct ast_db_entry *db_tree; 02321 struct ast_db_entry *entry; 02322 struct agent_pvt *cur_agent; 02323 char agent_data[256]; 02324 char *parse; 02325 char *agent_chan; 02326 char *agent_callerid; 02327 02328 db_tree = ast_db_gettree(pa_family, NULL); 02329 02330 ast_mutex_lock(&agentlock); 02331 for (entry = db_tree; entry; entry = entry->next) { 02332 agent_num = entry->key + strlen(pa_family) + 2; 02333 cur_agent = agents; 02334 while (cur_agent) { 02335 ast_mutex_lock(&cur_agent->lock); 02336 if (strcmp(agent_num, cur_agent->agent) == 0) 02337 break; 02338 ast_mutex_unlock(&cur_agent->lock); 02339 cur_agent = cur_agent->next; 02340 } 02341 if (!cur_agent) { 02342 ast_db_del(pa_family, agent_num); 02343 continue; 02344 } else 02345 ast_mutex_unlock(&cur_agent->lock); 02346 if (!ast_db_get(pa_family, agent_num, agent_data, sizeof(agent_data)-1)) { 02347 if (option_debug) 02348 ast_log(LOG_DEBUG, "Reload Agent: %s on %s\n", cur_agent->agent, agent_data); 02349 parse = agent_data; 02350 agent_chan = strsep(&parse, ";"); 02351 agent_callerid = strsep(&parse, ";"); 02352 ast_copy_string(cur_agent->loginchan, agent_chan, sizeof(cur_agent->loginchan)); 02353 if (agent_callerid) { 02354 ast_copy_string(cur_agent->logincallerid, agent_callerid, sizeof(cur_agent->logincallerid)); 02355 set_agentbycallerid(cur_agent->logincallerid, cur_agent->agent); 02356 } else 02357 cur_agent->logincallerid[0] = '\0'; 02358 if (cur_agent->loginstart == 0) 02359 time(&cur_agent->loginstart); 02360 ast_device_state_changed("Agent/%s", cur_agent->agent); 02361 } 02362 } 02363 ast_mutex_unlock(&agentlock); 02364 if (db_tree) { 02365 ast_log(LOG_NOTICE, "Agents successfully reloaded from database.\n"); 02366 ast_db_freetree(db_tree); 02367 } 02368 }
|
|
Definition at line 727 of file chan_agent.c. References ast_strlen_zero(), GETAGENTBYCALLERID, and pbx_builtin_setvar_helper(). Referenced by __login_exec(), agent_hangup(), agent_logoff(), and reload_agents(). 00728 { 00729 char buf[AST_MAX_BUF]; 00730 00731 /* if there is no Caller ID, nothing to do */ 00732 if (ast_strlen_zero(callerid)) 00733 return; 00734 00735 snprintf(buf, sizeof(buf), "%s_%s",GETAGENTBYCALLERID, callerid); 00736 pbx_builtin_setvar_helper(NULL, buf, agent); 00737 }
|
|
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 2459 of file chan_agent.c. References agent_tech, agents, app, app2, app3, ast_channel_unregister(), ast_cli_unregister(), ast_log(), ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, ast_unregister_application(), cli_agent_logoff, cli_show_agents, LOG_WARNING, agent_pvt::next, and agent_pvt::owner. 02460 { 02461 struct agent_pvt *p; 02462 /* First, take us out of the channel loop */ 02463 /* Unregister CLI application */ 02464 ast_cli_unregister(&cli_show_agents); 02465 ast_cli_unregister(&cli_agent_logoff); 02466 /* Unregister dialplan applications */ 02467 ast_unregister_application(app); 02468 ast_unregister_application(app2); 02469 ast_unregister_application(app3); 02470 /* Unregister manager command */ 02471 ast_manager_unregister("Agents"); 02472 ast_manager_unregister("AgentLogoff"); 02473 ast_manager_unregister("AgentCallbackLogin"); 02474 /* Unregister channel */ 02475 ast_channel_unregister(&agent_tech); 02476 if (!ast_mutex_lock(&agentlock)) { 02477 /* Hangup all interfaces if they have an owner */ 02478 p = agents; 02479 while(p) { 02480 if (p->owner) 02481 ast_softhangup(p->owner, AST_SOFTHANGUP_APPUNLOAD); 02482 p = p->next; 02483 } 02484 agents = NULL; 02485 ast_mutex_unlock(&agentlock); 02486 } else { 02487 ast_log(LOG_WARNING, "Unable to lock the monitor\n"); 02488 return -1; 02489 } 02490 return 0; 02491 }
|
|
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 2493 of file chan_agent.c. 02494 {
02495 return usecnt;
02496 }
|
|
Definition at line 156 of file chan_agent.c. Referenced by 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 1650 of file chan_agent.c. |
|
Definition at line 256 of file chan_agent.c. Referenced by load_module(), and unload_module(). |
|
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. Referenced by add_agent(), agent_unlink(), read_agent_config(), and unload_module(). |
|
Definition at line 77 of file chan_agent.c. Referenced by load_module(), 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 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 load_module(). |
|
Initial value: { { "agent", "logoff", NULL }, agent_logoff_cmd, "Sets an agent offline", agent_logoff_usage, complete_agent_logoff_cmd } Definition at line 1659 of file chan_agent.c. Referenced by load_module(), and unload_module(). |
|
Initial value: { { "show", "agents", NULL }, agents_show, "Show status of agents", show_agents_usage, NULL } Definition at line 1655 of file chan_agent.c. Referenced by load_module(), and unload_module(). |
|
Definition at line 75 of file chan_agent.c. Referenced by agents_show(), and read_agent_config(). |
|
Definition at line 170 of file chan_agent.c. Referenced by read_agent_config(). |
|
Definition at line 72 of file chan_agent.c. |
|
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 read_agent_config(). |
|
Definition at line 1664 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 read_agent_config(). |
|
Definition at line 139 of file chan_agent.c. Referenced by add_agent(), agents_show(), 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 read_agent_config(). |
|
Definition at line 167 of file chan_agent.c. Referenced by 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 1646 of file chan_agent.c. |
|
Definition at line 1663 of file chan_agent.c. |
|
Definition at line 81 of file chan_agent.c. Referenced by load_module(). |
|
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. |
|
Definition at line 173 of file chan_agent.c. Referenced by read_agent_config(). |
|
Definition at line 171 of file chan_agent.c. Referenced by __agent_start_monitoring(), and read_agent_config(). |
|
Definition at line 161 of file chan_agent.c. Referenced by agent_hangup(), and agent_new(). |
|
Definition at line 155 of file chan_agent.c. Referenced by add_agent(), and read_agent_config(). |