GitHub CI: update list of container images
[tinc] / src / autoconnect.c
index 132467e..d771078 100644 (file)
@@ -1,6 +1,6 @@
 /*
     autoconnect.c -- automatic connection establishment
-    Copyright (C) 2017 Guus Sliepen <guus@tinc-vpn.org>
+    Copyright (C) 2017-2022 Guus Sliepen <guus@tinc-vpn.org>
 
     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
 
 #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;
+       uint32_t count = 0;
 
-       for splay_each(node_t, n, node_tree) {
+       for splay_each(node_t, n, &node_tree) {
                if(n == myself || n->connection || !(n->status.has_address || n->status.reachable)) {
                        continue;
                }
@@ -40,21 +42,22 @@ static void make_new_connection() {
                return;
        }
 
-       int r = rand() % count;
+       uint32_t r = prng(count);
 
-       for splay_each(node_t, n, node_tree) {
+       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;
                        }
@@ -63,8 +66,8 @@ 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);
+                       outgoing->node = n;
+                       list_insert_tail(&outgoing_list, outgoing);
                        setup_outgoing_connection(outgoing, false);
                }
 
@@ -72,7 +75,7 @@ static void make_new_connection() {
        }
 }
 
-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
@@ -80,9 +83,9 @@ 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) {
+       for splay_each(node_t, n, &node_tree) {
                if(r--) {
                        continue;
                }
@@ -92,28 +95,29 @@ static void connect_to_unreachable() {
                        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);
+               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;
+       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) {
+       for list_each(connection_t, c, &connection_list) {
+               if(!c->edge || !c->outgoing || !c->node || c->node->edge_tree.count < 2) {
                        continue;
                }
 
@@ -124,10 +128,10 @@ static void drop_superfluous_outgoing_connection() {
                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;
                }
 
@@ -136,19 +140,19 @@ static void drop_superfluous_outgoing_connection() {
                }
 
                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;
@@ -159,16 +163,16 @@ static void drop_superfluous_pending_connections() {
                        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;
+       uint32_t nc = 0;
 
-       for list_each(connection_t, c, connection_list) {
+       for list_each(connection_t, c, &connection_list) {
                if(c->edge) {
                        nc++;
                }
@@ -185,10 +189,9 @@ void do_autoconnect() {
                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();
 }