-/*
- setup all initial network connections
-*/
-int setup_network_connections(void)
-{
- config_t const *cfg;
- char *scriptname;
-cp
- if((cfg = get_config_val(config, pingtimeout)) == NULL)
- timeout = 5;
- else
- timeout = cfg->data.val;
-
- if(setup_tap_fd() < 0)
- return -1;
-
- if(setup_myself() < 0)
- return -1;
-
- /* Run tinc-up script to further initialize the tap interface */
-
- asprintf(&scriptname, "%s/tinc-up", confbase);
-
- if(!fork())
- {
-
- execl(scriptname, NULL);
-
- if(errno != ENOENT)
- syslog(LOG_WARNING, _("Error while executing %s: %m"), scriptname);
-
- exit(0);
- }
-
- free(scriptname);
-
- if((cfg = get_next_config_val(config, connectto, upstreamindex++)) == NULL)
- /* No upstream IP given, we're listen only. */
- return 0;
-
- while(cfg)
- {
- if(!setup_outgoing_connection(cfg->data.ptr)) /* function returns 0 when there are no problems */
- return 0;
- cfg = get_next_config_val(config, connectto, upstreamindex++); /* Or else we try the next ConnectTo line */
- }
-
- signal(SIGALRM, sigalrm_handler);
- upstreamindex = 0;
- seconds_till_retry = MAXTIMEOUT;
- syslog(LOG_NOTICE, _("Trying to re-establish outgoing connection in %d seconds"), seconds_till_retry);
- alarm(seconds_till_retry);
-cp
- return 0;
+ contradicting_add_edge = 0;
+ contradicting_del_edge = 0;
+
+ /* If AutoConnect is set, check if we need to make or break connections. */
+
+ if(autoconnect && node_tree->count > 1) {
+ /* Count number of active connections */
+ int nc = 0;
+ for list_each(connection_t, c, connection_list) {
+ if(c->edge)
+ nc++;
+ }
+
+ if(nc < 3) {
+ /* Not enough active connections, try to add one.
+ Choose a random node, if we don't have a connection to it,
+ and we are not already trying to make one, create an
+ outgoing connection to this node.
+ */
+ int r = rand() % node_tree->count;
+ int i = 0;
+
+ for splay_each(node_t, n, node_tree) {
+ if(i++ != r)
+ continue;
+
+ if(n->connection)
+ break;
+
+ bool found = false;
+
+ for list_each(outgoing_t, outgoing, outgoing_list) {
+ if(!strcmp(outgoing->name, n->name)) {
+ found = true;
+ break;
+ }
+ }
+
+ 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(outgoing_list, outgoing);
+ setup_outgoing_connection(outgoing);
+ }
+ break;
+ }
+ } else if(nc > 3) {
+ /* 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, connection_list) {
+ if(!c->edge)
+ 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(outgoing_list, c->outgoing);
+ c->outgoing = NULL;
+ terminate_connection(c, c->edge);
+ break;
+ }
+ }
+
+ if(nc >= 3) {
+ /* If we have enough active connections,
+ remove any pending outgoing connections.
+ */
+ for list_each(outgoing_t, o, outgoing_list) {
+ bool found = false;
+ for list_each(connection_t, c, connection_list) {
+ if(c->outgoing == o) {
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "Cancelled outgoing connection to %s", o->name);
+ list_delete_node(outgoing_list, node);
+ }
+ }
+ }
+ }
+
+ timeout_set(data, &(struct timeval){5, rand() % 100000});