- 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 ---");