[svn-commits] dhubbard: branch group/issue3450 r138772 - in /team/group/issue3450: ./ apps/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Mon Aug 18 18:23:24 CDT 2008


Author: dhubbard
Date: Mon Aug 18 18:23:24 2008
New Revision: 138772

URL: http://svn.digium.com/view/asterisk?view=rev&rev=138772
Log:
Merged revisions 138310-138311,138361,138409,138412,138442,138473,138476,138479,138482,138517-138518,138570,138631,138687,138694,138738 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/trunk

................
r138310 | jpeeler | 2008-08-15 18:42:28 -0500 (Fri, 15 Aug 2008) | 8 lines

Blocked revisions 138309 via svnmerge

........
r138309 | jpeeler | 2008-08-15 18:41:54 -0500 (Fri, 15 Aug 2008) | 1 line

add forgotten locks around ss_thread_count in ss_thread for dahdi restart
........

................
r138311 | jpeeler | 2008-08-15 18:46:09 -0500 (Fri, 15 Aug 2008) | 20 lines

Merged revisions 138119,138151,138238 via svnmerge from 
https://origsvn.digium.com/svn/asterisk/branches/1.4

........
r138119 | jpeeler | 2008-08-15 14:21:51 -0500 (Fri, 15 Aug 2008) | 4 lines

Fixes the dahdi restart functionality. Dahdi restart allows one to restart all DAHDI channels, even if they are currently in use. This is different from unloading and then loading the module since unloading requires the use count to be zero. Reloading the module is different in that the signalling is not changed from what it was originally configured. Also, this fixes not closing all the file descriptors for D-channels upon module unload (which would prevent loading the module afterwards).

(closes issue #11017)

........
r138151 | jpeeler | 2008-08-15 14:41:29 -0500 (Fri, 15 Aug 2008) | 1 line

declared static mutexes using AST_MUTEX_DEFINE_STATIC macro
........
r138238 | jpeeler | 2008-08-15 16:28:26 -0500 (Fri, 15 Aug 2008) | 1 line

initialize condition variable ss_thread_complete using ast_cond_init
........

................
r138361 | jpeeler | 2008-08-15 20:13:26 -0500 (Fri, 15 Aug 2008) | 9 lines

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

........
r138360 | jpeeler | 2008-08-15 20:12:18 -0500 (Fri, 15 Aug 2008) | 1 line

fixes use count to properly decrement if an active dahdi channel is destroyed allowing module to be unloaded
........

................
r138409 | tilghman | 2008-08-16 07:52:06 -0500 (Sat, 16 Aug 2008) | 3 lines

Also make sure hinting won't crash on reload.
(Closes issue #13312)

................
r138412 | tilghman | 2008-08-16 08:07:08 -0500 (Sat, 16 Aug 2008) | 2 lines

Fix compilation warnings (found with dev-mode)

................
r138442 | seanbright | 2008-08-16 11:40:43 -0500 (Sat, 16 Aug 2008) | 4 lines

Since it's introduction in revision 3497, cdr_tds has *never* read
the port configuration option from cdr_tds.conf.  So go ahead and
remove it from the sample config.

................
r138473 | seanbright | 2008-08-17 08:31:54 -0500 (Sun, 17 Aug 2008) | 7 lines

Fix the output of the JitterBufStats manager event.

(closes issue #13324)
Reported by: srt
Patches:
      13324_missing_nl_in_jitterbufstats_event_2.diff uploaded by srt (license 378)

................
r138476 | seanbright | 2008-08-17 08:40:36 -0500 (Sun, 17 Aug 2008) | 7 lines

Add missing colons to RTCPReceived and RTCPSent manager events.

(closes issue #13319)
Reported by: srt
Patches:
      13319_rtcp_manager_event_headers.diff uploaded by srt (license 378)

................
r138479 | seanbright | 2008-08-17 08:51:08 -0500 (Sun, 17 Aug 2008) | 7 lines

Add Uniqueid header to ParkedCall manager event.

(closes issue #13323)
Reported by: srt
Patches:
      13323_unique_id_for_parkedcalls_event.diff uploaded by srt (license 378)

................
r138482 | seanbright | 2008-08-17 09:12:11 -0500 (Sun, 17 Aug 2008) | 6 lines

Move Uniqueid to the end of the event for those that rely on the position
of the name/value pairs, pointed out by snuffy-home on #asterisk-commits.

For those of you who rely on the position of name/value pairs in manager
events... stop... that is why associative arrays were invented.

................
r138517 | jpeeler | 2008-08-17 21:06:54 -0500 (Sun, 17 Aug 2008) | 8 lines

Blocked revisions 138516 via svnmerge

........
r138516 | jpeeler | 2008-08-17 21:05:29 -0500 (Sun, 17 Aug 2008) | 1 line

fix compilation warnings
........

................
r138518 | jpeeler | 2008-08-17 21:13:04 -0500 (Sun, 17 Aug 2008) | 1 line

add missing define for SS7 in dahdi_restart
................
r138570 | seanbright | 2008-08-18 06:58:49 -0500 (Mon, 18 Aug 2008) | 8 lines

Blocked revisions 138569 via svnmerge

........
r138569 | seanbright | 2008-08-18 07:57:24 -0400 (Mon, 18 Aug 2008) | 1 line

You know what's awesome?  Code that compiles... ;)
........

................
r138631 | qwell | 2008-08-18 10:54:07 -0500 (Mon, 18 Aug 2008) | 1 line

Remove option that isn't valid here.
................
r138687 | mmichelson | 2008-08-18 15:04:10 -0500 (Mon, 18 Aug 2008) | 18 lines

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

........
r138685 | mmichelson | 2008-08-18 15:01:14 -0500 (Mon, 18 Aug 2008) | 10 lines

Change the inequalities used in app_queue with regards
to timeouts from being strict to non-strict for more
accuracy.

(closes issue #13239)
Reported by: atis
Patches:
      app_queue_timeouts_v2.patch uploaded by atis (license 242)


........

................
r138694 | mmichelson | 2008-08-18 15:23:11 -0500 (Mon, 18 Aug 2008) | 10 lines

Change the queue timeout priority logic into less ugly
and confusing code pieces. Clarify the logic within
queues.conf.sample.

(closes issue #12690)
Reported by: atis
Patches:
      queue_timeoutpriority.patch uploaded by atis (license 242)


................
r138738 | rmudgett | 2008-08-18 16:07:28 -0500 (Mon, 18 Aug 2008) | 30 lines

channels/chan_misdn.c
*  Made bearer2str() use allowed_bearers_array[]
*  Made use the causes.h defines instead of hardcoded numbers.
*  Made use Asterisk presentation indicator values if either of the
mISDN presentation or screen options are negative.
*  Updated the misdn_set_opt application option descriptions.
*  Renamed the awkward Caller ID presentation misdn_set_opt
application option value not_screened to restricted.
Deprecated the not_screened option value.

channels/misdn/isdn_lib.c
*  Made use the causes.h defines instead of hardcoded numbers.
*  Fixed some spelling errors and typos.
*  Added all defined facility code strings to fac2str().

channels/misdn/isdn_lib.h
*  Added doxygen comments to struct misdn_bchannel.

channels/misdn/isdn_lib_intern.h
*  Added doxygen comments to struct misdn_stack.

channels/misdn_config.c
configs/misdn.conf.sample
*  Updated the mISDN presentation and screen parameter descriptions.

doc/tex/misdn.tex
*  Updated the misdn_set_opt application option descriptions.
*  Fixed some spelling errors and typos.


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

Modified:
    team/group/issue3450/   (props changed)
    team/group/issue3450/Makefile
    team/group/issue3450/apps/app_queue.c
    team/group/issue3450/channels/chan_dahdi.c
    team/group/issue3450/channels/chan_iax2.c
    team/group/issue3450/channels/chan_misdn.c
    team/group/issue3450/channels/misdn/isdn_lib.c
    team/group/issue3450/channels/misdn/isdn_lib.h
    team/group/issue3450/channels/misdn/isdn_lib_intern.h
    team/group/issue3450/channels/misdn_config.c
    team/group/issue3450/configs/cdr_tds.conf.sample
    team/group/issue3450/configs/misdn.conf.sample
    team/group/issue3450/configs/queues.conf.sample
    team/group/issue3450/doc/tex/misdn.tex
    team/group/issue3450/main/features.c
    team/group/issue3450/main/pbx.c
    team/group/issue3450/main/rtp.c

Propchange: team/group/issue3450/
------------------------------------------------------------------------------
Binary property 'branch-1.4-blocked' - no diff available.

Propchange: team/group/issue3450/
------------------------------------------------------------------------------
Binary property 'branch-1.4-merged' - no diff available.

Propchange: team/group/issue3450/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Mon Aug 18 18:23:24 2008
@@ -1,1 +1,1 @@
-/trunk:1-138270
+/trunk:1-138769

Modified: team/group/issue3450/Makefile
URL: http://svn.digium.com/view/asterisk/team/group/issue3450/Makefile?view=diff&rev=138772&r1=138771&r2=138772
==============================================================================
--- team/group/issue3450/Makefile (original)
+++ team/group/issue3450/Makefile Mon Aug 18 18:23:24 2008
@@ -684,7 +684,6 @@
 		echo ";transcode_via_sln = yes ; Build transcode paths via SLINEAR, instead of directly" ; \
 		echo ";runuser = asterisk ; The user to run as" ; \
 		echo ";rungroup = asterisk ; The group to run as" ; \
-		echo "dahdichanname = yes ; Set channel name as DAHDI" ; \
 		echo "" ; \
 		echo "; Changing the following lines may compromise your security." ; \
 		echo ";[files]" ; \

Modified: team/group/issue3450/apps/app_queue.c
URL: http://svn.digium.com/view/asterisk/team/group/issue3450/apps/app_queue.c?view=diff&rev=138772&r1=138771&r2=138772
==============================================================================
--- team/group/issue3450/apps/app_queue.c (original)
+++ team/group/issue3450/apps/app_queue.c Mon Aug 18 18:23:24 2008
@@ -2313,6 +2313,14 @@
 			/* Ring just the best channel */
 			ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
 			ret = ring_entry(qe, best, busies);
+		}
+		
+		/* If we have timed out, break out */
+		if (qe->expire && (time(NULL) >= qe->expire)) {
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Queue timed out while ringing members.\n");
+			ret = 0;
+			break;
 		}
 	}
 
@@ -2855,7 +2863,7 @@
 			break;
 
 		/* If we have timed out, break out */
-		if (qe->expire && (time(NULL) > qe->expire)) {
+		if (qe->expire && (time(NULL) >= qe->expire)) {
 			*reason = QUEUE_TIMEOUT;
 			break;
 		}
@@ -2890,7 +2898,7 @@
 			break;
 
 		/* If we have timed out, break out */
-		if (qe->expire && (time(NULL) > qe->expire)) {
+		if (qe->expire && (time(NULL) >= qe->expire)) {
 			*reason = QUEUE_TIMEOUT;
 			break;
 		}
@@ -2901,12 +2909,12 @@
 			break;
 		
 		/* see if we need to move to the next penalty level for this queue */
-		while (qe->pr && ((time(NULL) - qe->start) > qe->pr->time)) {
+		while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
 			update_qe_rule(qe);
 		}
 
 		/* If we have timed out, break out */
-		if (qe->expire && (time(NULL) > qe->expire)) {
+		if (qe->expire && (time(NULL) >= qe->expire)) {
 			*reason = QUEUE_TIMEOUT;
 			break;
 		}
@@ -2920,7 +2928,7 @@
 		}
 		
 		/* If we have timed out, break out */
-		if (qe->expire && (time(NULL) > qe->expire)) {
+		if (qe->expire && (time(NULL) >= qe->expire)) {
 			*reason = QUEUE_TIMEOUT;
 			break;
 		}
@@ -3245,7 +3253,7 @@
 	 * This should be extremely rare. queue_exec will take care
 	 * of removing the caller and reporting the timeout as the reason.
 	 */
-	if (qe->expire && now > qe->expire) {
+	if (qe->expire && now >= qe->expire) {
 		res = 0;
 		goto out;
 	}
@@ -3407,10 +3415,22 @@
 		}
 	}
 
-	if (qe->expire && (!qe->parent->timeout || (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP && (qe->expire - now) <= qe->parent->timeout)))
-		to = (qe->expire - now) * 1000;
-	else
-		to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
+	if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
+		/* Application arguments have higher timeout priority (behaviour for <=1.6) */
+		if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout))
+			to = (qe->expire - now) * 1000;
+		else
+			to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
+	} else {
+		/* Config timeout is higher priority thatn application timeout */
+		if (qe->expire && qe->expire<=now) {
+			to = 0;
+		} else if (qe->parent->timeout) {
+			to = qe->parent->timeout * 1000;
+		} else {
+			to = -1;
+		}
+	}
 	orig = to;
 	++qe->pending;
 	ao2_unlock(qe->parent);
@@ -4707,7 +4727,7 @@
 		enum queue_member_status status;
 
 		/* Leave if we have exceeded our queuetimeout */
-		if (qe.expire && (time(NULL) > qe.expire)) {
+		if (qe.expire && (time(NULL) >= qe.expire)) {
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
@@ -4730,7 +4750,7 @@
 				goto stop;
 	
 		/* Leave if we have exceeded our queuetimeout */
-		if (qe.expire && (time(NULL) > qe.expire)) {
+		if (qe.expire && (time(NULL) >= qe.expire)) {
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;
@@ -4786,7 +4806,7 @@
 		}
 
 		/* Leave if we have exceeded our queuetimeout */
-		if (qe.expire && (time(NULL) > qe.expire)) {
+		if (qe.expire && (time(NULL) >= qe.expire)) {
 			record_abandoned(&qe);
 			reason = QUEUE_TIMEOUT;
 			res = 0;

Modified: team/group/issue3450/channels/chan_dahdi.c
URL: http://svn.digium.com/view/asterisk/team/group/issue3450/channels/chan_dahdi.c?view=diff&rev=138772&r1=138771&r2=138772
==============================================================================
--- team/group/issue3450/channels/chan_dahdi.c (original)
+++ team/group/issue3450/channels/chan_dahdi.c Mon Aug 18 18:23:24 2008
@@ -292,6 +292,14 @@
 /*! \brief This is the thread for the monitor which checks for input on the channels
    which are not currently in use. */
 static pthread_t monitor_thread = AST_PTHREADT_NULL;
+static ast_cond_t mwi_thread_complete;
+static ast_cond_t ss_thread_complete;
+AST_MUTEX_DEFINE_STATIC(mwi_thread_lock);
+AST_MUTEX_DEFINE_STATIC(ss_thread_lock);
+AST_MUTEX_DEFINE_STATIC(restart_lock);
+static int mwi_thread_count = 0;
+static int ss_thread_count = 0;
+static int num_restart_pending = 0;
 
 static int restart_monitor(void);
 
@@ -575,6 +583,7 @@
 	unsigned int priexclusive:1;
 	unsigned int pulse:1;
 	unsigned int pulsedial:1;			/*!< whether a pulse dial phone is detected */
+	unsigned int restartpending:1;		/*!< flag to ensure counted only once for restart */
 	unsigned int restrictcid:1;			/*!< Whether restrict the callerid -> only send ANI */
 	unsigned int threewaycalling:1;
 	unsigned int transfer:1;
@@ -897,7 +906,8 @@
 		}
 	} while (res);
 	/* Then break the poll */
-	pthread_kill(pri->master, SIGURG);
+	if (pri->master != AST_PTHREADT_NULL)
+		pthread_kill(pri->master, SIGURG);
 	return 0;
 }
 #endif
@@ -919,7 +929,8 @@
 		}
 	} while (res);
 	/* Then break the poll */
-	pthread_kill(pri->master, SIGURG);
+	if (pri->master != AST_PTHREADT_NULL)
+		pthread_kill(pri->master, SIGURG);
 	return 0;
 }
 #endif
@@ -957,11 +968,11 @@
 static int dahdi_get_index(struct ast_channel *ast, struct dahdi_pvt *p, int nullok)
 {
 	int res;
-	if (p->subs[0].owner == ast)
+	if (p->subs[SUB_REAL].owner == ast)
 		res = 0;
-	else if (p->subs[1].owner == ast)
+	else if (p->subs[SUB_CALLWAIT].owner == ast)
 		res = 1;
-	else if (p->subs[2].owner == ast)
+	else if (p->subs[SUB_THREEWAY].owner == ast)
 		res = 2;
 	else {
 		res = -1;
@@ -1857,7 +1868,8 @@
 	if (res < 0) {
 		if (errno == EINPROGRESS)
 			return 0;
-		ast_log(LOG_WARNING, "DAHDI hook failed: %s\n", strerror(errno));
+		ast_log(LOG_WARNING, "DAHDI hook failed returned %d (trying %d): %s\n", res, hs, strerror(errno));
+		/* will expectedly fail if phone is off hook during operation, such as during a restart */
 	}
 
 	return res;
@@ -2786,7 +2798,9 @@
 	if (p->vars)
 		ast_variables_destroy(p->vars);
 	ast_mutex_destroy(&p->lock);
-	ast_free(p);
+	if (p->owner)
+		p->owner->tech_pvt = NULL;
+	free(p);
 	*pvt = NULL;
 }
 
@@ -2844,6 +2858,39 @@
 		destroy_dahdi_pvt(&cur);
 	}
 	return 0;
+}
+
+static void destroy_all_channels(void)
+{
+	int x;
+	struct dahdi_pvt *p, *pl;
+
+	while (num_restart_pending) {
+		usleep(1);
+	}
+
+	ast_mutex_lock(&iflock);
+	/* Destroy all the interfaces and free their memory */
+	p = iflist;
+	while (p) {
+		/* Free any callerid */
+		if (p->cidspill)
+			ast_free(p->cidspill);
+		/* Close the DAHDI thingy */
+		if (p->subs[SUB_REAL].dfd > -1)
+			dahdi_close(p->subs[SUB_REAL].dfd);
+		pl = p;
+		p = p->next;
+		x = pl->channel;
+		/* Free associated memory */
+		if (pl)
+			destroy_dahdi_pvt(&pl);
+		if (option_verbose > 2) 
+			ast_verbose(VERBOSE_PREFIX_2 "Unregistered channel %d\n", x);
+	}
+	iflist = NULL;
+	ifcount = 0;
+	ast_mutex_unlock(&iflock);
 }
 
 #ifdef HAVE_PRI
@@ -3296,7 +3343,8 @@
 			p->pri = NULL;
 		}
 #endif
-		restart_monitor();
+		if (num_restart_pending == 0)
+			restart_monitor();
 	}
 
 	p->callwaitingrepeat = 0;
@@ -3308,6 +3356,11 @@
 	ast_verb(3, "Hungup '%s'\n", ast->name);
 
 	ast_mutex_lock(&iflock);
+
+	if (p->restartpending) {
+		num_restart_pending--;
+	}
+
 	tmp = iflist;
 	prev = NULL;
 	if (p->destroy) {
@@ -6106,21 +6159,23 @@
 	int res;
 	int idx;
 
+	ast_mutex_lock(&ss_thread_lock);
+	ss_thread_count++;
+	ast_mutex_unlock(&ss_thread_lock);
 	/* in the bizarre case where the channel has become a zombie before we
 	   even get started here, abort safely
 	*/
 	if (!p) {
 		ast_log(LOG_WARNING, "Channel became a zombie before simple switch could be started (%s)\n", chan->name);
 		ast_hangup(chan);
-		return NULL;
-	}
-
+		goto quit;
+	}
 	ast_verb(3, "Starting simple switch on '%s'\n", chan->name);
 	idx = dahdi_get_index(chan, p, 1);
 	if (idx < 0) {
 		ast_log(LOG_WARNING, "Huh?\n");
 		ast_hangup(chan);
-		return NULL;
+		goto quit;
 	}
 	if (p->dsp)
 		ast_dsp_digitreset(p->dsp);
@@ -6146,7 +6201,7 @@
 			if (res < 0) {
 				ast_debug(1, "waitfordigit returned < 0...\n");
 				ast_hangup(chan);
-				return NULL;
+				goto quit;
 			} else if (res) {
 				exten[len++] = res;
 				exten[len] = '\0';
@@ -6178,7 +6233,7 @@
 			/* Since we send release complete here, we won't get one */
 			p->call = NULL;
 		}
-		return NULL;
+		goto quit;
 		break;
 #endif
 	case SIG_FEATD:
@@ -6193,7 +6248,7 @@
 	case SIG_SF_FEATB:
 	case SIG_SFWINK:
 		if (dahdi_wink(p, idx))	
-			return NULL;
+			goto quit;
 		/* Fall through */
 	case SIG_EM:
 	case SIG_EM_E1:
@@ -6230,7 +6285,7 @@
 			case SIG_FEATDMF_TA:
 				res = my_getsigstr(chan, dtmfbuf + 1, "#", 3000);
 				if ((res < 1) && (p->dsp)) ast_dsp_digitreset(p->dsp);
-				if (dahdi_wink(p, idx)) return NULL;
+				if (dahdi_wink(p, idx)) goto quit;
 				dtmfbuf[0] = 0;
 				/* Wait for the first digit (up to 5 seconds). */
 				res = ast_waitfordigit(chan, 5000);
@@ -6245,7 +6300,7 @@
 				/* if international caca, do it again to get real ANO */
 				if ((p->sig == SIG_FEATDMF) && (dtmfbuf[1] != '0') && (strlen(dtmfbuf) != 14))
 				{
-					if (dahdi_wink(p, idx)) return NULL;
+					if (dahdi_wink(p, idx)) goto quit;
 					dtmfbuf[0] = 0;
 					/* Wait for the first digit (up to 5 seconds). */
 					res = ast_waitfordigit(chan, 5000);
@@ -6292,7 +6347,7 @@
 					if (res < 0) {
 						ast_debug(1, "waitfordigit returned < 0...\n");
 						ast_hangup(chan);
-						return NULL;
+						goto quit;
 					} else if (res) {
 						dtmfbuf[len++] = res;
 						dtmfbuf[len] = '\0';
@@ -6306,11 +6361,11 @@
 		if (res == -1) {
 			ast_log(LOG_WARNING, "getdtmf on channel %d: %s\n", p->channel, strerror(errno));
 			ast_hangup(chan);
-			return NULL;
+			goto quit;
 		} else if (res < 0) {
 			ast_debug(1, "Got hung up before digits finished\n");
 			ast_hangup(chan);
-			return NULL;
+			goto quit;
 		}
 
 		if (p->sig == SIG_FGC_CAMA) {
@@ -6318,7 +6373,7 @@
 
 			if (ast_safe_sleep(chan,1000) == -1) {
 	                        ast_hangup(chan);
-	                        return NULL;
+	                        goto quit;
 			}
                         dahdi_set_hook(p->subs[SUB_REAL].dfd, DAHDI_OFFHOOK);
                         ast_dsp_set_digitmode(p->dsp, DSP_DIGITMODE_MF | p->dtmfrelax);
@@ -6407,7 +6462,7 @@
                         /* some switches require a minimum guard time between
                            the last FGD wink and something that answers
                            immediately. This ensures it */
-                        if (ast_safe_sleep(chan,100)) return NULL;
+                        if (ast_safe_sleep(chan,100)) goto quit;
 		}
 		dahdi_enable_ec(p);
 		if (NEED_MFDETECT(p)) {
@@ -6429,7 +6484,7 @@
 				ast_log(LOG_WARNING, "PBX exited non-zero\n");
 				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
 			}
-			return NULL;
+			goto quit;
 		} else {
 			ast_verb(2, "Unknown extension '%s' in context '%s' requested\n", exten, chan->context);
 			sleep(2);
@@ -6443,7 +6498,7 @@
 				ast_waitstream(chan, "");
 			res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
 			ast_hangup(chan);
-			return NULL;
+			goto quit;
 		}
 		break;
 	case SIG_FXOLS:
@@ -6467,7 +6522,7 @@
 				ast_debug(1, "waitfordigit returned < 0...\n");
 				res = tone_zone_play_tone(p->subs[idx].dfd, -1);
 				ast_hangup(chan);
-				return NULL;
+				goto quit;
 			} else if (res)  {
 				ast_debug(1,"waitfordigit returned '%c' (%d), timeout = %d\n", res, res, timeout);
 				exten[len++]=res;
@@ -6513,7 +6568,7 @@
 							ast_log(LOG_WARNING, "PBX exited non-zero\n");
 							res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
 						}
-						return NULL;
+						goto quit;
 					}
 				} else {
 					/* It's a match, but they just typed a digit, and there is an ambiguous match,
@@ -6525,7 +6580,7 @@
 				res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
 				dahdi_wait_event(p->subs[idx].dfd);
 				ast_hangup(chan);
-				return NULL;
+				goto quit;
 			} else if (p->callwaiting && !strcmp(exten, "*70")) {
 				ast_verb(3, "Disabling call waiting on %s\n", chan->name);
 				/* Disable call waiting if enabled */
@@ -6561,11 +6616,11 @@
 						dahdi_wait_event(p->subs[idx].dfd);
 					}
 					ast_hangup(chan);
-					return NULL;
+					goto quit;
 				} else {
 					ast_log(LOG_WARNING, "Huh?  Got *8# on call not on real\n");
 					ast_hangup(chan);
-					return NULL;
+					goto quit;
 				}
 				
 			} else if (!p->hidecallerid && !strcmp(exten, "*67")) {
@@ -6680,7 +6735,7 @@
 					if (ast_bridged_channel(p->subs[SUB_REAL].owner))
 						ast_queue_control(p->subs[SUB_REAL].owner, AST_CONTROL_UNHOLD);
 					ast_hangup(chan);
-					return NULL;
+					goto quit;
 				} else {
 					tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
 					dahdi_wait_event(p->subs[idx].dfd);
@@ -6689,7 +6744,7 @@
 					unalloc_sub(p, SUB_THREEWAY);
 					p->owner = p->subs[SUB_REAL].owner;
 					ast_hangup(chan);
-					return NULL;
+					goto quit;
 				}					
 			} else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
 							((exten[0] != '*') || (strlen(exten) > 2))) {
@@ -6721,7 +6776,7 @@
 					if (!f) {
 						ast_log(LOG_WARNING, "Whoa, hangup while waiting for first ring!\n");
 						ast_hangup(chan);
-						return NULL;
+						goto quit;
 					} else if ((f->frametype == AST_FRAME_CONTROL) && (f->subclass == AST_CONTROL_RING)) {
 						res = 1;
 					} else
@@ -6776,7 +6831,7 @@
 						ast_log(LOG_WARNING, "DTMFCID timed out waiting for ring. "
 							"Exiting simple switch\n");
 						ast_hangup(chan);
-						return NULL;
+						goto quit;
 					} 
 					f = ast_read(chan);
 					if (!f)
@@ -6821,7 +6876,7 @@
 							ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
 							callerid_free(cs);
 							ast_hangup(chan);
-							return NULL;
+							goto quit;
 						}
 						if (i & DAHDI_IOMUX_SIGEVENT) {
 							res = dahdi_get_event(p->subs[idx].dfd);
@@ -6843,7 +6898,7 @@
 									ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
 									callerid_free(cs);
 									ast_hangup(chan);
-									return NULL;
+									goto quit;
 								}
 								break;
 							}
@@ -6886,12 +6941,12 @@
 							ast_log(LOG_WARNING, "CID timed out waiting for ring. "
 								"Exiting simple switch\n");
 							ast_hangup(chan);
-							return NULL;
+							goto quit;
 						} 
 						if (!(f = ast_read(chan))) {
 							ast_log(LOG_WARNING, "Hangup received waiting for ring. Exiting simple switch\n");
 							ast_hangup(chan);
-							return NULL;
+							goto quit;
 						}
 						ast_frfree(f);
 						if (chan->_state == AST_STATE_RING ||
@@ -6922,7 +6977,7 @@
 								ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
 								callerid_free(cs);
 								ast_hangup(chan);
-								return NULL;
+								goto quit;
 							}
 							if (i & DAHDI_IOMUX_SIGEVENT) {
 								res = dahdi_get_event(p->subs[idx].dfd);
@@ -6945,7 +7000,7 @@
 										ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
 										callerid_free(cs);
 										ast_hangup(chan);
-										return NULL;
+										goto quit;
 									}
 									break;
 								}
@@ -7002,7 +7057,7 @@
 					"restarted by the actual ring.\n", 
 					chan->name);
 				ast_hangup(chan);
-				return NULL;
+				goto quit;
 			}
 		} else if (p->use_callerid && p->cid_start == CID_START_RING) {
                         if (p->cid_signalling == CID_SIG_DTMF) {
@@ -7073,7 +7128,7 @@
 						ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
 						callerid_free(cs);
 						ast_hangup(chan);
-						return NULL;
+						goto quit;
 					}
 					if (i & DAHDI_IOMUX_SIGEVENT) {
 						res = dahdi_get_event(p->subs[idx].dfd);
@@ -7084,7 +7139,7 @@
 							p->polarity = POLARITY_IDLE;
 							callerid_free(cs);
 							ast_hangup(chan);
-							return NULL;
+							goto quit;
 						}
 						res = 0;
 						/* Let us detect callerid when the telco uses distinctive ring */
@@ -7104,7 +7159,7 @@
 								ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
 								callerid_free(cs);
 								ast_hangup(chan);
-								return NULL;
+								goto quit;
 							}
 							break;
 						}
@@ -7142,7 +7197,7 @@
 							ast_log(LOG_WARNING, "I/O MUX failed: %s\n", strerror(errno));
 							callerid_free(cs);
 							ast_hangup(chan);
-							return NULL;
+							goto quit;
 						}
 						if (i & DAHDI_IOMUX_SIGEVENT) {
 							res = dahdi_get_event(p->subs[idx].dfd);
@@ -7165,7 +7220,7 @@
 									ast_log(LOG_WARNING, "read returned error: %s\n", strerror(errno));
 									callerid_free(cs);
 									ast_hangup(chan);
-									return NULL;
+									goto quit;
 								}
 								break;
 							}
@@ -7260,7 +7315,7 @@
 			ast_hangup(chan);
 			ast_log(LOG_WARNING, "PBX exited non-zero\n");
 		}
-		return NULL;
+		goto quit;
 	default:
 		ast_log(LOG_WARNING, "Don't know how to handle simple switch with signalling %s on channel %d\n", sig2str(p->sig), p->channel);
 		res = tone_zone_play_tone(p->subs[idx].dfd, DAHDI_TONE_CONGESTION);
@@ -7271,6 +7326,11 @@
 	if (res < 0)
 			ast_log(LOG_WARNING, "Unable to play congestion tone on channel %d\n", p->channel);
 	ast_hangup(chan);
+quit:
+	ast_mutex_lock(&ss_thread_lock);
+	ss_thread_count--;
+	ast_cond_signal(&ss_thread_complete);
+	ast_mutex_unlock(&ss_thread_lock);
 	return NULL;
 }
 
@@ -7298,7 +7358,6 @@
 {
 	struct mwi_thread_data *mtd = data;
 	struct callerid_state *cs;
-	pthread_attr_t attr;
 	pthread_t threadid;
 	int samples = 0;
 	char *name, *number;
@@ -7357,10 +7416,7 @@
 				mtd->pvt->ringt = mtd->pvt->ringt_base;
 
 				if ((chan = dahdi_new(mtd->pvt, AST_STATE_RING, 0, SUB_REAL, 0, 0))) {
-					pthread_attr_init(&attr);
-					pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-
-					if (ast_pthread_create(&threadid, &attr, ss_thread, chan)) {
+					if (ast_pthread_create_detached(&threadid, NULL, ss_thread, chan)) {
 						ast_log(LOG_WARNING, "Unable to start simple switch thread on channel %d\n", mtd->pvt->channel);
 						res = tone_zone_play_tone(mtd->pvt->subs[SUB_REAL].dfd, DAHDI_TONE_CONGESTION);
 						if (res < 0)
@@ -7448,6 +7504,10 @@
 	int x, i, res;
 	int num_read;
 	enum mwisend_states mwi_send_state = MWI_SEND_SPILL; /*Assume FSK only */
+
+	ast_mutex_lock(&mwi_thread_lock);
+	mwi_thread_count++;
+	ast_mutex_unlock(&mwi_thread_lock);
 
 	/* Determine how this spill is to be sent */
 	if(mwisend_rpas) {
@@ -7571,15 +7631,21 @@
 				break;
 		}
 	}
+
 quit:
-		if(mtd->pvt->cidspill) {
-	ast_free(mtd->pvt->cidspill);
-	mtd->pvt->cidspill = NULL;
-		}
-		mtd->pvt->mwisendactive = 0;
-		ast_free(mtd);
-
-		return NULL;
+	if(mtd->pvt->cidspill) {
+		ast_free(mtd->pvt->cidspill);
+		mtd->pvt->cidspill = NULL;
+	}
+	mtd->pvt->mwisendactive = 0;
+	ast_free(mtd);
+
+	ast_mutex_lock(&mwi_thread_lock);
+	mwi_thread_count--;
+	ast_cond_signal(&mwi_thread_complete);
+	ast_mutex_unlock(&mwi_thread_lock);
+
+	return NULL;
 }
 
 
@@ -7592,7 +7658,10 @@
 	tmp = iflist;
 	while (tmp) {
 		if (tmp->channel == channel) {
+			int x = DAHDI_FLASH;
+			ioctl(tmp->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */
 			destroy_channel(prev, tmp, 1);
+			ast_module_unref(ast_module_info->self);
 			return RESULT_SUCCESS;
 		}
 		prev = tmp;
@@ -7853,6 +7922,8 @@
 	}
 	ast_debug(1, "Monitor starting...\n");
 #endif
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
 	for (;;) {
 		/* Lock the interface list */
 		ast_mutex_lock(&iflock);
@@ -7892,10 +7963,13 @@
 		/* Okay, now that we know what to do, release the interface lock */
 		ast_mutex_unlock(&iflock);
 		
+		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
 		pthread_testcancel();
 		/* Wait at least a second for something to happen */
 		res = poll(pfds, count, 1000);
 		pthread_testcancel();
+		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
 		/* Okay, poll has finished.  Let's see what happened.  */
 		if (res < 0) {
 			if ((errno != EAGAIN) && (errno != EINTR))
@@ -8048,7 +8122,7 @@
 		pthread_kill(monitor_thread, SIGURG);
 	} else {
 		/* Start a new monitor */
-		if (ast_pthread_create_detached_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
+		if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
 			ast_mutex_unlock(&monlock);
 			ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
 			return -1;
@@ -8259,9 +8333,10 @@
 		tmp2 = tmp2->next;
 	}
 
-	if (!here && !reloading) {
+	if (!here && reloading != 1) {
 		if (!(tmp = ast_calloc(1, sizeof(*tmp)))) {
-			destroy_dahdi_pvt(&tmp);
+			if (tmp)
+				free(tmp);
 			return NULL;
 		}
 		ast_mutex_init(&tmp->lock);
@@ -8277,9 +8352,12 @@
 			if ((channel != CHAN_PSEUDO) && !pri) {
 				snprintf(fn, sizeof(fn), "%d", channel);
 				/* Open non-blocking */
-				if (!here)
+				tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
+				while (tmp->subs[SUB_REAL].dfd < 0 && reloading == 2) { /* the kernel may not call dahdi_release fast enough for the open flagbit to be cleared in time */
+					usleep(1);
 					tmp->subs[SUB_REAL].dfd = dahdi_open(fn);
-				/* Allocate a dahdi structure */
+				}
+				/* Allocate a DAHDI structure */
 				if (tmp->subs[SUB_REAL].dfd < 0) {
 					ast_log(LOG_ERROR, "Unable to open channel %d: %s\nhere = %d, tmp->channel = %d, channel = %d\n", channel, strerror(errno), here, tmp->channel, channel);
 					destroy_dahdi_pvt(&tmp);
@@ -9793,7 +9871,7 @@
 				if (p->owner) {
 					p->owner->hangupcause = e->rel.cause;
 					p->owner->_softhangup |= AST_SOFTHANGUP_DEV;
-				} else
+				} else if (!p->restartpending)
 					ast_log(LOG_WARNING, "REL on channel (CIC %d) without owner!\n", p->cic);
 
 				/* End the loopback if we have one */
@@ -10377,6 +10455,9 @@
 	char plancallingani[256];
 	char calledtonstr[10];
 	
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
+
+	gettimeofday(&lastidle, NULL);
 	if (!ast_strlen_zero(pri->idledial) && !ast_strlen_zero(pri->idleext)) {
 		/* Need to do idle dialing, check to be sure though */
 		cc = strchr(pri->idleext, '@');
@@ -10501,8 +10582,12 @@
 		}
 		ast_mutex_unlock(&pri->lock);
 
+		pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+		pthread_testcancel();
 		e = NULL;
 		res = poll(fds, numdchans, lowest.tv_sec * 1000 + lowest.tv_usec / 1000);
+		pthread_testcancel();
+		pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
 
 		ast_mutex_lock(&pri->lock);
 		if (!res) {
@@ -12164,20 +12249,150 @@
 	return ( RESULT_SUCCESS == ret ) ? CLI_SUCCESS : CLI_FAILURE;
 }
 
+static void dahdi_softhangup_all(void)
+{
+	struct dahdi_pvt *p;
+retry:
+	ast_mutex_lock(&iflock);
+    for (p = iflist; p; p = p->next) {
+		ast_mutex_lock(&p->lock);
+        if (p->owner && !p->restartpending) {
+			if (ast_channel_trylock(p->owner)) {
+				if (option_debug > 2)
+					ast_verbose("Avoiding deadlock\n");
+				/* Avoid deadlock since you're not supposed to lock iflock or pvt before a channel */
+				ast_mutex_unlock(&p->lock);
+				ast_mutex_unlock(&iflock);
+				goto retry;
+			}
+			if (option_debug > 2)
+				ast_verbose("Softhanging up on %s\n", p->owner->name);
+			ast_softhangup_nolock(p->owner, AST_SOFTHANGUP_EXPLICIT);
+			p->restartpending = 1;
+			num_restart_pending++;
+			ast_channel_unlock(p->owner);
+		}
+		ast_mutex_unlock(&p->lock);
+    }
+	ast_mutex_unlock(&iflock);
+}
+
 static int setup_dahdi(int reload);
 static int dahdi_restart(void)
 {
+#if defined(HAVE_PRI) || defined(HAVE_SS7)
+	int i, j;
+#endif
+	int cancel_code;
+	struct dahdi_pvt *p;
+
+	ast_mutex_lock(&restart_lock);
+
 	ast_verb(1, "Destroying channels and reloading DAHDI configuration.\n");
-	while (iflist) {
-		ast_debug(1, "Destroying DAHDI channel no. %d\n", iflist->channel);
-		/* Also updates iflist: */
-		destroy_channel(NULL, iflist, 1);
-	}
-	ast_debug(1, "Channels destroyed. Now re-reading config.\n");
+	dahdi_softhangup_all();
+	ast_verb(4, "Initial softhangup of all DAHDI channels complete.\n");
+
+#if defined(HAVE_PRI)
+	for (i = 0; i < NUM_SPANS; i++) {
+		if (pris[i].master && (pris[i].master != AST_PTHREADT_NULL)) {
+			cancel_code = pthread_cancel(pris[i].master);
+			pthread_kill(pris[i].master, SIGURG);
+			ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) pris[i].master, cancel_code);
+			pthread_join(pris[i].master, NULL);
+			ast_debug(4, "Joined thread of span %d\n", i);
+		}
+	}
+#endif
+
+#if defined(HAVE_SS7)
+	for (i = 0; i < NUM_SPANS; i++) {
+		if (linksets[i].master && (linksets[i].master != AST_PTHREADT_NULL)) {
+			cancel_code = pthread_cancel(linksets[i].master);
+			pthread_kill(linksets[i].master, SIGURG);
+			ast_debug(4, "Waiting to join thread of span %d with pid=%p, cancel_code=%d\n", i, (void *) linksets[i].master, cancel_code);
+			pthread_join(linksets[i].master, NULL);
+			ast_debug(4, "Joined thread of span %d\n", i);
+		}
+    }
+#endif
+
+	ast_mutex_lock(&monlock);
+	if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
+		cancel_code = pthread_cancel(monitor_thread);
+		pthread_kill(monitor_thread, SIGURG);
+		ast_debug(4, "Waiting to join monitor thread with pid=%p, cancel_code=%d\n", (void *) monitor_thread, cancel_code);
+		pthread_join(monitor_thread, NULL);
+		ast_debug(4, "Joined monitor thread\n");
+	}
+	monitor_thread = AST_PTHREADT_NULL; /* prepare to restart thread in setup_dahdi once channels are reconfigured */
+
+	ast_mutex_lock(&mwi_thread_lock);
+	while (mwi_thread_count > 0) {
+		ast_debug(3, "Waiting on %d mwi_send_thread(s) to finish\n", mwi_thread_count);
+		ast_cond_wait(&mwi_thread_complete, &mwi_thread_lock);
+	}
+	ast_mutex_unlock(&mwi_thread_lock);
+	ast_mutex_lock(&ss_thread_lock);
+	while (ss_thread_count > 0) { /* let ss_threads finish and run dahdi_hangup before dahvi_pvts are destroyed */
+		int x = DAHDI_FLASH;
+		ast_debug(3, "Waiting on %d ss_thread(s) to finish\n", ss_thread_count);
+
+		for (p = iflist; p; p = p->next) {
+			if (p->owner)
+				ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x); /* important to create an event for dahdi_wait_event to register so that all ss_threads terminate */      
+			}
+			ast_cond_wait(&ss_thread_complete, &ss_thread_lock);
+		}
+
+	/* ensure any created channels before monitor threads were stopped are hungup */
+	dahdi_softhangup_all();
+	ast_verb(4, "Final softhangup of all DAHDI channels complete.\n");
+	destroy_all_channels();
+	ast_debug(1, "Channels destroyed. Now re-reading config. %d active channels remaining.\n", ast_active_channels());
+
+	ast_mutex_unlock(&monlock);
+
+#ifdef HAVE_PRI
+	for (i = 0; i < NUM_SPANS; i++) {
+		for (j = 0; j < NUM_DCHANS; j++)
+			dahdi_close(pris[i].fds[j]);
+	}
+
+	memset(pris, 0, sizeof(pris));
+	for (i = 0; i < NUM_SPANS; i++) {
+		ast_mutex_init(&pris[i].lock);
+		pris[i].offset = -1;
+		pris[i].master = AST_PTHREADT_NULL;
+		for (j = 0; j < NUM_DCHANS; j++)
+			pris[i].fds[j] = -1;
+		}
+	pri_set_error(dahdi_pri_error);
+	pri_set_message(dahdi_pri_message);
+#endif
+#ifdef HAVE_SS7
+	for (i = 0; i < NUM_SPANS; i++) {
+		for (j = 0; j < NUM_DCHANS; j++)
+			dahdi_close(linksets[i].fds[j]);
+	}
+
+	memset(linksets, 0, sizeof(linksets));
+	for (i = 0; i < NUM_SPANS; i++) {
+		ast_mutex_init(&linksets[i].lock);
+		linksets[i].master = AST_PTHREADT_NULL;
+		for (j = 0; j < NUM_DCHANS; j++)
+			linksets[i].fds[j] = -1;
+	}
+	ss7_set_error(dahdi_ss7_error);
+	ss7_set_message(dahdi_ss7_message);
+#endif
+
 	if (setup_dahdi(2) != 0) {
 		ast_log(LOG_WARNING, "Reload channels from dahdi config failed!\n");
+		ast_mutex_unlock(&ss_thread_lock);
 		return 1;
 	}
+	ast_mutex_unlock(&ss_thread_lock);
+	ast_mutex_unlock(&restart_lock);
 	return 0;
 }
 
@@ -13102,21 +13317,480 @@
 	return 0;
 }
 
+#ifdef HAVE_SS7
+static int linkset_addsigchan(int sigchan)
+{
+	struct dahdi_ss7 *link;
+	int res;
+	int curfd;
+	struct dahdi_params p;
+	struct dahdi_bufferinfo bi;
+	struct dahdi_spaninfo si;
+
+
+	link = ss7_resolve_linkset(cur_linkset);
+	if (!link) {
+		ast_log(LOG_ERROR, "Invalid linkset number.  Must be between 1 and %d\n", NUM_SPANS + 1);
+		return -1;
+	}
+
+	if (cur_ss7type < 0) {
+		ast_log(LOG_ERROR, "Unspecified or invalid ss7type\n");
+		return -1;
+	}
+
+	if (!link->ss7)
+		link->ss7 = ss7_new(cur_ss7type);
+
+	if (!link->ss7) {
+		ast_log(LOG_ERROR, "Can't create new SS7!\n");
+		return -1;
+	}
+
+	link->type = cur_ss7type;
+
+	if (cur_pointcode < 0) {
+		ast_log(LOG_ERROR, "Unspecified pointcode!\n");
+		return -1;
+	} else
+		ss7_set_pc(link->ss7, cur_pointcode);
+
+	if (sigchan < 0) {
+		ast_log(LOG_ERROR, "Invalid sigchan!\n");
+		return -1;
+	} else {
+		if (link->numsigchans >= NUM_DCHANS) {
+			ast_log(LOG_ERROR, "Too many sigchans on linkset %d\n", cur_linkset);
+			return -1;
+		}
+		curfd = link->numsigchans;
+
+		link->fds[curfd] = open("/dev/dahdi/channel", O_RDWR, 0600);
+		if ((link->fds[curfd] < 0) || (ioctl(link->fds[curfd],DAHDI_SPECIFY,&sigchan) == -1)) {
+			ast_log(LOG_ERROR, "Unable to open SS7 sigchan %d (%s)\n", sigchan, strerror(errno));
+			return -1;
+		}
+		res = ioctl(link->fds[curfd], DAHDI_GET_PARAMS, &p);
+		if (res) {
+			dahdi_close(link->fds[curfd]);
+			link->fds[curfd] = -1;
+			ast_log(LOG_ERROR, "Unable to get parameters for sigchan %d (%s)\n", sigchan, strerror(errno));
+			return -1;
+		}
+		if ((p.sigtype != DAHDI_SIG_HDLCFCS) && (p.sigtype != DAHDI_SIG_HARDHDLC) && (p.sigtype != DAHDI_SIG_MTP2)) {
+			dahdi_close(link->fds[curfd]);
+			link->fds[curfd] = -1;
+			ast_log(LOG_ERROR, "sigchan %d is not in HDLC/FCS mode.\n", sigchan);
+			return -1;
+		}
+
+		bi.txbufpolicy = DAHDI_POLICY_IMMEDIATE;
+		bi.rxbufpolicy = DAHDI_POLICY_IMMEDIATE;
+		bi.numbufs = 32;
+		bi.bufsize = 512;
+
+		if (ioctl(link->fds[curfd], DAHDI_SET_BUFINFO, &bi)) {
+			ast_log(LOG_ERROR, "Unable to set appropriate buffering on channel %d: %s\n", sigchan, strerror(errno));
+			dahdi_close(link->fds[curfd]);
+			link->fds[curfd] = -1;
+			return -1;
+		}
+
+		if (p.sigtype == DAHDI_SIG_MTP2)
+			ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIMTP2, link->fds[curfd]);
+		else
+			ss7_add_link(link->ss7, SS7_TRANSPORT_DAHDIDCHAN, link->fds[curfd]);
+
+		link->numsigchans++;
+
+		memset(&si, 0, sizeof(si));
+		res = ioctl(link->fds[curfd], DAHDI_SPANSTAT, &si);
+		if (res) {
+			dahdi_close(link->fds[curfd]);
+			link->fds[curfd] = -1;
+			ast_log(LOG_ERROR, "Unable to get span state for sigchan %d (%s)\n", sigchan, strerror(errno));
+		}
+

[... 2942 lines stripped ...]



More information about the svn-commits mailing list