gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r14485 - in gnunet/src: core dht fs hostlist include testin


From: gnunet
Subject: [GNUnet-SVN] r14485 - in gnunet/src: core dht fs hostlist include testing topology util
Date: Tue, 22 Feb 2011 16:19:49 +0100

Author: nevans
Date: 2011-02-22 16:19:49 +0100 (Tue, 22 Feb 2011)
New Revision: 14485

Modified:
   gnunet/src/core/core_api.c
   gnunet/src/core/core_api_iterate_peers.c
   gnunet/src/core/gnunet-service-core.c
   gnunet/src/dht/gnunet-dht-driver.c
   gnunet/src/dht/gnunet-service-dht.c
   gnunet/src/fs/fs_test_lib.c
   gnunet/src/hostlist/hostlist-client.c
   gnunet/src/include/gnunet_protocols.h
   gnunet/src/include/gnunet_testing_lib.h
   gnunet/src/include/gnunet_transport_service.h
   gnunet/src/testing/test_testing_topology.c
   gnunet/src/testing/testing.c
   gnunet/src/testing/testing_group.c
   gnunet/src/topology/gnunet-daemon-topology.c
   gnunet/src/util/client.c
Log:
Testing and core related changes.

Modified: gnunet/src/core/core_api.c
===================================================================
--- gnunet/src/core/core_api.c  2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/core/core_api.c  2011-02-22 15:19:49 UTC (rev 14485)
@@ -1733,8 +1733,12 @@
 
   if (NULL != GNUNET_CONTAINER_multihashmap_get (h->peers,
                                           &peer->hashPubKey))
-    return NULL; /* Already connected, means callback should have happened 
already! */
-
+    {
+#if DEBUG_CORE
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Peers are already connected!\n");
+#endif
+      return NULL;
+    }
   
   cm = GNUNET_malloc (sizeof (struct ControlMessage) + 
                      sizeof (struct ConnectMessage));

Modified: gnunet/src/core/core_api_iterate_peers.c
===================================================================
--- gnunet/src/core/core_api_iterate_peers.c    2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/core/core_api_iterate_peers.c    2011-02-22 15:19:49 UTC (rev 
14485)
@@ -153,9 +153,13 @@
 
   msg = (struct GNUNET_MessageHeader *)buf;
   msg->size = htons (msize);
-  msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
   if (peer != NULL)
-    memcpy(&msg[1], peer, sizeof(struct GNUNET_PeerIdentity));
+    {
+      msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED);
+      memcpy(&msg[1], peer, sizeof(struct GNUNET_PeerIdentity));
+    }
+  else
+    msg->type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS);
 
   return msize;
 }
@@ -198,7 +202,7 @@
                                                             GNUNET_YES,
                                                             &transmit_request,
                                                             peer);
-
+  GNUNET_assert(request_context->th != NULL);
   GNUNET_CLIENT_receive(client, &receive_info, request_context, 
GNUNET_TIME_relative_get_forever());
   return GNUNET_OK;
 }

Modified: gnunet/src/core/gnunet-service-core.c
===================================================================
--- gnunet/src/core/gnunet-service-core.c       2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/core/gnunet-service-core.c       2011-02-22 15:19:49 UTC (rev 
14485)
@@ -1498,7 +1498,6 @@
 {
   struct GNUNET_MessageHeader done_msg;
   struct GNUNET_SERVER_TransmitContext *tc;
-  struct GNUNET_PeerIdentity *peer;
   int msize;
   /* notify new client about existing neighbours */
 
@@ -1506,11 +1505,6 @@
   tc = GNUNET_SERVER_transmit_context_create (client);
   if (msize == sizeof(struct GNUNET_MessageHeader))
     GNUNET_CONTAINER_multihashmap_iterate (neighbours, &queue_connect_message, 
tc);
-  else if (msize == sizeof(struct GNUNET_MessageHeader) + sizeof(struct 
GNUNET_PeerIdentity))
-    {
-      peer = (struct GNUNET_PeerIdentity *)&message[1];
-      GNUNET_CONTAINER_multihashmap_get_multiple(neighbours, 
&peer->hashPubKey, &queue_connect_message, tc);
-    }
   else
     GNUNET_break(0);
 
@@ -1521,7 +1515,39 @@
                                       GNUNET_TIME_UNIT_FOREVER_REL);
 }
 
+/**
+ * Handle CORE_ITERATE_PEERS request.
+ *
+ * @param cls unused
+ * @param client client sending the iteration request
+ * @param message iteration request message
+ */
+static void
+handle_client_have_peer (void *cls,
+                             struct GNUNET_SERVER_Client *client,
+                             const struct GNUNET_MessageHeader *message)
 
+{
+  struct GNUNET_MessageHeader done_msg;
+  struct GNUNET_SERVER_TransmitContext *tc;
+  struct GNUNET_PeerIdentity *peer;
+  int msize;
+  /* notify new client about existing neighbours */
+
+  msize = ntohs(message->size);
+  tc = GNUNET_SERVER_transmit_context_create (client);
+
+  peer = (struct GNUNET_PeerIdentity *)&message[1];
+  GNUNET_CONTAINER_multihashmap_get_multiple(neighbours, &peer->hashPubKey, 
&queue_connect_message, tc);
+
+  done_msg.size = htons (sizeof (struct GNUNET_MessageHeader));
+  done_msg.type = htons (GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END);
+  GNUNET_SERVER_transmit_context_append_message (tc, &done_msg);
+  GNUNET_SERVER_transmit_context_run (tc,
+                                      GNUNET_TIME_UNIT_FOREVER_REL);
+}
+
+
 /**
  * Handle REQUEST_INFO request.
  */
@@ -2973,10 +2999,6 @@
   if ( (GNUNET_YES == n->is_connected) ||
        (n->th != NULL) )
     {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Core received `%s' request for `%4s', already connected!\n",
-                 "REQUEST_CONNECT",
-                 GNUNET_i2s (&cm->peer));
       if (GNUNET_YES == n->is_connected) 
        GNUNET_STATISTICS_update (stats, 
                                  gettext_noop ("# connection requests ignored 
(already connected)"), 
@@ -3004,10 +3026,12 @@
                            1,
                            GNUNET_NO);
 
+#if DEBUG_CORE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Core received `%s' request for `%4s', will try to establish 
connection\n",
              "REQUEST_CONNECT",
              GNUNET_i2s (&cm->peer));
+#endif
 
   /* ask transport to connect to the peer */
   n->th = GNUNET_TRANSPORT_notify_transmit_ready (transport,
@@ -4662,6 +4686,9 @@
     {&handle_client_iterate_peers, NULL,
      GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS,
      sizeof (struct GNUNET_MessageHeader)},
+    {&handle_client_have_peer, NULL,
+     GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED,
+     sizeof (struct GNUNET_MessageHeader) + sizeof(struct 
GNUNET_PeerIdentity)},
     {&handle_client_request_info, NULL,
      GNUNET_MESSAGE_TYPE_CORE_REQUEST_INFO,
      sizeof (struct RequestInfoMessage)},

Modified: gnunet/src/dht/gnunet-dht-driver.c
===================================================================
--- gnunet/src/dht/gnunet-dht-driver.c  2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/dht/gnunet-dht-driver.c  2011-02-22 15:19:49 UTC (rev 14485)
@@ -34,9 +34,10 @@
 #include "gnunet_dht_service.h"
 #include "dhtlog.h"
 #include "dht.h"
+#include "gauger.h"
 
 /* Specific DEBUG hack, do not use normally (may leak memory, segfault, or eat 
children.) */
-#define ONLY_TESTING GNUNET_YES
+#define ONLY_TESTING GNUNET_NO
 
 /* DEFINES */
 #define VERBOSE GNUNET_NO
@@ -688,6 +689,16 @@
 static unsigned long long gets_completed;
 
 /**
+ * Total number of items to attempt to get.
+ */
+static unsigned long long cumulative_num_gets;
+
+/**
+ * How many gets are done?
+ */
+static unsigned long long cumulative_successful_gets;
+
+/**
  * How many gets failed?
  */
 static unsigned long long gets_failed;
@@ -1354,7 +1365,7 @@
         {
           timeout = 
GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime);
         }
-      GNUNET_TESTING_daemons_connect(d1, d2, timeout, 
DEFAULT_RECONNECT_ATTEMPTS, NULL, NULL);
+      GNUNET_TESTING_daemons_connect(d1, d2, timeout, 
DEFAULT_RECONNECT_ATTEMPTS, GNUNET_YES, NULL, NULL);
     }
   if (GNUNET_TIME_absolute_get_remaining(find_peer_context->endtime).rel_value 
> 0)
     return GNUNET_YES;
@@ -1793,6 +1804,9 @@
 
   if (tc->reason == GNUNET_SCHEDULER_REASON_TIMEOUT)
     gets_failed++;
+  else
+    cumulative_successful_gets++;
+
   GNUNET_assert(test_get->get_handle != NULL);
   GNUNET_DHT_get_stop(test_get->get_handle);
   test_get->get_handle = NULL;
@@ -1889,6 +1903,7 @@
   GNUNET_assert(test_get->dht_handle != NULL);
   outstanding_gets++;
 
+  cumulative_num_gets++;
   /* Insert the data at the first peer */
   test_get->get_handle = GNUNET_DHT_get_start(test_get->dht_handle,
                                               get_delay,
@@ -2617,7 +2632,11 @@
           (second_daemon == repeat_connect_peer2))
         {
           if (emsg != NULL) /* Peers failed to connect again! */
-            return;
+            {
+              GNUNET_assert(repeat_connect_task == GNUNET_SCHEDULER_NO_TASK);
+              repeat_connect_task = 
GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
 60), &repeat_connect, NULL);
+              return;
+            }
           else /* Repeat peers actually connected! */
             {
               if (repeat_connect_task != GNUNET_SCHEDULER_NO_TASK)
@@ -2676,12 +2695,6 @@
         }
 #endif
     }
-#if ONLY_TESTING
-  else if (repeat_connect_mode == GNUNET_YES)
-    {
-      repeat_connect_task = 
GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS,
 60), &repeat_connect, NULL);
-    }
-#endif
 
   if (emsg == NULL)
     {
@@ -2708,7 +2721,7 @@
     }
 
 #if ONLY_TESTING
-  if (repeat_connect_mode == GNUNET_YES)
+  if ((repeat_connect_mode == GNUNET_YES) )
     return;
 #endif
 
@@ -2728,6 +2741,27 @@
           dhtlog_handle->insert_topology(expected_connections);
         }
 
+
+      total_duration = GNUNET_TIME_absolute_get_difference (connect_start_time,
+                                                            
GNUNET_TIME_absolute_get()).rel_value / 1000;
+      failed_conns_per_sec_total = (double)failed_connections / total_duration;
+      conns_per_sec_total = (double)total_connections / total_duration;
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Overall connection info --- 
Total: %u, Total Failed %u/s\n",
+                 total_connections, failed_connections);
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Overall connection info --- 
Total: %.2f/s, Total Failed %.2f/s\n",
+                 conns_per_sec_total, failed_conns_per_sec_total);
+      /** Comment out until gauger is ready */
+      /**
+      GNUNET_asprintf(&temp_conn_string, "dht_peer_connection_speed");
+      GNUNET_asprintf(&temp_failed_conn_string, 
"dht_peer_failed_connection_speed");
+
+      GAUGER_COUNTER(temp_conn_string, conns_per_sec_total, trial_to_run, 
DATE);
+      GAUGER_COUNTER(temp_failed_conn_string, failed_conns_per_sec_total, 
trial_to_run, DATE);
+
+      GNUNET_free(temp_conn_string);
+      GNUNET_free(temp_failed_conn_string);
+      */
+
       GNUNET_SCHEDULER_cancel (die_task);
 
       if ((GNUNET_YES == dhtlog_minimal) && (NULL != dhtlog_handle))

Modified: gnunet/src/dht/gnunet-service-dht.c
===================================================================
--- gnunet/src/dht/gnunet-service-dht.c 2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/dht/gnunet-service-dht.c 2011-02-22 15:19:49 UTC (rev 14485)
@@ -2181,7 +2181,7 @@
           if (GNUNET_YES == consider_peer (&new_peer))
             {
               increment_stats (STAT_HELLOS_PROVIDED);
-              GNUNET_TRANSPORT_offer_hello (transport_handle, hello_msg);
+              GNUNET_TRANSPORT_offer_hello (transport_handle, hello_msg, NULL, 
NULL);
               GNUNET_CORE_peer_request_connect (coreAPI,
                                                 GNUNET_TIME_relative_multiply
                                                 (GNUNET_TIME_UNIT_SECONDS, 5),
@@ -2701,7 +2701,7 @@
       if (GNUNET_YES == consider_peer (&peer_id))
         {
           increment_stats (STAT_HELLOS_PROVIDED);
-          GNUNET_TRANSPORT_offer_hello (transport_handle, other_hello);
+          GNUNET_TRANSPORT_offer_hello (transport_handle, other_hello, NULL, 
NULL);
           GNUNET_CORE_peer_request_connect (coreAPI,
                                             GNUNET_TIME_relative_multiply
                                             (GNUNET_TIME_UNIT_SECONDS, 5),

Modified: gnunet/src/fs/fs_test_lib.c
===================================================================
--- gnunet/src/fs/fs_test_lib.c 2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/fs/fs_test_lib.c 2011-02-22 15:19:49 UTC (rev 14485)
@@ -482,6 +482,7 @@
                                  daemon2->daemon,
                                  timeout,
                                  CONNECT_ATTEMPTS,
+                                 GNUNET_YES,
                                  &notify_connection,
                                  ncc);
 }

Modified: gnunet/src/hostlist/hostlist-client.c
===================================================================
--- gnunet/src/hostlist/hostlist-client.c       2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/hostlist/hostlist-client.c       2011-02-22 15:19:49 UTC (rev 
14485)
@@ -335,7 +335,7 @@
                                    1, 
                                    GNUNET_NO);
          stat_hellos_obtained++;
-         GNUNET_TRANSPORT_offer_hello (transport, msg);
+         GNUNET_TRANSPORT_offer_hello (transport, msg, NULL, NULL);
        }
       else
        {

Modified: gnunet/src/include/gnunet_protocols.h
===================================================================
--- gnunet/src/include/gnunet_protocols.h       2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/include/gnunet_protocols.h       2011-02-22 15:19:49 UTC (rev 
14485)
@@ -388,29 +388,34 @@
 #define GNUNET_MESSAGE_TYPE_CORE_ITERATE_PEERS_END 79
 
 /**
+ * Check whether a given peer is currently connected to CORE.
+ */
+#define GNUNET_MESSAGE_TYPE_CORE_PEER_CONNECTED 80
+
+/**
  * Session key exchange between peers.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_SET_KEY 80
+#define GNUNET_MESSAGE_TYPE_CORE_SET_KEY 81
 
 /**
  * Encapsulation for an encrypted message between peers.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE 81
+#define GNUNET_MESSAGE_TYPE_CORE_ENCRYPTED_MESSAGE 82
 
 /**
  * Check that other peer is alive (challenge).
  */
-#define GNUNET_MESSAGE_TYPE_CORE_PING 82
+#define GNUNET_MESSAGE_TYPE_CORE_PING 83
 
 /**
  * Confirmation that other peer is alive.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_PONG 83
+#define GNUNET_MESSAGE_TYPE_CORE_PONG 84
 
 /**
  * Request by the other peer to terminate the connection.
  */
-#define GNUNET_MESSAGE_TYPE_CORE_HANGUP 84
+#define GNUNET_MESSAGE_TYPE_CORE_HANGUP 85
 
 /**
  * Message sent by datastore client on join.

Modified: gnunet/src/include/gnunet_testing_lib.h
===================================================================
--- gnunet/src/include/gnunet_testing_lib.h     2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/include/gnunet_testing_lib.h     2011-02-22 15:19:49 UTC (rev 
14485)
@@ -158,6 +158,11 @@
   SP_START_CORE,
 
   /**
+   * CORE is up, now make sure we get the HELLO for this peer.
+   */
+  SP_GET_HELLO,
+
+  /**
    * Core has notified us that we've established a connection to the service.
    * The main FSM halts here and waits to be moved to UPDATE or CLEANUP.
    */
@@ -545,15 +550,19 @@
  *        allowed to take?
  * @param max_connect_attempts how many times should we try to reconnect
  *        (within timeout)
+ * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
+ *                   the HELLO has already been exchanged
  * @param cb function to call at the end
  * @param cb_cls closure for cb
  */
-void GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
-                                    struct GNUNET_TESTING_Daemon *d2,
-                                    struct GNUNET_TIME_Relative timeout,
-                                    unsigned int max_connect_attempts,
-                                    GNUNET_TESTING_NotifyConnection cb,
-                                    void *cb_cls);
+void
+GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
+                                struct GNUNET_TESTING_Daemon *d2,
+                                struct GNUNET_TIME_Relative timeout,
+                                unsigned int max_connect_attempts,
+                                int send_hello,
+                                GNUNET_TESTING_NotifyConnection cb,
+                                void *cb_cls);
 
 
 

Modified: gnunet/src/include/gnunet_transport_service.h
===================================================================
--- gnunet/src/include/gnunet_transport_service.h       2011-02-22 08:25:03 UTC 
(rev 14484)
+++ gnunet/src/include/gnunet_transport_service.h       2011-02-22 15:19:49 UTC 
(rev 14485)
@@ -603,15 +603,19 @@
 /**
  * Offer the transport service the HELLO of another peer.  Note that
  * the transport service may just ignore this message if the HELLO is
- * malformed or useless due to our local configuration.  If the HELLO
- * is working, we should add it to PEERINFO.
+ * malformed or useless due to our local configuration.
  *
  * @param handle connection to transport service
  * @param hello the hello message
+ * @param cont continuation to call when HELLO has been sent
+ * @param cls closure for continuation
+ *
  */
 void
 GNUNET_TRANSPORT_offer_hello (struct GNUNET_TRANSPORT_Handle *handle,
-                              const struct GNUNET_MessageHeader *hello);
+                              const struct GNUNET_MessageHeader *hello,
+                              GNUNET_SCHEDULER_Task cont,
+                              void *cls);
 
 
 /**

Modified: gnunet/src/testing/test_testing_topology.c
===================================================================
--- gnunet/src/testing/test_testing_topology.c  2011-02-22 08:25:03 UTC (rev 
14484)
+++ gnunet/src/testing/test_testing_topology.c  2011-02-22 15:19:49 UTC (rev 
14485)
@@ -1027,6 +1027,7 @@
   char *connect_topology_option_str;
   char *connect_topology_option_modifier_string;
   unsigned long long temp_settle;
+  unsigned long long max_outstanding_connections;
   ok = 1;
 
   dotOutFile = fopen (dotOutFileName, "w");
@@ -1152,6 +1153,14 @@
       return;
     }
 
+  if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_number (cfg, "testing", 
"max_outstanding_connections",
+                                               &max_outstanding_connections))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n", 
"testing", "max_outstanding_connections");
+      return;
+    }
+
   if (GNUNET_SYSERR ==
       GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
                                              &num_peers))
@@ -1180,7 +1189,7 @@
   GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
   pg = GNUNET_TESTING_daemons_start (cfg,
                                      peers_left,
-                                     peers_left / 2,
+                                     max_outstanding_connections,
                                      peers_left,
                                      GNUNET_TIME_relative_multiply
                                      (GNUNET_TIME_UNIT_SECONDS,

Modified: gnunet/src/testing/testing.c
===================================================================
--- gnunet/src/testing/testing.c        2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/testing/testing.c        2011-02-22 15:19:49 UTC (rev 14485)
@@ -38,7 +38,7 @@
 #include "gnunet_hello_lib.h"
 
 #define DEBUG_TESTING GNUNET_NO
-#define DEBUG_TESTING_RECONNECT GNUNET_NO
+#define DEBUG_TESTING_RECONNECT GNUNET_YES
 
 /**
  * How long do we wait after starting gnunet-service-arm
@@ -65,10 +65,19 @@
 process_hello (void *cls, const struct GNUNET_MessageHeader *message)
 {
   struct GNUNET_TESTING_Daemon *daemon = cls;
+  GNUNET_TESTING_NotifyDaemonRunning cb;
+
   int msize;
   if (daemon == NULL)
     return;
 
+  GNUNET_assert (daemon->phase == SP_GET_HELLO);
+
+  cb = daemon->cb;
+  daemon->cb = NULL;
+  if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */
+    GNUNET_SCHEDULER_cancel(daemon->task);
+
   if (daemon->server != NULL)
     {
 #if DEBUG_TESTING
@@ -105,9 +114,15 @@
       GNUNET_TRANSPORT_disconnect (daemon->th);
       daemon->th = NULL;
     }
+  daemon->phase = SP_START_DONE;
 
+  if (NULL != cb) /* FIXME: what happens when this callback calls 
GNUNET_TESTING_daemon_stop? */
+    cb (daemon->cb_cls, &daemon->id, daemon->cfg, daemon, NULL);
 }
 
+static void
+start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
 /**
  * Function called after GNUNET_CORE_connect has succeeded
  * (or failed for good).  Note that the private key of the
@@ -127,12 +142,10 @@
               const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
 {
   struct GNUNET_TESTING_Daemon *d = cls;
-  GNUNET_TESTING_NotifyDaemonRunning cb;
 
   GNUNET_assert (d->phase == SP_START_CORE);
-  d->phase = SP_START_DONE;
-  cb = d->cb;
-  d->cb = NULL;
+  d->phase = SP_GET_HELLO;
+
   if (server == NULL)
     {
       d->server = NULL;
@@ -141,8 +154,8 @@
                                     GNUNET_TIME_absolute_get_remaining
                                     (d->max_timeout), d->dead_cb,
                                     d->dead_cb_cls, GNUNET_YES, GNUNET_NO);
-      else if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d,
+      else if (NULL != d->cb)
+        d->cb (d->cb_cls, NULL, d->cfg, d,
             _("Failed to connect to core service\n"));
       return;
     }
@@ -155,9 +168,6 @@
   d->server = server;
   d->running = GNUNET_YES;
 
-  if (NULL != cb)               /* FIXME: what happens when this callback 
calls GNUNET_TESTING_daemon_stop? */
-    cb (d->cb_cls, my_identity, d->cfg, d, NULL);
-
   if (GNUNET_NO == d->running)
     {
 #if DEBUG_TESTING
@@ -192,6 +202,12 @@
 #endif
 
   GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
+  /* wait some more */
+  if (d->task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel(d->task);
+  d->task
+    = GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT,
+                                    &start_fsm, d);
 }
 
 
@@ -551,7 +567,12 @@
                     (NULL == d->hostname)
                     ? _("`gnunet-arm' does not seem to terminate.\n")
                     : _("`ssh' does not seem to terminate.\n"));
+              GNUNET_CONFIGURATION_destroy (d->cfg);
+              GNUNET_free (d->cfgfile);
+              GNUNET_free_non_null (d->hostname);
+              GNUNET_free_non_null (d->username);
               GNUNET_free(d->proc);
+              GNUNET_free(d);
               return;
             }
           /* wait some more */
@@ -570,18 +591,68 @@
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Calling CORE_connect\n");
 #endif
+      /* Fall through */
+    case SP_START_CORE:
+      if (d->server != NULL)
+        GNUNET_CORE_disconnect(d->server);
+
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value ==
+          0)
+        {
+          cb = d->cb;
+          d->cb = NULL;
+          if (NULL != cb)
+            cb (d->cb_cls,
+                NULL,
+                d->cfg,
+                d,
+                _("Unable to connect to CORE service for peer!\n"));
+          GNUNET_CONFIGURATION_destroy (d->cfg);
+          GNUNET_free (d->cfgfile);
+          GNUNET_free_non_null (d->hostname);
+          GNUNET_free_non_null (d->username);
+          GNUNET_free (d);
+          return;
+        }
       d->server = GNUNET_CORE_connect (d->cfg, 1,
-#if NO_MORE_TIMEOUT_FIXME
-                                       ARM_START_WAIT,
-#endif
                                        d,
                                        &testing_init,
                                        NULL, NULL, NULL,
                                        NULL, GNUNET_NO,
                                        NULL, GNUNET_NO, no_handlers);
+      d->task
+        = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_relative_multiply(GNUNET_CONSTANTS_SERVICE_RETRY, 2),
+                                        &start_fsm, d);
       break;
-    case SP_START_CORE:
-      GNUNET_break (0);
+    case SP_GET_HELLO:
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value ==
+          0)
+        {
+          if (d->server != NULL)
+            GNUNET_CORE_disconnect(d->server);
+          if (d->th != NULL)
+            GNUNET_TRANSPORT_disconnect(d->th);
+          cb = d->cb;
+          d->cb = NULL;
+          if (NULL != cb)
+            cb (d->cb_cls,
+                NULL,
+                d->cfg,
+                d,
+                _("Unable to get HELLO for peer!\n"));
+          GNUNET_CONFIGURATION_destroy (d->cfg);
+          GNUNET_free (d->cfgfile);
+          GNUNET_free_non_null (d->hostname);
+          GNUNET_free_non_null (d->username);
+          GNUNET_free (d);
+          return;
+        }
+      if (d->hello != NULL)
+        return;
+      GNUNET_assert(d->task == GNUNET_SCHEDULER_NO_TASK);
+      d->task
+        = GNUNET_SCHEDULER_add_delayed 
(GNUNET_TIME_relative_multiply(GNUNET_CONSTANTS_SERVICE_RETRY, 2),
+                                        &start_fsm, d);
       break;
     case SP_START_DONE:
       GNUNET_break (0);
@@ -1368,12 +1439,6 @@
   void *cb_cls;
 
   /**
-   * When should this operation be complete (or we must trigger
-   * a timeout).
-   */
-  struct GNUNET_TIME_Absolute timeout;
-
-  /**
    * The relative timeout from whence this connect attempt was
    * started.  Allows for reconnect attempts.
    */
@@ -1383,7 +1448,7 @@
    * Maximum number of connect attempts, will retry connection
    * this number of times on failures.
    */
-  unsigned int max_connect_attempts;
+  unsigned int connect_attempts;
 
   /**
    * Hello timeout task
@@ -1407,6 +1472,11 @@
   int connected;
 
   /**
+   * When connecting, do we need to send the HELLO?
+   */
+  int send_hello;
+
+  /**
    * The distance between the two connected peers
    */
   uint32_t distance;
@@ -1431,8 +1501,6 @@
                        const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct ConnectContext *ctx = cls;
-  struct GNUNET_TIME_Relative remaining;
-
   ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
     {
@@ -1445,6 +1513,7 @@
       GNUNET_CORE_peer_request_connect_cancel (ctx->connect_request_handle);
       ctx->connect_request_handle = NULL;
     }
+
   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
     {
       if (ctx->d1th != NULL)
@@ -1458,12 +1527,16 @@
       ctx->d2core = NULL;
 #endif
       ctx->d1core = NULL;
-
       GNUNET_free (ctx);
       return;
     }
 
-  remaining = GNUNET_TIME_absolute_get_remaining (ctx->timeout);
+  if (ctx->d1th != NULL)
+    GNUNET_TRANSPORT_disconnect (ctx->d1th);
+  ctx->d1th = NULL;
+  if (ctx->d1core != NULL)
+    GNUNET_CORE_disconnect (ctx->d1core);
+  ctx->d1core = NULL;
 
   if (ctx->connected == GNUNET_YES)
     {
@@ -1476,13 +1549,8 @@
                    ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
         }
     }
-  else if (remaining.rel_value > 0)
+  else if (ctx->connect_attempts > 0)
     {
-      if (ctx->d1core != NULL)
-        {
-          GNUNET_CORE_disconnect (ctx->d1core);
-          ctx->d1core = NULL;
-        }
       ctx->d1core_ready = GNUNET_NO;
 #if CONNECT_CORE2
       if (ctx->d2core != NULL)
@@ -1491,12 +1559,6 @@
           ctx->d2core = NULL;
         }
 #endif
-
-      if (ctx->d1th != NULL)
-        {
-          GNUNET_TRANSPORT_disconnect (ctx->d1th);
-          ctx->d1th = NULL;
-        }
       GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx);
       return;
     }
@@ -1510,12 +1572,6 @@
         }
     }
 
-  if (ctx->d1th != NULL)
-    GNUNET_TRANSPORT_disconnect (ctx->d1th);
-  ctx->d1th = NULL;
-  if (ctx->d1core != NULL)
-    GNUNET_CORE_disconnect (ctx->d1core);
-  ctx->d1core = NULL;
   GNUNET_free (ctx);
 }
 
@@ -1535,8 +1591,15 @@
 {
   struct ConnectContext *ctx = cls;
 
+#if DEBUG_TESTING
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Connected peer %s to peer %s\n",
+                ctx->d1->shortname, GNUNET_i2s(peer));
+#endif
+
   if (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))
     {
+
       ctx->connected = GNUNET_YES;
       ctx->distance = 0;        /* FIXME: distance */
       if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
@@ -1606,17 +1669,16 @@
     {
       hello = GNUNET_HELLO_get_header (ctx->d2->hello);
       GNUNET_assert (hello != NULL);
-      GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello);
+      GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL);
       GNUNET_assert (ctx->d1core != NULL);
       ctx->connect_request_handle =
         GNUNET_CORE_peer_request_connect (ctx->d1core,
-                                          GNUNET_TIME_relative_divide
-                                          (ctx->relative_timeout,
-                                           ctx->max_connect_attempts + 1),
-                                           &ctx->d2->id,
-                                           &core_connect_request_cont, ctx);
+                                          ctx->relative_timeout,
+                                          &ctx->d2->id,
+                                          &core_connect_request_cont, ctx);
+
 #if DEBUG_TESTING
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "Sending connect request to CORE of %s for peer %s\n",
                   GNUNET_i2s (&ctx->d1->id),
                   GNUNET_h2s (&ctx->d2->id.hashPubKey));
@@ -1649,8 +1711,90 @@
 {
   struct ConnectContext *connect_ctx = cls;
   connect_ctx->d1core_ready = GNUNET_YES;
+
+  if (connect_ctx->send_hello == GNUNET_NO)
+    {
+      connect_ctx->connect_request_handle =
+          GNUNET_CORE_peer_request_connect (connect_ctx->d1core,
+                                            connect_ctx->relative_timeout,
+                                            &connect_ctx->d2->id,
+                                            &core_connect_request_cont, 
connect_ctx);
+      GNUNET_assert(connect_ctx->connect_request_handle != NULL);
+#if DEBUG_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Sending connect request to CORE of %s for peer %s\n",
+                  connect_ctx->d1->shortname,
+                  connect_ctx->d2->shortname);
+#endif
+    }
+
 }
 
+
+static void
+reattempt_daemons_connect (void *cls,
+                           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct ConnectContext *ctx = cls;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    {
+      GNUNET_free(ctx);
+      return;
+    }
+#if DEBUG_TESTING_RECONNECT
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "re-attempting connect of peer %s to peer %s\n",
+              ctx->d1->shortname, ctx->d2->shortname);
+#endif
+  ctx->connect_attempts--;
+  GNUNET_assert (ctx->d1core == NULL);
+  ctx->d1core_ready = GNUNET_NO;
+  ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
+                                     ctx,
+                                     &core_init_notify,
+                                     &connect_notify, NULL, NULL,
+                                     NULL, GNUNET_NO,
+                                     NULL, GNUNET_NO, no_handlers);
+  if (ctx->d1core == NULL)
+    {
+      if (NULL != ctx->cb)
+        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+                 ctx->d2->cfg, ctx->d1, ctx->d2,
+                 _("Failed to connect to core service of first peer!\n"));
+      GNUNET_free (ctx);
+      return;
+    }
+
+  if (ctx->send_hello == GNUNET_YES)
+    {
+      ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
+                                            &ctx->d1->id,
+                                            ctx->d1, NULL, NULL, NULL);
+      if (ctx->d1th == NULL)
+        {
+          GNUNET_CORE_disconnect (ctx->d1core);
+          GNUNET_free (ctx);
+          if (NULL != ctx->cb)
+            ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+                     ctx->d2->cfg, ctx->d1, ctx->d2,
+                     _("Failed to connect to transport service!\n"));
+          return;
+        }
+      ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+    }
+  else
+    {
+      ctx->connect_request_handle =
+        GNUNET_CORE_peer_request_connect (ctx->d1core,
+                                          ctx->relative_timeout,
+                                          &ctx->d2->id,
+                                          &core_connect_request_cont, ctx);
+    }
+  ctx->timeout_task =
+    GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+                                  &notify_connect_result, ctx);
+}
+
 /**
  * Iterator for currently known peers, to ensure
  * that we don't try to send duplicate connect
@@ -1676,7 +1820,7 @@
       ctx->distance = 0;        /* FIXME: distance */
       return;
     }
-  else if (peer == NULL) /* Peer not already connected, need to schedule 
connect request! */
+  else if (peer == NULL) /* End of iteration over peers */
     {
       if (ctx->connected == GNUNET_YES)
         {
@@ -1685,14 +1829,23 @@
           return;
         }
 
-      ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
-                                         ctx,
-                                         &core_init_notify,
-                                         &connect_notify, NULL, NULL,
-                                         NULL, GNUNET_NO,
-                                         NULL, GNUNET_NO, no_handlers);
+      /* Peer not already connected, need to schedule connect request! */
       if (ctx->d1core == NULL)
         {
+#if DEBUG_TESTING
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Peers are NOT connected, connecting to core!\n");
+#endif
+          ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
+                                             ctx,
+                                             &core_init_notify,
+                                             &connect_notify, NULL, NULL,
+                                             NULL, GNUNET_NO,
+                                             NULL, GNUNET_NO, no_handlers);
+        }
+
+      if (ctx->d1core == NULL)
+        {
           GNUNET_free (ctx);
           if (NULL != ctx->cb)
             ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, 
ctx->d2->cfg, ctx->d1, ctx->d2,
@@ -1700,34 +1853,25 @@
           return;
         }
 
-#if DEBUG_TESTING > 2
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Asked to connect peer %s to peer %s\n",
-              ctx->d1->shortname, ctx->d2->shortname);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting to transport service of peer %s\n", 
ctx->d2->shortname);
-
-#endif
-
-      ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
-                                            &ctx->d1->id, ctx->d1, NULL, NULL, 
NULL);
-      if (ctx->d1th == NULL)
+      if (ctx->send_hello == GNUNET_YES)
         {
-          GNUNET_CORE_disconnect (ctx->d1core);
-          GNUNET_free (ctx);
-          if (NULL != ctx->cb)
-            ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg, 
ctx->d2->cfg, ctx->d1, ctx->d2,
-                _("Failed to connect to transport service!\n"));
-          return;
+          ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
+                                                &ctx->d1->id, ctx->d1, NULL, 
NULL, NULL);
+          if (ctx->d1th == NULL)
+            {
+              GNUNET_CORE_disconnect (ctx->d1core);
+              GNUNET_free (ctx);
+              if (NULL != ctx->cb)
+                ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, 
ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2,
+                    _("Failed to connect to transport service!\n"));
+              return;
+            }
+          ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
         }
 
       ctx->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
-                                      (ctx->relative_timeout,
-                                       ctx->max_connect_attempts),
-                                       &notify_connect_result, ctx);
-
-      ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+        GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+                                      &notify_connect_result, ctx);
     }
 }
 
@@ -1741,6 +1885,8 @@
  *        allowed to take?
  * @param max_connect_attempts how many times should we try to reconnect
  *        (within timeout)
+ * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
+ *                   the HELLO has already been exchanged
  * @param cb function to call at the end
  * @param cb_cls closure for cb
  */
@@ -1749,6 +1895,7 @@
                                 struct GNUNET_TESTING_Daemon *d2,
                                 struct GNUNET_TIME_Relative timeout,
                                 unsigned int max_connect_attempts,
+                                int send_hello,
                                 GNUNET_TESTING_NotifyConnection cb,
                                 void *cb_cls)
 {
@@ -1761,17 +1908,18 @@
             _("Peers are not fully running yet, can not connect!\n"));
       return;
     }
+
   ctx = GNUNET_malloc (sizeof (struct ConnectContext));
   ctx->d1 = d1;
   ctx->d2 = d2;
-  ctx->timeout = GNUNET_TIME_relative_to_absolute (timeout);
   ctx->timeout_hello =
     GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
-  ctx->relative_timeout = timeout;
+  ctx->relative_timeout = GNUNET_TIME_relative_divide(timeout, 
max_connect_attempts);
   ctx->cb = cb;
   ctx->cb_cls = cb_cls;
-  ctx->max_connect_attempts = max_connect_attempts;
+  ctx->connect_attempts = max_connect_attempts;
   ctx->connected = GNUNET_NO;
+  ctx->send_hello = send_hello;
 #if DEBUG_TESTING
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Asked to connect peer %s to peer %s\n",
@@ -1779,66 +1927,8 @@
 #endif
 
   /* Core is up! Iterate over all _known_ peers first to check if we are 
already connected to the peer! */
-  GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id, 
&core_initial_iteration, ctx);
-  /* GNUNET_CORE_iterate_peers(ctx->d1->cfg, &core_initial_iteration, ctx); */
-
+  GNUNET_assert(GNUNET_OK == GNUNET_CORE_is_peer_connected (ctx->d1->cfg, 
&ctx->d2->id, &core_initial_iteration, ctx));
+  /*GNUNET_assert(GNUNET_OK == GNUNET_CORE_iterate_peers (ctx->d1->cfg, 
&core_initial_iteration, ctx));*/
 }
 
-static void
-reattempt_daemons_connect (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-
-  struct ConnectContext *ctx = cls;
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
-    {
-      return;
-    }
-#if DEBUG_TESTING_RECONNECT
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "re-attempting connect of peer %s to peer %s\n",
-              ctx->d1->shortname, ctx->d2->shortname);
-#endif
-
-  GNUNET_assert (ctx->d1core == NULL);
-  ctx->d1core_ready = GNUNET_NO;
-  ctx->d1core = GNUNET_CORE_connect (ctx->d1->cfg, 1,
-                                     ctx,
-                                     &core_init_notify,
-                                     &connect_notify, NULL, NULL,
-                                     NULL, GNUNET_NO,
-                                     NULL, GNUNET_NO, no_handlers);
-  if (ctx->d1core == NULL)
-    {
-      if (NULL != ctx->cb)
-        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-                 ctx->d2->cfg, ctx->d1, ctx->d2,
-                 _("Failed to connect to core service of first peer!\n"));
-      GNUNET_free (ctx);
-      return;
-    }
-
-  ctx->d1th = GNUNET_TRANSPORT_connect (ctx->d1->cfg,
-                                        &ctx->d1->id,
-                                        ctx->d1, NULL, NULL, NULL);
-  if (ctx->d1th == NULL)
-    {
-      GNUNET_CORE_disconnect (ctx->d1core);
-      GNUNET_free (ctx);
-      if (NULL != ctx->cb)
-        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-                 ctx->d2->cfg, ctx->d1, ctx->d2,
-                 _("Failed to connect to transport service!\n"));
-      return;
-    }
-
-  ctx->timeout_task =
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
-                                  (ctx->relative_timeout,
-                                   ctx->max_connect_attempts),
-                                  &notify_connect_result, ctx);
-
-  ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
-}
-
 /* end of testing.c */

Modified: gnunet/src/testing/testing_group.c
===================================================================
--- gnunet/src/testing/testing_group.c  2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/testing/testing_group.c  2011-02-22 15:19:49 UTC (rev 14485)
@@ -30,7 +30,7 @@
 #include "gnunet_testing_lib.h"
 #include "gnunet_core_service.h"
 
-#define VERBOSE_TESTING GNUNET_YES
+#define VERBOSE_TESTING GNUNET_NO
 
 #define VERBOSE_TOPOLOGY GNUNET_YES
 
@@ -38,6 +38,8 @@
 
 #define OLD 1
 
+#define USE_SEND_HELLOS GNUNET_NO
+
 /**
  * Lowest port used for GNUnet testing.  Should be high enough to not
  * conflict with other applications running on the hosts but be low
@@ -159,6 +161,40 @@
 };
 
 
+struct SendHelloContext
+{
+  /**
+   * Global handle to the peer group.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * The data about this specific peer.
+   */
+  struct PeerData *peer;
+
+  /**
+   * The next HELLO that needs sent to this peer.
+   */
+  struct PeerConnection *peer_pos;
+
+  /**
+   * Are we connected to CORE yet?
+   */
+  unsigned int core_ready;
+
+  /**
+   * How many attempts should we make for failed connections?
+   */
+  unsigned int connect_attempts;
+
+  /**
+   * Task for scheduling core connect requests to be sent.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier core_connect_task;
+};
+
+
 struct ShutdownContext
 {
   struct GNUNET_TESTING_PeerGroup *pg;
@@ -599,6 +635,46 @@
   struct GNUNET_STATISTICS_GetHandle *stats_get_handle;
 };
 
+
+struct ConnectTopologyContext
+{
+  /**
+   * How many connections are left to create.
+   */
+  unsigned int remaining_connections;
+
+  /**
+   * Handle to group of peers.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * How long to try this connection before timing out.
+   */
+  struct GNUNET_TIME_Relative connect_timeout;
+
+  /**
+   * How many times to retry connecting the two peers.
+   */
+  unsigned int connect_attempts;
+
+  /**
+   * Temp value set for each iteration.
+   */
+  //struct PeerData *first;
+
+  /**
+   * Notification that all peers are connected.
+   */
+  GNUNET_TESTING_NotifyCompletion notify_connections_done;
+
+  /**
+   * Closure for notify.
+   */
+  void *notify_cls;
+};
+
+
 /**
  * Handle to a group of GNUnet peers.
  */
@@ -682,6 +758,11 @@
   unsigned int outstanding_connects;
 
   /**
+   * Number of HELLOs we have yet to send.
+   */
+  unsigned int remaining_hellos;
+
+  /**
    * How many connects have already been scheduled?
    */
   unsigned int total_connects_scheduled;
@@ -707,72 +788,59 @@
    * Stop scheduling peers connecting.
    */
   unsigned int stop_connects;
+
+  /**
+   * Connection context for peer group.
+   */
+  struct ConnectTopologyContext ct_ctx;
 };
 
 struct UpdateContext
 {
-  struct GNUNET_CONFIGURATION_Handle *ret;
-  const struct GNUNET_CONFIGURATION_Handle *orig;
-  const char *hostname;
-  unsigned int nport;
-  unsigned int upnum;
-  unsigned int fdnum;
-};
-
-struct ConnectTopologyContext
-{
   /**
-   * How many connections are left to create.
+   * The altered configuration.
    */
-  unsigned int remaining_connections;
+  struct GNUNET_CONFIGURATION_Handle *ret;
 
   /**
-   * How many more connections do we need to schedule?
+   * The original configuration to alter.
    */
-  unsigned int remaining_connects_to_schedule;
+  const struct GNUNET_CONFIGURATION_Handle *orig;
 
   /**
-   * Handle to group of peers.
+   * The hostname that this peer will run on.
    */
-  struct GNUNET_TESTING_PeerGroup *pg;
+  const char *hostname;
 
   /**
-   * How long to try this connection before timing out.
+   * The next possible port to assign.
    */
-  struct GNUNET_TIME_Relative connect_timeout;
+  unsigned int nport;
 
   /**
-   * How many times to retry connecting the two peers.
+   * Unique number for unix domain sockets.
    */
-  unsigned int connect_attempts;
+  unsigned int upnum;
 
   /**
-   * Temp value set for each iteration.
+   * Unique number for this peer/host to offset
+   * things that are grouped by host.
    */
-  //struct PeerData *first;
+  unsigned int fdnum;
+};
 
-  /**
-   * Notification that all peers are connected.
-   */
-  GNUNET_TESTING_NotifyCompletion notify_connections_done;
 
-  /**
-   * Closure for notify.
-   */
-  void *notify_cls;
-};
-
 struct ConnectContext
 {
   /**
-   * Peer to connect second to.
+   * Index of peer to connect second to.
    */
-  struct GNUNET_TESTING_Daemon *first;
+  uint32_t first_index;
 
   /**
-   * Peer to connect first to.
+   * Index of peer to connect first to.
    */
-  struct GNUNET_TESTING_Daemon *second;
+  uint32_t second_index;
 
   /**
    * Higher level topology connection context.
@@ -915,6 +983,10 @@
 }
 #endif
 
+#if USE_SEND_HELLOS
+static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
+#endif
+
 /**
  * Get a topology from a string input.
  *
@@ -1102,25 +1174,34 @@
   char *per_host_variable;
   unsigned long long num_per_host;
 
+  GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
+  GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
+
   if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
     {
-      GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
-      if ((ival != 0)
-          && (GNUNET_YES !=
+      if ((ival != 0) &&
+          (GNUNET_YES !=
               GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
                                                     single_variable)))
         {
           GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
           value = cval;
         }
-
-      GNUNET_free (single_variable);
+      else if ((ival != 0) &&
+               (GNUNET_YES ==
+               GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
+                                                     single_variable)) &&
+               GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing",
+                                                      per_host_variable,
+                                                      &num_per_host))
+        {
+          GNUNET_snprintf (cval, sizeof (cval), "%u", ival + ctx->fdnum % 
num_per_host);
+          value = cval;
+        }
     }
 
   if (0 == strcmp (option, "UNIXPATH"))
     {
-      GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
-      GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
       if (GNUNET_YES !=
           GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
                                                 single_variable))
@@ -1142,15 +1223,14 @@
                            section, ctx->fdnum % num_per_host);
           value = uval;
         }
-      GNUNET_free (single_variable);
-      GNUNET_free (per_host_variable);
     }
 
   if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
     {
       value = ctx->hostname;
     }
-
+  GNUNET_free (single_variable);
+  GNUNET_free (per_host_variable);
   GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
 }
 
@@ -1176,13 +1256,13 @@
 make_config (const struct GNUNET_CONFIGURATION_Handle *cfg,
              uint32_t off,
              uint16_t * port,
-             uint32_t * upnum, const char *hostname, uint32_t * fdnum)
+             uint32_t * upnum, const char *hostname,
+             uint32_t * fdnum)
 {
   struct UpdateContext uc;
   uint16_t orig;
   char *control_host;
   char *allowed_hosts;
-  unsigned long long temp_port;
 
   orig = *port;
   uc.nport = *port;
@@ -1223,16 +1303,6 @@
       GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", "");
       GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH", 
"");
 
-
-      if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(uc.orig, 
"statistics", "port", &temp_port) &&
-          (temp_port != 0) &&
-          (GNUNET_YES !=
-              GNUNET_CONFIGURATION_get_value_yesno (uc.orig, "testing",
-                                                    
"single_statistics_per_host")))
-        {
-          GNUNET_CONFIGURATION_set_value_number (uc.ret, "statistics", "port", 
temp_port + off);
-        }
-
       GNUNET_free_non_null (control_host);
       GNUNET_free (allowed_hosts);
     }
@@ -1493,9 +1563,6 @@
       new_first = GNUNET_malloc (sizeof (struct PeerConnection));
       new_first->index = second;
       GNUNET_CONTAINER_DLL_insert(*first_list, *first_tail, new_first);
-      /*
-      new_first->next = *first_list;
-      *first_list = new_first;*/
 #else
       GNUNET_assert (GNUNET_OK ==
                            GNUNET_CONTAINER_multihashmap_put (pg->
@@ -1516,10 +1583,6 @@
       new_second = GNUNET_malloc (sizeof (struct PeerConnection));
       new_second->index = first;
       GNUNET_CONTAINER_DLL_insert(*second_list, *second_tail, new_second);
-      /*
-      new_second->next = *second_list;
-      *second_list = new_second;
-      *second_list */
 #else
       GNUNET_assert (GNUNET_OK ==
                      GNUNET_CONTAINER_multihashmap_put (pg->
@@ -2606,7 +2669,8 @@
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                       _("Copying file with command cp %s %s\n"), mytemp, arg);
 #endif
-
+          ret = GNUNET_OS_process_wait(procarr[pg_iter]); /* FIXME: schedule 
this, throttle! */
+          GNUNET_OS_process_close (procarr[pg_iter]);
           GNUNET_free (arg);
         }
       else                      /* Remote, scp the file to the correct place */
@@ -2895,34 +2959,403 @@
  *
  * @param ct_ctx the overall connection context
  */
-static void preschedule_connect(struct ConnectTopologyContext *ct_ctx)
+static void preschedule_connect(struct GNUNET_TESTING_PeerGroup *pg)
 {
-  struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
+  struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx;
   struct PeerConnection *connection_iter;
   struct ConnectContext *connect_context;
   uint32_t random_peer;
 
-  if (ct_ctx->remaining_connects_to_schedule == 0)
+  if (ct_ctx->remaining_connections == 0)
     return;
   random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 
pg->total);
   while (pg->peers[random_peer].connect_peers_head == NULL)
     random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 
pg->total);
 
   connection_iter = pg->peers[random_peer].connect_peers_head;
-#if DEBUG_TESTING
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling connection between %d and 
%d\n", random_peer, connection_iter->index);
-#endif
   connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
-  connect_context->first = pg->peers[random_peer].daemon;
-  connect_context->second = pg->peers[connection_iter->index].daemon;
+  connect_context->first_index = random_peer;
+  connect_context->second_index = connection_iter->index;
   connect_context->ct_ctx = ct_ctx;
   GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
   GNUNET_CONTAINER_DLL_remove(pg->peers[random_peer].connect_peers_head, 
pg->peers[random_peer].connect_peers_tail, connection_iter);
-  ct_ctx->remaining_connects_to_schedule--;
+  GNUNET_free(connection_iter);
+  ct_ctx->remaining_connections--;
 }
 
+#if USE_SEND_HELLOS
+/* Forward declaration */
+static void schedule_send_hellos (void *cls, const struct 
GNUNET_SCHEDULER_TaskContext *tc);
 
+
 /**
+ * Close connections and free the hello context.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  if (send_hello_context->peer->daemon->server != NULL)
+    {
+      GNUNET_CORE_disconnect(send_hello_context->peer->daemon->server);
+      send_hello_context->peer->daemon->server = NULL;
+    }
+  if (send_hello_context->peer->daemon->th != NULL)
+    {
+      GNUNET_TRANSPORT_disconnect(send_hello_context->peer->daemon->th);
+      send_hello_context->peer->daemon->th = NULL;
+    }
+  if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel(send_hello_context->core_connect_task);
+      send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+  send_hello_context->pg->outstanding_connects--;
+  GNUNET_free(send_hello_context);
+}
+
+/**
+ * For peers that haven't yet connected, notify
+ * the caller that they have failed (timeout).
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+notify_remaining_connections_failed (void *cls, const struct 
GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+  struct PeerConnection *connection;
+
+  GNUNET_CORE_disconnect(send_hello_context->peer->daemon->server);
+  send_hello_context->peer->daemon->server = NULL;
+
+  connection = send_hello_context->peer->connect_peers_head;
+
+  while (connection != NULL)
+    {
+      if (pg->notify_connection != NULL)
+        {
+          pg->notify_connection(pg->notify_connection_cls,
+                                &send_hello_context->peer->daemon->id,
+                                &pg->peers[connection->index].daemon->id,
+                                0, /* FIXME */
+                                send_hello_context->peer->daemon->cfg,
+                                pg->peers[connection->index].daemon->cfg,
+                                send_hello_context->peer->daemon,
+                                pg->peers[connection->index].daemon,
+                                "Peers failed to connect (timeout)");
+        }
+      
GNUNET_CONTAINER_DLL_remove(send_hello_context->peer->connect_peers_head, 
send_hello_context->peer->connect_peers_tail, connection);
+      GNUNET_free(connection);
+      connection = connection->next;
+    }
+  GNUNET_SCHEDULER_add_now(&free_hello_context, send_hello_context);
+#if BAD
+      other_peer = &pg->peers[connection->index];
+#endif
+}
+
+
+/**
+ * For peers that haven't yet connected, send
+ * CORE connect requests.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+send_core_connect_requests (void *cls, const struct 
GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct PeerConnection *conn;
+  GNUNET_assert(send_hello_context->peer->daemon->server != NULL);
+
+  send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+
+  send_hello_context->connect_attempts++;
+  if (send_hello_context->connect_attempts < 
send_hello_context->pg->ct_ctx.connect_attempts)
+    {
+      conn = send_hello_context->peer->connect_peers_head;
+      while (conn != NULL)
+        {
+          
GNUNET_CORE_peer_request_connect(send_hello_context->peer->daemon->server,
+                                           GNUNET_TIME_relative_get_forever(),
+                                           
&send_hello_context->pg->peers[conn->index].daemon->id,
+                                           NULL,
+                                           NULL);
+          conn = conn->next;
+        }
+      send_hello_context->core_connect_task = 
GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_divide(send_hello_context->pg->ct_ctx.connect_timeout,
 send_hello_context->pg->ct_ctx.connect_attempts) ,
+                                                                           
&send_core_connect_requests,
+                                                                           
send_hello_context);
+    }
+  else
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Timeout before all connections 
created, marking rest as failed!\n");
+      GNUNET_SCHEDULER_add_now(&notify_remaining_connections_failed, 
send_hello_context);
+    }
+
+}
+
+
+/**
+ * Success, connection is up.  Signal client our success.
+ *
+ * @param cls our "struct SendHelloContext"
+ * @param peer identity of the peer that has connected
+ * @param atsi performance information
+ *
+ * FIXME: remove peers from BOTH lists, call notify twice, should
+ * double the speed of connections as long as the list iteration
+ * doesn't take too long!
+ */
+static void
+core_connect_notify (void *cls,
+                     const struct GNUNET_PeerIdentity *peer,
+                     const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct PeerConnection *connection;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+#if BAD
+  struct PeerData *other_peer;
+#endif
+#if DEBUG_TESTING
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Connected peer %s to peer %s\n",
+                ctx->d1->shortname, GNUNET_i2s(peer));
+#endif
+
+  if (0 == memcmp(&send_hello_context->peer->daemon->id, peer, sizeof(struct 
GNUNET_PeerIdentity)))
+    return;
+
+  connection = send_hello_context->peer->connect_peers_head;
+#if BAD
+  other_peer = NULL;
+#endif
+
+  while ((connection != NULL) &&
+         (0 != memcmp(&pg->peers[connection->index].daemon->id, peer, 
sizeof(struct GNUNET_PeerIdentity))))
+    {
+      connection = connection->next;
+    }
+
+  if (connection == NULL)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Connected peer %s to %s, not in 
list (no problem(?))\n", GNUNET_i2s(peer), 
send_hello_context->peer->daemon->shortname);
+    }
+  else
+    {
+#if BAD
+      other_peer = &pg->peers[connection->index];
+#endif
+      if (pg->notify_connection != NULL)
+        {
+          pg->notify_connection(pg->notify_connection_cls,
+                                &send_hello_context->peer->daemon->id,
+                                peer,
+                                0, /* FIXME */
+                                send_hello_context->peer->daemon->cfg,
+                                pg->peers[connection->index].daemon->cfg,
+                                send_hello_context->peer->daemon,
+                                pg->peers[connection->index].daemon,
+                                NULL);
+        }
+      
GNUNET_CONTAINER_DLL_remove(send_hello_context->peer->connect_peers_head, 
send_hello_context->peer->connect_peers_tail, connection);
+      GNUNET_free(connection);
+    }
+
+#if BAD
+  /* Notify of reverse connection and remove from other peers list of 
outstanding */
+  if (other_peer != NULL)
+    {
+      connection = other_peer->connect_peers_head;
+      while ((connection != NULL) &&
+             (0 != memcmp(&send_hello_context->peer->daemon->id, 
&pg->peers[connection->index].daemon->id, sizeof(struct GNUNET_PeerIdentity))))
+        {
+          connection = connection->next;
+        }
+      if (connection != NULL)
+        {
+          if (pg->notify_connection != NULL)
+            {
+              pg->notify_connection(pg->notify_connection_cls,
+                                    peer,
+                                    &send_hello_context->peer->daemon->id,
+                                    0, /* FIXME */
+                                    pg->peers[connection->index].daemon->cfg,
+                                    send_hello_context->peer->daemon->cfg,
+                                    pg->peers[connection->index].daemon,
+                                    send_hello_context->peer->daemon,
+                                    NULL);
+            }
+
+          GNUNET_CONTAINER_DLL_remove(other_peer->connect_peers_head, 
other_peer->connect_peers_tail, connection);
+          GNUNET_free(connection);
+        }
+    }
+#endif
+
+  if (send_hello_context->peer->connect_peers_head == NULL)
+    {
+      GNUNET_SCHEDULER_add_now(&free_hello_context, send_hello_context);
+    }
+}
+
+/**
+ * Notify of a successful connection to the core service.
+ *
+ * @param cls a struct SendHelloContext *
+ * @param server handle to the core service
+ * @param my_identity the peer identity of this peer
+ * @param publicKey the public key of the peer
+ */
+void
+core_init (void *cls,
+                  struct GNUNET_CORE_Handle * server,
+                  const struct GNUNET_PeerIdentity *
+                  my_identity,
+                  const struct
+                  GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *
+                  publicKey)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  send_hello_context->core_ready = GNUNET_YES;
+}
+
+
+/**
+ * Function called once a hello has been sent
+ * to the transport, move on to the next one
+ * or go away forever.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  //unsigned int pg_iter;
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    {
+      GNUNET_free(send_hello_context);
+      return;
+    }
+
+  send_hello_context->pg->remaining_hellos--;
+#if DEBUG_TESTING
+  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sent HELLO, have %d remaining!\n", 
send_hello_context->pg->remaining_hellos);
+#endif
+  if (send_hello_context->peer_pos == NULL) /* All HELLOs (for this peer!) 
have been transmitted! */
+    {
+#if DEBUG_TESTING
+      GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "All hellos for this peer sent, 
disconnecting transport!\n");
+#endif
+      GNUNET_assert(send_hello_context->peer->daemon->th != NULL);
+      GNUNET_TRANSPORT_disconnect(send_hello_context->peer->daemon->th);
+      send_hello_context->peer->daemon->th = NULL;
+
+      /*if (send_hello_context->pg->remaining_hellos == 0)
+        {
+          for (pg_iter = 0; pg_iter < 
send_hello_context->pg->max_outstanding_connections; pg_iter++)
+            {
+              preschedule_connect(&send_hello_context->pg->ct_ctx);
+            }
+        }
+        */
+      GNUNET_assert (send_hello_context->peer->daemon->server == NULL);
+      send_hello_context->peer->daemon->server = 
GNUNET_CORE_connect(send_hello_context->peer->cfg,
+                                                                     1,
+                                                                     
send_hello_context,
+                                                                     
&core_init,
+                                                                     
&core_connect_notify,
+                                                                     NULL,
+                                                                     NULL,
+                                                                     NULL, 
GNUNET_NO,
+                                                                     NULL, 
GNUNET_NO,
+                                                                     
no_handlers);
+
+      send_hello_context->core_connect_task = 
GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_relative_divide(send_hello_context->pg->ct_ctx.connect_timeout,
 send_hello_context->pg->ct_ctx.connect_attempts),
+                                                                           
&send_core_connect_requests,
+                                                                           
send_hello_context);
+    }
+  else
+    GNUNET_SCHEDULER_add_now(&schedule_send_hellos, send_hello_context);
+}
+
+
+/**
+ * Connect to a peer, give it all the HELLO's of those peers
+ * we will later ask it to connect to.
+ *
+ * @param ct_ctx the overall connection context
+ */
+static void schedule_send_hellos (void *cls, const struct 
GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+
+  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    {
+      GNUNET_free(send_hello_context);
+      return;
+    }
+
+  GNUNET_assert(send_hello_context->peer_pos != NULL); /* All of the HELLO 
sends to be scheduled have been scheduled! */
+
+  if (((send_hello_context->peer->daemon->th == NULL) &&
+       (pg->outstanding_connects > pg->max_outstanding_connections)) ||
+      (pg->stop_connects == GNUNET_YES))
+    {
+#if VERBOSE_TESTING > 2
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _
+                  ("Delaying connect, we have too many outstanding 
connections!\n"));
+#endif
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                    &schedule_send_hellos, send_hello_context);
+    }
+  else
+    {
+#if VERBOSE_TESTING > 2
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  _("Creating connection, outstanding_connections is %d\n"),
+                  outstanding_connects);
+#endif
+      if (send_hello_context->peer->daemon->th == NULL)
+        {
+          pg->outstanding_connects++; /* Actual TRANSPORT, CORE connections! */
+          send_hello_context->peer->daemon->th = 
GNUNET_TRANSPORT_connect(send_hello_context->peer->cfg,
+                                                                          NULL,
+                                                                          
send_hello_context,
+                                                                          NULL,
+                                                                          NULL,
+                                                                          
NULL);
+        }
+#if DEBUG_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _("Offering Hello of peer %s to peer %s\n"),
+                  send_hello_context->peer->daemon->shortname, 
pg->peers[send_hello_context->peer_pos->index].daemon->shortname);
+#endif
+      GNUNET_TRANSPORT_offer_hello(send_hello_context->peer->daemon->th,
+                                   (const struct GNUNET_MessageHeader 
*)pg->peers[send_hello_context->peer_pos->index].daemon->hello,
+                                   &hello_sent_callback,
+                                   send_hello_context);
+      send_hello_context->peer_pos = send_hello_context->peer_pos->next;
+      GNUNET_assert(send_hello_context->peer->daemon->th != NULL);
+    }
+}
+#endif
+
+
+/**
  * Internal notification of a connection, kept so that we can ensure some 
connections
  * happen instead of flooding all testing daemons with requests to connect.
  */
@@ -2937,23 +3370,54 @@
                          struct GNUNET_TESTING_Daemon *second_daemon,
                          const char *emsg)
 {
-  struct ConnectTopologyContext *ct_ctx = cls;
+  struct ConnectContext *connect_ctx = cls;
+  struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx;
   struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
+  struct PeerConnection *connection;
   pg->outstanding_connects--;
-  ct_ctx->remaining_connections--;
+
+  /*
+   * Check whether the inverse connection has been scheduled yet,
+   * if not, we can remove it from the other peers list and avoid
+   * even trying to connect them again!
+   */
+  connection = pg->peers[connect_ctx->second_index].connect_peers_head;
+#if BAD
+  other_peer = NULL;
+#endif
+
+  while ((connection != NULL) &&
+         (0 != memcmp(first, &pg->peers[connection->index].daemon->id, 
sizeof(struct GNUNET_PeerIdentity))))
+    {
+      connection = connection->next;
+    }
+
+  if (connection != NULL) /* Can safely remove! */
+    {
+      ct_ctx->remaining_connections--;
+      if (pg->notify_connection != NULL) /* Notify of reverse connection */
+        pg->notify_connection (pg->notify_connection_cls, second, first, 
distance,
+                               second_cfg, first_cfg, second_daemon, 
first_daemon,
+                               emsg);
+
+      
GNUNET_CONTAINER_DLL_remove(pg->peers[connect_ctx->second_index].connect_peers_head,
 pg->peers[connect_ctx->second_index].connect_peers_tail, connection);
+      GNUNET_free(connection);
+    }
+
   if (ct_ctx->remaining_connections == 0)
     {
       if (ct_ctx->notify_connections_done != NULL)
         ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL);
-      GNUNET_free (ct_ctx);
     }
   else
-    preschedule_connect(ct_ctx);
+    preschedule_connect(pg);
 
   if (pg->notify_connection != NULL)
     pg->notify_connection (pg->notify_connection_cls, first, second, distance,
                            first_cfg, second_cfg, first_daemon, second_daemon,
                            emsg);
+
+  GNUNET_free(connect_ctx);
 }
 
 
@@ -2975,8 +3439,8 @@
 
   if ((pg->outstanding_connects > pg->max_outstanding_connections) || 
(pg->stop_connects == GNUNET_YES))
     {
-#if VERBOSE_TESTING > 2
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+#if VERBOSE_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   _
                   ("Delaying connect, we have too many outstanding 
connections!\n"));
 #endif
@@ -2986,20 +3450,24 @@
     }
   else
     {
-#if VERBOSE_TESTING > 2
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  _("Creating connection, outstanding_connections is %d\n"),
-                  outstanding_connects);
+#if VERBOSE_TESTING
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _("Creating connection, outstanding_connections is %d (max 
%d)\n"),
+                  pg->outstanding_connects, pg->max_outstanding_connections);
 #endif
       pg->outstanding_connects++;
       pg->total_connects_scheduled++;
-      GNUNET_TESTING_daemons_connect (connect_context->first,
-                                      connect_context->second,
+      GNUNET_TESTING_daemons_connect 
(pg->peers[connect_context->first_index].daemon,
+                                      
pg->peers[connect_context->second_index].daemon,
                                       connect_context->ct_ctx->connect_timeout,
                                       
connect_context->ct_ctx->connect_attempts,
+#if USE_SEND_HELLOS
+                                      GNUNET_NO,
+#else
+                                      GNUNET_YES,
+#endif
                                       &internal_connect_notify,
-                                      connect_context->ct_ctx);
-      GNUNET_free (connect_context);
+                                      connect_context); /* FIXME: free connect 
context! */
     }
 }
 
@@ -3123,16 +3591,18 @@
 {
   unsigned int pg_iter;
   unsigned int total;
-  struct ConnectTopologyContext *ct_ctx;
+
 #if OLD
   struct PeerConnection *connection_iter;
 #endif
+#if USE_SEND_HELLOS
+  struct SendHelloContext *send_hello_context
+#endif
 
   total = 0;
-  ct_ctx = GNUNET_malloc (sizeof (struct ConnectTopologyContext));
-  ct_ctx->notify_connections_done = notify_callback;
-  ct_ctx->notify_cls = notify_cls;
-  ct_ctx->pg = pg;
+  pg->ct_ctx.notify_connections_done = notify_callback;
+  pg->ct_ctx.notify_cls = notify_cls;
+  pg->ct_ctx.pg = pg;
 
   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
     {
@@ -3150,19 +3620,29 @@
     }
 
   if (total == 0)
+    return total;
+
+  pg->ct_ctx.connect_timeout = connect_timeout;
+  pg->ct_ctx.connect_attempts = connect_attempts;
+  pg->ct_ctx.remaining_connections = total;
+
+#if USE_SEND_HELLOS
+  /* First give all peers the HELLO's of other peers (connect to first peer's 
transport service, give HELLO's of other peers, continue...) */
+  pg->remaining_hellos = total;
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
     {
-      GNUNET_free (ct_ctx);
-      return total;
+      send_hello_context = GNUNET_malloc(sizeof(struct SendHelloContext));
+      send_hello_context->peer = &pg->peers[pg_iter];
+      send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head;
+      send_hello_context->pg = pg;
+      GNUNET_SCHEDULER_add_now(&schedule_send_hellos, send_hello_context);
     }
-  ct_ctx->connect_timeout = connect_timeout;
-  ct_ctx->connect_attempts = connect_attempts;
-  ct_ctx->remaining_connections = total;
-  ct_ctx->remaining_connects_to_schedule = total;
-
+#else
   for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++)
-  {
-    preschedule_connect(ct_ctx);
-  }
+    {
+      preschedule_connect(pg);
+    }
+#endif
   return total;
 
 }

Modified: gnunet/src/topology/gnunet-daemon-topology.c
===================================================================
--- gnunet/src/topology/gnunet-daemon-topology.c        2011-02-22 08:25:03 UTC 
(rev 14484)
+++ gnunet/src/topology/gnunet-daemon-topology.c        2011-02-22 15:19:49 UTC 
(rev 14485)
@@ -1230,7 +1230,7 @@
     }
   if (transport != NULL)
     GNUNET_TRANSPORT_offer_hello (transport,
-                                 message);
+                                 message, NULL, NULL);
   return GNUNET_OK;
 }
 

Modified: gnunet/src/util/client.c
===================================================================
--- gnunet/src/util/client.c    2011-02-22 08:25:03 UTC (rev 14484)
+++ gnunet/src/util/client.c    2011-02-22 15:19:49 UTC (rev 14485)
@@ -304,6 +304,7 @@
 #if DEBUG_CLIENT
               GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Connected to unixpath 
`%s'!\n", unixpath);
 #endif
+              GNUNET_free(unixpath);
               return sock;
            }
        }




reply via email to

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