- load_all_subnets();
-
- for(node = subnet_tree->head; node; node = next) {
- next = node->next;
- subnet = node->data;
- if(subnet->expires == 1) {
- send_del_subnet(broadcast, subnet);
- if(subnet->owner->status.reachable)
- subnet_update(subnet->owner, subnet, false);
- subnet_del(subnet->owner, subnet);
- } else if(subnet->expires == -1) {
- subnet->expires = 0;
- } else {
- send_add_subnet(broadcast, subnet);
- if(subnet->owner->status.reachable)
- subnet_update(subnet->owner, subnet, true);
+
+ // find better nodes to connect to
+
+ if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects)
+ {
+ unsigned int connects = 0;
+
+ for(int 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->last_connect_try == 0 || (time(NULL) - 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->last_connect_try == 0 || (time(NULL) - 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 = time(NULL);
+
+ /* check if there is already a connection attempt to this node */
+ bool found = false;
+ for list_each(outgoing_t, outgoing, mesh->outgoings)
+ {
+ if(!strcmp(outgoing->name, connect_to->name))
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if(!found)
+ {
+ logger(mesh, MESHLINK_DEBUG, "Autoconnecting to %s", connect_to->name);
+ outgoing_t *outgoing = xzalloc(sizeof(outgoing_t));
+ outgoing->mesh = mesh;
+ outgoing->name = xstrdup(connect_to->name);
+ list_insert_tail(mesh->outgoings, outgoing);
+ setup_outgoing_connection(mesh, outgoing);
+ }
+ else
+ { logger(mesh, MESHLINK_DEBUG, "* skip autoconnect since it is an outgoing connection already"); }
+ }
+
+
+ // disconnect suboptimal outgoing connections
+
+ if(min_connects < cur_connects /*&& cur_connects <= max_connects*/)
+ {
+ unsigned int connects = 0;
+
+ for(int 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;
+ }