From 6e39dfe32584e9edaa45d0df31765839dae219c5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 3 May 2012 20:00:20 +0200 Subject: Use pipe to transmit resolved addresses to main thread --- src/fastd.c | 95 ++++++++++++++++++++++++++++++----------------------------- src/fastd.h | 9 ++---- src/resolve.c | 20 +++++-------- 3 files changed, 60 insertions(+), 64 deletions(-) diff --git a/src/fastd.c b/src/fastd.c index 49238f3..d001ba4 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -55,17 +55,6 @@ static void on_terminate(int signo) { terminate = true; } -static void on_sigusr1(int signo, siginfo_t *siginfo, void *context) { - if (siginfo->si_code != SI_QUEUE || !siginfo->si_value.sival_ptr) - return; - - fastd_resolve_return *ret = siginfo->si_value.sival_ptr; - - ret->next = ret->ctx->resolve_returns; - ret->ctx->resolve_returns = ret; -} - - static void init_signals(fastd_context *ctx) { struct sigaction action; @@ -83,11 +72,16 @@ static void init_signals(fastd_context *ctx) { exit_errno(ctx, "sigaction"); if(sigaction(SIGINT, &action, NULL)) exit_errno(ctx, "sigaction"); +} - action.sa_flags = SA_SIGINFO; - action.sa_sigaction = on_sigusr1; - if(sigaction(SIGUSR1, &action, NULL)) - exit_errno(ctx, "sigaction"); +static void init_pipes(fastd_context *ctx) { + int pipefd[2]; + + if (pipe(pipefd)) + exit_errno(ctx, "pipe"); + + ctx->resolverfd = pipefd[0]; + ctx->resolvewfd = pipefd[1]; } static void init_sockets(fastd_context *ctx) { @@ -530,6 +524,40 @@ static void handle_socket(fastd_context *ctx, int sockfd) { } } +static void handle_resolv_returns(fastd_context *ctx) { + fastd_resolve_return resolve_return; + + if (read(ctx->resolverfd, &resolve_return, sizeof(resolve_return)) < 0) { + if (errno != EINTR) + pr_warn(ctx, "recvfrom: %s", strerror(errno)); + + return; + } + + fastd_peer *peer; + for (peer = ctx->peers; peer; peer = peer->next) { + if (!peer->config) + continue; + + if (!strequal(peer->config->hostname, resolve_return.hostname)) + continue; + + if (!fastd_peer_config_matches_dynamic(peer->config, &resolve_return.constraints)) + continue; + + if (fastd_peer_claim_address(ctx, peer, &resolve_return.addr)) { + send_handshake(ctx, peer); + } + else { + pr_warn(ctx, "hostname `%s' resolved to address %I which is used by a fixed peer", resolve_return.hostname, &resolve_return.addr); + fastd_task_schedule_handshake(ctx, peer, fastd_rand(ctx, 17500, 22500)); + } + break; + } + + free(resolve_return.hostname); +} + static void handle_input(fastd_context *ctx) { struct pollfd fds[3]; fds[0].fd = ctx->tunfd; @@ -538,13 +566,15 @@ static void handle_input(fastd_context *ctx) { fds[1].events = POLLIN; fds[2].fd = ctx->sock6fd; fds[2].events = POLLIN; + fds[3].fd = ctx->resolverfd; + fds[3].events = POLLIN; int timeout = fastd_task_timeout(ctx); if (timeout < 0 || timeout > 60000) timeout = 60000; /* call maintenance at least once a minute */ - int ret = poll(fds, 3, timeout); + int ret = poll(fds, 4, timeout); if (ret < 0) { if (errno == EINTR) return; @@ -560,6 +590,8 @@ static void handle_input(fastd_context *ctx) { handle_socket(ctx, ctx->sockfd); if (fds[2].revents & POLLIN) handle_socket(ctx, ctx->sock6fd); + if (fds[3].revents & POLLIN) + handle_resolv_returns(ctx); } static void cleanup_peers(fastd_context *ctx) { @@ -575,34 +607,6 @@ static void cleanup_peers(fastd_context *ctx) { } } - -static void handle_resolv_returns(fastd_context *ctx) { - while (ctx->resolve_returns) { - fastd_peer *peer; - for (peer = ctx->peers; peer; peer = peer->next) { - if (!peer->config) - continue; - - if (!strequal(peer->config->hostname, ctx->resolve_returns->hostname)) - continue; - - if (!fastd_peer_config_matches_dynamic(peer->config, &ctx->resolve_returns->constraints)) - continue; - - if (fastd_peer_claim_address(ctx, peer, &ctx->resolve_returns->addr)) - send_handshake(ctx, peer); - else - pr_warn(ctx, "hostname `%s' resolved to address %I which is used by a fixed peer", ctx->resolve_returns->hostname, ctx->resolve_returns->addr); - break; - } - - fastd_resolve_return *next = ctx->resolve_returns->next; - free(ctx->resolve_returns->hostname); - free(ctx->resolve_returns); - ctx->resolve_returns = next; - } -} - static void maintenance(fastd_context *ctx) { cleanup_peers(ctx); @@ -617,6 +621,7 @@ int main(int argc, char *argv[]) { fastd_random_bytes(&ctx, &ctx.randseed, sizeof(ctx.randseed), false); init_signals(&ctx); + init_pipes(&ctx); fastd_config conf; fastd_configure(&ctx, &conf, argc, argv); @@ -658,8 +663,6 @@ int main(int argc, char *argv[]) { fastd_reconfigure(&ctx, &conf); } - handle_resolv_returns(&ctx); - pthread_sigmask(SIG_SETMASK, &oldset, NULL); } diff --git a/src/fastd.h b/src/fastd.h index 1de2e2d..6a503d8 100644 --- a/src/fastd.h +++ b/src/fastd.h @@ -101,10 +101,6 @@ union _fastd_peer_address { }; struct _fastd_resolve_return { - fastd_resolve_return *next; - - fastd_context *ctx; - char *hostname; fastd_peer_address constraints; @@ -173,6 +169,9 @@ struct _fastd_context { fastd_peer *peers; fastd_queue task_queue; + int resolverfd; + int resolvewfd; + int tunfd; int sockfd; int sock6fd; @@ -184,8 +183,6 @@ struct _fastd_context { unsigned int randseed; fastd_protocol_state *protocol_state; - - fastd_resolve_return *resolve_returns; }; struct _fastd_string_stack { diff --git a/src/resolve.c b/src/resolve.c index 23e7f32..6848a11 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -31,7 +31,7 @@ #include #include -#include +#include typedef struct _resolv_arg { @@ -70,25 +70,21 @@ static void* resolve_peer(void *varg) { error = true; } - fastd_resolve_return *ret = malloc(sizeof(fastd_resolve_return)); + fastd_resolve_return ret; - ret->ctx = arg->ctx; - - ret->hostname = arg->hostname; - ret->constraints = arg->constraints; + ret.hostname = arg->hostname; + ret.constraints = arg->constraints; if (!error) { pr_debug(arg->ctx, "Resolved host `%s' successfully", arg->hostname); - memcpy(&ret->addr, res->ai_addr, res->ai_addrlen); + memcpy(&ret.addr, res->ai_addr, res->ai_addrlen); } else { - ret->addr.sa.sa_family = AF_UNSPEC; + ret.addr.sa.sa_family = AF_UNSPEC; } - union sigval sigval; - sigval.sival_ptr = ret; - if (pthread_sigqueue(arg->master_thread, SIGUSR1, sigval)) - exit_errno(arg->ctx, "pthread_sigqueue"); + if (write(arg->ctx->resolvewfd, &ret, sizeof(ret)) < 0) + exit_errno(arg->ctx, "write"); freeaddrinfo(res); free(arg); -- cgit v1.2.3