/* Arrange for function to be called some time, roughly equal to dt seconds, in the future. */ void timer_call (timer_func_t * func, any arg, f64 dt) { timer_callback_t *t; sigset_t save; /* Install signal handler on first call. */ static word signal_installed = 0; if (!signal_installed) { struct sigaction sa; /* Initialize time_resolution before first call to timer_interrupt */ time_resolution = 0.75 / (f64) HZ; clib_memset (&sa, 0, sizeof (sa)); sa.sa_handler = timer_interrupt; if (sigaction (TIMER_SIGNAL, &sa, 0) < 0) clib_panic ("sigaction"); signal_installed = 1; } timer_block (&save); /* Add new timer. */ vec_add2 (timers, t, 1); t->time = unix_time_now () + dt; t->func = func; t->arg = arg; { word reset_timer = vec_len (timers) == 1; if (_vec_len (timers) > 1) { reset_timer += t->time < (t - 1)->time; sort_timers (timers); } if (reset_timer) timer_interrupt (TIMER_SIGNAL); } timer_unblock (&save); }
int main (int argc, char **argv) { static char *ifname = NULL; /* Name of interface to attach to */ fd_set rfds, readers; int n, nfds = 0, i; int daemonize = 0; /* Remember the name of the executable... */ progname = strrchr(argv[0], '/'); if (progname) progname++; else progname = argv[0]; /* Use debug output as default */ debug = 1; /* Parse command line: */ argc--; argv++; while(argc) { if(argv[0][0] == '-') { switch(argv[0][1]) { case 'i': if(argv[1] != NULL) { ifname = argv[1]; argc--; argv++; break; } print_usage(); exit(-1); case 'd': debug = 0; daemonize = 1; break; case 'l': log_to_file = 1; break; case 'u': unidir_hack = 1; break; case 'g': rreq_gratuitous = 1; break; case 't': log_rt_table = 1; if(argv[1] != NULL && argv[1][0] != '-') { printf("arg: %d\n", atoi(argv[1])); rt_log_interval = atoi(argv[1])*1000; argc--; argv++; } break; default: print_usage(); exit(-1); } } else { fprintf(stderr, "Unknown option: %s\n", argv[0]); print_usage(); exit(-1); } argc--; argv++; } /* Check that we are running as root */ if (geteuid() != 0) { fprintf(stderr, "aodvd: must be root\n"); exit(1); } /* Detach from terminal */ if(daemonize) { if (fork() != 0) exit(0); /* Close stdin, stdout and stderr... */ close(0); close(1); close(2); setsid(); } /* Initialize data structures and services... */ host_init(ifname); log_init(); timer_queue_init(); rt_table_init(); packet_input_init(); aodv_socket_init(); log(LOG_NOTICE, 0, "INIT: Attaching to interface %s, override with -i <interface>.",this_host->ifname); /* Make sure we cleanup at exit... */ atexit((void *)&cleanup); /* Make sure we run at high priority to make up for the user space packet processing... */ /* nice(-5); */ /* Catch SIGHUP, SIGINT and SIGTERM type signals */ signal(SIGHUP, signal_handler); signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); /* Only capture segmentation faults when we are not debugging... */ #ifndef DEBUG signal(SIGSEGV, signal_handler); #endif /* Set sockets to watch... */ FD_ZERO(&readers); for (i = 0; i < nr_callbacks; i++) { FD_SET(callbacks[i].fd, &readers); if (callbacks[i].fd >= nfds) nfds = callbacks[i].fd + 1; } /* Set bcast_time, which ensures that we don't send unnecessary hello msgs. */ this_host->bcast_time = get_currtime(); /* Schedule the first Hello */ timer_new(HELLO_INTERVAL, hello_send, NULL); if(log_rt_table) timer_new(rt_log_interval, print_rt_table, NULL); while(1) { memcpy((char *)&rfds, (char *)&readers, sizeof(rfds)); if ((n = select(nfds, &rfds, NULL, NULL, NULL)) < 0) { if (errno != EINTR) log(LOG_WARNING, errno, "main.c: Failed select (main loop)"); continue; } if (n > 0) { for (i = 0; i < nr_callbacks; i++) { if (FD_ISSET(callbacks[i].fd, &rfds)) { /* We don't want any timer SIGALRM's while executing the callback functions, therefore we block the timer... */ timer_block(); (*callbacks[i].func)(callbacks[i].fd); timer_unblock(); } } } } /* Main loop */ return 0; }