commit 77bbded42c50c6d18b4389b0f3672b36e30f86fa
parent 7ef674b52c2bdf9f65abdcc738be8cbd588cf4aa
Author: Jacki <jacki@thejackimonster.de>
Date: Wed, 10 Apr 2024 02:14:28 +0200
Implement functionality for attribute and ticket usage
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
4 files changed, 694 insertions(+), 19 deletions(-)
diff --git a/include/gnunet/gnunet_chat_lib.h b/include/gnunet/gnunet_chat_lib.h
@@ -195,7 +195,7 @@ typedef enum GNUNET_GenericReturnValue
* Iterator over attributes of a specific chat handle.
*
* @param[in,out] cls Closure from #GNUNET_CHAT_get_attributes
- * @param[in] handle Chat handle
+ * @param[in,out] handle Chat handle
* @param[in] name Attribute name
* @param[in] value Attribute value
* @return #GNUNET_YES if we should continue to iterate, #GNUNET_NO otherwise.
@@ -516,11 +516,11 @@ void
GNUNET_CHAT_set_attribute (struct GNUNET_CHAT_Handle *handle,
const char *name,
const char *value,
- const struct GNUNET_TIME_Relative *expires);
+ struct GNUNET_TIME_Relative expires);
/**
- * Deletes an attribute of a chat handle for related communication under a given
- * <i>name</i>.
+ * Deletes an attribute of a chat <i>handle</i> for related communication
+ * under a given <i>name</i>.
*
* @param[in,out] handle Chat handle
* @param[in] name Attribute name
@@ -543,6 +543,47 @@ GNUNET_CHAT_get_attributes (struct GNUNET_CHAT_Handle *handle,
void *cls);
/**
+ * Share an attribute of a chat <i>handle</i> under a given <i>name</i>
+ * with a specific chat <i>contact</i>.
+ *
+ * @param[in,out] handle Chat handle
+ * @param[in,out] contact Chat contact
+ * @param[in] name Attribute name
+ */
+void
+GNUNET_CHAT_share_attribute_with (struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Contact *contact,
+ const char *name);
+
+/**
+ * Unshare an attribute of a chat <i>handle</i> under a given <i>name</i>
+ * from a specific chat <i>contact</i>.
+ *
+ * @param[in,out] handle Chat handle
+ * @param[in,out] contact Chat contact
+ * @param[in] name Attribute name
+ */
+void
+GNUNET_CHAT_unshare_attribute_from (struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Contact *contact,
+ const char *name);
+
+/**
+ * Calls an optional <i>callback</i> for each attribute of a given chat
+ * <i>handle</i> shared with a specific chat <i>contact</i>.
+ *
+ * @param[in,out] handle Chat handle
+ * @param[in] contact Chat contact
+ * @param[in] callback Callback for attribute iteration (optional)
+ * @param[in,out] cls Closure for attribute iteration (optional)
+ */
+void
+GNUNET_CHAT_get_shared_attributes (struct GNUNET_CHAT_Handle *handle,
+ const struct GNUNET_CHAT_Contact *contact,
+ GNUNET_CHAT_ContactAttributeCallback callback,
+ void *cls);
+
+/**
* Convert an UTF-8 String to a chat URI which will be newly allocated.
*
* @param[in] uri UTF-8 string to parse
diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h
@@ -94,8 +94,10 @@ struct GNUNET_CHAT_UriLookups
struct GNUNET_CHAT_AttributeProcess
{
struct GNUNET_CHAT_Handle *handle;
+ const struct GNUNET_CHAT_Contact *contact;
struct GNUNET_RECLAIM_Attribute *attribute;
+ char *name;
GNUNET_CHAT_AttributeCallback callback;
void *closure;
@@ -110,6 +112,13 @@ struct GNUNET_CHAT_AttributeProcess
struct GNUNET_CHAT_TicketProcess
{
struct GNUNET_CHAT_Handle *handle;
+ const struct GNUNET_CHAT_Contact *contact;
+
+ struct GNUNET_RECLAIM_Ticket *ticket;
+ char *name;
+
+ GNUNET_CHAT_ContactAttributeCallback callback;
+ void *closure;
struct GNUNET_CRYPTO_PrivateKey identity;
@@ -379,7 +388,7 @@ handle_process_records (struct GNUNET_CHAT_Handle *handle,
/**
* Updates the tickets of a given chat <i>handle</i>, revoking
- * all tickets of a <i>identity</i>.
+ * all tickets of an <i>identity</i>.
*
* @param[in,out] handle Chat handle
* @param[in] identity Identity private key
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
@@ -275,7 +275,7 @@ void
GNUNET_CHAT_set_attribute (struct GNUNET_CHAT_Handle *handle,
const char *name,
const char *value,
- const struct GNUNET_TIME_Relative *expires)
+ struct GNUNET_TIME_Relative expires)
{
GNUNET_CHAT_VERSION_ASSERT();
@@ -336,7 +336,7 @@ GNUNET_CHAT_set_attribute (struct GNUNET_CHAT_Handle *handle,
handle->reclaim,
key,
attributes->attribute,
- expires,
+ &expires,
cont_update_attribute_with_status,
attributes
);
@@ -375,25 +375,22 @@ GNUNET_CHAT_delete_attribute (struct GNUNET_CHAT_Handle *handle,
memset(attributes, 0, sizeof(struct GNUNET_CHAT_AttributeProcess));
attributes->handle = handle;
- attributes->attribute = GNUNET_RECLAIM_attribute_new(
- name,
- NULL,
- GNUNET_RECLAIM_ATTRIBUTE_TYPE_NONE,
- NULL,
- 0
- );
+ attributes->name = GNUNET_strdup(name);
- if (!attributes->attribute)
+ if (!attributes->name)
{
GNUNET_free(attributes);
return;
}
- attributes->op = GNUNET_RECLAIM_attribute_delete(
+ attributes->iter = GNUNET_RECLAIM_get_attributes_start(
handle->reclaim,
key,
- attributes->attribute,
- cont_update_attribute_with_status,
+ cb_task_error_iterate_attribute,
+ attributes,
+ cb_delete_attribute,
+ attributes,
+ cb_task_finish_iterate_attribute,
attributes
);
@@ -455,6 +452,160 @@ GNUNET_CHAT_get_attributes (struct GNUNET_CHAT_Handle *handle,
}
+void
+GNUNET_CHAT_share_attribute_with (struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Contact *contact,
+ const char *name)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if ((!handle) || (handle->destruction) || (!contact))
+ return;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ const struct GNUNET_CRYPTO_PublicKey *pubkey = contact_get_key(
+ contact
+ );
+
+ if ((!key) || (!pubkey) || (!name))
+ return;
+
+ struct GNUNET_CHAT_AttributeProcess *attributes = GNUNET_new(
+ struct GNUNET_CHAT_AttributeProcess
+ );
+
+ if (!attributes)
+ return;
+
+ memset(attributes, 0, sizeof(struct GNUNET_CHAT_AttributeProcess));
+
+ attributes->handle = handle;
+ attributes->contact = contact;
+ attributes->name = GNUNET_strdup(name);
+
+ attributes->iter = GNUNET_RECLAIM_get_attributes_start(
+ handle->reclaim,
+ key,
+ cb_task_error_iterate_attribute,
+ attributes,
+ cb_share_attribute,
+ attributes,
+ cb_task_finish_iterate_attribute,
+ attributes
+ );
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->attributes_head,
+ handle->attributes_tail,
+ attributes
+ );
+}
+
+
+void
+GNUNET_CHAT_unshare_attribute_from (struct GNUNET_CHAT_Handle *handle,
+ struct GNUNET_CHAT_Contact *contact,
+ const char *name)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if ((!handle) || (handle->destruction) || (!contact))
+ return;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ if ((!key) || (!name))
+ return;
+
+ struct GNUNET_CHAT_TicketProcess *tickets = GNUNET_new(
+ struct GNUNET_CHAT_TicketProcess
+ );
+
+ if (!tickets)
+ return;
+
+ memset(tickets, 0, sizeof(struct GNUNET_CHAT_TicketProcess));
+
+ tickets->handle = handle;
+ tickets->contact = contact;
+ tickets->name = GNUNET_strdup(name);
+
+ tickets->iter = GNUNET_RECLAIM_ticket_iteration_start(
+ handle->reclaim,
+ key,
+ cb_task_error_iterate_ticket,
+ tickets,
+ cb_iterate_ticket_check,
+ tickets,
+ cb_task_finish_iterate_ticket,
+ tickets
+ );
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+}
+
+
+void
+GNUNET_CHAT_get_shared_attributes (struct GNUNET_CHAT_Handle *handle,
+ const struct GNUNET_CHAT_Contact *contact,
+ GNUNET_CHAT_ContactAttributeCallback callback,
+ void *cls)
+{
+ GNUNET_CHAT_VERSION_ASSERT();
+
+ if ((!handle) || (handle->destruction) || (!contact))
+ return;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ if (!key)
+ return;
+
+ struct GNUNET_CHAT_TicketProcess *tickets = GNUNET_new(
+ struct GNUNET_CHAT_TicketProcess
+ );
+
+ if (!tickets)
+ return;
+
+ memset(tickets, 0, sizeof(struct GNUNET_CHAT_TicketProcess));
+
+ tickets->handle = handle;
+ tickets->contact = contact;
+
+ tickets->callback = callback;
+ tickets->closure = cls;
+
+ tickets->iter = GNUNET_RECLAIM_ticket_iteration_start(
+ handle->reclaim,
+ key,
+ cb_task_error_iterate_ticket,
+ tickets,
+ cb_iterate_ticket,
+ tickets,
+ cb_task_finish_iterate_ticket,
+ tickets
+ );
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+}
+
+
struct GNUNET_CHAT_Uri*
GNUNET_CHAT_uri_parse (const char *uri,
char **emsg)
diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c
@@ -26,7 +26,11 @@
#include "gnunet_chat_handle.h"
#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_messenger_service.h>
+#include <gnunet/gnunet_reclaim_lib.h>
+#include <gnunet/gnunet_reclaim_service.h>
#include <stdlib.h>
+#include <string.h>
#define GNUNET_UNUSED __attribute__ ((unused))
@@ -438,6 +442,11 @@ cb_task_finish_iterate_attribute (void *cls)
if (attributes->iter)
GNUNET_RECLAIM_get_attributes_stop(attributes->iter);
+ attributes->iter = NULL;
+
+ if (attributes->op)
+ return;
+
GNUNET_CONTAINER_DLL_remove(
handle->attributes_head,
handle->attributes_tail,
@@ -467,6 +476,55 @@ cb_task_error_iterate_attribute (void *cls)
}
void
+cb_delete_attribute (void *cls,
+ const struct GNUNET_CRYPTO_PublicKey *identity,
+ const struct GNUNET_RECLAIM_Attribute *attribute)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_AttributeProcess *attributes = (
+ (struct GNUNET_CHAT_AttributeProcess*) cls
+ );
+
+ if (! attributes->name)
+ {
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_stop(attributes->iter);
+
+ attributes->iter = NULL;
+ return;
+ }
+
+ struct GNUNET_CHAT_Handle *handle = attributes->handle;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ if (0 == strcmp(attribute->name, attributes->name))
+ {
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_stop(attributes->iter);
+
+ attributes->iter = NULL;
+ attributes->op = GNUNET_RECLAIM_attribute_delete(
+ handle->reclaim,
+ key,
+ attribute,
+ cont_update_attribute_with_status,
+ attributes
+ );
+
+ GNUNET_free(attributes->name);
+ attributes->name = NULL;
+ return;
+ }
+
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_next(attributes->iter);
+}
+
+void
cb_iterate_attribute (void *cls,
const struct GNUNET_CRYPTO_PublicKey *identity,
const struct GNUNET_RECLAIM_Attribute *attribute)
@@ -479,7 +537,7 @@ cb_iterate_attribute (void *cls,
struct GNUNET_CHAT_Handle *handle = attributes->handle;
- const char *value = GNUNET_RECLAIM_attribute_value_to_string(
+ char *value = GNUNET_RECLAIM_attribute_value_to_string(
attribute->type,
attribute->data,
attribute->data_size
@@ -488,6 +546,422 @@ cb_iterate_attribute (void *cls,
if (attributes->callback)
attributes->callback(attributes->closure, handle, attribute->name, value);
+ if (value)
+ GNUNET_free (value);
+
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_next(attributes->iter);
+}
+
+void
+cb_issue_ticket (void *cls,
+ const struct GNUNET_RECLAIM_Ticket *ticket,
+ const struct GNUNET_RECLAIM_PresentationList *presentations)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_AttributeProcess *attributes = (
+ (struct GNUNET_CHAT_AttributeProcess*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = attributes->handle;
+ struct GNUNET_CHAT_Context *context = contact_find_context(
+ attributes->contact
+ );
+
+ if ((context) && (context->room) && (ticket))
+ GNUNET_MESSENGER_send_ticket(context->room, ticket);
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->attributes_head,
+ handle->attributes_tail,
+ attributes
+ );
+
+ GNUNET_free(attributes);
+}
+
+void
+cb_share_attribute (void *cls,
+ const struct GNUNET_CRYPTO_PublicKey *identity,
+ const struct GNUNET_RECLAIM_Attribute *attribute)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_AttributeProcess *attributes = (
+ (struct GNUNET_CHAT_AttributeProcess*) cls
+ );
+
+ if (! attributes->name)
+ {
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_stop(attributes->iter);
+
+ attributes->iter = NULL;
+ return;
+ }
+
+ struct GNUNET_CHAT_Handle *handle = attributes->handle;
+
+ if (0 == strcmp(attribute->name, attributes->name))
+ {
+ GNUNET_free(attributes->name);
+ attributes->name = NULL;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ const struct GNUNET_CRYPTO_PublicKey *pubkey = contact_get_key(
+ attributes->contact
+ );
+
+ if (attributes->iter)
+ GNUNET_RECLAIM_get_attributes_stop(attributes->iter);
+
+ attributes->iter = NULL;
+
+ struct GNUNET_RECLAIM_AttributeList *attrs;
+ attrs = GNUNET_new (struct GNUNET_RECLAIM_AttributeList);
+
+ if (attrs)
+ GNUNET_RECLAIM_attribute_list_add(
+ attrs,
+ attribute->name,
+ &(attribute->credential),
+ attribute->type,
+ attribute->data,
+ attribute->data_size
+ );
+
+ if ((key) && (pubkey) && (attrs))
+ attributes->op = GNUNET_RECLAIM_ticket_issue(
+ handle->reclaim,
+ key,
+ pubkey,
+ attrs,
+ cb_issue_ticket,
+ attributes
+ );
+
+ if (attrs)
+ GNUNET_RECLAIM_attribute_list_destroy(attrs);
+
+ return;
+ }
+
if (attributes->iter)
GNUNET_RECLAIM_get_attributes_next(attributes->iter);
}
+
+void
+cb_task_finish_iterate_ticket (void *cls)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ if (tickets->iter)
+ GNUNET_RECLAIM_ticket_iteration_stop (tickets->iter);
+
+ if (tickets->name)
+ GNUNET_free(tickets->name);
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+
+ GNUNET_free(tickets);
+}
+
+void
+cb_task_error_iterate_ticket (void *cls)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ handle_send_internal_message(
+ tickets->handle,
+ NULL,
+ GNUNET_CHAT_FLAG_WARNING,
+ "Ticket iteration failed!"
+ );
+
+ cb_task_finish_iterate_ticket(cls);
+}
+
+void
+cont_revoke_ticket (void *cls,
+ int32_t success,
+ const char *emsg)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ if (success == GNUNET_SYSERR)
+ handle_send_internal_message(
+ handle,
+ NULL,
+ GNUNET_CHAT_FLAG_WARNING,
+ emsg
+ );
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+
+ GNUNET_free(tickets);
+}
+
+void
+cb_consume_ticket_check (void *cls,
+ const struct GNUNET_CRYPTO_PublicKey *identity,
+ const struct GNUNET_RECLAIM_Attribute *attribute,
+ const struct GNUNET_RECLAIM_Presentation *presentation)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ if ((!identity) && (!attribute) && (!presentation))
+ {
+ tickets->op = NULL;
+
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ if (tickets->name)
+ {
+ GNUNET_free(tickets->name);
+ tickets->name = NULL;
+ }
+ else if (!key)
+ tickets->op = GNUNET_RECLAIM_ticket_revoke(
+ handle->reclaim,
+ key,
+ tickets->ticket,
+ cont_revoke_ticket,
+ tickets
+ );
+
+ if (tickets->ticket)
+ GNUNET_free(tickets->ticket);
+
+ tickets->ticket = NULL;
+
+ if (tickets->op)
+ return;
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+
+ GNUNET_free(tickets);
+ }
+
+ if ((!attribute) || (! tickets->name) ||
+ (0 != strcmp(tickets->name, attribute->name)))
+ return;
+
+ if (tickets->name)
+ GNUNET_free(tickets->name);
+
+ tickets->name = NULL;
+}
+
+void
+cb_iterate_ticket_check (void *cls,
+ const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ const struct GNUNET_CRYPTO_PublicKey *pubkey = contact_get_key(
+ tickets->contact
+ );
+
+ if ((!key) || (!pubkey))
+ return;
+
+ if (0 != GNUNET_memcmp(pubkey, &(ticket->audience)))
+ goto skip_ticket;
+
+ struct GNUNET_CHAT_TicketProcess *tick = GNUNET_new(
+ struct GNUNET_CHAT_TicketProcess
+ );
+
+ if (!tick)
+ return;
+
+ memset(tick, 0, sizeof (struct GNUNET_CHAT_TicketProcess));
+
+ tick->handle = handle;
+ tick->contact = tickets->contact;
+
+ if (tickets->name)
+ tick->name = GNUNET_strdup (tickets->name);
+
+ tick->ticket = GNUNET_new (struct GNUNET_RECLAIM_Ticket);
+
+ if (tick->ticket)
+ GNUNET_memcpy (
+ tick->ticket,
+ ticket,
+ sizeof (struct GNUNET_RECLAIM_Ticket)
+ );
+
+ tick->callback = tickets->callback;
+ tick->closure = tickets->closure;
+
+ tick->op = GNUNET_RECLAIM_ticket_consume(
+ handle->reclaim,
+ key,
+ ticket,
+ cb_consume_ticket_check,
+ tick
+ );
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tick
+ );
+
+skip_ticket:
+ if (tickets->iter)
+ GNUNET_RECLAIM_ticket_iteration_next (tickets->iter);
+}
+
+void
+cb_consume_ticket (void *cls,
+ const struct GNUNET_CRYPTO_PublicKey *identity,
+ const struct GNUNET_RECLAIM_Attribute *attribute,
+ const struct GNUNET_RECLAIM_Presentation *presentation)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ if ((!identity) && (!attribute) && (!presentation))
+ {
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ GNUNET_CONTAINER_DLL_remove(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tickets
+ );
+
+ GNUNET_free(tickets);
+ return;
+ }
+
+ if (!attribute)
+ return;
+
+ char *value = GNUNET_RECLAIM_attribute_value_to_string(
+ attribute->type,
+ attribute->data,
+ attribute->data_size
+ );
+
+ if (tickets->callback)
+ tickets->callback(tickets->closure, tickets->contact, attribute->name, value);
+
+ if (value)
+ GNUNET_free (value);
+}
+
+void
+cb_iterate_ticket (void *cls,
+ const struct GNUNET_RECLAIM_Ticket *ticket)
+{
+ GNUNET_assert(cls);
+
+ struct GNUNET_CHAT_TicketProcess *tickets = (
+ (struct GNUNET_CHAT_TicketProcess*) cls
+ );
+
+ struct GNUNET_CHAT_Handle *handle = tickets->handle;
+
+ const struct GNUNET_CRYPTO_PrivateKey *key = handle_get_key(
+ handle
+ );
+
+ const struct GNUNET_CRYPTO_PublicKey *pubkey = contact_get_key(
+ tickets->contact
+ );
+
+ if ((!key) || (!pubkey))
+ return;
+
+ if (0 != GNUNET_memcmp(pubkey, &(ticket->audience)))
+ goto skip_ticket;
+
+ struct GNUNET_CHAT_TicketProcess *tick = GNUNET_new(
+ struct GNUNET_CHAT_TicketProcess
+ );
+
+ if (!tick)
+ return;
+
+ memset(tick, 0, sizeof (struct GNUNET_CHAT_TicketProcess));
+
+ tick->handle = handle;
+ tick->contact = tickets->contact;
+
+ tick->callback = tickets->callback;
+ tick->closure = tickets->closure;
+
+ tick->op = GNUNET_RECLAIM_ticket_consume(
+ handle->reclaim,
+ key,
+ ticket,
+ cb_consume_ticket,
+ tick
+ );
+
+ GNUNET_CONTAINER_DLL_insert_tail(
+ handle->tickets_head,
+ handle->tickets_tail,
+ tick
+ );
+
+skip_ticket:
+ if (tickets->iter)
+ GNUNET_RECLAIM_ticket_iteration_next (tickets->iter);
+}