X-Git-Url: https://tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fautoconnect.c;h=d25d65e30f528e0c237df8e4b70493bdf512e3c3;hb=refs%2Fheads%2F1.1;hp=1ea51b5eb6c6f708403e7d0e14844f9cd2edfe37;hpb=92fdabc439bdb5e16f64a4bf2ed1deda54f7c544;p=tinc diff --git a/src/autoconnect.c b/src/autoconnect.c index 1ea51b5e..d771078a 100644 --- a/src/autoconnect.c +++ b/src/autoconnect.c @@ -1,6 +1,6 @@ /* autoconnect.c -- automatic connection establishment - Copyright (C) 2017 Guus Sliepen + Copyright (C) 2017-2022 Guus Sliepen This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -19,36 +19,45 @@ #include "system.h" +#include "autoconnect.h" #include "connection.h" +#include "crypto.h" #include "logger.h" #include "node.h" #include "xalloc.h" -static void make_new_connection() { +static void make_new_connection(void) { /* Select a random node we haven't connected to yet. */ - int count = 0; - for splay_each(node_t, n, node_tree) { - if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) + uint32_t count = 0; + + for splay_each(node_t, n, &node_tree) { + if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) { continue; + } + count++; } - if(!count) + if(!count) { return; + } - int r = rand() % count; + uint32_t r = prng(count); - for splay_each(node_t, n, node_tree) { - if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) + for splay_each(node_t, n, &node_tree) { + if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) { continue; + } - if(r--) + if(r) { + --r; continue; + } bool found = false; - for list_each(outgoing_t, outgoing, outgoing_list) { - if(!strcmp(outgoing->name, n->name)) { + for list_each(outgoing_t, outgoing, &outgoing_list) { + if(outgoing->node == n) { found = true; break; } @@ -56,17 +65,17 @@ static void make_new_connection() { if(!found) { logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = xstrdup(n->name); - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); + outgoing_t *outgoing = xzalloc(sizeof(*outgoing)); + outgoing->node = n; + list_insert_tail(&outgoing_list, outgoing); + setup_outgoing_connection(outgoing, false); } break; } } -static void connect_to_unreachable() { +static void connect_to_unreachable(void) { /* Select a random known node. The rationale is that if there are many * reachable nodes, and only a few unreachable nodes, we don't want all * reachable nodes to try to connect to the unreachable ones at the @@ -74,85 +83,99 @@ static void connect_to_unreachable() { * are only a few reachable nodes, and many unreachable ones, we're * going to try harder to connect to them. */ - int r = rand() % node_tree->count; + uint32_t r = prng(node_tree.count); - for splay_each(node_t, n, node_tree) { - if(r--) + for splay_each(node_t, n, &node_tree) { + if(r--) { continue; + } /* Is it unreachable and do we know an address for it? If not, return. */ - if(n == myself || n->connection || n->status.reachable || !n->status.has_address) + if(n == myself || n->connection || n->status.reachable || !n->status.has_address) { return; + } - /* Are we already trying to make an outgoing connection to it? If not, return. */ - for list_each(outgoing_t, outgoing, outgoing_list) - if(!strcmp(outgoing->name, n->name)) + /* Are we already trying to make an outgoing connection to it? If so, return. */ + for list_each(outgoing_t, outgoing, &outgoing_list) { + if(outgoing->node == n) { return; + } + } logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name); - outgoing_t *outgoing = xzalloc(sizeof *outgoing); - outgoing->name = xstrdup(n->name); - list_insert_tail(outgoing_list, outgoing); - setup_outgoing_connection(outgoing); + outgoing_t *outgoing = xzalloc(sizeof(*outgoing)); + outgoing->node = n; + list_insert_tail(&outgoing_list, outgoing); + setup_outgoing_connection(outgoing, false); return; } } -static void drop_superfluous_outgoing_connection() { +static void drop_superfluous_outgoing_connection(void) { /* Choose a random outgoing connection to a node that has at least one other connection. */ - int count = 0; - for list_each(connection_t, c, connection_list) { - if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) + uint32_t count = 0; + + for list_each(connection_t, c, &connection_list) { + if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree.count < 2) { continue; + } + count++; } - if(!count) + if(!count) { return; + } - int r = rand() % count; + uint32_t r = prng(count); - for list_each(connection_t, c, connection_list) { - if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree->count < 2) + for list_each(connection_t, c, &connection_list) { + if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree.count < 2) { continue; - - if(r--) + } + + if(r--) { continue; + } logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name); - list_delete(outgoing_list, c->outgoing); + list_delete(&outgoing_list, c->outgoing); c->outgoing = NULL; terminate_connection(c, c->edge); break; } } -static void drop_superfluous_pending_connections() { - for list_each(outgoing_t, o, outgoing_list) { +static void drop_superfluous_pending_connections(void) { + for list_each(outgoing_t, o, &outgoing_list) { /* Only look for connections that are waiting to be retried later. */ bool found = false; - for list_each(connection_t, c, connection_list) { + + for list_each(connection_t, c, &connection_list) { if(c->outgoing == o) { found = true; break; } } - if(found) + if(found) { continue; + } - logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name); - list_delete_node(outgoing_list, node); + logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->node->name); + list_delete_node(&outgoing_list, node); } } -void do_autoconnect() { +void do_autoconnect(void) { /* Count number of active connections. */ - int nc = 0; - for list_each(connection_t, c, connection_list) { - if(c->edge) + uint32_t nc = 0; + + for list_each(connection_t, c, &connection_list) { + if(c->edge) { nc++; + } } /* Less than 3 connections? Eagerly try to make a new one. */ @@ -160,15 +183,15 @@ void do_autoconnect() { make_new_connection(); return; } - + /* More than 3 connections? See if we can get rid of a superfluous one. */ - if(nc > 3) + if(nc > 3) { drop_superfluous_outgoing_connection(); + } + /* Drop pending outgoing connections from the outgoing list. */ + drop_superfluous_pending_connections(); /* Check if there are unreachable nodes that we should try to connect to. */ connect_to_unreachable(); - - /* Drop pending outgoing connections from the outgoing list. */ - drop_superfluous_pending_connections(); }