cleanup, 1. step (to get some local changes away):
[olsrd.git] / lib / dot_draw / src / olsrd_dot_draw.c
index 6166b75..4e4ba42 100644 (file)
 /*
- * OLSR plugin
- * Copyright (C) 2004 Andreas T√łnnesen (andreto@olsr.org)
+ * The olsr.org Optimized Link-State Routing daemon(olsrd)
+ * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
+ *                     includes code by Bruno Randolf
+ * All rights reserved.
  *
- * This file is part of the olsrd dynamic gateway detection.
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met:
  *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * * Redistributions of source code must retain the above copyright 
+ *   notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright 
+ *   notice, this list of conditions and the following disclaimer in 
+ *   the documentation and/or other materials provided with the 
+ *   distribution.
+ * * Neither the name of olsr.org, olsrd nor the names of its 
+ *   contributors may be used to endorse or promote products derived 
+ *   from this software without specific prior written permission.
  *
- * This plugin is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
+ * POSSIBILITY OF SUCH DAMAGE.
  *
- * You should have received a copy of the GNU General Public License
- * along with olsrd-unik; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- * 
- * 
- * $Id: olsrd_dot_draw.c,v 1.6 2004/11/06 14:07:20 kattemat Exp $
+ * Visit http://www.olsr.org for more information.
  *
+ * If you find this software useful feel free to make a donation
+ * to the project. For more information see the website or contact
+ * the copyright holders.
+ *
+ * $Id: olsrd_dot_draw.c,v 1.23 2007/04/20 14:06:18 bernd67 Exp $
  */
 
 /*
- * Dynamic linked library for UniK OLSRd
+ * Dynamic linked library for the olsr.org olsr daemon
  */
 
-#include "olsrd_dot_draw.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <time.h>
+#include <math.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
+
+#include "olsr.h"
+#include "olsr_types.h"
+#include "neighbor_table.h"
+#include "two_hop_neighbor_table.h"
+#include "tc_set.h"
+#include "hna_set.h"
+#include "mid_set.h"
+#include "link_set.h"
+#include "socket_parser.h"
+
+#include "olsrd_dot_draw.h"
+#include "olsrd_plugin.h"
+
+
 #ifdef WIN32
 #define close(x) closesocket(x)
 #endif
 
-int ipc_socket;
-int ipc_open;
-int ipc_connection;
-int ipc_socket_up;
+
+static int ipc_socket;
+static int ipc_open;
+static int ipc_connection;
+static int ipc_socket_up;
+
+
+
+/* IPC initialization function */
+static int
+plugin_ipc_init(void);
+
+static char*
+olsr_netmask_to_string(union hna_netmask *mask);
+
+/* Event function to register with the sceduler */
+static int
+pcf_event(int, int, int);
+
+static void
+ipc_action(int);
+
+static void
+ipc_print_neigh_link(struct neighbor_entry *neighbor);
+
+static void
+ipc_print_tc_link(struct tc_entry *entry, struct topo_dst *dst_entry);
+
+static void
+ipc_print_net(union olsr_ip_addr *, union olsr_ip_addr *, union hna_netmask *);
+
+static int
+ipc_send(const char *, int);
+
+static int
+ipc_send_str(const char *);
+
+static double 
+calc_etx(double, double);
+
 
 /**
  *Do initialization here
@@ -49,21 +124,70 @@ int ipc_socket_up;
  *function in uolsrd_plugin.c
  */
 int
-olsr_plugin_init()
+olsrd_plugin_init(void)
 {
-
   /* Initial IPC value */
   ipc_open = 0;
   ipc_socket_up = 0;
+  ipc_socket = -1;
+  ipc_connection = -1;
 
   /* Register the "ProcessChanges" function */
   register_pcf(&pcf_event);
 
+  plugin_ipc_init();
+
   return 1;
 }
 
-int
-plugin_ipc_init()
+
+/**
+ * destructor - called at unload
+ */
+void
+olsr_plugin_exit(void)
+{
+  if(ipc_open)
+    close(ipc_socket);
+}
+
+
+static void
+ipc_print_neigh_link(struct neighbor_entry *neighbor)
+{
+  char buf[256];
+  const char* adr;
+  double etx = 0.0;
+  char* style = "solid";
+  struct link_entry* link;
+  adr = olsr_ip_to_string(&olsr_cnf->main_addr);
+  sprintf( buf, "\"%s\" -> ", adr );
+  ipc_send_str(buf);
+  
+  adr = olsr_ip_to_string(&neighbor->neighbor_main_addr);
+  
+  if (neighbor->status == 0) { // non SYM
+       style = "dashed";
+  }
+  else {   
+      link = get_best_link_to_neighbor(&neighbor->neighbor_main_addr);
+      if (link) {
+        etx = calc_etx( link->loss_link_quality, link->neigh_link_quality);
+      }
+  }
+    
+  sprintf( buf, "\"%s\"[label=\"%.2f\", style=%s];\n", adr, etx, style );
+  ipc_send_str(buf);
+  
+   if (neighbor->is_mpr) {
+       sprintf( buf, "\"%s\"[shape=box];\n", adr );
+       ipc_send_str(buf);
+  }
+}
+
+
+static int
+plugin_ipc_init(void)
 {
   struct sockaddr_in sin;
   olsr_u32_t yes = 1;
@@ -82,13 +206,21 @@ plugin_ipc_init()
        return 0;
       }
 
+#if defined __FreeBSD__ && defined SO_NOSIGPIPE
+      if (setsockopt(ipc_socket, SOL_SOCKET, SO_NOSIGPIPE, (char *)&yes, sizeof(yes)) < 0) 
+      {
+       perror("SO_REUSEADDR failed");
+       return 0;
+      }
+#endif
+
       /* Bind the socket */
       
       /* complete the socket structure */
       memset(&sin, 0, sizeof(sin));
       sin.sin_family = AF_INET;
       sin.sin_addr.s_addr = INADDR_ANY;
-      sin.sin_port = htons(2004);
+      sin.sin_port = htons(ipc_port);
       
       /* bind the socket to the port number */
       if (bind(ipc_socket, (struct sockaddr *) &sin, sizeof(sin)) == -1) 
@@ -106,6 +238,7 @@ plugin_ipc_init()
 
 
       /* Register with olsrd */
+      printf("Adding socket with olsrd\n");
       add_olsr_socket(ipc_socket, &ipc_action);
       ipc_socket_up = 1;
     }
@@ -113,28 +246,37 @@ plugin_ipc_init()
   return 1;
 }
 
-void
-ipc_action(int fd)
+
+static void
+ipc_action(int fd __attribute__((unused)))
 {
   struct sockaddr_in pin;
-  socklen_t addrlen;
-  char *addr;  
-
-  addrlen = sizeof(struct sockaddr_in);
+  socklen_t addrlen = sizeof(struct sockaddr_in);
 
+  if (ipc_open)
+    {
+      int rc;
+      do {
+        rc = close(ipc_connection);
+      } while (rc == -1 && (errno == EINTR || errno == EAGAIN));
+      if (rc == -1) {
+        olsr_printf(1, "(DOT DRAW) Error on closing previously active TCP connection on fd %d: %s\n", ipc_connection, strerror(errno));
+      }
+      ipc_open = 0;
+    }
+  
   if ((ipc_connection = accept(ipc_socket, (struct sockaddr *)  &pin, &addrlen)) == -1)
     {
       olsr_printf(1, "(DOT DRAW)IPC accept: %s\n", strerror(errno));
-      exit(1);
     }
   else
     {
-      addr = inet_ntoa(pin.sin_addr);
-      if(ntohl(pin.sin_addr.s_addr) != INADDR_LOOPBACK)
+      char *addr = inet_ntoa(pin.sin_addr);
+      if(ntohl(pin.sin_addr.s_addr) != ntohl(ipc_accept_ip.s_addr))
        {
          olsr_printf(1, "Front end-connection from foregin host(%s) not allowed!\n", addr);
          close(ipc_connection);
-         return;
+          ipc_connection = -1;
        }
       else
        {
@@ -143,42 +285,13 @@ ipc_action(int fd)
          pcf_event(1, 1, 1);
        }
     }
-
-}
-
-/*
- * destructor - called at unload
- */
-void
-olsr_plugin_exit()
-{
-  if(ipc_open)
-    close(ipc_socket);
 }
 
 
-
-/* Mulitpurpose funtion */
-int
-plugin_io(int cmd, void *data, size_t size)
-{
-
-  switch(cmd)
-    {
-    default:
-      return 0;
-    }
-  
-  return 1;
-}
-
-
-
-
 /**
  *Scheduled event
  */
-int
+static int
 pcf_event(int changes_neighborhood,
          int changes_topology,
          int changes_hna)
@@ -186,7 +299,6 @@ pcf_event(int changes_neighborhood,
   int res;
   olsr_u8_t index;
   struct neighbor_entry *neighbor_table_tmp;
-  struct neighbor_2_list_entry *list_2;
   struct tc_entry *entry;
   struct topo_dst *dst_entry;
   struct hna_entry *tmp_hna;
@@ -198,7 +310,7 @@ pcf_event(int changes_neighborhood,
     {
       /* Print tables to IPC socket */
 
-      ipc_send("digraph topology\n{\n", strlen("digraph topology\n{\n"));
+      ipc_send_str("digraph topology\n{\n");
 
       /* Neighbors */
       for(index=0;index<HASHSIZE;index++)
@@ -208,25 +320,7 @@ pcf_event(int changes_neighborhood,
              neighbor_table_tmp != &neighbortable[index];
              neighbor_table_tmp = neighbor_table_tmp->next)
            {
-             if(neighbor_table_tmp->is_mpr)
-               {
-                 ipc_print_mpr_link(main_addr, &neighbor_table_tmp->neighbor_main_addr);                 
-                 ipc_print_mpr_link(&neighbor_table_tmp->neighbor_main_addr, main_addr);
-               }
-             else
-               {
-                 ipc_print_neigh_link(main_addr, &neighbor_table_tmp->neighbor_main_addr);               
-                 ipc_print_neigh_link(&neighbor_table_tmp->neighbor_main_addr, main_addr);
-               }
-
-             for(list_2 = neighbor_table_tmp->neighbor_2_list.next;
-                 list_2 != &neighbor_table_tmp->neighbor_2_list;
-                 list_2 = list_2->next)
-               {
-                 ipc_print_2h_link(&neighbor_table_tmp->neighbor_main_addr, 
-                                   &list_2->neighbor_2->neighbor_2_addr);
-               }
-             
+             ipc_print_neigh_link( neighbor_table_tmp );
            }
        }
 
@@ -241,12 +335,11 @@ pcf_event(int changes_neighborhood,
              dst_entry = entry->destinations.next;
              while(dst_entry != &entry->destinations)
                {
-                 ipc_print_tc_link(&entry->T_last_addr, &dst_entry->T_dest_addr);
+                 ipc_print_tc_link(entry, dst_entry);
                  dst_entry = dst_entry->next;
                }
              entry = entry->next;
            }
-         
        }
 
       /* HNA entries */
@@ -272,7 +365,7 @@ pcf_event(int changes_neighborhood,
        }
 
 
-      ipc_send("}\n\n", strlen("}\n\n"));
+      ipc_send_str("}\n\n");
 
       res = 1;
     }
@@ -285,102 +378,80 @@ pcf_event(int changes_neighborhood,
 }
 
 
-
-
-static void inline
-ipc_print_neigh_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
+#define MIN_LINK_QUALITY 0.01
+static double 
+calc_etx(double loss, double neigh_loss) 
 {
-  char *adr;
-
-  adr = olsr_ip_to_string(from);
-  ipc_send("\"", 1);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\" -> \"", strlen("\" -> \""));
-  adr = olsr_ip_to_string(to);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"[label=\"neigh\", style=dashed];\n", strlen("\"[label=\"neigh\", style=dashed];\n"));
-
+  if (loss < MIN_LINK_QUALITY || neigh_loss < MIN_LINK_QUALITY)
+    return 0.0;
+  else
+    return 1.0 / (loss * neigh_loss);
 }
 
-static void inline
-ipc_print_2h_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
-{
-  char *adr;
-
-  adr = olsr_ip_to_string(from);
-  ipc_send("\"", 1);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\" -> \"", strlen("\" -> \""));
-  adr = olsr_ip_to_string(to);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"[label=\"2 hop\"];\n", strlen("\"[label=\"2 hop\"];\n"));
 
-}
-
-static void inline
-ipc_print_mpr_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
+static void
+ipc_print_tc_link(struct tc_entry *entry, struct topo_dst *dst_entry)
 {
-  char *adr;
-
-  adr = olsr_ip_to_string(from);
-  ipc_send("\"", 1);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\" -> \"", strlen("\" -> \""));
-  adr = olsr_ip_to_string(to);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"[label=\"MPR\", style=dashed];\n", strlen("\"[label=\"MPR\", style=dashed]];\n"));
+  char buf[256];
+  const char* adr;
+  double etx = calc_etx( dst_entry->link_quality, dst_entry->inverse_link_quality );
 
+  adr = olsr_ip_to_string(&entry->T_last_addr);
+  sprintf( buf, "\"%s\" -> ", adr );
+  ipc_send_str(buf);
+  
+  adr = olsr_ip_to_string(&dst_entry->T_dest_addr);
+  sprintf( buf, "\"%s\"[label=\"%.2f\"];\n", adr, etx );
+  ipc_send_str(buf);
 }
 
-static void inline
-ipc_print_tc_link(union olsr_ip_addr *from, union olsr_ip_addr *to)
-{
-  char *adr;
-
-  adr = olsr_ip_to_string(from);
-  ipc_send("\"", 1);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\" -> \"", strlen("\" -> \""));
-  adr = olsr_ip_to_string(to);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"[label=\"TC\"];\n", strlen("\"[label=\"TC\"];\n"));
 
-}
-
-static void inline
+static void
 ipc_print_net(union olsr_ip_addr *gw, union olsr_ip_addr *net, union hna_netmask *mask)
 {
-  char *adr;
+  const char *adr;
 
   adr = olsr_ip_to_string(gw);
-  ipc_send("\"", 1);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\" -> \"", strlen("\" -> \""));
+  ipc_send_str("\"");
+  ipc_send_str(adr);
+  ipc_send_str("\" -> \"");
   adr = olsr_ip_to_string(net);
-  ipc_send(adr, strlen(adr));
-  ipc_send("/", 1);
+  ipc_send_str(adr);
+  ipc_send_str("/");
   adr = olsr_netmask_to_string(mask);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"[label=\"HNA\"];\n", strlen("\"[label=\"HNA\"];\n"));
-  ipc_send("\"", 1);
+  ipc_send_str(adr);
+  ipc_send_str("\"[label=\"HNA\"];\n");
+  ipc_send_str("\"");
   adr = olsr_ip_to_string(net);
-  ipc_send(adr, strlen(adr));
-  ipc_send("/", 1);
+  ipc_send_str(adr);
+  ipc_send_str("/");
   adr = olsr_netmask_to_string(mask);
-  ipc_send(adr, strlen(adr));
-  ipc_send("\"", 1);
-  ipc_send("[shape=diamond];\n", strlen("[shape=diamond];\n"));
+  ipc_send_str(adr);
+  ipc_send_str("\"");
+  ipc_send_str("[shape=diamond];\n");
 }
 
+static int
+ipc_send_str(const char *data)
+{
+  if(!ipc_open)
+    return 0;
+  return ipc_send(data, strlen(data));
+}
 
 
-int
-ipc_send(char *data, int size)
+static int
+ipc_send(const char *data, int size)
 {
   if(!ipc_open)
     return 0;
 
-  if (send(ipc_connection, data, size, MSG_NOSIGNAL) < 0) 
+#if defined __FreeBSD__ || defined __NetBSD__ || defined __OpenBSD__ || defined __MacOSX__
+#define FLAGS 0
+#else
+#define FLAGS MSG_NOSIGNAL
+#endif
+  if (send(ipc_connection, data, size, FLAGS) == -1)
     {
       olsr_printf(1, "(DOT DRAW)IPC connection lost!\n");
       close(ipc_connection);
@@ -391,73 +462,24 @@ ipc_send(char *data, int size)
   return 1;
 }
 
-
-
-
-
-/**
- *Converts a olsr_ip_addr to a string
- *Goes for both IPv4 and IPv6
- *
- *NON REENTRANT! If you need to use this
- *function twice in e.g. the same printf
- *it will not work.
- *You must use it in different calls e.g.
- *two different printfs
- *
- *@param the IP to convert
- *@return a pointer to a static string buffer
- *representing the address in "dots and numbers"
- *
- */
-char *
-olsr_ip_to_string(union olsr_ip_addr *addr)
-{
-
-  char *ret;
-  struct in_addr in;
-  
-  if(ipversion == AF_INET)
-    {
-      in.s_addr=addr->v4;
-      ret = inet_ntoa(in);
-    }
-  else
-    {
-      /* IPv6 */
-      ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
-    }
-
-  return ret;
-}
-
-
-
-
-/**
- *This function is just as bad as the previous one :-(
- */
-char *
+static char*
 olsr_netmask_to_string(union hna_netmask *mask)
 {
   char *ret;
   struct in_addr in;
-  
-  if(ipversion == AF_INET)
+
+  if(olsr_cnf->ip_version == AF_INET)
     {
       in.s_addr = mask->v4;
       ret = inet_ntoa(in);
-      return ret;
-
     }
   else
     {
       /* IPv6 */
+      static char netmask[5];
       sprintf(netmask, "%d", mask->v6);
-      return netmask;
+      ret = netmask;
     }
 
   return ret;
 }
-
-