[asterisk-commits] irroot: branch irroot/patches r336227 - /team/irroot/patches/

SVN commits to the Asterisk project asterisk-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 asterisk-commits mailing list