2 This file is part of GNUnet.
3 (C) 2009 Christian Grothoff (and other contributing authors)
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 2, or (at your
8 option) any later version.
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.
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.
21 * @file transport/test_transport_api_dv.c
22 * @brief base test case for dv transport (separated from other transport
23 * testcases for two reasons. 1) dv-service relies on core and other
24 * transport plugins, dv plugin relies on dv-service, so dv-plugin needs
25 * to live here, and 2) a dv plugin testcase is different from other
26 * tranport plugin testcases because we need at least three peer to test
29 * This test case tests DV functionality. Specifically it starts three
30 * peers connected in a line (1 <-> 2 <-> 3). Then a message is transmitted
31 * from peer 1 to peer 3. Assuming that DV is working, peer 2 should have
32 * gossiped about peer 3 to 1, and should then forward a message from one
36 #include "gnunet_common.h"
37 #include "gnunet_hello_lib.h"
38 #include "gnunet_getopt_lib.h"
39 #include "gnunet_os_lib.h"
40 #include "gnunet_program_lib.h"
41 #include "gnunet_scheduler_lib.h"
42 #include "gnunet_transport_service.h"
43 #include "../transport/transport.h"
45 #define VERBOSE GNUNET_YES
47 #define VERBOSE_ARM GNUNET_NO
49 #define START_ARM GNUNET_YES
52 * How long until we give up on transmitting the message?
54 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 50)
60 struct GNUNET_CONFIGURATION_Handle *cfg;
61 struct GNUNET_TRANSPORT_Handle *th;
62 struct GNUNET_PeerIdentity id;
64 const struct GNUNET_HELLO_Message *hello;
70 static struct PeerContext p1;
72 static struct PeerContext p2;
74 static struct PeerContext p3;
76 static struct GNUNET_SCHEDULER_Handle *sched;
80 GNUNET_SCHEDULER_TaskIdentifier die_task;
83 #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
85 #define OKPP do { ok++; } while (0)
93 GNUNET_SCHEDULER_cancel (sched, die_task);
94 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transport 1!\n");
95 GNUNET_TRANSPORT_disconnect (p1.th);
96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transport 2!\n");
97 GNUNET_TRANSPORT_disconnect (p2.th);
98 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transport 3!\n");
99 GNUNET_TRANSPORT_disconnect (p3.th);
101 die_task = GNUNET_SCHEDULER_NO_TASK;
102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Transports disconnected, returning success!\n");
107 stop_arm (struct PeerContext *p)
110 p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
115 "-c", p->cfg_file, "-e", "-q", NULL);
117 GNUNET_OS_process_wait (p->arm_pid);
119 GNUNET_CONFIGURATION_destroy (p->cfg);
124 restart_transport (struct PeerContext *p)
127 p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
132 "-c", p->cfg_file, "-k", "transport", "-q", NULL);
134 GNUNET_OS_process_wait (p->arm_pid);
138 p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
143 "-c", p->cfg_file, "-i", "transport", "-q", NULL);
145 GNUNET_OS_process_wait (p->arm_pid);
155 fprintf(stderr, "Ending on an unhappy note.\n");
158 GNUNET_TRANSPORT_disconnect (p1.th);
159 GNUNET_TRANSPORT_disconnect (p2.th);
160 GNUNET_TRANSPORT_disconnect (p3.th);
167 notify_receive (void *cls,
168 const struct GNUNET_PeerIdentity *peer,
169 const struct GNUNET_MessageHeader *message,
170 struct GNUNET_TIME_Relative latency,
174 if (ntohs(message->type) != MTYPE)
177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received message of type %d from peer (%p) distance %d!\n",
178 ntohs(message->type), cls, distance);
180 GNUNET_assert (MTYPE == ntohs (message->type));
181 GNUNET_assert (sizeof (struct GNUNET_MessageHeader) ==
182 ntohs (message->size));
188 notify_ready (void *cls, size_t size, void *buf)
190 struct GNUNET_MessageHeader *hdr;
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193 "Transmitting message to peer (%p) - %u!\n", cls, size);
194 GNUNET_assert (size >= 256);
199 hdr->size = htons (sizeof (struct GNUNET_MessageHeader));
200 hdr->type = htons (MTYPE);
203 return sizeof (struct GNUNET_MessageHeader);
208 notify_connect (void *cls,
209 const struct GNUNET_PeerIdentity *peer,
210 struct GNUNET_TIME_Relative latency,
215 struct PeerContext *from_peer = cls;
225 if (memcmp(peer, &p1.id, sizeof(struct GNUNET_PeerIdentity)) == 0)
227 else if (memcmp(peer, &p2.id, sizeof(struct GNUNET_PeerIdentity)) == 0)
229 else if (memcmp(peer, &p3.id, sizeof(struct GNUNET_PeerIdentity)) == 0)
232 if ((cls == &p1) && (memcmp(peer, &p3.id, sizeof(struct GNUNET_PeerIdentity)) == 0))
235 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
236 "Peer 1 notified about connection to peer 3, distance %u!\n", distance);
238 GNUNET_TRANSPORT_notify_transmit_ready (p1.th,
240 256, 0, TIMEOUT, ¬ify_ready,
243 GNUNET_asprintf(&from_peer_str, "%s", GNUNET_i2s(&from_peer->id));
244 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
245 "Peer `%d' %4s connected to peer `%d' %4s distance %d!\n", peer_num, from_peer_str, connect_num, GNUNET_i2s(peer), distance);
250 notify_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
252 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
253 "Peer `%4s' disconnected (%p)!\n",
254 GNUNET_i2s (peer), cls);
259 setup_peer (struct PeerContext *p, const char *cfgname)
261 p->cfg = GNUNET_CONFIGURATION_create ();
262 p->cfg_file = strdup(cfgname);
264 p->arm_pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-arm",
269 "-c", cfgname, "-s", "-q", NULL);
271 GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
276 exchange_hello_last (void *cls,
277 const struct GNUNET_MessageHeader *message)
279 struct PeerContext *me = cls;
281 GNUNET_TRANSPORT_get_hello_cancel (p3.th, &exchange_hello_last, me);
283 GNUNET_assert (message != NULL);
284 GNUNET_assert (GNUNET_OK ==
285 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
288 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
289 "Received HELLO size %d\n", GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
292 "Finished exchanging HELLOs, now waiting for transmission!\n");
298 exchange_hello_next (void *cls,
299 const struct GNUNET_MessageHeader *message)
301 struct PeerContext *me = cls;
303 GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_next, me);
304 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
305 "Exchanging HELLO with peer (%p)!\n", cls);
307 GNUNET_assert (message != NULL);
308 GNUNET_assert (GNUNET_OK ==
309 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
313 "Received HELLO size %d\n", GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
315 GNUNET_TRANSPORT_offer_hello (p3.th, message);
317 GNUNET_TRANSPORT_get_hello (p3.th, &exchange_hello_last, &p3);
324 exchange_hello (void *cls,
325 const struct GNUNET_MessageHeader *message)
327 struct PeerContext *me = cls;
329 GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, me);
330 p2.th = GNUNET_TRANSPORT_connect (sched, p2.cfg,
333 ¬ify_connect, ¬ify_disconnect);
335 GNUNET_assert(p2.th != NULL);
337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
338 "Exchanging HELLO with peer (%p)!\n", cls);
340 GNUNET_assert (message != NULL);
341 GNUNET_assert (GNUNET_OK ==
342 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
346 "Received HELLO size %d\n", GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message));
348 GNUNET_TRANSPORT_offer_hello (p2.th, message);
349 GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_next, &p2);
353 blacklist_setup_third (void *cls,
354 const struct GNUNET_MessageHeader *message)
356 struct PeerContext *me = cls;
357 char *blacklist_filename;
358 struct GNUNET_DISK_FileHandle *file;
359 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
363 GNUNET_TRANSPORT_get_hello_cancel (p3.th, &blacklist_setup_third, &p3);
365 GNUNET_assert (message != NULL);
366 GNUNET_assert (GNUNET_OK ==
367 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
370 GNUNET_asprintf(&blacklist_filename, "/tmp/test-gnunetd-transport-peer-1/blacklist");
371 if (blacklist_filename != NULL)
373 file = GNUNET_DISK_file_open(blacklist_filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE,
374 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
375 GNUNET_free(blacklist_filename);
379 GNUNET_SCHEDULER_cancel(sched, die_task);
380 GNUNET_SCHEDULER_add_now(sched, &end_badly, NULL);
383 GNUNET_CRYPTO_hash_to_enc(&me->id.hashPubKey, &peer_enc);
384 size = GNUNET_asprintf(&buf, "%s:%s\n", "tcp", (char *)&peer_enc);
385 GNUNET_DISK_file_write(file, buf, size);
386 GNUNET_free_non_null(buf);
389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
390 "Restarting transport service (%p) with gnunet-arm -c %s -L DEBUG -k transport!\n", cls, p1.cfg_file);
392 restart_transport(&p1);
394 p1.th = GNUNET_TRANSPORT_connect (sched, p1.cfg,
397 ¬ify_connect, ¬ify_disconnect);
399 GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
403 blacklist_setup_first (void *cls,
404 const struct GNUNET_MessageHeader *message)
406 struct PeerContext *me = cls;
407 char *blacklist_filename;
408 struct GNUNET_DISK_FileHandle *file;
409 struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
413 GNUNET_TRANSPORT_get_hello_cancel (p1.th, &blacklist_setup_first, me);
416 GNUNET_assert (message != NULL);
417 GNUNET_assert (GNUNET_OK ==
418 GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
421 GNUNET_asprintf(&blacklist_filename, "/tmp/test-gnunetd-transport-peer-3/blacklist");
422 if (blacklist_filename != NULL)
424 file = GNUNET_DISK_file_open(blacklist_filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_TRUNCATE | GNUNET_DISK_OPEN_CREATE,
425 GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
426 GNUNET_free(blacklist_filename);
430 GNUNET_SCHEDULER_cancel(sched, die_task);
431 GNUNET_SCHEDULER_add_now(sched, &end_badly, NULL);
434 GNUNET_CRYPTO_hash_to_enc(&me->id.hashPubKey, &peer_enc);
435 size = GNUNET_asprintf(&buf, "%s:%s\n", "tcp", (char *)&peer_enc);
436 GNUNET_DISK_file_write(file, buf, size);
437 GNUNET_free_non_null(buf);
440 GNUNET_TRANSPORT_disconnect(p1.th);
442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
443 "Restarting transport service (%p) with gnunet-arm -c %s -L DEBUG -k transport!\n", cls, p3.cfg_file);
444 restart_transport(&p3);
446 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
447 "reconnecting to transport (%p)!\n", cls);
448 p3.th = GNUNET_TRANSPORT_connect (sched, p3.cfg,
451 ¬ify_connect, ¬ify_disconnect);
453 GNUNET_TRANSPORT_get_hello (p3.th, &blacklist_setup_third, &p3);
455 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
456 "reconnecting to transport (%p) failed.!\n", cls);
457 //GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
463 struct GNUNET_SCHEDULER_Handle *s,
465 const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
467 GNUNET_assert (ok == 1);
471 die_task = GNUNET_SCHEDULER_add_delayed (sched,
472 GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5), &end_badly, NULL);
474 setup_peer (&p1, "test_transport_api_dv_peer1.conf");
475 setup_peer (&p2, "test_transport_api_dv_peer2.conf");
476 setup_peer (&p3, "test_transport_api_dv_peer3.conf");
478 p1.th = GNUNET_TRANSPORT_connect (sched, p1.cfg,
481 ¬ify_connect, ¬ify_disconnect);
482 GNUNET_assert(p1.th != NULL);
483 /*GNUNET_assert(p2.th != NULL);
484 GNUNET_assert(p3.th != NULL);*/
486 GNUNET_TRANSPORT_get_hello (p1.th, &blacklist_setup_first, &p1);
493 char *const argv[] = { "test-transport-api",
495 "test_transport_api_data.conf",
502 struct GNUNET_GETOPT_CommandLineOption options[] = {
503 GNUNET_GETOPT_OPTION_END
507 GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
508 argv, "test-transport-api", "nohelp",
518 main (int argc, char *argv[])
522 return GNUNET_SYSERR;
525 GNUNET_log_setup ("test-transport-api-dv",
533 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-1");
534 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-2");
535 GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-transport-peer-3");
539 /* end of test_transport_api_dv.c */