X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=src%2Fnet.c;h=8400b936bd4f08d18ed8c5fe44a31e053098ed1c;hb=31ab43d8a0691e773db6992fa3b52ca24f7f8db4;hp=654a7813cee55fca752d9092458a9a0cd6bc9091;hpb=a021bf25db676353b8ea50740ce343962c3dddb9;p=meshlink diff --git a/src/net.c b/src/net.c index 654a7813..8400b936 100644 --- a/src/net.c +++ b/src/net.c @@ -31,6 +31,7 @@ #include "protocol.h" #include "xalloc.h" +#include static const int min(int a, int b) { return a < b ? a : b; @@ -130,8 +131,8 @@ static void timeout_handler(event_loop_t *loop, void *data) { timeout_set(&mesh->loop, data, &(struct timeval){mesh->pingtimeout, rand() % 100000}); } -// devclass asc, last_connect_try desc -static int node_compare_devclass_asc_last_connect_try_desc(const void *a, const void *b) +// devclass asc, last_successfull_connection desc +static int node_compare_devclass_asc_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; @@ -141,30 +142,42 @@ static int node_compare_devclass_asc_last_connect_try_desc(const void *a, const if(na->devclass > nb->devclass) { return 1; } - if(na->last_connect_try == nb->last_connect_try) + if(na->last_successfull_connection == nb->last_successfull_connection) return 0; - if(nb->last_connect_try == 0 || na->last_connect_try < nb->last_connect_try) + if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) return -1; - if(na->last_connect_try == 0 || na->last_connect_try > nb->last_connect_try) + if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) + return 1; + + if(na < nb) + return -1; + + if(na > nb) return 1; return 0; } -// last_connect_try desc -static int node_compare_last_connect_try_desc(const void *a, const void *b) +// last_successfull_connection desc +static int node_compare_lsc_desc(const void *a, const void *b) { const node_t *na = a, *nb = b; - if(na->last_connect_try == nb->last_connect_try) + if(na->last_successfull_connection == nb->last_successfull_connection) return 0; - if(nb->last_connect_try == 0 || na->last_connect_try < nb->last_connect_try) + if(na->last_successfull_connection == 0 || na->last_successfull_connection > nb->last_successfull_connection) + return -1; + + if(nb->last_successfull_connection == 0 || na->last_successfull_connection < nb->last_successfull_connection) + return 1; + + if(na < nb) return -1; - if(na->last_connect_try == 0 || na->last_connect_try > nb->last_connect_try) + if(na > nb) return 1; return 0; @@ -181,10 +194,110 @@ static int node_compare_devclass_desc(const void *a, const void *b) if(na->devclass > nb->devclass) { return 1; } + if(na < nb) + return -1; + + if(na > nb) + return 1; + return 0; } +/* + +autoconnect() +{ + timeout = 5 + + // find the best one for initial connect + + if cur < min + newcon = + first from nodes + where dclass <= my.dclass and !connection and (timestamp - last_retry) > retry_timeout + order by dclass asc, last_connection desc + if newcon + timeout = 0 + goto connect + + + // find better nodes to connect to: in case we have less than min connections within [BACKBONE, i] and there are nodes which we are not connected to within the range + + if min <= cur < max + j = 0 + for i = BACKBONE to my.dclass + j += count(from connections where node.dclass = i) + if j < min + newcon = + first from nodes + where dclass = i and !connection and (timestamp - last_retry) > retry_timeout + order by last_connection desc + if newcon + goto connect + else + break + + + // heal partitions + + if min <= cur < max + newcon = + first from nodes + where dclass <= my.dclass and !reachable and (timestamp - last_retry) > retry_timeout + order by dclass asc, last_connection desc + if newcon + goto connect + + + // connect + +connect: + if newcon + connect newcon + + + // disconnect outgoing connections in case we have more than min connections within [BACKBONE, i] and there are nodes which we are connected to within the range [i, PORTABLE] + + if min < cur <= max + j = 0 + for i = BACKBONE to my.dclass + j += count(from connections where node.dclass = i) + if min < j + delcon = + first from nodes + where dclass >= i and outgoing_connection + order by dclass desc + if disconnect + goto disconnect + else + break + + + // disconnect connections in case we have more than enough connections + + if max < cur + delcon = + first from nodes + where outgoing_connection + order by dclass desc + goto disconnect + + // disconnect + +disconnect + if delcon + disconnect delcon + + + // next iteration + next (timeout, autoconnect) + +} + +*/ + + static void periodic_handler(event_loop_t *loop, void *data) { meshlink_handle_t *mesh = loop->data; @@ -216,9 +329,13 @@ static void periodic_handler(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_INFO, "--- autoconnect begin ---"); - int retry_timeout = min(mesh->nodes->count * 5, 60); + logger(mesh, MESHLINK_INFO, "* devclass = %d", mesh->devclass); + logger(mesh, MESHLINK_INFO, "* nodes = %d", mesh->nodes->count); + logger(mesh, MESHLINK_INFO, "* retry_timeout = %d", retry_timeout); + + // connect disconnect nodes node_t* connect_to = NULL; @@ -238,10 +355,12 @@ static void periodic_handler(event_loop_t *loop, void *data) { } logger(mesh, MESHLINK_INFO, "* cur_connects = %d", cur_connects); - + logger(mesh, MESHLINK_INFO, "* outgoings = %d", mesh->outgoings->count); // get min_connects and max_connects + assert(mesh->devclass >= 0 && mesh->devclass <= _DEV_CLASS_MAX); + int min_connects = dev_class_traits[mesh->devclass].min_connects; int max_connects = dev_class_traits[mesh->devclass].max_connects; @@ -253,11 +372,12 @@ static void periodic_handler(event_loop_t *loop, void *data) { if(cur_connects < min_connects) { - splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_last_connect_try_desc, NULL); + splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + logger(mesh, MESHLINK_INFO, "* n->devclass = %d", n->devclass); + if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -265,9 +385,11 @@ static void periodic_handler(event_loop_t *loop, void *data) { { logger(mesh, MESHLINK_INFO, "* found best one for initial connect"); - timeout = 0; + //timeout = 0; connect_to = (node_t*)nodes->head->data; } + else + { logger(mesh, MESHLINK_INFO, "* could not find node for initial connect"); } splay_free_tree(nodes); } @@ -275,7 +397,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { // find better nodes to connect to - if(!connect_to && min_connects <= cur_connects < max_connects) + if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) { unsigned int connects = 0; @@ -289,11 +411,11 @@ static void periodic_handler(event_loop_t *loop, void *data) { if( connects < min_connects ) { - splay_tree_t *nodes = splay_alloc_tree(node_compare_last_connect_try_desc, NULL); + splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -311,18 +433,21 @@ static void periodic_handler(event_loop_t *loop, void *data) { else { break; } } + + if(!connect_to) + { logger(mesh, MESHLINK_INFO, "* could not find better nodes"); } } // heal partitions - if(!connect_to && min_connects <= cur_connects < max_connects) + if(!connect_to && min_connects <= cur_connects && cur_connects < max_connects) { - splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_last_connect_try_desc, NULL); + splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) + if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -331,6 +456,8 @@ static void periodic_handler(event_loop_t *loop, void *data) { logger(mesh, MESHLINK_INFO, "* try to heal partition"); connect_to = (node_t*)nodes->head->data; } + else + { logger(mesh, MESHLINK_INFO, "* could not find nodes for partition healing"); } splay_free_tree(nodes); } @@ -340,18 +467,36 @@ static void periodic_handler(event_loop_t *loop, void *data) { if(connect_to && !connect_to->connection) { - logger(mesh, MESHLINK_INFO, "Autoconnecting to %s", connect_to->name); - outgoing_t *outgoing = xzalloc(sizeof(outgoing_t)); - outgoing->mesh = mesh; - outgoing->name = xstrdup(connect_to->name); - list_insert_tail(mesh->outgoings, outgoing); - setup_outgoing_connection(mesh, outgoing); + connect_to->last_connect_try = time(NULL); + + /* check if there is already a connection attempt to this node */ + bool found = false; + for list_each(outgoing_t, outgoing, mesh->outgoings) + { + if(!strcmp(outgoing->name, connect_to->name)) + { + found = true; + break; + } + } + + if(!found) + { + logger(mesh, MESHLINK_INFO, "Autoconnecting to %s", connect_to->name); + outgoing_t *outgoing = xzalloc(sizeof(outgoing_t)); + outgoing->mesh = mesh; + outgoing->name = xstrdup(connect_to->name); + list_insert_tail(mesh->outgoings, outgoing); + setup_outgoing_connection(mesh, outgoing); + } + else + { logger(mesh, MESHLINK_INFO, "* skip autoconnect since it is an outgoing connection already"); } } // disconnect suboptimal outgoing connections - if(min_connects < cur_connects <= max_connects) + if(min_connects < cur_connects && cur_connects <= max_connects) { unsigned int connects = 0; @@ -383,6 +528,9 @@ static void periodic_handler(event_loop_t *loop, void *data) { break; } } + + if(!disconnect_from) + { logger(mesh, MESHLINK_INFO, "* no suboptimal outgoing connections"); } } @@ -400,11 +548,13 @@ static void periodic_handler(event_loop_t *loop, void *data) { if(nodes->head) { - logger(mesh, MESHLINK_INFO, "* disconnect connection (too many connections"); + logger(mesh, MESHLINK_INFO, "* disconnect connection (too many connections)"); - timeout = 0; + //timeout = 0; disconnect_from = (node_t*)nodes->head->data; } + else + { logger(mesh, MESHLINK_INFO, "* no node we want to disconnect, even though we have too many connections"); } splay_free_tree(nodes); } @@ -465,7 +615,7 @@ int main_loop(meshlink_handle_t *mesh) { mesh->datafromapp.signum = 0; signal_add(&(mesh->loop),&(mesh->datafromapp), (signal_cb_t)meshlink_send_from_queue,mesh, mesh->datafromapp.signum); - if(!event_loop_run(&mesh->loop)) { + if(!event_loop_run(&(mesh->loop), &(mesh->mesh_mutex))) { logger(mesh, MESHLINK_ERROR, "Error while waiting for input: %s", strerror(errno)); return 1; }