[asterisk-commits] russell: branch russell/chan_refcount r89795 - in /team/russell/chan_refcount...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Nov 27 16:18:41 CST 2007


Author: russell
Date: Tue Nov 27 16:18:41 2007
New Revision: 89795

URL: http://svn.digium.com/view/asterisk?view=rev&rev=89795
Log:
sync with trunk

Modified:
    team/russell/chan_refcount/   (props changed)
    team/russell/chan_refcount/main/autoservice.c
    team/russell/chan_refcount/main/pbx.c
    team/russell/chan_refcount/pbx/pbx_config.c

Propchange: team/russell/chan_refcount/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/russell/chan_refcount/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Nov 27 16:18:41 2007
@@ -1,1 +1,1 @@
-/trunk:1-89786
+/trunk:1-89794

Modified: team/russell/chan_refcount/main/autoservice.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/autoservice.c?view=diff&rev=89795&r1=89794&r2=89795
==============================================================================
--- team/russell/chan_refcount/main/autoservice.c (original)
+++ team/russell/chan_refcount/main/autoservice.c Tue Nov 27 16:18:41 2007
@@ -47,6 +47,11 @@
 
 struct asent {
 	struct ast_channel *chan;
+	/*! This gets incremented each time autoservice gets started on the same
+	 *  channel.  It will ensure that it doesn't actually get stopped until 
+	 *  it gets stopped for the last time. */
+	unsigned int use_count;
+	AST_LIST_HEAD_NOLOCK(, ast_frame) dtmf_frames;
 	AST_LIST_ENTRY(asent) list;
 };
 
@@ -74,8 +79,42 @@
 		AST_RWLIST_UNLOCK(&aslist);
 
 		if ((chan = ast_waitfor_n(mons, x, &ms))) {
-			/* Read and ignore anything that occurs */
 			struct ast_frame *f = ast_read(chan);
+			
+			/* Do not add a default entry in this switch statement.  Each new
+			 * frame type should be addressed directly as to whether it should
+			 * be queued up or not. */
+			switch (f->frametype) {
+			/* Save these frames */
+			case AST_FRAME_DTMF_BEGIN:
+			case AST_FRAME_DTMF_END:
+			case AST_FRAME_CONTROL:
+			case AST_FRAME_TEXT:
+			case AST_FRAME_IMAGE:
+			case AST_FRAME_HTML:
+			{
+				struct ast_frame *dup_f;
+
+				AST_RWLIST_WRLOCK(&aslist);
+				AST_RWLIST_TRAVERSE(&aslist, as, list) {
+					if (as->chan != chan)
+						continue;
+					if ((dup_f = ast_frdup(f)))
+						AST_LIST_INSERT_TAIL(&as->dtmf_frames, dup_f, frame_list);
+				}
+				AST_RWLIST_UNLOCK(&aslist);
+			}
+
+			/* Throw these frames away */
+			case AST_FRAME_VOICE:
+			case AST_FRAME_VIDEO:
+			case AST_FRAME_NULL:
+			case AST_FRAME_IAX:
+			case AST_FRAME_CNG:
+			case AST_FRAME_MODEM:
+				break;
+			}
+
 			if (f)
 				ast_frfree(f);
 		}
@@ -95,13 +134,16 @@
 
 	/* Check if the channel already has autoservice */
 	AST_RWLIST_TRAVERSE(&aslist, as, list) {
-		if (as->chan == chan)
+		if (as->chan == chan) {
+			as->use_count++;
 			break;
+		}
 	}
 
 	/* If not, start autoservice on channel */
 	if (!as && (as = ast_calloc(1, sizeof(*as)))) {
 		as->chan = chan;
+		as->use_count = 1;
 		AST_RWLIST_INSERT_HEAD(&aslist, as, list);
 		res = 0;
 		if (asthread == AST_PTHREADT_NULL) { /* need start the thread */
@@ -116,7 +158,9 @@
 				pthread_kill(asthread, SIGURG);
 		}
 	}
+
 	AST_RWLIST_UNLOCK(&aslist);
+
 	return res;
 }
 
@@ -124,11 +168,22 @@
 {
 	int res = -1;
 	struct asent *as;
+	AST_LIST_HEAD_NOLOCK(, ast_frame) dtmf_frames;
+	struct ast_frame *f;
+	int removed = 1;
+
+	AST_LIST_HEAD_INIT_NOLOCK(&dtmf_frames);
 
 	AST_RWLIST_WRLOCK(&aslist);
 	AST_RWLIST_TRAVERSE_SAFE_BEGIN(&aslist, as, list) {	
 		if (as->chan == chan) {
 			AST_RWLIST_REMOVE_CURRENT(list);
+			as->use_count--;
+			if (as->use_count) {
+				removed = 0;
+				break;
+			}
+			AST_LIST_APPEND_LIST(&dtmf_frames, &as->dtmf_frames, frame_list);
 			ast_free(as);
 			if (!ast_check_hangup(chan))
 				res = 0;
@@ -137,13 +192,22 @@
 	}
 	AST_RWLIST_TRAVERSE_SAFE_END;
 
-	if (asthread != AST_PTHREADT_NULL) 
+	if (removed && asthread != AST_PTHREADT_NULL) 
 		pthread_kill(asthread, SIGURG);
+	
 	AST_RWLIST_UNLOCK(&aslist);
+
+	if (!removed)
+		return 0;
 
 	/* Wait for it to un-block */
 	while (ast_test_flag(chan, AST_FLAG_BLOCKING))
 		usleep(1000);
 
+	while ((f = AST_LIST_REMOVE_HEAD(&dtmf_frames, frame_list))) {
+		ast_queue_frame(chan, f);
+		ast_frfree(f);
+	}
+
 	return res;
 }

Modified: team/russell/chan_refcount/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/main/pbx.c?view=diff&rev=89795&r1=89794&r2=89795
==============================================================================
--- team/russell/chan_refcount/main/pbx.c (original)
+++ team/russell/chan_refcount/main/pbx.c Tue Nov 27 16:18:41 2007
@@ -2583,7 +2583,8 @@
 	pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
 }
 
-/*! \brief The return value depends on the action:
+/*! 
+ * \brief The return value depends on the action:
  *
  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
  *	and return 0 on failure, -1 on match;
@@ -2593,6 +2594,12 @@
  *	
  * \retval 0 on success.
  * \retval  -1 on failure.
+ *
+ * \note The channel is auto-serviced in this function, because doing an extension
+ * match may block for a long time.  For example, if the lookup has to use a network
+ * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
+ * auto-service code will queue up any important signalling frames to be processed
+ * after this is done.
  */
 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
   const char *context, const char *exten, int priority,
@@ -2605,20 +2612,25 @@
 	char passdata[EXT_DATA_SIZE];
 
 	int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
+
+	ast_autoservice_start(c);
 	
 	ast_rdlock_contexts();
 	if (found)
 		*found = 0;
+
 	e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
 	if (e) {
 		if (found)
 			*found = 1;
 		if (matching_action) {
 			ast_unlock_contexts();
+			ast_autoservice_stop(c);
 			return -1;	/* success, we found it */
 		} else if (action == E_FINDLABEL) { /* map the label to a priority */
 			res = e->priority;
 			ast_unlock_contexts();
+			ast_autoservice_stop(c);
 			return res;	/* the priority we were looking for */
 		} else {	/* spawn */
 			if (!e->cached_app)
@@ -2627,6 +2639,7 @@
 			ast_unlock_contexts();
 			if (!app) {
 				ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
+				ast_autoservice_stop(c);
 				return -1;
 			}
 			if (c->context != context)
@@ -2662,17 +2675,20 @@
 					"AppData: %s\r\n"
 					"Uniqueid: %s\r\n",
 					c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
+			ast_autoservice_stop(c);
 			return pbx_exec(c, app, passdata);	/* 0 on success, -1 on failure */
 		}
 	} else if (q.swo) {	/* not found here, but in another switch */
 		ast_unlock_contexts();
-		if (matching_action)
+		if (matching_action) {
+			ast_autoservice_stop(c);
 			return -1;
-		else {
+		} else {
 			if (!q.swo->exec) {
 				ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
 				res = -1;
 			}
+			ast_autoservice_stop(c);
 			return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
 		}
 	} else {	/* not found anywhere, see what happened */
@@ -2697,6 +2713,8 @@
 		default:
 			ast_debug(1, "Shouldn't happen!\n");
 		}
+
+		ast_autoservice_stop(c);
 
 		return (matching_action) ? 0 : -1;
 	}
@@ -3590,7 +3608,8 @@
 			return c;
 	}
 #endif
-	ast_unlock_contexts();
+	if (!c)
+		ast_unlock_contexts();
 
 	return c;
 }

Modified: team/russell/chan_refcount/pbx/pbx_config.c
URL: http://svn.digium.com/view/asterisk/team/russell/chan_refcount/pbx/pbx_config.c?view=diff&rev=89795&r1=89794&r2=89795
==============================================================================
--- team/russell/chan_refcount/pbx/pbx_config.c (original)
+++ team/russell/chan_refcount/pbx/pbx_config.c Tue Nov 27 16:18:41 2007
@@ -1000,7 +1000,7 @@
 	if (!app_data)
 		app_data="";
 	if (ast_add_extension(a->argv[5], a->argc == 7 ? 1 : 0, exten, iprior, NULL, cidmatch, app,
-		(void *)strdup(app_data), ast_free, registrar)) {
+		(void *)strdup(app_data), ast_free_ptr, registrar)) {
 		switch (errno) {
 		case ENOMEM:
 			ast_cli(a->fd, "Out of free memory\n");




More information about the asterisk-commits mailing list