]> git.meshlink.io Git - meshlink/blobdiff - src/net.c
Restart UDP key exchange after PingTimeout if it didn't work.
[meshlink] / src / net.c
index c05564e3fd4371ee7bc397446b8679f92a2a99d2..4045c136fa676912ac42110e6eb0920974cf8650 100644 (file)
--- a/src/net.c
+++ b/src/net.c
 #include "protocol.h"
 #include "xalloc.h"
 
+static const int min(int a, int b) {
+       return a < b ? a : b;
+}
+
 /*
   Terminate a connection:
   - Mark it as inactive
@@ -39,7 +43,7 @@
   - Check if we need to retry making an outgoing connection
 */
 void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) {
-       logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
+       logger(mesh, MESHLINK_INFO, "Closing connection with %s (%s)", c->name, c->hostname);
 
        c->status.active = false;
 
@@ -94,12 +98,18 @@ void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report)
 */
 static void timeout_handler(event_loop_t *loop, void *data) {
        meshlink_handle_t *mesh = loop->data;
+       logger(mesh, MESHLINK_DEBUG, "timeout_handler()");
 
        for list_each(connection_t, c, mesh->connections) {
+               // Also make sure that if outstanding key requests for the UDP counterpart of a connection has timed out, we restart it.
+               if(c->node) {
+                       if(c->node->status.waitingforkey && c->node->last_req_key + mesh->pingtimeout <= mesh->loop.now.tv_sec)
+                               send_req_key(mesh, c->node);
+               }
                if(c->last_ping_time + mesh->pingtimeout <= mesh->loop.now.tv_sec) {
                        if(c->status.active) {
                                if(c->status.pinged) {
-                                       logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)mesh->loop.now.tv_sec - c->last_ping_time);
+                                       logger(mesh, MESHLINK_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)mesh->loop.now.tv_sec - c->last_ping_time);
                                } else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) {
                                        send_ping(mesh, c);
                                        continue;
@@ -108,9 +118,9 @@ static void timeout_handler(event_loop_t *loop, void *data) {
                                }
                        } else {
                                if(c->status.connecting)
-                                       logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
+                                       logger(mesh, MESHLINK_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
                                else
-                                       logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
+                                       logger(mesh, MESHLINK_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
                        }
                        terminate_connection(mesh, c, c->status.active);
                }
@@ -154,8 +164,9 @@ static void cond_add_connection(meshlink_handle_t *mesh, int rand_modulo, bool (
                if(!found) {
                        //TODO: if the node is blacklisted the connection will not happen, but
                        //the user will read this debug message "Autoconnecting to %s" that is misleading
-                       logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
+                       logger(mesh, MESHLINK_INFO, "Autoconnecting to %s", n->name);
                        outgoing_t *outgoing = xzalloc(sizeof *outgoing);
+                       outgoing->mesh = mesh;
                        outgoing->name = xstrdup(n->name);
                        list_insert_tail(mesh->outgoings, outgoing);
                        setup_outgoing_connection(mesh, outgoing);
@@ -196,7 +207,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
        */
 
        if(mesh->contradicting_del_edge > 100 && mesh->contradicting_add_edge > 100) {
-               logger(DEBUG_ALWAYS, LOG_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", mesh->sleeptime);
+               logger(mesh, MESHLINK_WARNING, "Possible node with same Name as us! Sleeping %d seconds.", mesh->sleeptime);
                usleep(mesh->sleeptime * 1000000LL);
                mesh->sleeptime *= 2;
                if(mesh->sleeptime < 0)
@@ -210,6 +221,8 @@ static void periodic_handler(event_loop_t *loop, void *data) {
        mesh->contradicting_add_edge = 0;
        mesh->contradicting_del_edge = 0;
 
+       int timeout = 5;
+
        /* If AutoConnect is set, check if we need to make or break connections. */
 
        if(autoconnect && mesh->nodes->count > 1) {
@@ -234,7 +247,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                           outgoing connection to this node.
                        */
                        cond_add_connection(mesh, mesh->nodes->count, &found_random_node);
-               } else if (num_unreachable > 0) {
+               } else if(num_unreachable > 0) {
                        /* Min number of connections established. Now try
                           to connect to some unreachable nodes to attempt
                           to heal possible partitions.
@@ -260,7 +273,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                                if(!c->outgoing || !c->node || c->node->edge_tree->count < 2)
                                        break;
 
-                               logger(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
+                               logger(mesh, MESHLINK_INFO, "Autodisconnecting from %s", c->name);
                                list_delete(mesh->outgoings, c->outgoing);
                                c->outgoing = NULL;
                                terminate_connection(mesh, c, c->status.active);
@@ -289,7 +302,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                                        }
                                }
                                if(!found) {
-                                       logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
+                                       logger(mesh, MESHLINK_INFO, "Cancelled outgoing connection to %s", o->name);
                                        /* The node variable is leaked in from using the list_each macro.
                                           The o variable could be used, but using node directly
                                           is more efficient.
@@ -298,9 +311,12 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                                }
                        }
                }
+
+               if (nc + mesh->outgoings->count < min(autoconnect, mesh->nodes->count - 1))
+                       timeout = 0;
        }
 
-       timeout_set(&mesh->loop, data, &(struct timeval){5, rand() % 100000});
+       timeout_set(&mesh->loop, data, &(struct timeval){timeout, rand() % 100000});
 }
 
 void handle_meta_connection_data(meshlink_handle_t *mesh, connection_t *c) {
@@ -333,14 +349,14 @@ void retry(meshlink_handle_t *mesh) {
 */
 int main_loop(meshlink_handle_t *mesh) {
        timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval){mesh->pingtimeout, rand() % 100000});
-       timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval){mesh->pingtimeout, rand() % 100000});
+       timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval){0, 0});
 
        //Add signal handler
        mesh->datafromapp.signum = 0;
        signal_add(&(mesh->loop),&(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue,mesh, mesh->datafromapp.signum);
 
        if(!event_loop_run(&mesh->loop)) {
-               logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno));
+               logger(mesh, MESHLINK_ERROR, "Error while waiting for input: %s", strerror(errno));
                return 1;
        }