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 mutexl; // log 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')
108 void printlog(const char *fmt, ...)
114 pthread_mutex_lock(&mutexl);
117 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
118 buffer[sizeof(buffer)-1]=0;
123 if (options.deb & DEBUG_LOG)
124 debug(NULL, 0, "LOG ->", buffer);
126 if ((fp = fopen(options.log, "a")))
129 fprintf(fp, "%04d.%02d.%02d %02d:%02d:%02d %s", 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, buffer);
135 pthread_mutex_unlock(&mutexl);
138 void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...)
143 if (!(options.deb & mask))
145 pthread_mutex_lock(&mutexd);
148 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
149 buffer[sizeof(buffer)-1]=0;
152 debug(function, line, debug_prefix, buffer);
154 pthread_mutex_unlock(&mutexd);
157 void _printerror(const char *function, int line, const char *fmt, ...)
162 pthread_mutex_lock(&mutexe);
165 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
166 buffer[sizeof(buffer)-1]=0;
170 debug(function, line, "ERROR", buffer);
171 else /* only if we do not debug */
174 fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
176 fprintf(stderr, "ERROR %s", buffer);
179 pthread_mutex_unlock(&mutexe);
183 void sighandler(int sigset)
185 struct sched_param schedp;
187 if (sigset == SIGHUP)
189 if (sigset == SIGPIPE)
194 /* set scheduler & priority */
195 if (options.schedule > 1)
197 memset(&schedp, 0, sizeof(schedp));
198 schedp.sched_priority = 0;
199 sched_setscheduler(0, SCHED_OTHER, &schedp);
201 fprintf(stderr, "PBX: Signal received: %d\n", sigset);
202 PERROR("Signal received: %d\n", sigset);
211 #define ARGC (args.GetCount()+1)
212 #define ARGV(a) (args[a-1])
213 void PBXMain::Main(void)
215 PArgList &args = GetArguments();
218 #define ARGV(a) (argv[a])
219 int main(int argc, char *argv[])
223 int lockfd = -1; /* file lock */
224 struct message *message;
226 class Endpoint *epoint;
230 char prefix_string[64];
231 struct sched_param schedp;
232 char *debug_prefix = "alloc";
233 int created_mutexd = 0, created_mutexl = 0, created_mutexe = 0,
234 created_lock = 0, created_signal = 0, created_debug = 0;
235 #ifdef DEBUG_DURATION
236 time_t durationupdate;
237 double idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
240 int idletime = 0, idlecheck = 0;
247 printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
254 printf("Usage: pbx (query | start | fork | rules | route)\n");
255 printf("query = Show available isdn ports.\n");
256 printf("start = Run pbx normally, abort with CTRL+C.\n");
257 printf("fork = Do daemon fork and run as background process.\n");
258 printf("interface = Get help of available interface syntax.\n");
259 printf("rules = Get help of available routing rule syntax.\n");
260 printf("rules [action] = Get individual help for given action.\n");
261 // printf("route = Show current routing as it is parsed.\n");
270 /* check for root (real or effective) */
271 if (getuid() && geteuid())
273 fprintf(stderr, "Please run %s as super-user.\n", NAME);
278 if (pthread_mutex_init(&mutexd, NULL))
280 fprintf(stderr, "cannot create 'PDEBUG' mutex\n");
284 if (pthread_mutex_init(&mutexl, NULL))
286 fprintf(stderr, "cannot create 'printlog' mutex\n");
290 if (pthread_mutex_init(&mutexe, NULL))
292 fprintf(stderr, "cannot create 'PERROR' mutex\n");
298 if (!(strcasecmp(ARGV(1),"interface")))
306 if (!(strcasecmp(ARGV(1),"rules")))
316 /* query available isdn ports */
317 if (!(strcasecmp(ARGV(1),"query")))
325 if (read_options() == 0)
328 /* initialize stuff of the NT lib */
329 if (options.deb & DEBUG_STACK)
331 global_debug = 0xffffffff & ~DBGM_MSG;
332 // global_debug = DBGM_L3DATA;
334 global_debug = DBGM_MAN;
335 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
336 if (options.deb & DEBUG_LOG)
337 debug_init(global_debug, debug_log, debug_log, debug_log);
339 debug_init(global_debug, NULL, NULL, NULL);
344 /* read ruleset(s) */
345 if (!(ruleset_first = ruleset_parse()))
348 /* set pointer to main ruleset */
349 ruleset_main = getrulesetbyname("main");
352 fprintf(stderr, "\n***\n -> Missing 'main' ruleset, causing ALL calls to be disconnected.\n***\n\n");
353 PDEBUG(DEBUG_LOG, "Missing 'main' ruleset, causing ALL calls to be disconnected.\n");
358 /* query available isdn ports */
359 if (!(strcasecmp(ARGV(1),"route")))
361 ruleset_debug(ruleset_first);
367 /* do fork in special cases */
368 if (!(strcasecmp(ARGV(1),"fork")))
377 fprintf(stderr, "Cannot fork!\n");
392 fprintf(stderr, "Cannot fork!\n");
397 printf("PBX: Starting daemon.\n");
403 if (!!strcasecmp(ARGV(1),"start"))
408 /* create lock and lock! */
409 if ((lockfd = open("/var/run/pbx.lock", O_CREAT, 0)) < 0)
411 fprintf(stderr, "Cannot create lock file: /var/run/pbx.lock\n");
414 if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
416 if (errno == EWOULDBLOCK)
417 fprintf(stderr, "PBX: Another PBX process is running. Please kill the other one.\n");
418 else fprintf(stderr, "Locking process failed: errno=%d\n", errno);
423 /* initialize admin socket */
426 fprintf(stderr, "Unable to initialize admin socket.\n");
430 /* generate alaw / ulaw tables */
431 generate_tables(options.law);
433 /* load tones (if requested) */
434 if (fetch_tones() == 0)
436 fprintf(stderr, "Unable to fetch tones into memory.\n");
440 /* read interfaces and open ports */
441 if (!read_interfaces())
443 PERROR_RUNTIME("No interfaces specified or failed to parse interface.conf.\n");
444 fprintf(stderr, "No interfaces specified or failed to parse interface.conf.\n");
448 interface_first = interface_newlist;
449 free_interfaces(interface_newlist);
450 interface_newlist = NULL;
452 /* locking memory paging */
456 if (mlockall(MCL_CURRENT | MCL_FUTURE) >= 0)
466 fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
469 fprintf(stderr, "No permission to lock paging, exitting...\n");
472 fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
475 fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
480 /* set real time scheduler & priority */
481 if (options.schedule > 1)
483 memset(&schedp, 0, sizeof(schedp));
484 schedp.sched_priority = options.schedule;
485 ret = sched_setscheduler(0, SCHED_RR, &schedp);
488 PERROR("Scheduling failed with given priority %d (errno = %d).\nCheck options.conf 'schedule', exitting...\n", options.schedule, errno);
493 /* signal handlers */
494 signal(SIGINT,sighandler);
495 signal(SIGHUP,sighandler);
496 signal(SIGTERM,sighandler);
497 signal(SIGPIPE,sighandler);
501 printf("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
502 printlog("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
504 #ifdef DEBUG_DURATION
506 durationupdate = now;
507 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
512 /* all loops must be counted from the beginning since nodes might get freed during handler */
515 /* handle mISDN messages from kernel */
516 debug_prefix = "ISDN";
519 #ifdef DEBUG_DURATION
521 isdn_duration += (now_d - start_d);
526 /* loop through all port ports and call their handler */
531 debug_prefix = port->p_name;
533 ret = port->handler();
536 if (ret < 0) /* port has been destroyed */
540 #ifdef DEBUG_DURATION
542 port_duration += (now_d - start_d);
546 /* loop through all epoint and call their handler */
548 epoint = epoint_first;
551 debug_prefix = prefix_string;
552 SPRINT(prefix_string, "ep%ld", epoint->ep_serial);
554 ret = epoint->handler();
557 if (ret < 0) /* epoint has been destroyed */
559 epoint = epoint->next;
561 #ifdef DEBUG_DURATION
563 epoint_duration += (now_d - start_d);
567 /* loop through all calls and call their handler */
572 debug_prefix = "call";
574 ret = call->handler();
577 if (ret < 0) /* call has been destroyed */
581 #ifdef DEBUG_DURATION
583 call_duration += (now_d - start_d);
589 /* process any message */
591 debug_prefix = "message";
592 while ((message = message_get()))
595 switch(message->flow)
598 debug_prefix = "msg port->epoint";
599 epoint = find_epoint_id(message->id_to);
604 epoint->ep_app->ea_message_port(message->id_from, message->type, &message->param);
607 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);
611 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);
616 debug_prefix = "msg epoint->call";
617 call = find_call_id(message->id_to);
620 call->message_epoint(message->id_from, message->type, &message->param);
623 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);
628 debug_prefix = "msg call->epoint";
629 epoint = find_epoint_id(message->id_to);
634 epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
637 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);
641 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);
646 debug_prefix = "msg epoint->port";
647 port = find_port_id(message->id_to);
650 port->message_epoint(message->id_from, message->type, &message->param);
654 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);
659 PERROR("Message flow %d unknown.\n", message->flow);
661 message_free(message);
663 debug_prefix = "message";
665 #ifdef DEBUG_DURATION
667 message_duration += (now_d - start_d);
675 #ifdef DEBUG_DURATION
677 admin_duration += (now_d - start_d);
683 /* check for child to exit (eliminate zombies) */
684 if (waitpid(-1, NULL, WNOHANG) > 0)
686 PDEBUG(DEBUG_EPOINT, "a child process (created by endpoint) has exitted.\n");
691 /* do idle checking */
692 if (idlecheck != now)
694 PDEBUG(DEBUG_IDLETIME, "Idle time : %d%%\n", idletime/10000);
698 #ifdef DEBUG_DURATION
700 idle_duration += (now_d - start_d);
702 if (durationupdate != now)
704 durationupdate = now;
705 printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
706 (int)(idle_duration*100),
707 (int)(isdn_duration*100),
708 (int)(port_duration*100),
709 (int)(epoint_duration*100),
710 (int)(call_duration*100),
711 (int)(message_duration*100),
712 (int)(admin_duration*100));
713 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
719 /* did we do nothing? so we wait to give time to other processes */
722 usleep(4000); /* wait 32 samples */
726 printlog("PBX terminated\n");
733 /* set scheduler & priority
735 if (options.schedule > 1)
737 memset(&schedp, 0, sizeof(schedp));
738 schedp.sched_priority = 0;
739 sched_setscheduler(0, SCHED_OTHER, &schedp);
744 signal(SIGINT,SIG_DFL);
745 signal(SIGHUP,SIG_DFL);
746 signal(SIGTERM,SIG_DFL);
747 signal(SIGPIPE,SIG_DFL);
750 /* destroy objects */
751 debug_prefix = "free";
767 /* free interfaces */
769 free_interfaces(interface_first);
770 interface_first = NULL;
772 /* close isdn ports */
773 mISDNport_close_all();
778 while ((message = message_get()))
781 message_free(message);
785 PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
792 /* free admin socket */
797 flock(lockfd, LOCK_UN);
803 ruleset_free(ruleset_first);
804 ruleset_first = NULL;
808 if (pthread_mutex_destroy(&mutexe))
809 fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
811 if (pthread_mutex_destroy(&mutexl))
812 fprintf(stderr, "cannot destroy 'printlog' mutex\n");
814 if (pthread_mutex_destroy(&mutexd))
815 fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
822 /* display memory leak */
823 #define MEMCHECK(a, b) \
826 printf("\n******************************\n\007"); \
827 printf("\nERROR: %d %s\n", b, a); \
828 printf("\n******************************\n"); \
832 MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
833 MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
834 MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
835 MEMCHECK("memory block(s) left (message.c)",mmemuse)
836 MEMCHECK("memory block(s) left (route.c)",rmemuse)
837 MEMCHECK("memory block(s) left (args)",amemuse)
838 MEMCHECK("class(es) left",classuse)
839 MEMCHECK("file descriptor(s) left",fduse)
840 MEMCHECK("file handler(s) left",fhuse)
844 printf("PBX: Exit (code %d)\n", ret);
854 /* special debug function to detect buffer overflow
856 int budetect_stop = 0;
857 void budetect(const char *file, int line, char *function)
861 /* modify this function to detect race-bugs */
862 #warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
864 class PmISDN *pmisdn;
865 struct mISDNport *mISDNport = mISDNport_first;
871 ii = mISDNport->b_num;
874 if (mISDNport->b_port[i])
879 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_ISDN)
881 pmisdn = (class PmISDN *)port;
882 if (pmisdn->p_isdn_crypt_listen)
884 PERROR_RUNTIME("************************************************\n");
885 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
886 PERROR_RUNTIME("** p_isdn_crypt_listen = %d\n", pmisdn->p_isdn_crypt_listen);
887 PERROR_RUNTIME("************************************************\n");
891 if (port == mISDNport->b_port[i])
896 PERROR_RUNTIME("************************************************\n");
897 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
898 PERROR_RUNTIME("** b_port not in list.\n");
899 PERROR_RUNTIME("************************************************\n");
906 mISDNport = mISDNport->next;