2007-05-06 13:54:52 +00:00
/*****************************************************************************\
* * * *
2007-05-27 13:24:02 +00:00
* * Linux Call Router * *
2007-05-06 13:54:52 +00:00
* * * *
* * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * *
* * Copyright : Andreas Eversberg * *
* * * *
* * Main function * *
* * * *
\ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include "main.h"
MESSAGES
2007-08-24 10:04:34 +00:00
double now_d , last_d ;
2007-05-06 13:54:52 +00:00
time_t now ;
struct tm * now_tm ;
struct timeval now_tv ;
struct timezone now_tz ;
# define GET_NOW() \
{ \
gettimeofday ( & now_tv , & now_tz ) ; \
now_d = ( ( double ) ( now_tv . tv_usec ) ) / 1000000 + now_tv . tv_sec ; \
now = now_tv . tv_sec ; \
now_tm = localtime ( & now ) ; \
}
2008-03-24 10:13:44 +00:00
FILE * debug_fp = NULL ;
2007-05-06 13:54:52 +00:00
int quit = 0 ;
2007-08-26 13:23:58 +00:00
#if 0
struct lcr_fdset lcr_fdset [ FD_SETSIZE ] ;
# endif
2007-05-06 13:54:52 +00:00
pthread_mutex_t mutexd ; // debug output mutex
2008-04-24 17:35:55 +00:00
pthread_mutex_t mutext ; // trace output mutex
2007-05-06 13:54:52 +00:00
pthread_mutex_t mutexe ; // error output mutex
2008-04-24 17:35:55 +00:00
//pthread_mutex_t mutex_lcr; // lcr process mutex
2007-05-06 13:54:52 +00:00
int memuse = 0 ;
int mmemuse = 0 ;
int cmemuse = 0 ;
int ememuse = 0 ;
int pmemuse = 0 ;
int amemuse = 0 ;
int rmemuse = 0 ;
int classuse = 0 ;
int fduse = 0 ;
int fhuse = 0 ;
2008-09-02 00:02:11 +00:00
const char * debug_prefix = NULL ;
2007-05-06 13:54:52 +00:00
int debug_count = 0 ;
int last_debug = 0 ;
int debug_newline = 1 ;
int nooutput = 0 ;
2008-09-02 00:02:11 +00:00
void debug_usleep ( int msec , const char * file , int line , int hour , int min , int sec )
2007-08-11 08:12:10 +00:00
{
usleep ( msec ) ;
}
2008-09-02 00:02:11 +00:00
void debug ( const char * function , int line , const char * prefix , char * buffer )
2007-05-06 13:54:52 +00:00
{
/* if we have a new debug count, we add a mark */
if ( last_debug ! = debug_count )
{
last_debug = debug_count ;
if ( ! nooutput )
printf ( " \033 [34m--------------------- %04d.%02d.%02d %02d:%02d:%02d %06d \033 [36m \n " , now_tm - > tm_year + 1900 , now_tm - > tm_mon + 1 , now_tm - > tm_mday , now_tm - > tm_hour , now_tm - > tm_min , now_tm - > tm_sec , debug_count % 1000000 ) ;
2008-03-24 10:13:44 +00:00
if ( debug_fp )
fprintf ( debug_fp , " --------------------- %04d.%02d.%02d %02d:%02d:%02d %06d \n " , now_tm - > tm_year + 1900 , now_tm - > tm_mon + 1 , now_tm - > tm_mday , now_tm - > tm_hour , now_tm - > tm_min , now_tm - > tm_sec , debug_count % 1000000 ) ;
2007-05-06 13:54:52 +00:00
}
if ( ! nooutput )
{
if ( debug_newline )
printf ( " \033 [32m%06d %s \033 [37m%s " , debug_count % 1000000 , prefix ? prefix : " " , prefix ? " " : " " ) ;
if ( function )
printf ( " (in %s() line %d): %s " , function , line , buffer ) ;
else
printf ( " %s " , buffer ) ;
}
2008-03-24 10:13:44 +00:00
if ( debug_fp )
2007-05-06 13:54:52 +00:00
{
if ( debug_newline )
{
if ( function )
2008-03-24 10:13:44 +00:00
fprintf ( debug_fp , " %s%s(in %s() line %d): %s " , prefix ? prefix : " " , prefix ? " " : " " , function , line , buffer ) ;
2007-05-06 13:54:52 +00:00
else
2008-03-24 10:13:44 +00:00
fprintf ( debug_fp , " %s%s: %s " , prefix ? prefix : " " , prefix ? " " : " " , buffer ) ;
2007-05-06 13:54:52 +00:00
}
}
debug_newline = 0 ;
if ( buffer [ 0 ] )
if ( buffer [ strlen ( buffer ) - 1 ] = = ' \n ' )
debug_newline = 1 ;
}
2008-06-14 06:34:50 +00:00
void _printdebug ( const char * function , int line , unsigned int mask , const char * fmt , . . . )
2007-05-06 13:54:52 +00:00
{
char buffer [ 4096 ] ;
va_list args ;
if ( ! ( options . deb & mask ) )
return ;
pthread_mutex_lock ( & mutexd ) ;
va_start ( args , fmt ) ;
VUNPRINT ( buffer , sizeof ( buffer ) - 1 , fmt , args ) ;
buffer [ sizeof ( buffer ) - 1 ] = 0 ;
va_end ( args ) ;
debug ( function , line , debug_prefix , buffer ) ;
pthread_mutex_unlock ( & mutexd ) ;
}
void _printerror ( const char * function , int line , const char * fmt , . . . )
{
char buffer [ 4096 ] ;
va_list args ;
pthread_mutex_lock ( & mutexe ) ;
va_start ( args , fmt ) ;
VUNPRINT ( buffer , sizeof ( buffer ) - 1 , fmt , args ) ;
buffer [ sizeof ( buffer ) - 1 ] = 0 ;
va_end ( args ) ;
if ( options . deb )
debug ( function , line , " ERROR " , buffer ) ;
else /* only if we do not debug */
{
if ( function )
fprintf ( stderr , " ERROR (in %s() line %d) %s " , function , line , buffer ) ;
else
fprintf ( stderr , " ERROR %s " , buffer ) ;
}
pthread_mutex_unlock ( & mutexe ) ;
}
void sighandler ( int sigset )
{
struct sched_param schedp ;
if ( sigset = = SIGHUP )
return ;
if ( sigset = = SIGPIPE )
return ;
if ( ! quit )
{
2008-05-02 19:40:31 +00:00
quit = sigset ;
2007-05-06 13:54:52 +00:00
/* set scheduler & priority */
if ( options . schedule > 1 )
{
memset ( & schedp , 0 , sizeof ( schedp ) ) ;
schedp . sched_priority = 0 ;
sched_setscheduler ( 0 , SCHED_OTHER , & schedp ) ;
}
2007-07-07 15:13:20 +00:00
fprintf ( stderr , " LCR: Signal received: %d \n " , sigset ) ;
2008-05-02 19:40:31 +00:00
PDEBUG ( DEBUG_LOG , " Signal received: %d \n " , sigset ) ;
2007-05-06 13:54:52 +00:00
}
}
/*
* the main
*/
int main ( int argc , char * argv [ ] )
{
int ret = - 1 ;
int lockfd = - 1 ; /* file lock */
2008-04-25 07:06:20 +00:00
struct lcr_msg * message ;
2007-05-06 13:54:52 +00:00
class Port * port ;
class Endpoint * epoint ;
2007-07-17 17:28:09 +00:00
class Join * join ;
2007-05-06 13:54:52 +00:00
int i ;
int all_idle ;
char prefix_string [ 64 ] ;
struct sched_param schedp ;
2008-09-02 00:02:11 +00:00
const char * debug_prefix = " alloc " ;
2007-06-27 06:23:50 +00:00
int created_mutexd = 0 , /* created_mutext = 0,*/ created_mutexe = 0 ,
2008-05-02 19:19:06 +00:00
created_lock = 0 , created_signal = 0 , created_debug = 0 ,
created_misdn = 0 ;
2007-05-06 13:54:52 +00:00
int idletime = 0 , idlecheck = 0 ;
2008-08-30 06:24:52 +00:00
char tracetext [ 256 ] , lock [ 128 ] ;
2007-05-06 13:54:52 +00:00
2007-08-26 13:23:58 +00:00
#if 0
/* init fdset */
memset ( lcr_fdset , 0 , sizeof ( lcr_fdset ) ) ;
# endif
2008-04-12 16:24:31 +00:00
/* lock LCR process */
2008-04-24 17:35:55 +00:00
// pthread_mutex_lock(&mutex_lcr);
2008-04-12 16:24:31 +00:00
2007-05-06 13:54:52 +00:00
/* current time */
GET_NOW ( ) ;
/* show version */
printf ( " \n ** %s Version %s \n \n " , NAME , VERSION_STRING ) ;
/* show options */
2007-07-07 15:13:20 +00:00
if ( argc < = 1 )
2007-05-06 13:54:52 +00:00
{
usage :
printf ( " \n " ) ;
2007-07-07 15:13:20 +00:00
printf ( " Usage: lcr (query | start | fork | rules | route) \n " ) ;
2007-05-06 13:54:52 +00:00
printf ( " query = Show available isdn ports. \n " ) ;
2007-07-07 15:13:20 +00:00
printf ( " start = Run lcr normally, abort with CTRL+C. \n " ) ;
2007-05-06 13:54:52 +00:00
printf ( " fork = Do daemon fork and run as background process. \n " ) ;
printf ( " interface = Get help of available interface syntax. \n " ) ;
printf ( " rules = Get help of available routing rule syntax. \n " ) ;
printf ( " rules [action] = Get individual help for given action. \n " ) ;
// printf("route = Show current routing as it is parsed.\n");
printf ( " \n " ) ;
2007-07-15 10:01:27 +00:00
ret = 999 ;
2007-05-06 13:54:52 +00:00
goto free ;
}
/* init crc */
crc_init ( ) ;
/* the mutex init */
if ( pthread_mutex_init ( & mutexd , NULL ) )
{
fprintf ( stderr , " cannot create 'PDEBUG' mutex \n " ) ;
goto free ;
}
created_mutexd = 1 ;
2007-06-27 06:23:50 +00:00
// if (pthread_mutex_init(&mutext, NULL))
// {
// fprintf(stderr, "cannot create 'trace' mutex\n");
// goto free;
// }
// created_mutext = 1;
2007-05-06 13:54:52 +00:00
if ( pthread_mutex_init ( & mutexe , NULL ) )
{
fprintf ( stderr , " cannot create 'PERROR' mutex \n " ) ;
goto free ;
}
created_mutexe = 1 ;
/* show interface */
2007-07-07 15:13:20 +00:00
if ( ! ( strcasecmp ( argv [ 1 ] , " interface " ) ) )
2007-05-06 13:54:52 +00:00
{
doc_interface ( ) ;
ret = 0 ;
goto free ;
}
/* show rules */
2007-07-07 15:13:20 +00:00
if ( ! ( strcasecmp ( argv [ 1 ] , " rules " ) ) )
2007-05-06 13:54:52 +00:00
{
2007-07-07 15:13:20 +00:00
if ( argc < = 2 )
2007-05-06 13:54:52 +00:00
doc_rules ( NULL ) ;
else
2007-07-07 15:13:20 +00:00
doc_rules ( argv [ 2 ] ) ;
2007-05-06 13:54:52 +00:00
ret = 0 ;
goto free ;
}
/* query available isdn ports */
2007-07-07 15:13:20 +00:00
if ( ! ( strcasecmp ( argv [ 1 ] , " query " ) ) )
2007-05-06 13:54:52 +00:00
{
2008-09-12 05:43:21 +00:00
fprintf ( stderr , " -> Using 'misdn_info' \n " ) ;
system ( " misdn_info " ) ;
2007-05-06 13:54:52 +00:00
ret = 0 ;
goto free ;
}
/* read options */
if ( read_options ( ) = = 0 )
2008-06-06 13:18:59 +00:00
{
PERROR ( " %s " , options_error ) ;
2007-05-06 13:54:52 +00:00
goto free ;
2008-06-06 13:18:59 +00:00
}
2007-05-06 13:54:52 +00:00
2007-07-31 05:34:18 +00:00
/* init mISDN */
if ( mISDN_initialize ( ) < 0 )
goto free ;
2008-05-02 19:19:06 +00:00
created_misdn = 1 ;
2007-05-06 13:54:52 +00:00
created_debug = 1 ;
/* read ruleset(s) */
if ( ! ( ruleset_first = ruleset_parse ( ) ) )
goto free ;
/* set pointer to main ruleset */
ruleset_main = getrulesetbyname ( " main " ) ;
if ( ! ruleset_main )
{
fprintf ( stderr , " \n *** \n -> Missing 'main' ruleset, causing ALL calls to be disconnected. \n *** \n \n " ) ;
PDEBUG ( DEBUG_LOG , " Missing 'main' ruleset, causing ALL calls to be disconnected. \n " ) ;
sleep ( 2 ) ;
}
#if 0
/* query available isdn ports */
2007-07-07 15:13:20 +00:00
if ( ! ( strcasecmp ( argv [ 1 ] , " route " ) ) )
2007-05-06 13:54:52 +00:00
{
ruleset_debug ( ruleset_first ) ;
ret = 0 ;
goto free ;
}
# endif
/* do fork in special cases */
2007-07-07 15:13:20 +00:00
if ( ! ( strcasecmp ( argv [ 1 ] , " fork " ) ) )
2007-05-06 13:54:52 +00:00
{
pid_t pid ;
2009-03-15 08:20:20 +00:00
FILE * pidfile ;
2007-05-06 13:54:52 +00:00
/* do daemon fork */
pid = fork ( ) ;
if ( pid < 0 )
{
fprintf ( stderr , " Cannot fork! \n " ) ;
goto free ;
}
if ( pid ! = 0 )
{
exit ( 0 ) ;
}
usleep ( 200000 ) ;
printf ( " \n " ) ;
/* do second fork */
pid = fork ( ) ;
if ( pid < 0 )
{
fprintf ( stderr , " Cannot fork! \n " ) ;
goto free ;
}
if ( pid ! = 0 )
{
2007-07-07 15:13:20 +00:00
printf ( " LCR: Starting daemon. \n " ) ;
2007-05-06 13:54:52 +00:00
exit ( 0 ) ;
}
nooutput = 1 ;
2009-03-15 08:20:20 +00:00
/* write pid file */
pidfile = fopen ( " /var/run/lcr.pid " , " w " ) ;
2009-03-15 09:19:45 +00:00
if ( pidfile )
{
fprintf ( pidfile , " %d \n " , getpid ( ) ) ;
fclose ( pidfile ) ;
}
2007-05-06 13:54:52 +00:00
} else
/* if not start */
2007-07-07 15:13:20 +00:00
if ( ! ! strcasecmp ( argv [ 1 ] , " start " ) )
2007-05-06 13:54:52 +00:00
{
goto usage ;
}
/* create lock and lock! */
2008-08-30 06:24:52 +00:00
SPRINT ( lock , " %s/lcr.lock " , options . lock ) ;
2008-09-03 18:57:58 +00:00
if ( ( lockfd = open ( lock , O_CREAT | O_WRONLY , S_IWUSR ) ) < 0 )
2007-05-06 13:54:52 +00:00
{
2008-08-30 06:24:52 +00:00
fprintf ( stderr , " Cannot create lock file: %s \n " , lock ) ;
fprintf ( stderr , " Check options.conf to change to path with permissions for you. \n " ) ;
2007-05-06 13:54:52 +00:00
goto free ;
}
if ( flock ( lockfd , LOCK_EX | LOCK_NB ) < 0 )
{
if ( errno = = EWOULDBLOCK )
2007-07-07 15:13:20 +00:00
fprintf ( stderr , " LCR: Another LCR process is running. Please kill the other one. \n " ) ;
2007-05-06 13:54:52 +00:00
else fprintf ( stderr , " Locking process failed: errno=%d \n " , errno ) ;
goto free ;
}
created_lock = 1 ;
/* initialize admin socket */
if ( admin_init ( ) )
{
fprintf ( stderr , " Unable to initialize admin socket. \n " ) ;
goto free ;
}
/* generate alaw / ulaw tables */
generate_tables ( options . law ) ;
/* load tones (if requested) */
if ( fetch_tones ( ) = = 0 )
{
fprintf ( stderr , " Unable to fetch tones into memory. \n " ) ;
goto free ;
}
2009-05-11 09:07:58 +00:00
# ifdef WITH_GSM
/* handle gsm */
if ( options . gsm & & gsm_init ( ) )
{
fprintf ( stderr , " GSM initialization failed. \n " ) ;
goto free ;
}
# else
if ( options . gsm )
{
fprintf ( stderr , " GSM is enabled, but not compiled. Use --with-gsm while configure! \n " ) ;
goto free ;
}
# endif
2007-05-06 13:54:52 +00:00
/* read interfaces and open ports */
if ( ! read_interfaces ( ) )
{
PERROR_RUNTIME ( " No interfaces specified or failed to parse interface.conf. \n " ) ;
fprintf ( stderr , " No interfaces specified or failed to parse interface.conf. \n " ) ;
goto free ;
}
relink_interfaces ( ) ;
interface_first = interface_newlist ;
interface_newlist = NULL ;
/* locking memory paging */
i = 0 ;
while ( i < 10 )
{
if ( mlockall ( MCL_CURRENT | MCL_FUTURE ) > = 0 )
break ;
usleep ( 200000 ) ;
i + + ;
}
if ( i = = 10 )
{
switch ( errno )
{
case ENOMEM :
2009-01-06 17:34:05 +00:00
fprintf ( stderr , " Warning: Not enough memory to lock paging. \n " ) ;
2007-05-06 13:54:52 +00:00
break ;
case EPERM :
2009-01-06 17:34:05 +00:00
fprintf ( stderr , " Warning: No permission to lock paging. \n " ) ;
2007-05-06 13:54:52 +00:00
break ;
case EFAULT :
2009-01-06 17:34:05 +00:00
fprintf ( stderr , " Warning: 'Bad address' while locking paging. \n " ) ;
2007-05-06 13:54:52 +00:00
break ;
default :
2009-01-06 17:34:05 +00:00
fprintf ( stderr , " Warning: Unknown error %d while locking paging. \n " , errno ) ;
2007-05-06 13:54:52 +00:00
}
}
/* set real time scheduler & priority */
if ( options . schedule > 1 )
{
memset ( & schedp , 0 , sizeof ( schedp ) ) ;
schedp . sched_priority = options . schedule ;
ret = sched_setscheduler ( 0 , SCHED_RR , & schedp ) ;
if ( ret < 0 )
{
PERROR ( " Scheduling failed with given priority %d (errno = %d). \n Check options.conf 'schedule', exitting... \n " , options . schedule , errno ) ;
goto free ;
}
}
/* signal handlers */
signal ( SIGINT , sighandler ) ;
signal ( SIGHUP , sighandler ) ;
signal ( SIGTERM , sighandler ) ;
signal ( SIGPIPE , sighandler ) ;
created_signal = 1 ;
/*** main loop ***/
2007-07-08 09:24:26 +00:00
SPRINT ( tracetext , " %s %s started, waiting for calls... " , NAME , VERSION_STRING ) ;
2008-09-14 10:27:11 +00:00
start_trace ( - 1 , NULL , NULL , NULL , 0 , 0 , 0 , tracetext ) ;
2007-07-08 09:24:26 +00:00
printf ( " %s \n " , tracetext ) ;
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
GET_NOW ( ) ;
quit = 0 ;
while ( ! quit )
{
2008-04-12 16:24:31 +00:00
2007-08-24 10:04:34 +00:00
last_d = now_d ;
GET_NOW ( ) ;
if ( now_d - last_d > 1.0 )
{
PERROR ( " LCR was stalling %d.%d seconds \n " , ( ( int ) ( ( now_d - last_d ) * 10.0 ) ) / 10 , ( int ) ( ( now_d - last_d ) * 10.0 ) ) ;
}
2007-05-06 13:54:52 +00:00
/* all loops must be counted from the beginning since nodes might get freed during handler */
all_idle = 1 ;
2007-09-23 07:43:30 +00:00
//#warning debugging usleep crash
// debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
2007-08-11 08:12:10 +00:00
2007-05-06 13:54:52 +00:00
/* handle mISDN messages from kernel */
debug_prefix = " ISDN " ;
if ( mISDN_handler ( ) )
all_idle = 0 ;
2007-09-23 07:43:30 +00:00
//#warning debugging usleep crash
// debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
2007-08-11 08:12:10 +00:00
2007-05-06 13:54:52 +00:00
BUDETECT
/* loop through all port ports and call their handler */
port_again :
port = port_first ;
while ( port )
{
debug_prefix = port - > p_name ;
debug_count + + ;
ret = port - > handler ( ) ;
if ( ret )
all_idle = 0 ;
if ( ret < 0 ) /* port has been destroyed */
goto port_again ;
port = port - > next ;
}
/* loop through all epoint and call their handler */
epoint_again :
epoint = epoint_first ;
while ( epoint )
{
debug_prefix = prefix_string ;
SPRINT ( prefix_string , " ep%ld " , epoint - > ep_serial ) ;
debug_count + + ;
ret = epoint - > handler ( ) ;
if ( ret )
all_idle = 0 ;
if ( ret < 0 ) /* epoint has been destroyed */
goto epoint_again ;
epoint = epoint - > next ;
}
2007-07-17 17:28:09 +00:00
/* loop through all joins and call their handler */
join_again :
join = join_first ;
while ( join )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
debug_prefix = " join " ;
2007-05-06 13:54:52 +00:00
debug_count + + ;
2007-07-17 17:28:09 +00:00
ret = join - > handler ( ) ;
2007-05-06 13:54:52 +00:00
if ( ret )
all_idle = 0 ;
2007-07-17 17:28:09 +00:00
if ( ret < 0 ) /* join has been destroyed */
goto join_again ;
join = join - > next ;
2007-05-06 13:54:52 +00:00
}
debug_prefix = 0 ;
/* process any message */
debug_count + + ;
debug_prefix = " message " ;
while ( ( message = message_get ( ) ) )
{
all_idle = 0 ;
switch ( message - > flow )
{
case PORT_TO_EPOINT :
debug_prefix = " msg port->epoint " ;
epoint = find_epoint_id ( message - > id_to ) ;
if ( epoint )
{
if ( epoint - > ep_app )
{
epoint - > ep_app - > ea_message_port ( message - > id_from , message - > type , & message - > param ) ;
} else
{
PDEBUG ( DEBUG_MSG , " Warning: message %s from port %d to endpoint %d. endpoint doesn't have an application. \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
}
} else
{
PDEBUG ( DEBUG_MSG , " Warning: message %s from port %d to endpoint %d. endpoint doesn't exist anymore. \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
}
break ;
2007-07-17 17:28:09 +00:00
case EPOINT_TO_JOIN :
debug_prefix = " msg epoint->join " ;
join = find_join_id ( message - > id_to ) ;
if ( join )
2007-05-06 13:54:52 +00:00
{
2007-07-17 17:28:09 +00:00
join - > message_epoint ( message - > id_from , message - > type , & message - > param ) ;
2007-05-06 13:54:52 +00:00
} else
{
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_MSG , " Warning: message %s from endpoint %d to join %d. join doesn't exist anymore \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
2007-05-06 13:54:52 +00:00
}
break ;
2007-07-17 17:28:09 +00:00
case JOIN_TO_EPOINT :
debug_prefix = " msg join->epoint " ;
2007-05-06 13:54:52 +00:00
epoint = find_epoint_id ( message - > id_to ) ;
if ( epoint )
{
if ( epoint - > ep_app )
{
2007-07-17 17:28:09 +00:00
epoint - > ep_app - > ea_message_join ( message - > id_from , message - > type , & message - > param ) ;
2007-05-06 13:54:52 +00:00
} else
{
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_MSG , " Warning: message %s from join %d to endpoint %d. endpoint doesn't have an application. \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
2007-05-06 13:54:52 +00:00
}
} else
{
2007-07-17 17:28:09 +00:00
PDEBUG ( DEBUG_MSG , " Warning: message %s from join %d to endpoint %d. endpoint doesn't exist anymore. \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
2007-05-06 13:54:52 +00:00
}
break ;
case EPOINT_TO_PORT :
debug_prefix = " msg epoint->port " ;
port = find_port_id ( message - > id_to ) ;
if ( port )
{
port - > message_epoint ( message - > id_from , message - > type , & message - > param ) ;
BUDETECT
} else
{
PDEBUG ( DEBUG_MSG , " Warning: message %s from endpoint %d to port %d. port doesn't exist anymore \n " , messages_txt [ message - > type ] , message - > id_from , message - > id_to ) ;
}
break ;
default :
PERROR ( " Message flow %d unknown. \n " , message - > flow ) ;
}
message_free ( message ) ;
debug_count + + ;
debug_prefix = " message " ;
}
BUDETECT
/* handle socket */
if ( admin_handle ( ) )
all_idle = 0 ;
BUDETECT
2009-05-11 09:07:58 +00:00
# ifdef WITH_GSM
/* handle gsm */
if ( options . gsm )
while ( handle_gsm ( ) )
all_idle = 0 ;
# endif
BUDETECT
2007-05-06 13:54:52 +00:00
#if 0
/* check for child to exit (eliminate zombies) */
if ( waitpid ( - 1 , NULL , WNOHANG ) > 0 )
{
PDEBUG ( DEBUG_EPOINT , " a child process (created by endpoint) has exitted. \n " ) ;
all_idle = 0 ;
}
# endif
2007-09-23 07:43:30 +00:00
//#warning debugging usleep crash
// debug_usleep(1, __FILE__, __LINE__, now_tm->tm_hour, now_tm->tm_min, now_tm->tm_sec);
2007-05-06 13:54:52 +00:00
/* do idle checking */
if ( idlecheck ! = now )
{
PDEBUG ( DEBUG_IDLETIME , " Idle time : %d%% \n " , idletime / 10000 ) ;
idletime = 0 ;
idlecheck = now ;
}
/* did we do nothing? so we wait to give time to other processes */
if ( all_idle )
{
2008-04-24 17:35:55 +00:00
// pthread_mutex_unlock(&mutex_lcr); // unlock LCR
2007-08-11 08:12:10 +00:00
debug_usleep ( 4000 , __FILE__ , __LINE__ , now_tm - > tm_hour , now_tm - > tm_min , now_tm - > tm_sec ) ;
2008-04-24 17:35:55 +00:00
// pthread_mutex_lock(&mutex_lcr); // lock LCR
2007-05-06 13:54:52 +00:00
idletime + = 4000 ;
}
}
2007-07-17 17:28:09 +00:00
SPRINT ( tracetext , " %s terminated " , NAME ) ;
printf ( " %s \n " , tracetext ) ;
2008-09-14 10:27:11 +00:00
start_trace ( - 1 , NULL , NULL , NULL , 0 , 0 , 0 , tracetext ) ;
2008-05-02 19:40:31 +00:00
if ( quit )
2008-09-02 00:02:11 +00:00
add_trace ( ( char * ) " signal " , NULL , " %d " , quit ) ;
2007-07-17 17:28:09 +00:00
end_trace ( ) ;
2007-05-06 13:54:52 +00:00
ret = 0 ;
/* free all */
free :
/* set scheduler & priority
*/
if ( options . schedule > 1 )
{
memset ( & schedp , 0 , sizeof ( schedp ) ) ;
2008-01-05 21:58:22 +00:00
schedp . sched_priority = options . schedule ;
2007-05-06 13:54:52 +00:00
sched_setscheduler ( 0 , SCHED_OTHER , & schedp ) ;
}
/* reset signals */
if ( created_signal )
{
signal ( SIGINT , SIG_DFL ) ;
signal ( SIGHUP , SIG_DFL ) ;
signal ( SIGTERM , SIG_DFL ) ;
signal ( SIGPIPE , SIG_DFL ) ;
}
/* destroy objects */
debug_prefix = " free " ;
while ( port_first )
{
debug_count + + ;
delete port_first ;
}
while ( epoint_first )
{
debug_count + + ;
delete epoint_first ;
}
epoint_first = NULL ;
debug_count + + ;
2007-07-17 17:28:09 +00:00
join_free ( ) ;
2007-05-06 13:54:52 +00:00
/* free interfaces */
if ( interface_first )
free_interfaces ( interface_first ) ;
interface_first = NULL ;
/* close isdn ports */
mISDNport_close_all ( ) ;
/* flush messages */
debug_count + + ;
i = 0 ;
while ( ( message = message_get ( ) ) )
{
i + + ;
message_free ( message ) ;
}
if ( i )
{
PDEBUG ( DEBUG_MSG , " freed %d pending messages \n " , i ) ;
}
/* free tones */
if ( toneset_first )
free_tones ( ) ;
/* free admin socket */
admin_cleanup ( ) ;
/* close lock */
if ( created_lock )
flock ( lockfd , LOCK_UN ) ;
if ( lockfd > = 0 )
2008-08-30 06:24:52 +00:00
{
chmod ( lock , 0700 ) ;
unlink ( lock ) ;
2007-05-06 13:54:52 +00:00
close ( lockfd ) ;
2008-08-30 06:24:52 +00:00
}
2007-05-06 13:54:52 +00:00
/* free rulesets */
if ( ruleset_first )
ruleset_free ( ruleset_first ) ;
ruleset_first = NULL ;
/* free mutex */
if ( created_mutexe )
if ( pthread_mutex_destroy ( & mutexe ) )
fprintf ( stderr , " cannot destroy 'PERROR' mutex \n " ) ;
2007-06-27 06:23:50 +00:00
// if (created_mutext)
// if (pthread_mutex_destroy(&mutext))
// fprintf(stderr, "cannot destroy 'trace' mutex\n");
2007-05-06 13:54:52 +00:00
if ( created_mutexd )
if ( pthread_mutex_destroy ( & mutexd ) )
fprintf ( stderr , " cannot destroy 'PDEBUG' mutex \n " ) ;
2007-07-31 05:34:18 +00:00
/* deinitialize mISDN */
2008-05-02 19:19:06 +00:00
if ( created_misdn )
mISDN_deinitialize ( ) ;
2007-05-06 13:54:52 +00:00
2009-05-11 09:07:58 +00:00
# ifdef WITH_GSM
/* free gsm */
if ( options . gsm )
gsm_exit ( 0 ) ;
# endif
2007-05-06 13:54:52 +00:00
/* display memory leak */
# define MEMCHECK(a, b) \
if ( b ) \
{ \
2007-07-08 09:24:26 +00:00
SPRINT ( tracetext , a , NAME ) ; \
2008-09-14 10:27:11 +00:00
start_trace ( - 1 , NULL , NULL , NULL , 0 , 0 , 0 , tracetext ) ; \
2007-07-08 09:24:26 +00:00
if ( ret ) add_trace ( " blocks " , NULL , " %d " , b ) ; \
end_trace ( ) ; \
2007-05-06 13:54:52 +00:00
printf ( " \n ****************************** \n \007 " ) ; \
printf ( " \n ERROR: %d %s \n " , b , a ) ; \
printf ( " \n ****************************** \n " ) ; \
ret = - 1 ; \
}
MEMCHECK ( " " , memuse )
2007-07-17 17:28:09 +00:00
MEMCHECK ( " memory block(s) left (port.cpp ...) " , pmemuse )
MEMCHECK ( " memory block(s) left (epoint*.cpp ...) " , ememuse )
MEMCHECK ( " memory block(s) left (join*.cpp) " , cmemuse )
2007-05-06 13:54:52 +00:00
MEMCHECK ( " memory block(s) left (message.c) " , mmemuse )
MEMCHECK ( " memory block(s) left (route.c) " , rmemuse )
MEMCHECK ( " memory block(s) left (args) " , amemuse )
MEMCHECK ( " class(es) left " , classuse )
MEMCHECK ( " file descriptor(s) left " , fduse )
MEMCHECK ( " file handler(s) left " , fhuse )
2008-04-12 16:24:31 +00:00
/* unlock LCR process */
2008-04-24 17:35:55 +00:00
// pthread_mutex_unlock(&mutex_lcr);
2008-04-12 16:24:31 +00:00
2007-05-06 13:54:52 +00:00
/* take me out */
return ( ret ) ;
}
# ifdef BUDETECT_DEF
/* special debug function to detect buffer overflow
*/
int budetect_stop = 0 ;
2008-09-02 00:02:11 +00:00
void budetect ( const char * file , int line , const char * function )
2007-05-06 13:54:52 +00:00
{
if ( budetect_stop )
return ;
/* modify this function to detect race-bugs */
# warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
class Port * port ;
class PmISDN * pmisdn ;
struct mISDNport * mISDNport = mISDNport_first ;
int i , ii ;
while ( mISDNport )
{
i = 0 ;
ii = mISDNport - > b_num ;
while ( i < ii )
{
if ( mISDNport - > b_port [ i ] )
{
port = port_first ;
while ( port )
{
if ( ( port - > p_type & PORT_CLASS_MASK ) = = PORT_CLASS_ISDN )
{
pmisdn = ( class PmISDN * ) port ;
if ( pmisdn - > p_isdn_crypt_listen )
{
PERROR_RUNTIME ( " ************************************************ \n " ) ;
PERROR_RUNTIME ( " ** BUG detected in %s, line %d, function %s \n " , file , line , function ) ;
PERROR_RUNTIME ( " ** p_isdn_crypt_listen = %d \n " , pmisdn - > p_isdn_crypt_listen ) ;
PERROR_RUNTIME ( " ************************************************ \n " ) ;
budetect_stop = 1 ;
}
}
if ( port = = mISDNport - > b_port [ i ] )
break ;
port = port - > next ;
if ( ! port )
{
PERROR_RUNTIME ( " ************************************************ \n " ) ;
PERROR_RUNTIME ( " ** BUG detected in %s, line %d, function %s \n " , file , line , function ) ;
PERROR_RUNTIME ( " ** b_port not in list. \n " ) ;
PERROR_RUNTIME ( " ************************************************ \n " ) ;
budetect_stop = 1 ;
}
}
}
i + + ;
}
mISDNport = mISDNport - > next ;
}
}
# endif