int main(int argc, char **argv) { int i, len, timeout, controlfd, alarm_tick; double sptime, eptime, last_tick_time; unsigned long delay; struct cfg cf; char buf[256]; memset(&cf, 0, sizeof(cf)); init_config(&cf, argc, argv); seedrandom(); init_hash_table(&cf.stable); init_port_table(&cf); controlfd = init_controlfd(&cf); if (cf.stable.nodaemon == 0) { if (rtpp_daemon(0, 0) == -1) err(1, "can't switch into daemon mode"); /* NOTREACHED */ } glog = cf.stable.glog = rtpp_log_open(&cf.stable, "rtpproxy", NULL, LF_REOPEN); atexit(ehandler); rtpp_log_write(RTPP_LOG_INFO, cf.stable.glog, "rtpproxy started, pid %d", getpid()); if (cf.timeout_socket != NULL) { cf.timeout_handler = rtpp_notify_init(glog, cf.timeout_socket); if (cf.timeout_handler == NULL) { rtpp_log_ewrite(RTPP_LOG_ERR, glog, "can't start notification thread"); exit(1); } } i = open(pid_file, O_WRONLY | O_CREAT | O_TRUNC, DEFFILEMODE); if (i >= 0) { len = sprintf(buf, "%u\n", (unsigned int)getpid()); write(i, buf, len); close(i); } else { rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable.glog, "can't open pidfile for writing"); } signal(SIGHUP, fatsignal); signal(SIGINT, fatsignal); signal(SIGKILL, fatsignal); signal(SIGPIPE, SIG_IGN); signal(SIGTERM, fatsignal); signal(SIGXCPU, fatsignal); signal(SIGXFSZ, fatsignal); signal(SIGVTALRM, fatsignal); signal(SIGPROF, fatsignal); signal(SIGUSR1, fatsignal); signal(SIGUSR2, fatsignal); if (cf.stable.run_uname != NULL || cf.stable.run_gname != NULL) { if (drop_privileges(&cf) != 0) { rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable.glog, "can't switch to requested user/group"); exit(1); } } cf.stable.controlfd = controlfd; cf.sessinfo.sessions[0] = NULL; cf.sessinfo.nsessions = 0; cf.rtp_nsessions = 0; rtpp_command_async_init(&cf); sptime = 0; last_tick_time = 0; for (;;) { pthread_mutex_lock(&cf.glock); pthread_mutex_lock(&cf.sessinfo.lock); if (cf.rtp_nsessions > 0 || cf.sessinfo.nsessions > 0) { timeout = RTPS_TICKS_MIN; } else { timeout = TIMETICK * 1000; } pthread_mutex_unlock(&cf.sessinfo.lock); pthread_mutex_unlock(&cf.glock); eptime = getdtime(); delay = (eptime - sptime) * 1000000.0; if (delay < (1000000 / POLL_LIMIT)) { usleep((1000000 / POLL_LIMIT) - delay); sptime = getdtime(); } else { sptime = eptime; } pthread_mutex_lock(&cf.sessinfo.lock); if (cf.sessinfo.nsessions > 0) { i = poll(cf.sessinfo.pfds, cf.sessinfo.nsessions, timeout); pthread_mutex_unlock(&cf.sessinfo.lock); if (i < 0 && errno == EINTR) continue; } else { pthread_mutex_unlock(&cf.sessinfo.lock); usleep(timeout * 1000); } eptime = getdtime(); pthread_mutex_lock(&cf.glock); if (cf.rtp_nsessions > 0) { process_rtp_servers(&cf, eptime); } pthread_mutex_unlock(&cf.glock); if (eptime > last_tick_time + TIMETICK) { alarm_tick = 1; last_tick_time = eptime; } else { alarm_tick = 0; } pthread_mutex_lock(&cf.glock); process_rtp(&cf, eptime, alarm_tick); pthread_mutex_unlock(&cf.glock); } exit(0); }
static void rtpp_proc_async_run(void *arg) { struct cfg *cf; double last_tick_time; int alarm_tick, i, ndrain, rtp_only; struct rtpp_proc_async_cf *proc_cf; long long ncycles_ref; #ifdef RTPP_DEBUG int ncycles_ref_pre, last_ctick; #endif struct sign_arg *s_a; struct rtpp_wi *wi, *wis[10]; struct sthread_args *sender; double tp[4]; struct rtpp_proc_rstats *rstats; struct rtpp_stats_obj *stats_cf; cf = (struct cfg *)arg; proc_cf = cf->stable->rtpp_proc_cf; stats_cf = cf->stable->rtpp_stats; rstats = &proc_cf->rstats; last_tick_time = 0; wi = rtpp_queue_get_item(proc_cf->time_q, 0); s_a = (struct sign_arg *)rtpp_wi_sgnl_get_data(wi, NULL); #ifdef RTPP_DEBUG last_ctick = s_a->clock_tick; ncycles_ref_pre = s_a->ncycles_ref; #endif rtpp_wi_free(wi); tp[0] = getdtime(); for (;;) { i = rtpp_queue_get_items(proc_cf->time_q, wis, 10, 0); if (i <= 0) { continue; } i -= 1; s_a = (struct sign_arg *)rtpp_wi_sgnl_get_data(wis[i], NULL); ndrain = (s_a->ncycles_ref - ncycles_ref) / (cf->stable->target_pfreq / MAX_RTP_RATE); #ifdef RTPP_DEBUG last_ctick = s_a->clock_tick; ncycles_ref_pre = ncycles_ref; #endif ncycles_ref = s_a->ncycles_ref; for(; i > -1; i--) { rtpp_wi_free(wis[i]); } tp[1] = getdtime(); #if RTPP_DEBUG if (last_ctick % (unsigned int)cf->stable->target_pfreq == 0 || last_ctick < 1000) { rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld sptime %f, CSV: %f,%f,%f", \ last_ctick, tp[1], (double)last_ctick / cf->stable->target_pfreq, \ ((double)ncycles_ref / cf->stable->target_pfreq) - tp[1], tp[1]); } #endif if (ndrain < 1) { ndrain = 1; } #if RTPP_DEBUG if (ndrain > 1) { rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld " \ "ncycles_ref %lld, ncycles_ref_pre %lld, ndrain %d CSV: %f,%f,%d", \ last_ctick, ncycles_ref, ncycles_ref_pre, ndrain, \ (double)last_ctick / cf->stable->target_pfreq, ndrain); } #endif alarm_tick = 0; if (last_tick_time == 0 || last_tick_time > tp[1]) { last_tick_time = tp[1]; } else if (last_tick_time + (double)TIMETICK < tp[1]) { alarm_tick = 1; last_tick_time = tp[1]; } if (alarm_tick || (ncycles_ref % 7) == 0) { rtp_only = 0; } else { rtp_only = 1; } pthread_mutex_lock(&cf->sessinfo.lock); if (cf->sessinfo.nsessions > 0) { if (rtp_only == 0) { i = poll(cf->sessinfo.pfds_rtcp, cf->sessinfo.nsessions, 0); } i = poll(cf->sessinfo.pfds_rtp, cf->sessinfo.nsessions, 0); pthread_mutex_unlock(&cf->sessinfo.lock); if (i < 0 && errno == EINTR) { rtpp_command_async_wakeup(cf->stable->rtpp_cmd_cf); tp[0] = getdtime(); continue; } } else { pthread_mutex_unlock(&cf->sessinfo.lock); } tp[2] = getdtime(); sender = rtpp_anetio_pick_sender(proc_cf->op); if (rtp_only == 0) { pthread_mutex_lock(&cf->glock); process_rtp(cf, tp[2], alarm_tick, ndrain, sender, rstats); } else { process_rtp_only(cf, tp[2], ndrain, sender, rstats); pthread_mutex_lock(&cf->glock); } if (cf->rtp_nsessions > 0) { process_rtp_servers(cf, tp[2], sender, rstats); } pthread_mutex_unlock(&cf->glock); rtpp_anetio_pump_q(sender); rtpp_command_async_wakeup(cf->stable->rtpp_cmd_cf); tp[3] = getdtime(); flush_rstats(stats_cf, rstats); #if RTPP_DEBUG recfilter_apply(&proc_cf->sleep_time, tp[1] - tp[0]); recfilter_apply(&proc_cf->poll_time, tp[2] - tp[1]); recfilter_apply(&proc_cf->proc_time, tp[3] - tp[2]); #endif tp[0] = tp[3]; #if RTPP_DEBUG if (last_ctick % (unsigned int)cf->stable->target_pfreq == 0 || last_ctick < 1000) { #if 0 rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld eptime %f, CSV: %f,%f,%f", \ last_ctick, tp[3], (double)last_ctick / cf->stable->target_pfreq, tp[3] - tp[1], tp[3]); #endif rtpp_log_write(RTPP_LOG_DBUG, cf->stable->glog, "run %lld eptime %f sleep_time %f poll_time %f proc_time %f CSV: %f,%f,%f,%f", \ last_ctick, tp[3], proc_cf->sleep_time.lastval, proc_cf->poll_time.lastval, proc_cf->proc_time.lastval, \ (double)last_ctick / cf->stable->target_pfreq, proc_cf->sleep_time.lastval, proc_cf->poll_time.lastval, proc_cf->proc_time.lastval); } #endif } }