1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
10 \*****************************************************************************/
15 #include <sys/types.h>
22 #include <sys/ioctl.h>
26 #include <sys/resource.h>
34 struct timeval now_tv;
35 struct timezone now_tz;
38 gettimeofday(&now_tv, &now_tz); \
39 now_d = ((double)(now_tv.tv_usec))/1000000 + now_tv.tv_sec; \
40 now = now_tv.tv_sec; \
41 now_tm = localtime(&now); \
43 //#define DEBUG_DURATION
48 pthread_mutex_t mutexd; // debug output mutex
49 //pthread_mutex_t mutext; // trace output mutex
50 pthread_mutex_t mutexe; // error output mutex
63 char *debug_prefix = 0;
66 int debug_newline = 1;
69 static void debug(const char *function, int line, char *prefix, char *buffer)
71 /* if we have a new debug count, we add a mark */
72 if (last_debug != debug_count)
74 last_debug = debug_count;
76 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);
77 if (options.deb&DEBUG_LOG && global_debug)
78 dprint(DBGM_MAN, 0, "--------------------- %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);
84 printf("\033[32m%06d %s\033[37m%s", debug_count%1000000, prefix?prefix:"", prefix?" ":"");
86 printf("(in %s() line %d): %s", function, line, buffer);
91 if (options.deb&DEBUG_LOG && global_debug)
96 dprint(DBGM_MAN, 0, "%s%s(in %s() line %d): %s", prefix?prefix:"", prefix?" ":"", function, line, buffer);
98 dprint(DBGM_MAN, 0, "%s%s: %s", prefix?prefix:"", prefix?" ":"", buffer);
104 if (buffer[strlen(buffer)-1] == '\n')
109 void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...)
114 if (!(options.deb & mask))
116 pthread_mutex_lock(&mutexd);
119 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
120 buffer[sizeof(buffer)-1]=0;
123 debug(function, line, debug_prefix, buffer);
125 pthread_mutex_unlock(&mutexd);
128 void _printerror(const char *function, int line, const char *fmt, ...)
133 pthread_mutex_lock(&mutexe);
136 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
137 buffer[sizeof(buffer)-1]=0;
141 debug(function, line, "ERROR", buffer);
142 else /* only if we do not debug */
145 fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
147 fprintf(stderr, "ERROR %s", buffer);
150 pthread_mutex_unlock(&mutexe);
154 void sighandler(int sigset)
156 struct sched_param schedp;
158 if (sigset == SIGHUP)
160 if (sigset == SIGPIPE)
165 /* set scheduler & priority */
166 if (options.schedule > 1)
168 memset(&schedp, 0, sizeof(schedp));
169 schedp.sched_priority = 0;
170 sched_setscheduler(0, SCHED_OTHER, &schedp);
172 fprintf(stderr, "PBX: Signal received: %d\n", sigset);
173 PERROR("Signal received: %d\n", sigset);
182 #define ARGC (args.GetCount()+1)
183 #define ARGV(a) (args[a-1])
184 void PBXMain::Main(void)
186 PArgList &args = GetArguments();
189 #define ARGV(a) (argv[a])
190 int main(int argc, char *argv[])
194 int lockfd = -1; /* file lock */
195 struct message *message;
197 class Endpoint *epoint;
201 char prefix_string[64];
202 struct sched_param schedp;
203 char *debug_prefix = "alloc";
204 int created_mutexd = 0,/* created_mutext = 0,*/ created_mutexe = 0,
205 created_lock = 0, created_signal = 0, created_debug = 0;
206 #ifdef DEBUG_DURATION
207 time_t durationupdate;
208 double idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
211 int idletime = 0, idlecheck = 0;
218 printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
225 printf("Usage: pbx (query | start | fork | rules | route)\n");
226 printf("query = Show available isdn ports.\n");
227 printf("start = Run pbx normally, abort with CTRL+C.\n");
228 printf("fork = Do daemon fork and run as background process.\n");
229 printf("interface = Get help of available interface syntax.\n");
230 printf("rules = Get help of available routing rule syntax.\n");
231 printf("rules [action] = Get individual help for given action.\n");
232 // printf("route = Show current routing as it is parsed.\n");
241 /* check for root (real or effective) */
242 if (getuid() && geteuid())
244 fprintf(stderr, "Please run %s as super-user.\n", NAME);
249 if (pthread_mutex_init(&mutexd, NULL))
251 fprintf(stderr, "cannot create 'PDEBUG' mutex\n");
255 // if (pthread_mutex_init(&mutext, NULL))
257 // fprintf(stderr, "cannot create 'trace' mutex\n");
260 // created_mutext = 1;
261 if (pthread_mutex_init(&mutexe, NULL))
263 fprintf(stderr, "cannot create 'PERROR' mutex\n");
269 if (!(strcasecmp(ARGV(1),"interface")))
277 if (!(strcasecmp(ARGV(1),"rules")))
287 /* query available isdn ports */
288 if (!(strcasecmp(ARGV(1),"query")))
296 if (read_options() == 0)
299 /* initialize stuff of the NT lib */
300 if (options.deb & DEBUG_STACK)
302 global_debug = 0xffffffff & ~DBGM_MSG;
303 // global_debug = DBGM_L3DATA;
305 global_debug = DBGM_MAN;
306 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
307 if (options.deb & DEBUG_LOG)
308 debug_init(global_debug, debug_log, debug_log, debug_log);
310 debug_init(global_debug, NULL, NULL, NULL);
315 /* read ruleset(s) */
316 if (!(ruleset_first = ruleset_parse()))
319 /* set pointer to main ruleset */
320 ruleset_main = getrulesetbyname("main");
323 fprintf(stderr, "\n***\n -> Missing 'main' ruleset, causing ALL calls to be disconnected.\n***\n\n");
324 PDEBUG(DEBUG_LOG, "Missing 'main' ruleset, causing ALL calls to be disconnected.\n");
329 /* query available isdn ports */
330 if (!(strcasecmp(ARGV(1),"route")))
332 ruleset_debug(ruleset_first);
338 /* do fork in special cases */
339 if (!(strcasecmp(ARGV(1),"fork")))
348 fprintf(stderr, "Cannot fork!\n");
363 fprintf(stderr, "Cannot fork!\n");
368 printf("PBX: Starting daemon.\n");
374 if (!!strcasecmp(ARGV(1),"start"))
379 /* create lock and lock! */
380 if ((lockfd = open("/var/run/pbx.lock", O_CREAT, 0)) < 0)
382 fprintf(stderr, "Cannot create lock file: /var/run/pbx.lock\n");
385 if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
387 if (errno == EWOULDBLOCK)
388 fprintf(stderr, "PBX: Another PBX process is running. Please kill the other one.\n");
389 else fprintf(stderr, "Locking process failed: errno=%d\n", errno);
394 /* initialize admin socket */
397 fprintf(stderr, "Unable to initialize admin socket.\n");
401 /* generate alaw / ulaw tables */
402 generate_tables(options.law);
404 /* load tones (if requested) */
405 if (fetch_tones() == 0)
407 fprintf(stderr, "Unable to fetch tones into memory.\n");
411 /* read interfaces and open ports */
412 if (!read_interfaces())
414 PERROR_RUNTIME("No interfaces specified or failed to parse interface.conf.\n");
415 fprintf(stderr, "No interfaces specified or failed to parse interface.conf.\n");
419 interface_first = interface_newlist;
420 free_interfaces(interface_newlist);
421 interface_newlist = NULL;
423 /* locking memory paging */
427 if (mlockall(MCL_CURRENT | MCL_FUTURE) >= 0)
437 fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
440 fprintf(stderr, "No permission to lock paging, exitting...\n");
443 fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
446 fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
451 /* set real time scheduler & priority */
452 if (options.schedule > 1)
454 memset(&schedp, 0, sizeof(schedp));
455 schedp.sched_priority = options.schedule;
456 ret = sched_setscheduler(0, SCHED_RR, &schedp);
459 PERROR("Scheduling failed with given priority %d (errno = %d).\nCheck options.conf 'schedule', exitting...\n", options.schedule, errno);
464 /* signal handlers */
465 signal(SIGINT,sighandler);
466 signal(SIGHUP,sighandler);
467 signal(SIGTERM,sighandler);
468 signal(SIGPIPE,sighandler);
472 printf("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
474 #ifdef DEBUG_DURATION
476 durationupdate = now;
477 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
482 /* all loops must be counted from the beginning since nodes might get freed during handler */
485 /* handle mISDN messages from kernel */
486 debug_prefix = "ISDN";
489 #ifdef DEBUG_DURATION
491 isdn_duration += (now_d - start_d);
496 /* loop through all port ports and call their handler */
501 debug_prefix = port->p_name;
503 ret = port->handler();
506 if (ret < 0) /* port has been destroyed */
510 #ifdef DEBUG_DURATION
512 port_duration += (now_d - start_d);
516 /* loop through all epoint and call their handler */
518 epoint = epoint_first;
521 debug_prefix = prefix_string;
522 SPRINT(prefix_string, "ep%ld", epoint->ep_serial);
524 ret = epoint->handler();
527 if (ret < 0) /* epoint has been destroyed */
529 epoint = epoint->next;
531 #ifdef DEBUG_DURATION
533 epoint_duration += (now_d - start_d);
537 /* loop through all calls and call their handler */
542 debug_prefix = "call";
544 ret = call->handler();
547 if (ret < 0) /* call has been destroyed */
551 #ifdef DEBUG_DURATION
553 call_duration += (now_d - start_d);
559 /* process any message */
561 debug_prefix = "message";
562 while ((message = message_get()))
565 switch(message->flow)
568 debug_prefix = "msg port->epoint";
569 epoint = find_epoint_id(message->id_to);
574 epoint->ep_app->ea_message_port(message->id_from, message->type, &message->param);
577 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);
581 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);
586 debug_prefix = "msg epoint->call";
587 call = find_call_id(message->id_to);
590 call->message_epoint(message->id_from, message->type, &message->param);
593 PDEBUG(DEBUG_MSG, "Warning: message %s from endpoint %d to call %d. call doesn't exist anymore\n", messages_txt[message->type], message->id_from, message->id_to);
598 debug_prefix = "msg call->epoint";
599 epoint = find_epoint_id(message->id_to);
604 epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
607 PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't have an application.\n", messages_txt[message->type], message->id_from, message->id_to);
611 PDEBUG(DEBUG_MSG, "Warning: message %s from call %d to endpoint %d. endpoint doesn't exist anymore.\n", messages_txt[message->type], message->id_from, message->id_to);
616 debug_prefix = "msg epoint->port";
617 port = find_port_id(message->id_to);
620 port->message_epoint(message->id_from, message->type, &message->param);
624 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);
629 PERROR("Message flow %d unknown.\n", message->flow);
631 message_free(message);
633 debug_prefix = "message";
635 #ifdef DEBUG_DURATION
637 message_duration += (now_d - start_d);
645 #ifdef DEBUG_DURATION
647 admin_duration += (now_d - start_d);
653 /* check for child to exit (eliminate zombies) */
654 if (waitpid(-1, NULL, WNOHANG) > 0)
656 PDEBUG(DEBUG_EPOINT, "a child process (created by endpoint) has exitted.\n");
661 /* do idle checking */
662 if (idlecheck != now)
664 PDEBUG(DEBUG_IDLETIME, "Idle time : %d%%\n", idletime/10000);
668 #ifdef DEBUG_DURATION
670 idle_duration += (now_d - start_d);
672 if (durationupdate != now)
674 durationupdate = now;
675 printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
676 (int)(idle_duration*100),
677 (int)(isdn_duration*100),
678 (int)(port_duration*100),
679 (int)(epoint_duration*100),
680 (int)(call_duration*100),
681 (int)(message_duration*100),
682 (int)(admin_duration*100));
683 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
689 /* did we do nothing? so we wait to give time to other processes */
692 usleep(4000); /* wait 32 samples */
696 printf("PBX terminated\n");
703 /* set scheduler & priority
705 if (options.schedule > 1)
707 memset(&schedp, 0, sizeof(schedp));
708 schedp.sched_priority = 0;
709 sched_setscheduler(0, SCHED_OTHER, &schedp);
714 signal(SIGINT,SIG_DFL);
715 signal(SIGHUP,SIG_DFL);
716 signal(SIGTERM,SIG_DFL);
717 signal(SIGPIPE,SIG_DFL);
720 /* destroy objects */
721 debug_prefix = "free";
737 /* free interfaces */
739 free_interfaces(interface_first);
740 interface_first = NULL;
742 /* close isdn ports */
743 mISDNport_close_all();
748 while ((message = message_get()))
751 message_free(message);
755 PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
762 /* free admin socket */
767 flock(lockfd, LOCK_UN);
773 ruleset_free(ruleset_first);
774 ruleset_first = NULL;
778 if (pthread_mutex_destroy(&mutexe))
779 fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
780 // if (created_mutext)
781 // if (pthread_mutex_destroy(&mutext))
782 // fprintf(stderr, "cannot destroy 'trace' mutex\n");
784 if (pthread_mutex_destroy(&mutexd))
785 fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
792 /* display memory leak */
793 #define MEMCHECK(a, b) \
796 printf("\n******************************\n\007"); \
797 printf("\nERROR: %d %s\n", b, a); \
798 printf("\n******************************\n"); \
802 MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
803 MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
804 MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
805 MEMCHECK("memory block(s) left (message.c)",mmemuse)
806 MEMCHECK("memory block(s) left (route.c)",rmemuse)
807 MEMCHECK("memory block(s) left (args)",amemuse)
808 MEMCHECK("class(es) left",classuse)
809 MEMCHECK("file descriptor(s) left",fduse)
810 MEMCHECK("file handler(s) left",fhuse)
814 printf("PBX: Exit (code %d)\n", ret);
824 /* special debug function to detect buffer overflow
826 int budetect_stop = 0;
827 void budetect(const char *file, int line, char *function)
831 /* modify this function to detect race-bugs */
832 #warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
834 class PmISDN *pmisdn;
835 struct mISDNport *mISDNport = mISDNport_first;
841 ii = mISDNport->b_num;
844 if (mISDNport->b_port[i])
849 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_ISDN)
851 pmisdn = (class PmISDN *)port;
852 if (pmisdn->p_isdn_crypt_listen)
854 PERROR_RUNTIME("************************************************\n");
855 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
856 PERROR_RUNTIME("** p_isdn_crypt_listen = %d\n", pmisdn->p_isdn_crypt_listen);
857 PERROR_RUNTIME("************************************************\n");
861 if (port == mISDNport->b_port[i])
866 PERROR_RUNTIME("************************************************\n");
867 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
868 PERROR_RUNTIME("** b_port not in list.\n");
869 PERROR_RUNTIME("************************************************\n");
876 mISDNport = mISDNport->next;