even nicer indentation, thanks to LRN's indent patch
[oweals/gnunet.git] / src / testing / testing.c
1 /*
2       This file is part of GNUnet
3       (C) 2008, 2009 Christian Grothoff (and other contributing authors)
4
5       GNUnet is free software; you can redistribute it and/or modify
6       it under the terms of the GNU General Public License as published
7       by the Free Software Foundation; either version 3, or (at your
8       option) any later version.
9
10       GNUnet is distributed in the hope that it will be useful, but
11       WITHOUT ANY WARRANTY; without even the implied warranty of
12       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13       General Public License for more details.
14
15       You should have received a copy of the GNU General Public License
16       along with GNUnet; see the file COPYING.  If not, write to the
17       Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18       Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file testing/testing.c
23  * @brief convenience API for writing testcases for GNUnet
24  *        Many testcases need to start and stop gnunetd,
25  *        and this library is supposed to make that easier
26  *        for TESTCASES.  Normal programs should always
27  *        use functions from gnunet_{util,arm}_lib.h.  This API is
28  *        ONLY for writing testcases!
29  * @author Christian Grothoff
30  *
31  */
32 #include "platform.h"
33 #include "gnunet_arm_service.h"
34 #include "gnunet_core_service.h"
35 #include "gnunet_constants.h"
36 #include "gnunet_testing_lib.h"
37 #include "gnunet_transport_service.h"
38 #include "gnunet_hello_lib.h"
39
40 #define DEBUG_TESTING GNUNET_NO
41
42 #define DEBUG_TESTING_RECONNECT GNUNET_NO
43
44 #define WAIT_FOR_HELLO GNUNET_NO
45
46 /**
47  * Hack to deal with initial HELLO's being often devoid of addresses.
48  * This hack causes 'process_hello' to ignore HELLOs without addresses.
49  * The correct implementation would continue with 'process_hello' until
50  * the connection could be established...
51  */
52 #define EMPTY_HACK GNUNET_YES
53
54 /**
55  * How long do we wait after starting gnunet-service-arm
56  * for the core service to be alive?
57  */
58 #define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
59
60 /**
61  * How many times are we willing to try to wait for "scp" or
62  * "gnunet-service-arm" to complete (waitpid) before giving up?
63  */
64 #define MAX_EXEC_WAIT_RUNS 250
65
66 static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
67
68 #if EMPTY_HACK
69 static int
70 test_address (void *cls, const char *tname,
71               struct GNUNET_TIME_Absolute expiration, const void *addr,
72               uint16_t addrlen)
73 {
74   int *empty = cls;
75
76   *empty = GNUNET_NO;
77   return GNUNET_OK;
78 }
79 #endif
80
81 /**
82  * Receive the HELLO from one peer, give it to the other
83  * and ask them to connect.
84  *
85  * @param cls "struct ConnectContext"
86  * @param message HELLO message of peer
87  */
88 static void
89 process_hello (void *cls, const struct GNUNET_MessageHeader *message)
90 {
91   struct GNUNET_TESTING_Daemon *daemon = cls;
92   int msize;
93
94 #if WAIT_FOR_HELLO
95   GNUNET_TESTING_NotifyDaemonRunning cb;
96 #endif
97 #if EMPTY_HACK
98   int empty;
99
100   empty = GNUNET_YES;
101   GNUNET_assert (message != NULL);
102   GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) message,
103                                   GNUNET_NO, &test_address, &empty);
104   if (GNUNET_YES == empty)
105   {
106 #if DEBUG_TESTING
107     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Skipping empty HELLO address\n");
108 #endif
109     return;
110   }
111 #endif
112   if (daemon == NULL)
113     return;
114
115   GNUNET_assert (daemon->phase == SP_GET_HELLO ||
116                  daemon->phase == SP_START_DONE);
117 #if WAIT_FOR_HELLO
118   cb = daemon->cb;
119 #endif
120   daemon->cb = NULL;
121   if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */
122     GNUNET_SCHEDULER_cancel (daemon->task);
123
124   if (daemon->server != NULL)
125   {
126 #if DEBUG_TESTING
127     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
128                 "Received `%s' from transport service of `%4s', disconnecting core!\n",
129                 "HELLO", GNUNET_i2s (&daemon->id));
130 #endif
131     GNUNET_CORE_disconnect (daemon->server);
132     daemon->server = NULL;
133   }
134
135   msize = ntohs (message->size);
136   if (msize < 1)
137   {
138     return;
139   }
140   if (daemon->th != NULL)
141   {
142     GNUNET_TRANSPORT_get_hello_cancel (daemon->th, &process_hello, daemon);
143   }
144 #if DEBUG_TESTING
145   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
146               "Received `%s' from transport service of `%4s'\n", "HELLO",
147               GNUNET_i2s (&daemon->id));
148 #endif
149
150   GNUNET_free_non_null (daemon->hello);
151   daemon->hello = GNUNET_malloc (msize);
152   memcpy (daemon->hello, message, msize);
153
154   if (daemon->th != NULL)
155   {
156     GNUNET_TRANSPORT_disconnect (daemon->th);
157     daemon->th = NULL;
158   }
159   daemon->phase = SP_START_DONE;
160
161 #if WAIT_FOR_HELLO
162   if (NULL != cb)               /* FIXME: what happens when this callback calls GNUNET_TESTING_daemon_stop? */
163     cb (daemon->cb_cls, &daemon->id, daemon->cfg, daemon, NULL);
164 #endif
165 }
166
167 static void
168 start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
169
170 #if WAIT_FOR_HELLO
171 /**
172  * Function called after GNUNET_CORE_connect has succeeded
173  * (or failed for good).  Note that the private key of the
174  * peer is intentionally not exposed here; if you need it,
175  * your process should try to read the private key file
176  * directly (which should work if you are authorized...).
177  *
178  * @param cls closure
179  * @param server handle to the server, NULL if we failed
180  * @param my_identity ID of this peer, NULL if we failed
181  * @param publicKey public key of this peer, NULL if we failed
182  */
183 static void
184 testing_init (void *cls, struct GNUNET_CORE_Handle *server,
185               const struct GNUNET_PeerIdentity *my_identity,
186               const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
187 {
188   struct GNUNET_TESTING_Daemon *d = cls;
189
190   GNUNET_assert (d->phase == SP_START_CORE);
191   d->phase = SP_GET_HELLO;
192
193   if (server == NULL)
194   {
195     d->server = NULL;
196     if (GNUNET_YES == d->dead)
197       GNUNET_TESTING_daemon_stop (d,
198                                   GNUNET_TIME_absolute_get_remaining
199                                   (d->max_timeout), d->dead_cb, d->dead_cb_cls,
200                                   GNUNET_YES, GNUNET_NO);
201     else if (NULL != d->cb)
202       d->cb (d->cb_cls, NULL, d->cfg, d,
203              _("Failed to connect to core service\n"));
204     return;
205   }
206 #if DEBUG_TESTING
207   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started peer `%4s'.\n",
208               GNUNET_i2s (my_identity));
209 #endif
210   d->id = *my_identity;         /* FIXME: shouldn't we already have this from reading the hostkey file? */
211   if (d->shortname == NULL)
212     d->shortname = strdup (GNUNET_i2s (my_identity));
213   d->server = server;
214   d->running = GNUNET_YES;
215
216   if (GNUNET_NO == d->running)
217   {
218 #if DEBUG_TESTING
219     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220                 "Peer is dead (d->running == GNUNET_NO)\n");
221 #endif
222     return;
223   }
224 #if DEBUG_TESTING
225   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
226               "Successfully started peer `%4s', connecting to transport service.\n",
227               GNUNET_i2s (my_identity));
228 #endif
229
230   d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL);
231   if (d->th == NULL)
232   {
233     if (GNUNET_YES == d->dead)
234       GNUNET_TESTING_daemon_stop (d,
235                                   GNUNET_TIME_absolute_get_remaining
236                                   (d->max_timeout), d->dead_cb, d->dead_cb_cls,
237                                   GNUNET_YES, GNUNET_NO);
238     else if (NULL != d->cb)
239       d->cb (d->cb_cls, &d->id, d->cfg, d,
240              _("Failed to connect to transport service!\n"));
241     return;
242   }
243 #if DEBUG_TESTING
244   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245               "Connected to transport service `%s', getting HELLO\n",
246               GNUNET_i2s (my_identity));
247 #endif
248
249   GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
250   /* wait some more */
251   if (d->task != GNUNET_SCHEDULER_NO_TASK)
252     GNUNET_SCHEDULER_cancel (d->task);
253   d->task =
254       GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
255 }
256 #endif
257
258 #if !WAIT_FOR_HELLO
259 /**
260  * Notify of a peer being up and running.  Scheduled as a task
261  * so that variables which may need to be set are set before
262  * the connect callback can set up new operations.
263  *
264  * @param cls the testing daemon
265  * @param tc task scheduler context
266  */
267 static void
268 notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
269 {
270   struct GNUNET_TESTING_Daemon *d = cls;
271   GNUNET_TESTING_NotifyDaemonRunning cb;
272
273   cb = d->cb;
274   d->cb = NULL;
275   if (NULL != cb)
276     cb (d->cb_cls, &d->id, d->cfg, d, NULL);
277 }
278 #endif
279
280 /**
281  * Finite-state machine for starting GNUnet.
282  *
283  * @param cls our "struct GNUNET_TESTING_Daemon"
284  * @param tc unused
285  */
286 static void
287 start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
288 {
289   struct GNUNET_TESTING_Daemon *d = cls;
290   GNUNET_TESTING_NotifyDaemonRunning cb;
291   enum GNUNET_OS_ProcessStatusType type;
292   unsigned long code;
293   char *dst;
294   int bytes_read;
295
296 #if DEBUG_TESTING
297   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer FSM is in phase %u.\n", d->phase);
298 #endif
299
300   d->task = GNUNET_SCHEDULER_NO_TASK;
301   switch (d->phase)
302   {
303   case SP_COPYING:
304     /* confirm copying complete */
305     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
306     {
307       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
308       {
309         cb = d->cb;
310         d->cb = NULL;
311         if (NULL != cb)
312           cb (d->cb_cls, NULL, d->cfg, d,
313               _
314               ("`scp' does not seem to terminate (timeout copying config).\n"));
315         return;
316       }
317       /* wait some more */
318       d->task =
319           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
320                                         d);
321       return;
322     }
323     if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
324     {
325       cb = d->cb;
326       d->cb = NULL;
327       if (NULL != cb)
328         cb (d->cb_cls, NULL, d->cfg, d, _("`scp' did not complete cleanly.\n"));
329       return;
330     }
331     GNUNET_OS_process_close (d->proc);
332 #if DEBUG_TESTING
333     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334                 "Successfully copied configuration file.\n");
335 #endif
336     d->phase = SP_COPIED;
337     /* fall-through */
338   case SP_COPIED:
339     /* Start create hostkey process if we don't already know the peer identity! */
340     if (GNUNET_NO == d->have_hostkey)
341     {
342       d->pipe_stdout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_YES);
343       if (d->pipe_stdout == NULL)
344       {
345         cb = d->cb;
346         d->cb = NULL;
347         if (NULL != cb)
348           cb (d->cb_cls, NULL, d->cfg, d,
349               (NULL ==
350                d->hostname) ?
351               _("Failed to create pipe for `gnunet-peerinfo' process.\n") :
352               _("Failed to create pipe for `ssh' process.\n"));
353         return;
354       }
355       if (NULL == d->hostname)
356       {
357 #if DEBUG_TESTING
358         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
359                     "Starting `%s', with command `%s %s %s %s'.\n",
360                     "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile,
361                     "-sq");
362 #endif
363         d->proc =
364             GNUNET_OS_start_process (NULL, d->pipe_stdout, "gnunet-peerinfo",
365                                      "gnunet-peerinfo", "-c", d->cfgfile, "-sq",
366                                      NULL);
367         GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
368       }
369       else
370       {
371         if (d->username != NULL)
372           GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
373         else
374           dst = GNUNET_strdup (d->hostname);
375
376 #if DEBUG_TESTING
377         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
378                     "Starting `%s', with command `%s %s %s %s %s %s'.\n",
379                     "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c",
380                     d->cfgfile, "-sq");
381 #endif
382         if (d->ssh_port_str == NULL)
383         {
384           d->proc = GNUNET_OS_start_process (NULL, d->pipe_stdout, "ssh", "ssh",
385 #if !DEBUG_TESTING
386                                              "-q",
387 #endif
388                                              dst, "gnunet-peerinfo", "-c",
389                                              d->cfgfile, "-sq", NULL);
390         }
391         else
392         {
393           d->proc =
394               GNUNET_OS_start_process (NULL, d->pipe_stdout, "ssh", "ssh", "-p",
395                                        d->ssh_port_str,
396 #if !DEBUG_TESTING
397                                        "-q",
398 #endif
399                                        dst, "gnunet-peerinfo", "-c", d->cfgfile,
400                                        "-sq", NULL);
401         }
402         GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
403         GNUNET_free (dst);
404       }
405       if (NULL == d->proc)
406       {
407         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
408                     _("Could not start `%s' process to create hostkey.\n"),
409                     (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh");
410         cb = d->cb;
411         d->cb = NULL;
412         if (NULL != cb)
413           cb (d->cb_cls, NULL, d->cfg, d,
414               (NULL ==
415                d->hostname) ? _("Failed to start `gnunet-peerinfo' process.\n")
416               : _("Failed to start `ssh' process.\n"));
417         GNUNET_DISK_pipe_close (d->pipe_stdout);
418         return;
419       }
420 #if DEBUG_TESTING
421       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
422                   "Started `%s', waiting for hostkey.\n", "gnunet-peerinfo");
423 #endif
424       d->phase = SP_HOSTKEY_CREATE;
425       d->task =
426           GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
427                                           (d->max_timeout),
428                                           GNUNET_DISK_pipe_handle
429                                           (d->pipe_stdout,
430                                            GNUNET_DISK_PIPE_END_READ),
431                                           &start_fsm, d);
432     }
433     else                        /* Already have a hostkey! */
434     {
435       if (d->hostkey_callback != NULL)
436       {
437         d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
438         d->hostkey_callback = NULL;
439         d->phase = SP_HOSTKEY_CREATED;
440       }
441       else
442         d->phase = SP_TOPOLOGY_SETUP;
443
444       /* wait some more */
445       d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
446     }
447     break;
448   case SP_HOSTKEY_CREATE:
449     bytes_read =
450         GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle
451                                (d->pipe_stdout, GNUNET_DISK_PIPE_END_READ),
452                                &d->hostkeybuf[d->hostkeybufpos],
453                                sizeof (d->hostkeybuf) - d->hostkeybufpos);
454     if (bytes_read > 0)
455       d->hostkeybufpos += bytes_read;
456
457     if ((d->hostkeybufpos < 104) && (bytes_read > 0))
458     {
459       /* keep reading */
460       d->task =
461           GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
462                                           (d->max_timeout),
463                                           GNUNET_DISK_pipe_handle
464                                           (d->pipe_stdout,
465                                            GNUNET_DISK_PIPE_END_READ),
466                                           &start_fsm, d);
467       return;
468     }
469     d->hostkeybuf[103] = '\0';
470
471     if ((bytes_read < 0) ||
472         (GNUNET_OK !=
473          GNUNET_CRYPTO_hash_from_string (d->hostkeybuf, &d->id.hashPubKey)))
474     {
475       /* error */
476       if (bytes_read < 0)
477         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
478                     _("Error reading from gnunet-peerinfo: %s\n"),
479                     STRERROR (errno));
480       else
481         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
482                     _("Malformed output from gnunet-peerinfo!\n"));
483       cb = d->cb;
484       d->cb = NULL;
485       GNUNET_DISK_pipe_close (d->pipe_stdout);
486       d->pipe_stdout = NULL;
487       (void) GNUNET_OS_process_kill (d->proc, SIGKILL);
488       GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc));
489       GNUNET_OS_process_close (d->proc);
490       d->proc = NULL;
491       if (NULL != cb)
492         cb (d->cb_cls, NULL, d->cfg, d, _("`Failed to get hostkey!\n"));
493       return;
494     }
495     d->shortname = GNUNET_strdup (GNUNET_i2s (&d->id));
496     GNUNET_DISK_pipe_close (d->pipe_stdout);
497     d->pipe_stdout = NULL;
498     (void) GNUNET_OS_process_kill (d->proc, SIGKILL);
499     GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc));
500     GNUNET_OS_process_close (d->proc);
501     d->proc = NULL;
502     d->have_hostkey = GNUNET_YES;
503     if (d->hostkey_callback != NULL)
504     {
505       d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
506       d->hostkey_callback = NULL;
507       d->phase = SP_HOSTKEY_CREATED;
508     }
509     else
510     {
511       d->phase = SP_TOPOLOGY_SETUP;
512     }
513 #if DEBUG_TESTING
514     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully got hostkey!\n");
515 #endif
516     /* Fall through */
517   case SP_HOSTKEY_CREATED:
518     /* wait for topology finished */
519     if ((GNUNET_YES == d->dead) ||
520         (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0))
521     {
522       cb = d->cb;
523       d->cb = NULL;
524       if (NULL != cb)
525         cb (d->cb_cls, NULL, d->cfg, d,
526             _("`Failed while waiting for topology setup!\n"));
527       return;
528     }
529
530     d->task =
531         GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
532                                       d);
533     break;
534   case SP_TOPOLOGY_SETUP:      /* Indicates topology setup has completed! */
535     /* start GNUnet on remote host */
536     if (NULL == d->hostname)
537     {
538 #if DEBUG_TESTING
539       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
540                   "Starting `%s', with command `%s %s %s %s %s %s'.\n",
541                   "gnunet-arm", "gnunet-arm", "-c", d->cfgfile, "-L", "DEBUG",
542                   "-s");
543 #endif
544       d->proc =
545           GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm", "-c",
546                                    d->cfgfile,
547 #if DEBUG_TESTING
548                                    "-L", "DEBUG",
549 #endif
550                                    "-s", "-q", "-T",
551                                    GNUNET_TIME_relative_to_string
552                                    (GNUNET_TIME_absolute_get_remaining
553                                     (d->max_timeout)), NULL);
554     }
555     else
556     {
557       if (d->username != NULL)
558         GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
559       else
560         dst = GNUNET_strdup (d->hostname);
561
562 #if DEBUG_TESTING
563       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
564                   "Starting `%s', with command `%s %s %s %s %s %s %s %s'.\n",
565                   "gnunet-arm", "ssh", dst, "gnunet-arm", "-c", d->cfgfile,
566                   "-L", "DEBUG", "-s", "-q");
567 #endif
568       if (d->ssh_port_str == NULL)
569       {
570         d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
571 #if !DEBUG_TESTING
572                                            "-q",
573 #endif
574                                            dst, "gnunet-arm",
575 #if DEBUG_TESTING
576                                            "-L", "DEBUG",
577 #endif
578                                            "-c", d->cfgfile, "-s", "-q", "-T",
579                                            GNUNET_TIME_relative_to_string
580                                            (GNUNET_TIME_absolute_get_remaining
581                                             (d->max_timeout)), NULL);
582       }
583       else
584       {
585
586         d->proc =
587             GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", "-p",
588                                      d->ssh_port_str,
589 #if !DEBUG_TESTING
590                                      "-q",
591 #endif
592                                      dst, "gnunet-arm",
593 #if DEBUG_TESTING
594                                      "-L", "DEBUG",
595 #endif
596                                      "-c", d->cfgfile, "-s", "-q", "-T",
597                                      GNUNET_TIME_relative_to_string
598                                      (GNUNET_TIME_absolute_get_remaining
599                                       (d->max_timeout)), NULL);
600       }
601       GNUNET_free (dst);
602     }
603     if (NULL == d->proc)
604     {
605       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
606                   _("Could not start `%s' process to start GNUnet.\n"),
607                   (NULL == d->hostname) ? "gnunet-arm" : "ssh");
608       cb = d->cb;
609       d->cb = NULL;
610       if (NULL != cb)
611         cb (d->cb_cls, NULL, d->cfg, d,
612             (NULL ==
613              d->hostname) ? _("Failed to start `gnunet-arm' process.\n") :
614             _("Failed to start `ssh' process.\n"));
615       return;
616     }
617 #if DEBUG_TESTING
618     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
619                 "Started `%s', waiting for `%s' to be up.\n", "gnunet-arm",
620                 "gnunet-service-core");
621 #endif
622     d->phase = SP_START_ARMING;
623     d->task =
624         GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
625                                       d);
626     break;
627   case SP_START_ARMING:
628     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
629     {
630       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
631       {
632         cb = d->cb;
633         d->cb = NULL;
634         if (NULL != cb)
635           cb (d->cb_cls, NULL, d->cfg, d,
636               (NULL ==
637                d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
638               _("`ssh' does not seem to terminate.\n"));
639         GNUNET_CONFIGURATION_destroy (d->cfg);
640         GNUNET_free (d->cfgfile);
641         GNUNET_free_non_null (d->hostname);
642         GNUNET_free_non_null (d->username);
643         GNUNET_free (d->proc);
644         GNUNET_free (d);
645         return;
646       }
647       /* wait some more */
648       d->task =
649           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
650                                         d);
651       return;
652     }
653 #if DEBUG_TESTING
654     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully started `%s'.\n",
655                 "gnunet-arm");
656 #endif
657     GNUNET_free (d->proc);
658     d->phase = SP_START_CORE;
659 #if DEBUG_TESTING
660     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Calling CORE_connect\n");
661 #endif
662     /* Fall through */
663   case SP_START_CORE:
664     if (d->server != NULL)
665       GNUNET_CORE_disconnect (d->server);
666
667 #if WAIT_FOR_HELLO
668     if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
669     {
670       cb = d->cb;
671       d->cb = NULL;
672       if (NULL != cb)
673         cb (d->cb_cls, NULL, d->cfg, d,
674             _("Unable to connect to CORE service for peer!\n"));
675       GNUNET_CONFIGURATION_destroy (d->cfg);
676       GNUNET_free (d->cfgfile);
677       GNUNET_free_non_null (d->hostname);
678       GNUNET_free_non_null (d->username);
679       GNUNET_free (d);
680       return;
681     }
682     d->server =
683         GNUNET_CORE_connect (d->cfg, 1, d, &testing_init, NULL, NULL, NULL,
684                              NULL, GNUNET_NO, NULL, GNUNET_NO, no_handlers);
685     d->task =
686         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
687                                       (GNUNET_CONSTANTS_SERVICE_RETRY, 2),
688                                       &start_fsm, d);
689 #else
690     d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL);
691     if (d->th == NULL)
692     {
693       if (GNUNET_YES == d->dead)
694         GNUNET_TESTING_daemon_stop (d,
695                                     GNUNET_TIME_absolute_get_remaining
696                                     (d->max_timeout), d->dead_cb,
697                                     d->dead_cb_cls, GNUNET_YES, GNUNET_NO);
698       else if (NULL != d->cb)
699         d->cb (d->cb_cls, &d->id, d->cfg, d,
700                _("Failed to connect to transport service!\n"));
701       return;
702     }
703 #if DEBUG_TESTING
704     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705                 "Connected to transport service `%s', getting HELLO\n",
706                 GNUNET_i2s (&d->id));
707 #endif
708
709     GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
710     GNUNET_SCHEDULER_add_now (&notify_daemon_started, d);
711     /*cb = d->cb;
712      * d->cb = NULL;
713      * if (NULL != cb)
714      * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */
715     d->running = GNUNET_YES;
716     d->phase = SP_GET_HELLO;
717 #endif
718     break;
719   case SP_GET_HELLO:
720     if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
721     {
722       if (d->server != NULL)
723         GNUNET_CORE_disconnect (d->server);
724       if (d->th != NULL)
725         GNUNET_TRANSPORT_disconnect (d->th);
726       cb = d->cb;
727       d->cb = NULL;
728       if (NULL != cb)
729         cb (d->cb_cls, NULL, d->cfg, d, _("Unable to get HELLO for peer!\n"));
730       GNUNET_CONFIGURATION_destroy (d->cfg);
731       GNUNET_free (d->cfgfile);
732       GNUNET_free_non_null (d->hostname);
733       GNUNET_free_non_null (d->username);
734       GNUNET_free (d);
735       return;
736     }
737     if (d->hello != NULL)
738       return;
739     GNUNET_assert (d->task == GNUNET_SCHEDULER_NO_TASK);
740     d->task =
741         GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
742                                       (GNUNET_CONSTANTS_SERVICE_RETRY, 2),
743                                       &start_fsm, d);
744     break;
745   case SP_START_DONE:
746     GNUNET_break (0);
747     break;
748   case SP_SERVICE_START:
749     /* confirm gnunet-arm exited */
750     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
751     {
752       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
753       {
754         cb = d->cb;
755         d->cb = NULL;
756         if (NULL != cb)
757           cb (d->cb_cls, NULL, d->cfg, d,
758               (NULL ==
759                d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
760               _("`ssh' does not seem to terminate.\n"));
761         return;
762       }
763       /* wait some more */
764       d->task =
765           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
766                                         d);
767       return;
768     }
769 #if EXTRA_CHECKS
770     if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
771     {
772       cb = d->cb;
773       d->cb = NULL;
774       if (NULL != cb)
775         cb (d->cb_cls, NULL, d->cfg, d,
776             (NULL ==
777              d->hostname) ?
778             _
779             ("`gnunet-arm' terminated with non-zero exit status (or timed out)!\n")
780             : _("`ssh' does not seem to terminate.\n"));
781       return;
782     }
783 #endif
784 #if DEBUG_TESTING
785     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service startup complete!\n");
786 #endif
787     cb = d->cb;
788     d->cb = NULL;
789     d->phase = SP_START_DONE;
790     if (NULL != cb)
791       cb (d->cb_cls, &d->id, d->cfg, d, NULL);
792     break;
793   case SP_SERVICE_SHUTDOWN_START:
794     /* confirm copying complete */
795     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
796     {
797       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
798       {
799         if (NULL != d->dead_cb)
800           d->dead_cb (d->dead_cb_cls,
801                       _
802                       ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
803         return;
804       }
805       /* wait some more */
806       d->task =
807           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
808                                         d);
809       return;
810     }
811 #if EXTRA_CHECKS
812     if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
813     {
814       if (NULL != d->dead_cb)
815         d->dead_cb (d->dead_cb_cls,
816                     _
817                     ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
818       return;
819     }
820 #endif
821 #if DEBUG_TESTING
822     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n");
823 #endif
824     if (NULL != d->dead_cb)
825       d->dead_cb (d->dead_cb_cls, NULL);
826     break;
827   case SP_SHUTDOWN_START:
828     /* confirm copying complete */
829     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
830     {
831       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
832       {
833         if (NULL != d->dead_cb)
834           d->dead_cb (d->dead_cb_cls,
835                       _
836                       ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
837         if (d->th != NULL)
838         {
839           GNUNET_TRANSPORT_get_hello_cancel (d->th, &process_hello, d);
840           GNUNET_TRANSPORT_disconnect (d->th);
841           d->th = NULL;
842         }
843         GNUNET_CONFIGURATION_destroy (d->cfg);
844         GNUNET_free (d->cfgfile);
845         GNUNET_free_non_null (d->hello);
846         GNUNET_free_non_null (d->hostname);
847         GNUNET_free_non_null (d->username);
848         GNUNET_free_non_null (d->shortname);
849         GNUNET_free_non_null (d->proc);
850         d->proc = NULL;
851         GNUNET_free (d);
852         return;
853       }
854       /* wait some more */
855       d->task =
856           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
857                                         d);
858       return;
859     }
860     if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
861     {
862       if (NULL != d->dead_cb)
863         d->dead_cb (d->dead_cb_cls,
864                     _
865                     ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
866       if (d->th != NULL)
867       {
868         GNUNET_TRANSPORT_get_hello_cancel (d->th, &process_hello, d);
869         GNUNET_TRANSPORT_disconnect (d->th);
870         d->th = NULL;
871       }
872       if (d->server != NULL)
873       {
874         GNUNET_CORE_disconnect (d->server);
875         d->server = NULL;
876       }
877       GNUNET_CONFIGURATION_destroy (d->cfg);
878       GNUNET_free (d->cfgfile);
879       GNUNET_free_non_null (d->hello);
880       GNUNET_free_non_null (d->hostname);
881       GNUNET_free_non_null (d->username);
882       GNUNET_free_non_null (d->shortname);
883       GNUNET_free_non_null (d->proc);
884       d->proc = NULL;
885       GNUNET_free (d);
886       return;
887     }
888 #if DEBUG_TESTING
889     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer shutdown complete.\n");
890 #endif
891     if (d->server != NULL)
892     {
893       GNUNET_CORE_disconnect (d->server);
894       d->server = NULL;
895     }
896
897     if (d->th != NULL)
898     {
899       GNUNET_TRANSPORT_get_hello_cancel (d->th, &process_hello, d);
900       GNUNET_TRANSPORT_disconnect (d->th);
901       d->th = NULL;
902     }
903
904     if (NULL != d->dead_cb)
905       d->dead_cb (d->dead_cb_cls, NULL);
906
907     /* state clean up and notifications */
908     if (d->churn == GNUNET_NO)
909     {
910       GNUNET_CONFIGURATION_destroy (d->cfg);
911       GNUNET_free (d->cfgfile);
912       GNUNET_free_non_null (d->hostname);
913       GNUNET_free_non_null (d->username);
914     }
915
916     GNUNET_free_non_null (d->hello);
917     d->hello = NULL;
918     GNUNET_free_non_null (d->shortname);
919     GNUNET_free_non_null (d->proc);
920     d->proc = NULL;
921     d->shortname = NULL;
922     if (d->churn == GNUNET_NO)
923       GNUNET_free (d);
924
925     break;
926   case SP_CONFIG_UPDATE:
927     /* confirm copying complete */
928     if (GNUNET_OK != GNUNET_OS_process_status (d->proc, &type, &code))
929     {
930       if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)   /* FIXME: config update should take timeout parameter! */
931       {
932         cb = d->cb;
933         d->cb = NULL;
934         if (NULL != cb)
935           cb (d->cb_cls, NULL, d->cfg, d,
936               _("`scp' does not seem to terminate.\n"));
937         return;
938       }
939       /* wait some more */
940       d->task =
941           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
942                                         d);
943       return;
944     }
945     if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
946     {
947       if (NULL != d->update_cb)
948         d->update_cb (d->update_cb_cls, _("`scp' did not complete cleanly.\n"));
949       return;
950     }
951 #if DEBUG_TESTING
952     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
953                 "Successfully copied configuration file.\n");
954 #endif
955     if (NULL != d->update_cb)
956       d->update_cb (d->update_cb_cls, NULL);
957     d->phase = SP_START_DONE;
958     break;
959   }
960 }
961
962 /**
963  * Continues GNUnet daemon startup when user wanted to be notified
964  * once a hostkey was generated (for creating friends files, blacklists,
965  * etc.).
966  *
967  * @param daemon the daemon to finish starting
968  */
969 void
970 GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon)
971 {
972   GNUNET_assert (daemon->phase == SP_HOSTKEY_CREATED);
973   daemon->phase = SP_TOPOLOGY_SETUP;
974 }
975
976 /**
977  * Check whether the given daemon is running.
978  *
979  * @param daemon the daemon to check
980  *
981  * @return GNUNET_YES if the daemon is up, GNUNET_NO if the
982  *         daemon is down, GNUNET_SYSERR on error.
983  */
984 int
985 GNUNET_TESTING_daemon_running (struct GNUNET_TESTING_Daemon *daemon)
986 {
987   if (daemon == NULL)
988     return GNUNET_SYSERR;
989
990   if (daemon->running == GNUNET_YES)
991     return GNUNET_YES;
992   return GNUNET_NO;
993 }
994
995
996 /**
997  * Starts a GNUnet daemon service which has been previously stopped.
998  *
999  * @param d the daemon for which the service should be started
1000  * @param service the name of the service to start
1001  * @param timeout how long to wait for process for shutdown to complete
1002  * @param cb function called once the service starts
1003  * @param cb_cls closure for cb
1004  */
1005 void
1006 GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d,
1007                                              char *service,
1008                                              struct GNUNET_TIME_Relative
1009                                              timeout,
1010                                              GNUNET_TESTING_NotifyDaemonRunning
1011                                              cb, void *cb_cls)
1012 {
1013   char *arg;
1014
1015   d->cb = cb;
1016   d->cb_cls = cb_cls;
1017
1018   GNUNET_assert (d->running == GNUNET_YES);
1019
1020   if (d->phase == SP_CONFIG_UPDATE)
1021   {
1022     GNUNET_SCHEDULER_cancel (d->task);
1023     d->phase = SP_START_DONE;
1024   }
1025
1026   if (d->churned_services == NULL)
1027   {
1028     d->cb (d->cb_cls, &d->id, d->cfg, d,
1029            "No service has been churned off yet!!");
1030     return;
1031   }
1032   d->phase = SP_SERVICE_START;
1033   GNUNET_free (d->churned_services);
1034   d->churned_services = NULL;
1035   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1036   /* Check if this is a local or remote process */
1037   if (NULL != d->hostname)
1038   {
1039 #if DEBUG_TESTING
1040     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1041                 "Starting gnunet-arm with config `%s' on host `%s'.\n",
1042                 d->cfgfile, d->hostname);
1043 #endif
1044
1045     if (d->username != NULL)
1046       GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
1047     else
1048       arg = GNUNET_strdup (d->hostname);
1049
1050     d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
1051 #if !DEBUG_TESTING
1052                                        "-q",
1053 #endif
1054                                        arg, "gnunet-arm",
1055 #if DEBUG_TESTING
1056                                        "-L", "DEBUG",
1057 #endif
1058                                        "-c", d->cfgfile, "-i", service, "-q",
1059                                        "-T",
1060                                        GNUNET_TIME_relative_to_string (timeout),
1061                                        NULL);
1062     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1063                 "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q\n",
1064                 arg, "gnunet-arm", d->cfgfile, service);
1065     GNUNET_free (arg);
1066   }
1067   else
1068   {
1069 #if DEBUG_TESTING
1070     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1071                 "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
1072 #endif
1073     d->proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm",
1074 #if DEBUG_TESTING
1075                                        "-L", "DEBUG",
1076 #endif
1077                                        "-c", d->cfgfile, "-i", service, "-q",
1078                                        "-T",
1079                                        GNUNET_TIME_relative_to_string (timeout),
1080                                        NULL);
1081   }
1082
1083   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1084   d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
1085 }
1086
1087 /**
1088  * Starts a GNUnet daemon's service.
1089  *
1090  * @param d the daemon for which the service should be started
1091  * @param service the name of the service to start
1092  * @param timeout how long to wait for process for startup
1093  * @param cb function called once gnunet-arm returns
1094  * @param cb_cls closure for cb
1095  */
1096 void
1097 GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d,
1098                                      char *service,
1099                                      struct GNUNET_TIME_Relative timeout,
1100                                      GNUNET_TESTING_NotifyDaemonRunning cb,
1101                                      void *cb_cls)
1102 {
1103   char *arg;
1104
1105   d->cb = cb;
1106   d->cb_cls = cb_cls;
1107
1108   GNUNET_assert (service != NULL);
1109   GNUNET_assert (d->running == GNUNET_YES);
1110   GNUNET_assert (d->phase == SP_START_DONE);
1111
1112 #if DEBUG_TESTING
1113   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1114               _("Starting service %s for peer `%4s'\n"), service,
1115               GNUNET_i2s (&d->id));
1116 #endif
1117
1118   d->phase = SP_SERVICE_START;
1119   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1120   /* Check if this is a local or remote process */
1121   if (NULL != d->hostname)
1122   {
1123 #if DEBUG_TESTING
1124     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1125                 "Starting gnunet-arm with config `%s' on host `%s'.\n",
1126                 d->cfgfile, d->hostname);
1127 #endif
1128
1129     if (d->username != NULL)
1130       GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
1131     else
1132       arg = GNUNET_strdup (d->hostname);
1133
1134     d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
1135 #if !DEBUG_TESTING
1136                                        "-q",
1137 #endif
1138                                        arg, "gnunet-arm",
1139 #if DEBUG_TESTING
1140                                        "-L", "DEBUG",
1141 #endif
1142                                        "-c", d->cfgfile, "-i", service, "-q",
1143                                        "-T",
1144                                        GNUNET_TIME_relative_to_string (timeout),
1145                                        NULL);
1146     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1147                 "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q -T %s\n",
1148                 arg, "gnunet-arm", d->cfgfile, service,
1149                 GNUNET_TIME_relative_to_string (timeout));
1150     GNUNET_free (arg);
1151   }
1152   else
1153   {
1154 #if DEBUG_TESTING
1155     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1156                 "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
1157 #endif
1158     d->proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm",
1159 #if DEBUG_TESTING
1160                                        "-L", "DEBUG",
1161 #endif
1162                                        "-c", d->cfgfile, "-i", service, "-q",
1163                                        "-T",
1164                                        GNUNET_TIME_relative_to_string (timeout),
1165                                        NULL);
1166     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1167                 "Starting gnunet-arm with command %s -c %s -i %s -q -T %s\n",
1168                 "gnunet-arm", d->cfgfile, service,
1169                 GNUNET_TIME_relative_to_string (timeout));
1170   }
1171
1172   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1173   d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
1174 }
1175
1176 /**
1177  * Start a peer that has previously been stopped using the daemon_stop
1178  * call (and files weren't deleted and the allow restart flag)
1179  *
1180  * @param daemon the daemon to start (has been previously stopped)
1181  * @param timeout how long to wait for restart
1182  * @param cb the callback for notification when the peer is running
1183  * @param cb_cls closure for the callback
1184  */
1185 void
1186 GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon,
1187                                      struct GNUNET_TIME_Relative timeout,
1188                                      GNUNET_TESTING_NotifyDaemonRunning cb,
1189                                      void *cb_cls)
1190 {
1191   if (daemon->running == GNUNET_YES)
1192   {
1193     cb (cb_cls, &daemon->id, daemon->cfg, daemon,
1194         "Daemon already running, can't restart!");
1195     return;
1196   }
1197
1198   daemon->cb = cb;
1199   daemon->cb_cls = cb_cls;
1200   daemon->phase = SP_TOPOLOGY_SETUP;
1201   daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1202
1203   GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon,
1204                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1205 }
1206
1207 /**
1208  * Starts a GNUnet daemon.  GNUnet must be installed on the target
1209  * system and available in the PATH.  The machine must furthermore be
1210  * reachable via "ssh" (unless the hostname is "NULL") without the
1211  * need to enter a password.
1212  *
1213  * @param cfg configuration to use
1214  * @param timeout how long to wait starting up peers
1215  * @param pretend GNUNET_YES to set up files but not start peer GNUNET_NO
1216  *                to really start the peer (default)
1217  * @param hostname name of the machine where to run GNUnet
1218  *        (use NULL for localhost).
1219  * @param ssh_username ssh username to use when connecting to hostname
1220  * @param sshport port to pass to ssh process when connecting to hostname
1221  * @param hostkey pointer to a hostkey to be written to disk (instead of being generated)
1222  * @param hostkey_callback function to call once the hostkey has been
1223  *        generated for this peer, but it hasn't yet been started
1224  *        (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
1225  * @param hostkey_cls closure for hostkey callback
1226  * @param cb function to call once peer is up, or failed to start
1227  * @param cb_cls closure for cb
1228  * @return handle to the daemon (actual start will be completed asynchronously)
1229  */
1230 struct GNUNET_TESTING_Daemon *
1231 GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
1232                              struct GNUNET_TIME_Relative timeout, int pretend,
1233                              const char *hostname, const char *ssh_username,
1234                              uint16_t sshport, const char *hostkey,
1235                              GNUNET_TESTING_NotifyHostkeyCreated
1236                              hostkey_callback, void *hostkey_cls,
1237                              GNUNET_TESTING_NotifyDaemonRunning cb,
1238                              void *cb_cls)
1239 {
1240   struct GNUNET_TESTING_Daemon *ret;
1241   char *arg;
1242   char *username;
1243   char *servicehome;
1244   char *baseservicehome;
1245   char *slash;
1246   char *hostkeyfile;
1247   char *temp_file_name;
1248   struct GNUNET_DISK_FileHandle *fn;
1249   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
1250   struct GNUNET_CRYPTO_RsaPrivateKey *private_key;
1251
1252   ret = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Daemon));
1253   ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname);
1254   if (sshport != 0)
1255   {
1256     GNUNET_asprintf (&ret->ssh_port_str, "%d", sshport);
1257   }
1258   else
1259     ret->ssh_port_str = NULL;
1260
1261   /* Find service home and base service home directories, create it if it doesn't exist */
1262   GNUNET_assert (GNUNET_OK ==
1263                  GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
1264                                                         "SERVICEHOME",
1265                                                         &servicehome));
1266
1267   GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_create (servicehome));
1268   GNUNET_asprintf (&temp_file_name, "%s/gnunet-testing-config", servicehome);
1269   ret->cfgfile = GNUNET_DISK_mktemp (temp_file_name);
1270   GNUNET_free (temp_file_name);
1271 #if DEBUG_TESTING
1272   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1273               "Setting up peer with configuration file `%s'.\n", ret->cfgfile);
1274 #endif
1275   if (NULL == ret->cfgfile)
1276   {
1277     GNUNET_free_non_null (ret->ssh_port_str);
1278     GNUNET_free_non_null (ret->hostname);
1279     GNUNET_free (ret);
1280     return NULL;
1281   }
1282   ret->hostkey_callback = hostkey_callback;
1283   ret->hostkey_cls = hostkey_cls;
1284   ret->cb = cb;
1285   ret->cb_cls = cb_cls;
1286   ret->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1287   ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
1288   GNUNET_CONFIGURATION_set_value_string (ret->cfg, "PATHS", "DEFAULTCONFIG",
1289                                          ret->cfgfile);
1290
1291   if (hostkey != NULL)          /* Get the peer identity from the hostkey */
1292   {
1293     private_key = GNUNET_CRYPTO_rsa_decode_key (hostkey, HOSTKEYFILESIZE);
1294     GNUNET_assert (private_key != NULL);
1295     GNUNET_CRYPTO_rsa_key_get_public (private_key, &public_key);
1296     GNUNET_CRYPTO_hash (&public_key,
1297                         sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
1298                         &ret->id.hashPubKey);
1299     ret->shortname = GNUNET_strdup (GNUNET_i2s (&ret->id));
1300     ret->have_hostkey = GNUNET_YES;
1301     GNUNET_CRYPTO_rsa_key_free (private_key);
1302   }
1303
1304   /* Write hostkey to file, if we were given one */
1305   hostkeyfile = NULL;
1306   if (hostkey != NULL)
1307   {
1308     GNUNET_asprintf (&hostkeyfile, "%s/.hostkey", servicehome);
1309     fn = GNUNET_DISK_file_open (hostkeyfile,
1310                                 GNUNET_DISK_OPEN_READWRITE |
1311                                 GNUNET_DISK_OPEN_CREATE,
1312                                 GNUNET_DISK_PERM_USER_READ |
1313                                 GNUNET_DISK_PERM_USER_WRITE);
1314     GNUNET_assert (fn != NULL);
1315     GNUNET_assert (HOSTKEYFILESIZE ==
1316                    GNUNET_DISK_file_write (fn, hostkey, HOSTKEYFILESIZE));
1317     GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fn));
1318   }
1319
1320   /* write configuration to temporary file */
1321   if (GNUNET_OK != GNUNET_CONFIGURATION_write (ret->cfg, ret->cfgfile))
1322   {
1323     if (0 != UNLINK (ret->cfgfile))
1324       GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
1325                                 ret->cfgfile);
1326     GNUNET_CONFIGURATION_destroy (ret->cfg);
1327     GNUNET_free_non_null (ret->hostname);
1328     GNUNET_free (ret->cfgfile);
1329     GNUNET_free (ret);
1330     return NULL;
1331   }
1332   if (ssh_username != NULL)
1333     username = GNUNET_strdup (ssh_username);
1334   if ((ssh_username == NULL) &&
1335       (GNUNET_OK !=
1336        GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "USERNAME",
1337                                               &username)))
1338   {
1339     if (NULL != getenv ("USER"))
1340       username = GNUNET_strdup (getenv ("USER"));
1341     else
1342       username = NULL;
1343   }
1344   ret->username = username;
1345
1346   if (GNUNET_NO == pretend)     /* Copy files, enter finite state machine */
1347   {
1348     /* copy directory to remote host */
1349     if (NULL != hostname)
1350     {
1351 #if DEBUG_TESTING
1352       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1353                   "Copying configuration directory to host `%s'.\n", hostname);
1354 #endif
1355       baseservicehome = GNUNET_strdup (servicehome);
1356       /* Remove trailing /'s */
1357       while (baseservicehome[strlen (baseservicehome) - 1] == '/')
1358         baseservicehome[strlen (baseservicehome) - 1] = '\0';
1359       /* Find next directory /, jump one ahead */
1360       slash = strrchr (baseservicehome, '/');
1361       if (slash != NULL)
1362         *(++slash) = '\0';
1363
1364       ret->phase = SP_COPYING;
1365       if (NULL != username)
1366         GNUNET_asprintf (&arg, "%s@%s:%s", username, hostname, baseservicehome);
1367       else
1368         GNUNET_asprintf (&arg, "%s:%s", hostname, baseservicehome);
1369       GNUNET_free (baseservicehome);
1370       if (ret->ssh_port_str == NULL)
1371       {
1372         ret->proc = GNUNET_OS_start_process (NULL, NULL, "scp", "scp", "-r",
1373 #if !DEBUG_TESTING
1374                                              "-q",
1375 #endif
1376                                              servicehome, arg, NULL);
1377 #if DEBUG_TESTING
1378         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1379                     "copying directory with command scp -r %s %s\n",
1380                     servicehome, arg);
1381 #endif
1382       }
1383       else
1384       {
1385         ret->proc =
1386             GNUNET_OS_start_process (NULL, NULL, "scp", "scp", "-r", "-P",
1387                                      ret->ssh_port_str,
1388 #if !DEBUG_TESTING
1389                                      "-q",
1390 #endif
1391                                      servicehome, arg, NULL);
1392       }
1393       GNUNET_free (arg);
1394       if (NULL == ret->proc)
1395       {
1396         GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1397                     _
1398                     ("Could not start `%s' process to copy configuration directory.\n"),
1399                     "scp");
1400         if (0 != UNLINK (ret->cfgfile))
1401           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
1402                                     ret->cfgfile);
1403         GNUNET_CONFIGURATION_destroy (ret->cfg);
1404         GNUNET_free_non_null (ret->hostname);
1405         GNUNET_free_non_null (ret->username);
1406         GNUNET_free (ret->cfgfile);
1407         GNUNET_free (ret);
1408         if ((hostkey != NULL) && (0 != UNLINK (hostkeyfile)))
1409           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
1410                                     hostkeyfile);
1411         GNUNET_free_non_null (hostkeyfile);
1412         GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (servicehome));
1413         GNUNET_free (servicehome);
1414         return NULL;
1415       }
1416
1417       ret->task =
1418           GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
1419                                         ret);
1420       GNUNET_free_non_null (hostkeyfile);
1421       GNUNET_free (servicehome);
1422       return ret;
1423     }
1424 #if DEBUG_TESTING
1425     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1426                 "No need to copy configuration file since we are running locally.\n");
1427 #endif
1428     ret->phase = SP_COPIED;
1429     GNUNET_SCHEDULER_add_continuation (&start_fsm, ret,
1430                                        GNUNET_SCHEDULER_REASON_PREREQ_DONE);
1431   }
1432   GNUNET_free_non_null (hostkeyfile);
1433   GNUNET_free (servicehome);
1434   return ret;
1435 }
1436
1437
1438 /**
1439  * Restart (stop and start) a GNUnet daemon.
1440  *
1441  * @param d the daemon that should be restarted
1442  * @param cb function called once the daemon is (re)started
1443  * @param cb_cls closure for cb
1444  */
1445 void
1446 GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
1447                                GNUNET_TESTING_NotifyDaemonRunning cb,
1448                                void *cb_cls)
1449 {
1450   char *arg;
1451   char *del_arg;
1452
1453   del_arg = NULL;
1454   if (NULL != d->cb)
1455   {
1456     d->dead = GNUNET_YES;
1457     return;
1458   }
1459
1460   d->cb = cb;
1461   d->cb_cls = cb_cls;
1462
1463   if (d->phase == SP_CONFIG_UPDATE)
1464   {
1465     GNUNET_SCHEDULER_cancel (d->task);
1466     d->phase = SP_START_DONE;
1467   }
1468   if (d->server != NULL)
1469   {
1470     GNUNET_CORE_disconnect (d->server);
1471     d->server = NULL;
1472   }
1473
1474   if (d->th != NULL)
1475   {
1476     GNUNET_TRANSPORT_get_hello_cancel (d->th, &process_hello, d);
1477     GNUNET_TRANSPORT_disconnect (d->th);
1478     d->th = NULL;
1479   }
1480   /* state clean up and notifications */
1481   GNUNET_free_non_null (d->hello);
1482
1483 #if DEBUG_TESTING
1484   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
1485               GNUNET_i2s (&d->id));
1486 #endif
1487
1488   d->phase = SP_START_ARMING;
1489
1490   /* Check if this is a local or remote process */
1491   if (NULL != d->hostname)
1492   {
1493 #if DEBUG_TESTING
1494     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1495                 "Stopping gnunet-arm with config `%s' on host `%s'.\n",
1496                 d->cfgfile, d->hostname);
1497 #endif
1498
1499     if (d->username != NULL)
1500       GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
1501     else
1502       arg = GNUNET_strdup (d->hostname);
1503
1504     d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
1505 #if !DEBUG_TESTING
1506                                        "-q",
1507 #endif
1508                                        arg, "gnunet-arm",
1509 #if DEBUG_TESTING
1510                                        "-L", "DEBUG",
1511 #endif
1512                                        "-c", d->cfgfile, "-e", "-r", NULL);
1513     /* Use -r to restart arm and all services */
1514
1515     GNUNET_free (arg);
1516   }
1517   else
1518   {
1519 #if DEBUG_TESTING
1520     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1521                 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
1522 #endif
1523     d->proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm",
1524 #if DEBUG_TESTING
1525                                        "-L", "DEBUG",
1526 #endif
1527                                        "-c", d->cfgfile, "-e", "-r", NULL);
1528   }
1529
1530   GNUNET_free_non_null (del_arg);
1531   d->task =
1532       GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
1533
1534 }
1535
1536
1537 /**
1538  * Stops a GNUnet daemon.
1539  *
1540  * @param d the daemon that should be stopped
1541  * @param service the name of the service to stop
1542  * @param timeout how long to wait for process for shutdown to complete
1543  * @param cb function called once the daemon was stopped
1544  * @param cb_cls closure for cb
1545  * @param delete_files GNUNET_YES to remove files, GNUNET_NO
1546  *        to leave them
1547  * @param allow_restart GNUNET_YES to restart peer later (using this API)
1548  *        GNUNET_NO to kill off and clean up for good
1549  */
1550 void
1551 GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d,
1552                                     char *service,
1553                                     struct GNUNET_TIME_Relative timeout,
1554                                     GNUNET_TESTING_NotifyCompletion cb,
1555                                     void *cb_cls)
1556 {
1557   char *arg;
1558
1559   d->dead_cb = cb;
1560   d->dead_cb_cls = cb_cls;
1561
1562   GNUNET_assert (d->running == GNUNET_YES);
1563
1564   if (d->phase == SP_CONFIG_UPDATE)
1565   {
1566     GNUNET_SCHEDULER_cancel (d->task);
1567     d->phase = SP_START_DONE;
1568   }
1569
1570 #if DEBUG_TESTING
1571   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
1572               GNUNET_i2s (&d->id));
1573 #endif
1574   if (d->churned_services != NULL)
1575   {
1576     d->dead_cb (d->dead_cb_cls, "A service has already been turned off!!");
1577     return;
1578   }
1579   d->phase = SP_SERVICE_SHUTDOWN_START;
1580   d->churned_services = GNUNET_strdup (service);
1581   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1582   /* Check if this is a local or remote process */
1583   if (NULL != d->hostname)
1584   {
1585 #if DEBUG_TESTING
1586     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1587                 "Stopping gnunet-arm with config `%s' on host `%s'.\n",
1588                 d->cfgfile, d->hostname);
1589 #endif
1590
1591     if (d->username != NULL)
1592       GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
1593     else
1594       arg = GNUNET_strdup (d->hostname);
1595
1596     d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
1597 #if !DEBUG_TESTING
1598                                        "-q",
1599 #endif
1600                                        arg, "gnunet-arm",
1601 #if DEBUG_TESTING
1602                                        "-L", "DEBUG",
1603 #endif
1604                                        "-c", d->cfgfile, "-k", service, "-q",
1605                                        "-T",
1606                                        GNUNET_TIME_relative_to_string (timeout),
1607                                        NULL);
1608     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1609                 "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -k %s -q\n",
1610                 arg, "gnunet-arm", d->cfgfile, service);
1611     GNUNET_free (arg);
1612   }
1613   else
1614   {
1615 #if DEBUG_TESTING
1616     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1617                 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
1618 #endif
1619     d->proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm",
1620 #if DEBUG_TESTING
1621                                        "-L", "DEBUG",
1622 #endif
1623                                        "-c", d->cfgfile, "-k", service, "-q",
1624                                        "-T",
1625                                        GNUNET_TIME_relative_to_string (timeout),
1626                                        NULL);
1627   }
1628
1629   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1630   d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
1631 }
1632
1633
1634 /**
1635  * Stops a GNUnet daemon.
1636  *
1637  * @param d the daemon that should be stopped
1638  * @param timeout how long to wait for process for shutdown to complete
1639  * @param cb function called once the daemon was stopped
1640  * @param cb_cls closure for cb
1641  * @param delete_files GNUNET_YES to remove files, GNUNET_NO
1642  *        to leave them
1643  * @param allow_restart GNUNET_YES to restart peer later (using this API)
1644  *        GNUNET_NO to kill off and clean up for good
1645  */
1646 void
1647 GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
1648                             struct GNUNET_TIME_Relative timeout,
1649                             GNUNET_TESTING_NotifyCompletion cb, void *cb_cls,
1650                             int delete_files, int allow_restart)
1651 {
1652   char *arg;
1653   char *del_arg;
1654
1655   d->dead_cb = cb;
1656   d->dead_cb_cls = cb_cls;
1657
1658   if (NULL != d->cb)
1659   {
1660 #if DEBUG_TESTING
1661     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Setting d->dead on peer `%4s'\n"),
1662                 GNUNET_i2s (&d->id));
1663 #endif
1664     d->dead = GNUNET_YES;
1665     return;
1666   }
1667
1668   if ((d->running == GNUNET_NO) && (d->churn == GNUNET_YES))    /* Peer has already been stopped in churn context! */
1669   {
1670     /* Free what was left from churning! */
1671     GNUNET_assert (d->cfg != NULL);
1672     GNUNET_CONFIGURATION_destroy (d->cfg);
1673     if (delete_files == GNUNET_YES)
1674     {
1675       if (0 != UNLINK (d->cfgfile))
1676       {
1677         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "unlink");
1678       }
1679     }
1680     GNUNET_free (d->cfgfile);
1681     GNUNET_free_non_null (d->hostname);
1682     GNUNET_free_non_null (d->username);
1683     if (NULL != d->dead_cb)
1684       d->dead_cb (d->dead_cb_cls, NULL);
1685     GNUNET_free (d);
1686     return;
1687   }
1688
1689   del_arg = NULL;
1690   if (delete_files == GNUNET_YES)
1691   {
1692     GNUNET_asprintf (&del_arg, "-d");
1693   }
1694
1695   if (d->phase == SP_CONFIG_UPDATE)
1696   {
1697     GNUNET_SCHEDULER_cancel (d->task);
1698     d->phase = SP_START_DONE;
1699   }
1700   /** Move this call to scheduled shutdown as fix for CORE_connect calling daemon_stop?
1701   if (d->server != NULL)
1702     {
1703       GNUNET_CORE_disconnect (d->server);
1704       d->server = NULL;
1705     }
1706     */
1707   /* shutdown ARM process (will terminate others) */
1708 #if DEBUG_TESTING
1709   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
1710               GNUNET_i2s (&d->id));
1711 #endif
1712   d->phase = SP_SHUTDOWN_START;
1713   d->running = GNUNET_NO;
1714   if (allow_restart == GNUNET_YES)
1715     d->churn = GNUNET_YES;
1716   if (d->th != NULL)
1717   {
1718     GNUNET_TRANSPORT_get_hello_cancel (d->th, &process_hello, d);
1719     GNUNET_TRANSPORT_disconnect (d->th);
1720     d->th = NULL;
1721   }
1722   /* Check if this is a local or remote process */
1723   if (NULL != d->hostname)
1724   {
1725 #if DEBUG_TESTING
1726     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1727                 "Stopping gnunet-arm with config `%s' on host `%s'.\n",
1728                 d->cfgfile, d->hostname);
1729 #endif
1730
1731     if (d->username != NULL)
1732       GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
1733     else
1734       arg = GNUNET_strdup (d->hostname);
1735
1736     d->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh",
1737 #if !DEBUG_TESTING
1738                                        "-q",
1739 #endif
1740                                        arg, "gnunet-arm",
1741 #if DEBUG_TESTING
1742                                        "-L", "DEBUG",
1743 #endif
1744                                        "-c", d->cfgfile, "-e", "-q", "-T",
1745                                        GNUNET_TIME_relative_to_string (timeout),
1746                                        del_arg, NULL);
1747     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1748                 "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -e -q %s\n",
1749                 arg, "gnunet-arm", d->cfgfile, del_arg);
1750     /* Use -e to end arm, and -d to remove temp files */
1751     GNUNET_free (arg);
1752   }
1753   else
1754   {
1755 #if DEBUG_TESTING
1756     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1757                 "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
1758 #endif
1759     d->proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm", "gnunet-arm",
1760 #if DEBUG_TESTING
1761                                        "-L", "DEBUG",
1762 #endif
1763                                        "-c", d->cfgfile, "-e", "-q", "-T",
1764                                        GNUNET_TIME_relative_to_string (timeout),
1765                                        del_arg, NULL);
1766   }
1767
1768   GNUNET_free_non_null (del_arg);
1769   d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
1770   d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
1771 }
1772
1773
1774 /**
1775  * Changes the configuration of a GNUnet daemon.
1776  *
1777  * @param d the daemon that should be modified
1778  * @param cfg the new configuration for the daemon
1779  * @param cb function called once the configuration was changed
1780  * @param cb_cls closure for cb
1781  */
1782 void
1783 GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
1784                                    struct GNUNET_CONFIGURATION_Handle *cfg,
1785                                    GNUNET_TESTING_NotifyCompletion cb,
1786                                    void *cb_cls)
1787 {
1788   char *arg;
1789
1790   if (d->phase != SP_START_DONE)
1791   {
1792     if (NULL != cb)
1793       cb (cb_cls,
1794           _
1795           ("Peer not yet running, can not change configuration at this point."));
1796     return;
1797   }
1798
1799   /* 1) write configuration to temporary file */
1800   if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, d->cfgfile))
1801   {
1802     if (NULL != cb)
1803       cb (cb_cls, _("Failed to write new configuration to disk."));
1804     return;
1805   }
1806
1807   /* 2) copy file to remote host (if necessary) */
1808   if (NULL == d->hostname)
1809   {
1810     /* signal success */
1811     if (NULL != cb)
1812       cb (cb_cls, NULL);
1813     return;
1814   }
1815 #if DEBUG_TESTING
1816   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1817               "Copying updated configuration file to remote host `%s'.\n",
1818               d->hostname);
1819 #endif
1820   d->phase = SP_CONFIG_UPDATE;
1821   if (NULL != d->username)
1822     GNUNET_asprintf (&arg, "%s@%s:%s", d->username, d->hostname, d->cfgfile);
1823   else
1824     GNUNET_asprintf (&arg, "%s:%s", d->hostname, d->cfgfile);
1825   d->proc = GNUNET_OS_start_process (NULL, NULL, "scp", "scp",
1826 #if !DEBUG_TESTING
1827                                      "-q",
1828 #endif
1829                                      d->cfgfile, arg, NULL);
1830   GNUNET_free (arg);
1831   if (NULL == d->proc)
1832   {
1833     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1834                 _("Could not start `%s' process to copy configuration file.\n"),
1835                 "scp");
1836     if (NULL != cb)
1837       cb (cb_cls, _("Failed to copy new configuration to remote machine."));
1838     d->phase = SP_START_DONE;
1839     return;
1840   }
1841   d->update_cb = cb;
1842   d->update_cb_cls = cb_cls;
1843   d->task =
1844       GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
1845 }
1846
1847
1848 /**
1849  * Data kept for each pair of peers that we try
1850  * to connect.
1851  */
1852 struct ConnectContext
1853 {
1854   /**
1855    * Testing handle to the first daemon.
1856    */
1857   struct GNUNET_TESTING_Daemon *d1;
1858
1859   /**
1860    * Handle to core of first daemon (to check connect)
1861    */
1862   struct GNUNET_CORE_Handle *d1core;
1863
1864   /**
1865    * Have we actually connected to the core of the first daemon yet?
1866    */
1867   int d1core_ready;
1868
1869   /**
1870    * Testing handle to the second daemon.
1871    */
1872   struct GNUNET_TESTING_Daemon *d2;
1873
1874   /**
1875    * Handler for the request to core to connect to this peer.
1876    */
1877   struct GNUNET_CORE_PeerRequestHandle *connect_request_handle;
1878
1879   /**
1880    * Transport handle to the first daemon (to offer the HELLO of the second daemon to).
1881    */
1882   struct GNUNET_TRANSPORT_Handle *d1th;
1883
1884   /**
1885    * Function to call once we are done (or have timed out).
1886    */
1887   GNUNET_TESTING_NotifyConnection cb;
1888
1889   /**
1890    * Closure for "nb".
1891    */
1892   void *cb_cls;
1893
1894   /**
1895    * The relative timeout from whence this connect attempt was
1896    * started.  Allows for reconnect attempts.
1897    */
1898   struct GNUNET_TIME_Relative relative_timeout;
1899
1900   /**
1901    * Maximum number of connect attempts, will retry connection
1902    * this number of times on failures.
1903    */
1904   unsigned int connect_attempts;
1905
1906   /**
1907    * Hello timeout task
1908    */
1909   GNUNET_SCHEDULER_TaskIdentifier hello_send_task;
1910
1911   /**
1912    * Connect timeout task
1913    */
1914   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
1915
1916   /**
1917    * When should this operation be complete (or we must trigger
1918    * a timeout).
1919    */
1920   struct GNUNET_TIME_Relative timeout_hello;
1921
1922   /**
1923    * Was the connection attempt successful?
1924    */
1925   int connected;
1926
1927   /**
1928    * When connecting, do we need to send the HELLO?
1929    */
1930   int send_hello;
1931
1932   /**
1933    * The distance between the two connected peers
1934    */
1935   uint32_t distance;
1936 };
1937
1938
1939 /** Forward declaration **/
1940 static void
1941 reattempt_daemons_connect (void *cls,
1942                            const struct GNUNET_SCHEDULER_TaskContext *tc);
1943
1944
1945 /**
1946  * Notify callback about success or failure of the attempt
1947  * to connect the two peers
1948  *
1949  * @param cls our "struct ConnectContext" (freed)
1950  * @param tc reason tells us if we succeeded or failed
1951  */
1952 static void
1953 notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1954 {
1955   struct ConnectContext *ctx = cls;
1956
1957   ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1958   if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
1959   {
1960     GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
1961     ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
1962   }
1963
1964   if (ctx->connect_request_handle != NULL)
1965   {
1966     GNUNET_CORE_peer_request_connect_cancel (ctx->connect_request_handle);
1967     ctx->connect_request_handle = NULL;
1968   }
1969
1970   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
1971   {
1972     if (ctx->d1th != NULL)
1973       GNUNET_TRANSPORT_disconnect (ctx->d1th);
1974     ctx->d1th = NULL;
1975     if (ctx->d1core != NULL)
1976       GNUNET_CORE_disconnect (ctx->d1core);
1977 #if CONNECT_CORE2
1978     if (ctx->d2core != NULL)
1979       GNUNET_CORE_disconnect (ctx->d2core);
1980     ctx->d2core = NULL;
1981 #endif
1982     ctx->d1core = NULL;
1983     GNUNET_free (ctx);
1984     return;
1985   }
1986
1987   if (ctx->d1th != NULL)
1988     GNUNET_TRANSPORT_disconnect (ctx->d1th);
1989   ctx->d1th = NULL;
1990   if (ctx->d1core != NULL)
1991     GNUNET_CORE_disconnect (ctx->d1core);
1992   ctx->d1core = NULL;
1993
1994   if (ctx->connected == GNUNET_YES)
1995   {
1996     if (ctx->cb != NULL)
1997     {
1998       ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance,
1999                ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
2000     }
2001   }
2002   else if (ctx->connect_attempts > 0)
2003   {
2004     ctx->d1core_ready = GNUNET_NO;
2005 #if CONNECT_CORE2
2006     if (ctx->d2core != NULL)
2007     {
2008       GNUNET_CORE_disconnect (ctx->d2core);
2009       ctx->d2core = NULL;
2010     }
2011 #endif
2012     GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx);
2013     return;
2014   }
2015   else
2016   {
2017     if (ctx->cb != NULL)
2018     {
2019       ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2020                ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect"));
2021     }
2022   }
2023
2024   GNUNET_free (ctx);
2025 }
2026
2027
2028 /**
2029  * Success, connection is up.  Signal client our success.
2030  *
2031  * @param cls our "struct ConnectContext"
2032  * @param peer identity of the peer that has connected
2033  * @param atsi performance information
2034  *
2035  */
2036 static void
2037 connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
2038                 const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2039 {
2040   struct ConnectContext *ctx = cls;
2041
2042 #if DEBUG_TESTING
2043   GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Connected peer %s to peer %s\n",
2044               ctx->d1->shortname, GNUNET_i2s (peer));
2045 #endif
2046
2047   if (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))
2048   {
2049
2050     ctx->connected = GNUNET_YES;
2051     ctx->distance = 0;          /* FIXME: distance */
2052     if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
2053     {
2054       GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
2055       ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
2056     }
2057     GNUNET_SCHEDULER_cancel (ctx->timeout_task);
2058     ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
2059   }
2060 }
2061
2062 #if CONNECT_CORE2
2063 /**
2064  * Success, connection is up.  Signal client our success.
2065  *
2066  * @param cls our "struct ConnectContext"
2067  * @param peer identity of the peer that has connected
2068  * @param atsi performance information
2069  *
2070  */
2071 static void
2072 connect_notify_core2 (void *cls, const struct GNUNET_PeerIdentity *peer,
2073                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2074 {
2075   struct ConnectContext *ctx = cls;
2076
2077   if (memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)) == 0)
2078   {
2079     ctx->connected = GNUNET_YES;
2080     ctx->distance = 0;          /* FIXME: distance */
2081     GNUNET_SCHEDULER_cancel (ctx->timeout_task);
2082     ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
2083   }
2084
2085 }
2086 #endif
2087
2088 /**
2089  * Task called once a core connect request has been transmitted.
2090  *
2091  * @param cls struct ConnectContext
2092  * @param success was the request successful?
2093  */
2094 void
2095 core_connect_request_cont (void *cls, int success)
2096 {
2097   struct ConnectContext *ctx = cls;
2098
2099   ctx->connect_request_handle = NULL;
2100 }
2101
2102 static void
2103 send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2104 {
2105   struct ConnectContext *ctx = cls;
2106   struct GNUNET_MessageHeader *hello;
2107
2108   ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
2109   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
2110     return;
2111   if ((ctx->d1core_ready == GNUNET_YES) && (ctx->d2->hello != NULL) &&
2112       (NULL != GNUNET_HELLO_get_header (ctx->d2->hello)) &&
2113       (ctx->d1->phase == SP_START_DONE) && (ctx->d2->phase == SP_START_DONE))
2114   {
2115     hello = GNUNET_HELLO_get_header (ctx->d2->hello);
2116     GNUNET_assert (hello != NULL);
2117 #if DEBUG_TESTING
2118     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Offering hello of %s to %s\n",
2119                 ctx->d2->shortname, ctx->d1->shortname);
2120 #endif
2121     GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL);
2122     GNUNET_assert (ctx->d1core != NULL);
2123     ctx->connect_request_handle =
2124         GNUNET_CORE_peer_request_connect (ctx->d1core, &ctx->d2->id,
2125                                           &core_connect_request_cont, ctx);
2126
2127 #if DEBUG_TESTING
2128     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2129                 "Sending connect request to CORE of %s for peer %s\n",
2130                 GNUNET_i2s (&ctx->d1->id),
2131                 GNUNET_h2s (&ctx->d2->id.hashPubKey));
2132 #endif
2133     ctx->timeout_hello =
2134         GNUNET_TIME_relative_add (ctx->timeout_hello,
2135                                   GNUNET_TIME_relative_multiply
2136                                   (GNUNET_TIME_UNIT_MILLISECONDS, 500));
2137   }
2138   ctx->hello_send_task =
2139       GNUNET_SCHEDULER_add_delayed (ctx->timeout_hello, &send_hello, ctx);
2140 }
2141
2142 /**
2143  * Notify of a successful connection to the core service.
2144  *
2145  * @param cls a ConnectContext
2146  * @param server handle to the core service
2147  * @param my_identity the peer identity of this peer
2148  * @param publicKey the public key of the peer
2149  */
2150 void
2151 core_init_notify (void *cls, struct GNUNET_CORE_Handle *server,
2152                   const struct GNUNET_PeerIdentity *my_identity,
2153                   const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded
2154                   *publicKey)
2155 {
2156   struct ConnectContext *connect_ctx = cls;
2157
2158   connect_ctx->d1core_ready = GNUNET_YES;
2159
2160   if (connect_ctx->send_hello == GNUNET_NO)
2161   {
2162     connect_ctx->connect_request_handle =
2163         GNUNET_CORE_peer_request_connect (connect_ctx->d1core,
2164                                           &connect_ctx->d2->id,
2165                                           &core_connect_request_cont,
2166                                           connect_ctx);
2167     GNUNET_assert (connect_ctx->connect_request_handle != NULL);
2168 #if DEBUG_TESTING
2169     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2170                 "Sending connect request to CORE of %s for peer %s\n",
2171                 connect_ctx->d1->shortname, connect_ctx->d2->shortname);
2172 #endif
2173   }
2174
2175 }
2176
2177
2178 static void
2179 reattempt_daemons_connect (void *cls,
2180                            const struct GNUNET_SCHEDULER_TaskContext *tc)
2181 {
2182   struct ConnectContext *ctx = cls;
2183
2184   if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
2185   {
2186     GNUNET_free (ctx);
2187     return;
2188   }
2189 #if DEBUG_TESTING_RECONNECT
2190   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2191               "re-attempting connect of peer %s to peer %s\n",
2192               ctx->d1->shortname, ctx->d2->shortname);
2193 #endif
2194   ctx->connect_attempts--;
2195   GNUNET_assert (ctx->d1core == NULL);
2196   ctx->d1core_ready = GNUNET_NO;
2197   ctx->d1core =
2198       GNUNET_CORE_connect (ctx->d1->cfg, 1, ctx, &core_init_notify,
2199                            &connect_notify, NULL, NULL, NULL, GNUNET_NO, NULL,
2200                            GNUNET_NO, no_handlers);
2201   if (ctx->d1core == NULL)
2202   {
2203     if (NULL != ctx->cb)
2204       ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2205                ctx->d2->cfg, ctx->d1, ctx->d2,
2206                _("Failed to connect to core service of first peer!\n"));
2207     GNUNET_free (ctx);
2208     return;
2209   }
2210
2211   /* Don't know reason for initial connect failure, update the HELLO for the second peer */
2212   if (NULL != ctx->d2->hello)
2213   {
2214     GNUNET_free (ctx->d2->hello);
2215     ctx->d2->hello = NULL;
2216     if (NULL != ctx->d2->th)
2217     {
2218       GNUNET_TRANSPORT_get_hello_cancel (ctx->d2->th, &process_hello, ctx->d2);
2219       GNUNET_TRANSPORT_disconnect (ctx->d2->th);
2220     }
2221     ctx->d2->th =
2222         GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
2223                                   NULL);
2224     GNUNET_assert (ctx->d2->th != NULL);
2225     GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
2226   }
2227
2228   if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))
2229   {
2230     ctx->d2->th =
2231         GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
2232                                   NULL);
2233     if (ctx->d2->th == NULL)
2234     {
2235       GNUNET_CORE_disconnect (ctx->d1core);
2236       GNUNET_free (ctx);
2237       if (NULL != ctx->cb)
2238         ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2239                  ctx->d2->cfg, ctx->d1, ctx->d2,
2240                  _("Failed to connect to transport service!\n"));
2241       return;
2242     }
2243     GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
2244   }
2245
2246   if (ctx->send_hello == GNUNET_YES)
2247   {
2248     ctx->d1th =
2249         GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
2250                                   NULL, NULL);
2251     if (ctx->d1th == NULL)
2252     {
2253       GNUNET_CORE_disconnect (ctx->d1core);
2254       GNUNET_free (ctx);
2255       if (NULL != ctx->cb)
2256         ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2257                  ctx->d2->cfg, ctx->d1, ctx->d2,
2258                  _("Failed to connect to transport service!\n"));
2259       return;
2260     }
2261     ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
2262   }
2263   else
2264   {
2265     ctx->connect_request_handle =
2266         GNUNET_CORE_peer_request_connect (ctx->d1core, &ctx->d2->id,
2267                                           &core_connect_request_cont, ctx);
2268   }
2269   ctx->timeout_task =
2270       GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
2271                                     &notify_connect_result, ctx);
2272 }
2273
2274 /**
2275  * Iterator for currently known peers, to ensure
2276  * that we don't try to send duplicate connect
2277  * requests to core.
2278  *
2279  * @param cls our "struct ConnectContext"
2280  * @param peer identity of the peer that has connected,
2281  *        NULL when iteration has finished
2282  * @param atsi performance information
2283  *
2284  */
2285 static void
2286 core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer,
2287                         const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2288 {
2289   struct ConnectContext *ctx = cls;
2290
2291   if ((peer != NULL) &&
2292       (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))))
2293   {
2294     ctx->connected = GNUNET_YES;
2295     ctx->distance = 0;          /* FIXME: distance */
2296     return;
2297   }
2298   else if (peer == NULL)        /* End of iteration over peers */
2299   {
2300     if (ctx->connected == GNUNET_YES)
2301     {
2302       ctx->timeout_task =
2303           GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
2304       return;
2305     }
2306
2307     /* Peer not already connected, need to schedule connect request! */
2308     if (ctx->d1core == NULL)
2309     {
2310 #if DEBUG_TESTING
2311       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2312                   "Peers are NOT connected, connecting to core!\n");
2313 #endif
2314       ctx->d1core =
2315           GNUNET_CORE_connect (ctx->d1->cfg, 1, ctx, &core_init_notify,
2316                                &connect_notify, NULL, NULL, NULL, GNUNET_NO,
2317                                NULL, GNUNET_NO, no_handlers);
2318     }
2319
2320     if (ctx->d1core == NULL)
2321     {
2322       GNUNET_free (ctx);
2323       if (NULL != ctx->cb)
2324         ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2325                  ctx->d2->cfg, ctx->d1, ctx->d2,
2326                  _("Failed to connect to core service of first peer!\n"));
2327       return;
2328     }
2329
2330     if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))      /* Do not yet have the second peer's hello, set up a task to get it */
2331     {
2332       ctx->d2->th =
2333           GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL,
2334                                     NULL, NULL);
2335       if (ctx->d2->th == NULL)
2336       {
2337         GNUNET_CORE_disconnect (ctx->d1core);
2338         GNUNET_free (ctx);
2339         if (NULL != ctx->cb)
2340           ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2341                    ctx->d2->cfg, ctx->d1, ctx->d2,
2342                    _("Failed to connect to transport service!\n"));
2343         return;
2344       }
2345       GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
2346     }
2347
2348     if (ctx->send_hello == GNUNET_YES)
2349     {
2350       ctx->d1th =
2351           GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
2352                                     NULL, NULL);
2353       if (ctx->d1th == NULL)
2354       {
2355         GNUNET_CORE_disconnect (ctx->d1core);
2356         GNUNET_free (ctx);
2357         if (NULL != ctx->cb)
2358           ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
2359                    ctx->d2->cfg, ctx->d1, ctx->d2,
2360                    _("Failed to connect to transport service!\n"));
2361         return;
2362       }
2363       ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
2364     }
2365
2366     ctx->timeout_task =
2367         GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
2368                                       &notify_connect_result, ctx);
2369   }
2370 }
2371
2372
2373 /**
2374  * Establish a connection between two GNUnet daemons.
2375  *
2376  * @param d1 handle for the first daemon
2377  * @param d2 handle for the second daemon
2378  * @param timeout how long is the connection attempt
2379  *        allowed to take?
2380  * @param max_connect_attempts how many times should we try to reconnect
2381  *        (within timeout)
2382  * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
2383  *                   the HELLO has already been exchanged
2384  * @param cb function to call at the end
2385  * @param cb_cls closure for cb
2386  */
2387 void
2388 GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
2389                                 struct GNUNET_TESTING_Daemon *d2,
2390                                 struct GNUNET_TIME_Relative timeout,
2391                                 unsigned int max_connect_attempts,
2392                                 int send_hello,
2393                                 GNUNET_TESTING_NotifyConnection cb,
2394                                 void *cb_cls)
2395 {
2396   struct ConnectContext *ctx;
2397
2398   if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO))
2399   {
2400     if (NULL != cb)
2401       cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2,
2402           _("Peers are not fully running yet, can not connect!\n"));
2403     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n");
2404     return;
2405   }
2406
2407   ctx = GNUNET_malloc (sizeof (struct ConnectContext));
2408   ctx->d1 = d1;
2409   ctx->d2 = d2;
2410   ctx->timeout_hello =
2411       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
2412   ctx->relative_timeout =
2413       GNUNET_TIME_relative_divide (timeout, max_connect_attempts);
2414   ctx->cb = cb;
2415   ctx->cb_cls = cb_cls;
2416   ctx->connect_attempts = max_connect_attempts;
2417   ctx->connected = GNUNET_NO;
2418   ctx->send_hello = send_hello;
2419 #if DEBUG_TESTING
2420   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect peer %s to peer %s\n",
2421               d1->shortname, d2->shortname);
2422 #endif
2423
2424   /* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */
2425   GNUNET_assert (GNUNET_OK ==
2426                  GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id,
2427                                                 &core_initial_iteration, ctx));
2428   /*GNUNET_assert(GNUNET_OK == GNUNET_CORE_iterate_peers (ctx->d1->cfg, &core_initial_iteration, ctx)); */
2429 }
2430
2431 /* end of testing.c */