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