tinc-gui: Reformat codebase according to PEP8
[tinc] / src / graph.c
index 48310bc..e570feb 100644 (file)
@@ -1,6 +1,6 @@
 /*
     graph.c -- graph algorithms
-    Copyright (C) 2001-2012 Guus Sliepen <guus@tinc-vpn.org>,
+    Copyright (C) 2001-2013 Guus Sliepen <guus@tinc-vpn.org>,
                   2001-2005 Ivo Timmermans
 
     This program is free software; you can redistribute it and/or modify
 
 #include "system.h"
 
-#include "config.h"
 #include "connection.h"
 #include "device.h"
 #include "edge.h"
 #include "graph.h"
 #include "list.h"
 #include "logger.h"
+#include "names.h"
 #include "netutl.h"
 #include "node.h"
-#include "process.h"
 #include "protocol.h"
+#include "script.h"
 #include "subnet.h"
 #include "utils.h"
 #include "xalloc.h"
 #include "graph.h"
 
 /* Implementation of Kruskal's algorithm.
-   Running time: O(E)
+   Running time: O(EN)
    Please note that sorting on weight is already done by add_edge().
 */
 
@@ -78,11 +78,24 @@ static void mst_kruskal(void) {
        for splay_each(node_t, n, node_tree)
                n->status.visited = false;
 
+       /* Starting point */
+
+       for splay_each(edge_t, e, edge_weight_tree) {
+               if(e->from->status.reachable) {
+                       e->from->status.visited = true;
+                       break;
+               }
+       }
+
        /* Add safe edges */
 
+       bool skipped = false;
+
        for splay_each(edge_t, e, edge_weight_tree) {
-               if(!e->reverse || (e->from->status.visited && e->to->status.visited))
+               if(!e->reverse || (e->from->status.visited == e->to->status.visited)) {
+                       skipped = true;
                        continue;
+               }
 
                e->from->status.visited = true;
                e->to->status.visited = true;
@@ -93,8 +106,12 @@ static void mst_kruskal(void) {
                if(e->reverse->connection)
                        e->reverse->connection->status.mst = true;
 
-               logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name,
-                                  e->to->name, e->weight);
+               logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight);
+
+               if(skipped) {
+                       skipped = false;
+                       next = edge_weight_tree->head;
+               }
        }
 }
 
@@ -125,14 +142,14 @@ static void sssp_bfs(void) {
 
        /* Loop while todo_list is filled */
 
-       for list_each(node_t, n, todo_list) {                   /* "n" is the node from which we start */
+       for list_each(node_t, n, todo_list) {                   /* "n" is the node from which we start */
                logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Examining edges from %s", n->name);
 
                if(n->distance < 0)
                        abort();
 
-               for splay_each(edge_t, e, n->edge_tree) {       /* "e" is the edge connected to "from" */
-                       if(!e->reverse)
+               for splay_each(edge_t, e, n->edge_tree) {       /* "e" is the edge connected to "from" */
+                       if(!e->reverse || e->to == myself)
                                continue;
 
                        /* Situation:
@@ -159,9 +176,13 @@ static void sssp_bfs(void) {
                           && (e->to->distance != n->distance + 1 || e->weight >= e->to->prevedge->weight))
                                continue;
 
+                       // Only update nexthop if it doesn't increase the path length
+
+                       if(!e->to->status.visited || (e->to->distance == n->distance + 1 && e->weight >= e->to->prevedge->weight))
+                               e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
+
                        e->to->status.visited = true;
                        e->to->status.indirect = indirect;
-                       e->to->nexthop = (n->nexthop == myself) ? e->to : n->nexthop;
                        e->to->prevedge = e;
                        e->to->via = indirect ? n->via : e->to;
                        e->to->options = e->options;
@@ -183,17 +204,24 @@ static void sssp_bfs(void) {
 static void check_reachability(void) {
        /* Check reachability status. */
 
+       int reachable_count = 0;
+       int became_reachable_count = 0;
+       int became_unreachable_count = 0;
        for splay_each(node_t, n, node_tree) {
                if(n->status.visited != n->status.reachable) {
                        n->status.reachable = !n->status.reachable;
-                       n->last_state_change = time(NULL);
+                       n->last_state_change = now.tv_sec;
 
                        if(n->status.reachable) {
                                logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became reachable",
                                           n->name, n->hostname);
+                               if (n != myself)
+                                       became_reachable_count++;
                        } else {
                                logger(DEBUG_TRAFFIC, LOG_DEBUG, "Node %s (%s) became unreachable",
                                           n->name, n->hostname);
+                               if (n != myself)
+                                       became_unreachable_count++;
                        }
 
                        if(experimental && OPTION_VERSION(n->options) >= 2)
@@ -210,16 +238,16 @@ static void check_reachability(void) {
 
                        n->status.udp_confirmed = false;
                        n->maxmtu = MTU;
+                       n->maxrecentlen = 0;
                        n->minmtu = 0;
                        n->mtuprobes = 0;
 
-                       if(timeout_initialized(&n->mtuevent))
-                               event_del(&n->mtuevent);
+                       timeout_del(&n->udp_ping_timeout);
 
                        char *name;
                        char *address;
                        char *port;
-                       char *envp[7];
+                       char *envp[8] = {NULL};
 
                        xasprintf(&envp[0], "NETNAME=%s", netname ? : "");
                        xasprintf(&envp[1], "DEVICE=%s", device ? : "");
@@ -228,7 +256,7 @@ static void check_reachability(void) {
                        sockaddr2str(&n->address, &address, &port);
                        xasprintf(&envp[4], "REMOTEADDRESS=%s", address);
                        xasprintf(&envp[5], "REMOTEPORT=%s", port);
-                       envp[6] = NULL;
+                       xasprintf(&envp[6], "NAME=%s", myself->name);
 
                        execute_script(n->status.reachable ? "host-up" : "host-down", envp);
 
@@ -239,22 +267,31 @@ static void check_reachability(void) {
                        free(address);
                        free(port);
 
-                       for(int i = 0; i < 6; i++)
+                       for(int i = 0; i < 7; i++)
                                free(envp[i]);
 
                        subnet_update(n, NULL, n->status.reachable);
 
                        if(!n->status.reachable) {
                                update_node_udp(n, NULL);
+                               memset(&n->status, 0, sizeof n->status);
+                               n->options = 0;
                        } else if(n->connection) {
-                               if(n->status.sptps) {
-                                       if(n->connection->outgoing)
-                                               send_req_key(n);
-                               } else {
+                               // Speed up UDP probing by sending our key.
+                               if(!n->status.sptps)
                                        send_ans_key(n);
-                               }
                        }
                }
+
+               if(n->status.reachable && n != myself)
+                       reachable_count++;
+       }
+
+       if (device_standby) {
+               if (reachable_count == 0 && became_unreachable_count > 0)
+                       device_disable();
+               else if (reachable_count > 0 && reachable_count == became_reachable_count)
+                       device_enable();
        }
 }