gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r20896 - gnunet/src/integration-tests


From: gnunet
Subject: [GNUnet-SVN] r20896 - gnunet/src/integration-tests
Date: Wed, 4 Apr 2012 16:18:44 +0200

Author: wachs
Date: 2012-04-04 16:18:43 +0200 (Wed, 04 Apr 2012)
New Revision: 20896

Added:
   gnunet/src/integration-tests/connection_watchdog.c
Modified:
   gnunet/src/integration-tests/Makefile.am
Log:
- connection_watchdog tool


Modified: gnunet/src/integration-tests/Makefile.am
===================================================================
--- gnunet/src/integration-tests/Makefile.am    2012-04-04 11:41:46 UTC (rev 
20895)
+++ gnunet/src/integration-tests/Makefile.am    2012-04-04 14:18:43 UTC (rev 
20896)
@@ -9,10 +9,13 @@
   XLIB = -lgcov
 endif
 
-bin_PROGRAMS =
+#bin_PROGRAMS = \
+# connection_watchdog
 
 check_PROGRAMS =
 
+noinst_PROGRAMS = connection_watchdog
+
 noinst_SCRIPTS = \
  gnunet_testing.py \
  gnunet_pyexpect.py \
@@ -38,6 +41,13 @@
  $(check_SCRIPTS)  
 endif
 
+connection_watchdog_SOURCE = \
+ connection_watchdog.c      
+connection_watchdog_LDADD = \
+  $(top_builddir)/src/core/libgnunetcore.la \
+  $(top_builddir)/src/transport/libgnunettransport.la \
+  $(top_builddir)/src/util/libgnunetutil.la
+
 do_subst = $(SED) -e 's,address@hidden@],$(PYTHON),g'
 
 %.py: %.py.in Makefile

Added: gnunet/src/integration-tests/connection_watchdog.c
===================================================================
--- gnunet/src/integration-tests/connection_watchdog.c                          
(rev 0)
+++ gnunet/src/integration-tests/connection_watchdog.c  2012-04-04 14:18:43 UTC 
(rev 20896)
@@ -0,0 +1,376 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009, 2010 Christian Grothoff (and other contributing authors)
+
+     GNUnet 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 3, or (at your
+     option) any later version.
+
+     GNUnet 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.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file integration-test/connection_watchdog.c
+ * @brief tool to monitor core and transport connections for consistency
+ * @author Matthias Wachs
+ */
+#include "platform.h"
+#include "gnunet_common.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_getopt_lib.h"
+#include "gnunet_os_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_scheduler_lib.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_statistics_service.h"
+
+/**
+ * Final status code.
+ */
+static int ret;
+
+struct GNUNET_TRANSPORT_Handle *th;
+struct GNUNET_CORE_Handle *ch;
+struct GNUNET_PeerIdentity my_peer_id;
+
+static unsigned int transport_connections;
+static unsigned int core_connections;
+
+
+
+static struct GNUNET_CONTAINER_MultiHashMap *peers;
+
+struct PeerContainer
+{
+  struct GNUNET_PeerIdentity id;
+  int transport_connected;
+  int core_connected;
+};
+
+
+int map_check_it (void *cls,
+                  const GNUNET_HashCode * key,
+                  void *value)
+{
+  struct PeerContainer *pc = value;
+  if (pc->core_connected != pc->transport_connected)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+     "Inconsistend peer `%s': TRANSPORT %s <-> CORE %s\n",
+     GNUNET_i2s (&pc->id),
+     (GNUNET_YES == pc->transport_connected) ? "YES" : "NO",
+     (GNUNET_YES == pc->core_connected) ? "YES" : "NO");
+  }
+
+  return GNUNET_OK;
+}
+
+
+int map_cleanup_it (void *cls,
+                  const GNUNET_HashCode * key,
+                  void *value)
+{
+  struct PeerContainer *pc = value;
+  GNUNET_CONTAINER_multihashmap_remove(peers, key, value);
+  GNUNET_free (pc);
+  return GNUNET_OK;
+}
+
+static void map_check (void)
+{
+
+  GNUNET_CONTAINER_multihashmap_iterate (peers, &map_check_it, NULL);
+}
+
+static void
+map_connect (const struct GNUNET_PeerIdentity *peer, void * source)
+{
+  struct PeerContainer * pc;
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(peers, 
&peer->hashPubKey))
+  {
+    pc = GNUNET_malloc (sizeof (struct PeerContainer));
+    pc->id = *peer;
+    pc->core_connected = GNUNET_NO;
+    pc->transport_connected = GNUNET_NO;
+    GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(peers, 
&peer->hashPubKey, pc, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+
+  pc = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
+  if (source == th)
+  {
+    if (GNUNET_NO == pc->transport_connected)
+    {
+      pc->transport_connected = GNUNET_YES;
+      return;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+           "%s notified multiple times about for peers `%s' (%s : %s)\n",
+           "TRANSPORT",
+           GNUNET_i2s (&pc->id),
+           "CORE", (pc->core_connected == GNUNET_YES) ? "yes" : "no");
+      GNUNET_break (0);
+    }
+  }
+  if (source == ch)
+  {
+    if (GNUNET_NO == pc->core_connected)
+    {
+      pc->core_connected = GNUNET_YES;
+      return;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+           "%s notified multiple times about for peers `%s' (%s : %s)\n",
+           "CORE",
+           GNUNET_i2s (&pc->id),
+               "TRANSPORT", (pc->transport_connected == GNUNET_YES) ? "yes" : 
"no");
+      GNUNET_break (0);
+      return;
+    }
+  }
+}
+
+
+static void
+map_disconnect (const struct GNUNET_PeerIdentity * peer, void * source)
+{
+
+  struct PeerContainer * pc;
+  if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(peers, 
&peer->hashPubKey))
+  {
+    if (source == th)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         "%s disconnect notification for unknown peer `%s'\n",
+         "TRANSPORT", GNUNET_i2s (peer));
+      GNUNET_break (0);
+      return;
+    }
+    if (source == ch)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+         "%s disconnect notification for unknown peer `%s'\n",
+         "CORE", GNUNET_i2s (peer));
+      return;
+    }
+  }
+
+  pc = GNUNET_CONTAINER_multihashmap_get(peers, &peer->hashPubKey);
+  if (source == th)
+  {
+    if (GNUNET_YES == pc->transport_connected)
+    {
+      pc->transport_connected = GNUNET_NO;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+           "%s notified for not connected peer `%s' (%s : %s)\n",
+           "TRANSPORT",
+           GNUNET_i2s (&pc->id),
+           "CORE", (pc->core_connected == GNUNET_YES) ? "yes" : "no");
+      GNUNET_break (0);
+    }
+  }
+  if (source == ch)
+  {
+    if (GNUNET_YES == pc->core_connected)
+    {
+      pc->core_connected = GNUNET_NO;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+           "%s notified for not connected peer `%s' (%s : %s)\n",
+           "CORE",
+           GNUNET_i2s (&pc->id),
+           "TRANSPORT", (pc->transport_connected == GNUNET_YES) ? "yes" : 
"no");
+      GNUNET_break (0);
+    }
+  }
+
+  if ((GNUNET_NO == pc->core_connected) && (GNUNET_NO == 
pc->transport_connected))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Removing peer `%s'\n", GNUNET_i2s 
(&pc->id));
+    GNUNET_assert (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (peers, 
&peer->hashPubKey, pc));
+    GNUNET_free (pc);
+  }
+
+}
+
+
+static void
+cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  if (NULL != th)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting from transport 
service\n");
+    GNUNET_TRANSPORT_disconnect (th);
+    th = NULL;
+  }
+  if (NULL != ch)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Disconnecting from core service\n");
+    GNUNET_CORE_disconnect (ch);
+    ch = NULL;
+  }
+
+  map_check();
+
+  GNUNET_CONTAINER_multihashmap_iterate (peers, &map_cleanup_it, NULL);
+  GNUNET_CONTAINER_multihashmap_destroy(peers);
+}
+
+void
+transport_notify_connect_cb (void *cls,
+                const struct GNUNET_PeerIdentity
+                * peer,
+                const struct
+                GNUNET_ATS_Information * ats,
+                uint32_t ats_count)
+{
+  transport_connections ++;
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "TRANSPORT connect notification for peer 
`%s' (%u total)\n",
+      GNUNET_i2s (peer), transport_connections);
+  map_connect (peer, th);
+}
+
+/**
+ * Function called to notify transport users that another
+ * peer disconnected from us.
+ *
+ * @param cls closure
+ * @param peer the peer that disconnected
+ */
+void
+transport_notify_disconnect_cb (void *cls,
+                               const struct
+                               GNUNET_PeerIdentity * peer)
+{
+  GNUNET_assert (transport_connections > 0);
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "TRANSPORT disconnect notification for 
peer `%s' (%u total)\n",
+      GNUNET_i2s (peer), transport_connections) ;
+  map_disconnect (peer, th);
+  transport_connections --;
+
+}
+
+
+static void
+core_connect_cb (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_ATS_Information *atsi,
+                      unsigned int atsi_count)
+{
+  if (0 != memcmp (peer, &my_peer_id, sizeof (struct GNUNET_PeerIdentity)))
+  {
+    core_connections ++;
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE      connect notification for 
peer `%s' (%u total)\n",
+      GNUNET_i2s (peer), core_connections);
+    map_connect (peer, ch);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE      connect notification for 
myself `%s' (%u total)\n",
+      GNUNET_i2s (peer), core_connections);
+  }
+}
+
+static void
+core_disconnect_cb (void *cls,
+                      const struct
+                      GNUNET_PeerIdentity * peer)
+{
+  if (0 != memcmp (peer, &my_peer_id, sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_assert (core_connections >= 0);
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE      disconnect notification for 
peer `%s' (%u total)\n",
+      GNUNET_i2s (peer), core_connections);
+    map_disconnect (peer, ch);
+    core_connections --;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "CORE      disconnect notification for 
myself `%s' (%u total)\n",
+      GNUNET_i2s (peer), core_connections);
+  }
+
+}
+
+static void
+core_init_cb (void *cls, struct GNUNET_CORE_Handle *server,
+                   const struct GNUNET_PeerIdentity *my_identity)
+{
+  my_peer_id = *my_identity;
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connected to core service\n");
+}
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  transport_connections = 0;
+  core_connections = 0;
+
+  peers = GNUNET_CONTAINER_multihashmap_create (20);
+
+  th = GNUNET_TRANSPORT_connect(cfg, NULL, NULL, NULL,
+                                &transport_notify_connect_cb,
+                                &transport_notify_disconnect_cb);
+  GNUNET_assert (th != NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connected to transport service\n");
+  ch =  GNUNET_CORE_connect (cfg, 1, NULL,
+                             &core_init_cb,
+                             &core_connect_cb,
+                             &core_disconnect_cb,
+                             NULL, GNUNET_NO,
+                             NULL, GNUNET_NO,
+                             NULL);
+  GNUNET_assert (ch != NULL);
+
+  GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &cleanup_task, 
NULL);
+
+}
+
+
+/**
+ * The main function.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    /* FIMXE: add options here */
+    GNUNET_GETOPT_OPTION_END
+  };
+  return (GNUNET_OK ==
+          GNUNET_PROGRAM_run (argc, argv, "gnunet-template",
+                              gettext_noop ("help text"), options, &run,
+                              NULL)) ? ret : 1;
+}
+
+/* end of connection_watchdog.c */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]