summaryrefslogtreecommitdiff
path: root/channels
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2013-07-17 16:56:14 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2013-07-17 16:56:14 +0000
commitb10bb8fa7b5ff80b539f9a80fb7ba429427334b6 (patch)
treef4c7e08f19034ab42c59296b816709d6a145938a /channels
parent19d8f8c8e4be5c14427e60771202f7bb61b4b91e (diff)
handle DAHDI_EVENT_REMOVED on a pri D-Channel
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/ git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394552 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 28fd65f4d..8f3889358 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"),