X-Git-Url: https://git.distorted.org.uk/~mdw/tripe/blobdiff_plain/47828bd9813b146e8569355b3083847299dd8729..78e45b53a3904ce832e8a7e4654bc2efe9fb2c2c:/server/tripe.c diff --git a/server/tripe.c b/server/tripe.c index 565c83dd..bf217b37 100644 --- a/server/tripe.c +++ b/server/tripe.c @@ -36,7 +36,10 @@ sel_state sel; static sel_timer it; #define T_INTERVAL MIN(1) -/*----- Main code ---------------------------------------------------------*/ +static unsigned iv_nreasons = 0; +static struct timeval iv_next = { 0, 0 }; + +/*----- The interval timer ------------------------------------------------*/ /* --- @interval@ --- * * @@ -50,15 +53,104 @@ static sel_timer it; static void interval(struct timeval *tv, void *v) { - struct timeval tvv; T( trace(T_PEER, "peer: interval timer"); ) + iv_next = *tv; rand_seed(RAND_GLOBAL, MAXHASHSZ); p_interval(); - tvv = *tv; - tvv.tv_sec += T_INTERVAL; - sel_addtimer(&sel, &it, &tvv, interval, v); + iv_next.tv_sec += T_INTERVAL; + sel_addtimer(&sel, &it, &iv_next, interval, v); +} + +/* --- @iv_addreason@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Adds an `interval timer reason'; if there are no others, the + * interval timer is engaged. + */ + +void iv_addreason(void) +{ + struct timeval tv; + + if (!iv_nreasons) { + gettimeofday(&tv, 0); + if (TV_CMP(&tv, >=, &iv_next)) interval(&tv, 0); + else sel_addtimer(&sel, &it, &iv_next, interval, 0); + } + iv_nreasons++; +} + +/* --- @iv_rmreason@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Removes an interval timer reason; if there are none left, the + * interval timer is disengaged. + */ + +void iv_rmreason(void) +{ + assert(iv_nreasons); iv_nreasons--; + if (!iv_nreasons) sel_rmtimer(&it); +} + +/*----- The main loop -----------------------------------------------------*/ + +/* --- @lp_init@ --- * + * + * Arguments: --- + * + * Returns: --- + * + * Use: Initializes the main loop. Most importantly, this sets up + * the select multiplexor that everything else hooks onto. + */ + +void lp_init(void) +{ + rand_noisesrc(RAND_GLOBAL, &noise_source); + rand_seed(RAND_GLOBAL, MAXHASHSZ); + gettimeofday(&iv_next, 0); iv_next.tv_sec += T_INTERVAL; + signal(SIGPIPE, SIG_IGN); + sel_init(&sel); + sig_init(&sel); +} + +/* --- @lp_run@ --- * + * + * Arguments: --- + * + * Returns: Zero on successful termination; @-1@ if things went wrong. + * + * Use: Cranks the main loop until it should be cranked no more. + */ + +int lp_run(void) +{ + int nerr = 0; + + for (;;) { + a_preselect(); + if (!sel_select(&sel)) nerr = 0; + else if (errno != EINTR && errno != EAGAIN) { + a_warn("SERVER", "select-error", "?ERRNO", A_END); + nerr++; + if (nerr > 8) { + a_warn("ABORT", "repeated-select-errors", A_END); + abort(); + } + } + } + return (0); } +/*----- Main code ---------------------------------------------------------*/ + /* --- @main@ --- * * * Arguments: @int argc@ = number of command line arguments @@ -125,9 +217,8 @@ int main(int argc, char *argv[]) struct addrinfo aihint = { 0 }, *ailist; unsigned f = 0; int i; - int err, selerr = 0; + int err; unsigned af; - struct timeval tv; uid_t u = -1; gid_t g = -1; @@ -287,14 +378,8 @@ int main(int argc, char *argv[]) dir, strerror(errno)); } - sel_init(&sel); - sig_init(&sel); - rand_noisesrc(RAND_GLOBAL, &noise_source); - rand_seed(RAND_GLOBAL, MAXHASHSZ); - signal(SIGPIPE, SIG_IGN); - for (i = 0; tunnels[i]; i++) - tunnels[i]->init(); - p_init(ailist); freeaddrinfo(ailist); + lp_init(); + if (!(f & f_daemon)) { af = AF_WARN; #ifndef NTRACE @@ -303,35 +388,37 @@ int main(int argc, char *argv[]) if (f & f_foreground) af |= AF_FOREGROUND; a_create(STDIN_FILENO, STDOUT_FILENO, af); + a_switcherr(); } - ps_split(f & f_daemon); - a_init(csock, u, g, csockmode); + + p_init(); + for (i = 0; tunnels[i]; i++) + tunnels[i]->init(); + p_bind(ailist); freeaddrinfo(ailist); + + for (i = 0; tunnels[i]; i++) { + if (tunnels[i]->flags&TUNF_PRIVOPEN) { + ps_split(f & f_daemon); + break; + } + } + + a_init(); + a_signals(); + a_listen(csock, u, g, csockmode); u_setugid(u, g); km_init(kr_priv, kr_pub, tag_priv); + kx_init(); if (f & f_daemon) { - if (daemonize()) - die(EXIT_FAILURE, "couldn't become a daemon: %s", strerror(errno)); - a_daemon(); - } - - tv.tv_sec = time(0) + T_INTERVAL; - tv.tv_usec = 0; - sel_addtimer(&sel, &it, &tv, interval, 0); - - for (;;) { - a_preselect(); - if (!sel_select(&sel)) - selerr = 0; - else if (errno != EINTR && errno != EAGAIN) { - a_warn("SERVER", "select-error", "?ERRNO", A_END); - selerr++; - if (selerr > 8) { - a_warn("ABORT", "repeated-select-errors", A_END); - abort(); - } + if (daemonize()) { + a_warn("SERVER", "daemon-error", "?ERRNO", A_END); + exit(EXIT_FAILURE); } + a_daemon(); + a_switcherr(); } + lp_run(); return (0); }