@ -276,6 +276,14 @@ AST_MUTEX_DEFINE_STATIC(monlock);
/*! \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 ) ;
@ -559,6 +567,7 @@ static struct dahdi_pvt {
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 ;
@ -881,7 +890,8 @@ static inline int pri_grab(struct dahdi_pvt *pvt, struct dahdi_pri *pri)
}
} 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
@ -903,7 +913,8 @@ static inline int ss7_grab(struct dahdi_pvt *pvt, struct dahdi_ss7 *pri)
}
} 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
@ -941,11 +952,11 @@ static struct dahdi_ring_cadence AS_RP_cadence = {{250, 10000}};
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 ;
@ -1841,7 +1852,8 @@ static inline int dahdi_set_hook(int fd, int hs)
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 ;
@ -2770,7 +2782,9 @@ static void destroy_dahdi_pvt(struct dahdi_pvt **pvt)
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 ;
}
@ -2830,6 +2844,39 @@ static int destroy_channel(struct dahdi_pvt *prev, struct dahdi_pvt *cur, int no
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
static char * dahdi_send_keypad_facility_app = " DAHDISendKeypadFacility " ;
@ -3280,7 +3327,8 @@ static int dahdi_hangup(struct ast_channel *ast)
p - > pri = NULL ;
}
# endif
restart_monitor ( ) ;
if ( num_restart_pending = = 0 )
restart_monitor ( ) ;
}
p - > callwaitingrepeat = 0 ;
@ -3292,6 +3340,11 @@ static int dahdi_hangup(struct ast_channel *ast)
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 ) {
@ -6090,21 +6143,23 @@ static void *ss_thread(void *data)
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 ) ;
@ -6130,7 +6185,7 @@ static void *ss_thread(void *data)
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 ' ;
@ -6162,7 +6217,7 @@ static void *ss_thread(void *data)
/* Since we send release complete here, we won't get one */
p - > call = NULL ;
}
return NULL ;
goto quit ;
break ;
# endif
case SIG_FEATD :
@ -6177,7 +6232,7 @@ static void *ss_thread(void *data)
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 :
@ -6214,7 +6269,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6229,7 +6284,7 @@ static void *ss_thread(void *data)
/* 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 ) ;
@ -6276,7 +6331,7 @@ static void *ss_thread(void *data)
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 ' ;
@ -6290,11 +6345,11 @@ static void *ss_thread(void *data)
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 ) {
@ -6302,7 +6357,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6391,7 +6446,7 @@ static void *ss_thread(void *data)
/* 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 ) ) {
@ -6413,7 +6468,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6427,7 +6482,7 @@ static void *ss_thread(void *data)
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 :
@ -6451,7 +6506,7 @@ static void *ss_thread(void *data)
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 ;
@ -6497,7 +6552,7 @@ static void *ss_thread(void *data)
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,
@ -6509,7 +6564,7 @@ static void *ss_thread(void *data)
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 */
@ -6545,11 +6600,11 @@ static void *ss_thread(void *data)
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 " ) ) {
@ -6664,7 +6719,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6673,7 +6728,7 @@ static void *ss_thread(void *data)
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 ) ) ) {
@ -6705,7 +6760,7 @@ static void *ss_thread(void *data)
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
@ -6760,7 +6815,7 @@ static void *ss_thread(void *data)
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 )
@ -6805,7 +6860,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6827,7 +6882,7 @@ static void *ss_thread(void *data)
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
goto quit ;
}
break ;
}
@ -6870,12 +6925,12 @@ static void *ss_thread(void *data)
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 | |
@ -6906,7 +6961,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -6929,7 +6984,7 @@ static void *ss_thread(void *data)
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
goto quit ;
}
break ;
}
@ -6986,7 +7041,7 @@ static void *ss_thread(void *data)
" 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 ) {
@ -7057,7 +7112,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -7068,7 +7123,7 @@ static void *ss_thread(void *data)
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 */
@ -7088,7 +7143,7 @@ static void *ss_thread(void *data)
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
goto quit ;
}
break ;
}
@ -7126,7 +7181,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -7149,7 +7204,7 @@ static void *ss_thread(void *data)
ast_log ( LOG_WARNING , " read returned error: %s \n " , strerror ( errno ) ) ;
callerid_free ( cs ) ;
ast_hangup ( chan ) ;
return NULL ;
goto quit ;
}
break ;
}
@ -7244,7 +7299,7 @@ static void *ss_thread(void *data)
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 ) ;
@ -7255,6 +7310,11 @@ static void *ss_thread(void *data)
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 ;
}
@ -7282,7 +7342,6 @@ static void *mwi_thread(void *data)
{
struct mwi_thread_data * mtd = data ;
struct callerid_state * cs ;
pthread_attr_t attr ;
pthread_t threadid ;
int samples = 0 ;
char * name , * number ;
@ -7341,10 +7400,7 @@ static void *mwi_thread(void *data)
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 )
@ -7433,6 +7489,10 @@ static void *mwi_send_thread(void *data)
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 ) {
mwi_send_state = MWI_SEND_SA ;
@ -7555,15 +7615,21 @@ static void *mwi_send_thread(void *data)
break ;
}
}
quit :
if ( mtd - > pvt - > cidspill ) {
ast_free ( mtd - > pvt - > cidspill ) ;
mtd - > pvt - > cidspill = NULL ;
}
mtd - > pvt - > mwisendactive = 0 ;
ast_free ( mtd ) ;
if ( mtd - > pvt - > cidspill ) {
ast_free ( mtd - > pvt - > cidspill ) ;
mtd - > pvt - > cidspill = NULL ;
}
mtd - > pvt - > mwisendactive = 0 ;
ast_free ( mtd ) ;
return NULL ;
ast_mutex_lock ( & mwi_thread_lock ) ;
mwi_thread_count - - ;
ast_cond_signal ( & mwi_thread_complete ) ;
ast_mutex_unlock ( & mwi_thread_lock ) ;
return NULL ;
}
@ -7576,6 +7642,8 @@ static int dahdi_destroy_channel_bynum(int channel)
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 ) ;
return RESULT_SUCCESS ;
}
@ -7837,6 +7905,8 @@ static void *do_monitor(void *data)
}
ast_debug ( 1 , " Monitor starting... \n " ) ;
# endif
pthread_setcancelstate ( PTHREAD_CANCEL_DISABLE , NULL ) ;
for ( ; ; ) {
/* Lock the interface list */
ast_mutex_lock ( & iflock ) ;
@ -7876,10 +7946,13 @@ static void *do_monitor(void *data)
/* 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 ) )
@ -8032,7 +8105,7 @@ static int restart_monitor(void)
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 ;
@ -8243,9 +8316,10 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
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 ) ;
@ -8261,9 +8335,12 @@ static struct dahdi_pvt *mkintf(int channel, const struct dahdi_chan_conf *conf,
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 \n here = %d, tmp->channel = %d, channel = %d \n " , channel , strerror ( errno ) , here , tmp - > channel , channel ) ;
destroy_dahdi_pvt ( & tmp ) ;
@ -9754,7 +9831,7 @@ static void *ss7_linkset(void *data)
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 */
@ -10338,6 +10415,9 @@ static void *pri_dchannel(void *vpri)
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 , ' @ ' ) ;
@ -10462,8 +10542,12 @@ static void *pri_dchannel(void *vpri)
}
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 ) {
@ -11884,20 +11968,148 @@ static char *dahdi_destroy_channel(struct ast_cli_entry *e, int cmd, struct ast_
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 )
{
int i , j , 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 ) ;
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 ) ;
}
}
ast_debug ( 1 , " Channels destroyed. Now re-reading config. \n " ) ;
# 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 ;
}
@ -12822,91 +13034,6 @@ static int action_dahdishowchannels(struct mansession *s, const struct message *
return 0 ;
}
static int __unload_module ( void )
{
int x ;
struct dahdi_pvt * p , * pl ;
# if defined(HAVE_PRI) || defined(HAVE_SS7)
int i ;
# endif
# if defined(HAVE_PRI)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( pris [ i ] . master ! = AST_PTHREADT_NULL )
pthread_cancel ( pris [ i ] . master ) ;
}
ast_cli_unregister_multiple ( dahdi_pri_cli , ARRAY_LEN ( dahdi_pri_cli ) ) ;
ast_unregister_application ( dahdi_send_keypad_facility_app ) ;
# endif
ast_cli_unregister_multiple ( dahdi_cli , sizeof ( dahdi_cli ) / sizeof ( struct ast_cli_entry ) ) ;
ast_manager_unregister ( " DAHDIDialOffhook " ) ;
ast_manager_unregister ( " DAHDIHangup " ) ;
ast_manager_unregister ( " DAHDITransfer " ) ;
ast_manager_unregister ( " DAHDIDNDoff " ) ;
ast_manager_unregister ( " DAHDIDNDon " ) ;
ast_manager_unregister ( " DAHDIShowChannels " ) ;
ast_manager_unregister ( " DAHDIRestart " ) ;
ast_channel_unregister ( & dahdi_tech ) ;
ast_mutex_lock ( & iflock ) ;
/* Hangup all interfaces if they have an owner */
p = iflist ;
while ( p ) {
if ( p - > owner )
ast_softhangup ( p - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
p = p - > next ;
}
ast_mutex_unlock ( & iflock ) ;
ast_mutex_lock ( & monlock ) ;
if ( monitor_thread & & ( monitor_thread ! = AST_PTHREADT_STOP ) & & ( monitor_thread ! = AST_PTHREADT_NULL ) ) {
pthread_cancel ( monitor_thread ) ;
pthread_kill ( monitor_thread , SIGURG ) ;
pthread_join ( monitor_thread , NULL ) ;
}
monitor_thread = AST_PTHREADT_STOP ;
ast_mutex_unlock ( & monlock ) ;
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 ) ;
ast_verb ( 3 , " Unregistered channel %d \n " , x ) ;
}
iflist = NULL ;
ifcount = 0 ;
ast_mutex_unlock ( & iflock ) ;
# if defined(HAVE_PRI)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( pris [ i ] . master & & ( pris [ i ] . master ! = AST_PTHREADT_NULL ) )
pthread_join ( pris [ i ] . master , NULL ) ;
dahdi_close ( pris [ i ] . fds [ i ] ) ;
}
# endif /* HAVE_PRI */
# if defined(HAVE_SS7)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( linksets [ i ] . master & & ( linksets [ i ] . master ! = AST_PTHREADT_NULL ) )
pthread_join ( linksets [ i ] . master , NULL ) ;
dahdi_close ( linksets [ i ] . fds [ i ] ) ;
}
# endif /* HAVE_SS7 */
return 0 ;
}
# ifdef HAVE_SS7
static int linkset_addsigchan ( int sigchan )
{
@ -13359,6 +13486,104 @@ static struct ast_cli_entry dahdi_ss7_cli[] = {
} ;
# endif /* HAVE_SS7 */
static int __unload_module ( void )
{
int x ;
struct dahdi_pvt * p , * pl ;
# if defined(HAVE_PRI) || defined(HAVE_SS7)
int i , j ;
# endif
# ifdef HAVE_PRI
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( pris [ i ] . master ! = AST_PTHREADT_NULL )
pthread_cancel ( pris [ i ] . master ) ;
}
ast_cli_unregister_multiple ( dahdi_pri_cli , ARRAY_LEN ( dahdi_pri_cli ) ) ;
ast_unregister_application ( dahdi_send_keypad_facility_app ) ;
# endif
# if defined(HAVE_SS7)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( linksets [ i ] . master ! = AST_PTHREADT_NULL )
pthread_cancel ( linksets [ i ] . master ) ;
}
ast_cli_unregister_multiple ( dahdi_ss7_cli , sizeof ( dahdi_ss7_cli ) / sizeof ( struct ast_cli_entry ) ) ;
# endif
ast_cli_unregister_multiple ( dahdi_cli , sizeof ( dahdi_cli ) / sizeof ( struct ast_cli_entry ) ) ;
ast_manager_unregister ( " DAHDIDialOffhook " ) ;
ast_manager_unregister ( " DAHDIHangup " ) ;
ast_manager_unregister ( " DAHDITransfer " ) ;
ast_manager_unregister ( " DAHDIDNDoff " ) ;
ast_manager_unregister ( " DAHDIDNDon " ) ;
ast_manager_unregister ( " DAHDIShowChannels " ) ;
ast_manager_unregister ( " DAHDIRestart " ) ;
ast_channel_unregister ( & dahdi_tech ) ;
ast_mutex_lock ( & iflock ) ;
/* Hangup all interfaces if they have an owner */
p = iflist ;
while ( p ) {
if ( p - > owner )
ast_softhangup ( p - > owner , AST_SOFTHANGUP_APPUNLOAD ) ;
p = p - > next ;
}
ast_mutex_unlock ( & iflock ) ;
ast_mutex_lock ( & monlock ) ;
if ( monitor_thread & & ( monitor_thread ! = AST_PTHREADT_STOP ) & & ( monitor_thread ! = AST_PTHREADT_NULL ) ) {
pthread_cancel ( monitor_thread ) ;
pthread_kill ( monitor_thread , SIGURG ) ;
pthread_join ( monitor_thread , NULL ) ;
}
monitor_thread = AST_PTHREADT_STOP ;
ast_mutex_unlock ( & monlock ) ;
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 ) ;
ast_verb ( 3 , " Unregistered channel %d \n " , x ) ;
}
iflist = NULL ;
ifcount = 0 ;
ast_mutex_unlock ( & iflock ) ;
# if defined(HAVE_PRI)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( pris [ i ] . master & & ( pris [ i ] . master ! = AST_PTHREADT_NULL ) )
pthread_join ( pris [ i ] . master , NULL ) ;
for ( j = 0 ; j < NUM_DCHANS ; j + + ) {
dahdi_close ( pris [ i ] . fds [ j ] ) ;
}
}
# endif
# if defined(HAVE_SS7)
for ( i = 0 ; i < NUM_SPANS ; i + + ) {
if ( linksets [ i ] . master & & ( linksets [ i ] . master ! = AST_PTHREADT_NULL ) )
pthread_join ( linksets [ i ] . master , NULL ) ;
for ( j = 0 ; j < NUM_DCHANS ; j + + ) {
dahdi_close ( linksets [ i ] . fds [ j ] ) ;
}
}
# endif
ast_cond_destroy ( & mwi_thread_complete ) ;
ast_cond_destroy ( & ss_thread_complete ) ;
return 0 ;
}
static int unload_module ( void )
{
# if defined(HAVE_PRI) || defined(HAVE_SS7)
@ -13803,7 +14028,7 @@ static int process_dahdi(struct dahdi_chan_conf *confp, const char *cat, struct
} else {
mwisend_rpas = 0 ;
}
} else if ( ! reload ) {
} else if ( reload ! = 1 ) {
if ( ! strcasecmp ( v - > name , " signalling " ) | | ! strcasecmp ( v - > name , " signaling " ) ) {
int orig_radio = confp - > chan . radio ;
int orig_outsigmod = confp - > chan . outsigmod ;
@ -14389,7 +14614,7 @@ static int setup_dahdi(int reload)
/* It's a little silly to lock it, but we mind as well just to be sure */
ast_mutex_lock ( & iflock ) ;
# ifdef HAVE_PRI
if ( ! reload ) {
if ( reload ! = 1 ) {
/* Process trunkgroups first */
v = ast_variable_browse ( cfg , " trunkgroups " ) ;
while ( v ) {
@ -14519,7 +14744,7 @@ static int setup_dahdi(int reload)
ast_mutex_unlock ( & iflock ) ;
# ifdef HAVE_PRI
if ( ! reload ) {
if ( reload ! = 1 ) {
int x ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( pris [ x ] . pvts [ 0 ] ) {
@ -14533,7 +14758,7 @@ static int setup_dahdi(int reload)
}
# endif
# ifdef HAVE_SS7
if ( ! reload ) {
if ( reload ! = 1 ) {
int x ;
for ( x = 0 ; x < NUM_SPANS ; x + + ) {
if ( linksets [ x ] . ss7 ) {
@ -14612,6 +14837,9 @@ static int load_module(void)
ast_manager_register ( " DAHDIShowChannels " , 0 , action_dahdishowchannels , " Show status DAHDI channels " ) ;
ast_manager_register ( " DAHDIRestart " , 0 , action_dahdirestart , " Fully Restart DAHDI channels (terminates calls) " ) ;
ast_cond_init ( & mwi_thread_complete , NULL ) ;
ast_cond_init ( & ss_thread_complete , NULL ) ;
return res ;
}