You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

712 lines
20 KiB

  1. /*
  2. * This file is part of GNUnet
  3. * Copyright (C) 2013 GNUnet e.V.
  4. *
  5. * GNUnet is free software: you can redistribute it and/or modify it
  6. * under the terms of the GNU Affero General Public License as published
  7. * by the Free Software Foundation, either version 3 of the License,
  8. * or (at your 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. * Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. SPDX-License-Identifier: AGPL3.0-or-later
  18. */
  19. /**
  20. * @author Gabor X Toth
  21. *
  22. * @file
  23. * PSYC Slicer API
  24. */
  25. #include <inttypes.h>
  26. #include "platform.h"
  27. #include "gnunet_util_lib.h"
  28. #include "gnunet_psyc_util_lib.h"
  29. #define LOG(kind,...) GNUNET_log_from (kind, "psyc-util-slicer",__VA_ARGS__)
  30. /**
  31. * Handle for a try-and-slice instance.
  32. */
  33. struct GNUNET_PSYC_Slicer
  34. {
  35. /**
  36. * Method handlers: H(method_name) -> SlicerMethodCallbacks
  37. */
  38. struct GNUNET_CONTAINER_MultiHashMap *method_handlers;
  39. /**
  40. * Modifier handlers: H(modifier_name) -> SlicerModifierCallbacks
  41. */
  42. struct GNUNET_CONTAINER_MultiHashMap *modifier_handlers;
  43. /**
  44. * Receive handle for incoming messages.
  45. */
  46. struct GNUNET_PSYC_ReceiveHandle *recv;
  47. /**
  48. * Currently being processed message.
  49. */
  50. const struct GNUNET_PSYC_MessageHeader *msg;
  51. /**
  52. * Currently being processed message part.
  53. */
  54. const struct GNUNET_MessageHeader *pmsg;
  55. /**
  56. * ID of currently being received message.
  57. */
  58. uint64_t message_id;
  59. /**
  60. * Fragment offset of currently being received message.
  61. */
  62. uint64_t fragment_offset;
  63. /**
  64. * Flags of currently being received message.
  65. */
  66. uint32_t flags;
  67. /**
  68. * Method name of currently being received message.
  69. */
  70. char *method_name;
  71. /**
  72. * Name of currently processed modifier.
  73. */
  74. char *mod_name;
  75. /**
  76. * Value of currently processed modifier.
  77. */
  78. char *mod_value;
  79. /**
  80. * Public key of the nym the current message originates from.
  81. */
  82. struct GNUNET_CRYPTO_EcdsaPublicKey nym_pub_key;
  83. /**
  84. * Size of @a method_name (including terminating \0).
  85. */
  86. uint16_t method_name_size;
  87. /**
  88. * Size of @a modifier_name (including terminating \0).
  89. */
  90. uint16_t mod_name_size;
  91. /**
  92. * Size of modifier value fragment.
  93. */
  94. uint16_t mod_value_size;
  95. /**
  96. * Full size of modifier value.
  97. */
  98. uint16_t mod_full_value_size;
  99. /**
  100. * Remaining bytes from the value of the current modifier.
  101. */
  102. uint16_t mod_value_remaining;
  103. /**
  104. * Operator of currently processed modifier.
  105. */
  106. uint8_t mod_oper;
  107. };
  108. /**
  109. * Callbacks for a slicer method handler.
  110. */
  111. struct SlicerMethodCallbacks
  112. {
  113. GNUNET_PSYC_MessageCallback msg_cb;
  114. GNUNET_PSYC_MethodCallback method_cb;
  115. GNUNET_PSYC_ModifierCallback modifier_cb;
  116. GNUNET_PSYC_DataCallback data_cb;
  117. GNUNET_PSYC_EndOfMessageCallback eom_cb;
  118. void *cls;
  119. };
  120. struct SlicerMethodRemoveClosure
  121. {
  122. struct GNUNET_PSYC_Slicer *slicer;
  123. struct SlicerMethodCallbacks rm_cbs;
  124. };
  125. /**
  126. * Callbacks for a slicer method handler.
  127. */
  128. struct SlicerModifierCallbacks
  129. {
  130. GNUNET_PSYC_ModifierCallback modifier_cb;
  131. void *cls;
  132. };
  133. struct SlicerModifierRemoveClosure
  134. {
  135. struct GNUNET_PSYC_Slicer *slicer;
  136. struct SlicerModifierCallbacks rm_cbs;
  137. };
  138. /**
  139. * Call a method handler for an incoming message part.
  140. */
  141. static int
  142. slicer_method_handler_notify (void *cls, const struct GNUNET_HashCode *key,
  143. void *value)
  144. {
  145. struct GNUNET_PSYC_Slicer *slicer = cls;
  146. const struct GNUNET_MessageHeader *pmsg = slicer->pmsg;
  147. struct SlicerMethodCallbacks *cbs = value;
  148. uint16_t ptype = ntohs (pmsg->type);
  149. switch (ptype)
  150. {
  151. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD:
  152. {
  153. if (NULL != cbs->msg_cb)
  154. cbs->msg_cb (cbs->cls, slicer->msg);
  155. if (NULL == cbs->method_cb)
  156. break;
  157. struct GNUNET_PSYC_MessageMethod *
  158. meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
  159. cbs->method_cb (cbs->cls, slicer->msg, meth, slicer->message_id,
  160. slicer->method_name);
  161. break;
  162. }
  163. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  164. {
  165. if (NULL == cbs->modifier_cb)
  166. break;
  167. struct GNUNET_PSYC_MessageModifier *
  168. mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
  169. cbs->modifier_cb (cbs->cls, slicer->msg, &mod->header, slicer->message_id,
  170. mod->oper, (const char *) &mod[1],
  171. (const void *) &mod[1] + ntohs (mod->name_size),
  172. ntohs (mod->header.size) - sizeof (*mod) - ntohs (mod->name_size),
  173. ntohs (mod->value_size));
  174. break;
  175. }
  176. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  177. {
  178. if (NULL == cbs->modifier_cb)
  179. break;
  180. cbs->modifier_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
  181. slicer->mod_oper, slicer->mod_name, &pmsg[1],
  182. ntohs (pmsg->size) - sizeof (*pmsg),
  183. slicer->mod_full_value_size);
  184. break;
  185. }
  186. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_DATA:
  187. {
  188. if (NULL == cbs->data_cb)
  189. break;
  190. cbs->data_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id,
  191. &pmsg[1], ntohs (pmsg->size) - sizeof (*pmsg));
  192. break;
  193. }
  194. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END:
  195. if (NULL == cbs->eom_cb)
  196. break;
  197. cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_NO);
  198. break;
  199. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_CANCEL:
  200. if (NULL == cbs->eom_cb)
  201. break;
  202. cbs->eom_cb (cbs->cls, slicer->msg, pmsg, slicer->message_id, GNUNET_YES);
  203. break;
  204. }
  205. return GNUNET_YES;
  206. }
  207. /**
  208. * Call a method handler for an incoming message part.
  209. */
  210. static int
  211. slicer_modifier_handler_notify (void *cls, const struct GNUNET_HashCode *key,
  212. void *value)
  213. {
  214. struct GNUNET_PSYC_Slicer *slicer = cls;
  215. struct SlicerModifierCallbacks *cbs = value;
  216. cbs->modifier_cb (cbs->cls, slicer->msg, slicer->pmsg, slicer->message_id,
  217. slicer->mod_oper, slicer->mod_name, slicer->mod_value,
  218. slicer->mod_value_size, slicer->mod_full_value_size);
  219. return GNUNET_YES;
  220. }
  221. /**
  222. * Process an incoming message and call matching handlers.
  223. *
  224. * @param slicer
  225. * The slicer to use.
  226. * @param msg
  227. * The message as it arrived from the network.
  228. */
  229. void
  230. GNUNET_PSYC_slicer_message (struct GNUNET_PSYC_Slicer *slicer,
  231. const struct GNUNET_PSYC_MessageHeader *msg)
  232. {
  233. GNUNET_PSYC_receive_message (slicer->recv, msg);
  234. }
  235. /**
  236. * Process an incoming message part and call matching handlers.
  237. *
  238. * @param cls
  239. * Closure.
  240. * @param message_id
  241. * ID of the message.
  242. * @param flags
  243. * Flags for the message.
  244. * @see enum GNUNET_PSYC_MessageFlags
  245. * @param msg
  246. * The message part. as it arrived from the network.
  247. */
  248. void
  249. GNUNET_PSYC_slicer_message_part (struct GNUNET_PSYC_Slicer *slicer,
  250. const struct GNUNET_PSYC_MessageHeader *msg,
  251. const struct GNUNET_MessageHeader *pmsg)
  252. {
  253. slicer->msg = msg;
  254. slicer->pmsg = pmsg;
  255. uint64_t message_id = GNUNET_ntohll (msg->message_id);
  256. uint16_t ptype = ntohs (pmsg->type);
  257. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_METHOD == ptype)
  258. {
  259. struct GNUNET_PSYC_MessageMethod *
  260. meth = (struct GNUNET_PSYC_MessageMethod *) pmsg;
  261. slicer->method_name_size = ntohs (meth->header.size) - sizeof (*meth);
  262. slicer->method_name = GNUNET_malloc (slicer->method_name_size);
  263. GNUNET_memcpy (slicer->method_name, &meth[1], slicer->method_name_size);
  264. slicer->message_id = message_id;
  265. }
  266. else
  267. {
  268. GNUNET_assert (message_id == slicer->message_id);
  269. }
  270. char *nym_str = GNUNET_CRYPTO_ecdsa_public_key_to_string (&msg->slave_pub_key);
  271. LOG (GNUNET_ERROR_TYPE_DEBUG,
  272. "Slicer received message of type %u and size %u, "
  273. "with ID %" PRIu64 " and method %s from %s\n",
  274. ptype, ntohs (pmsg->size), message_id, slicer->method_name, nym_str);
  275. GNUNET_free (nym_str);
  276. /* try-and-slice modifier */
  277. switch (ptype)
  278. {
  279. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
  280. {
  281. struct GNUNET_PSYC_MessageModifier *
  282. mod = (struct GNUNET_PSYC_MessageModifier *) pmsg;
  283. slicer->mod_oper = mod->oper;
  284. slicer->mod_name_size = ntohs (mod->name_size);
  285. slicer->mod_name = GNUNET_malloc (slicer->mod_name_size);
  286. GNUNET_memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size);
  287. slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size;
  288. slicer->mod_full_value_size = ntohs (mod->value_size);
  289. slicer->mod_value_remaining = slicer->mod_full_value_size;
  290. slicer->mod_value_size
  291. = ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size;
  292. // fall through
  293. }
  294. case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
  295. if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT)
  296. {
  297. slicer->mod_value = (char *) &pmsg[1];
  298. slicer->mod_value_size = ntohs (pmsg->size) - sizeof (*pmsg);
  299. }
  300. slicer->mod_value_remaining -= slicer->mod_value_size;
  301. char *name = GNUNET_malloc (slicer->mod_name_size);
  302. GNUNET_memcpy (name, slicer->mod_name, slicer->mod_name_size);
  303. do
  304. {
  305. struct GNUNET_HashCode key;
  306. uint16_t name_len = strlen (name);
  307. GNUNET_CRYPTO_hash (name, name_len, &key);
  308. GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
  309. slicer_modifier_handler_notify,
  310. slicer);
  311. char *p = strrchr (name, '_');
  312. if (NULL == p)
  313. break;
  314. *p = '\0';
  315. } while (1);
  316. GNUNET_free (name);
  317. }
  318. /* try-and-slice method */
  319. char *name = GNUNET_malloc (slicer->method_name_size);
  320. GNUNET_memcpy (name, slicer->method_name, slicer->method_name_size);
  321. do
  322. {
  323. struct GNUNET_HashCode key;
  324. uint16_t name_len = strlen (name);
  325. GNUNET_CRYPTO_hash (name, name_len, &key);
  326. GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
  327. slicer_method_handler_notify,
  328. slicer);
  329. char *p = strrchr (name, '_');
  330. if (NULL == p)
  331. break;
  332. *p = '\0';
  333. } while (1);
  334. GNUNET_free (name);
  335. if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
  336. GNUNET_free (slicer->method_name);
  337. if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name)
  338. {
  339. GNUNET_free (slicer->mod_name);
  340. slicer->mod_name = NULL;
  341. slicer->mod_name_size = 0;
  342. slicer->mod_value_size = 0;
  343. slicer->mod_full_value_size = 0;
  344. slicer->mod_oper = 0;
  345. }
  346. slicer->msg = NULL;
  347. slicer->pmsg = NULL;
  348. }
  349. /**
  350. * Create a try-and-slice instance.
  351. *
  352. * A slicer processes incoming messages and notifies callbacks about matching
  353. * methods or modifiers encountered.
  354. *
  355. * @return A new try-and-slice construct.
  356. */
  357. struct GNUNET_PSYC_Slicer *
  358. GNUNET_PSYC_slicer_create (void)
  359. {
  360. struct GNUNET_PSYC_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
  361. slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  362. slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
  363. slicer->recv = GNUNET_PSYC_receive_create (NULL,
  364. (GNUNET_PSYC_MessagePartCallback)
  365. GNUNET_PSYC_slicer_message_part,
  366. slicer);
  367. return slicer;
  368. }
  369. /**
  370. * Add a method to the try-and-slice instance.
  371. *
  372. * The callbacks are called for messages with a matching @a method_name prefix.
  373. *
  374. * @param slicer
  375. * The try-and-slice instance to extend.
  376. * @param method_name
  377. * Name of the given method, use empty string to match all.
  378. * @param method_cb
  379. * Method handler invoked upon a matching message.
  380. * @param modifier_cb
  381. * Modifier handler, invoked after @a method_cb
  382. * for each modifier in the message.
  383. * @param data_cb
  384. * Data handler, invoked after @a modifier_cb for each data fragment.
  385. * @param eom_cb
  386. * Invoked upon reaching the end of a matching message.
  387. * @param cls
  388. * Closure for the callbacks.
  389. */
  390. void
  391. GNUNET_PSYC_slicer_method_add (struct GNUNET_PSYC_Slicer *slicer,
  392. const char *method_name,
  393. GNUNET_PSYC_MessageCallback msg_cb,
  394. GNUNET_PSYC_MethodCallback method_cb,
  395. GNUNET_PSYC_ModifierCallback modifier_cb,
  396. GNUNET_PSYC_DataCallback data_cb,
  397. GNUNET_PSYC_EndOfMessageCallback eom_cb,
  398. void *cls)
  399. {
  400. struct GNUNET_HashCode key;
  401. GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
  402. struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
  403. cbs->msg_cb = msg_cb,
  404. cbs->method_cb = method_cb;
  405. cbs->modifier_cb = modifier_cb;
  406. cbs->data_cb = data_cb;
  407. cbs->eom_cb = eom_cb;
  408. cbs->cls = cls;
  409. GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs,
  410. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  411. }
  412. static int
  413. slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
  414. {
  415. struct SlicerMethodRemoveClosure *rm_cls = cls;
  416. struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
  417. struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs;
  418. struct SlicerMethodCallbacks *cbs = value;
  419. if ((NULL == rm_cbs->msg_cb || cbs->msg_cb == rm_cbs->msg_cb)
  420. && (NULL == rm_cbs->method_cb || cbs->method_cb == rm_cbs->method_cb)
  421. && (NULL == rm_cbs->modifier_cb || cbs->modifier_cb == rm_cbs->modifier_cb)
  422. && (NULL == rm_cbs->data_cb || cbs->data_cb == rm_cbs->data_cb)
  423. && (NULL == rm_cbs->eom_cb || cbs->eom_cb == rm_cbs->eom_cb))
  424. {
  425. GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs);
  426. GNUNET_free (cbs);
  427. return GNUNET_NO;
  428. }
  429. return GNUNET_YES;
  430. }
  431. /**
  432. * Remove a registered method from the try-and-slice instance.
  433. *
  434. * Removes one matching handler registered with the given
  435. * @a method_name and callbacks.
  436. *
  437. * @param slicer
  438. * The try-and-slice instance.
  439. * @param method_name
  440. * Name of the method to remove.
  441. * @param method_cb
  442. * Method handler.
  443. * @param modifier_cb
  444. * Modifier handler.
  445. * @param data_cb
  446. * Data handler.
  447. * @param eom_cb
  448. * End of message handler.
  449. *
  450. * @return #GNUNET_OK if a method handler was removed,
  451. * #GNUNET_NO if no handler matched the given method name and callbacks.
  452. */
  453. int
  454. GNUNET_PSYC_slicer_method_remove (struct GNUNET_PSYC_Slicer *slicer,
  455. const char *method_name,
  456. GNUNET_PSYC_MessageCallback msg_cb,
  457. GNUNET_PSYC_MethodCallback method_cb,
  458. GNUNET_PSYC_ModifierCallback modifier_cb,
  459. GNUNET_PSYC_DataCallback data_cb,
  460. GNUNET_PSYC_EndOfMessageCallback eom_cb)
  461. {
  462. struct GNUNET_HashCode key;
  463. GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
  464. struct SlicerMethodRemoveClosure rm_cls;
  465. rm_cls.slicer = slicer;
  466. struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs;
  467. rm_cbs->msg_cb = msg_cb;
  468. rm_cbs->method_cb = method_cb;
  469. rm_cbs->modifier_cb = modifier_cb;
  470. rm_cbs->data_cb = data_cb;
  471. rm_cbs->eom_cb = eom_cb;
  472. return
  473. (GNUNET_SYSERR
  474. == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
  475. slicer_method_remove,
  476. &rm_cls))
  477. ? GNUNET_NO
  478. : GNUNET_OK;
  479. }
  480. /**
  481. * Watch a place for changed objects.
  482. *
  483. * @param slicer
  484. * The try-and-slice instance.
  485. * @param object_filter
  486. * Object prefix to match.
  487. * @param modifier_cb
  488. * Function to call when encountering a state modifier.
  489. * @param cls
  490. * Closure for callback.
  491. */
  492. void
  493. GNUNET_PSYC_slicer_modifier_add (struct GNUNET_PSYC_Slicer *slicer,
  494. const char *object_filter,
  495. GNUNET_PSYC_ModifierCallback modifier_cb,
  496. void *cls)
  497. {
  498. struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs);
  499. cbs->modifier_cb = modifier_cb;
  500. cbs->cls = cls;
  501. struct GNUNET_HashCode key;
  502. GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
  503. GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs,
  504. GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
  505. }
  506. static int
  507. slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
  508. {
  509. struct SlicerModifierRemoveClosure *rm_cls = cls;
  510. struct GNUNET_PSYC_Slicer *slicer = rm_cls->slicer;
  511. struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs;
  512. struct SlicerModifierCallbacks *cbs = value;
  513. if (cbs->modifier_cb == rm_cbs->modifier_cb)
  514. {
  515. GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs);
  516. GNUNET_free (cbs);
  517. return GNUNET_NO;
  518. }
  519. return GNUNET_YES;
  520. }
  521. /**
  522. * Remove a registered modifier from the try-and-slice instance.
  523. *
  524. * Removes one matching handler registered with the given
  525. * @a object_filter and @a modifier_cb.
  526. *
  527. * @param slicer
  528. * The try-and-slice instance.
  529. * @param object_filter
  530. * Object prefix to match.
  531. * @param modifier_cb
  532. * Function to call when encountering a state modifier changes.
  533. */
  534. int
  535. GNUNET_PSYC_slicer_modifier_remove (struct GNUNET_PSYC_Slicer *slicer,
  536. const char *object_filter,
  537. GNUNET_PSYC_ModifierCallback modifier_cb)
  538. {
  539. struct GNUNET_HashCode key;
  540. GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
  541. struct SlicerModifierRemoveClosure rm_cls;
  542. rm_cls.slicer = slicer;
  543. struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs;
  544. rm_cbs->modifier_cb = modifier_cb;
  545. return
  546. (GNUNET_SYSERR
  547. == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
  548. slicer_modifier_remove,
  549. &rm_cls))
  550. ? GNUNET_NO
  551. : GNUNET_OK;
  552. }
  553. static int
  554. slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value)
  555. {
  556. struct SlicerMethodCallbacks *cbs = value;
  557. GNUNET_free (cbs);
  558. return GNUNET_YES;
  559. }
  560. static int
  561. slicer_modifier_free (void *cls, const struct GNUNET_HashCode *key, void *value)
  562. {
  563. struct SlicerModifierCallbacks *cbs = value;
  564. GNUNET_free (cbs);
  565. return GNUNET_YES;
  566. }
  567. /**
  568. * Remove all registered method handlers.
  569. *
  570. * @param slicer
  571. * Slicer to clear.
  572. */
  573. void
  574. GNUNET_PSYC_slicer_method_clear (struct GNUNET_PSYC_Slicer *slicer)
  575. {
  576. GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers,
  577. slicer_method_free, NULL);
  578. GNUNET_CONTAINER_multihashmap_clear (slicer->method_handlers);
  579. }
  580. /**
  581. * Remove all registered modifier handlers.
  582. *
  583. * @param slicer
  584. * Slicer to clear.
  585. */
  586. void
  587. GNUNET_PSYC_slicer_modifier_clear (struct GNUNET_PSYC_Slicer *slicer)
  588. {
  589. GNUNET_CONTAINER_multihashmap_iterate (slicer->modifier_handlers,
  590. slicer_modifier_free, NULL);
  591. GNUNET_CONTAINER_multihashmap_clear (slicer->modifier_handlers);
  592. }
  593. /**
  594. * Remove all registered method & modifier handlers.
  595. *
  596. * @param slicer
  597. * Slicer to clear.
  598. */
  599. void
  600. GNUNET_PSYC_slicer_clear (struct GNUNET_PSYC_Slicer *slicer)
  601. {
  602. GNUNET_PSYC_slicer_method_clear (slicer);
  603. GNUNET_PSYC_slicer_modifier_clear (slicer);
  604. }
  605. /**
  606. * Destroy a given try-and-slice instance.
  607. *
  608. * @param slicer
  609. * Slicer to destroy
  610. */
  611. void
  612. GNUNET_PSYC_slicer_destroy (struct GNUNET_PSYC_Slicer *slicer)
  613. {
  614. GNUNET_PSYC_slicer_clear (slicer);
  615. GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers);
  616. GNUNET_CONTAINER_multihashmap_destroy (slicer->modifier_handlers);
  617. GNUNET_PSYC_receive_destroy (slicer->recv);
  618. GNUNET_free (slicer);
  619. }