static void do_timeout_notification(struct rtpp_notify_wi *wi, int retries, struct rtpp_log *log) { int result; if (wi->rttp->connected == 0) { reconnect_timeout_handler(log, wi->rttp); /* If connect fails, no notification will be sent */ if (wi->rttp->connected == 0) { RTPP_LOG(log, RTPP_LOG_ERR, "unable to send timeout notification"); return; } } do { result = send(wi->rttp->fd, wi->notify_buf, wi->len - 1, 0); } while (result == -1 && errno == EINTR); if (result < 0) { wi->rttp->connected = 0; RTPP_ELOG(log, RTPP_LOG_ERR, "failed to send timeout notification"); if (retries > 0) do_timeout_notification(wi, retries - 1, log); } }
int set_rlimits(struct cfg *cf) { struct rlimit rlp; if (getrlimit(RLIMIT_CORE, &rlp) < 0) { RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "getrlimit(RLIMIT_CORE)"); return (-1); } rlp.rlim_cur = RLIM_INFINITY; rlp.rlim_max = RLIM_INFINITY; if (setrlimit(RLIMIT_CORE, &rlp) < 0) { RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "setrlimit(RLIMIT_CORE)"); return (-1); } return (0); }
int drop_privileges(const struct rtpp_cfg_stable *cfsp) { if (cfsp->runcreds->gname != NULL) { if (setgid(cfsp->runcreds->gid) != 0) { RTPP_ELOG(cfsp->glog, RTPP_LOG_ERR, "can't set current group ID: %d", cfsp->runcreds->gid); return -1; } } if (cfsp->runcreds->uname == NULL) return 0; if (setuid(cfsp->runcreds->uid) != 0) { RTPP_ELOG(cfsp->glog, RTPP_LOG_ERR, "can't set current user ID: %d", cfsp->runcreds->uid); return -1; } return 0; }
static void reconnect_timeout_handler(struct rtpp_log *log, struct rtpp_tnotify_target *rttp) { assert (rttp->connected == 0); if (rttp->fd == -1) { RTPP_LOG(log, RTPP_LOG_DBUG, "connecting timeout socket"); } else { RTPP_LOG(log, RTPP_LOG_DBUG, "reconnecting timeout socket"); close(rttp->fd); } rttp->fd = socket(rttp->socket_type, SOCK_STREAM, 0); if (rttp->fd == -1) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't create timeout socket"); return; } if (rttp->local != NULL) { if (bind(rttp->fd, rttp->local, SA_LEN(rttp->local)) < 0) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't bind timeout socket"); goto e0; } } if (connect(rttp->fd, (struct sockaddr *)&(rttp->remote), rttp->remote_len) == -1) { RTPP_ELOG(log, RTPP_LOG_ERR, "can't connect to timeout socket"); goto e0; } else { rttp->connected = 1; } return; e0: close(rttp->fd); rttp->fd = -1; return; }
static int controlfd_init_tcp(struct cfg *cf, struct rtpp_ctrl_sock *csp) { struct sockaddr *ifsin; char *cp; int controlfd, so_rcvbuf, i; cp = strrchr(csp->cmd_sock, ':'); if (cp != NULL) { *cp = '\0'; cp++; } if (cp == NULL || *cp == '\0') cp = CPORT; csp->port_ctl = atoi(cp); i = (csp->type == RTPC_TCP6) ? AF_INET6 : AF_INET; ifsin = sstosa(&csp->bindaddr); if (setbindhost(ifsin, i, csp->cmd_sock, cp) != 0) { warnx("setbindhost failed"); return (-1); } controlfd = socket(i, SOCK_STREAM, 0); if (controlfd == -1) { warn("can't create socket"); return (-1); } so_rcvbuf = 16 * 1024; if (setsockopt(controlfd, SOL_SOCKET, SO_RCVBUF, &so_rcvbuf, sizeof(so_rcvbuf)) == -1) RTPP_ELOG(cf->stable->glog, RTPP_LOG_ERR, "unable to set 16K receive buffer size on controlfd"); if (bind(controlfd, ifsin, SA_LEN(ifsin)) < 0) { warn("can't bind to a socket"); goto e0; } if (listen(controlfd, 32) != 0) { warn("can't listen on a socket: %s", csp->cmd_sock); goto e0; } return (controlfd); e0: close(controlfd); return (-1); }
int rtpp_cfile_process(struct rtpp_cfg_stable *csp) { struct ucl_parser *parser; ucl_object_t *conf_root; ucl_object_iter_t it_conf; const ucl_object_t *obj_file; const char *cf_key; int fd, ecode; ecode = 0; fd = open(csp->cfile, O_RDONLY); if (fd < 0) { RTPP_ELOG(csp->glog, RTPP_LOG_ERR, "open failed: %s", csp->cfile); ecode = -1; goto e0; } parser = ucl_parser_new(UCL_PARSER_NO_FILEVARS); if (parser == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_parser_new() failed"); ecode = -1; goto e1; } ucl_parser_add_fd(parser, fd); conf_root = ucl_parser_get_object(parser); if (conf_root == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_parser_get_object() failed"); ecode = -1; goto e2; } if (ucl_parser_get_error(parser)) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Parse Error occured: %s", ucl_parser_get_error(parser)); ecode = -1; goto e3; } it_conf = ucl_object_iterate_new(conf_root); if (it_conf == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "ucl_object_iterate_new() failed"); ecode = -1; goto e3; } while ((obj_file = ucl_object_iterate_safe(it_conf, true)) != NULL) { cf_key = ucl_object_key(obj_file); RTPP_LOG(csp->glog, RTPP_LOG_DBUG, "Entry: %s", cf_key); if (strcasecmp(cf_key, "modules") == 0) { if (parse_modules(csp, obj_file) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "parse_modules() failed"); ecode = -1; goto e4; } } } if (ucl_object_iter_chk_excpn(it_conf)) { ecode = -1; } e4: ucl_object_iterate_free(it_conf); e3: ucl_object_unref(conf_root); e2: ucl_parser_free(parser); e1: close(fd); e0: return (ecode); }
static int parse_modules(struct rtpp_cfg_stable *csp, const ucl_object_t *wop) { ucl_object_iter_t it_conf; const ucl_object_t *obj_file; const char *cf_key; const ucl_object_t *obj_key; int ecode, success; void *confp; const conf_helper_map *fent, *map; struct rtpp_module_conf *mcp; char mpath[PATH_MAX + 1]; const char *cp, *mp; struct rtpp_module_if *mif; it_conf = ucl_object_iterate_new(wop); if (it_conf == NULL) return (-1); ecode = 0; while ((obj_file = ucl_object_iterate_safe(it_conf, true)) != NULL) { cf_key = ucl_object_key(obj_file); RTPP_LOG(csp->glog, RTPP_LOG_DBUG, "\tmodule: %s", cf_key); obj_key = ucl_object_find_key(obj_file, "load"); if (obj_key == NULL) { cp = rtpp_module_dsop_canonic(cf_key, mpath, sizeof(mpath)); if (cp == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: Unable to find load parameter in module: %s", cf_key); ecode = -1; goto e0; } } else { if (obj_key->type != UCL_STRING) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Error: \"load\" parameter in %s has a wrong type, string is expected", cf_key); ecode = -1; goto e0; } mp = ucl_object_tostring(obj_key); cp = realpath(mp, mpath); if (cp == NULL) { RTPP_ELOG(csp->glog, RTPP_LOG_ERR, "realpath() failed: %s", mp); ecode = -1; goto e0; } } mif = rtpp_module_if_ctor(cp); if (mif == NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "dymanic module constructor has failed: %s", cp); ecode = -1; goto e0; } if (CALL_METHOD(mif, load, csp, csp->glog) != 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->load() method has failed: %s", mif, cp); goto e1; } if (CALL_METHOD(mif, get_mconf, &mcp) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->get_mconf() method has failed: %s", mif, cp); goto e1; } fent = NULL; if (mcp != NULL) { map = mcp->conf_map; confp = mcp->conf_data; } else { map = default_module_map; confp = NULL; } success = conf_helper_mapper(csp->glog, obj_file, map, confp, &fent); if (!success) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "Config parsing issue in section %s", cf_key); if (fent != NULL && fent->conf_key != NULL) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "\tparameter %s", fent->conf_key); } goto e1; } if (CALL_METHOD(mif, config) < 0) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "%p->config() method has failed: %s", mif, cp); goto e1; } rtpp_list_append(csp->modules_cf, mif); continue; e1: ecode = -1; CALL_SMETHOD(mif->rcnt, decref); goto e0; } e0: if (ucl_object_iter_chk_excpn(it_conf)) { RTPP_LOG(csp->glog, RTPP_LOG_ERR, "UCL has failed with an internal error"); ecode = -1; } ucl_object_iterate_free(it_conf); return (ecode); }
static void rtpp_anetio_sthread(struct sthread_args *args) { int n, nsend, i, send_errno, nretry; struct rtpp_wi *wi, *wis[100]; #if RTPP_DEBUG_timers double tp[3], runtime, sleeptime; long run_n; runtime = sleeptime = 0.0; run_n = 0; tp[0] = getdtime(); #endif for (;;) { nsend = rtpp_queue_get_items(args->out_q, wis, 100, 0); #if RTPP_DEBUG_timers tp[1] = getdtime(); #endif for (i = 0; i < nsend; i++) { wi = wis[i]; if (wi->wi_type == RTPP_WI_TYPE_SGNL) { rtpp_wi_free(wi); goto out; } nretry = 0; do { n = sendto(wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, wi->tolen); send_errno = (n < 0) ? errno : 0; #if RTPP_DEBUG_netio >= 1 if (wi->debug != 0) { char daddr[MAX_AP_STRBUF]; addrport2char_r(wi->sendto, daddr, sizeof(daddr), ':'); if (n < 0) { RTPP_ELOG(wi->log, RTPP_LOG_DBUG, "sendto(%d, %p, %lld, %d, %p (%s), %d) = %d", wi->sock, wi->msg, (long long)wi->msg_len, wi->flags, wi->sendto, daddr, wi->tolen, n); } else if (n < wi->msg_len) { RTPP_LOG(wi->log, RTPP_LOG_DBUG, "sendto(%d, %p, %lld, %d, %p (%s), %d) = %d: short write", wi->sock, wi->msg, (long long)wi->msg_len, wi->flags, wi->sendto, daddr, wi->tolen, n); #if RTPP_DEBUG_netio >= 2 } else { RTPP_LOG(wi->log, RTPP_LOG_DBUG, "sendto(%d, %p, %d, %d, %p (%s), %d) = %d", wi->sock, wi->msg, wi->msg_len, wi->flags, wi->sendto, daddr, wi->tolen, n); #endif } } #endif if (n >= 0) { wi->nsend--; } else { /* "EPERM" is Linux thing, yield and retry */ if ((send_errno == EPERM || send_errno == ENOBUFS) && nretry < RTPP_ANETIO_MAX_RETRY) { sched_yield(); nretry++; } else { break; } } } while (wi->nsend > 0); rtpp_wi_free(wi); } #if RTPP_DEBUG_timers sleeptime += tp[1] - tp[0]; tp[0] = getdtime(); runtime += tp[0] - tp[1]; if ((run_n % 10000) == 0) { RTPP_LOG(args->glog, RTPP_LOG_DBUG, "rtpp_anetio_sthread(%p): run %ld aload = %f filtered = %f", \ args, run_n, runtime / (runtime + sleeptime), args->average_load.lastval); } if (runtime + sleeptime > 1.0) { recfilter_apply(&args->average_load, runtime / (runtime + sleeptime)); runtime = sleeptime = 0.0; } run_n += 1; #endif } out: return; }