]> git.meshlink.io Git - meshlink/commitdiff
Speed up initial autoconnect after joining a mesh.
authorGuus Sliepen <guus@meshlink.io>
Thu, 30 May 2019 21:34:35 +0000 (23:34 +0200)
committerGuus Sliepen <guus@meshlink.io>
Thu, 13 Jun 2019 21:48:14 +0000 (23:48 +0200)
When we just joined a mesh, we quickly want to establish redundant
connections. We do this by resetting the outgoing timer if we receive a
public key for a node that we are trying to connect to, and by speeding up
the autoconnect algorithm if we don't have 3 connections (in progress) yet.

src/net.c
src/protocol_key.c
test/Makefile.am
test/trio2.c [new file with mode: 0644]
test/trio2.test [new file with mode: 0755]

index a1cccbdf8e875471064f7d0b1367677814e75afe..a42d933bef822a375fea4c5b4e823d4f6553f683 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -585,6 +585,10 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        terminate_connection(mesh, disconnect_from->connection, disconnect_from->connection->status.active);
                }
 
+               // reduce timeout if we don't have enough connections + outgoings
+               if(cur_connects + mesh->outgoings->count < 3) {
+                       timeout = 1;
+               }
 
                // done!
 
index c1ffe322aa06ce24046494923ad4e8cdece13a73..64a0ce8faff20b743ed81740d925fe613dd04793 100644 (file)
@@ -133,6 +133,17 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char *
 
                logger(mesh, MESHLINK_INFO, "Learned ECDSA public key from %s", from->name);
                from->status.dirty = true;
+
+               /* If we are trying to form an outgoing connection to this node, retry immediately */
+               for list_each(outgoing_t, outgoing, mesh->outgoings) {
+                       if(outgoing->node == from && outgoing->ev.cb) {
+                               outgoing->timeout = 0;
+                               timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval) {
+                                       0, 0
+                               });
+                       }
+               }
+
                return true;
        }
 
index 45ad064cd8beaae0c02a0f20207b9a8664f1a4f2..edeb1a55e3e044a2e7d61e9f8c664e6d16517c2c 100644 (file)
@@ -10,7 +10,8 @@ TESTS = \
        import-export.test \
        invite-join.test \
        sign-verify.test \
-       trio.test
+       trio.test \
+       trio2.test
 
 if BLACKBOX_TESTS
 SUBDIRS = blackbox
@@ -34,7 +35,8 @@ check_PROGRAMS = \
        import-export \
        invite-join \
        sign-verify \
-       trio
+       trio \
+       trio2
 
 if INSTALL_TESTS
 bin_PROGRAMS = $(check_PROGRAMS)
@@ -78,3 +80,6 @@ sign_verify_LDADD = ../src/libmeshlink.la
 
 trio_SOURCES = trio.c
 trio_LDADD = ../src/libmeshlink.la
+
+trio2_SOURCES = trio2.c
+trio2_LDADD = ../src/libmeshlink.la
diff --git a/test/trio2.c b/test/trio2.c
new file mode 100644 (file)
index 0000000..d9b3a0f
--- /dev/null
@@ -0,0 +1,132 @@
+#define _GNU_SOURCE
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <sys/time.h>
+
+#include "meshlink.h"
+#include "devtools.h"
+#include "utils.h"
+
+static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
+       (void)mesh;
+
+       static struct timeval tv0;
+       struct timeval tv;
+
+       if(tv0.tv_sec == 0) {
+               gettimeofday(&tv0, NULL);
+       }
+
+       gettimeofday(&tv, NULL);
+       fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000);
+
+       if(mesh) {
+               fprintf(stderr, "(%s) ", mesh->name);
+       }
+
+       fprintf(stderr, "[%d] %s\n", level, text);
+}
+
+static bool received = false;
+
+static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+       (void)mesh;
+       (void)source;
+
+       fprintf(stderr, "RECEIVED SOMETHING\n");
+
+       if(len == 5 && !memcmp(data, "Hello", 5)) {
+               received = true;
+       }
+}
+
+int main() {
+       // Create three instances.
+
+       const char *name[3] = {"foo", "bar", "baz"};
+       meshlink_handle_t *mesh[3];
+       char *data[3];
+
+       for(int i = 0; i < 3; i++) {
+               char *path;
+               int ret_val;
+               (void)ret_val;
+               ret_val = asprintf(&path, "trio2_conf.%d", i);
+               assert(path);
+
+               mesh[i] = meshlink_open(path, name[i], "trio2", DEV_CLASS_BACKBONE);
+               assert(mesh[i]);
+
+               meshlink_add_address(mesh[i], "localhost");
+
+               data[i] = meshlink_export(mesh[i]);
+               assert(data[i]);
+       }
+
+       meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb);
+
+       // first node knows the two other nodes
+
+       for(int i = 1; i < 3; i++) {
+               assert(meshlink_import(mesh[i], data[0]));
+               assert(meshlink_import(mesh[0], data[i]));
+
+               assert(meshlink_get_node(mesh[i], name[0]));
+               assert(meshlink_get_node(mesh[0], name[i]));
+       }
+
+       // second and third node should not know each other yet
+
+       assert(!meshlink_get_node(mesh[1], name[2]));
+       assert(!meshlink_get_node(mesh[2], name[1]));
+
+       // start the nodes
+
+       for(int i = 0; i < 3; i++) {
+               assert(meshlink_start(mesh[i]));
+       }
+
+       // the nodes should now learn about each other
+
+       assert_after(meshlink_get_node(mesh[1], name[2]), 5);
+       assert_after(meshlink_get_node(mesh[2], name[1]), 5);
+
+       // Check that the second and third node autoconnect to each other
+
+       devtool_edge_t *edges = NULL;
+       size_t nedges = 0;
+       assert_after((edges = devtool_get_all_edges(mesh[1], edges, &nedges), nedges == 3), 15);
+
+       // Stop the nodes nodes
+
+       for(int i = 0; i < 3; i++) {
+               meshlink_stop(mesh[i]);
+       }
+
+       // Start just the other two nodes
+
+       meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb);
+
+       for(int i = 1; i < 3; i++) {
+               assert(meshlink_start(mesh[i]));
+       }
+
+       assert(meshlink_get_node(mesh[1], name[2]));
+       assert(meshlink_get_node(mesh[2], name[1]));
+
+       // Communication should still be possible
+
+       received = false;
+       meshlink_set_receive_cb(mesh[1], receive_cb);
+       assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 25);
+
+       // Clean up.
+
+       for(int i = 0; i < 3; i++) {
+               meshlink_close(mesh[i]);
+       }
+}
diff --git a/test/trio2.test b/test/trio2.test
new file mode 100755 (executable)
index 0000000..426ba50
--- /dev/null
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+rm -Rf trio2_conf.*
+./trio2