[Pkg-voip-commits] [asterisk] 01/11: backport dynamic DAHDI support.

tzafrir at debian.org tzafrir at debian.org
Mon Sep 30 19:35:02 UTC 2013


This is an automated email from the git hooks/post-receive script.

tzafrir pushed a commit to branch master
in repository asterisk.

commit 20c14f86d5d0f560369dcebb61055bcc62d062a4
Author: Tzafrir Cohen <tzafrir at debian.org>
Date:   Mon Sep 23 17:01:32 2013 +0300

    backport dynamic DAHDI support.
---
 debian/changelog                       |    2 +
 debian/patches/dahdi_create_channels   |  568 ++++++++++++++++++++++++++++++++
 debian/patches/dahdi_pri_event_removed |  160 +++++++++
 debian/patches/series                  |    5 +
 4 files changed, 735 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 9029940..5664991 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -26,6 +26,8 @@ asterisk (1:11.5.0~dfsg-1) UNRELEASED; urgency=low
       stupidity inflicted by pjproject.
     - get-orig-source: remove res/pjproject from the source tarball.
   * debian/rules: switch to dh.
+  * Patches dahdi_create_channels, dahdi_pri_event_removed: backport dynamic
+    DAHDI support.
 
   [ David Sarmiento ]
   * Re-enabled pjproject
diff --git a/debian/patches/dahdi_create_channels b/debian/patches/dahdi_create_channels
new file mode 100644
index 0000000..6209a09
--- /dev/null
+++ b/debian/patches/dahdi_create_channels
@@ -0,0 +1,568 @@
+From: Tzafrir Cohen <tzafrir.cohen at xorcom.com>
+Date: Thu, 8 Aug 2013 22:09:07 +0000
+Subject: [PATCH] chan_dahdi: create channels at run-time
+Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=396474
+
+This code adds chan_dahdi the command 'dahdi create channels <range>'
+(where <range> is a single <n>-<m> or 'new') and updates 'dahdi destroy
+channel' with a similar 'dahdi destroy channels'. It allows DAHDI
+channels and spans to be added after the initial channel load
+(without destroying all other channels as in 'dahdi restart').
+
+It also includes some fixes to the D-Channel / span destruction code
+(r394552).
+
+This change is intended to provide a hook for a script running from
+udev once a span has been assigned ("registered") / unassigned
+("unregistered") for its channels. The udev hook configures the span's
+channels with dahdi_cfg -S, and can then ask Asterisk to create ethe
+channels. See the scripts added to DAHDI-tools in 2.7.0.
+
+Review: https://reviewboard.asterisk.org/r/1598/
+
+A trivial backport from trunk / 12.
+
+---
+ channels/chan_dahdi.c |  322 +++++++++++++++++++++++++++++++++++++++----------
+ 1 file changed, 261 insertions(+), 61 deletions(-)
+
+diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
+index 8ce700c..b694ecf 100644
+--- a/channels/chan_dahdi.c
++++ b/channels/chan_dahdi.c
+@@ -461,6 +461,8 @@ static const char config[] = "chan_dahdi.conf";
+ static int num_cadence = 4;
+ static int user_has_defined_cadences = 0;
+ 
++static int has_pseudo;
++
+ static struct dahdi_ring_cadence cadences[NUM_CADENCE_MAX] = {
+ 	{ { 125, 125, 2000, 4000 } },			/*!< Quick chirp followed by normal ring */
+ 	{ { 250, 250, 500, 1000, 250, 250, 500, 4000 } }, /*!< British style ring */
+@@ -817,6 +819,18 @@ struct dahdi_chan_conf {
+ 	 * \note Set from the "smdiport" string read in from chan_dahdi.conf
+ 	 */
+ 	char smdi_port[SMDI_MAX_FILENAME_LEN];
++
++	/*!
++	 * \brief Don't create channels below this number
++	 * \note by default is 0 (no limit)
++	 */
++	int wanted_channels_start;
++
++	/*!
++	 * \brief Don't create channels above this number (infinity by default)
++	 * \note by default is 0 (special value that means "no limit").
++	 */
++	int wanted_channels_end;
+ };
+ 
+ /*! returns a new dahdi_chan_conf with default values (by-value) */
+@@ -2633,7 +2647,7 @@ static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
+ #endif	/* defined(HAVE_PRI) */
+ 
+ #if defined(HAVE_PRI)
+-static int pri_destroy_dchan(struct sig_pri_span *pri);
++static void pri_destroy_span(struct sig_pri_span *pri);
+ 
+ static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
+ {
+@@ -2663,7 +2677,7 @@ static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
+ 		pri_event_noalarm(pri, index, 0);
+ 		break;
+ 	case DAHDI_EVENT_REMOVED:
+-		pri_destroy_dchan(pri);
++		pri_destroy_span(pri);
+ 		break;
+ 	default:
+ 		break;
+@@ -10736,29 +10750,121 @@ static int mwi_send_process_event(struct dahdi_pvt * pvt, int event)
+ 	return handled;
+ }
+ 
+-/* destroy a DAHDI channel, identified by its number */
+-static int dahdi_destroy_channel_bynum(int channel)
++/* destroy a range DAHDI channels, identified by their number */
++static void dahdi_destroy_channel_range(int start, int end)
+ {
+ 	struct dahdi_pvt *cur;
++	struct dahdi_pvt *next;
++	int destroyed_first = 0;
++	int destroyed_last = 0;
+ 
+ 	ast_mutex_lock(&iflock);
+-	for (cur = iflist; cur; cur = cur->next) {
+-		if (cur->channel == channel) {
++	ast_debug(1, "range: %d-%d\n", start, end);
++	for (cur = iflist; cur; cur = next) {
++		next = cur->next;
++		if (cur->channel >= start && cur->channel <= end) {
+ 			int x = DAHDI_FLASH;
+ 
++			if (cur->channel > destroyed_last) {
++				destroyed_last = cur->channel;
++			}
++			if (destroyed_first < 1 || cur->channel < destroyed_first) {
++				destroyed_first = cur->channel;
++			}
++			ast_debug(3, "Destroying %d\n", cur->channel);
+ 			/* important to create an event for dahdi_wait_event to register so that all analog_ss_threads terminate */
+ 			ioctl(cur->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
+ 
+ 			destroy_channel(cur, 1);
+-			ast_mutex_unlock(&iflock);
+ 			ast_module_unref(ast_module_info->self);
+-			return RESULT_SUCCESS;
+ 		}
+ 	}
+ 	ast_mutex_unlock(&iflock);
+-	return RESULT_FAILURE;
++	if (destroyed_first > start || destroyed_last < end) {
++		ast_debug(1, "Asked to destroy %d-%d, destroyed %d-%d,\n",
++			start, end, destroyed_first, destroyed_last);
++	}
++}
++
++static int setup_dahdi(int reload);
++static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, struct dahdi_chan_conf *base_conf, struct dahdi_chan_conf *conf);
++
++/*!
++ * \internal
++ * \brief create a range of new DAHDI channels
++ *
++ * \param start first channel in the range
++ * \param end last channel in the range
++ *
++ * \retval RESULT_SUCCESS on success.
++ * \retval RESULT_FAILURE on error.
++ */
++static int dahdi_create_channel_range(int start, int end)
++{
++	struct dahdi_pvt *cur;
++	struct dahdi_chan_conf default_conf = dahdi_chan_conf_default();
++	struct dahdi_chan_conf base_conf = dahdi_chan_conf_default();
++	struct dahdi_chan_conf conf = dahdi_chan_conf_default();
++	int i, x;
++	int ret = RESULT_FAILURE; /* be pessimistic */
++
++	ast_debug(1, "channel range caps: %d - %d\n", start, end);
++	ast_mutex_lock(&iflock);
++	for (cur = iflist; cur; cur = cur->next) {
++		if (cur->channel >= start && cur->channel <= end) {
++			ast_log(LOG_ERROR,
++				"channel range %d-%d is occupied\n",
++				start, end);
++			goto out;
++		}
++	}
++	for (x = 0; x < NUM_SPANS; x++) {
++#ifdef HAVE_PRI
++		struct dahdi_pri *pri = pris + x;
++
++		if (!pris[x].pri.pvts[0]) {
++			break;
++		}
++		for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
++			int channo = pri->dchannels[i];
++
++			if (!channo) {
++				break;
++			}
++			if (!pri->pri.fds[i]) {
++				break;
++			}
++			if (channo >= start && channo <= end) {
++				ast_log(LOG_ERROR,
++						"channel range %d-%d is occupied by span %d\n",
++						start, end, x + 1);
++				goto out;
++			}
++		}
++#endif
++	}
++	if (!default_conf.chan.cc_params || !base_conf.chan.cc_params ||
++		!conf.chan.cc_params) {
++		goto out;
++	}
++	default_conf.wanted_channels_start = start;
++	base_conf.wanted_channels_start = start;
++	conf.wanted_channels_start = start;
++	default_conf.wanted_channels_end = end;
++	base_conf.wanted_channels_end = end;
++	conf.wanted_channels_end = end;
++	if (setup_dahdi_int(0, &default_conf, &base_conf, &conf) == 0) {
++		ret = RESULT_SUCCESS;
++	}
++out:
++	ast_cc_config_params_destroy(default_conf.chan.cc_params);
++	ast_cc_config_params_destroy(base_conf.chan.cc_params);
++	ast_cc_config_params_destroy(conf.chan.cc_params);
++	ast_mutex_unlock(&iflock);
++	return ret;
+ }
+ 
++
+ static struct dahdi_pvt *handle_init_event(struct dahdi_pvt *i, int event)
+ {
+ 	int res;
+@@ -11124,11 +11230,7 @@ static void *do_monitor(void *data)
+ 		doomed = NULL;
+ 		for (i = iflist;; i = i->next) {
+ 			if (doomed) {
+-				int res;
+-				res = dahdi_destroy_channel_bynum(doomed->channel);
+-				if (res != RESULT_SUCCESS) {
+-					ast_log(LOG_WARNING, "Couldn't find channel to destroy, hopefully another destroy operation just happened.\n");
+-				}
++				dahdi_destroy_channel_range(doomed->channel, doomed->channel);
+ 				doomed = NULL;
+ 			}
+ 			if (!i) {
+@@ -13574,10 +13676,21 @@ static int prepare_pri(struct dahdi_pri *pri)
+ 	for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
+ 		if (!pri->dchannels[i])
+ 			break;
++		if (pri->pri.fds[i] >= 0) {
++			/* A partial range addition. Not a complete setup. */
++			break;
++		}
+ 		pri->pri.fds[i] = open("/dev/dahdi/channel", O_RDWR);
++		if ((pri->pri.fds[i] < 0)) {
++			ast_log(LOG_ERROR, "Unable to open D-channel (fd=%d) (%s)\n",
++				pri->pri.fds[i], strerror(errno));
++			return -1;
++		}
+ 		x = pri->dchannels[i];
+-		if ((pri->pri.fds[i] < 0) || (ioctl(pri->pri.fds[i],DAHDI_SPECIFY,&x) == -1)) {
+-			ast_log(LOG_ERROR, "Unable to open D-channel %d (%s)\n", x, strerror(errno));
++		res = ioctl(pri->pri.fds[i], DAHDI_SPECIFY, &x);
++		if (res) {
++			dahdi_close_pri_fd(pri, i);
++			ast_log(LOG_ERROR, "Unable to SPECIFY channel %d (%s)\n", x, strerror(errno));
+ 			return -1;
+ 		}
+ 		memset(&p, 0, sizeof(p));
+@@ -13978,22 +14091,44 @@ static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_
+  *
+  * \param pri the pri span
+  *
+- * \return TRUE if the span was valid and we attempted destroying.
+- *
+  * Shuts down a span and destroys its D-Channel. Further destruction
+  * of the B-channels using dahdi_destroy_channel() would probably be required
+  * for the B-Channels.
+  */
+-static int pri_destroy_dchan(struct sig_pri_span *pri)
++static void pri_destroy_span(struct sig_pri_span *pri)
+ {
+ 	int i;
++	int res;
++	int cancel_code;
+ 	struct dahdi_pri* dahdi_pri;
++	pthread_t master = pri->master;
+ 
+-	if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
+-		return 0;
++	if (!master || (master == AST_PTHREADT_NULL)) {
++		return;
++	}
++	ast_debug(2, "About to destroy DAHDI channels of span %d.\n", pri->span);
++	for (i = 0; i < pri->numchans; i++) {
++		int channel;
++		struct sig_pri_chan *pvt = pri->pvts[i];
++
++		if (!pvt) {
++			continue;
++		}
++		channel = pvt->channel;
++		ast_debug(2, "About to destroy B-channel %d.\n", channel);
++		dahdi_destroy_channel_range(channel, channel);
+ 	}
+-	pthread_cancel(pri->master);
+-	pthread_join(pri->master, NULL);
++
++	cancel_code = pthread_cancel(master);
++	ast_debug(4,
++		"Waiting to join thread of span %d "
++		"with pid=%p cancel_code=%d\n",
++		pri->span, (void *)master, cancel_code);
++	res = pthread_join(master, NULL);
++	if (res != 0) {
++		ast_log(LOG_NOTICE, "pthread_join failed: %d\n", res);
++	}
++	pri->master = AST_PTHREADT_NULL;
+ 
+ 	/* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
+ 	dahdi_pri = container_of(pri, struct dahdi_pri, pri);
+@@ -14001,17 +14136,16 @@ static int pri_destroy_dchan(struct sig_pri_span *pri)
+ 		ast_debug(4, "closing pri_fd %d\n", i);
+ 		dahdi_close_pri_fd(dahdi_pri, i);
+ 	}
+-	pri->pri = NULL;
++	sig_pri_init_pri(pri);
+ 	ast_debug(1, "PRI span %d destroyed\n", pri->span);
+-	return 1;
+ }
+ 
+ static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
+ 		struct ast_cli_args *a)
+ {
+ 	int span;
+-	int i;
+ 	int res;
++	struct sig_pri_span *pri;
+ 
+ 	switch (cmd) {
+ 	case CLI_INIT:
+@@ -14035,25 +14169,13 @@ static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
+ 			a->argv[3], 1, NUM_SPANS);
+ 		return CLI_SUCCESS;
+ 	}
+-	if (!pris[span - 1].pri.pri) {
++	pri = &pris[span - 1].pri;
++	if (!pri->pri) {
+ 		ast_cli(a->fd, "No PRI running on span %d\n", span);
+ 		return CLI_SUCCESS;
+ 	}
+ 
+-	for (i = 0; i < pris[span - 1].pri.numchans; i++) {
+-		int channel;
+-		struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
+-
+-		if (!pvt) {
+-			continue;
+-		}
+-		channel = pvt->channel;
+-		ast_debug(2, "About to destroy B-channel %d.\n", channel);
+-		dahdi_destroy_channel_bynum(channel);
+-	}
+-	ast_debug(2, "About to destroy D-channel of span %d.\n", span);
+-	pri_destroy_dchan(&pris[span - 1].pri);
+-
++	pri_destroy_span(pri);
+ 	return CLI_SUCCESS;
+ }
+ 
+@@ -14505,26 +14627,97 @@ static struct ast_cli_entry dahdi_mfcr2_cli[] = {
+ 
+ #endif /* HAVE_OPENR2 */
+ 
+-static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++static char *dahdi_destroy_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+-	int channel;
+-	int ret;
++	int start;
++	int end;
+ 	switch (cmd) {
+ 	case CLI_INIT:
+-		e->command = "dahdi destroy channel";
++		e->command = "dahdi destroy channels";
+ 		e->usage =
+-			"Usage: dahdi destroy channel <chan num>\n"
++			"Usage: dahdi destroy channels <from_channel> [<to_channel>]\n"
+ 			"	DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.  Immediately removes a given channel, whether it is in use or not\n";
+ 		return NULL;
+ 	case CLI_GENERATE:
+ 		return NULL;
+ 	}
+-	if (a->argc != 4)
++	if ((a->argc < 4) || a->argc > 5) {
+ 		return CLI_SHOWUSAGE;
++	}
++	start = atoi(a->argv[3]);
++	if (start < 1) {
++		ast_cli(a->fd, "Invalid starting channel number %s.\n",
++				a->argv[4]);
++		return CLI_FAILURE;
++	}
++	if (a->argc == 5) {
++		end = atoi(a->argv[4]);
++		if (end < 1) {
++			ast_cli(a->fd, "Invalid ending channel number %s.\n",
++					a->argv[4]);
++			return CLI_FAILURE;
++		}
++	} else {
++		end = start;
++	}
+ 
+-	channel = atoi(a->argv[3]);
+-	ret = dahdi_destroy_channel_bynum(channel);
+-	return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
++	if (end < start) {
++		ast_cli(a->fd,
++			"range end (%d) is smaller than range start (%d)\n",
++			end, start);
++		return CLI_FAILURE;
++	}
++	dahdi_destroy_channel_range(start, end);
++	return CLI_SUCCESS;
++}
++
++static char *dahdi_create_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
++{
++	int start;
++	int end;
++	int ret;
++
++	switch (cmd) {
++	case CLI_INIT:
++		e->command = "dahdi create channels";
++		e->usage = "Usage: dahdi create channels <from> [<to>] - a range of channels\n"
++			   "       dahdi create channels new           - add channels not yet created\n"
++			   "For ISDN  and SS7 the range should include complete spans.\n";
++		return NULL;
++	case CLI_GENERATE:
++		return NULL;
++	}
++	if ((a->argc < 4) || a->argc > 5) {
++		return CLI_SHOWUSAGE;
++	}
++	if (a->argc == 4 && !strcmp(a->argv[3], "new")) {
++		ret = dahdi_create_channel_range(0, 0);
++		return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
++	}
++	start = atoi(a->argv[3]);
++	if (start <= 0) {
++		ast_cli(a->fd, "Invalid starting channel number '%s'.\n",
++				a->argv[3]);
++		return CLI_FAILURE;
++	}
++	if (a->argc == 5) {
++		end = atoi(a->argv[4]);
++		if (end <= 0) {
++			ast_cli(a->fd, "Invalid ending channel number '%s'.\n",
++					a->argv[4]);
++			return CLI_FAILURE;
++		}
++	} else {
++		end = start;
++	}
++	if (end < start) {
++		ast_cli(a->fd,
++			"range end (%d) is smaller than range start (%d)\n",
++			end, start);
++		return CLI_FAILURE;
++	}
++	ret = dahdi_create_channel_range(start, end);
++	return (RESULT_SUCCESS == ret) ? CLI_SUCCESS : CLI_FAILURE;
+ }
+ 
+ static void dahdi_softhangup_all(void)
+@@ -14555,7 +14748,6 @@ retry:
+ 	ast_mutex_unlock(&iflock);
+ }
+ 
+-static int setup_dahdi(int reload);
+ static int dahdi_restart(void)
+ {
+ #if defined(HAVE_PRI) || defined(HAVE_SS7)
+@@ -15332,7 +15524,8 @@ static struct ast_cli_entry dahdi_cli[] = {
+ 	AST_CLI_DEFINE(handle_dahdi_show_cadences, "List cadences"),
+ 	AST_CLI_DEFINE(dahdi_show_channels, "Show active DAHDI channels"),
+ 	AST_CLI_DEFINE(dahdi_show_channel, "Show information on a channel"),
+-	AST_CLI_DEFINE(dahdi_destroy_channel, "Destroy a channel"),
++	AST_CLI_DEFINE(dahdi_destroy_channels, "Destroy channels"),
++	AST_CLI_DEFINE(dahdi_create_channels, "Create channels"),
+ 	AST_CLI_DEFINE(dahdi_restart_cmd, "Fully restart DAHDI channels"),
+ 	AST_CLI_DEFINE(dahdi_show_status, "Show all DAHDI cards status"),
+ 	AST_CLI_DEFINE(dahdi_show_version, "Show the DAHDI version in use"),
+@@ -16359,7 +16552,7 @@ static char *parse_spanchan(char *chanstr, char **subdir)
+ 	return p;
+ }
+ 
+-static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno, int *found_pseudo)
++static int build_channels(struct dahdi_chan_conf *conf, const char *value, int reload, int lineno)
+ {
+ 	char *c, *chan;
+ 	char *subdir;
+@@ -16382,8 +16575,6 @@ static int build_channels(struct dahdi_chan_conf *conf, const char *value, int r
+ 			finish = start;
+ 		} else if (!strcasecmp(chan, "pseudo")) {
+ 			finish = start = CHAN_PSEUDO;
+-			if (found_pseudo)
+-				*found_pseudo = 1;
+ 		} else {
+ 			ast_log(LOG_ERROR, "Syntax error parsing '%s' at '%s'\n", value, chan);
+ 			return -1;
+@@ -16413,6 +16604,12 @@ static int build_channels(struct dahdi_chan_conf *conf, const char *value, int r
+ 					}
+ 				}
+ 			}
++			if (conf->wanted_channels_start &&
++				(real_channel < conf->wanted_channels_start ||
++				 real_channel > conf->wanted_channels_end)
++			   ) {
++				continue;
++			}
+ 			tmp = mkintf(real_channel, conf, reload);
+ 
+ 			if (tmp) {
+@@ -16422,6 +16619,9 @@ static int build_channels(struct dahdi_chan_conf *conf, const char *value, int r
+ 						(reload == 1) ? "reconfigure" : "register", value);
+ 				return -1;
+ 			}
++			if (real_channel == CHAN_PSEUDO) {
++				has_pseudo = 1;
++			}
+ 		}
+ 	}
+ 
+@@ -16608,7 +16808,6 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
+ {
+ 	struct dahdi_pvt *tmp;
+ 	int y;
+-	int found_pseudo = 0;
+ 	struct ast_variable *dahdichan = NULL;
+ 
+ 	for (; v; v = v->next) {
+@@ -16621,7 +16820,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
+ 				ast_log(LOG_WARNING, "Channel '%s' ignored.\n", v->value);
+ 				continue;
+ 			}
+-			if (build_channels(confp, v->value, reload, v->lineno, &found_pseudo)) {
++			if (build_channels(confp, v->value, reload, v->lineno)) {
+ 				if (confp->ignore_failed_channels) {
+ 					ast_log(LOG_WARNING, "Channel '%s' failure ignored: ignore_failed_channels.\n", v->value);
+ 					continue;
+@@ -17754,8 +17953,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
+ 
+ 	if (dahdichan) {
+ 		/* Process the deferred dahdichan value. */
+-		if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno,
+-			&found_pseudo)) {
++		if (build_channels(confp, dahdichan->value, reload, dahdichan->lineno)) {
+ 			if (confp->ignore_failed_channels) {
+ 				ast_log(LOG_WARNING,
+ 					"Dahdichan '%s' failure ignored: ignore_failed_channels.\n",
+@@ -17778,7 +17976,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
+ 
+ 	/*< \todo why check for the pseudo in the per-channel section.
+ 	 * Any actual use for manual setup of the pseudo channel? */
+-	if (!found_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
++	if (!has_pseudo && reload != 1 && !(options & PROC_DAHDI_OPT_NOCHAN)) {
+ 		/* use the default configuration for a channel, so
+ 		   that any settings from real configured channels
+ 		   don't "leak" into the pseudo channel config
+@@ -17792,6 +17990,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
+ 		}
+ 		if (tmp) {
+ 			ast_verb(3, "Automatically generated pseudo channel\n");
++			has_pseudo = 1;
+ 		} else {
+ 			ast_log(LOG_WARNING, "Unable to register pseudo channel!\n");
+ 		}
+@@ -18071,7 +18270,8 @@ static int setup_dahdi_int(int reload, struct dahdi_chan_conf *default_conf, str
+ 	if (reload != 1) {
+ 		int x;
+ 		for (x = 0; x < NUM_SPANS; x++) {
+-			if (pris[x].pri.pvts[0]) {
++			if (pris[x].pri.pvts[0] &&
++					pris[x].pri.master == AST_PTHREADT_NULL) {
+ 				prepare_pri(pris + x);
+ 				if (sig_pri_start_pri(&pris[x].pri)) {
+ 					ast_log(LOG_ERROR, "Unable to start D-channel on span %d\n", x + 1);
+-- 
+1.7.10.4
+
diff --git a/debian/patches/dahdi_pri_event_removed b/debian/patches/dahdi_pri_event_removed
new file mode 100644
index 0000000..4b0b2b1
--- /dev/null
+++ b/debian/patches/dahdi_pri_event_removed
@@ -0,0 +1,160 @@
+From: Tzafrir Cohen <tzafrir.cohen at xorcom.com>
+Date: Wed, 17 Jul 2013 16:56:14 +0000
+Subject: handle DAHDI_EVENT_REMOVED on a pri D-Channel
+Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=394552
+
+When a DAHDI device is removed at run-time it sends the event
+DAHDI_EVENT_REMOVED on each channel. This is intended to signal the
+userspace program to close the respective file handle, as the driver of
+the device will need all of them closed to properly clean-up.
+
+This event has long since been handled in chan_dahdi (chan_zap at the
+time). However the event that is sent on a D-Channel of a "PRI" (ISDN)
+span simply gets ignored.
+
+This commit adds handling for closing the file descriptor (and shutting
+down the span, while we're at it).
+
+It also adds a CLI command 'pri destroy span <N>' to destroy the span
+and its DAHDI channels.
+
+Review: https://reviewboard.asterisk.org/r/726/
+
+Trivial backport from trunk / 12.
+
+---
+ channels/chan_dahdi.c |   97 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 97 insertions(+)
+
+diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
+index 28fd65f..8f38893 100644
+--- a/channels/chan_dahdi.c
++++ b/channels/chan_dahdi.c
+@@ -3371,6 +3371,8 @@ static int sig_pri_tone_to_dahditone(enum sig_pri_tone tone)
+ #endif	/* defined(HAVE_PRI) */
+ 
+ #if defined(HAVE_PRI)
++static int pri_destroy_dchan(struct sig_pri_span *pri);
++
+ static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
+ {
+ 	int x;
+@@ -3398,6 +3400,9 @@ static void my_handle_dchan_exception(struct sig_pri_span *pri, int index)
+ 	case DAHDI_EVENT_NOALARM:
+ 		pri_event_noalarm(pri, index, 0);
+ 		break;
++	case DAHDI_EVENT_REMOVED:
++		pri_destroy_dchan(pri);
++		break;
+ 	default:
+ 		break;
+ 	}
+@@ -15059,6 +15064,97 @@ static char *handle_pri_show_spans(struct ast_cli_entry *e, int cmd, struct ast_
+ #endif	/* defined(HAVE_PRI) */
+ 
+ #if defined(HAVE_PRI)
++#define container_of(ptr, type, member) \
++	((type *)((char *)(ptr) - offsetof(type, member)))
++/*!
++ * \internal
++ * \brief Destroy a D-Channel of a PRI span
++ * \since 12
++ *
++ * \param pri the pri span
++ *
++ * \return TRUE if the span was valid and we attempted destroying.
++ *
++ * Shuts down a span and destroys its D-Channel. Further destruction
++ * of the B-channels using dahdi_destroy_channel() would probably be required
++ * for the B-Channels.
++ */
++static int pri_destroy_dchan(struct sig_pri_span *pri)
++{
++	int i;
++	struct dahdi_pri* dahdi_pri;
++
++	if (!pri->master || (pri->master == AST_PTHREADT_NULL)) {
++		return 0;
++	}
++	pthread_cancel(pri->master);
++	pthread_join(pri->master, NULL);
++
++	/* The 'struct dahdi_pri' that contains our 'struct sig_pri_span' */
++	dahdi_pri = container_of(pri, struct dahdi_pri, pri);
++	for (i = 0; i < SIG_PRI_NUM_DCHANS; i++) {
++		ast_debug(4, "closing pri_fd %d\n", i);
++		dahdi_close_pri_fd(dahdi_pri, i);
++	}
++	pri->pri = NULL;
++	ast_debug(1, "PRI span %d destroyed\n", pri->span);
++	return 1;
++}
++
++static char *handle_pri_destroy_span(struct ast_cli_entry *e, int cmd,
++		struct ast_cli_args *a)
++{
++	int span;
++	int i;
++	int res;
++
++	switch (cmd) {
++	case CLI_INIT:
++		e->command = "pri destroy span";
++		e->usage =
++			"Usage: pri destroy span <span>\n"
++			"       Destorys D-channel of span and its B-channels.\n"
++			"	DON'T USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING.\n";
++		return NULL;
++	case CLI_GENERATE:
++		return complete_span_4(a->line, a->word, a->pos, a->n);
++	}
++
++	if (a->argc < 4) {
++		return CLI_SHOWUSAGE;
++	}
++	res = sscanf(a->argv[3], "%30d", &span);
++	if ((res != 1) || span < 1 || span > NUM_SPANS) {
++		ast_cli(a->fd,
++			"Invalid span '%s'.  Should be a number from %d to %d\n",
++			a->argv[3], 1, NUM_SPANS);
++		return CLI_SUCCESS;
++	}
++	if (!pris[span - 1].pri.pri) {
++		ast_cli(a->fd, "No PRI running on span %d\n", span);
++		return CLI_SUCCESS;
++	}
++
++	for (i = 0; i < pris[span - 1].pri.numchans; i++) {
++		int channel;
++		struct sig_pri_chan *pvt = pris[span - 1].pri.pvts[i];
++
++		if (!pvt) {
++			continue;
++		}
++		channel = pvt->channel;
++		ast_debug(2, "About to destroy B-channel %d.\n", channel);
++		dahdi_destroy_channel_bynum(channel);
++	}
++	ast_debug(2, "About to destroy D-channel of span %d.\n", span);
++	pri_destroy_dchan(&pris[span - 1].pri);
++
++	return CLI_SUCCESS;
++}
++
++#endif	/* defined(HAVE_PRI) */
++
++#if defined(HAVE_PRI)
+ static char *handle_pri_show_span(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+ {
+ 	int span;
+@@ -15164,6 +15260,7 @@ static struct ast_cli_entry dahdi_pri_cli[] = {
+ 	AST_CLI_DEFINE(handle_pri_show_channels, "Displays PRI channel information"),
+ 	AST_CLI_DEFINE(handle_pri_show_spans, "Displays PRI span information"),
+ 	AST_CLI_DEFINE(handle_pri_show_span, "Displays PRI span information"),
++	AST_CLI_DEFINE(handle_pri_destroy_span, "Destroy a PRI span"),
+ 	AST_CLI_DEFINE(handle_pri_show_debug, "Displays current PRI debug settings"),
+ 	AST_CLI_DEFINE(handle_pri_set_debug_file, "Sends PRI debug output to the specified file"),
+ 	AST_CLI_DEFINE(handle_pri_version, "Displays libpri version"),
+-- 
+1.7.10.4
+
diff --git a/debian/patches/series b/debian/patches/series
index 545f0ab..bada686 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -23,3 +23,8 @@ ilbc_disable
 astdatadir
 bzero
 pjproject
+
+# Backport of dynamic generation of DAHDI channels:
+dahdi_pri_event_removed
+dahdi_create_channels
+

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-voip/asterisk.git



More information about the Pkg-voip-commits mailing list