test_dht_monitor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435
  1. /*
  2. This file is part of GNUnet.
  3. Copyright (C) 2011, 2012 GNUnet e.V.
  4. GNUnet is free software: you can redistribute it and/or modify it
  5. under the terms of the GNU Affero General Public License as published
  6. by the Free Software Foundation, either version 3 of the License,
  7. or (at your 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. Affero General Public License for more details.
  12. You should have received a copy of the GNU Affero General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. SPDX-License-Identifier: AGPL3.0-or-later
  15. */
  16. /**
  17. * @file dht/test_dht_monitor.c
  18. * @brief Test for the dht monitoring API; checks that we receive "some" monitor events
  19. * @author Christian Grothoff
  20. */
  21. #include "platform.h"
  22. #include "gnunet_testbed_service.h"
  23. #include "gnunet_dht_service.h"
  24. #include "dht_test_lib.h"
  25. /**
  26. * How long do we run the test at most?
  27. */
  28. #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
  29. /**
  30. * How often do we run the PUTs?
  31. */
  32. #define PUT_FREQUENCY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
  33. /**
  34. * Information we keep for each GET operation.
  35. */
  36. struct GetOperation
  37. {
  38. /**
  39. * DLL.
  40. */
  41. struct GetOperation *next;
  42. /**
  43. * DLL.
  44. */
  45. struct GetOperation *prev;
  46. /**
  47. * Handle for the operation.
  48. */
  49. struct GNUNET_DHT_GetHandle *get;
  50. };
  51. /**
  52. * Return value from 'main'.
  53. */
  54. static int ok;
  55. /**
  56. * Head of list of active GET operations.
  57. */
  58. static struct GetOperation *get_head;
  59. /**
  60. * Tail of list of active GET operations.
  61. */
  62. static struct GetOperation *get_tail;
  63. /**
  64. * Array of the testbed's peers.
  65. */
  66. static struct GNUNET_TESTBED_Peer **my_peers;
  67. /**
  68. * Number of peers to run.
  69. */
  70. static unsigned int NUM_PEERS = 3;
  71. /**
  72. * Task called to disconnect peers.
  73. */
  74. static struct GNUNET_SCHEDULER_Task *timeout_task;
  75. /**
  76. * Task to do DHT_puts
  77. */
  78. static struct GNUNET_SCHEDULER_Task * put_task;
  79. static struct GNUNET_DHT_MonitorHandle **monitors;
  80. static unsigned int monitor_counter;
  81. /**
  82. * Task run on success or timeout to clean up.
  83. * Terminates active get operations and shuts down
  84. * the testbed.
  85. *
  86. * @param cls the `struct GNUNET_DHT_TEST_Context`
  87. */
  88. static void
  89. shutdown_task (void *cls)
  90. {
  91. struct GNUNET_DHT_TEST_Context *ctx = cls;
  92. unsigned int i;
  93. struct GetOperation *get_op;
  94. ok = (monitor_counter > NUM_PEERS) ? 0 : 2;
  95. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  96. "Received %u monitor events\n",
  97. monitor_counter);
  98. while (NULL != (get_op = get_tail))
  99. {
  100. GNUNET_DHT_get_stop (get_op->get);
  101. GNUNET_CONTAINER_DLL_remove (get_head,
  102. get_tail,
  103. get_op);
  104. GNUNET_free (get_op);
  105. }
  106. for (i=0;i<NUM_PEERS;i++)
  107. GNUNET_DHT_monitor_stop (monitors[i]);
  108. GNUNET_free (monitors);
  109. GNUNET_SCHEDULER_cancel (put_task);
  110. GNUNET_DHT_TEST_cleanup (ctx);
  111. if (NULL != timeout_task)
  112. {
  113. GNUNET_SCHEDULER_cancel (timeout_task);
  114. timeout_task = NULL;
  115. }
  116. }
  117. /**
  118. * Task run on success or timeout to clean up.
  119. * Terminates active get operations and shuts down
  120. * the testbed.
  121. *
  122. * @param cls NULL
  123. */
  124. static void
  125. timeout_task_cb (void *cls)
  126. {
  127. timeout_task = NULL;
  128. GNUNET_SCHEDULER_shutdown ();
  129. }
  130. /**
  131. * Iterator called on each result obtained for a DHT
  132. * operation that expects a reply
  133. *
  134. * @param cls closure with our 'struct GetOperation'
  135. * @param exp when will this value expire
  136. * @param key key of the result
  137. * @param get_path peers on reply path (or NULL if not recorded)
  138. * @param get_path_length number of entries in get_path
  139. * @param put_path peers on the PUT path (or NULL if not recorded)
  140. * @param put_path_length number of entries in get_path
  141. * @param type type of the result
  142. * @param size number of bytes in data
  143. * @param data pointer to the result data
  144. */
  145. static void
  146. dht_get_handler (void *cls, struct GNUNET_TIME_Absolute exp,
  147. const struct GNUNET_HashCode * key,
  148. const struct GNUNET_PeerIdentity *get_path,
  149. unsigned int get_path_length,
  150. const struct GNUNET_PeerIdentity *put_path,
  151. unsigned int put_path_length,
  152. enum GNUNET_BLOCK_Type type,
  153. size_t size, const void *data)
  154. {
  155. struct GetOperation *get_op = cls;
  156. struct GNUNET_HashCode want;
  157. if (sizeof (struct GNUNET_HashCode) != size)
  158. {
  159. GNUNET_break (0);
  160. return;
  161. }
  162. GNUNET_CRYPTO_hash (key, sizeof (*key), &want);
  163. if (0 != memcmp (&want, data, sizeof (want)))
  164. {
  165. GNUNET_break (0);
  166. return;
  167. }
  168. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  169. "Get successful\n");
  170. GNUNET_DHT_get_stop (get_op->get);
  171. GNUNET_CONTAINER_DLL_remove (get_head,
  172. get_tail,
  173. get_op);
  174. GNUNET_free (get_op);
  175. if (NULL != get_head)
  176. return;
  177. /* all DHT GET operations successful; terminate! */
  178. ok = 0;
  179. GNUNET_SCHEDULER_shutdown ();
  180. }
  181. /**
  182. * Task to put the id of each peer into the DHT.
  183. *
  184. * @param cls array with NUM_PEERS DHT handles
  185. */
  186. static void
  187. do_puts (void *cls)
  188. {
  189. struct GNUNET_DHT_Handle **hs = cls;
  190. struct GNUNET_HashCode key;
  191. struct GNUNET_HashCode value;
  192. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  193. "Putting values into DHT\n");
  194. for (unsigned int i = 0; i < NUM_PEERS; i++)
  195. {
  196. GNUNET_CRYPTO_hash (&i, sizeof (i), &key);
  197. GNUNET_CRYPTO_hash (&key, sizeof (key), &value);
  198. GNUNET_DHT_put (hs[i], &key, 10U,
  199. GNUNET_DHT_RO_RECORD_ROUTE |
  200. GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
  201. GNUNET_BLOCK_TYPE_TEST,
  202. sizeof (value), &value,
  203. GNUNET_TIME_UNIT_FOREVER_ABS,
  204. NULL, NULL);
  205. }
  206. put_task = GNUNET_SCHEDULER_add_delayed (PUT_FREQUENCY,
  207. &do_puts, hs);
  208. }
  209. /**
  210. * Callback called on each GET request going through the DHT.
  211. * Prints the info about the intercepted packet and increments a counter.
  212. *
  213. * @param cls Closure.
  214. * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
  215. * @param type The type of data in the request.
  216. * @param hop_count Hop count so far.
  217. * @param path_length number of entries in path (or 0 if not recorded).
  218. * @param path peers on the GET path (or NULL if not recorded).
  219. * @param desired_replication_level Desired replication level.
  220. * @param key Key of the requested data.
  221. */
  222. static void
  223. monitor_get_cb (void *cls,
  224. enum GNUNET_DHT_RouteOption options,
  225. enum GNUNET_BLOCK_Type type,
  226. uint32_t hop_count,
  227. uint32_t desired_replication_level,
  228. unsigned int path_length,
  229. const struct GNUNET_PeerIdentity *path,
  230. const struct GNUNET_HashCode * key)
  231. {
  232. unsigned int i;
  233. i = (unsigned int) (long) cls;
  234. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  235. "%u got a GET message for key %s\n",
  236. i,
  237. GNUNET_h2s (key));
  238. monitor_counter++;
  239. }
  240. /**
  241. * Callback called on each PUT request going through the DHT.
  242. * Prints the info about the intercepted packet and increments a counter.
  243. *
  244. * @param cls Closure.
  245. * @param options Options, for instance RecordRoute, DemultiplexEverywhere.
  246. * @param type The type of data in the request.
  247. * @param hop_count Hop count so far.
  248. * @param path_length number of entries in path (or 0 if not recorded).
  249. * @param path peers on the PUT path (or NULL if not recorded).
  250. * @param desired_replication_level Desired replication level.
  251. * @param exp Expiration time of the data.
  252. * @param key Key under which data is to be stored.
  253. * @param data Pointer to the data carried.
  254. * @param size Number of bytes in data.
  255. */
  256. static void
  257. monitor_put_cb (void *cls,
  258. enum GNUNET_DHT_RouteOption options,
  259. enum GNUNET_BLOCK_Type type,
  260. uint32_t hop_count,
  261. uint32_t desired_replication_level,
  262. unsigned int path_length,
  263. const struct GNUNET_PeerIdentity *path,
  264. struct GNUNET_TIME_Absolute exp,
  265. const struct GNUNET_HashCode * key,
  266. const void *data,
  267. size_t size)
  268. {
  269. unsigned int i;
  270. i = (unsigned int) (long) cls;
  271. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  272. "%u got a PUT message for key %s with %u bytes\n",
  273. i,
  274. GNUNET_h2s (key),
  275. (unsigned int) size);
  276. monitor_counter++;
  277. }
  278. /**
  279. * Callback called on each GET reply going through the DHT.
  280. * Prints the info about the intercepted packet and increments a counter.
  281. *
  282. * @param cls Closure.
  283. * @param type The type of data in the result.
  284. * @param get_path Peers on GET path (or NULL if not recorded).
  285. * @param get_path_length number of entries in get_path.
  286. * @param put_path peers on the PUT path (or NULL if not recorded).
  287. * @param put_path_length number of entries in get_path.
  288. * @param exp Expiration time of the data.
  289. * @param key Key of the data.
  290. * @param data Pointer to the result data.
  291. * @param size Number of bytes in data.
  292. */
  293. static void
  294. monitor_res_cb (void *cls,
  295. enum GNUNET_BLOCK_Type type,
  296. const struct GNUNET_PeerIdentity *get_path,
  297. unsigned int get_path_length,
  298. const struct GNUNET_PeerIdentity *put_path,
  299. unsigned int put_path_length,
  300. struct GNUNET_TIME_Absolute exp,
  301. const struct GNUNET_HashCode * key,
  302. const void *data,
  303. size_t size)
  304. {
  305. unsigned int i;
  306. i = (unsigned int) (long) cls;
  307. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  308. "%u got a REPLY message for key %s with %u bytes\n",
  309. i,
  310. GNUNET_h2s (key),
  311. (unsigned int) size);
  312. monitor_counter++;
  313. }
  314. /**
  315. * Main function of the test.
  316. *
  317. * @param cls closure (NULL)
  318. * @param ctx argument to give to GNUNET_DHT_TEST_cleanup on test end
  319. * @param num_peers number of peers that are running
  320. * @param peers array of peers
  321. * @param dhts handle to each of the DHTs of the peers
  322. */
  323. static void
  324. run (void *cls,
  325. struct GNUNET_DHT_TEST_Context *ctx,
  326. unsigned int num_peers,
  327. struct GNUNET_TESTBED_Peer **peers,
  328. struct GNUNET_DHT_Handle **dhts)
  329. {
  330. unsigned int i;
  331. unsigned int j;
  332. struct GNUNET_HashCode key;
  333. struct GetOperation *get_op;
  334. GNUNET_assert (NUM_PEERS == num_peers);
  335. my_peers = peers;
  336. monitors = GNUNET_new_array (num_peers,
  337. struct GNUNET_DHT_MonitorHandle *);
  338. for (i = 0; i < num_peers; i++)
  339. monitors[i] = GNUNET_DHT_monitor_start (dhts[i],
  340. GNUNET_BLOCK_TYPE_ANY,
  341. NULL,
  342. &monitor_get_cb,
  343. &monitor_res_cb,
  344. &monitor_put_cb,
  345. (void *)(long)i);
  346. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  347. "Peers setup, starting test\n");
  348. put_task = GNUNET_SCHEDULER_add_now (&do_puts, dhts);
  349. for (i=0;i<num_peers;i++)
  350. {
  351. GNUNET_CRYPTO_hash (&i, sizeof (i), &key);
  352. for (j=0;j<num_peers;j++)
  353. {
  354. get_op = GNUNET_new (struct GetOperation);
  355. GNUNET_CONTAINER_DLL_insert (get_head,
  356. get_tail,
  357. get_op);
  358. get_op->get = GNUNET_DHT_get_start (dhts[j],
  359. GNUNET_BLOCK_TYPE_TEST, /* type */
  360. &key, /*key to search */
  361. 4U, /* replication level */
  362. GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
  363. NULL, /* xquery */
  364. 0, /* xquery bits */
  365. &dht_get_handler, get_op);
  366. }
  367. }
  368. timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  369. &timeout_task_cb,
  370. NULL);
  371. GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
  372. ctx);
  373. }
  374. /**
  375. * Main: start test
  376. */
  377. int
  378. main (int xargc, char *xargv[])
  379. {
  380. GNUNET_DHT_TEST_run ("test-dht-monitor",
  381. "test_dht_monitor.conf",
  382. NUM_PEERS,
  383. &run, NULL);
  384. return ok;
  385. }
  386. /* end of test_dht_monitor.c */