-void handle_meta_connection_data(int fd, short events, void *data) {
- connection_t *c = data;
- int result;
- socklen_t len = sizeof result;
-
- if(c->status.connecting) {
- c->status.connecting = false;
-
- getsockopt(c->socket, SOL_SOCKET, SO_ERROR, &result, &len);
-
- if(!result)
- finish_connecting(c);
- else {
- ifdebug(CONNECTIONS) logger(LOG_DEBUG,
- "Error while connecting to %s (%s): %s",
- c->name, c->hostname, sockstrerror(result));
- closesocket(c->socket);
- do_outgoing_connection(c);
- return;
+ if(!found) {
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "Autoconnecting to %s", n->name);
+ outgoing_t *outgoing = xzalloc(sizeof *outgoing);
+ outgoing->name = xstrdup(n->name);
+ list_insert_tail(mesh->outgoings, outgoing);
+ setup_outgoing_connection(outgoing);
+ }
+ break;
+ }
+ } else 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(DEBUG_CONNECTIONS, LOG_INFO, "Autodisconnecting from %s", c->name);
+ list_delete(mesh->outgoings, c->outgoing);
+ c->outgoing = NULL;
+ terminate_connection(c, c->status.active);
+ break;
+ }
+ }
+
+ if(nc >= autoconnect) {
+ /* If we have enough active connections,
+ remove any pending outgoing connections.
+ */
+ for list_each(outgoing_t, o, mesh->outgoings) {
+ bool found = false;
+ for list_each(connection_t, c, mesh->connections) {
+ if(c->outgoing == o) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
+ list_delete_node(mesh->outgoings, node);
+ }
+ }