[asterisk-commits] murf: branch murf/bug11210 r109173 - in /team/murf/bug11210: ./ apps/ channel...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Mar 17 13:07:20 CDT 2008


Author: murf
Date: Mon Mar 17 13:07:20 2008
New Revision: 109173

URL: http://svn.digium.com/view/asterisk?view=rev&rev=109173
Log:
Merged revisions 107998,108032,108034,108084,108137 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r107998 | tilghman | 2008-03-12 01:43:03 -0600 (Wed, 12 Mar 2008) | 7 lines

Deadlock fixes
(closes issue #12143)
 Reported by: kactus
 Patches: 
       20080312__bug12143__2.diff.txt uploaded by Corydon76 (license 14)
 Tested by: kactus

................
r108032 | russell | 2008-03-12 11:02:57 -0600 (Wed, 12 Mar 2008) | 12 lines

Merged revisions 108031 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r108031 | russell | 2008-03-12 11:59:07 -0500 (Wed, 12 Mar 2008) | 4 lines

Destroy the channel lock after the channel datastores.

(inspired by issue #12187)

........

................
r108034 | russell | 2008-03-12 11:06:37 -0600 (Wed, 12 Mar 2008) | 4 lines

 - Add Tilghman to the copyright info ... he wrote the hard part :)
 - Remove some magic in unload_module that isn't needed.  Module use counts
   already ensure that the function isn't going to be in use at this point.

................
r108084 | file | 2008-03-12 12:29:33 -0600 (Wed, 12 Mar 2008) | 12 lines

Merged revisions 108083 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r108083 | file | 2008-03-12 15:26:37 -0300 (Wed, 12 Mar 2008) | 4 lines

Add a trigger mode that triggers on both read and write. The actual function that returns the combined audio frame though will wait until both sides have fed in audio, or until one side stops (such as the case when you call Wait).
(closes issue #11945)
Reported by: xheliox

........

................
r108137 | russell | 2008-03-12 13:59:05 -0600 (Wed, 12 Mar 2008) | 50 lines

Merged revisions 108135 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r108135 | russell | 2008-03-12 14:57:42 -0500 (Wed, 12 Mar 2008) | 40 lines

(closes issue #12187, reported by atis, fixed by me after some brainstorming
 on the issue with mmichelson)

- Update copyright info on app_chanspy.

- Fix a race condition that caused app_chanspy to crash.  The issue was that
  the chanspy datastore magic that was used to ensure that spyee channels did
  not disappear out from under the code did not completely solve the problem.
  It was actually possible for chanspy to acquire a channel reference out of
  its datastore to a channel that was in the middle of being destroyed.  That
  was because datastore destruction in ast_channel_free() was done near the
  end.  So, this left the code in app_chanspy accessing a channel that was
  partially, or completely invalid because it was in the process of being free'd
  by another thread.  The following sort of shows the code path where the race 
  occurred:

  =============================================================================
  Thread 1 (PBX thread for spyee chan)  ||   Thread 2 (chanspy)
  --------------------------------------||-------------------------------------
  ast_channel_free()                    ||
    - remove channel from channel list  ||
    - lock/unlock the channel to ensure ||
      that no references retrieved from ||
      the channel list exist.           ||
  --------------------------------------||-------------------------------------
                                        || channel_spy()
    - destroy some channel data         ||  - Lock chanspy datastore
                                        ||  - Retrieve reference to channel
                                        ||  - lock channel
                                        ||  - Unlock chanspy datastore
  --------------------------------------||-------------------------------------
     - destroy channel datastores       ||
        - call chanspy datastore d'tor  ||  
          which NULL's out the ds'      ||  - Operate on the channel ...
          reference to the channel      ||     
                                        ||
    - free the channel                  || 
                                        ||
                                        ||  - unlock the channel
  --------------------------------------||-------------------------------------
  =============================================================================

........

................

Modified:
    team/murf/bug11210/   (props changed)
    team/murf/bug11210/apps/app_chanspy.c
    team/murf/bug11210/apps/app_mixmonitor.c
    team/murf/bug11210/channels/chan_sip.c
    team/murf/bug11210/funcs/func_config.c
    team/murf/bug11210/include/asterisk/astobj2.h
    team/murf/bug11210/include/asterisk/audiohook.h
    team/murf/bug11210/include/asterisk/pbx.h
    team/murf/bug11210/main/astobj2.c
    team/murf/bug11210/main/audiohook.c
    team/murf/bug11210/main/channel.c
    team/murf/bug11210/main/pbx.c

Propchange: team/murf/bug11210/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/murf/bug11210/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Mar 17 13:07:20 2008
@@ -1,1 +1,1 @@
-/trunk:1-107978
+/trunk:1-108141

Modified: team/murf/bug11210/apps/app_chanspy.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/apps/app_chanspy.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/apps/app_chanspy.c (original)
+++ team/murf/bug11210/apps/app_chanspy.c Mon Mar 17 13:07:20 2008
@@ -2,7 +2,7 @@
  * Asterisk -- An open source telephony toolkit.
  *
  * Copyright (C) 2005 Anthony Minessale II (anthmct at yahoo.com)
- * Copyright (C) 2005 - 2006, Digium, Inc.
+ * Copyright (C) 2005 - 2008, Digium, Inc.
  *
  * A license has been granted to Digium (via disclaimer) for the use of
  * this code.
@@ -23,6 +23,8 @@
  * \brief ChanSpy: Listen in on any channel.
  *
  * \author Anthony Minessale II <anthmct at yahoo.com>
+ * \author Joshua Colp <jcolp at digium.com>
+ * \author Russell Bryant <russell at digium.com>
  *
  * \ingroup applications
  */

Modified: team/murf/bug11210/apps/app_mixmonitor.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/apps/app_mixmonitor.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/apps/app_mixmonitor.c (original)
+++ team/murf/bug11210/apps/app_mixmonitor.c Mon Mar 17 13:07:20 2008
@@ -253,7 +253,7 @@
 		return;
 	}
 
-	ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_WRITE);
+	ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
 
 	if (readvol)
 		mixmonitor->audiohook.options.read_volume = readvol;

Modified: team/murf/bug11210/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/channels/chan_sip.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/channels/chan_sip.c (original)
+++ team/murf/bug11210/channels/chan_sip.c Mon Mar 17 13:07:20 2008
@@ -2382,6 +2382,7 @@
 }
 
 #define sip_pvt_lock(x) ao2_lock(x)
+#define sip_pvt_trylock(x) ao2_trylock(x)
 #define sip_pvt_unlock(x) ao2_unlock(x)
 
 /*!
@@ -6125,6 +6126,7 @@
 		}
 	}
 
+restartsearch:
 	if (!pedanticsipchecking) {
 		struct sip_pvt tmp_dialog = {
 			.callid = callid,
@@ -6136,11 +6138,18 @@
 			return sip_pvt_ptr;
 		}
 	} else { /* in pedantic mode! -- do the fancy linear search */
+		ao2_lock(dialogs);
 		p = ao2_t_callback(dialogs, 0 /* single, data */, find_call_cb, &arg, "pedantic linear search for dialog");
 		if (p) {
-			sip_pvt_lock(p);
+			if (sip_pvt_trylock(p)) {
+				ao2_unlock(dialogs);
+				usleep(1);
+				ao2_lock(dialogs);
+				goto restartsearch;
+			}
 			return p;
 		}
+		ao2_unlock(dialogs);
 	}
  
 	/* See if the method is capable of creating a dialog */
@@ -12776,7 +12785,13 @@
 {
 	struct sip_pvt *dialog = dialogobj;
 	time_t *t = arg;
-	sip_pvt_lock(dialog);
+	
+	if (sip_pvt_trylock(dialog)) {
+		ao2_unlock(dialogs);
+		usleep(1);
+		ao2_lock(dialogs);
+		return CMP_STOP;
+	}
 	
 	/* Check RTP timeouts and kill calls if we have a timeout set and do not get RTP */
 	check_rtp_timeout(dialog, *t);
@@ -19147,7 +19162,7 @@
 		}
 
 		/* Check for dialogs needing to be killed */
-
+	  restartsearch:
 		t = time(NULL);
 		/* don't scan the dialogs list if it hasn't been a reasonable period
 		   of time since the last time we did it (when MWI is being sent, we can
@@ -19155,6 +19170,9 @@
 		*/
 
 		ao2_t_callback(dialogs, OBJ_UNLINK|OBJ_NODATA, dialog_needdestroy, &t, "callback to remove dialogs w/needdestroy");
+
+		if (ao2_container_count(dialogs) != 0)
+			goto restartsearch;
 
 		pthread_testcancel();
 		/* Wait for sched or io */

Modified: team/murf/bug11210/funcs/func_config.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/funcs/func_config.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/funcs/func_config.c (original)
+++ team/murf/bug11210/funcs/func_config.c Mon Mar 17 13:07:20 2008
@@ -4,6 +4,7 @@
  * Copyright (C) 2008, Digium, Inc.
  *
  * Russell Bryant <russell at digium.com>
+ * Tilghman Lesher <func_config__200803 at the-tilghman.com>
  *
  * See http://www.asterisk.org for more information about
  * the Asterisk project. Please do not directly contact
@@ -21,6 +22,7 @@
  * \brief A function to retrieve variables from an Asterisk configuration file
  *
  * \author Russell Bryant <russell at digium.com>
+ * \author Tilghman Lesher <func_config__200803 at the-tilghman.com>
  * 
  * \ingroup functions
  */
@@ -170,20 +172,13 @@
 	struct config_item *cur;
 	int res = ast_custom_function_unregister(&config_function);
 
-	/* Allow anything already in the routine to exit */
-	usleep(1);
 	AST_RWLIST_WRLOCK(&configs);
-	usleep(1);
-	AST_RWLIST_UNLOCK(&configs);
-	/* Even if it needed to upgrade a lock */
-	usleep(1);
-	AST_RWLIST_WRLOCK(&configs);
-	/* At this point, no other thread should be queued inside this module */
 	while ((cur = AST_RWLIST_REMOVE_HEAD(&configs, entry))) {
 		ast_config_destroy(cur->cfg);
 		ast_free(cur);
 	}
 	AST_RWLIST_UNLOCK(&configs);
+
 	return res;
 }
 

Modified: team/murf/bug11210/include/asterisk/astobj2.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/include/asterisk/astobj2.h?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/include/asterisk/astobj2.h (original)
+++ team/murf/bug11210/include/asterisk/astobj2.h Mon Mar 17 13:07:20 2008
@@ -447,7 +447,7 @@
 /*! \brief
  * Lock an object.
  * 
- * \param a A pointer to the object we want lock.
+ * \param a A pointer to the object we want to lock.
  * \return 0 on success, other values on error.
  */
 int ao2_lock(void *a);
@@ -460,8 +460,15 @@
  */
 int ao2_unlock(void *a);
 
+/*! \brief
+ * Try locking-- (don't block if fail)
+ *
+ * \param a A pointer to the object we want to lock.
+ * \return 0 on success, other values on error.
+ */
+int ao2_trylock(void *a);
+
 /*! 
- *
  \page AstObj2_Containers AstObj2 Containers
 
 Containers are data structures meant to store several objects,

Modified: team/murf/bug11210/include/asterisk/audiohook.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/include/asterisk/audiohook.h?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/include/asterisk/audiohook.h (original)
+++ team/murf/bug11210/include/asterisk/audiohook.h Mon Mar 17 13:07:20 2008
@@ -57,6 +57,7 @@
 	AST_AUDIOHOOK_TRIGGER_READ = (1 << 0),  /*!< Audiohook wants to be triggered when reading audio in */
 	AST_AUDIOHOOK_TRIGGER_WRITE = (2 << 0), /*!< Audiohook wants to be triggered when writing audio out */
 	AST_AUDIOHOOK_WANTS_DTMF = (1 << 1),    /*!< Audiohook also wants to receive DTMF frames */
+	AST_AUDIOHOOK_TRIGGER_SYNC = (1 << 2),  /*!< Audiohook wants to be triggered when both sides have combined audio available */
 };
 
 struct ast_audiohook;
@@ -86,6 +87,8 @@
 	unsigned int flags;                                    /*!< Flags on the audiohook */
 	struct ast_slinfactory read_factory;                   /*!< Factory where frames read from the channel, or read from the whisper source will go through */
 	struct ast_slinfactory write_factory;                  /*!< Factory where frames written to the channel will go through */
+	struct timeval read_time;                              /*!< Last time read factory was fed */
+	struct timeval write_time;                             /*!< Last time write factory was fed */
 	int format;                                            /*!< Format translation path is setup as */
 	struct ast_trans_pvt *trans_pvt;                       /*!< Translation path for reading frames */
 	ast_audiohook_manipulate_callback manipulate_callback; /*!< Manipulation callback */

Modified: team/murf/bug11210/include/asterisk/pbx.h
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/include/asterisk/pbx.h?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/include/asterisk/pbx.h (original)
+++ team/murf/bug11210/include/asterisk/pbx.h Mon Mar 17 13:07:20 2008
@@ -758,6 +758,8 @@
 const char *ast_get_ignorepat_name(struct ast_ignorepat *ip);
 const char *ast_get_switch_name(struct ast_sw *sw);
 const char *ast_get_switch_data(struct ast_sw *sw);
+int ast_get_switch_eval(struct ast_sw *sw);
+	
 /*! @} */
 
 /*! @name Other Extension stuff */

Modified: team/murf/bug11210/main/astobj2.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/astobj2.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/main/astobj2.c (original)
+++ team/murf/bug11210/main/astobj2.c Mon Mar 17 13:07:20 2008
@@ -169,6 +169,22 @@
 #endif
 
 	return ast_mutex_unlock(&p->priv_data.lock);
+}
+
+int ao2_trylock(void *user_data)
+{
+	struct astobj2 *p = INTERNAL_OBJ(user_data);
+	int ret;
+	
+	if (p == NULL)
+		return -1;
+
+	ret =  ast_mutex_unlock(&p->priv_data.lock);
+#ifdef AO2_DEBUG
+	if (!ret)
+		ast_atomic_fetchadd_int(&ao2.total_locked, 1);
+#endif
+	return ret;
 }
 
 /*

Modified: team/murf/bug11210/main/audiohook.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/audiohook.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/main/audiohook.c (original)
+++ team/murf/bug11210/main/audiohook.c Mon Mar 17 13:07:20 2008
@@ -121,22 +121,21 @@
 int ast_audiohook_write_frame(struct ast_audiohook *audiohook, enum ast_audiohook_direction direction, struct ast_frame *frame)
 {
 	struct ast_slinfactory *factory = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_factory : &audiohook->write_factory);
+	struct timeval *time = (direction == AST_AUDIOHOOK_DIRECTION_READ ? &audiohook->read_time : &audiohook->write_time);
 
 	/* Write frame out to respective factory */
 	ast_slinfactory_feed(factory, frame);
 
+	/* Update last fed time for the above factory */
+	*time = ast_tvnow();
+
 	/* If we need to notify the respective handler of this audiohook, do so */
-	switch (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE)) {
-	case AST_AUDIOHOOK_TRIGGER_READ:
-		if (direction == AST_AUDIOHOOK_DIRECTION_READ)
-			ast_cond_signal(&audiohook->trigger);
-		break;
-	case AST_AUDIOHOOK_TRIGGER_WRITE:
-		if (direction == AST_AUDIOHOOK_DIRECTION_WRITE)
-			ast_cond_signal(&audiohook->trigger);
-		break;
-	default:
-		break;
+	if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_READ) && (direction == AST_AUDIOHOOK_DIRECTION_READ)) {
+		ast_cond_signal(&audiohook->trigger);
+	} else if ((ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_MODE) == AST_AUDIOHOOK_TRIGGER_WRITE) && (direction == AST_AUDIOHOOK_DIRECTION_WRITE)) {
+		ast_cond_signal(&audiohook->trigger);
+	} else if (ast_test_flag(audiohook, AST_AUDIOHOOK_TRIGGER_SYNC)) {
+		ast_cond_signal(&audiohook->trigger);
 	}
 
 	return 0;
@@ -172,7 +171,7 @@
 
 static struct ast_frame *audiohook_read_frame_both(struct ast_audiohook *audiohook, size_t samples)
 {
-	int i = 0;
+	int i = 0, usable_read, usable_write;
 	short buf1[samples], buf2[samples], *read_buf = NULL, *write_buf = NULL, *final_buf = NULL, *data1 = NULL, *data2 = NULL;
 	struct ast_frame frame = {
 		.frametype = AST_FRAME_VOICE,
@@ -182,8 +181,30 @@
 		.samples = samples,
 	};
 
+	/* Make sure both factories have the required samples */
+	usable_read = (ast_slinfactory_available(&audiohook->read_factory) >= samples ? 1 : 0);
+	usable_write = (ast_slinfactory_available(&audiohook->write_factory) >= samples ? 1 : 0);
+
+	if (!usable_read && !usable_write) {
+		/* If both factories are unusable bail out */
+		ast_debug(1, "Read factory %p and write factory %p both fail to provide %zd samples\n", &audiohook->read_factory, &audiohook->write_factory, samples);
+		return NULL;
+	}
+
+	/* If we want to provide only a read factory make sure we aren't waiting for other audio */
+	if (usable_read && !usable_write && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
+		ast_debug(1, "Write factory %p was pretty quick last time, waiting for them.\n", &audiohook->write_factory);
+		return NULL;
+	}
+
+	/* If we want to provide only a write factory make sure we aren't waiting for other audio */
+	if (usable_write && !usable_read && (ast_tvdiff_ms(ast_tvnow(), audiohook->write_time) < (samples/8)*2)) {
+		ast_debug(1, "Read factory %p was pretty quick last time, waiting for them.\n", &audiohook->read_factory);
+		return NULL;
+	}
+
 	/* Start with the read factory... if there are enough samples, read them in */
-	if (ast_slinfactory_available(&audiohook->read_factory) >= samples) {
+	if (usable_read && ast_slinfactory_available(&audiohook->read_factory) >= samples) {
 		if (ast_slinfactory_read(&audiohook->read_factory, buf1, samples)) {
 			read_buf = buf1;
 			/* Adjust read volume if need be */
@@ -202,7 +223,7 @@
 		ast_log(LOG_DEBUG, "Failed to get %d samples from read factory %p\n", (int)samples, &audiohook->read_factory);
 
 	/* Move on to the write factory... if there are enough samples, read them in */
-	if (ast_slinfactory_available(&audiohook->write_factory) >= samples) {
+	if (usable_write && ast_slinfactory_available(&audiohook->write_factory) >= samples) {
 		if (ast_slinfactory_read(&audiohook->write_factory, buf2, samples)) {
 			write_buf = buf2;
 			/* Adjust write volume if need be */

Modified: team/murf/bug11210/main/channel.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/channel.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/main/channel.c (original)
+++ team/murf/bug11210/main/channel.c Mon Mar 17 13:07:20 2008
@@ -1257,10 +1257,21 @@
 		AST_RWLIST_UNLOCK(&channels);
 		ast_log(LOG_ERROR, "Unable to find channel in list to free. Assuming it has already been done.\n");
 	}
-	/* Lock and unlock the channel just to be sure nobody
-	   has it locked still */
+	/* Lock and unlock the channel just to be sure nobody has it locked still
+	   due to a reference retrieved from the channel list. */
 	ast_channel_lock(chan);
 	ast_channel_unlock(chan);
+
+	/* Get rid of each of the data stores on the channel */
+	while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
+		/* Free the data store */
+		ast_channel_datastore_free(datastore);
+
+	/* Lock and unlock the channel just to be sure nobody has it locked still
+	   due to a reference that was stored in a datastore. (i.e. app_chanspy) */
+	ast_channel_lock(chan);
+	ast_channel_unlock(chan);
+
 	if (chan->tech_pvt) {
 		ast_log(LOG_WARNING, "Channel '%s' may not have been hung up properly\n", chan->name);
 		ast_free(chan->tech_pvt);
@@ -1287,7 +1298,6 @@
 	if (chan->pbx)
 		ast_log(LOG_WARNING, "PBX may not have been terminated properly on '%s'\n", chan->name);
 	free_cid(&chan->cid);
-	ast_mutex_destroy(&chan->lock_dont_use);
 	/* Close pipes if appropriate */
 	if ((fd = chan->alertpipe[0]) > -1)
 		close(fd);
@@ -1305,12 +1315,6 @@
 	while ((f = AST_LIST_REMOVE_HEAD(&chan->readq, frame_list)))
 		ast_frfree(f);
 	
-	/* Get rid of each of the data stores on the channel */
-	while ((datastore = AST_LIST_REMOVE_HEAD(&chan->datastores, entry)))
-		/* Free the data store */
-		ast_channel_datastore_free(datastore);
-	AST_LIST_HEAD_INIT_NOLOCK(&chan->datastores);
-
 	/* loop over the variables list, freeing all data and deleting list items */
 	/* no need to lock the list, as the channel is already locked */
 	
@@ -1321,6 +1325,8 @@
 
 	/* Destroy the jitterbuffer */
 	ast_jb_destroy(chan);
+	
+	ast_mutex_destroy(&chan->lock_dont_use);
 
 	ast_string_field_free_memory(chan);
 	ast_free(chan);

Modified: team/murf/bug11210/main/pbx.c
URL: http://svn.digium.com/view/asterisk/team/murf/bug11210/main/pbx.c?view=diff&rev=109173&r1=109172&r2=109173
==============================================================================
--- team/murf/bug11210/main/pbx.c (original)
+++ team/murf/bug11210/main/pbx.c Mon Mar 17 13:07:20 2008
@@ -5292,6 +5292,36 @@
 
 AST_LIST_HEAD(store_hints, store_hint);
 
+static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
+{
+	struct ast_include *i;
+	struct ast_ignorepat *ip;
+	struct ast_sw *sw;
+	
+	/* copy in the includes, switches, and ignorepats */
+	/* walk through includes */
+	for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
+		if (strcmp(ast_get_include_registrar(i), registrar) == 0)
+			continue; /* not mine */
+		ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
+	}
+	
+	/* walk through switches */
+	for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
+		if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
+			continue; /* not mine */
+		ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw));
+	}
+	
+	/* walk thru ignorepats ... */
+	for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
+		if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
+			continue; /* not mine */
+		ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
+	}
+}
+
+
 /* the purpose of this routine is to duplicate a context, with all its substructure,
    except for any extens that have a matching registrar */
 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
@@ -5329,6 +5359,9 @@
 				/* make sure the new context exists, so we have somewhere to stick this exten/prio */
 				if (!new) {
 					new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
+
+					/* copy in the includes, switches, and ignorepats */
+					context_merge_incls_swits_igps_other_registrars(new, context, registrar);
 				}
 				if (!new) {
 					ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
@@ -5357,6 +5390,9 @@
 		/* we could have given it the registrar of the other module who incremented the refcount,
 		   but that's not available, so we give it the registrar we know about */
 		new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
+		
+		/* copy in the includes, switches, and ignorepats */
+		context_merge_incls_swits_igps_other_registrars(new, context, registrar);
 	}
 }
 
@@ -7945,6 +7981,11 @@
 	return sw ? sw->data : NULL;
 }
 
+int ast_get_switch_eval(struct ast_sw *sw)
+{
+	return sw->eval;
+}
+
 const char *ast_get_switch_registrar(struct ast_sw *sw)
 {
 	return sw ? sw->registrar : NULL;




More information about the asterisk-commits mailing list