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')
109 void printlog(const char *fmt, ...)
115 pthread_mutex_lock(&mutexl);
118 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
119 buffer[sizeof(buffer)-1]=0;
124 if (options.deb & DEBUG_LOG)
125 debug(NULL, 0, "LOG ->", buffer);
127 if ((fp = fopen(options.log, "a")))
130 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);
136 pthread_mutex_unlock(&mutexl);
139 void _printdebug(const char *function, int line, unsigned long mask, const char *fmt, ...)
144 if (!(options.deb & mask))
146 pthread_mutex_lock(&mutexd);
149 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
150 buffer[sizeof(buffer)-1]=0;
153 debug(function, line, debug_prefix, buffer);
155 pthread_mutex_unlock(&mutexd);
158 void _printerror(const char *function, int line, const char *fmt, ...)
163 pthread_mutex_lock(&mutexe);
166 VUNPRINT(buffer,sizeof(buffer)-1,fmt,args);
167 buffer[sizeof(buffer)-1]=0;
171 debug(function, line, "ERROR", buffer);
172 else /* only if we do not debug */
175 fprintf(stderr, "ERROR (in %s() line %d) %s", function, line, buffer);
177 fprintf(stderr, "ERROR %s", buffer);
180 pthread_mutex_unlock(&mutexe);
184 void sighandler(int sigset)
186 struct sched_param schedp;
188 if (sigset == SIGHUP)
190 if (sigset == SIGPIPE)
195 /* set scheduler & priority */
196 if (options.schedule > 1)
198 memset(&schedp, 0, sizeof(schedp));
199 schedp.sched_priority = 0;
200 sched_setscheduler(0, SCHED_OTHER, &schedp);
202 fprintf(stderr, "PBX: Signal received: %d\n", sigset);
203 PERROR("Signal received: %d\n", sigset);
212 #define ARGC (args.GetCount()+1)
213 #define ARGV(a) (args[a-1])
214 void PBXMain::Main(void)
216 PArgList &args = GetArguments();
219 #define ARGV(a) (argv[a])
220 int main(int argc, char *argv[])
224 int lockfd = -1; /* file lock */
225 struct message *message;
227 class Endpoint *epoint;
231 char prefix_string[64];
232 struct sched_param schedp;
233 char *debug_prefix = "alloc";
234 int created_mutexd = 0, created_mutexl = 0, created_mutexe = 0,
235 created_lock = 0, created_signal = 0, created_debug = 0;
236 #ifdef DEBUG_DURATION
237 time_t durationupdate;
238 double idle_duration, isdn_duration, port_duration, epoint_duration, call_duration, message_duration, admin_duration;
241 int idletime = 0, idlecheck = 0;
248 printf("\n** %s Version %s\n\n", NAME, VERSION_STRING);
255 printf("Usage: pbx (query | start | fork | rules | route)\n");
256 printf("query = Show available isdn ports.\n");
257 printf("start = Run pbx normally, abort with CTRL+C.\n");
258 printf("fork = Do daemon fork and run as background process.\n");
259 printf("interface = Get help of available interface syntax.\n");
260 printf("rules = Get help of available routing rule syntax.\n");
261 printf("rules [action] = Get individual help for given action.\n");
262 // printf("route = Show current routing as it is parsed.\n");
271 /* check for root (real or effective) */
272 if (getuid() && geteuid())
274 fprintf(stderr, "Please run %s as super-user.\n", NAME);
279 if (pthread_mutex_init(&mutexd, NULL))
281 fprintf(stderr, "cannot create 'PDEBUG' mutex\n");
285 if (pthread_mutex_init(&mutexl, NULL))
287 fprintf(stderr, "cannot create 'printlog' mutex\n");
291 if (pthread_mutex_init(&mutexe, NULL))
293 fprintf(stderr, "cannot create 'PERROR' mutex\n");
299 if (!(strcasecmp(ARGV(1),"interface")))
307 if (!(strcasecmp(ARGV(1),"rules")))
317 /* query available isdn ports */
318 if (!(strcasecmp(ARGV(1),"query")))
326 if (read_options() == 0)
329 /* initialize stuff of the NT lib */
330 if (options.deb & DEBUG_STACK)
332 global_debug = 0xffffffff & ~DBGM_MSG;
333 // global_debug = DBGM_L3DATA;
335 global_debug = DBGM_MAN;
336 SPRINT(debug_log, "%s/debug.log", INSTALL_DATA);
337 if (options.deb & DEBUG_LOG)
338 debug_init(global_debug, debug_log, debug_log, debug_log);
340 debug_init(global_debug, NULL, NULL, NULL);
345 /* read ruleset(s) */
346 if (!(ruleset_first = ruleset_parse()))
349 /* set pointer to main ruleset */
350 ruleset_main = getrulesetbyname("main");
353 fprintf(stderr, "\n***\n -> Missing 'main' ruleset, causing ALL calls to be disconnected.\n***\n\n");
354 PDEBUG(DEBUG_LOG, "Missing 'main' ruleset, causing ALL calls to be disconnected.\n");
359 /* query available isdn ports */
360 if (!(strcasecmp(ARGV(1),"route")))
362 ruleset_debug(ruleset_first);
368 /* do fork in special cases */
369 if (!(strcasecmp(ARGV(1),"fork")))
378 fprintf(stderr, "Cannot fork!\n");
393 fprintf(stderr, "Cannot fork!\n");
398 printf("PBX: Starting daemon.\n");
404 if (!!strcasecmp(ARGV(1),"start"))
409 /* create lock and lock! */
410 if ((lockfd = open("/var/run/pbx.lock", O_CREAT, 0)) < 0)
412 fprintf(stderr, "Cannot create lock file: /var/run/pbx.lock\n");
415 if (flock(lockfd, LOCK_EX|LOCK_NB) < 0)
417 if (errno == EWOULDBLOCK)
418 fprintf(stderr, "PBX: Another PBX process is running. Please kill the other one.\n");
419 else fprintf(stderr, "Locking process failed: errno=%d\n", errno);
424 /* initialize admin socket */
427 fprintf(stderr, "Unable to initialize admin socket.\n");
431 /* generate alaw / ulaw tables */
432 generate_tables(options.law);
434 /* load tones (if requested) */
435 if (fetch_tones() == 0)
437 fprintf(stderr, "Unable to fetch tones into memory.\n");
441 /* read interfaces and open ports */
442 if (!read_interfaces())
444 PERROR_RUNTIME("No interfaces specified or failed to parse interface.conf.\n");
445 fprintf(stderr, "No interfaces specified or failed to parse interface.conf.\n");
449 interface_first = interface_newlist;
450 free_interfaces(interface_newlist);
451 interface_newlist = NULL;
453 /* locking memory paging */
457 if (mlockall(MCL_CURRENT | MCL_FUTURE) >= 0)
467 fprintf(stderr, "Not enough memory to lock paging, exitting...\n");
470 fprintf(stderr, "No permission to lock paging, exitting...\n");
473 fprintf(stderr, "'Bad address' while locking paging, exitting...\n");
476 fprintf(stderr, "Unknown error %d while locking paging, exitting...\n", errno);
481 /* set real time scheduler & priority */
482 if (options.schedule > 1)
484 memset(&schedp, 0, sizeof(schedp));
485 schedp.sched_priority = options.schedule;
486 ret = sched_setscheduler(0, SCHED_RR, &schedp);
489 PERROR("Scheduling failed with given priority %d (errno = %d).\nCheck options.conf 'schedule', exitting...\n", options.schedule, errno);
494 /* signal handlers */
495 signal(SIGINT,sighandler);
496 signal(SIGHUP,sighandler);
497 signal(SIGTERM,sighandler);
498 signal(SIGPIPE,sighandler);
502 printf("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
503 printlog("%s %s started, waiting for calls...\n", NAME, VERSION_STRING);
505 #ifdef DEBUG_DURATION
507 durationupdate = now;
508 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
513 /* all loops must be counted from the beginning since nodes might get freed during handler */
516 /* handle mISDN messages from kernel */
517 debug_prefix = "ISDN";
520 #ifdef DEBUG_DURATION
522 isdn_duration += (now_d - start_d);
527 /* loop through all port ports and call their handler */
532 debug_prefix = port->p_name;
534 ret = port->handler();
537 if (ret < 0) /* port has been destroyed */
541 #ifdef DEBUG_DURATION
543 port_duration += (now_d - start_d);
547 /* loop through all epoint and call their handler */
549 epoint = epoint_first;
552 debug_prefix = prefix_string;
553 SPRINT(prefix_string, "ep%ld", epoint->ep_serial);
555 ret = epoint->handler();
558 if (ret < 0) /* epoint has been destroyed */
560 epoint = epoint->next;
562 #ifdef DEBUG_DURATION
564 epoint_duration += (now_d - start_d);
568 /* loop through all calls and call their handler */
573 debug_prefix = "call";
575 ret = call->handler();
578 if (ret < 0) /* call has been destroyed */
582 #ifdef DEBUG_DURATION
584 call_duration += (now_d - start_d);
590 /* process any message */
592 debug_prefix = "message";
593 while ((message = message_get()))
596 switch(message->flow)
599 debug_prefix = "msg port->epoint";
600 epoint = find_epoint_id(message->id_to);
605 epoint->ep_app->ea_message_port(message->id_from, message->type, &message->param);
608 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);
612 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);
617 debug_prefix = "msg epoint->call";
618 call = find_call_id(message->id_to);
621 call->message_epoint(message->id_from, message->type, &message->param);
624 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);
629 debug_prefix = "msg call->epoint";
630 epoint = find_epoint_id(message->id_to);
635 epoint->ep_app->ea_message_call(message->id_from, message->type, &message->param);
638 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);
642 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);
647 debug_prefix = "msg epoint->port";
648 port = find_port_id(message->id_to);
651 port->message_epoint(message->id_from, message->type, &message->param);
655 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);
660 PERROR("Message flow %d unknown.\n", message->flow);
662 message_free(message);
664 debug_prefix = "message";
666 #ifdef DEBUG_DURATION
668 message_duration += (now_d - start_d);
676 #ifdef DEBUG_DURATION
678 admin_duration += (now_d - start_d);
684 /* check for child to exit (eliminate zombies) */
685 if (waitpid(-1, NULL, WNOHANG) > 0)
687 PDEBUG(DEBUG_EPOINT, "a child process (created by endpoint) has exitted.\n");
692 /* do idle checking */
693 if (idlecheck != now)
695 PDEBUG(DEBUG_IDLETIME, "Idle time : %d%%\n", idletime/10000);
699 #ifdef DEBUG_DURATION
701 idle_duration += (now_d - start_d);
703 if (durationupdate != now)
705 durationupdate = now;
706 printf("Idle:%3d ISDN:%3d Port:%3d Epoint:%3d Call:%3d Message:%3d Admin:%3d\n",
707 (int)(idle_duration*100),
708 (int)(isdn_duration*100),
709 (int)(port_duration*100),
710 (int)(epoint_duration*100),
711 (int)(call_duration*100),
712 (int)(message_duration*100),
713 (int)(admin_duration*100));
714 idle_duration = isdn_duration = port_duration = epoint_duration = call_duration = message_duration = admin_duration = 0;
720 /* did we do nothing? so we wait to give time to other processes */
723 usleep(4000); /* wait 32 samples */
727 printlog("PBX terminated\n");
734 /* set scheduler & priority
736 if (options.schedule > 1)
738 memset(&schedp, 0, sizeof(schedp));
739 schedp.sched_priority = 0;
740 sched_setscheduler(0, SCHED_OTHER, &schedp);
745 signal(SIGINT,SIG_DFL);
746 signal(SIGHUP,SIG_DFL);
747 signal(SIGTERM,SIG_DFL);
748 signal(SIGPIPE,SIG_DFL);
751 /* destroy objects */
752 debug_prefix = "free";
768 /* free interfaces */
770 free_interfaces(interface_first);
771 interface_first = NULL;
773 /* close isdn ports */
774 mISDNport_close_all();
779 while ((message = message_get()))
782 message_free(message);
786 PDEBUG(DEBUG_MSG, "freed %d pending messages\n", i);
793 /* free admin socket */
798 flock(lockfd, LOCK_UN);
804 ruleset_free(ruleset_first);
805 ruleset_first = NULL;
809 if (pthread_mutex_destroy(&mutexe))
810 fprintf(stderr, "cannot destroy 'PERROR' mutex\n");
812 if (pthread_mutex_destroy(&mutexl))
813 fprintf(stderr, "cannot destroy 'printlog' mutex\n");
815 if (pthread_mutex_destroy(&mutexd))
816 fprintf(stderr, "cannot destroy 'PDEBUG' mutex\n");
823 /* display memory leak */
824 #define MEMCHECK(a, b) \
827 printf("\n******************************\n\007"); \
828 printf("\nERROR: %d %s\n", b, a); \
829 printf("\n******************************\n"); \
833 MEMCHECK("memory block(s) left (port.cpp)",pmemuse)
834 MEMCHECK("memory block(s) left (epoint.cpp)",ememuse)
835 MEMCHECK("memory block(s) left (call.cpp)",cmemuse)
836 MEMCHECK("memory block(s) left (message.c)",mmemuse)
837 MEMCHECK("memory block(s) left (route.c)",rmemuse)
838 MEMCHECK("memory block(s) left (args)",amemuse)
839 MEMCHECK("class(es) left",classuse)
840 MEMCHECK("file descriptor(s) left",fduse)
841 MEMCHECK("file handler(s) left",fhuse)
845 printf("PBX: Exit (code %d)\n", ret);
855 /* special debug function to detect buffer overflow
857 int budetect_stop = 0;
858 void budetect(const char *file, int line, char *function)
862 /* modify this function to detect race-bugs */
863 #warning DID YOU MODIFY THIS FUNCTION TO DETECT THE BUFFER OVERFLOW BUG?
865 class PmISDN *pmisdn;
866 struct mISDNport *mISDNport = mISDNport_first;
872 ii = mISDNport->b_num;
875 if (mISDNport->b_port[i])
880 if ((port->p_type&PORT_CLASS_MASK) == PORT_CLASS_ISDN)
882 pmisdn = (class PmISDN *)port;
883 if (pmisdn->p_isdn_crypt_listen)
885 PERROR_RUNTIME("************************************************\n");
886 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
887 PERROR_RUNTIME("** p_isdn_crypt_listen = %d\n", pmisdn->p_isdn_crypt_listen);
888 PERROR_RUNTIME("************************************************\n");
892 if (port == mISDNport->b_port[i])
897 PERROR_RUNTIME("************************************************\n");
898 PERROR_RUNTIME("** BUG detected in %s, line %d, function %s\n", file, line, function);
899 PERROR_RUNTIME("** b_port not in list.\n");
900 PERROR_RUNTIME("************************************************\n");
907 mISDNport = mISDNport->next;