]> git.meshlink.io Git - meshlink/commitdiff
class based connect behaviour
authorNiklas Hofmann <niklas.hofmann@everbase.net>
Sat, 9 Aug 2014 16:26:35 +0000 (18:26 +0200)
committerNiklas Hofmann <niklas.hofmann@everbase.net>
Sat, 9 Aug 2014 16:26:35 +0000 (18:26 +0200)
src/discovery.c
src/meshlink.c
src/meshlink_internal.h
src/net.c
src/net.h
src/net_setup.c
src/protocol_auth.c

index b50aea8d80f689991355db5dac9269eb292fa06e..d17f962b4ebfebb7ba41b4fd3887a9eb3bc69dc3 100644 (file)
@@ -163,7 +163,6 @@ static void discovery_server_callback(AvahiServer *server, AvahiServerState stat
                 {
                     logger(mesh, MESHLINK_ERROR, "Avahi failed to set new host name: %s\n", avahi_strerror(result));
                     avahi_simple_poll_quit(mesh->avahi_poll);
-                    return;
                 }
             }
             break;
@@ -347,7 +346,7 @@ static void discovery_browse_callback(AvahiSServiceBrowser *browser, AvahiIfInde
                 logger(mesh, MESHLINK_ERROR, "(Browser) %s\n", avahi_strerror(avahi_server_errno(mesh->avahi_server)));
                 avahi_simple_poll_quit(mesh->avahi_poll);
             }
-            return;
+            break;
 
         case AVAHI_BROWSER_NEW:
             {
index 7f009d940468a30afd704c2371c3bd25261b4e18..95ab41c7ab03f072fa1547b42be6eee92b20cadf 100644 (file)
@@ -1706,7 +1706,7 @@ static void __attribute__((destructor)) meshlink_exit(void) {
        crypto_exit();
 }
 
-int weight_from_dclass(dclass_t dclass)
+int cweight_from_dclass(dclass_t dclass)
 {
        switch(dclass)
        {
@@ -1722,3 +1722,84 @@ int weight_from_dclass(dclass_t dclass)
 
        return 9;
 }
+
+int max_ccount_from_dclass(dclass_t dclass)
+{
+       switch(dclass)
+       {
+       case BACKBONE:
+               return 10000;
+
+       case STATIONARY:
+               return 100;
+
+       case PORTABLE:
+               return 3;
+       }
+
+       return 3;
+}
+
+bool dclass_ccounts_satisfied(dclass_t dclass, splay_tree_t* counts, int total_count)
+{
+       // lookup keys
+       dclass_ccount_t key_portable;
+       key_portable.dclass = PORTABLE;
+
+       dclass_ccount_t key_stationary;
+       key_stationary.dclass = STATIONARY;
+
+       dclass_ccount_t key_backbone;
+       key_backbone.dclass = BACKBONE;
+
+       // check num of portable devices
+       dclass_ccount_t* portable = splay_search(counts, &key_portable);
+
+       if(portable)
+       {
+               if(portable->ccount > 9)
+                       return true;
+       }
+
+       // check num of stationary devices
+       dclass_ccount_t* stationary = splay_search(counts, &key_stationary);
+
+       if(stationary)
+       {
+               if(stationary->ccount > 6)
+                       return true;
+       }
+
+       // check num of backbone devices
+       dclass_ccount_t* backbone = splay_search(counts, &key_backbone);
+
+       if(backbone)
+       {
+               if(backbone->ccount > 3)
+                       return true;
+       }
+
+       // fallback
+       if(total_count >= max_ccount_from_dclass(dclass))
+               return true;
+
+       return false;
+}
+
+int dclass_ccount_compare(const void *a, const void *b)
+{
+       const dclass_ccount_t* da = a;
+       const dclass_ccount_t* db = b;
+
+       return da->dclass - db->dclass;
+}
+
+dclass_ccount_t* dclass_ccount_alloc()
+{
+       return xzalloc(sizeof(dclass_ccount_t));
+}
+
+void dclass_ccount_delete(void *c)
+{
+       free(c);
+}
index 63a71dc048dc0f81d693908dab280a396fbf9499..f7f0ba789b7164cd66e8afef1a542d4a27df02aa 100644 (file)
@@ -158,6 +158,17 @@ extern void meshlink_send_from_queue(event_loop_t* el,meshlink_handle_t *mesh);
 extern meshlink_log_level_t global_log_level;
 extern meshlink_log_cb_t global_log_cb;
 
-extern int weight_from_dclass(dclass_t dclass);
+extern int cweight_from_dclass(dclass_t dclass);
+extern int max_ccount_from_dclass(dclass_t dclass);
+extern bool dclass_ccounts_satisfied(dclass_t dclass, splay_tree_t* counts, int total_count);
+
+typedef struct {
+       dclass_t dclass;
+       int ccount;
+} dclass_ccount_t;
+
+extern int dclass_ccount_compare(const void *a, const void *b);
+extern dclass_ccount_t* dclass_ccount_alloc();
+extern void dclass_ccount_delete(void *c);
 
 #endif // MESHLINK_INTERNAL_H
index 4045c136fa676912ac42110e6eb0920974cf8650..e5e80ae9d9e3c1cf1bc414ca48705977a70f5060 100644 (file)
--- a/src/net.c
+++ b/src/net.c
@@ -223,14 +223,32 @@ static void periodic_handler(event_loop_t *loop, void *data) {
 
        int timeout = 5;
 
-       /* If AutoConnect is set, check if we need to make or break connections. */
+       /* Check if we need to make or break connections. */
 
-       if(autoconnect && mesh->nodes->count > 1) {
-               /* Count number of active connections */
-               int nc = 0;
+       if(mesh->nodes->count > 1) {
+
+               splay_tree_t* ccounts = splay_alloc_tree(dclass_ccount_compare, NULL);
+
+               /* Count number of active connections per device class */
+               int num_total = 0;
                for list_each(connection_t, c, mesh->connections) {
                        if(c->status.active)
-                               nc++;
+                       {
+                               dclass_ccount_t key;
+                               key.dclass = c->node->dclass;
+
+                               dclass_ccount_t* ccount = splay_search(ccounts, &key);
+
+                               if(!ccount)
+                               {
+                                       ccount = dclass_ccount_alloc();
+                                       ccount->dclass = c->node->dclass;
+                                       splay_insert(ccounts, ccount);
+                               }
+
+                               ccount->ccount++;
+                               num_total++;
+                       }
                }
 
                /* Count number of unreachable nodes */
@@ -240,14 +258,18 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                                num_unreachable++;
                }
 
-               if(nc < autoconnect) {
+               bool satisfied = dclass_ccounts_satisfied(mesh->self->dclass, ccounts, num_total);
+
+               if(!satisfied) {
                        /* 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.
                        */
                        cond_add_connection(mesh, mesh->nodes->count, &found_random_node);
-               } else if(num_unreachable > 0) {
+               }
+
+               if(satisfied && num_unreachable > 0) {
                        /* Min number of connections established. Now try
                           to connect to some unreachable nodes to attempt
                           to heal possible partitions.
@@ -255,12 +277,12 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        cond_add_connection(mesh, num_unreachable, &found_random_unreachable_node);
                }
                
-               if(nc > autoconnect) {
+               if(max_ccount_from_dclass(mesh->self->dclass) > num_total) {
                        /* 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 r = rand() % num_total;
                        int i = 0;
 
                        for list_each(connection_t, c, mesh->connections) {
@@ -281,7 +303,7 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        }
                }
 
-               if(nc >= autoconnect) {
+               if(satisfied) {
                        /* If we have enough active connections,
                           remove any pending outgoing connections.
                           Do not remove pending connections to unreachable
@@ -312,8 +334,10 @@ static void periodic_handler(event_loop_t *loop, void *data) {
                        }
                }
 
-               if (nc + mesh->outgoings->count < min(autoconnect, mesh->nodes->count - 1))
+               if (!satisfied && (num_total + mesh->outgoings->count) < mesh->nodes->count)
                        timeout = 0;
+
+               splay_free_tree(ccounts);
        }
 
        timeout_set(&mesh->loop, data, &(struct timeval){timeout, rand() % 100000});
index 6014a3d6207881d15b4fbc8bbfe8aa8f43d48f2e..d2a60bcf685c858ef079f59b8d1b76305b609722 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -76,7 +76,6 @@ extern unsigned replaywin;
 extern int keylifetime;
 extern int max_connection_burst;
 extern bool do_prune;
-extern int autoconnect;
 
 /* Yes, very strange placement indeed, but otherwise the typedefs get all tangled up */
 #include "connection.h"
index 68b8ed7499d92209573e5aeb582bc991e753b0d4..3a14729a12248fd7a29156b81d5c5f51b537d772 100644 (file)
@@ -32,8 +32,6 @@
 #include "utils.h"
 #include "xalloc.h"
 
-int autoconnect = 3;
-
 bool node_read_ecdsa_public_key(meshlink_handle_t *mesh, node_t *n) {
        if(ecdsa_active(n->ecdsa))
                return true;
@@ -230,7 +228,6 @@ bool setup_myself_reloadable(meshlink_handle_t *mesh) {
        mesh->localdiscovery = true;
        keylifetime = 3600; // TODO: check if this can be removed as well
        mesh->maxtimeout = 900;
-       autoconnect = 3;
        mesh->self->options |= OPTION_PMTU_DISCOVERY;
 
        read_invitation_key(mesh);
@@ -383,8 +380,7 @@ bool setup_myself(meshlink_handle_t *mesh) {
 
        graph(mesh);
 
-       if(autoconnect)
-               load_all_nodes(mesh);
+       load_all_nodes(mesh);
 
        /* Open sockets */
 
index 76188f6ebdba79fa11837daffeea33b897750ad0..65736253020c08cf49d6c6758b4c37187aaee749 100644 (file)
@@ -444,7 +444,7 @@ bool ack_h(meshlink_handle_t *mesh, connection_t *c, const char *request) {
        sockaddr2str(&c->address, &hisaddress, NULL);
        c->edge->address = str2sockaddr(hisaddress, hisport);
        free(hisaddress);
-       c->edge->weight = weight_from_dclass(dclass);
+       c->edge->weight = cweight_from_dclass(dclass);
        c->edge->connection = c;
        c->edge->options = c->options;