#include "system.h"
#include "utils.h"
-#include "splay_tree.h"
#include "conf.h"
#include "connection.h"
#include "device.h"
int contradicting_add_edge = 0;
int contradicting_del_edge = 0;
static int sleeptime = 10;
+time_t last_config_check = 0;
/* Purge edges and subnets of unreachable nodes. Use carefully. */
/*
Terminate a connection:
- - Close the socket
- - Remove associated edge and tell other connections about it if report = true
+ - Mark it as inactive
+ - Remove the edge representing this connection
+ - Kill it with fire
- Check if we need to retry making an outgoing connection
- - Deactivate the host
*/
void terminate_connection(connection_t *c, bool report) {
- logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)",
- c->name, c->hostname);
+ logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname);
c->status.active = false;
}
}
- free_connection_partially(c);
+ outgoing_t *outgoing = c->outgoing;
+ connection_del(c);
/* Check if this was our outgoing connection */
- if(c->outgoing) {
- do_outgoing_connection(c);
- } else {
- connection_del(c);
- }
+ if(outgoing)
+ do_outgoing_connection(outgoing);
}
/*
and close the connection.
*/
static void timeout_handler(int fd, short events, void *event) {
- splay_node_t *node, *next;
- connection_t *c;
time_t now = time(NULL);
- for(node = connection_tree->head; node; node = next) {
+ for(list_node_t *node = connection_list->head, *next; node; node = next) {
next = node->next;
- c = node->data;
+ connection_t *c = node->data;
if(c->status.control)
continue;
if(c->last_ping_time + pingtimeout <= now) {
if(c->status.active) {
if(c->status.pinged) {
- logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds",
- c->name, c->hostname, (long)now - c->last_ping_time);
- terminate_connection(c, true);
- continue;
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)now - c->last_ping_time);
} else if(c->last_ping_time + pinginterval <= now) {
send_ping(c);
+ continue;
+ } else {
+ continue;
}
} else {
- if(c->status.connecting) {
+ if(c->status.connecting)
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout while connecting to %s (%s)", c->name, c->hostname);
- c->status.connecting = false;
- closesocket(c->socket);
- do_outgoing_connection(c);
- } else {
+ else
logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname);
- terminate_connection(c, false);
- continue;
- }
}
+ terminate_connection(c, c->status.active);
}
}
if(!result)
finish_connecting(c);
else {
- logger(DEBUG_CONNECTIONS, LOG_DEBUG,
- "Error while connecting to %s (%s): %s",
- c->name, c->hostname, sockstrerror(result));
- closesocket(c->socket);
- do_outgoing_connection(c);
+ logger(DEBUG_CONNECTIONS, LOG_DEBUG, "Error while connecting to %s (%s): %s", c->name, c->hostname, sockstrerror(result));
+ terminate_connection(c, false);
return;
}
}
}
int reload_configuration(void) {
- connection_t *c;
- splay_node_t *node, *next;
char *fname;
- struct stat s;
- static time_t last_config_check = 0;
/* Reread our own configuration file */
setup_myself_reloadable();
- /* Close connections to hosts that have a changed or deleted host config file */
-
- for(node = connection_tree->head; node; node = next) {
- c = node->data;
- next = node->next;
-
- if(c->status.control)
- continue;
-
- if(c->outgoing) {
- free(c->outgoing->name);
- if(c->outgoing->ai)
- freeaddrinfo(c->outgoing->ai);
- free(c->outgoing);
- c->outgoing = NULL;
- }
-
- xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
- if(stat(fname, &s) || s.st_mtime > last_config_check)
- terminate_connection(c, c->status.active);
- free(fname);
- }
-
- last_config_check = time(NULL);
-
/* If StrictSubnet is set, expire deleted Subnets and read new ones in */
if(strictsubnets) {
- subnet_t *subnet;
-
- for(node = subnet_tree->head; node; node = node->next) {
- subnet = node->data;
+ for(splay_node_t *node = subnet_tree->head; node; node = node->next) {
+ subnet_t *subnet = node->data;
subnet->expires = 1;
}
load_all_subnets();
- for(node = subnet_tree->head; node; node = next) {
+ for(splay_node_t *node = subnet_tree->head, *next; node; node = next) {
next = node->next;
- subnet = node->data;
+ subnet_t *subnet = node->data;
if(subnet->expires == 1) {
send_del_subnet(everyone, subnet);
if(subnet->owner->status.reachable)
}
}
} else { /* Only read our own subnets back in */
- subnet_t *subnet, *s2;
-
- for(node = myself->subnet_tree->head; node; node = node->next) {
+ for(splay_node_t *node = myself->subnet_tree->head; node; node = node->next) {
subnet_t *subnet = node->data;
- logger(DEBUG_ALWAYS, LOG_DEBUG, "subnet %p expires %d\n", subnet, (int)subnet->expires);
if(!subnet->expires)
subnet->expires = 1;
}
config_t *cfg = lookup_config(config_tree, "Subnet");
while(cfg) {
+ subnet_t *subnet, *s2;
+
if(!get_config_subnet(cfg, &subnet))
continue;
if((s2 = lookup_subnet(myself, subnet))) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "read subnet that already exists: %p expires %d\n", s2, (int)s2->expires);
if(s2->expires == 1)
s2->expires = 0;
free_subnet(subnet);
} else {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "read new subnet %p", subnet);
subnet_add(myself, subnet);
send_add_subnet(everyone, subnet);
subnet_update(myself, subnet, true);
cfg = lookup_config_next(config_tree, cfg);
}
- for(node = myself->subnet_tree->head; node; node = next) {
+ for(splay_node_t *node = myself->subnet_tree->head, *next; node; node = next) {
next = node->next;
subnet_t *subnet = node->data;
if(subnet->expires == 1) {
- logger(DEBUG_ALWAYS, LOG_DEBUG, "removed subnet %p", subnet);
send_del_subnet(everyone, subnet);
subnet_update(myself, subnet, false);
subnet_del(myself, subnet);
try_outgoing_connections();
+ /* Close connections to hosts that have a changed or deleted host config file */
+
+ for(list_node_t *node = connection_list->head, *next; node; node = next) {
+ connection_t *c = node->data;
+ next = node->next;
+
+ if(c->status.control)
+ continue;
+
+ xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", confbase, c->name);
+ struct stat s;
+ if(stat(fname, &s) || s.st_mtime > last_config_check) {
+ logger(DEBUG_CONNECTIONS, LOG_INFO, "Host config file of %s has been changed", c->name);
+ terminate_connection(c, c->status.active);
+ }
+ free(fname);
+ }
+
+ last_config_check = time(NULL);
+
return 0;
}
void retry(void) {
- connection_t *c;
- splay_node_t *node, *next;
-
- for(node = connection_tree->head; node; node = next) {
+ for(list_node_t *node = connection_list->head, *next; node; node = next) {
next = node->next;
- c = node->data;
+ connection_t *c = node->data;
if(c->outgoing && !c->node) {
if(timeout_initialized(&c->outgoing->ev))
if(c->status.connecting)
close(c->socket);
c->outgoing->timeout = 0;
- do_outgoing_connection(c);
+ terminate_connection(c, c->status.active);
}
}
}