diff options
Diffstat (limited to 'src/psycutil/psyc_slicer.c')
-rw-r--r-- | src/psycutil/psyc_slicer.c | 711 |
1 files changed, 0 insertions, 711 deletions
diff --git a/src/psycutil/psyc_slicer.c b/src/psycutil/psyc_slicer.c deleted file mode 100644 index 9b25d8a4b..000000000 --- a/src/psycutil/psyc_slicer.c +++ /dev/null | |||
@@ -1,711 +0,0 @@ | |||
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 | */ | ||
40 | struct 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 | */ | ||
137 | struct 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 | |||
148 | struct 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 | */ | ||
158 | struct SlicerModifierCallbacks | ||
159 | { | ||
160 | GNUNET_PSYC_ModifierCallback modifier_cb; | ||
161 | void *cls; | ||
162 | }; | ||
163 | |||
164 | |||
165 | struct 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 | */ | ||
175 | static int | ||
176 | slicer_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 | */ | ||
252 | static int | ||
253 | slicer_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 | */ | ||
274 | void | ||
275 | GNUNET_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 | */ | ||
295 | void | ||
296 | GNUNET_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 | */ | ||
416 | struct GNUNET_PSYC_Slicer * | ||
417 | GNUNET_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 | */ | ||
451 | void | ||
452 | GNUNET_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 | |||
477 | static int | ||
478 | slicer_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 | */ | ||
521 | int | ||
522 | GNUNET_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 | */ | ||
564 | void | ||
565 | GNUNET_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 | |||
581 | static int | ||
582 | slicer_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 | */ | ||
612 | int | ||
613 | GNUNET_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 | |||
635 | static int | ||
636 | slicer_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 | |||
644 | static int | ||
645 | slicer_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 | */ | ||
659 | void | ||
660 | GNUNET_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 | */ | ||
674 | void | ||
675 | GNUNET_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 | */ | ||
689 | void | ||
690 | GNUNET_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 | */ | ||
703 | void | ||
704 | GNUNET_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 | } | ||