[svn-commits] irroot: branch irroot/patches r336227 - /team/irroot/patches/
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Fri Sep 16 08:27:14 CDT 2011
Author: irroot
Date: Fri Sep 16 08:27:13 2011
New Revision: 336227
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=336227
Log:
Distrotech Patch for branches/1.8
Modified:
team/irroot/patches/distrotech-1.8.patch
Modified: team/irroot/patches/distrotech-1.8.patch
URL: http://svnview.digium.com/svn/asterisk/team/irroot/patches/distrotech-1.8.patch?view=diff&rev=336227&r1=336226&r2=336227
==============================================================================
--- team/irroot/patches/distrotech-1.8.patch (original)
+++ team/irroot/patches/distrotech-1.8.patch Fri Sep 16 08:27:13 2011
@@ -571,3 +571,4571 @@
}
if (!ast_test_flag(p, LOCAL_ALREADY_MASQED)) {
+Index: configure.ac
+===================================================================
+--- configure.ac (.../branches/1.8) (revision 336225)
++++ configure.ac (.../team/irroot/distrotech-customers-1.8) (revision 336225)
+@@ -1698,7 +1698,7 @@
+ AST_EXT_LIB_CHECK([SUPPSERV], [suppserv], [encodeFac], [mISDNuser/suppserv.h])
+ AST_C_DEFINE_CHECK([MISDN_FAC_RESULT], [Fac_RESULT], [mISDNuser/suppserv.h])
+ AST_C_DEFINE_CHECK([MISDN_FAC_ERROR], [Fac_ERROR], [mISDNuser/suppserv.h])
+- AC_CHECK_HEADER([linux/mISDNdsp.h], [AC_DEFINE_UNQUOTED([MISDN_1_2], 1, [Build chan_misdn for mISDN 1.2 or later.])])
++ AC_CHECK_HEADER([mISDN/mISDNdsp.h], [AC_DEFINE_UNQUOTED([MISDN_1_2], 1, [Build chan_misdn for mISDN 1.2 or later.])])
+ AC_CHECK_MEMBER([Q931_info_t.redirect_dn], [], [PBX_MISDN=0], [#include <mISDNuser/mISDNlib.h>])
+ fi
+
+Index: apps/app_queue.c
+===================================================================
+--- apps/app_queue.c (.../branches/1.8) (revision 336225)
++++ apps/app_queue.c (.../team/irroot/distrotech-customers-1.8) (revision 336225)
+@@ -522,11 +522,25 @@
+ <enum name="count">
+ <para>Returns the total number of members for the specified queue.</para>
+ </enum>
++ <enum name="penalty">
++ <para>Gets or sets queue member penalty.</para>
++ </enum>
++ <enum name="paused">
++ <para>Gets or sets queue member paused status.</para>
++ </enum>
++ <enum name="ignorebusy">
++ <para>Gets or sets queue member ignorebusy.</para>
++ </enum>
+ </enumlist>
+ </parameter>
++ <parameter name="interface" required="false" />
+ </syntax>
+ <description>
+- <para>Returns the number of members currently associated with the specified <replaceable>queuename</replaceable>.</para>
++ <para>Allows access to queue counts [R] and member information [R/W].</para>
++ <para>
++ <replaceable>queuename</replaceable> is required for all operations
++ <replaceable>interface</replaceable> is required for all member operations.
++ </para>
+ </description>
+ <see-also>
+ <ref type="application">Queue</ref>
+@@ -659,6 +673,7 @@
+ </syntax>
+ <description>
+ <para>Gets or sets queue members penalty.</para>
++ <warning><para>This function has been deprecated in favor of the <literal>QUEUE_MEMBER()</literal> function</para></warning>
+ </description>
+ <see-also>
+ <ref type="application">Queue</ref>
+@@ -934,6 +949,12 @@
+ /*! \brief queues.conf [general] option */
+ static int update_cdr = 0;
+
++/*! \brief queues.conf [general] option */
++static int negative_penalty_invalid = 0;
++
++/*! \brief queues.conf [general] option */
++static int log_membername_as_agent = 0;
++
+ enum queue_result {
+ QUEUE_UNKNOWN = 0,
+ QUEUE_TIMEOUT = 1,
+@@ -1043,6 +1064,7 @@
+ unsigned int dead:1; /*!< Used to detect members deleted in realtime */
+ unsigned int delme:1; /*!< Flag to delete entry on reload */
+ char rt_uniqueid[80]; /*!< Unique id of realtime member entry */
++ unsigned int ignorebusy:1; /*!< Flag to ignore member if the status is not available */
+ };
+
+ enum empty_conditions {
+@@ -1160,6 +1182,7 @@
+ int timeout; /*!< How long to wait for an answer */
+ int weight; /*!< Respective weight */
+ int autopause; /*!< Auto pause queue members if they fail to answer */
++ int autopausedelay; /*!< Delay auto pause for autopausedelay seconds since last call */
+ int timeoutpriority; /*!< Do we allow a fraction of the timeout to occur for a ring? */
+
+ /* Queue strategy things */
+@@ -1190,9 +1213,12 @@
+ static struct ao2_container *queues;
+
+ static void update_realtime_members(struct call_queue *q);
++static struct member *interface_exists(struct call_queue *q, const char *interface);
+ static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
+
+-static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
++static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
++
++static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
+ /*! \brief sets the QUEUESTATUS channel variable */
+ static void set_queue_result(struct ast_channel *chan, enum queue_result res)
+ {
+@@ -1436,13 +1462,14 @@
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "MemberName: %s\r\n"
++ "StateInterface: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+ "LastCall: %d\r\n"
+ "Status: %d\r\n"
+ "Paused: %d\r\n",
+- q->name, m->interface, m->membername, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
++ q->name, m->interface, m->membername, m->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
+ m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
+ );
+
+@@ -1552,7 +1579,7 @@
+ return state;
+ }
+
+-static int extension_state_cb(char *context, char *exten, enum ast_extension_states state, void *data)
++static int extension_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data)
+ {
+ struct ao2_iterator miter, qiter;
+ struct member *m;
+@@ -1698,6 +1725,7 @@
+ q->numperiodicannounce = 0;
+ q->autopause = QUEUE_AUTOPAUSE_OFF;
+ q->timeoutpriority = TIMEOUT_PRIORITY_APP;
++ q->autopausedelay = 0;
+ if (!q->members) {
+ if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED)
+ /* linear strategy depends on order, so we have to place all members in a single bucket */
+@@ -2008,6 +2036,8 @@
+ q->montype = 1;
+ } else if (!strcasecmp(param, "autopause")) {
+ q->autopause = autopause2int(val);
++ } else if (!strcasecmp(param, "autopausedelay")) {
++ q->autopausedelay = atoi(val);
+ } else if (!strcasecmp(param, "maxlen")) {
+ q->maxlen = atoi(val);
+ if (q->maxlen < 0)
+@@ -2077,16 +2107,24 @@
+ * \brief Find rt member record to update otherwise create one.
+ *
+ * Search for member in queue, if found update penalty/paused state,
+- * if no member exists create one flag it as a RT member and add to queue member list.
++ * if no member exists create one flag it as a RT member and add to queue member list.
+ */
+-static void rt_handle_member_record(struct call_queue *q, char *interface, const char *rt_uniqueid, const char *membername, const char *penalty_str, const char *paused_str, const char* state_interface)
++static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
+ {
+ struct member *m;
+ struct ao2_iterator mem_iter;
+ int penalty = 0;
+ int paused = 0;
+ int found = 0;
++ int ignorebusy = 0;
+
++ const char *config_val;
++ const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
++ const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
++ const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
++ const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
++ const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
++
+ if (ast_strlen_zero(rt_uniqueid)) {
+ ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
+ return;
+@@ -2094,8 +2132,11 @@
+
+ if (penalty_str) {
+ penalty = atoi(penalty_str);
+- if (penalty < 0)
++ if ((penalty < 0) && negative_penalty_invalid) {
++ return;
++ } else if (penalty < 0) {
+ penalty = 0;
++ }
+ }
+
+ if (paused_str) {
+@@ -2104,33 +2145,45 @@
+ paused = 0;
+ }
+
+- /* Find member by realtime uniqueid and update */
+- mem_iter = ao2_iterator_init(q->members, 0);
+- while ((m = ao2_iterator_next(&mem_iter))) {
+- if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
+- m->dead = 0; /* Do not delete this one. */
+- ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
+- if (paused_str)
+- m->paused = paused;
+- if (strcasecmp(state_interface, m->state_interface)) {
+- ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
+- }
+- m->penalty = penalty;
+- found = 1;
+- ao2_ref(m, -1);
+- break;
+- }
+- ao2_ref(m, -1);
+- }
++ if ((config_val = ast_variable_retrieve(member_config, interface, "ignorebusy"))) {
++ ignorebusy = ast_true(config_val);
++ } else {
++ ignorebusy = 1;
++ }
++
++ /* Find member by realtime uniqueid and update */
++ mem_iter = ao2_iterator_init(q->members, 0);
++ while ((m = ao2_iterator_next(&mem_iter))) {
++ if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
++ m->dead = 0; /* Do not delete this one. */
++ ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
++ if (paused_str)
++ m->paused = paused;
++ if (strcasecmp(state_interface, m->state_interface)) {
++ ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
++ }
++ m->penalty = penalty;
++ m->ignorebusy = ignorebusy;
++ found = 1;
++ ao2_ref(m, -1);
++ break;
++ }
++ ao2_ref(m, -1);
++ }
+ ao2_iterator_destroy(&mem_iter);
+
+- /* Create a new member */
+- if (!found) {
++ /* Create a new member */
++ if (!found) {
+ if ((m = create_queue_member(interface, membername, penalty, paused, state_interface))) {
+ m->dead = 0;
+ m->realtime = 1;
++ m->ignorebusy = ignorebusy;
+ ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
+- ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", "");
++ if (!log_membername_as_agent) {
++ ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", "");
++ } else {
++ ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", "");
++ }
+ ao2_link(q->members, m);
+ ao2_ref(m, -1);
+ m = NULL;
+@@ -2304,19 +2357,18 @@
+ ao2_iterator_destroy(&mem_iter);
+
+ while ((interface = ast_category_browse(member_config, interface))) {
+- rt_handle_member_record(q, interface,
+- ast_variable_retrieve(member_config, interface, "uniqueid"),
+- S_OR(ast_variable_retrieve(member_config, interface, "membername"),interface),
+- ast_variable_retrieve(member_config, interface, "penalty"),
+- ast_variable_retrieve(member_config, interface, "paused"),
+- S_OR(ast_variable_retrieve(member_config, interface, "state_interface"),interface));
++ rt_handle_member_record(q, interface, member_config);
+ }
+
+ /* Delete all realtime members that have been deleted in DB. */
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((m = ao2_iterator_next(&mem_iter))) {
+ if (m->dead) {
+- ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
++ if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
++ ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
++ } else {
++ ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
++ }
+ ao2_unlink(q->members, m);
+ q->membercount--;
+ }
+@@ -2425,19 +2477,18 @@
+ ao2_iterator_destroy(&mem_iter);
+
+ while ((interface = ast_category_browse(member_config, interface))) {
+- rt_handle_member_record(q, interface,
+- ast_variable_retrieve(member_config, interface, "uniqueid"),
+- S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface),
+- ast_variable_retrieve(member_config, interface, "penalty"),
+- ast_variable_retrieve(member_config, interface, "paused"),
+- S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface));
++ rt_handle_member_record(q, interface, member_config);
+ }
+
+ /* Delete all realtime members that have been deleted in DB. */
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((m = ao2_iterator_next(&mem_iter))) {
+ if (m->dead) {
+- ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
++ if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
++ ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
++ } else {
++ ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
++ }
+ ao2_unlink(q->members, m);
+ q->membercount--;
+ }
+@@ -2874,16 +2925,24 @@
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((mem = ao2_iterator_next(&mem_iter))) {
+ switch (mem->status) {
+- case AST_DEVICE_INUSE:
+- if (!q->ringinuse)
++ case AST_DEVICE_INVALID:
++ case AST_DEVICE_UNAVAILABLE:
+ break;
+- /* else fall through */
+- case AST_DEVICE_NOT_INUSE:
+- case AST_DEVICE_UNKNOWN:
+- if (!mem->paused) {
+- avl++;
+- }
+- break;
++ case AST_DEVICE_INUSE:
++ case AST_DEVICE_BUSY:
++ case AST_DEVICE_RINGING:
++ case AST_DEVICE_RINGINUSE:
++ case AST_DEVICE_ONHOLD:
++ if ((!q->ringinuse) || (!mem->ignorebusy)) {
++ break;
++ }
++ /* else fall through */
++ case AST_DEVICE_NOT_INUSE:
++ case AST_DEVICE_UNKNOWN:
++ if (!mem->paused) {
++ avl++;
++ }
++ break;
+ }
+ ao2_ref(mem, -1);
+
+@@ -3009,38 +3068,54 @@
+ char tech[256];
+ char *location;
+ const char *macrocontext, *macroexten;
++ enum ast_device_state newstate;
+
+ /* on entry here, we know that tmp->chan == NULL */
++ if (tmp->member->paused) {
++ ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
++ if (qe->chan->cdr) {
++ ast_cdr_busy(qe->chan->cdr);
++ }
++ tmp->stillgoing = 0;
++ return 0;
++ }
++
+ if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
+ (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
+- ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
++ ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
+ (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
++ }
+ tmp->stillgoing = 0;
+ (*busies)++;
+ return 0;
+ }
+
+- if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
+- ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
+- if (qe->chan->cdr)
+- ast_cdr_busy(qe->chan->cdr);
+- tmp->stillgoing = 0;
+- return 0;
++ if (!qe->parent->ringinuse || !tmp->member->ignorebusy) {
++ if ((tmp->member->status == AST_DEVICE_UNKNOWN) || (tmp->member->status == AST_DEVICE_NOT_INUSE)) {
++ newstate = ast_parse_device_state(tmp->member->interface);
++ if (newstate != tmp->member->status) {
++ ast_log(LOG_ERROR, "Found a channel matching iterface %s while status was %i changed to %i\n",
++ tmp->member->interface, tmp->member->status, newstate);
++ update_status(qe->parent, tmp->member, newstate);
++ }
++ }
++ if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
++ ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
++ if (qe->chan->cdr) {
++ ast_cdr_busy(qe->chan->cdr);
++ }
++ tmp->stillgoing = 0;
++ return 0;
++ }
+ }
+
+- if (tmp->member->paused) {
+- ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
+- if (qe->chan->cdr)
+- ast_cdr_busy(qe->chan->cdr);
+- tmp->stillgoing = 0;
+- return 0;
+- }
+ if (use_weight && compare_weight(qe->parent,tmp->member)) {
+ ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
++ }
+ tmp->stillgoing = 0;
+ (*busies)++;
+ return 0;
+@@ -3055,8 +3130,9 @@
+ /* Request the peer */
+ tmp->chan = ast_request(tech, qe->chan->nativeformats, qe->chan, location, &status);
+ if (!tmp->chan) { /* If we can't, just go on to the next call */
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_cdr_busy(qe->chan->cdr);
++ }
+ tmp->stillgoing = 0;
+
+ ao2_lock(qe->parent);
+@@ -3395,6 +3471,18 @@
+ }
+ ast_queue_log(qe->parent->name, qe->chan->uniqueid, membername, "RINGNOANSWER", "%d", rnatime);
+ if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && pause) {
++ if (qe->parent->autopausedelay > 0) {
++ struct member *mem;
++ ao2_lock(qe->parent);
++ if ((mem = interface_exists(qe->parent, interface))) {
++ time_t idletime = time(&idletime)-mem->lastcall;
++ if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
++ ao2_unlock(qe->parent);
++ return;
++ }
++ }
++ ao2_unlock(qe->parent);
++ }
+ if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
+ if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
+ ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
+@@ -4692,8 +4780,9 @@
+ else
+ ast_moh_stop(qe->chan);
+ /* If appropriate, log that we have a destination channel */
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_cdr_setdestchan(qe->chan->cdr, peer->name);
++ }
+ /* Make sure channels are compatible */
+ res = ast_channel_make_compatible(qe->chan, peer);
+ if (res < 0) {
+@@ -4773,10 +4862,11 @@
+ if (mixmonapp) {
+ ast_debug(1, "Starting MixMonitor as requested.\n");
+ if (!monitorfilename) {
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_copy_string(tmpid, qe->chan->cdr->uniqueid, sizeof(tmpid));
+- else
++ } else {
+ snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
++ }
+ } else {
+ const char *m = monitorfilename;
+ for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
+@@ -4843,12 +4933,13 @@
+
+ ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
+ /* We purposely lock the CDR so that pbx_exec does not update the application data */
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_set_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
++ }
+ pbx_exec(qe->chan, mixmonapp, mixmonargs);
+- if (qe->chan->cdr)
++ if (qe->chan->cdr) {
+ ast_clear_flag(qe->chan->cdr, AST_CDR_FLAG_LOCKED);
+-
++ }
+ } else {
+ ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
+ }
+@@ -4984,8 +5075,28 @@
+ qe->handled++;
+ ast_queue_log(queuename, qe->chan->uniqueid, member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, peer->uniqueid,
+ (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
+- if (update_cdr && qe->chan->cdr)
+- ast_copy_string(qe->chan->cdr->dstchannel, member->membername, sizeof(qe->chan->cdr->dstchannel));
++
++ if (update_cdr && qe->chan->cdr) {
++ struct ast_cdr *cdr;
++ struct ast_cdr *newcdr;
++
++ cdr = qe->chan->cdr;
++ while (cdr->next) {
++ cdr = cdr->next;
++ }
++ if ((strcasecmp(cdr->uniqueid, qe->chan->uniqueid)) && (strcasecmp(cdr->linkedid, qe->chan->uniqueid))) {
++ if ((newcdr = ast_cdr_dup(cdr))) {
++ ast_cdr_init(newcdr, qe->chan);
++ ast_cdr_reset(newcdr, 0);
++ ast_lock_channel(qe->chan);
++ cdr = ast_cdr_append(cdr, newcdr);
++ cdr = cdr->next;
++ ast_unlock_channel(qe->chan);
++ }
++ }
++ ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
++ }
++
+ if (qe->parent->eventwhencalled)
+ manager_event(EVENT_FLAG_AGENT, "AgentConnect",
+ "Queue: %s\r\n"
+@@ -5166,7 +5277,10 @@
+ ao2_lock(q);
+ if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
+ /* XXX future changes should beware of this assumption!! */
+- if (!mem->dynamic) {
++ /*Change Penalty on realtime users*/
++ if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
++ update_realtime_member_field(mem, q->name, "penalty", "-1");
++ } else if (!mem->dynamic) {
+ ao2_ref(mem, -1);
+ ao2_unlock(q);
+ queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
+@@ -5223,13 +5337,14 @@
+ "Queue: %s\r\n"
+ "Location: %s\r\n"
+ "MemberName: %s\r\n"
++ "StateInterface: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+ "LastCall: %d\r\n"
+ "Status: %d\r\n"
+ "Paused: %d\r\n",
+- q->name, new_member->interface, new_member->membername,
++ q->name, new_member->interface, new_member->membername, state_interface,
+ "dynamic",
+ new_member->penalty, new_member->calls, (int) new_member->lastcall,
+ new_member->status, new_member->paused);
+@@ -5336,35 +5451,34 @@
+ int foundinterface = 0, foundqueue = 0;
+ struct call_queue *q;
+ struct member *mem;
+- struct ao2_iterator queue_iter;
++ char rtpenalty[80];
+
+- if (penalty < 0) {
++ if (penalty < 0 && !negative_penalty_invalid) {
+ ast_log(LOG_ERROR, "Invalid penalty (%d)\n", penalty);
+ return RESULT_FAILURE;
+ }
+
+- queue_iter = ao2_iterator_init(queues, 0);
+- while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
++ if ((q = load_realtime_queue(queuename))) {
++ foundqueue++;
+ ao2_lock(q);
+- if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
+- foundqueue++;
+- if ((mem = interface_exists(q, interface))) {
+- foundinterface++;
++ if ((mem = interface_exists(q, interface))) {
++ foundinterface++;
++ if (!mem->realtime) {
+ mem->penalty = penalty;
+-
+- ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
+- manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
+- "Queue: %s\r\n"
+- "Location: %s\r\n"
+- "Penalty: %d\r\n",
+- q->name, mem->interface, penalty);
+- ao2_ref(mem, -1);
++ } else {
++ sprintf(rtpenalty,"%i", penalty);
++ update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
+ }
++ ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
++ manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
++ "Queue: %s\r\n"
++ "Location: %s\r\n"
++ "Penalty: %d\r\n",
++ q->name, mem->interface, penalty);
++ ao2_ref(mem, -1);
+ }
+ ao2_unlock(q);
+- queue_t_unref(q, "Done with iterator");
+ }
+- ao2_iterator_destroy(&queue_iter);
+
+ if (foundinterface) {
+ return RESULT_SUCCESS;
+@@ -5582,6 +5696,8 @@
+ {
+ int res=-1;
+ char *parse, *temppos = NULL;
++ struct member *mem = NULL;
++
+ AST_DECLARE_APP_ARGS(args,
+ AST_APP_ARG(queuename);
+ AST_APP_ARG(interface);
+@@ -5607,9 +5723,17 @@
+
+ ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
+
++ if (log_membername_as_agent) {
++ mem = find_member_by_queuename_and_interface(args.queuename, args.interface);
++ }
++
+ switch (remove_from_queue(args.queuename, args.interface)) {
+ case RES_OKAY:
+- ast_queue_log(args.queuename, chan->uniqueid, args.interface, "REMOVEMEMBER", "%s", "");
++ if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
++ ast_queue_log(args.queuename, chan->uniqueid, args.interface, "REMOVEMEMBER", "%s", "");
++ } else {
++ ast_queue_log(args.queuename, chan->uniqueid, mem->membername, "REMOVEMEMBER", "%s", "");
++ }
+ ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
+ pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
+ res = 0;
+@@ -5674,7 +5798,11 @@
+
+ switch (add_to_queue(args.queuename, args.interface, args.membername, penalty, 0, queue_persistent_members, args.state_interface)) {
+ case RES_OKAY:
+- ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
++ if (ast_strlen_zero(args.membername) || !log_membername_as_agent) {
++ ast_queue_log(args.queuename, chan->uniqueid, args.interface, "ADDMEMBER", "%s", "");
++ } else {
++ ast_queue_log(args.queuename, chan->uniqueid, args.membername, "ADDMEMBER", "%s", "");
++ }
+ ast_log(LOG_NOTICE, "Added interface '%s' to queue '%s'\n", args.interface, args.queuename);
+ pbx_builtin_setvar_helper(chan, "AQMSTATUS", "ADDED");
+ res = 0;
+@@ -5690,7 +5818,7 @@
+ res = 0;
+ break;
+ case RES_OUTOFMEMORY:
+- ast_log(LOG_ERROR, "Out of memory adding member %s to queue %s\n", args.interface, args.queuename);
++ ast_log(LOG_ERROR, "Out of memory adding interface %s to queue %s\n", args.interface, args.queuename);
+ break;
+ }
+
+@@ -6134,31 +6262,37 @@
+ return 0;
+ }
+
+-/*!
++/*!
+ * \brief Get number either busy / free / ready or total members of a specific queue
+- * \retval number of members (busy / free / ready / total)
++ * \brief Get or set member properties penalty / paused / ignorebusy
++ * \retval number of members (busy / free / ready / total) or member info (penalty / paused / ignorebusy)
+ * \retval -1 on error
+ */
+-static int queue_function_qac(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
++static int queue_function_mem_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+ {
+ int count = 0;
+ struct member *m;
+ struct ao2_iterator mem_iter;
+ struct call_queue *q;
+- char *option;
+
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(queuename);
++ AST_APP_ARG(option);
++ AST_APP_ARG(interface);
++ );
++ /* Make sure the returned value on error is zero length string. */
++ buf[0] = '\0';
++
+ if (ast_strlen_zero(data)) {
+ ast_log(LOG_ERROR, "%s requires an argument: queuename\n", cmd);
+ return -1;
+ }
+
+- if ((option = strchr(data, ',')))
+- *option++ = '\0';
+- else
+- option = "logged";
+- if ((q = load_realtime_queue(data))) {
++ AST_STANDARD_APP_ARGS(args, data);
++
++ if ((q = load_realtime_queue(args.queuename))) {
+ ao2_lock(q);
+- if (!strcasecmp(option, "logged")) {
++ if (!strcasecmp(args.option, "logged")) {
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((m = ao2_iterator_next(&mem_iter))) {
+ /* Count the agents who are logged in and presently answering calls */
+@@ -6168,7 +6302,7 @@
+ ao2_ref(m, -1);
+ }
+ ao2_iterator_destroy(&mem_iter);
+- } else if (!strcasecmp(option, "free")) {
++ } else if (!strcasecmp(args.option, "free")) {
+ mem_iter = ao2_iterator_init(q->members, 0);
+ while ((m = ao2_iterator_next(&mem_iter))) {
+ /* Count the agents who are logged in and presently answering calls */
+@@ -6178,7 +6312,7 @@
+ ao2_ref(m, -1);
+ }
+ ao2_iterator_destroy(&mem_iter);
+- } else if (!strcasecmp(option, "ready")) {
++ } else if (!strcasecmp(args.option, "ready")) {
+ time_t now;
+ time(&now);
+ mem_iter = ao2_iterator_init(q->members, 0);
+@@ -6191,22 +6325,104 @@
+ ao2_ref(m, -1);
+ }
+ ao2_iterator_destroy(&mem_iter);
+- } else /* must be "count" */
++ } else if (!strcasecmp(args.option, "count") || ast_strlen_zero(args.option)) {
+ count = q->membercount;
++ } else if (!strcasecmp(args.option, "penalty") && !ast_strlen_zero(args.interface) &&
++ ((m = interface_exists(q, args.interface)))) {
++ count = m->penalty;
++ } else if (!strcasecmp(args.option, "paused") && !ast_strlen_zero(args.interface) &&
++ ((m = interface_exists(q, args.interface)))) {
++ count = m->paused;
++ } else if (!strcasecmp(args.option, "ignorebusy") && !ast_strlen_zero(args.interface) &&
++ ((m = interface_exists(q, args.interface)))) {
++ count = m->ignorebusy;
++ }
+ ao2_unlock(q);
+ queue_t_unref(q, "Done with temporary reference in QUEUE_MEMBER()");
+- } else
+- ast_log(LOG_WARNING, "queue %s was not found\n", data);
++ } else {
++ ast_log(LOG_WARNING, "queue %s was not found\n", args.queuename);
++ }
+
+ snprintf(buf, len, "%d", count);
+
+ return 0;
+ }
+
+-/*!
++/*! \brief Dialplan function QUEUE_MEMBER() Sets the members penalty / paused / ignorebusy. */
++static int queue_function_mem_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
++{
++ int memvalue;
++ struct call_queue *q;
++ struct member *m;
++ char rtvalue[80];
++
++ AST_DECLARE_APP_ARGS(args,
++ AST_APP_ARG(queuename);
++ AST_APP_ARG(option);
++ AST_APP_ARG(interface);
++ );
++
++ if (ast_strlen_zero(data)) {
++ ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER(<queuename>,<option>,<interface>)\n");
++ return -1;
++ }
++
++ AST_STANDARD_APP_ARGS(args, data);
++
++ if (args.argc < 3) {
++ ast_log(LOG_ERROR, "Missing argument. QUEUE_MEMBER_PENALTY(<queuename>,<interface>)\n");
++ return -1;
++ }
++
++ if (ast_strlen_zero(args.interface) && ast_strlen_zero(args.option)) {
++ ast_log (LOG_ERROR, "<interface> and <option> parameter's can't be null\n");
++ return -1;
++ }
++
++ memvalue = atoi(value);
++
++ if (!strcasecmp(args.option, "penalty")) {
++ /* if queuename = NULL then penalty will be set for interface in all the queues.*/
++ if (set_member_penalty(args.queuename, args.interface, memvalue)) {
++ ast_log(LOG_ERROR, "Invalid interface, queue or penalty\n");
++ return -1;
++ }
++ } else if ((q = load_realtime_queue(args.queuename))) {
++ ao2_lock(q);
++ if ((m = interface_exists(q, args.interface))) {
++ sprintf(rtvalue, "%s",(memvalue <= 0) ? "0" : "1");
++ if (!strcasecmp(args.option, "paused")) {
++ if (m->realtime) {
++ update_realtime_member_field(m, q->name, args.option, rtvalue);
++ } else {
++ m->paused = (memvalue <= 0) ? 0 : 1;
++ }
++ } else if (!strcasecmp(args.option, "ignorebusy")) {
++ if (m->realtime) {
++ update_realtime_member_field(m, q->name, args.option, rtvalue);
++ } else {
++ m->ignorebusy = (memvalue <= 0) ? 0 : 1;
++ }
++ } else {
++ ast_log(LOG_ERROR, "Invalid option, only penalty , paused or ignorebusy are valid\n");
++ return -1;
++ }
++ } else {
++ ast_log(LOG_ERROR, "Invalid interface or queue\n");
++ return -1;
++ }
++ ao2_unlock(q);
++ } else {
++ ast_log(LOG_ERROR, "Invalid queue\n");
++ return -1;
++ }
++ return 0;
++}
++
++/*!
+ * \brief Get the total number of members in a specific queue (Deprecated)
+- * \retval number of members
+- * \retval -1 on error
++ * \retval number of members
++ * \retval -1 on error
+ */
+ static int queue_function_qac_dep(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
+ {
+@@ -6412,7 +6628,8 @@
+
+ static struct ast_custom_function queuemembercount_function = {
+ .name = "QUEUE_MEMBER",
+- .read = queue_function_qac,
++ .read = queue_function_mem_read,
++ .write = queue_function_mem_write,
+ };
+
+ static struct ast_custom_function queuemembercount_dep = {
+@@ -6495,8 +6712,9 @@
+ {
+ const char *general_val = NULL;
+ queue_persistent_members = 0;
+- if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers")))
++ if ((general_val = ast_variable_retrieve(cfg, "general", "persistentmembers"))) {
+ queue_persistent_members = ast_true(general_val);
++ }
+ autofill_default = 0;
+ if ((general_val = ast_variable_retrieve(cfg, "general", "autofill")))
+ autofill_default = ast_true(general_val);
+@@ -6511,6 +6729,12 @@
+ shared_lastcall = 0;
+ if ((general_val = ast_variable_retrieve(cfg, "general", "shared_lastcall")))
+ shared_lastcall = ast_true(general_val);
++ negative_penalty_invalid = 0;
++ if ((general_val = ast_variable_retrieve(cfg, "general", "negative_penalty_invalid")))
++ negative_penalty_invalid = ast_true(general_val);
++ log_membername_as_agent = 0;
++ if ((general_val = ast_variable_retrieve(cfg, "general", "log_membername_as_agent")))
++ log_membername_as_agent = ast_true(general_val);
+ }
+
+ /*! \brief reload information pertaining to a single member
+@@ -6958,7 +7182,11 @@
+ while ((mem = ao2_iterator_next(&mem_iter))) {
+ ast_str_set(&out, 0, " %s", mem->membername);
+ if (strcasecmp(mem->membername, mem->interface)) {
+- ast_str_append(&out, 0, " (%s)", mem->interface);
++ ast_str_append(&out, 0, " (%s", mem->interface);
++ if (mem->state_interface) {
++ ast_str_append(&out, 0, " from %s", mem->state_interface);
++ }
++ ast_str_append(&out, 0, ")");
+ }
+ if (mem->penalty)
+ ast_str_append(&out, 0, " with penalty %d", mem->penalty);
+@@ -7226,6 +7454,7 @@
+ "Queue: %s\r\n"
+ "Name: %s\r\n"
+ "Location: %s\r\n"
++ "StateInterface: %s\r\n"
+ "Membership: %s\r\n"
+ "Penalty: %d\r\n"
+ "CallsTaken: %d\r\n"
+@@ -7234,7 +7463,7 @@
+ "Paused: %d\r\n"
+ "%s"
+ "\r\n",
+- q->name, mem->membername, mem->interface, mem->dynamic ? "dynamic" : "static",
++ q->name, mem->membername, mem->interface, mem->state_interface, mem->dynamic ? "dynamic" : "static",
+ mem->penalty, mem->calls, (int)mem->lastcall, mem->status, mem->paused, idText);
+ }
+ ao2_ref(mem, -1);
+@@ -7310,7 +7539,11 @@
+
+ switch (add_to_queue(queuename, interface, membername, penalty, paused, queue_persistent_members, state_interface)) {
+ case RES_OKAY:
+- ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
++ if (ast_strlen_zero(membername) || !log_membername_as_agent) {
++ ast_queue_log(queuename, "MANAGER", interface, "ADDMEMBER", "%s", "");
++ } else {
++ ast_queue_log(queuename, "MANAGER", membername, "ADDMEMBER", "%s", "");
++ }
+ astman_send_ack(s, m, "Added interface to queue");
+ break;
+ case RES_EXISTS:
+@@ -7330,6 +7563,7 @@
+ static int manager_remove_queue_member(struct mansession *s, const struct message *m)
+ {
+ const char *queuename, *interface;
++ struct member *mem = NULL;
+
+ queuename = astman_get_header(m, "Queue");
+ interface = astman_get_header(m, "Interface");
+@@ -7339,9 +7573,17 @@
+ return 0;
+ }
+
++ if (log_membername_as_agent) {
++ mem = find_member_by_queuename_and_interface(queuename, interface);
++ }
++
+ switch (remove_from_queue(queuename, interface)) {
+ case RES_OKAY:
+- ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
++ if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
++ ast_queue_log(queuename, "MANAGER", interface, "REMOVEMEMBER", "%s", "");
++ } else {
++ ast_queue_log(queuename, "MANAGER", mem->membername, "REMOVEMEMBER", "%s", "");
++ }
+ astman_send_ack(s, m, "Removed interface from queue");
+ break;
+ case RES_EXISTS:
+@@ -7563,7 +7805,11 @@
+
+ switch (add_to_queue(queuename, interface, membername, penalty, 0, queue_persistent_members, state_interface)) {
+ case RES_OKAY:
+- ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
++ if (ast_strlen_zero(membername) || !log_membername_as_agent) {
++ ast_queue_log(queuename, "CLI", interface, "ADDMEMBER", "%s", "");
++ } else {
++ ast_queue_log(queuename, "CLI", membername, "ADDMEMBER", "%s", "");
++ }
+ ast_cli(a->fd, "Added interface '%s' to queue '%s'\n", interface, queuename);
+ return CLI_SUCCESS;
+ case RES_EXISTS:
+@@ -7631,11 +7877,12 @@
+ static char *handle_queue_remove_member(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ const char *queuename, *interface;
++ struct member *mem = NULL;
+
+ switch (cmd) {
+ case CLI_INIT:
+ e->command = "queue remove member";
+- e->usage =
++ e->usage =
+ "Usage: queue remove member <channel> from <queue>\n"
+ " Remove a specific channel from a queue.\n";
+ return NULL;
+@@ -7652,10 +7899,18 @@
+ queuename = a->argv[5];
+ interface = a->argv[3];
+
++ if (log_membername_as_agent) {
++ mem = find_member_by_queuename_and_interface(queuename, interface);
++ }
++
+ switch (remove_from_queue(queuename, interface)) {
+ case RES_OKAY:
+- ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
+- ast_cli(a->fd, "Removed interface '%s' from queue '%s'\n", interface, queuename);
++ if (!mem || ast_strlen_zero(mem->membername) || !log_membername_as_agent) {
++ ast_queue_log(queuename, "CLI", interface, "REMOVEMEMBER", "%s", "");
++ } else {
++ ast_queue_log(queuename, "CLI", mem->membername, "REMOVEMEMBER", "%s", "");
++ }
++ ast_cli(a->fd, "Removed interface %s from queue '%s'\n", interface, queuename);
+ return CLI_SUCCESS;
+ case RES_EXISTS:
+ ast_cli(a->fd, "Unable to remove interface '%s' from queue '%s': Not there\n", interface, queuename);
+@@ -8378,6 +8633,26 @@
+ return 0;
+ }
+
++/* \brief Find a member by looking up queuename and interface.
++ * \return Returns a member or NULL if member not found.
++*/
++static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface)
++{
++ struct member tmpmem, *mem = NULL;
++ struct call_queue *q;
++
++ ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
++ if ((q = load_realtime_queue(queuename))) {
++ ao2_lock(q);
++ if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
++ ao2_ref(mem, -1);
++ }
++ ao2_unlock(q);
++ queue_t_unref(q, "Expiring temporary reference.");
++ }
++ return mem;
++}
++
+ AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "True Call Queueing",
+ .load = load_module,
+ .unload = unload_module,
+Index: addons/chan_ooh323.c
+===================================================================
+--- addons/chan_ooh323.c (.../branches/1.8) (revision 336225)
++++ addons/chan_ooh323.c (.../team/irroot/distrotech-customers-1.8) (revision 336225)
+@@ -25,6 +25,42 @@
+ #include "chan_ooh323.h"
+ #include <math.h>
+
++/*** DOCUMENTATION
++ <function name="OOH323" language="en_US">
++ <synopsis>
++ Allow Setting / Reading OOH323 Settings
++ </synopsis>
++ <syntax>
++ <parameter name="name" required="true">
++ <enumlist>
++ <enum name="faxdetect">
++ <para>Fax Detect [R/W]</para>
++ <para>Returns 0 or 1</para>
++ <para>Write yes or no</para>
++ </enum>
++ </enumlist>
++ <enumlist>
++ <enum name="t38support">
++ <para>t38support [R/W]</para>
++ <para>Returns 0 or 1</para>
++ <para>Write yes or no</para>
++ </enum>
++ </enumlist>
++ <enumlist>
++ <enum name="h323id">
++ <para>Returns h323id [R]</para>
++ </enum>
++ </enumlist>
++ </parameter>
++ </syntax>
++ <description>
++ <para>Read and set channel parameters in the dialplan.
++ <replaceable>name</replaceable> is one of the above only those with a [W] can be writen to.
++ </para>
++ </description>
++ </function>
++***/
++
+ #define FORMAT_STRING_SIZE 512
+
+ /* Defaults */
+@@ -50,6 +86,9 @@
+ #define T38_ENABLED 1
+ #define T38_FAXGW 1
+
++#define FAXDETECT_CNG 1
++#define FAXDETECT_T38 2
++
+ /* Channel description */
+ static const char type[] = "OOH323";
+ static const char tdesc[] = "Objective Systems H323 Channel Driver";
+@@ -140,6 +179,8 @@
+ struct ast_rtp_instance *vrtp; /* Placeholder for now */
+
+ int t38support; /* T.38 mode - disable, transparent, faxgw */
++ int faxdetect;
++ int faxdetected;
+ int rtptimeout;
+ struct ast_udptl *udptl;
+ int faxmode;
+@@ -201,25 +242,26 @@
+ /* Profile of H.323 user registered with PBX*/
+ struct ooh323_user{
+ ast_mutex_t lock;
+- char name[256];
+- char context[AST_MAX_EXTENSION];
+- int incominglimit;
[... 3505 lines stripped ...]
More information about the svn-commits
mailing list