예제 #1
0
static void
rtpp_mif_dtor(struct rtpp_module_if_priv *pvt)
{

    rtpp_module_if_fin(&(pvt->pub));
    /* First, stop the worker thread and wait for it to terminate */
    rtpp_queue_put_item(pvt->sigterm, pvt->req_q);
    pthread_join(pvt->thread_id, NULL);
    rtpp_queue_destroy(pvt->req_q);

    /* Then run module destructor (if any) */
    if (pvt->mip->dtor != NULL) {
        pvt->mip->dtor(pvt->mpvt);
    }

#if RTPP_CHECK_LEAKS
    /* Check if module leaked any mem */
    if (rtpp_memdeb_dumpstats(pvt->memdeb_p, 1) != 0) {
        RTPP_LOG(pvt->log, RTPP_LOG_ERR, "module '%s' leaked memory after "
          "destruction", pvt->mip->name);
    }
    rtpp_memdeb_dtor(pvt->memdeb_p);
#endif
    /* Unload and free everything */
    dlclose(pvt->dmp);
    CALL_METHOD(pvt->log->rcnt, decref);
    free(pvt);
}
예제 #2
0
파일: rtpp_sbuf.c 프로젝트: sippy/rtpproxy
int
rtpp_sbuf_selftest(void)
{
    struct rtpp_sbuf *sbp;
    int rval;
    const char *longtest = "INFO:GLOBAL:rtpp_proc_async_run: ncycles=2600 load=0.068641";

    RTPP_MEMDEB_APP_INIT();

    sbp = rtpp_sbuf_ctor(6);
    assert(sbp != NULL);
    assert(sbp->alen == 6);
    assert(sbp->cp == sbp->bp);
    assert(RS_ULEN(sbp) == 0);
    rval = rtpp_sbuf_write(sbp, "%d", 12345);
    assert(rval == SBW_OK);
    assert(sbp->cp[0] == '\0');
    assert(strcmp(sbp->bp, "12345") == 0);
    assert(RS_ULEN(sbp) == 5);
    rval = rtpp_sbuf_write(sbp, "%s", "F");
    assert(rval == SBW_SHRT);
    assert(sbp->cp[0] == '\0');
    assert(strcmp(sbp->bp, "12345") == 0);
    assert(RS_ULEN(sbp) == 5);
    assert(rtpp_sbuf_extend(sbp, 7) == 0);
    assert(RS_ULEN(sbp) == 5);
    assert(strcmp(sbp->bp, "12345") == 0);
    rval = rtpp_sbuf_write(sbp, "%s", "F");
    assert(rval == SBW_OK);
    assert(RS_ULEN(sbp) == 6);
    assert(strcmp(sbp->bp, "12345F") == 0);
    do {
        assert(rtpp_sbuf_extend(sbp, sbp->alen + 1) == 0);
        rval = rtpp_sbuf_write(sbp, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
          longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest,
          longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest, longtest);
    } while (rval == SBW_SHRT);
    assert(rval == SBW_OK);
    assert(RS_ULEN(sbp) == 1446);
    assert(sbp->alen == RS_ULEN(sbp) + 1);
    assert(strncmp(sbp->bp, "12345F", 6) == 0);
    rval = RS_ULEN(sbp);
    rtpp_sbuf_reset(sbp);
    assert(sbp->cp == sbp->bp);
    assert(sbp->cp[0] == '\0');
    assert(sbp->alen == rval + 1);
    rtpp_sbuf_dtor(sbp);

    rval = rtpp_memdeb_dumpstats(MEMDEB_SYM, 0);
    return (rval);
}
예제 #3
0
struct rtpp_module_if *
rtpp_module_if_ctor(struct rtpp_cfg_stable *cfsp, struct rtpp_log *log,
  const char *mpath)
{
    struct rtpp_refcnt *rcnt;
    struct rtpp_module_if_priv *pvt;
    const char *derr;

    pvt = rtpp_rzmalloc(sizeof(struct rtpp_module_if_priv), &rcnt);
    if (pvt == NULL) {
        goto e0;
    }
    pvt->pub.rcnt = rcnt;
    pvt->dmp = dlopen(mpath, RTLD_NOW);
    if (pvt->dmp == NULL) {
        derr = dlerror();
        if (strstr(derr, mpath) == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't dlopen(%s): %s", mpath, derr);
        } else {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't dlopen() module: %s", derr);
        }
        goto e1;
    }
    pvt->mip = dlsym(pvt->dmp, "rtpp_module");
    if (pvt->mip == NULL) {
        derr = dlerror();
        if (strstr(derr, mpath) == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't find 'rtpp_module' symbol in the %s"
              ": %s", mpath, derr);
        } else {
            RTPP_LOG(log, RTPP_LOG_ERR, "can't find 'rtpp_module' symbol: %s",
              derr);
        }
        goto e2;
    }
    if (!MI_VER_CHCK(pvt->mip)) {
        RTPP_LOG(log, RTPP_LOG_ERR, "incompatible API version in the %s, "
          "consider recompiling the module", mpath);
        goto e2;
    }

#if RTPP_CHECK_LEAKS
    pvt->mip->_malloc = &rtpp_memdeb_malloc;
    pvt->mip->_zmalloc = &rtpp_zmalloc_memdeb;
    pvt->mip->_free = &rtpp_memdeb_free;
    pvt->mip->_realloc = &rtpp_memdeb_realloc;
    pvt->mip->_strdup = &rtpp_memdeb_strdup;
    pvt->mip->_asprintf = &rtpp_memdeb_asprintf;
    pvt->mip->_vasprintf = &rtpp_memdeb_vasprintf;
    pvt->memdeb_p = rtpp_memdeb_init();
    rtpp_memdeb_setlog(pvt->memdeb_p, log);
#else
    pvt->mip->_malloc = (rtpp_module_malloc_t)&malloc;
    pvt->mip->_zmalloc = (rtpp_module_zmalloc_t)&rtpp_zmalloc;
    pvt->mip->_free = (rtpp_module_free_t)&free;
    pvt->mip->_realloc = (rtpp_module_realloc_t)&realloc;
    pvt->mip->_strdup = (rtpp_module_strdup_t)&strdup;
    pvt->mip->_asprintf = rtpp_module_asprintf;
    pvt->mip->_vasprintf = rtpp_module_vasprintf;
#endif
    if (pvt->memdeb_p == NULL) {
        goto e2;
    }
    /* We make a copy, so that the module cannot screw us up */
    pvt->mip->memdeb_p = pvt->memdeb_p;
    pvt->sigterm = rtpp_wi_malloc_sgnl(SIGTERM, NULL, 0);
    if (pvt->sigterm == NULL) {
        goto e3;
    }
    pvt->req_q = rtpp_queue_init(1, "rtpp_module_if(%s)", pvt->mip->name);
    if (pvt->req_q == NULL) {
        goto e4;
    }
    if (pvt->mip->ctor != NULL) {
        pvt->mpvt = pvt->mip->ctor(cfsp);
        if (pvt->mpvt == NULL) {
            RTPP_LOG(log, RTPP_LOG_ERR, "module '%s' failed to initialize",
              pvt->mip->name);
            goto e5;
        }
    }
    if (pvt->mip->on_session_end.argsize != rtpp_acct_OSIZE()) {
        RTPP_LOG(log, RTPP_LOG_ERR, "incompatible API version in the %s, "
          "consider recompiling the module", mpath);
        goto e6;
    }

    if (pthread_create(&pvt->thread_id, NULL,
      (void *(*)(void *))&rtpp_mif_run, pvt) != 0) {
        goto e6;
    }
    CALL_METHOD(log->rcnt, incref);
    pvt->log = log;
    pvt->pub.do_acct = &rtpp_mif_do_acct;
    CALL_METHOD(pvt->pub.rcnt, attach, (rtpp_refcnt_dtor_t)&rtpp_mif_dtor,
      pvt);
    return ((&pvt->pub));
e6:
    if (pvt->mip->dtor != NULL) {
        pvt->mip->dtor(pvt->mpvt);
    }
e5:
    rtpp_queue_destroy(pvt->req_q);
#if RTPP_CHECK_LEAKS
    if (rtpp_memdeb_dumpstats(pvt->memdeb_p, 1) != 0) {
        RTPP_LOG(log, RTPP_LOG_ERR, "module '%s' leaked memory in the failed "
          "constructor", pvt->mip->name);
    }
#endif
e4:
    rtpp_wi_free(pvt->sigterm);
e3:
#if RTPP_CHECK_LEAKS
    rtpp_memdeb_dtor(pvt->memdeb_p);
#endif
e2:
    dlclose(pvt->dmp);
e1:
    CALL_METHOD(rcnt, decref);
    free(pvt);
e0:
    return (NULL);
}
예제 #4
0
파일: main.c 프로젝트: yzy5768/rtpproxy
int
main(int argc, char **argv)
{
    int i, len;
    double eval, clk;
    long long ncycles_ref, counter;
    double eptime;
    double add_delay;
    struct cfg cf;
    char buf[256];
    struct recfilter loop_error;
    struct PFD phase_detector;
    useconds_t usleep_time;
    struct sched_param sparam;
#if RTPP_DEBUG
    double sleep_time, filter_lastval;
#endif
    memset(&cf, 0, sizeof(cf));

    cf.stable = malloc(sizeof(struct rtpp_cfg_stable));
    if (cf.stable == NULL) {
         err(1, "can't allocate memory for the struct rtpp_cfg_stable");
         /* NOTREACHED */
    }
    memset(cf.stable, '\0', sizeof(struct rtpp_cfg_stable));
    cf.stable->ctrl_socks = malloc(sizeof(struct rtpp_list));
    if (cf.stable->ctrl_socks == NULL) {
         err(1, "can't allocate memory for the struct rtpp_cfg_stable");
         /* NOTREACHED */
    }
    memset(cf.stable->ctrl_socks, '\0', sizeof(struct rtpp_list));
    RTPP_LIST_RESET(cf.stable->ctrl_socks);    

    init_config(&cf, argc, argv);

    seedrandom();

    cf.stable->sessions_ht = rtpp_hash_table_ctor();
    if (cf.stable->sessions_ht == NULL) {
        err(1, "can't allocate memory for the hash table");
         /* NOTREACHED */
    }
    cf.stable->rtpp_stats = rtpp_stats_ctor();
    if (cf.stable->rtpp_stats == NULL) {
        err(1, "can't allocate memory for the stats data");
         /* NOTREACHED */
    }
    init_port_table(&cf);

    if (rtpp_controlfd_init(&cf) != 0) {
        err(1, "can't inilialize control socket%s",
          cf.stable->ctrl_socks->len > 1 ? "s" : "");
    }

    if (cf.stable->nodaemon == 0) {
	if (rtpp_daemon(0, 0) == -1)
	    err(1, "can't switch into daemon mode");
	    /* NOTREACHED */
    }

    if (rtpp_notify_init() != 0)
        errx(1, "can't start notification thread");

    cf.stable->glog = rtpp_log_open(cf.stable, "rtpproxy", NULL, LF_REOPEN);
    rtpp_log_setlevel(cf.stable->glog, cf.stable->log_level);
    _sig_cf = &cf;
    atexit(ehandler);
    rtpp_log_write(RTPP_LOG_INFO, cf.stable->glog, "rtpproxy started, pid %d", getpid());

    i = open(cf.stable->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, sighup);
    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->sched_policy != SCHED_OTHER) {
        sparam.sched_priority = sched_get_priority_max(cf.stable->sched_policy);
        if (sched_setscheduler(0, cf.stable->sched_policy, &sparam) == -1) {
            rtpp_log_ewrite(RTPP_LOG_ERR, cf.stable->glog, "sched_setscheduler(SCHED_%s, %d)",
              (cf.stable->sched_policy == SCHED_FIFO) ? "FIFO" : "RR", sparam.sched_priority);
        }
    }

    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);
	}
    }
    set_rlimits(&cf);

    cf.sessinfo.sessions[0] = NULL;
    cf.sessinfo.nsessions = 0;
    cf.rtp_nsessions = 0;

    rtpp_command_async_init(&cf);
    rtpp_proc_async_init(&cf);

    counter = 0;
    recfilter_init(&loop_error, 0.96, 0.0, 0);
    PFD_init(&phase_detector, 2.0);
#ifdef HAVE_SYSTEMD_SD_DAEMON_H
    sd_notify(0, "READY=1");
#endif
#ifdef RTPP_CHECK_LEAKS
    rtpp_memdeb_setbaseln();
#endif
    for (;;) {
	eptime = getdtime();

        clk = (eptime + cf.stable->sched_offset) * cf.stable->target_pfreq;

        ncycles_ref = llrint(clk);

        eval = PFD_get_error(&phase_detector, clk);

#if RTPP_DEBUG
        filter_lastval = loop_error.lastval;
#endif

        if (eval != 0.0) {
            recfilter_apply(&loop_error, sigmoid(eval));
        }

#if RTPP_DEBUG
        if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000) {
          rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld ncycles %f raw error1 %f, filter lastval %f, filter nextval %f",
            counter, clk, eval, filter_lastval, loop_error.lastval);
        }
#endif
        add_delay = freqoff_to_period(cf.stable->target_pfreq, 1.0, loop_error.lastval);
        usleep_time = add_delay * 1000000.0;
#if RTPP_DEBUG
        if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000) {
            rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld filter lastval %f, filter nextval %f, error %f",
              counter, filter_lastval, loop_error.lastval, sigmoid(eval));
            rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld extra sleeping time %llu", counter, usleep_time);
        }
        sleep_time = getdtime();
#endif
        rtpp_proc_async_wakeup(cf.stable->rtpp_proc_cf, counter, ncycles_ref);
        usleep(usleep_time);
#if RTPP_DEBUG
        sleep_time = getdtime() - sleep_time;
        if (counter % (unsigned int)cf.stable->target_pfreq == 0 || counter < 1000 || sleep_time > add_delay * 2.0) {
            rtpp_log_write(RTPP_LOG_DBUG, cf.stable->glog, "run %lld sleeping time required %llu sleeping time actual %f, CSV: %f,%f,%f", \
              counter, usleep_time, sleep_time, (double)counter / cf.stable->target_pfreq, ((double)usleep_time) / 1000.0, sleep_time * 1000.0);
        }
#endif
        counter += 1;
        if (cf.stable->slowshutdown != 0) {
            pthread_mutex_lock(&cf.sessinfo.lock);
            if (cf.sessinfo.nsessions == 0) {
                /* The below unlock is not necessary, but does not hurt either */
                pthread_mutex_unlock(&cf.sessinfo.lock);
                rtpp_log_write(RTPP_LOG_INFO, cf.stable->glog,
                  "deorbiting-burn sequence completed, exiting");
                break;
            }
            pthread_mutex_unlock(&cf.sessinfo.lock);
        }
    }

#ifdef HAVE_SYSTEMD_SD_DAEMON_H
    sd_notify(0, "STATUS=Exited");
#endif

#ifdef RTPP_CHECK_LEAKS
    exit(rtpp_memdeb_dumpstats(&cf) == 0 ? 0 : 1);
#else
    exit(0);
#endif
}