test_gnunet_daemon_hostlist_learning.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576
  1. /*
  2. This file is part of GNUnet
  3. (C) 2009, 2010, 2011 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file hostlist/test_gnunet_daemon_hostlist.c
  19. * @brief test for gnunet_daemon_hostslist.c
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_arm_service.h"
  25. #include "gnunet_core_service.h"
  26. #include "gnunet_transport_service.h"
  27. #include "gnunet_resolver_service.h"
  28. #include "gnunet_statistics_service.h"
  29. #define VERBOSE GNUNET_NO
  30. #define START_ARM GNUNET_YES
  31. #define MAX_URL_LEN 1000
  32. /**
  33. * How long until wait until testcases fails
  34. */
  35. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 180)
  36. #define CHECK_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
  37. struct PeerContext
  38. {
  39. struct GNUNET_CONFIGURATION_Handle *cfg;
  40. struct GNUNET_TRANSPORT_Handle *th;
  41. struct GNUNET_MessageHeader *hello;
  42. struct GNUNET_CORE_Handle *core;
  43. struct GNUNET_STATISTICS_Handle *stats;
  44. #if START_ARM
  45. struct GNUNET_OS_Process *arm_proc;
  46. #endif
  47. };
  48. static int timeout;
  49. static int adv_sent;
  50. static int adv_arrived;
  51. static int learned_hostlist_saved;
  52. static int learned_hostlist_downloaded;
  53. static char * current_adv_uri;
  54. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  55. static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
  56. static GNUNET_SCHEDULER_TaskIdentifier check_task;
  57. static struct PeerContext adv_peer;
  58. static struct PeerContext learn_peer;
  59. static struct GNUNET_STATISTICS_GetHandle * download_stats;
  60. static struct GNUNET_STATISTICS_GetHandle * urisrecv_stat;
  61. static struct GNUNET_STATISTICS_GetHandle * advsent_stat;
  62. static void
  63. shutdown_testcase()
  64. {
  65. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  66. "Shutdown testcase....\n");
  67. if (timeout_task != GNUNET_SCHEDULER_NO_TASK)
  68. {
  69. GNUNET_SCHEDULER_cancel (timeout_task);
  70. timeout_task = GNUNET_SCHEDULER_NO_TASK;
  71. }
  72. if (NULL != download_stats)
  73. {
  74. GNUNET_STATISTICS_get_cancel (download_stats);
  75. download_stats = NULL;
  76. }
  77. if (NULL != urisrecv_stat)
  78. {
  79. GNUNET_STATISTICS_get_cancel (urisrecv_stat);
  80. urisrecv_stat = NULL;
  81. }
  82. if (NULL != advsent_stat)
  83. {
  84. GNUNET_STATISTICS_get_cancel (advsent_stat);
  85. advsent_stat = NULL;
  86. }
  87. if (check_task != GNUNET_SCHEDULER_NO_TASK)
  88. {
  89. GNUNET_SCHEDULER_cancel (check_task);
  90. check_task = GNUNET_SCHEDULER_NO_TASK;
  91. }
  92. if (NULL != current_adv_uri)
  93. {
  94. GNUNET_free (current_adv_uri);
  95. current_adv_uri = NULL;
  96. }
  97. if (adv_peer.th != NULL)
  98. {
  99. GNUNET_TRANSPORT_disconnect (adv_peer.th);
  100. adv_peer.th = NULL;
  101. }
  102. if (learn_peer.th != NULL)
  103. {
  104. GNUNET_TRANSPORT_disconnect (learn_peer.th);
  105. learn_peer.th = NULL;
  106. }
  107. if (adv_peer.core != NULL)
  108. {
  109. GNUNET_CORE_disconnect (adv_peer.core);
  110. adv_peer.core = NULL;
  111. }
  112. if (learn_peer.core != NULL)
  113. {
  114. GNUNET_CORE_disconnect (learn_peer.core);
  115. learn_peer.core = NULL;
  116. }
  117. #if START_ARM
  118. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  119. "Killing hostlist server ARM process.\n");
  120. if (0 != GNUNET_OS_process_kill (adv_peer.arm_proc, SIGTERM))
  121. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  122. "kill");
  123. if (GNUNET_OS_process_wait(adv_peer.arm_proc) != GNUNET_OK)
  124. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  125. "waitpid");
  126. GNUNET_OS_process_close (adv_peer.arm_proc);
  127. adv_peer.arm_proc = NULL;
  128. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  129. "Killing hostlist client ARM process.\n");
  130. if (0 != GNUNET_OS_process_kill (learn_peer.arm_proc, SIGTERM))
  131. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  132. "kill");
  133. if (GNUNET_OS_process_wait(learn_peer.arm_proc) != GNUNET_OK)
  134. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
  135. "waitpid");
  136. GNUNET_OS_process_close (learn_peer.arm_proc);
  137. learn_peer.arm_proc = NULL;
  138. #endif
  139. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  140. "Shutdown complete....\n");
  141. }
  142. /**
  143. * Timeout, give up.
  144. */
  145. static void
  146. timeout_error (void *cls,
  147. const struct GNUNET_SCHEDULER_TaskContext *tc)
  148. {
  149. timeout_task = GNUNET_SCHEDULER_NO_TASK;
  150. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  151. "Timeout while executing testcase, test failed.\n");
  152. timeout = GNUNET_YES;
  153. shutdown_testcase();
  154. }
  155. static void
  156. process_downloads_done (void *cls, int success)
  157. {
  158. download_stats = NULL;
  159. }
  160. static int
  161. process_downloads (void *cls,
  162. const char *subsystem,
  163. const char *name,
  164. uint64_t value,
  165. int is_persistent)
  166. {
  167. if ( (value >= 2) &&
  168. (learned_hostlist_downloaded == GNUNET_NO) )
  169. {
  170. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  171. "Peer has successfully downloaded advertised URI\n");
  172. learned_hostlist_downloaded = GNUNET_YES;
  173. if ( (learned_hostlist_saved == GNUNET_YES) &&
  174. (adv_sent == GNUNET_YES) )
  175. shutdown_testcase();
  176. }
  177. return GNUNET_OK;
  178. }
  179. static void
  180. process_uris_recv_done (void *cls, int success)
  181. {
  182. urisrecv_stat = NULL;
  183. }
  184. static int
  185. process_uris_recv (void *cls,
  186. const char *subsystem,
  187. const char *name,
  188. uint64_t value,
  189. int is_persistent)
  190. {
  191. if ( ((struct PeerContext *) cls == &learn_peer) &&
  192. (value == 1) &&
  193. (learned_hostlist_saved == GNUNET_NO) )
  194. {
  195. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  196. "Peer has successfully saved advertised URI\n");
  197. learned_hostlist_saved = GNUNET_YES;
  198. if ( (learned_hostlist_downloaded == GNUNET_YES) &&
  199. (adv_sent == GNUNET_YES) )
  200. shutdown_testcase();
  201. }
  202. return GNUNET_OK;
  203. }
  204. static void
  205. process_adv_sent_done (void *cls, int success)
  206. {
  207. advsent_stat = NULL;
  208. }
  209. static int
  210. process_adv_sent (void *cls,
  211. const char *subsystem,
  212. const char *name,
  213. uint64_t value,
  214. int is_persistent)
  215. {
  216. if ( (value >= 1) && (adv_sent == GNUNET_NO))
  217. {
  218. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  219. "Server has successfully sent advertisement\n");
  220. adv_sent = GNUNET_YES;
  221. if ( (learned_hostlist_downloaded == GNUNET_YES) &&
  222. (learned_hostlist_saved == GNUNET_YES) )
  223. shutdown_testcase();
  224. }
  225. return GNUNET_OK;
  226. }
  227. /**
  228. * Check the server statistics regularly
  229. */
  230. static void
  231. check_statistics (void *cls,
  232. const struct GNUNET_SCHEDULER_TaskContext *tc)
  233. {
  234. char *stat;
  235. check_task = GNUNET_SCHEDULER_NO_TASK;
  236. if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
  237. return;
  238. GNUNET_asprintf (&stat,
  239. gettext_noop("# advertised URI `%s' downloaded"),
  240. current_adv_uri);
  241. if (NULL != learn_peer.stats)
  242. {
  243. if (NULL != download_stats)
  244. GNUNET_STATISTICS_get_cancel (download_stats);
  245. download_stats = GNUNET_STATISTICS_get (learn_peer.stats,
  246. "hostlist",
  247. stat,
  248. GNUNET_TIME_UNIT_MINUTES,
  249. &process_downloads_done,
  250. &process_downloads,
  251. &learn_peer);
  252. if (NULL != urisrecv_stat)
  253. GNUNET_STATISTICS_get_cancel (urisrecv_stat);
  254. urisrecv_stat = GNUNET_STATISTICS_get (learn_peer.stats,
  255. "hostlist",
  256. gettext_noop("# advertised hostlist URIs"),
  257. GNUNET_TIME_UNIT_MINUTES,
  258. &process_uris_recv_done,
  259. &process_uris_recv,
  260. &learn_peer);
  261. }
  262. GNUNET_free (stat);
  263. if ( NULL != adv_peer.stats)
  264. {
  265. if (NULL != advsent_stat)
  266. GNUNET_STATISTICS_get_cancel (advsent_stat);
  267. advsent_stat = GNUNET_STATISTICS_get (adv_peer.stats,
  268. "hostlist",
  269. gettext_noop("# hostlist advertisements send"),
  270. GNUNET_TIME_UNIT_MINUTES,
  271. &process_adv_sent_done,
  272. &process_adv_sent,
  273. NULL);
  274. }
  275. check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL,
  276. &check_statistics,
  277. NULL);
  278. }
  279. /**
  280. * Core handler for p2p hostlist advertisements
  281. */
  282. static int
  283. ad_arrive_handler (void *cls,
  284. const struct GNUNET_PeerIdentity * peer,
  285. const struct GNUNET_MessageHeader * message,
  286. const struct GNUNET_TRANSPORT_ATS_Information *atsi)
  287. {
  288. char *hostname;
  289. char *expected_uri;
  290. unsigned long long port;
  291. const struct GNUNET_MessageHeader * incoming;
  292. const char *end;
  293. if (-1 == GNUNET_CONFIGURATION_get_value_number (adv_peer.cfg,
  294. "HOSTLIST",
  295. "HTTPPORT",
  296. &port))
  297. {
  298. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  299. "Could not read advertising server's configuration\n" );
  300. return GNUNET_SYSERR;
  301. }
  302. if ( GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string (adv_peer.cfg,
  303. "HOSTLIST",
  304. "EXTERNAL_DNS_NAME",
  305. &hostname))
  306. hostname = GNUNET_RESOLVER_local_fqdn_get ();
  307. GNUNET_asprintf (&expected_uri,
  308. "http://%s:%u/",
  309. hostname != NULL ? hostname : "localhost",
  310. (unsigned int) port);
  311. incoming = (const struct GNUNET_MessageHeader *) message;
  312. end = (const char*) &incoming[1];
  313. if ('\0' != end[ntohs(message->size) - sizeof (struct GNUNET_MessageHeader) - 1])
  314. {
  315. GNUNET_break (0);
  316. GNUNET_free (expected_uri);
  317. GNUNET_free_non_null (hostname);
  318. return GNUNET_SYSERR;
  319. }
  320. current_adv_uri = GNUNET_strdup (end);
  321. if ( 0 == strcmp( expected_uri, current_adv_uri ) )
  322. {
  323. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  324. "Received hostlist advertisement with URI `%s' as expected\n",
  325. current_adv_uri);
  326. adv_arrived = GNUNET_YES;
  327. adv_sent = GNUNET_YES;
  328. }
  329. else
  330. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  331. "Expected URI `%s' and recieved URI `%s' differ\n",
  332. expected_uri,
  333. current_adv_uri);
  334. GNUNET_free (expected_uri);
  335. GNUNET_free_non_null (hostname);
  336. return GNUNET_OK;
  337. }
  338. /**
  339. * List of handlers if we are learning.
  340. */
  341. static struct GNUNET_CORE_MessageHandler learn_handlers[] = {
  342. { &ad_arrive_handler, GNUNET_MESSAGE_TYPE_HOSTLIST_ADVERTISEMENT, 0},
  343. { NULL, 0, 0 }
  344. };
  345. static void
  346. setup_learn_peer (struct PeerContext *p,
  347. const char *cfgname)
  348. {
  349. char * filename;
  350. unsigned int result;
  351. p->cfg = GNUNET_CONFIGURATION_create ();
  352. #if START_ARM
  353. p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
  354. "gnunet-service-arm",
  355. #if VERBOSE
  356. "-L", "DEBUG",
  357. #endif
  358. "-c", cfgname, NULL);
  359. #endif
  360. GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
  361. if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (p->cfg,
  362. "HOSTLIST",
  363. "HOSTLISTFILE",
  364. &filename))
  365. {
  366. if (GNUNET_YES == GNUNET_DISK_file_test (filename))
  367. {
  368. result = UNLINK (filename);
  369. if (result == 0)
  370. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  371. _("Hostlist file `%s' was removed\n"),filename);
  372. }
  373. GNUNET_free (filename);
  374. }
  375. p->core = GNUNET_CORE_connect (p->cfg,
  376. 1,
  377. NULL,
  378. NULL,
  379. NULL, NULL, NULL,
  380. NULL, GNUNET_NO,
  381. NULL, GNUNET_NO,
  382. learn_handlers );
  383. GNUNET_assert ( NULL != p->core );
  384. p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg);
  385. GNUNET_assert ( NULL != p->stats );
  386. }
  387. static void
  388. setup_adv_peer (struct PeerContext *p,
  389. const char *cfgname)
  390. {
  391. p->cfg = GNUNET_CONFIGURATION_create ();
  392. #if START_ARM
  393. p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
  394. "gnunet-service-arm",
  395. #if VERBOSE
  396. "-L", "DEBUG",
  397. #endif
  398. "-c", cfgname, NULL);
  399. #endif
  400. GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
  401. p->stats = GNUNET_STATISTICS_create ("hostlist", p->cfg);
  402. GNUNET_assert ( NULL != p->stats );
  403. }
  404. static void
  405. run (void *cls,
  406. char *const *args,
  407. const char *cfgfile,
  408. const struct GNUNET_CONFIGURATION_Handle *c)
  409. {
  410. timeout = GNUNET_NO;
  411. adv_sent =GNUNET_NO;
  412. adv_arrived = 0;
  413. learned_hostlist_saved = GNUNET_NO;
  414. learned_hostlist_downloaded = GNUNET_NO;
  415. cfg = c;
  416. setup_adv_peer (&adv_peer, "test_learning_adv_peer.conf");
  417. setup_learn_peer (&learn_peer, "test_learning_learn_peer.conf");
  418. timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  419. &timeout_error,
  420. NULL);
  421. check_task = GNUNET_SCHEDULER_add_delayed (CHECK_INTERVALL,
  422. &check_statistics,
  423. NULL);
  424. }
  425. static int
  426. check ()
  427. {
  428. unsigned int failed;
  429. char *const argv[] = {
  430. "test-gnunet-daemon-hostlist-learning",
  431. "-c", "learning_data.conf",
  432. #if VERBOSE
  433. "-L", "DEBUG",
  434. #endif
  435. NULL
  436. };
  437. struct GNUNET_GETOPT_CommandLineOption options[] = {
  438. GNUNET_GETOPT_OPTION_END
  439. };
  440. GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
  441. argv, "test-gnunet-daemon-hostlist-learning",
  442. "nohelp", options,
  443. &run, NULL);
  444. failed = GNUNET_NO;
  445. if (timeout == GNUNET_YES)
  446. {
  447. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  448. "Testcase timeout\n");
  449. failed = GNUNET_YES;
  450. }
  451. if (adv_arrived != GNUNET_YES)
  452. {
  453. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  454. "Learning peer did not receive advertisement from server\n");
  455. failed = GNUNET_YES;
  456. }
  457. if ( learned_hostlist_saved == GNUNET_NO )
  458. {
  459. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  460. "Advertised hostlist was not saved in datastore\n");
  461. failed = GNUNET_YES;
  462. }
  463. if (learned_hostlist_downloaded == GNUNET_NO)
  464. {
  465. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  466. "Advertised hostlist could not be downloaded from server\n");
  467. failed = GNUNET_YES;
  468. }
  469. if (adv_sent == GNUNET_NO)
  470. {
  471. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  472. "Advertised was not sent from server to client\n");
  473. failed = GNUNET_YES;
  474. }
  475. if (GNUNET_YES == failed)
  476. return GNUNET_YES;
  477. return GNUNET_NO;
  478. }
  479. int
  480. main (int argc, char *argv[])
  481. {
  482. int ret;
  483. GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
  484. GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
  485. GNUNET_log_setup ("test-gnunet-daemon-hostlist",
  486. #if VERBOSE
  487. "DEBUG",
  488. #else
  489. "WARNING",
  490. #endif
  491. NULL);
  492. #if !WINDOWS
  493. system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > /dev/null");
  494. system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > /dev/null");
  495. #else
  496. system ("gnunet-peerinfo -s -c test_learning_adv_peer.conf > NUL");
  497. system ("gnunet-peerinfo -s -c test_learning_learn_peer.conf > NUL");
  498. #endif
  499. ret = check ();
  500. GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-1");
  501. GNUNET_DISK_directory_remove ("/tmp/test-gnunet-hostlist-peer-2");
  502. if (GNUNET_YES == GNUNET_DISK_file_test ("hostlists_learn_peer.file"))
  503. {
  504. if (0 == UNLINK("hostlists_learn_peer.file"))
  505. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  506. "Hostlist file hostlists_learn_peer.file was removed\n");
  507. }
  508. return ret;
  509. }
  510. /* end of test_gnunet_daemon_hostlist.c */