X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet.c;h=0475335592fd5c2b8445cf25f3ffd622dfd7c894;hb=3610b382c6971808aa1988e8af945a7816e7246b;hp=294014231b1b04f0f556c11d826b57f45596414f;hpb=eb049936ffce049cf6b53de8ca0f39c98a360363;p=meshlink diff --git a/src/net.c b/src/net.c index 29401423..04753355 100644 --- a/src/net.c +++ b/src/net.c @@ -31,36 +31,6 @@ #include "protocol.h" #include "xalloc.h" -/* Purge edges of unreachable nodes. Use carefully. */ - -// TODO: remove -void purge(void) { - logger(DEBUG_PROTOCOL, LOG_DEBUG, "Purging unreachable nodes"); - - /* Remove all edges owned by unreachable nodes. */ - - for splay_each(node_t, n, mesh->nodes) { - if(!n->status.reachable) { - logger(DEBUG_SCARY_THINGS, LOG_DEBUG, "Purging node %s (%s)", n->name, n->hostname); - - for splay_each(edge_t, e, n->edge_tree) { - send_del_edge(mesh->everyone, e); - edge_del(e); - } - } - } - - /* Check if anyone else claims to have an edge to an unreachable node. If not, delete node. */ - - for splay_each(node_t, n, mesh->nodes) { - if(!n->status.reachable) { - for splay_each(edge_t, e, mesh->edges) - if(e->to == n) - return; - } - } -} - /* Terminate a connection: - Mark it as inactive @@ -68,7 +38,7 @@ void purge(void) { - Kill it with fire - Check if we need to retry making an outgoing connection */ -void terminate_connection(connection_t *c, bool report) { +void terminate_connection(meshlink_handle_t *mesh, connection_t *c, bool report) { logger(DEBUG_CONNECTIONS, LOG_NOTICE, "Closing connection with %s (%s)", c->name, c->hostname); c->status.active = false; @@ -78,14 +48,14 @@ void terminate_connection(connection_t *c, bool report) { if(c->edge) { if(report) - send_del_edge(mesh->everyone, c->edge); + send_del_edge(mesh, mesh->everyone, c->edge); - edge_del(c->edge); + edge_del(mesh, c->edge); c->edge = NULL; /* Run MST and SSSP algorithms */ - graph(); + graph(mesh); /* If the node is not reachable anymore but we remember it had an edge to us, clean it up */ @@ -93,19 +63,19 @@ void terminate_connection(connection_t *c, bool report) { edge_t *e; e = lookup_edge(c->node, mesh->self); if(e) { - send_del_edge(mesh->everyone, e); - edge_del(e); + send_del_edge(mesh, mesh->everyone, e); + edge_del(mesh, e); } } } outgoing_t *outgoing = c->outgoing; - connection_del(c); + connection_del(mesh, c); /* Check if this was our outgoing connection */ if(outgoing) - do_outgoing_connection(outgoing); + do_outgoing_connection(mesh, outgoing); #ifndef HAVE_MINGW /* Clean up dead proxy processes */ @@ -122,14 +92,16 @@ void terminate_connection(connection_t *c, bool report) { end does not reply in time, we consider them dead and close the connection. */ -static void timeout_handler(void *data) { +static void timeout_handler(event_loop_t *loop, void *data) { + meshlink_handle_t *mesh = loop->data; + for list_each(connection_t, c, mesh->connections) { - if(c->last_ping_time + pingtimeout <= now.tv_sec) { + if(c->last_ping_time + mesh->pingtimeout <= mesh->loop.now.tv_sec) { 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.tv_sec - c->last_ping_time); - } else if(c->last_ping_time + pinginterval <= now.tv_sec) { - send_ping(c); + logger(DEBUG_CONNECTIONS, LOG_INFO, "%s (%s) didn't respond to PING in %ld seconds", c->name, c->hostname, (long)mesh->loop.now.tv_sec - c->last_ping_time); + } else if(c->last_ping_time + mesh->pinginterval <= mesh->loop.now.tv_sec) { + send_ping(mesh, c); continue; } else { continue; @@ -140,14 +112,16 @@ static void timeout_handler(void *data) { else logger(DEBUG_CONNECTIONS, LOG_WARNING, "Timeout from %s (%s) during authentication", c->name, c->hostname); } - terminate_connection(c, c->status.active); + terminate_connection(mesh, c, c->status.active); } } - timeout_set(data, &(struct timeval){pingtimeout, rand() % 100000}); + timeout_set(&mesh->loop, data, &(struct timeval){mesh->pingtimeout, rand() % 100000}); } -static void periodic_handler(void *data) { +static void periodic_handler(event_loop_t *loop, void *data) { + meshlink_handle_t *mesh = loop->data; + /* Check if there are too many contradicting ADD_EDGE and DEL_EDGE messages. This usually only happens when another node has the same Name as this node. If so, sleep for a short while to prevent a storm of contradicting messages. @@ -188,8 +162,18 @@ static void periodic_handler(void *data) { int i = 0; for splay_each(node_t, n, mesh->nodes) { - if(i++ != r) - continue; + bool trying_unreachable = false; + + if(i++ != r) { + if(n->status->reachable) { + continue; + } else { + /* If we see an unreachable node + before node i, try it anyway. + */ + trying_unreachable = true; + } + } if(n->connection) break; @@ -204,11 +188,22 @@ static void periodic_handler(void *data) { } if(!found) { + //TODO: if the node is blacklisted the connection will not happen, but + //the user will read this debug message "Autoconnecting to %s" that is misleading 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); + setup_outgoing_connection(mesh, outgoing); + } else if(trying_unreachable) { + /* We're trying an unreachable node instead + of node i. We already have an outgoing + to it. Try the next node rather than + breaking here, to avoid churning on a + connection attempt to the first + unreachable node. + */ + continue; } break; } @@ -233,7 +228,7 @@ static void periodic_handler(void *data) { 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); + terminate_connection(mesh, c, c->status.active); break; } } @@ -258,64 +253,22 @@ static void periodic_handler(void *data) { } } - timeout_set(data, &(struct timeval){5, rand() % 100000}); + timeout_set(&mesh->loop, data, &(struct timeval){5, rand() % 100000}); } -void handle_meta_connection_data(connection_t *c) { - if (!receive_meta(c)) { - terminate_connection(c, c->status.active); +void handle_meta_connection_data(meshlink_handle_t *mesh, connection_t *c) { + if (!receive_meta(mesh, c)) { + terminate_connection(mesh, c, c->status.active); return; } } -int reload_configuration(void) { - char *fname = NULL; - - /* Reread our own configuration file */ - - exit_configuration(&mesh->config); - init_configuration(&mesh->config); - - if(!read_server_config()) { - logger(DEBUG_ALWAYS, LOG_ERR, "Unable to reread configuration file."); - return EINVAL; - } - - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, mesh->self->name); - read_config_file(mesh->config, fname); - free(fname); - - /* Parse some options that are allowed to be changed while tinc is running */ - - setup_myself_reloadable(); - - /* Try to make outgoing connections */ - - try_outgoing_connections(); - - /* Close connections to hosts that have a changed or deleted host config file */ - - for list_each(connection_t, c, mesh->connections) { - xasprintf(&fname, "%s" SLASH "hosts" SLASH "%s", mesh->confbase, c->name); - struct stat s; - if(stat(fname, &s) || s.st_mtime > mesh->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); - } - - mesh->last_config_check = now.tv_sec; - - return 0; -} - -void retry(void) { +void retry(meshlink_handle_t *mesh) { /* Reset the reconnection timers for all outgoing connections */ for list_each(outgoing_t, outgoing, mesh->outgoings) { outgoing->timeout = 0; if(outgoing->ev.cb) - timeout_set(&outgoing->ev, &(struct timeval){0, 0}); + timeout_set(&mesh->loop, &outgoing->ev, &(struct timeval){0, 0}); } /* Check for outgoing connections that are in progress, and reset their ping timers */ @@ -325,23 +278,27 @@ void retry(void) { } /* Kick the ping timeout handler */ - timeout_set(&mesh->pingtimer, &(struct timeval){0, 0}); + timeout_set(&mesh->loop, &mesh->pingtimer, &(struct timeval){0, 0}); } /* this is where it all happens... */ -int main_loop(void) { - timeout_add(&mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval){pingtimeout, rand() % 100000}); - timeout_add(&mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval){pingtimeout, rand() % 100000}); +int main_loop(meshlink_handle_t *mesh) { + timeout_add(&mesh->loop, &mesh->pingtimer, timeout_handler, &mesh->pingtimer, &(struct timeval){mesh->pingtimeout, rand() % 100000}); + timeout_add(&mesh->loop, &mesh->periodictimer, periodic_handler, &mesh->periodictimer, &(struct timeval){mesh->pingtimeout, rand() % 100000}); + + //Add signal handler + mesh->datafromapp.signum = 0; + signal_add(&(mesh->loop),&(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue,mesh, mesh->datafromapp.signum); - if(!event_loop()) { + if(!event_loop_run(&mesh->loop)) { logger(DEBUG_ALWAYS, LOG_ERR, "Error while waiting for input: %s", strerror(errno)); return 1; } - timeout_del(&mesh->periodictimer); - timeout_del(&mesh->pingtimer); + timeout_del(&mesh->loop, &mesh->periodictimer); + timeout_del(&mesh->loop, &mesh->pingtimer); return 0; }