- asprintf(&fname, "%s/hosts/%s", confbase, c->name);
- if(stat(fname, &s) || s.st_mtime > last_config_check)
- terminate_connection(c, c->status.active);
- free(fname);
+ if(nc > autoconnect) {
+ /* Too many active connections, try to remove one.
+ Choose a random outgoing connection to a node
+ that has at least one other connection.
+ */
+ int r = rand() % nc;
+ int i = 0;
+
+ for list_each(connection_t, c, mesh->connections) {
+ if(!c->status.active)
+ continue;
+
+ if(i++ != r)
+ continue;
+
+ if(!c->outgoing || !c->node || c->node->edge_tree->count < 2)
+ break;
+
+ 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);
+ break;
+ }
+ }
+
+ if(nc >= autoconnect) {
+ /* If we have enough active connections,
+ remove any pending outgoing connections.
+ Do not remove pending connections to unreachable
+ nodes.
+ */
+ node_t *o_node = NULL;
+ for list_each(outgoing_t, o, mesh->outgoings) {
+ o_node = lookup_node(mesh, o->name);
+ /* o_node is NULL if it is not part of the graph yet */
+ if(!o_node || !o_node->status.reachable)
+ continue;
+
+ bool found = false;
+ for list_each(connection_t, c, mesh->connections) {
+ if(c->outgoing == o) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ 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.
+ */
+ list_delete_node(mesh->outgoings, node);
+ }
+ }
+ }
+
+ if (nc + mesh->outgoings->count < min(autoconnect, mesh->nodes->count - 1))
+ timeout = 0;