X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet.c;fp=src%2Fnet.c;h=6cf6f6302e674b462c97da937fcf449be1f93c5a;hb=93e77a457c257a2e98bc6309702fce36eb6f536b;hp=b5705a471b198dde06bed1792d0208a835490a1d;hpb=05333b3a26842d1c10b5fe9211420c281b9a9ef4;p=meshlink diff --git a/src/net.c b/src/net.c index b5705a47..6cf6f630 100644 --- a/src/net.c +++ b/src/net.c @@ -19,7 +19,7 @@ #include "system.h" -#include "utils.h" +#include "autoconnect.h" #include "conf.h" #include "connection.h" #include "graph.h" @@ -29,6 +29,7 @@ #include "net.h" #include "netutl.h" #include "protocol.h" +#include "utils.h" #include "xalloc.h" #include @@ -148,186 +149,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; @@ -360,244 +181,16 @@ 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_free_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_free_tree(nodes); - break; - } - - splay_free_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_free_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_free_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_free_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); - } + unsigned int cur_connects = do_autoconnect(mesh); // reduce timeout if we don't have enough connections + outgoings - if(cur_connects + mesh->outgoings->count < 3) { + if (cur_connects + mesh->outgoings->count < 3) { timeout = 1; } - - // done! - - logger(mesh, MESHLINK_DEBUG, "--- autoconnect end ---"); } + /* Write dirty config files out to disk */ + for splay_each(node_t, n, mesh->nodes) { if(n->status.dirty) { node_write_config(mesh, n);