From 01196a23874f5e826b0fd3641aac6b85ede32fa5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Wed, 24 Jul 2013 13:54:35 +0200 Subject: Don't let resolves delay handshakes --- src/fastd.c | 69 +++++++++++++++++++++++++++-------------------------------- src/peer.c | 42 ++++++++++++++++++++++++++++-------- src/peer.h | 1 + src/resolve.c | 20 +---------------- src/types.h | 2 ++ 5 files changed, 68 insertions(+), 66 deletions(-) diff --git a/src/fastd.c b/src/fastd.c index 13c28ba..6cfa442 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -793,28 +793,27 @@ static inline void schedule_handshake(fastd_context_t *ctx, fastd_peer_t *peer) } static void send_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { - if (!fastd_peer_may_connect(ctx, peer)) { - schedule_handshake(ctx, peer); - return; - } - if (!fastd_peer_is_established(peer)) fastd_peer_reset_socket(ctx, peer); - if (peer->sock) { - if (timespec_diff(&ctx->now, &peer->last_handshake) < ctx->conf->min_handshake_interval*1000 - && fastd_peer_address_equal(&peer->address, &peer->last_handshake_address)) { - pr_debug(ctx, "not sending a handshake to %P as we sent one a short time ago", peer); - } - else { - pr_debug(ctx, "sending handshake to %P...", peer); - peer->last_handshake = ctx->now; - peer->last_handshake_address = peer->address; - ctx->conf->protocol->handshake_init(ctx, peer->sock, &peer->local_address, &peer->address, peer); - } + if (!peer->sock) + return; + + if (peer->address.sa.sa_family == AF_UNSPEC) { + pr_debug(ctx, "not sending a handshake to %P (no valid address resolved)", peer); + return; } - schedule_handshake(ctx, peer); + if (timespec_diff(&ctx->now, &peer->last_handshake) < ctx->conf->min_handshake_interval*1000 + && fastd_peer_address_equal(&peer->address, &peer->last_handshake_address)) { + pr_debug(ctx, "not sending a handshake to %P as we sent one a short time ago", peer); + return; + } + + pr_debug(ctx, "sending handshake to %P...", peer); + peer->last_handshake = ctx->now; + peer->last_handshake_address = peer->address; + ctx->conf->protocol->handshake_init(ctx, peer->sock, &peer->local_address, &peer->address, peer); } static void handle_tasks(fastd_context_t *ctx) { @@ -822,15 +821,16 @@ static void handle_tasks(fastd_context_t *ctx) { while ((task = fastd_task_get(ctx)) != NULL) { switch (task->type) { case TASK_HANDSHAKE: - if (fastd_peer_is_dynamic(task->peer) && !(fastd_peer_is_floating(task->peer) && fastd_peer_is_established(task->peer))) { - if (fastd_peer_may_connect(ctx, task->peer)) - fastd_resolve_peer(ctx, task->peer); - else - schedule_handshake(ctx, task->peer); - } - else { - send_handshake(ctx, task->peer); - } + schedule_handshake(ctx, task->peer); + + if(!fastd_peer_may_connect(ctx, task->peer)) + break; + + if (fastd_peer_is_dynamic(task->peer) && !fastd_peer_is_established(task->peer)) + fastd_resolve_peer(ctx, task->peer); + + send_handshake(ctx, task->peer); + break; case TASK_KEEPALIVE: @@ -1045,18 +1045,18 @@ static void handle_socket(fastd_context_t *ctx, fastd_socket_t *sock) { handle_socket_receive(ctx, sock, &local_addr, &recvaddr, buffer); } -static void handle_resolv_returns(fastd_context_t *ctx) { +static void handle_resolve_returns(fastd_context_t *ctx) { fastd_resolve_return_t resolve_return; while (read(ctx->resolverfd, &resolve_return, sizeof(resolve_return)) < 0) { if (errno != EINTR) - exit_errno(ctx, "handle_resolv_return: read"); + exit_errno(ctx, "handle_resolve_return: read"); } char hostname[resolve_return.hostname_len+1]; while (read(ctx->resolverfd, hostname, resolve_return.hostname_len) < 0) { if (errno != EINTR) - exit_errno(ctx, "handle_resolv_return: read"); + exit_errno(ctx, "handle_resolve_return: read"); } hostname[resolve_return.hostname_len] = 0; @@ -1072,15 +1072,8 @@ static void handle_resolv_returns(fastd_context_t *ctx) { if (!fastd_peer_config_matches_dynamic(peer->config, &resolve_return.constraints)) continue; - peer->last_resolve_return = ctx->now; + fastd_peer_handle_resolve(ctx, peer, &resolve_return.addr); - if (fastd_peer_claim_address(ctx, peer, NULL, NULL, &resolve_return.addr)) { - send_handshake(ctx, peer); - } - else { - pr_warn(ctx, "hostname `%s' resolved to address %I which is used by a fixed peer", hostname, &resolve_return.addr); - schedule_handshake(ctx, peer); - } break; } } @@ -1141,7 +1134,7 @@ static void handle_input(fastd_context_t *ctx) { if (fds[0].revents & POLLIN) handle_tun(ctx); if (fds[1].revents & POLLIN) - handle_resolv_returns(ctx); + handle_resolve_returns(ctx); for (i = 2; i < ctx->n_socks+2; i++) { if (fds[i].revents & (POLLERR|POLLHUP|POLLNVAL)) diff --git a/src/peer.c b/src/peer.c index 668b5c9..422cd2e 100644 --- a/src/peer.c +++ b/src/peer.c @@ -152,6 +152,27 @@ static void reset_peer(fastd_context_t *ctx, fastd_peer_t *peer) { fastd_task_delete_peer(ctx, peer); } +static void init_handshake(fastd_context_t *ctx, fastd_peer_t *peer) { + unsigned delay = 0; + if (has_group_config_constraints(peer->group->conf)) + delay = fastd_rand(ctx, 0, 3000); + + if (!fastd_peer_is_established(peer)) + peer->state = STATE_HANDSHAKE; + + fastd_task_schedule_handshake(ctx, peer, delay); +} + +void fastd_peer_handle_resolve(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_peer_address_t *address) { + peer->last_resolve_return = ctx->now; + + if (!fastd_peer_claim_address(ctx, peer, NULL, NULL, address)) + pr_warn(ctx, "resolved address %I for peer %P which is used by a fixed peer", address, peer); + + if (peer->state == STATE_RESOLVING) + init_handshake(ctx, peer); +} + static void setup_peer(fastd_context_t *ctx, fastd_peer_t *peer) { if (!peer->config || peer->config->hostname) peer->address.sa.sa_family = AF_UNSPEC; @@ -174,12 +195,12 @@ static void setup_peer(fastd_context_t *ctx, fastd_peer_t *peer) { if (!peer->protocol_state) ctx->conf->protocol->init_peer_state(ctx, peer); - if (peer->address.sa.sa_family != AF_UNSPEC || fastd_peer_is_dynamic(peer)) { - unsigned delay = 0; - if (has_group_config_constraints(peer->group->conf)) - delay = fastd_rand(ctx, 0, 3000); - - fastd_task_schedule_handshake(ctx, peer, delay); + if (fastd_peer_is_dynamic(peer)) { + peer->state = STATE_RESOLVING; + fastd_resolve_peer(ctx, peer); + } + else if(peer->address.sa.sa_family != AF_UNSPEC) { + init_handshake(ctx, peer); } } @@ -404,9 +425,11 @@ fastd_peer_t* fastd_peer_add(fastd_context_t *ctx, fastd_peer_config_t *peer_con peer->protocol_state = NULL; peer->sock = NULL; peer->seen = (struct timespec){0, 0}; - setup_peer(ctx, peer); pr_verbose(ctx, "adding peer %P (group `%s')", peer, peer->group->conf->name); + + setup_peer(ctx, peer); + ctx->n_peers++; return peer; @@ -426,10 +449,11 @@ fastd_peer_t* fastd_peer_add_temporary(fastd_context_t *ctx) { peer->protocol_state = NULL; peer->sock = NULL; peer->seen = ctx->now; - setup_peer(ctx, peer); pr_debug(ctx, "adding temporary peer"); + setup_peer(ctx, peer); + return peer; } @@ -555,7 +579,7 @@ void fastd_peer_eth_addr_add(fastd_context_t *ctx, fastd_peer_t *peer, const fas int i; for (i = ctx->n_eth_addr-1; i > min; i--) ctx->eth_addr[i] = ctx->eth_addr[i-1]; - + ctx->eth_addr[min] = (fastd_peer_eth_addr_t){ *addr, peer, ctx->now }; pr_debug(ctx, "learned new MAC address %E on peer %P", addr, peer); diff --git a/src/peer.h b/src/peer.h index 43a6d02..a363424 100644 --- a/src/peer.h +++ b/src/peer.h @@ -111,6 +111,7 @@ bool fastd_peer_verify_temporary(fastd_context_t *ctx, fastd_peer_t *peer, const void fastd_peer_enable_temporary(fastd_context_t *ctx, fastd_peer_t *peer); void fastd_peer_set_established(fastd_context_t *ctx, fastd_peer_t *peer); bool fastd_peer_may_connect(fastd_context_t *ctx, fastd_peer_t *peer); +void fastd_peer_handle_resolve(fastd_context_t *ctx, fastd_peer_t *peer, const fastd_peer_address_t *address); bool fastd_peer_claim_address(fastd_context_t *ctx, fastd_peer_t *peer, fastd_socket_t *sock, const fastd_peer_address_t *local_addr, const fastd_peer_address_t *remote_addr); void fastd_peer_reset_socket(fastd_context_t *ctx, fastd_peer_t *peer); diff --git a/src/resolve.c b/src/resolve.c index 062eb91..103ba5f 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -109,25 +109,7 @@ void fastd_resolve_peer(fastd_context_t *ctx, fastd_peer_t *peer) { } if (timespec_diff(&ctx->now, &peer->last_resolve) < ctx->conf->min_resolve_interval*1000) { - pr_debug(ctx, "not resolving %P as it has been resolved a short time ago", peer); - - size_t hostname_len = strlen(peer->config->hostname); - char buf[sizeof(fastd_resolve_return_t) + hostname_len]; - - fastd_resolve_return_t *ret = (void*)buf; - char *hostname = buf + sizeof(fastd_resolve_return_t); - - memset(ret, 0, sizeof(fastd_resolve_return_t)); - - ret->constraints = peer->config->address; - ret->hostname_len = hostname_len; - memcpy(hostname, peer->config->hostname, hostname_len); - - ret->addr = peer->address; - - if (write(ctx->resolvewfd, buf, sizeof(buf)) < 0) - pr_error_errno(ctx, "can't write resolve return"); - + /* last resolve was just a few seconds ago */ return; } diff --git a/src/types.h b/src/types.h index f3553c2..0425db7 100644 --- a/src/types.h +++ b/src/types.h @@ -50,6 +50,8 @@ typedef enum fastd_drop_caps { typedef enum fastd_peer_state { STATE_INIT = 0, + STATE_RESOLVING, + STATE_HANDSHAKE, STATE_ESTABLISHED, } fastd_peer_state_t; -- cgit v1.2.3