- slicer->msg = msg;
-
- /* try-and-slice modifier */
-
- switch (ptype)
- {
- case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MODIFIER:
- {
- struct GNUNET_PSYC_MessageModifier *
- mod = (struct GNUNET_PSYC_MessageModifier *) msg;
- slicer->mod_oper = mod->oper;
- slicer->mod_name_size = ntohs (mod->name_size);
- slicer->mod_name = GNUNET_malloc (slicer->mod_name_size);
- memcpy (slicer->mod_name, &mod[1], slicer->mod_name_size);
- slicer->mod_value = (char *) &mod[1] + slicer->mod_name_size;
- slicer->mod_full_value_size = ntohs (mod->value_size);
- slicer->mod_value_remaining = slicer->mod_full_value_size;
- slicer->mod_value_size
- = ntohs (mod->header.size) - sizeof (*mod) - slicer->mod_name_size;
- }
- case GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT:
- if (ptype == GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_MOD_CONT)
- {
- slicer->mod_value = (char *) &msg[1];
- slicer->mod_value_size = ntohs (msg->size) - sizeof (*msg);
- }
- slicer->mod_value_remaining -= slicer->mod_value_size;
- char *name = GNUNET_malloc (slicer->mod_name_size);
- memcpy (name, slicer->mod_name, slicer->mod_name_size);
- do
- {
- struct GNUNET_HashCode key;
- uint16_t name_len = strlen (name);
- GNUNET_CRYPTO_hash (name, name_len, &key);
- GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
- slicer_modifier_handler_notify,
- slicer);
- char *p = strrchr (name, '_');
- if (NULL == p)
- break;
- *p = '\0';
- } while (1);
- GNUNET_free (name);
- }
-
- /* try-and-slice method */
-
- char *name = GNUNET_malloc (slicer->method_name_size);
- memcpy (name, slicer->method_name, slicer->method_name_size);
- do
- {
- struct GNUNET_HashCode key;
- uint16_t name_len = strlen (name);
- GNUNET_CRYPTO_hash (name, name_len, &key);
- GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
- slicer_method_handler_notify,
- slicer);
- char *p = strrchr (name, '_');
- if (NULL == p)
- break;
- *p = '\0';
- } while (1);
- GNUNET_free (name);
-
- if (GNUNET_MESSAGE_TYPE_PSYC_MESSAGE_END <= ptype)
- GNUNET_free (slicer->method_name);
-
- if (0 == slicer->mod_value_remaining && NULL != slicer->mod_name)
- {
- GNUNET_free (slicer->mod_name);
- slicer->mod_name = NULL;
- slicer->mod_name_size = 0;
- slicer->mod_value_size = 0;
- slicer->mod_full_value_size = 0;
- slicer->mod_oper = 0;
- }
-
- slicer->msg = NULL;
-}
-
-
-/**
- * Create a try-and-slice instance.
- *
- * A slicer processes incoming messages and notifies callbacks about matching
- * methods or modifiers encountered.
- *
- * @return A new try-and-slice construct.
- */
-struct GNUNET_SOCIAL_Slicer *
-GNUNET_SOCIAL_slicer_create (void)
-{
- struct GNUNET_SOCIAL_Slicer *slicer = GNUNET_malloc (sizeof (*slicer));
- slicer->method_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
- slicer->modifier_handlers = GNUNET_CONTAINER_multihashmap_create (1, GNUNET_NO);
- return slicer;
-}
-
-
-/**
- * Add a method to the try-and-slice instance.
- *
- * The callbacks are called for messages with a matching @a method_name prefix.
- *
- * @param slicer
- * The try-and-slice instance to extend.
- * @param method_name
- * Name of the given method, use empty string to match all.
- * @param method_cb
- * Method handler invoked upon a matching message.
- * @param modifier_cb
- * Modifier handler, invoked after @a method_cb
- * for each modifier in the message.
- * @param data_cb
- * Data handler, invoked after @a modifier_cb for each data fragment.
- * @param eom_cb
- * Invoked upon reaching the end of a matching message.
- * @param cls
- * Closure for the callbacks.
- */
-void
-GNUNET_SOCIAL_slicer_method_add (struct GNUNET_SOCIAL_Slicer *slicer,
- const char *method_name,
- GNUNET_SOCIAL_MethodCallback method_cb,
- GNUNET_SOCIAL_ModifierCallback modifier_cb,
- GNUNET_SOCIAL_DataCallback data_cb,
- GNUNET_SOCIAL_EndOfMessageCallback eom_cb,
- void *cls)
-{
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
-
- struct SlicerMethodCallbacks *cbs = GNUNET_malloc (sizeof (*cbs));
- cbs->method_cb = method_cb;
- cbs->modifier_cb = modifier_cb;
- cbs->data_cb = data_cb;
- cbs->eom_cb = eom_cb;
- cbs->cls = cls;
-
- GNUNET_CONTAINER_multihashmap_put (slicer->method_handlers, &key, cbs,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-}
-
-
-int
-slicer_method_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
-{
- struct SlicerMethodRemoveClosure *rm_cls = cls;
- struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer;
- struct SlicerMethodCallbacks *rm_cbs = &rm_cls->rm_cbs;
- struct SlicerMethodCallbacks *cbs = value;
-
- if (cbs->method_cb == rm_cbs->method_cb
- && cbs->modifier_cb == rm_cbs->modifier_cb
- && cbs->data_cb == rm_cbs->data_cb
- && cbs->eom_cb == rm_cbs->eom_cb)
- {
- GNUNET_CONTAINER_multihashmap_remove (slicer->method_handlers, key, cbs);
- GNUNET_free (cbs);
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Remove a registered method from the try-and-slice instance.
- *
- * Removes one matching handler registered with the given
- * @a method_name and callbacks.
- *
- * @param slicer
- * The try-and-slice instance.
- * @param method_name
- * Name of the method to remove.
- * @param method_cb
- * Method handler.
- * @param modifier_cb
- * Modifier handler.
- * @param data_cb
- * Data handler.
- * @param eom_cb
- * End of message handler.
- *
- * @return #GNUNET_OK if a method handler was removed,
- * #GNUNET_NO if no handler matched the given method name and callbacks.
- */
-int
-GNUNET_SOCIAL_slicer_method_remove (struct GNUNET_SOCIAL_Slicer *slicer,
- const char *method_name,
- GNUNET_SOCIAL_MethodCallback method_cb,
- GNUNET_SOCIAL_ModifierCallback modifier_cb,
- GNUNET_SOCIAL_DataCallback data_cb,
- GNUNET_SOCIAL_EndOfMessageCallback eom_cb)
-{
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (method_name, strlen (method_name), &key);
-
- struct SlicerMethodRemoveClosure rm_cls;
- rm_cls.slicer = slicer;
- struct SlicerMethodCallbacks *rm_cbs = &rm_cls.rm_cbs;
- rm_cbs->method_cb = method_cb;
- rm_cbs->modifier_cb = modifier_cb;
- rm_cbs->data_cb = data_cb;
- rm_cbs->eom_cb = eom_cb;
-
- return
- (GNUNET_SYSERR
- == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->method_handlers, &key,
- slicer_method_remove,
- &rm_cls))
- ? GNUNET_NO
- : GNUNET_OK;
-}
-
-
-/**
- * Watch a place for changed objects.
- *
- * @param slicer
- * The try-and-slice instance.
- * @param object_filter
- * Object prefix to match.
- * @param modifier_cb
- * Function to call when encountering a state modifier.
- * @param cls
- * Closure for callback.
- */
-void
-GNUNET_SOCIAL_slicer_modifier_add (struct GNUNET_SOCIAL_Slicer *slicer,
- const char *object_filter,
- GNUNET_SOCIAL_ModifierCallback modifier_cb,
- void *cls)
-{
- struct SlicerModifierCallbacks *cbs = GNUNET_malloc (sizeof *cbs);
- cbs->modifier_cb = modifier_cb;
- cbs->cls = cls;
-
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
- GNUNET_CONTAINER_multihashmap_put (slicer->modifier_handlers, &key, cbs,
- GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-}
-
-
-int
-slicer_modifier_remove (void *cls, const struct GNUNET_HashCode *key, void *value)
-{
- struct SlicerModifierRemoveClosure *rm_cls = cls;
- struct GNUNET_SOCIAL_Slicer *slicer = rm_cls->slicer;
- struct SlicerModifierCallbacks *rm_cbs = &rm_cls->rm_cbs;
- struct SlicerModifierCallbacks *cbs = value;
-
- if (cbs->modifier_cb == rm_cbs->modifier_cb)
- {
- GNUNET_CONTAINER_multihashmap_remove (slicer->modifier_handlers, key, cbs);
- GNUNET_free (cbs);
- return GNUNET_NO;
- }
- return GNUNET_YES;
-}
-
-
-/**
- * Remove a registered modifier from the try-and-slice instance.
- *
- * Removes one matching handler registered with the given
- * @a object_filter and @a modifier_cb.
- *
- * @param slicer
- * The try-and-slice instance.
- * @param object_filter
- * Object prefix to match.
- * @param modifier_cb
- * Function to call when encountering a state modifier changes.
- */
-int
-GNUNET_SOCIAL_slicer_modifier_remove (struct GNUNET_SOCIAL_Slicer *slicer,
- const char *object_filter,
- GNUNET_SOCIAL_ModifierCallback modifier_cb)
-{
- struct GNUNET_HashCode key;
- GNUNET_CRYPTO_hash (object_filter, strlen (object_filter), &key);
-
- struct SlicerModifierRemoveClosure rm_cls;
- rm_cls.slicer = slicer;
- struct SlicerModifierCallbacks *rm_cbs = &rm_cls.rm_cbs;
- rm_cbs->modifier_cb = modifier_cb;
-
- return
- (GNUNET_SYSERR
- == GNUNET_CONTAINER_multihashmap_get_multiple (slicer->modifier_handlers, &key,
- slicer_modifier_remove,
- &rm_cls))
- ? GNUNET_NO
- : GNUNET_OK;
- }
-
-
-int
-slicer_method_free (void *cls, const struct GNUNET_HashCode *key, void *value)
-{
- struct SlicerMethodCallbacks *cbs = value;
- GNUNET_free (cbs);
- return GNUNET_YES;
-}
-
-
-/**
- * Destroy a given try-and-slice instance.
- *
- * @param slicer
- * Slicer to destroy
- */
-void
-GNUNET_SOCIAL_slicer_destroy (struct GNUNET_SOCIAL_Slicer *slicer)
-{
- GNUNET_CONTAINER_multihashmap_iterate (slicer->method_handlers,
- slicer_method_free, NULL);
- GNUNET_CONTAINER_multihashmap_destroy (slicer->method_handlers);
- GNUNET_free (slicer);
-}
-
-
-/*** PLACE ***/
-
-
-static void
-place_send_connect_msg (struct GNUNET_SOCIAL_Place *plc)
-{
- uint16_t cmsg_size = ntohs (plc->connect_msg->size);
- struct GNUNET_MessageHeader * cmsg = GNUNET_malloc (cmsg_size);
- memcpy (cmsg, plc->connect_msg, cmsg_size);
- GNUNET_CLIENT_MANAGER_transmit_now (plc->client, cmsg);
-}
-
-
-static void
-place_recv_disconnect (void *cls,
- struct GNUNET_CLIENT_MANAGER_Connection *client,
- const struct GNUNET_MessageHeader *msg)
-{
- struct GNUNET_SOCIAL_Place *
- plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
-
- GNUNET_CLIENT_MANAGER_reconnect (client);
- place_send_connect_msg (plc);
-}
-
-
-static void
-place_recv_result (void *cls,
- struct GNUNET_CLIENT_MANAGER_Connection *client,
- const struct GNUNET_MessageHeader *msg)
-{
- struct GNUNET_SOCIAL_Place *
- plc = GNUNET_CLIENT_MANAGER_get_user_context_ (client, sizeof (*plc));
-
- const struct GNUNET_OperationResultMessage *
- res = (const struct GNUNET_OperationResultMessage *) msg;
-
- uint16_t size = ntohs (msg->size);
- if (size < sizeof (*res))
- { /* Error, message too small. */
- GNUNET_break (0);
- return;
- }
-
- uint16_t data_size = size - sizeof (*res);
- const char *data = (0 < data_size) ? (const char *) &res[1] : NULL;
- GNUNET_CLIENT_MANAGER_op_result (plc->client, GNUNET_ntohll (res->op_id),
- GNUNET_ntohll (res->result_code),
- data, data_size);
-}
-
-
-static void
-op_recv_history_result (void *cls, int64_t result,
- const void *err_msg, uint16_t err_msg_size)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Received history replay result: %" PRId64 ".\n", result);
-
- struct GNUNET_SOCIAL_HistoryRequest *hist = cls;
-
- if (NULL != hist->result_cb)
- hist->result_cb (hist->cls, result, err_msg, err_msg_size);
-
- GNUNET_PSYC_receive_destroy (hist->recv);
- GNUNET_free (hist);
-}