test_transport_api_multiaddress.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010 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 transport/test_transport_api.c
  19. * @brief base test case for transport implementations
  20. *
  21. * This test case serves as a base for tcp, udp, and udp-nat
  22. * transport test cases. Based on the executable being run
  23. * the correct test case will be performed. Conservation of
  24. * C code apparently.
  25. */
  26. #include "platform.h"
  27. #include "gnunet_common.h"
  28. #include "gnunet_hello_lib.h"
  29. #include "gnunet_getopt_lib.h"
  30. #include "gnunet_os_lib.h"
  31. #include "gnunet_program_lib.h"
  32. #include "gnunet_scheduler_lib.h"
  33. #include "gnunet_transport_service.h"
  34. #include "transport.h"
  35. #include "transport-testing.h"
  36. #define VERBOSE GNUNET_NO
  37. #define VERBOSE_ARM GNUNET_NO
  38. #define START_ARM GNUNET_YES
  39. /**
  40. * How long until we give up on transmitting the message?
  41. */
  42. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
  43. /**
  44. * How long until we give up on transmitting the message?
  45. */
  46. #define TIMEOUT_TRANSMIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
  47. #define MTYPE 12345
  48. static struct PeerContext p1;
  49. static struct PeerContext p2;
  50. static int ok;
  51. static int is_tcp;
  52. static GNUNET_SCHEDULER_TaskIdentifier die_task;
  53. static GNUNET_SCHEDULER_TaskIdentifier tct;
  54. #if VERBOSE
  55. #define OKPP do { ok++; fprintf (stderr, "Now at stage %u at %s:%u\n", ok, __FILE__, __LINE__); } while (0)
  56. #else
  57. #define OKPP do { ok++; } while (0)
  58. #endif
  59. static void
  60. stop_arm (struct PeerContext *p)
  61. {
  62. #if START_ARM
  63. if (NULL != p->arm_proc)
  64. {
  65. if (0 != GNUNET_OS_process_kill (p->arm_proc, SIGTERM))
  66. GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
  67. GNUNET_OS_process_wait (p->arm_proc);
  68. GNUNET_OS_process_close (p->arm_proc);
  69. p->arm_proc = NULL;
  70. }
  71. #endif
  72. GNUNET_CONFIGURATION_destroy (p->cfg);
  73. }
  74. static void
  75. exchange_hello_last (void *cls,
  76. const struct GNUNET_MessageHeader *message)
  77. {
  78. struct PeerContext *me = cls;
  79. GNUNET_assert (message != NULL);
  80. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  81. "Exchanging HELLO of size %d with peer (%s)!\n",
  82. (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
  83. GNUNET_i2s (&me->id));
  84. GNUNET_assert (GNUNET_OK ==
  85. GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
  86. message, &me->id));
  87. GNUNET_TRANSPORT_offer_hello (p1.th, message, NULL, NULL);
  88. }
  89. static void
  90. exchange_hello (void *cls,
  91. const struct GNUNET_MessageHeader *message)
  92. {
  93. struct PeerContext *me = cls;
  94. GNUNET_assert (message != NULL);
  95. GNUNET_assert (GNUNET_OK ==
  96. GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *)
  97. message, &me->id));
  98. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  99. "Exchanging HELLO of size %d from peer %s!\n",
  100. (int) GNUNET_HELLO_size((const struct GNUNET_HELLO_Message *)message),
  101. GNUNET_i2s (&me->id));
  102. GNUNET_TRANSPORT_offer_hello (p2.th, message, NULL, NULL);
  103. }
  104. static void
  105. end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  106. {
  107. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from transports!\n");
  108. GNUNET_break (0);
  109. die_task = GNUNET_SCHEDULER_NO_TASK;
  110. GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
  111. GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
  112. GNUNET_TRANSPORT_disconnect (p1.th);
  113. GNUNET_TRANSPORT_disconnect (p2.th);
  114. if (GNUNET_SCHEDULER_NO_TASK != tct)
  115. {
  116. GNUNET_SCHEDULER_cancel (tct);
  117. tct = GNUNET_SCHEDULER_NO_TASK;
  118. }
  119. ok = 1;
  120. }
  121. static void
  122. end_normally (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  123. {
  124. ok = 60;
  125. die_task = GNUNET_SCHEDULER_NO_TASK;
  126. GNUNET_TRANSPORT_get_hello_cancel (p2.th, &exchange_hello_last, &p2);
  127. GNUNET_TRANSPORT_get_hello_cancel (p1.th, &exchange_hello, &p1);
  128. GNUNET_TRANSPORT_disconnect (p1.th);
  129. GNUNET_TRANSPORT_disconnect (p2.th);
  130. if (GNUNET_SCHEDULER_NO_TASK != tct)
  131. {
  132. GNUNET_SCHEDULER_cancel (tct);
  133. tct = GNUNET_SCHEDULER_NO_TASK;
  134. }
  135. ok = 0;
  136. }
  137. static void
  138. notify_connect (void *cls,
  139. const struct GNUNET_PeerIdentity *peer,
  140. const struct GNUNET_TRANSPORT_ATS_Information *ats,
  141. uint32_t ats_count)
  142. {
  143. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  144. "Peer `%4s' connected to us (%p)!\n",
  145. GNUNET_i2s (peer),
  146. cls);
  147. if (cls == &p1)
  148. {
  149. GNUNET_assert (ok >= 2);
  150. OKPP;
  151. OKPP;
  152. if (GNUNET_SCHEDULER_NO_TASK != die_task)
  153. GNUNET_SCHEDULER_cancel (die_task);
  154. if (GNUNET_SCHEDULER_NO_TASK != tct)
  155. GNUNET_SCHEDULER_cancel (tct);
  156. tct = GNUNET_SCHEDULER_NO_TASK;
  157. die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT_TRANSMIT,
  158. &end_normally, NULL);
  159. }
  160. }
  161. static void
  162. notify_disconnect (void *cls,
  163. const struct GNUNET_PeerIdentity *peer)
  164. {
  165. if ( (ok != 60) &&
  166. (GNUNET_SCHEDULER_NO_TASK != die_task) )
  167. {
  168. GNUNET_SCHEDULER_cancel (die_task);
  169. die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
  170. }
  171. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  172. "Peer `%4s' disconnected (%p)!\n",
  173. GNUNET_i2s (peer), cls);
  174. }
  175. static void
  176. setup_peer (struct PeerContext *p,
  177. const char *cfgname)
  178. {
  179. p->cfg = GNUNET_CONFIGURATION_create ();
  180. GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
  181. if (GNUNET_CONFIGURATION_have_value (p->cfg,"PATHS", "SERVICEHOME"))
  182. {
  183. GNUNET_assert (GNUNET_OK ==
  184. GNUNET_CONFIGURATION_get_value_string (p->cfg,
  185. "PATHS", "SERVICEHOME",
  186. &p->servicehome));
  187. GNUNET_DISK_directory_remove (p->servicehome);
  188. }
  189. #if START_ARM
  190. p->arm_proc = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-arm",
  191. "gnunet-service-arm",
  192. #if VERBOSE_ARM
  193. "-L", "DEBUG",
  194. #endif
  195. "-c", cfgname, NULL);
  196. #endif
  197. p->th = GNUNET_TRANSPORT_connect (p->cfg,
  198. NULL, p,
  199. NULL,
  200. &notify_connect, &notify_disconnect);
  201. GNUNET_assert (p->th != NULL);
  202. }
  203. static void
  204. try_connect (void *cls,
  205. const struct GNUNET_SCHEDULER_TaskContext *tc)
  206. {
  207. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  208. "Asking peers to connect...\n");
  209. /* FIXME: 'pX.id' may still be all-zeros here... */
  210. GNUNET_TRANSPORT_try_connect (p2.th,
  211. &p1.id);
  212. GNUNET_TRANSPORT_try_connect (p1.th,
  213. &p2.id);
  214. tct = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
  215. &try_connect,
  216. NULL);
  217. }
  218. static void
  219. run (void *cls,
  220. char *const *args,
  221. const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
  222. {
  223. GNUNET_assert (ok == 1);
  224. OKPP;
  225. die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  226. &end_badly, NULL);
  227. if (is_tcp)
  228. {
  229. setup_peer (&p1, "test_transport_api_multiaddress_tcp_peer1.conf");
  230. setup_peer (&p2, "test_transport_api_multiaddress_tcp_peer2.conf");
  231. }
  232. GNUNET_assert(p1.th != NULL);
  233. GNUNET_assert(p2.th != NULL);
  234. GNUNET_TRANSPORT_get_hello (p1.th, &exchange_hello, &p1);
  235. GNUNET_TRANSPORT_get_hello (p2.th, &exchange_hello_last, &p2);
  236. tct = GNUNET_SCHEDULER_add_now (&try_connect, NULL);
  237. }
  238. static int
  239. check ()
  240. {
  241. static char *const argv[] = { "test-transport-api",
  242. "-c",
  243. "test_transport_api_data.conf",
  244. #if VERBOSE
  245. "-L", "DEBUG",
  246. #endif
  247. NULL
  248. };
  249. static struct GNUNET_GETOPT_CommandLineOption options[] = {
  250. GNUNET_GETOPT_OPTION_END
  251. };
  252. #if WRITECONFIG
  253. setTransportOptions("test_transport_api_data.conf");
  254. #endif
  255. ok = 1;
  256. GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
  257. argv, "test-transport-api", "nohelp",
  258. options, &run, &ok);
  259. stop_arm (&p1);
  260. stop_arm (&p2);
  261. if (p1.servicehome != NULL)
  262. {
  263. GNUNET_DISK_directory_remove (p1.servicehome);
  264. GNUNET_free(p1.servicehome);
  265. }
  266. if (p2.servicehome != NULL)
  267. {
  268. GNUNET_DISK_directory_remove (p2.servicehome);
  269. GNUNET_free(p2.servicehome);
  270. }
  271. return ok;
  272. }
  273. int
  274. main (int argc, char *argv[])
  275. {
  276. int ret;
  277. GNUNET_log_setup ("test-transport-api",
  278. #if VERBOSE
  279. "DEBUG",
  280. #else
  281. "WARNING",
  282. #endif
  283. NULL);
  284. if (strstr(argv[0], "tcp") != NULL)
  285. {
  286. is_tcp = GNUNET_YES;
  287. }
  288. ret = check ();
  289. return ret;
  290. }
  291. /* end of test_transport_api.c */