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