]> git.meshlink.io Git - meshlink-tiny/commitdiff
Remove support for multiple connections.
authorGuus Sliepen <guus@meshlink.io>
Sat, 19 Jun 2021 20:43:17 +0000 (22:43 +0200)
committerGuus Sliepen <guus@meshlink.io>
Sat, 19 Jun 2021 20:43:17 +0000 (22:43 +0200)
examples/chat.c
src/connection.c
src/meshlink.c
src/meshlink_internal.h
src/meta.c
src/net.c
src/net_setup.c
src/net_socket.c
src/node.c
src/protocol_auth.c
src/protocol_key.c

index bf3170916fbfe1c9e4cdb9633b78a91a5543065a..5d06538c3915a8a943ecfa7c2fde23a090513fa0 100644 (file)
@@ -41,9 +41,6 @@ static void node_status(meshlink_handle_t *mesh, meshlink_node_t *node, bool rea
        }
 }
 
-static meshlink_node_t **nodes;
-static size_t nnodes;
-
 static void parse_command(meshlink_handle_t *mesh, char *buf) {
        char *arg = strchr(buf, ' ');
 
@@ -69,30 +66,6 @@ static void parse_command(meshlink_handle_t *mesh, char *buf) {
                        fprintf(stderr, "Could not restart MeshLink: %s\n", meshlink_strerror(meshlink_errno));
                        exit(1);
                }
-       } else if(!strcasecmp(buf, "who")) {
-               if(!arg) {
-                       nodes = meshlink_get_all_nodes(mesh, nodes, &nnodes);
-
-                       if(!nnodes) {
-                               fprintf(stderr, "Could not get list of nodes: %s\n", meshlink_strerror(meshlink_errno));
-                       } else {
-                               printf("%zu known nodes:", nnodes);
-
-                               for(size_t i = 0; i < nnodes; i++) {
-                                       printf(" %s", nodes[i]->name);
-                               }
-
-                               printf("\n");
-                       }
-               } else {
-                       meshlink_node_t *node = meshlink_get_node(mesh, arg);
-
-                       if(!node) {
-                               fprintf(stderr, "Error looking up '%s': %s\n", arg, meshlink_strerror(meshlink_errno));
-                       } else {
-                               printf("Node %s found\n", arg);
-                       }
-               }
        } else if(!strcasecmp(buf, "quit")) {
                printf("Bye!\n");
                fclose(stdin);
index 9cc64914cd4ba217a85d824f9ff378e5f41884b1..97e391823ec1272dfb338b272de40e7ed82efe35 100644 (file)
 #include "xalloc.h"
 
 void init_connections(meshlink_handle_t *mesh) {
-       assert(!mesh->connections);
-       assert(!mesh->everyone);
-
-       mesh->connections = list_alloc((list_action_t) free_connection);
-       mesh->everyone = new_connection();
-       mesh->everyone->name = xstrdup("mesh->everyone");
+       assert(!mesh->connection);
 }
 
 void exit_connections(meshlink_handle_t *mesh) {
-       if(mesh->connections) {
-               list_delete_list(mesh->connections);
-       }
-
-       if(mesh->everyone) {
-               free_connection(mesh->everyone);
+       if(mesh->connection) {
+               free_connection(mesh->connection);
        }
 
-       mesh->connections = NULL;
-       mesh->everyone = NULL;
+       mesh->connection = NULL;
 }
 
 connection_t *new_connection(void) {
@@ -78,14 +68,17 @@ void free_connection(connection_t *c) {
 
 void connection_add(meshlink_handle_t *mesh, connection_t *c) {
        assert(c);
+       assert(!mesh->connection);
 
        c->mesh = mesh;
-       list_insert_tail(mesh->connections, c);
+       mesh->connection = c;
 }
 
 void connection_del(meshlink_handle_t *mesh, connection_t *c) {
        assert(c);
+       assert(mesh->connection == c);
 
        io_del(&mesh->loop, &c->io);
-       list_delete(mesh->connections, c);
+       free(mesh->connection);
+       mesh->connection = NULL;
 }
index 8b3b841f5862b8cfe73313362d28081421cf1fa8..19d9fdca9d32f31c9acd92ea330ce51a3686968f 100644 (file)
@@ -488,32 +488,17 @@ static bool ecdsa_keygen(meshlink_handle_t *mesh) {
        return true;
 }
 
-static bool timespec_lt(const struct timespec *a, const struct timespec *b) {
-       if(a->tv_sec == b->tv_sec) {
-               return a->tv_nsec < b->tv_nsec;
-       } else {
-               return a->tv_sec < b->tv_sec;
-       }
-}
-
 static struct timespec idle(event_loop_t *loop, void *data) {
        (void)loop;
        meshlink_handle_t *mesh = data;
-       struct timespec t, tmin = {3600, 0};
-
-       for splay_each(node_t, n, mesh->nodes) {
-               if(!n->utcp) {
-                       continue;
-               }
 
-               t = utcp_timeout(n->utcp);
-
-               if(timespec_lt(&t, &tmin)) {
-                       tmin = t;
-               }
+       if(mesh->peer && mesh->peer->utcp) {
+               return utcp_timeout(mesh->peer->utcp);
+       } else {
+               return (struct timespec) {
+                       3600, 0
+               };
        }
-
-       return tmin;
 }
 
 static bool meshlink_setup(meshlink_handle_t *mesh) {
@@ -1156,11 +1141,10 @@ bool meshlink_start(meshlink_handle_t *mesh) {
        }
 
        // Reset node connection timers
-       for splay_each(node_t, n, mesh->nodes) {
-               n->last_connect_try = 0;
+       if(mesh->peer) {
+               mesh->peer->last_connect_try = 0;
        }
 
-
        //Check that a valid name is set
        if(!mesh->name) {
                logger(mesh, MESHLINK_ERROR, "No name given!\n");
@@ -1229,25 +1213,17 @@ void meshlink_stop(meshlink_handle_t *mesh) {
        }
 
        // Close all metaconnections
-       if(mesh->connections) {
-               for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
-                       next = node->next;
-                       connection_t *c = node->data;
-                       c->outgoing = NULL;
-                       terminate_connection(mesh, c, false);
-               }
+       if(mesh->connection) {
+               mesh->connection->outgoing = NULL;
+               terminate_connection(mesh, mesh->connection, false);
        }
 
        exit_outgoings(mesh);
 
        // Try to write out any changed node config files, ignore errors at this point.
-       if(mesh->nodes) {
-               for splay_each(node_t, n, mesh->nodes) {
-                       if(n->status.dirty) {
-                               if(!node_write_config(mesh, n, false)) {
-                                       // ignore
-                               }
-                       }
+       if(mesh->peer && mesh->peer->status.dirty) {
+               if(!node_write_config(mesh, mesh->peer, false)) {
+                       // ignore
                }
        }
 
@@ -1703,149 +1679,6 @@ meshlink_node_t *meshlink_get_node(meshlink_handle_t *mesh, const char *name) {
        return (meshlink_node_t *)n;
 }
 
-meshlink_node_t **meshlink_get_all_nodes(meshlink_handle_t *mesh, meshlink_node_t **nodes, size_t *nmemb) {
-       if(!mesh || !nmemb || (*nmemb && !nodes)) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return NULL;
-       }
-
-       meshlink_node_t **result;
-
-       //lock mesh->nodes
-       if(pthread_mutex_lock(&mesh->mutex) != 0) {
-               abort();
-       }
-
-       *nmemb = mesh->nodes->count;
-       result = realloc(nodes, *nmemb * sizeof(*nodes));
-
-       if(result) {
-               meshlink_node_t **p = result;
-
-               for splay_each(node_t, n, mesh->nodes) {
-                       *p++ = (meshlink_node_t *)n;
-               }
-       } else {
-               *nmemb = 0;
-               free(nodes);
-               meshlink_errno = MESHLINK_ENOMEM;
-       }
-
-       pthread_mutex_unlock(&mesh->mutex);
-
-       return result;
-}
-
-static meshlink_node_t **meshlink_get_all_nodes_by_condition(meshlink_handle_t *mesh, const void *condition, meshlink_node_t **nodes, size_t *nmemb, search_node_by_condition_t search_node) {
-       meshlink_node_t **result;
-
-       if(pthread_mutex_lock(&mesh->mutex) != 0) {
-               abort();
-       }
-
-       *nmemb = 0;
-
-       for splay_each(node_t, n, mesh->nodes) {
-               if(search_node(n, condition)) {
-                       ++*nmemb;
-               }
-       }
-
-       if(*nmemb == 0) {
-               free(nodes);
-               pthread_mutex_unlock(&mesh->mutex);
-               return NULL;
-       }
-
-       result = realloc(nodes, *nmemb * sizeof(*nodes));
-
-       if(result) {
-               meshlink_node_t **p = result;
-
-               for splay_each(node_t, n, mesh->nodes) {
-                       if(search_node(n, condition)) {
-                               *p++ = (meshlink_node_t *)n;
-                       }
-               }
-       } else {
-               *nmemb = 0;
-               free(nodes);
-               meshlink_errno = MESHLINK_ENOMEM;
-       }
-
-       pthread_mutex_unlock(&mesh->mutex);
-
-       return result;
-}
-
-static bool search_node_by_dev_class(const node_t *node, const void *condition) {
-       dev_class_t *devclass = (dev_class_t *)condition;
-
-       if(*devclass == (dev_class_t)node->devclass) {
-               return true;
-       }
-
-       return false;
-}
-
-
-struct time_range {
-       time_t start;
-       time_t end;
-};
-
-meshlink_node_t **meshlink_get_all_nodes_by_dev_class(meshlink_handle_t *mesh, dev_class_t devclass, meshlink_node_t **nodes, size_t *nmemb) {
-       if(!mesh || devclass < 0 || devclass >= DEV_CLASS_COUNT || !nmemb) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return NULL;
-       }
-
-       return meshlink_get_all_nodes_by_condition(mesh, &devclass, nodes, nmemb, search_node_by_dev_class);
-}
-
-dev_class_t meshlink_get_node_dev_class(meshlink_handle_t *mesh, meshlink_node_t *node) {
-       if(!mesh || !node) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return -1;
-       }
-
-       dev_class_t devclass;
-
-       if(pthread_mutex_lock(&mesh->mutex) != 0) {
-               abort();
-       }
-
-       devclass = ((node_t *)node)->devclass;
-
-       pthread_mutex_unlock(&mesh->mutex);
-
-       return devclass;
-}
-
-bool meshlink_get_node_reachability(struct meshlink_handle *mesh, struct meshlink_node *node, time_t *last_reachable, time_t *last_unreachable) {
-       if(!mesh || !node) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return NULL;
-       }
-
-       node_t *n = (node_t *)node;
-       bool reachable;
-
-       if(pthread_mutex_lock(&mesh->mutex) != 0) {
-               abort();
-       }
-
-       reachable = n->status.reachable && !n->status.blacklisted;
-
-       // TODO: handle reachable times?
-       (void)last_reachable;
-       (void)last_unreachable;
-
-       pthread_mutex_unlock(&mesh->mutex);
-
-       return reachable;
-}
-
 bool meshlink_sign(meshlink_handle_t *mesh, const void *data, size_t len, void *signature, size_t *siglen) {
        logger(mesh, MESHLINK_DEBUG, "meshlink_sign(%p, %zu, %p, %p)", data, len, signature, (void *)siglen);
 
@@ -2017,7 +1850,7 @@ bool meshlink_join(meshlink_handle_t *mesh, const char *invitation) {
        }
 
        // Refuse to join a mesh if we are already part of one. We are part of one if we know at least one other node.
-       if(mesh->nodes->count > 1) {
+       if(mesh->peer) {
                logger(mesh, MESHLINK_ERROR, "Already part of an existing mesh\n");
                meshlink_errno = MESHLINK_EINVAL;
                goto exit;
@@ -2429,66 +2262,6 @@ bool meshlink_import(meshlink_handle_t *mesh, const char *data) {
        return true;
 }
 
-bool meshlink_forget_node(meshlink_handle_t *mesh, meshlink_node_t *node) {
-       logger(mesh, MESHLINK_DEBUG, "meshlink_forget_node(%s)", node ? node->name : "(null)");
-
-       if(!mesh || !node) {
-               meshlink_errno = MESHLINK_EINVAL;
-               return false;
-       }
-
-       node_t *n = (node_t *)node;
-
-       if(pthread_mutex_lock(&mesh->mutex) != 0) {
-               abort();
-       }
-
-       /* Check that the node is not reachable */
-       if(n->status.reachable || n->connection) {
-               pthread_mutex_unlock(&mesh->mutex);
-               logger(mesh, MESHLINK_WARNING, "Could not forget %s: still reachable", n->name);
-               return false;
-       }
-
-       /* Check that we don't have any active UTCP connections */
-       if(n->utcp && utcp_is_active(n->utcp)) {
-               pthread_mutex_unlock(&mesh->mutex);
-               logger(mesh, MESHLINK_WARNING, "Could not forget %s: active UTCP connections", n->name);
-               return false;
-       }
-
-       /* Check that we have no active connections to this node */
-       for list_each(connection_t, c, mesh->connections) {
-               if(c->node == n) {
-                       pthread_mutex_unlock(&mesh->mutex);
-                       logger(mesh, MESHLINK_WARNING, "Could not forget %s: active connection", n->name);
-                       return false;
-               }
-       }
-
-       /* Remove any pending outgoings to this node */
-       if(mesh->outgoings) {
-               for list_each(outgoing_t, outgoing, mesh->outgoings) {
-                       if(outgoing->node == n) {
-                               list_delete_node(mesh->outgoings, list_node);
-                       }
-               }
-       }
-
-       /* Delete the config file for this node */
-       if(!config_delete(mesh, "current", n->name)) {
-               pthread_mutex_unlock(&mesh->mutex);
-               return false;
-       }
-
-       /* Delete the node struct and any remaining edges referencing this node */
-       node_del(mesh, n);
-
-       pthread_mutex_unlock(&mesh->mutex);
-
-       return config_sync(mesh, "current");
-}
-
 /* Hint that a hostname may be found at an address
  * See header file for detailed comment.
  */
@@ -2863,12 +2636,10 @@ void meshlink_set_channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_ac
        mesh->channel_accept_cb = cb;
        mesh->receive_cb = channel_receive;
 
-       for splay_each(node_t, n, mesh->nodes) {
-               if(!n->utcp && n != mesh->self) {
-                       n->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, n);
-                       utcp_set_mtu(n->utcp, n->mtu - sizeof(meshlink_packethdr_t));
-                       utcp_set_retransmit_cb(n->utcp, channel_retransmit);
-               }
+       if(mesh->peer) {
+               mesh->peer->utcp = utcp_init(channel_accept, channel_pre_accept, channel_send, mesh->peer);
+               utcp_set_mtu(mesh->peer->utcp, mesh->peer->mtu - sizeof(meshlink_packethdr_t));
+               utcp_set_retransmit_cb(mesh->peer->utcp, channel_retransmit);
        }
 
        pthread_mutex_unlock(&mesh->mutex);
@@ -3514,7 +3285,7 @@ void meshlink_set_storage_policy(struct meshlink_handle *mesh, meshlink_storage_
 void handle_network_change(meshlink_handle_t *mesh, bool online) {
        (void)online;
 
-       if(!mesh->connections || !mesh->loop.running) {
+       if(!mesh->loop.running) {
                return;
        }
 
index b1caa0a34ef3a5b5b46a5131704a0d755575a34e..fc4683efeaa4ab857a85ce3da6a4147858321026 100644 (file)
@@ -93,10 +93,9 @@ struct meshlink_handle {
        meshlink_queue_t outpacketqueue;
        signal_t datafromapp;
 
-       struct splay_tree_t *nodes;
-
-       struct list_t *connections;
-       struct list_t *outgoings;
+       struct node_t *peer;
+       struct connection_t *connection;
+       struct outgoing_t *outgoing;
 
        // Meta-connection-related members
        struct splay_tree_t *past_request_tree;
index d79dc6edbec77482c4a1e6ec5fc152f175b8bbad..32e3de24ba9656b804e39f6c063813214011ad92 100644 (file)
@@ -64,9 +64,9 @@ void broadcast_meta(meshlink_handle_t *mesh, connection_t *from, const char *buf
        assert(buffer);
        assert(length);
 
-       for list_each(connection_t, c, mesh->connections)
-               if(c != from && c->status.active) {
-                       send_meta(mesh, c, buffer, length);
+       if(mesh->connection)
+               if(mesh->connection != from && mesh->connection->status.active) {
+                       send_meta(mesh, mesh->connection, buffer, length);
                }
 }
 
index 60c16cb9fadc8b9ca3ac2127b180927c0ffe20e0..c05baf77be7d78ff6f80a9d3cd136276c0850264 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -90,7 +90,7 @@ 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) {
+       for(connection_t *c = mesh->connection; c; c = NULL) {
                int pingtimeout = c->node ? mesh->dev_class_traits[c->node->devclass].pingtimeout : default_timeout;
                int pinginterval = c->node ? mesh->dev_class_traits[c->node->devclass].pinginterval : default_interval;
 
@@ -144,186 +144,6 @@ static void timeout_handler(event_loop_t *loop, void *data) {
        });
 }
 
-// devclass asc, last_successfull_connection desc
-static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) {
-       const node_t *na = a, *nb = b;
-
-       if(na->devclass < nb->devclass) {
-               return -1;
-       }
-
-       if(na->devclass > nb->devclass) {
-               return 1;
-       }
-
-       if(na->last_successfull_connection == nb->last_successfull_connection) {
-               return 0;
-       }
-
-       if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) {
-               return -1;
-       }
-
-       if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) {
-               return 1;
-       }
-
-       if(na < nb) {
-               return -1;
-       }
-
-       if(na > nb) {
-               return 1;
-       }
-
-       return 0;
-}
-
-// last_successfull_connection desc
-static int node_compare_lsc_desc(const void *a, const void *b) {
-       const node_t *na = a, *nb = b;
-
-       if(na->last_successfull_connection == nb->last_successfull_connection) {
-               return 0;
-       }
-
-       if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) {
-               return -1;
-       }
-
-       if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) {
-               return 1;
-       }
-
-       if(na < nb) {
-               return -1;
-       }
-
-       if(na > nb) {
-               return 1;
-       }
-
-       return 0;
-}
-
-// devclass desc
-static int node_compare_devclass_desc(const void *a, const void *b) {
-       const node_t *na = a, *nb = b;
-
-       if(na->devclass < nb->devclass) {
-               return -1;
-       }
-
-       if(na->devclass > nb->devclass) {
-               return 1;
-       }
-
-       if(na < nb) {
-               return -1;
-       }
-
-       if(na > nb) {
-               return 1;
-       }
-
-       return 0;
-}
-
-
-/*
-
-autoconnect()
-{
-        timeout = 5
-
-        // find the best one for initial connect
-
-        if cur < min
-                newcon =
-                        first from nodes
-                                where dclass <= my.dclass and !connection and (timestamp - last_retry) > retry_timeout
-                                order by dclass asc, last_connection desc
-                if newcon
-                        timeout = 0
-                        goto connect
-
-
-        // find better nodes to connect to: in case we have less than min connections within [BACKBONE, i] and there are nodes which we are not connected to within the range
-
-        if min <= cur < max
-                j = 0
-                for i = BACKBONE to my.dclass
-                        j += count(from connections where node.dclass = i)
-                        if j < min
-                                newcon =
-                                        first from nodes
-                                                where dclass = i and !connection and (timestamp - last_retry) > retry_timeout
-                                                order by last_connection desc
-                                if newcon
-                                        goto connect
-                        else
-                                break
-
-
-        // heal partitions
-
-        if min <= cur < max
-                newcon =
-                        first from nodes
-                                where dclass <= my.dclass and !reachable and (timestamp - last_retry) > retry_timeout
-                                order by dclass asc, last_connection desc
-                if newcon
-                        goto connect
-
-
-        // connect
-
-connect:
-        if newcon
-                connect newcon
-
-
-        // disconnect outgoing connections in case we have more than min connections within [BACKBONE, i] and there are nodes which we are connected to within the range [i, PORTABLE]
-
-        if min < cur <= max
-                j = 0
-                for i = BACKBONE to my.dclass
-                        j += count(from connections where node.dclass = i)
-                        if min < j
-                                delcon =
-                                        first from nodes
-                                                where dclass >= i and outgoing_connection
-                                                order by dclass desc
-                                if disconnect
-                                        goto disconnect
-                                else
-                                        break
-
-
-        // disconnect connections in case we have more than enough connections
-
-        if max < cur
-                delcon =
-                        first from nodes
-                                where outgoing_connection
-                                order by dclass desc
-                goto disconnect
-
-        // disconnect
-
-disconnect
-        if delcon
-                disconnect delcon
-
-
-        // next iteration
-        next (timeout, autoconnect)
-
-}
-
-*/
-
-
 static void periodic_handler(event_loop_t *loop, void *data) {
        meshlink_handle_t *mesh = loop->data;
 
@@ -356,246 +176,14 @@ static void periodic_handler(event_loop_t *loop, void *data) {
 
        /* Check if we need to make or break connections. */
 
-       if(mesh->nodes->count > 1) {
-
-               logger(mesh, MESHLINK_DEBUG, "--- autoconnect begin ---");
-
-               int retry_timeout = min(mesh->nodes->count * default_timeout, 60);
-
-               logger(mesh, MESHLINK_DEBUG, "* devclass = %d", mesh->devclass);
-               logger(mesh, MESHLINK_DEBUG, "* nodes = %d", mesh->nodes->count);
-               logger(mesh, MESHLINK_DEBUG, "* retry_timeout = %d", retry_timeout);
-
-
-               // connect disconnect nodes
-
-               node_t *connect_to = NULL;
-               node_t *disconnect_from = NULL;
-
-
-               // get cur_connects
-
-               unsigned int cur_connects = 0;
-
-               for list_each(connection_t, c, mesh->connections) {
-                       if(c->status.active) {
-                               cur_connects += 1;
-                       }
-               }
-
-               logger(mesh, MESHLINK_DEBUG, "* cur_connects = %d", cur_connects);
-               logger(mesh, MESHLINK_DEBUG, "* outgoings = %d", mesh->outgoings->count);
-
-               // get min_connects and max_connects
-
-               unsigned int min_connects = mesh->dev_class_traits[mesh->devclass].min_connects;
-               unsigned int max_connects = mesh->dev_class_traits[mesh->devclass].max_connects;
-
-               logger(mesh, MESHLINK_DEBUG, "* min_connects = %d", min_connects);
-               logger(mesh, MESHLINK_DEBUG, "* max_connects = %d", max_connects);
-
-               // find the best one for initial connect
-
-               if(cur_connects < min_connects) {
-                       splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL);
-
-                       for splay_each(node_t, n, mesh->nodes) {
-                               logger(mesh, MESHLINK_DEBUG, "* %s->devclass = %d", n->name, n->devclass);
-
-                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (mesh->loop.now.tv_sec - n->last_connect_try) > retry_timeout)) {
-                                       splay_insert(nodes, n);
-                               }
-                       }
-
-                       if(nodes->head) {
-                               //timeout = 0;
-                               connect_to = (node_t *)nodes->head->data;
-
-                               logger(mesh, MESHLINK_DEBUG, "* found best one for initial connect: %s", connect_to->name);
-                       } else {
-                               logger(mesh, MESHLINK_DEBUG, "* could not find node for initial connect");
-                       }
-
-                       splay_delete_tree(nodes);
-               }
-
-
-               // find better nodes to connect to
-
-               if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) {
-                       unsigned int connects = 0;
-
-                       for(dev_class_t devclass = 0; devclass <= mesh->devclass; ++devclass) {
-                               for list_each(connection_t, c, mesh->connections) {
-                                       if(c->status.active && c->node && c->node->devclass == devclass) {
-                                               connects += 1;
-                                       }
-                               }
-
-                               if(connects < min_connects) {
-                                       splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL);
-
-                                       for splay_each(node_t, n, mesh->nodes) {
-                                               if(n != mesh->self && n->devclass == devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (mesh->loop.now.tv_sec - n->last_connect_try) > retry_timeout)) {
-                                                       splay_insert(nodes, n);
-                                               }
-                                       }
-
-                                       if(nodes->head) {
-                                               logger(mesh, MESHLINK_DEBUG, "* found better node");
-                                               connect_to = (node_t *)nodes->head->data;
-
-                                               splay_delete_tree(nodes);
-                                               break;
-                                       }
-
-                                       splay_delete_tree(nodes);
-                               } else {
-                                       break;
-                               }
-                       }
-
-                       if(!connect_to) {
-                               logger(mesh, MESHLINK_DEBUG, "* could not find better nodes");
-                       }
-               }
-
-
-               // heal partitions
-
-               if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) {
-                       splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL);
-
-                       for splay_each(node_t, n, mesh->nodes) {
-                               if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && !n->status.blacklisted && (n->last_connect_try == 0 || (mesh->loop.now.tv_sec - n->last_connect_try) > retry_timeout)) {
-                                       splay_insert(nodes, n);
-                               }
-                       }
-
-                       if(nodes->head) {
-                               logger(mesh, MESHLINK_DEBUG, "* try to heal partition");
-                               connect_to = (node_t *)nodes->head->data;
-                       } else {
-                               logger(mesh, MESHLINK_DEBUG, "* could not find nodes for partition healing");
-                       }
-
-                       splay_delete_tree(nodes);
-               }
-
-
-               // perform connect
-
-               if(connect_to && !connect_to->connection) {
-                       connect_to->last_connect_try = mesh->loop.now.tv_sec;
-                       logger(mesh, MESHLINK_DEBUG, "Autoconnect trying to connect to %s", connect_to->name);
-
-                       /* check if there is already a connection attempt to this node */
-                       bool skip = false;
-
-                       for list_each(outgoing_t, outgoing, mesh->outgoings) {
-                               if(outgoing->node == connect_to) {
-                                       logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already");
-                                       skip = true;
-                                       break;
-                               }
-                       }
-
-                       if(!connect_to->status.reachable && !node_read_public_key(mesh, connect_to)) {
-                               logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since we don't know this node's public key");
-                               skip = true;
-                       }
-
-                       if(!skip) {
-                               logger(mesh, MESHLINK_DEBUG, "Autoconnecting to %s", connect_to->name);
-                               outgoing_t *outgoing = xzalloc(sizeof(outgoing_t));
-                               outgoing->node = connect_to;
-                               list_insert_tail(mesh->outgoings, outgoing);
-                               setup_outgoing_connection(mesh, outgoing);
-                       }
-               }
-
-
-               // disconnect suboptimal outgoing connections
-
-               if(min_connects < cur_connects /*&& cur_connects <= max_connects*/) {
-                       unsigned int connects = 0;
-
-                       for(dev_class_t devclass = 0; devclass <= mesh->devclass; ++devclass) {
-                               for list_each(connection_t, c, mesh->connections) {
-                                       if(c->status.active && c->node && c->node->devclass == devclass) {
-                                               connects += 1;
-                                       }
-                               }
-
-                               if(min_connects < connects) {
-                                       splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL);
-
-                                       for list_each(connection_t, c, mesh->connections) {
-                                               if(c->outgoing && c->node && c->node->devclass >= devclass) {
-                                                       splay_insert(nodes, c->node);
-                                               }
-                                       }
-
-                                       if(nodes->head) {
-                                               logger(mesh, MESHLINK_DEBUG, "* disconnect suboptimal outgoing connection");
-                                               disconnect_from = (node_t *)nodes->head->data;
-                                       }
-
-                                       splay_delete_tree(nodes);
-                                       break;
-                               }
-                       }
-
-                       if(!disconnect_from) {
-                               logger(mesh, MESHLINK_DEBUG, "* no suboptimal outgoing connections");
-                       }
-               }
-
-
-               // disconnect connections (too many connections)
-
-               if(!disconnect_from && max_connects < cur_connects) {
-                       splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_desc, NULL);
-
-                       for list_each(connection_t, c, mesh->connections) {
-                               if(c->status.active && c->node) {
-                                       splay_insert(nodes, c->node);
-                               }
-                       }
-
-                       if(nodes->head) {
-                               logger(mesh, MESHLINK_DEBUG, "* disconnect connection (too many connections)");
-
-                               //timeout = 0;
-                               disconnect_from = (node_t *)nodes->head->data;
-                       } else {
-                               logger(mesh, MESHLINK_DEBUG, "* no node we want to disconnect, even though we have too many connections");
-                       }
-
-                       splay_delete_tree(nodes);
-               }
-
-
-               // perform disconnect
-
-               if(disconnect_from && disconnect_from->connection) {
-                       logger(mesh, MESHLINK_DEBUG, "Autodisconnecting from %s", disconnect_from->connection->name);
-                       list_delete(mesh->outgoings, disconnect_from->connection->outgoing);
-                       disconnect_from->connection->outgoing = NULL;
-                       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!
-
-               logger(mesh, MESHLINK_DEBUG, "--- autoconnect end ---");
+       if(mesh->peer && !mesh->connection && !mesh->outgoing) {
+               logger(mesh, MESHLINK_DEBUG, "Autoconnecting to %s", mesh->peer->name);
+               mesh->outgoing = xzalloc(sizeof(outgoing_t));
+               mesh->outgoing->node = mesh->peer;
+               setup_outgoing_connection(mesh, mesh->outgoing);
        }
 
-       for splay_each(node_t, n, mesh->nodes) {
+       for(node_t *n = mesh->peer; n; n = NULL) {
                if(n->status.dirty) {
                        if(!node_write_config(mesh, n, false)) {
                                logger(mesh, MESHLINK_DEBUG, "Could not update %s", n->name);
@@ -632,7 +220,7 @@ void handle_meta_connection_data(meshlink_handle_t *mesh, connection_t *c) {
 
 void retry(meshlink_handle_t *mesh) {
        /* Reset the reconnection timers for all outgoing connections */
-       for list_each(outgoing_t, outgoing, mesh->outgoings) {
+       for(outgoing_t *outgoing = mesh->outgoing; outgoing; outgoing = NULL) {
                outgoing->timeout = 0;
 
                if(outgoing->ev.cb) {
@@ -644,7 +232,7 @@ void retry(meshlink_handle_t *mesh) {
 
        /* For active connections, check if their addresses are still valid.
         * If yes, reset their ping timers, otherwise terminate them. */
-       for list_each(connection_t, c, mesh->connections) {
+       for(connection_t *c = mesh->connection; c; c = NULL) {
                if(!c->status.active) {
                        continue;
                }
index 4369692fde5004c151a47dd6ee363591ace61014..96392809323abc57f11c2e78030e16f2be214cc0 100644 (file)
@@ -355,13 +355,9 @@ bool setup_network(meshlink_handle_t *mesh) {
   close all open network connections
 */
 void close_network_connections(meshlink_handle_t *mesh) {
-       if(mesh->connections) {
-               for(list_node_t *node = mesh->connections->head, *next; node; node = next) {
-                       next = node->next;
-                       connection_t *c = node->data;
-                       c->outgoing = NULL;
-                       terminate_connection(mesh, c, false);
-               }
+       if(mesh->connection) {
+               mesh->connection->outgoing = NULL;
+               terminate_connection(mesh, mesh->connection, false);
        }
 
        exit_requests(mesh);
index fe7bf3af11183ac7547d6ccd65ed272fd4555183..d4b6208693049cbed754a764c146fba91af11a55 100644 (file)
@@ -289,6 +289,22 @@ static bool get_next_outgoing_address(meshlink_handle_t *mesh, outgoing_t *outgo
        return false;
 }
 
+static void free_outgoing(outgoing_t *outgoing) {
+       meshlink_handle_t *mesh = outgoing->node->mesh;
+
+       timeout_del(&mesh->loop, &outgoing->ev);
+
+       if(outgoing->ai) {
+               if(outgoing->state == OUTGOING_RECENT || outgoing->state == OUTGOING_KNOWN) {
+                       free_known_addresses(outgoing->ai);
+               } else {
+                       freeaddrinfo(outgoing->ai);
+               }
+       }
+
+       free(outgoing);
+}
+
 void do_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) {
 begin:
 
@@ -297,7 +313,8 @@ begin:
                        /* We are waiting for a callback from the ADNS thread */
                } else if(outgoing->state == OUTGOING_NO_KNOWN_ADDRESSES) {
                        logger(mesh, MESHLINK_ERROR, "No known addresses for %s", outgoing->node->name);
-                       list_delete(mesh->outgoings, outgoing);
+                       free_outgoing(outgoing);
+                       mesh->outgoing = NULL;
                } else {
                        logger(mesh, MESHLINK_ERROR, "Could not set up a meta connection to %s", outgoing->node->name);
                        retry_outgoing(mesh, outgoing);
@@ -409,29 +426,13 @@ void setup_outgoing_connection(meshlink_handle_t *mesh, outgoing_t *outgoing) {
        do_outgoing_connection(mesh, outgoing);
 }
 
-static void free_outgoing(outgoing_t *outgoing) {
-       meshlink_handle_t *mesh = outgoing->node->mesh;
-
-       timeout_del(&mesh->loop, &outgoing->ev);
-
-       if(outgoing->ai) {
-               if(outgoing->state == OUTGOING_RECENT || outgoing->state == OUTGOING_KNOWN) {
-                       free_known_addresses(outgoing->ai);
-               } else {
-                       freeaddrinfo(outgoing->ai);
-               }
-       }
-
-       free(outgoing);
-}
-
 void init_outgoings(meshlink_handle_t *mesh) {
-       mesh->outgoings = list_alloc((list_action_t)free_outgoing);
+       mesh->outgoing = NULL;
 }
 
 void exit_outgoings(meshlink_handle_t *mesh) {
-       if(mesh->outgoings) {
-               list_delete_list(mesh->outgoings);
-               mesh->outgoings = NULL;
+       if(mesh->outgoing) {
+               free_outgoing(mesh->outgoing);
+               mesh->outgoing = NULL;
        }
 }
index 160bcb38248805e0724930632186c24391c2dfb1..1c1c864b14e2f89a2c198e819e54f296a108deea 100644 (file)
 #include "net.h"
 #include "netutl.h"
 #include "node.h"
-#include "splay_tree.h"
 #include "utils.h"
 #include "xalloc.h"
 
-static int node_compare(const node_t *a, const node_t *b) {
-       return strcmp(a->name, b->name);
-}
-
 void init_nodes(meshlink_handle_t *mesh) {
-       mesh->nodes = splay_alloc_tree((splay_compare_t) node_compare, (splay_action_t) free_node);
+       mesh->peer = NULL;
 }
 
 void exit_nodes(meshlink_handle_t *mesh) {
-       if(mesh->nodes) {
-               splay_delete_tree(mesh->nodes);
+       if(mesh->peer) {
+               free_node(mesh->peer);
        }
 
-       mesh->nodes = NULL;
+       mesh->peer = NULL;
 }
 
 node_t *new_node(void) {
@@ -76,22 +71,34 @@ void free_node(node_t *n) {
 }
 
 void node_add(meshlink_handle_t *mesh, node_t *n) {
+       if(n == mesh->self) {
+               return;
+       }
+
+       assert(!mesh->peer);
        n->mesh = mesh;
-       splay_insert(mesh->nodes, n);
+       mesh->peer = n;
 }
 
 void node_del(meshlink_handle_t *mesh, node_t *n) {
+       if(n == mesh->self) {
+               return;
+       }
+
+       assert(mesh->peer && mesh->peer == n);
        timeout_del(&mesh->loop, &n->mtutimeout);
-       splay_delete(mesh->nodes, n);
+       free_node(n);
+       mesh->peer = NULL;
 }
 
 node_t *lookup_node(meshlink_handle_t *mesh, const char *name) {
-       const node_t n = {.name = (char *)name};
-       node_t *result;
-
-       result = splay_search(mesh->nodes, &n);
-
-       return result;
+       if(mesh->peer && !strcmp(name, mesh->peer->name)) {
+               return mesh->peer;
+       } else if(!strcmp(name, mesh->self->name)) {
+               return mesh->self;
+       } else {
+               return NULL;
+       }
 }
 
 bool node_add_recent_address(meshlink_handle_t *mesh, node_t *n, const sockaddr_t *sa) {
index f46a4f473c6d5059b5ba449b8cf9fe8852c4a764..5ee7a5f5e98e5b10495938e86d0d966e8a4bf5fa 100644 (file)
@@ -173,23 +173,6 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                n = new_node();
                n->name = xstrdup(c->name);
                node_add(mesh, n);
-       } else {
-               if(n->connection) {
-                       /* Oh dear, we already have a connection to this node. */
-                       logger(mesh, MESHLINK_INFO, "Established a second connection with %s, closing old connection", n->connection->name);
-
-                       if(n->connection->outgoing) {
-                               if(c->outgoing) {
-                                       logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
-                               } else {
-                                       c->outgoing = n->connection->outgoing;
-                               }
-
-                               n->connection->outgoing = NULL;
-                       }
-
-                       terminate_connection(mesh, n->connection, false);
-               }
        }
 
        n->devclass = devclass;
@@ -213,25 +196,6 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
                mesh->meta_status_cb(mesh, (meshlink_node_t *)n, true);
        }
 
-       /*  Terminate any connections to this node that are not activated yet */
-
-       for list_each(connection_t, other, mesh->connections) {
-               if(!other->status.active && !strcmp(other->name, c->name)) {
-                       if(other->outgoing) {
-                               if(c->outgoing) {
-                                       logger(mesh, MESHLINK_WARNING, "Two outgoing connections to the same node!");
-                               } else {
-                                       c->outgoing = other->outgoing;
-                               }
-
-                               other->outgoing = NULL;
-                       }
-
-                       logger(mesh, MESHLINK_DEBUG, "Terminating pending second connection with %s", n->name);
-                       terminate_connection(mesh, other, false);
-               }
-       }
-
        /* TODO: Create an edge_t for this connection, send it */
 
        /* Request a session key to jump start UDP traffic */
index de6b1e5ea34ff3c67ac68c1e58ada692253022f4..e89f8ecec4eab958c7948c28ce7361987b4395a1 100644 (file)
@@ -182,10 +182,10 @@ static bool req_key_ext_h(meshlink_handle_t *mesh, connection_t *c, const char *
                }
 
                /* 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 timespec) {
+               if(mesh->outgoing) {
+                       if(mesh->outgoing->node == from && mesh->outgoing->ev.cb) {
+                               mesh->outgoing->timeout = 0;
+                               timeout_set(&mesh->loop, &mesh->outgoing->ev, &(struct timespec) {
                                        0, 0
                                });
                        }