libgnunetchat

library for GNUnet Messenger
Log | Files | Refs | README | LICENSE

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:
Minclude/gnunet/gnunet_chat_lib.h | 49+++++++++++++++++++++++++++++++++++++++++++++----
Msrc/gnunet_chat_handle.h | 11++++++++++-
Msrc/gnunet_chat_lib.c | 177+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/gnunet_chat_lib_intern.c | 476++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
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); +}