[asterisk-commits] rmudgett: branch rmudgett/bridge_phase r391589 - in /team/rmudgett/bridge_pha...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Jun 12 19:15:39 CDT 2013
Author: rmudgett
Date: Wed Jun 12 19:15:37 2013
New Revision: 391589
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=391589
Log:
Fill out agents.conf parsing code.
Modified:
team/rmudgett/bridge_phase/apps/app_agent_pool.c
team/rmudgett/bridge_phase/configs/agents.conf.sample
Modified: team/rmudgett/bridge_phase/apps/app_agent_pool.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/apps/app_agent_pool.c?view=diff&rev=391589&r1=391588&r2=391589
==============================================================================
--- team/rmudgett/bridge_phase/apps/app_agent_pool.c (original)
+++ team/rmudgett/bridge_phase/apps/app_agent_pool.c Wed Jun 12 19:15:37 2013
@@ -142,24 +142,7 @@
/* ------------------------------------------------------------------- */
-/*
- * BUGBUG Change agents.conf to use this format:
- * [general]
- * section reserved
- *
- * [agents]
- * gives warning if present and declines to load.
- *
- * [1001] <- agent-id/username
- * secret=password
- * fullname=Agent name used for logging purposes.
- * other parameters.
- *
- * None of the current global options need to remain global.
- * They can be made per agent.
- */
-
-/*! Single agent config line parameters. */
+/*! Agent config parameters. */
struct agent_cfg {
AST_DECLARE_STRING_FIELDS(
/*! Identification of the agent. (agents config container key) */
@@ -169,63 +152,131 @@
/*! Name of agent for logging and querying purposes */
AST_STRING_FIELD(full_name);
- /*! DTMF string for an agent to accept a call. (login override) */
+ /*!
+ * \brief DTMF string for an agent to accept a call.
+ *
+ * \note The channel variable AGENTACCEPTDTMF overrides on login.
+ */
AST_STRING_FIELD(dtmf_accept);
- /*! DTMF string for an agent to end a call. (login override) */
+ /*!
+ * \brief DTMF string for an agent to end a call.
+ *
+ * \note The channel variable AGENTENDDTMF overrides on login.
+ */
AST_STRING_FIELD(dtmf_end);
/*! Beep sound file to use. Alert the agent a call is waiting. */
AST_STRING_FIELD(beep_sound);
-/* BUGBUG NOT USED agents.conf goodbye option */
- AST_STRING_FIELD(goodbye_sound);
/*! MOH class to use while agent waiting for call. */
AST_STRING_FIELD(moh);
/*! Absolute recording filename directory. (Made to start and end with '/') */
AST_STRING_FIELD(save_calls_in);
- /*! Recording filename extension. */
+ /*! Recording format filename extension. */
AST_STRING_FIELD(record_format);
-/* BUGBUG the following config option likely cannot be supported: record_format_text */
- /*! Recording filename extension used with url_prefix. */
- AST_STRING_FIELD(record_format_text);
-/* BUGBUG the following config option likely cannot be supported: url_prefix */
- /*! CDR userfield recording filename directory. */
- AST_STRING_FIELD(url_prefix);
);
/*! Agent groups an agent belongs to. */
ast_group_t group;
- /*! Number of seconds for agent to ack a call before being logged off if non-zero. (login override) */
- int auto_logoff;
- /*! TRUE if agent needs to ack a call to accept it. (login override) */
+ /*!
+ * \brief Number of failed login attempts allowed.
+ *
+ * \note The channel variable AGENTLMAXLOGINTRIES overrides on login.
+ * \note If zero then unlimited attempts.
+ */
+ unsigned int max_login_tries;
+ /*!
+ * \brief Number of seconds for agent to ack a call before being logged off.
+ *
+ * \note The channel variable AGENTAUTOLOGOFF overrides on login.
+ * \note If zero then timer is disabled.
+ */
+ unsigned int auto_logoff;
+ /*!
+ * \brief Time after a call in ms before the agent can get a new call.
+ *
+ * \note The channel variable AGENTWRAPUPTIME overrides on login.
+ */
+ unsigned int wrapup_time;
+ /*!
+ * \brief TRUE if agent needs to ack a call to accept it.
+ *
+ * \note The channel variable AGENTACKCALL overrides on login.
+ */
int ack_call;
- /*! TRUE if agent can use DTMF to end a call. */
+ /*!
+ * \brief TRUE if agent can use DTMF to end a call.
+ *
+ * \note The channel variable AGENTENDCALL overrides on login.
+ */
int end_call;
- /*! Number ms after a call before can get a new call. (login override) */
- int wrapup_time;
- /*! Number of failed login attempts allowed. (login override) */
- int max_login_tries;
-/* BUGBUG the following config option likely cannot be supported: updatecdr */
- /*! TRUE if CDR is to be updated with agent id. (login override) */
- int updatecdr;
-/* BUGBUG NOT USED agents.conf autologoffunavail option */
- int autologoffunavail;
/*! TRUE if agent calls are recorded. */
int record_agent_calls;
};
-static void *agent_cfg_alloc(const char *username)
-{
- /*! \todo BUGBUG agent_cfg_alloc() not written */
- return NULL;
+/*!
+ * \internal
+ * \brief Agent config ao2 container sort function.
+ * \since 12.0.0
+ *
+ * \param obj_left pointer to the (user-defined part) of an object.
+ * \param obj_right pointer to the (user-defined part) of an object.
+ * \param flags flags from ao2_callback()
+ * OBJ_POINTER - if set, 'obj_right', is an object.
+ * OBJ_KEY - if set, 'obj_right', is a search key item that is not an object.
+ * OBJ_PARTIAL_KEY - if set, 'obj_right', is a partial search key item that is not an object.
+ *
+ * \retval <0 if obj_left < obj_right
+ * \retval =0 if obj_left == obj_right
+ * \retval >0 if obj_left > obj_right
+ */
+static int agent_cfg_sort_cmp(const void *obj_left, const void *obj_right, int flags)
+{
+ const struct agent_cfg *cfg_left = obj_left;
+ const struct agent_cfg *cfg_right = obj_right;
+ const char *right_key = obj_right;
+ int cmp;
+
+ switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
+ default:
+ case OBJ_POINTER:
+ right_key = cfg_right->username;
+ /* Fall through */
+ case OBJ_KEY:
+ cmp = strcmp(cfg_left->username, right_key);
+ break;
+ case OBJ_PARTIAL_KEY:
+ cmp = strncmp(cfg_left->username, right_key, strlen(right_key));
+ break;
+ }
+ return cmp;
+}
+
+static void agent_cfg_destructor(void *vdoomed)
+{
+ struct agent_cfg *doomed = vdoomed;
+
+ ast_string_field_free_memory(doomed);
+}
+
+static void *agent_cfg_alloc(const char *name)
+{
+ struct agent_cfg *cfg;
+
+ cfg = ao2_alloc_options(sizeof(*cfg), agent_cfg_destructor,
+ AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!cfg || ast_string_field_init(cfg, 64)) {
+ return NULL;
+ }
+ ast_string_field_set(cfg, username, name);
+ return cfg;
}
static void *agent_cfg_find(struct ao2_container *agents, const char *username)
{
- /*! \todo BUGBUG agent_cfg_find() not written */
- return NULL;
-}
-
-/*! Agents config section */
+ return ao2_find(agents, username, OBJ_KEY);
+}
+
+/*! Agents configuration */
struct agents_cfg {
- /*! Configured agents */
+ /*! Master configured agents container. */
struct ao2_container *agents;
};
@@ -239,6 +290,8 @@
.item_offset = offsetof(struct agents_cfg, agents),
};
+static struct aco_type *agent_types[] = ACO_TYPES(&agent_type);
+
/* The general category is reserved, but unused */
static struct aco_type general_type = {
.type = ACO_GLOBAL,
@@ -280,25 +333,130 @@
* .types = ACO_TYPES(&users_type, &users_general_type),
*};
*
- * .files = ACO_FILES(&agents_conf, &users_conf),
+ * .files = ACO_FILES(&agents_conf, &users_conf),
+ *
+ * Will need a preapply config function to create valid users.conf
+ * agents in the master agents config container.
+ * See verify_default_profiles();
*/
static AO2_GLOBAL_OBJ_STATIC(cfg_handle);
+static void agents_cfg_destructor(void *vdoomed)
+{
+ struct agents_cfg *doomed = vdoomed;
+
+ ao2_cleanup(doomed->agents);
+ doomed->agents = NULL;
+}
+
+/*!
+ * \internal
+ * \brief Create struct agents_cfg object.
+ * \since 12.0.0
+ *
+ * \note A lock is not needed for the object or any secondary
+ * created cfg objects. These objects are immutable after the
+ * config is loaded and applied.
+ *
+ * \retval New struct agents_cfg object.
+ * \retval NULL on error.
+ */
static void *agents_cfg_alloc(void)
{
- /*
- * Create struct agents_cfg object. A lock is not needed for
- * the object or any secondary created cfg objects. These
- * objects are immutable after the config is loaded.
- */
- /*! \todo BUGBUG agents_cfg_alloc() not written */
- return NULL;
+ struct agents_cfg *cfg;
+
+ cfg = ao2_alloc_options(sizeof(*cfg), agents_cfg_destructor,
+ AO2_ALLOC_OPT_LOCK_NOLOCK);
+ if (!cfg) {
+ return NULL;
+ }
+ cfg->agents = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
+ AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, agent_cfg_sort_cmp, NULL);
+ return cfg;
}
CONFIG_INFO_STANDARD(cfg_info, cfg_handle, agents_cfg_alloc,
.files = ACO_FILES(&agents_conf),
);
+
+/*!
+ * \internal
+ * \brief Handle the agent group option.
+ * \since 12.0.0
+ *
+ * \param opt The option being configured
+ * \param var The config variable to use to configure \a obj
+ * \param obj The object to be configured
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int agent_group_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct agent_cfg *cfg = obj;
+
+/* BUGBUG config framework needs to handle group and groupname parsing. */
+ cfg->group = ast_get_group(var->value);
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Handle the agent savecallsin option.
+ * \since 12.0.0
+ *
+ * \param opt The option being configured
+ * \param var The config variable to use to configure \a obj
+ * \param obj The object to be configured
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int agent_savecallsin_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct agent_cfg *cfg = obj;
+ size_t len;
+ int need_leading;
+ int need_trailing;
+
+ if (ast_strlen_zero(var->value)) {
+ ast_string_field_set(cfg, save_calls_in, "");
+ return 0;
+ }
+
+ /* Add a leading and/or trailing '/' if needed. */
+ len = strlen(var->value);
+ need_leading = var->value[0] != '/';
+ need_trailing = var->value[len - 1] != '/';
+ ast_string_field_build(cfg, save_calls_in, "%s%s%s",
+ need_leading ? "/" : "", var->value, need_trailing ? "/" : "");
+ return 0;
+}
+
+/*!
+ * \internal
+ * \brief Handle the agent custom_beep option.
+ * \since 12.0.0
+ *
+ * \param opt The option being configured
+ * \param var The config variable to use to configure \a obj
+ * \param obj The object to be configured
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int agent_custom_beep_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+ struct agent_cfg *cfg = obj;
+
+ if (ast_strlen_zero(var->value)) {
+ return -1;
+ }
+
+ ast_string_field_set(cfg, beep_sound, "");
+ return 0;
+}
static void destroy_config(void)
{
@@ -314,7 +472,24 @@
}
}
- /*! \todo BUGBUG load_config() not written */
+ /* Agent options */
+ aco_option_register(&cfg_info, "maxlogintries", ACO_EXACT, agent_types, "3", OPT_UINT_T, 0, FLDSET(struct agent_cfg, max_login_tries));
+ aco_option_register(&cfg_info, "autologoff", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, auto_logoff));
+ aco_option_register(&cfg_info, "ackcall", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, ack_call));
+ aco_option_register(&cfg_info, "acceptdtmf", ACO_EXACT, agent_types, "#", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, dtmf_accept));
+ aco_option_register(&cfg_info, "endcall", ACO_EXACT, agent_types, "yes", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, end_call));
+ aco_option_register(&cfg_info, "enddtmf", ACO_EXACT, agent_types, "*", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, dtmf_end));
+ aco_option_register(&cfg_info, "wrapuptime", ACO_EXACT, agent_types, "0", OPT_UINT_T, 0, FLDSET(struct agent_cfg, wrapup_time));
+ aco_option_register(&cfg_info, "musiconhold", ACO_EXACT, agent_types, "default", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, moh));
+ aco_option_register_custom(&cfg_info, "group", ACO_EXACT, agent_types, "", agent_group_handler, 0);
+ aco_option_register(&cfg_info, "recordagentcalls", ACO_EXACT, agent_types, "no", OPT_BOOL_T, 1, FLDSET(struct agent_cfg, record_agent_calls));
+ aco_option_register(&cfg_info, "recordformat", ACO_EXACT, agent_types, "wav", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, record_format));
+ aco_option_register_custom(&cfg_info, "savecallsin", ACO_EXACT, agent_types, "", agent_savecallsin_handler, 0);
+ aco_option_register_custom(&cfg_info, "custom_beep", ACO_EXACT, agent_types, "beep", agent_custom_beep_handler, 0);
+ aco_option_register(&cfg_info, "password", ACO_EXACT, agent_types, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, password));
+ aco_option_register(&cfg_info, "fullname", ACO_EXACT, agent_types, "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct agent_cfg, full_name));
+
+ /*! \todo BUGBUG load_config() needs users.conf handling. */
if (aco_process_config(&cfg_info, reload) == ACO_PROCESS_ERROR) {
goto error;
Modified: team/rmudgett/bridge_phase/configs/agents.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_phase/configs/agents.conf.sample?view=diff&rev=391589&r1=391588&r2=391589
==============================================================================
--- team/rmudgett/bridge_phase/configs/agents.conf.sample (original)
+++ team/rmudgett/bridge_phase/configs/agents.conf.sample Wed Jun 12 19:15:37 2013
@@ -9,12 +9,15 @@
;[agent-id]
;
; Define maxlogintries to allow the agent to try max logins before failed.
-; Default is 3
+; The channel variable AGENTLMAXLOGINTRIES overrides on login.
+; Default is 3.
;maxlogintries=5
;
-; Define autologoff times if appropriate. This is how long a call for
-; the agent has to wait for the agent to acknowledge the call before the
-; agent is automatically logged off (in seconds)
+; Set how long a call for the agent has to wait for the agent to acknowledge
+; the call before the agent is automatically logged off (in seconds).
+; If set to zero then the call will wait forever for the agent to acknowledge.
+; The channel variable AGENTAUTOLOGOFF overrides on login.
+; Default is 0.
;autologoff=15
;
;BUGBUG the following is going away: autologoffunavail
@@ -26,29 +29,34 @@
;
; Define ackcall to require the agent to give a DTMF acknowledgement
; when the agent receives a call.
+; The channel variable AGENTACKCALL overrides on login.
; Default is "no".
;ackcall=no
;
; Set what DTMF key sequence the agent should use to acknowledge a call.
-; Default is '#'.
+; The channel variable AGENTACCEPTDTMF overrides on login.
+; Default is "#".
;acceptdtmf=#
;
; Define endcall to allow the agent to hangup a call with a DTMF key
; sequence.
+; The channel variable AGENTENDCALL overrides on login.
; Default is "yes".
;endcall=yes
;
; Set what DTMF key sequence the agent should use to end a call.
-; Default is '*'.
+; The channel variable AGENTENDDTMF overrides on login.
+; Default is "*".
;enddtmf=*
;
; Set the minimum amount of time after disconnecting a call before
; the agent can receive a new call in milliseconds.
+; The channel variable AGENTWRAPUPTIME overrides on login.
; Default is 0.
;wrapuptime=5000
;
; Set the musiconhold class for the agent.
-; Default is default.
+; Default is "default".
;musiconhold=default
;
;BUGBUG the following is going away: goodbye
@@ -63,13 +71,13 @@
;updatecdr=no
;
; Set the agent groups this agent belongs to.
-; Default is none.
+; Default is "".
;group=3
;group=1,2
;group=
;
; Enable recording calls the agent takes.
-; Default is no.
+; Default is "no".
;recordagentcalls=yes
;
; The format used to record the calls: wav, gsm, wav49.
@@ -80,17 +88,22 @@
; The text to be added to the name of the recording. Allows forming a url link.
;urlprefix=http://localhost/calls/
;
-; Set the directory to save the agent's conversations in.
-; Default is /var/spool/asterisk/monitor
+; Set the absolute directory to save the agent's conversations in.
+; Default is "".
+; An empty string becomes asterisk.conf's astspooldir/monitor
+; which resolves to /var/spool/asterisk/monitor by default.
;savecallsin=/var/calls
;
; A custom beep sound file to play to the agent.
+; Default is "beep".
;custom_beep=beep
;
; Set the password the agent uses to login.
-;secret=1234
+; Default is "".
+;password=1234
;
; Set the agent name used in logging messages.
+; Default is "".
;fullname=Mark Spencer
;
; --------------------------------------------------
@@ -108,10 +121,10 @@
;
; Define agent 1001 using the my-agents template:
;[1001](my-agents)
-;secret=1234
+;password=1234
;fullname=Mark Spencer
;
; Define agent 1002 using the my-agents template:
;[1002](my-agents)
-;secret=4321
+;password=4321
;fullname=Will Meadows
More information about the asterisk-commits
mailing list