libgnunetchat

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

commit cbdb8030c9cbea9e00e5d569a0d90dabbd4155ea
parent 5f187deccd1685385b03e20d7f3b55f600adf6ac
Author: TheJackiMonster <thejackimonster@gmail.com>
Date:   Mon,  6 Dec 2021 23:43:36 +0100

Added status to context for edge cases with direct contact communication

Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>

Diffstat:
Minclude/gnunet_chat_lib.h | 22++++++++++++++++++++++
Msrc/gnunet_chat_contact.c | 41+++++------------------------------------
Msrc/gnunet_chat_contact_intern.c | 14++++++++++++--
Msrc/gnunet_chat_context.c | 27+++++++++++++++++++++++++++
Msrc/gnunet_chat_context.h | 5+++++
Msrc/gnunet_chat_handle.c | 14++++++++++++++
Msrc/gnunet_chat_handle.h | 4++++
Msrc/gnunet_chat_lib.c | 104++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Msrc/gnunet_chat_lib_intern.c | 21+++++++++++++--------
9 files changed, 186 insertions(+), 66 deletions(-)

diff --git a/include/gnunet_chat_lib.h b/include/gnunet_chat_lib.h @@ -528,6 +528,28 @@ struct GNUNET_CHAT_Context* GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group); /** + * Returns the current status of a given <i>context</i> whether it is usable + * or not to communicate with other contacts. + * + * @param[in] context Context + * @return #GNUNET_OK if usable, #GNUNET_NO if the context has been requested, + * #GNUNET_SYSERR otherwise. + */ +int +GNUNET_CHAT_context_get_status (const struct GNUNET_CHAT_Context *context); + +/** + * Requests a <i>context</i> to get established between all required contacts. + * The current status of this request can be tracked via + * #GNUNET_CHAT_context_get_status() and will only change through the + * receivement of new messages. + * + * @param[in,out] context Context + */ +void +GNUNET_CHAT_context_request (struct GNUNET_CHAT_Context *context); + +/** * Returns the chat contact which uses a given <i>context</i>. * * @param[in] context Context diff --git a/src/gnunet_chat_contact.c b/src/gnunet_chat_contact.c @@ -77,7 +77,9 @@ contact_find_context (struct GNUNET_CHAT_Contact *contact) return contact->context; struct GNUNET_CHAT_ContactFindRoom find; + find.member_count = 0; find.room = NULL; + GNUNET_MESSENGER_find_rooms( contact->handle->messenger, contact->member, @@ -85,46 +87,13 @@ contact_find_context (struct GNUNET_CHAT_Contact *contact) &find ); - // TODO: Check if the found room is a group or not - if (!(find.room)) return NULL; - struct GNUNET_HashCode key; - GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, &key, sizeof(key)); - - if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains( - contact->handle->contexts, &key)) - return NULL; - - struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room( - contact->handle->messenger, &key - ); - - if (!room) - return NULL; - - struct GNUNET_CHAT_Context *context = context_create_from_room( - contact->handle, room + return GNUNET_CONTAINER_multihashmap_get( + contact->handle->contexts, + GNUNET_MESSENGER_room_get_key(find.room) ); - - if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put( - contact->handle->contexts, &key, context, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) - { - context_destroy(context); - return NULL; - } - - struct GNUNET_MESSENGER_Message msg; - msg.header.kind = GNUNET_MESSENGER_KIND_INVITE; - GNUNET_CRYPTO_get_peer_identity(contact->handle->cfg, &(msg.body.invite.door)); - GNUNET_memcpy(&(msg.body.invite.key), &key, sizeof(msg.body.invite.key)); - - GNUNET_MESSENGER_send_message(find.room, &msg, contact->member); - - contact->context = context; - return contact->context; } void diff --git a/src/gnunet_chat_contact_intern.c b/src/gnunet_chat_contact_intern.c @@ -26,6 +26,7 @@ struct GNUNET_CHAT_ContactFindRoom { + int member_count; struct GNUNET_MESSENGER_Room *room; }; @@ -36,7 +37,16 @@ it_contact_find_room (void *cls, { GNUNET_assert((cls) && (room)); + const int member_count = GNUNET_MESSENGER_iterate_members(room, NULL, NULL); + struct GNUNET_CHAT_ContactFindRoom *find = cls; - find->room = room; - return GNUNET_NO; + + if ((find->member_count <= 0) || + ((member_count >= 1) && (member_count < find->member_count))) + { + find->member_count = member_count; + find->room = room; + } + + return GNUNET_YES; } diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c @@ -47,6 +47,33 @@ context_create_from_room (struct GNUNET_CHAT_Handle *handle, context->files = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO); context->room = room; + context->contact = NULL; + + context->user_pointer = NULL; + + return context; +} + +struct GNUNET_CHAT_Context* +context_create_from_contact (struct GNUNET_CHAT_Handle *handle, + const struct GNUNET_MESSENGER_Contact *contact) +{ + GNUNET_assert((handle) && (contact)); + + struct GNUNET_CHAT_Context* context = GNUNET_new(struct GNUNET_CHAT_Context); + + context->handle = handle; + + context->type = GNUNET_CHAT_CONTEXT_TYPE_CONTACT; + context->nick = NULL; + + context->timestamps = GNUNET_CONTAINER_multishortmap_create(4, GNUNET_NO); + context->messages = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO); + context->invites = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO); + context->files = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO); + + context->room = NULL; + context->contact = contact; context->user_pointer = NULL; diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h @@ -54,6 +54,7 @@ struct GNUNET_CHAT_Context struct GNUNET_CONTAINER_MultiHashMap *files; struct GNUNET_MESSENGER_Room *room; + const struct GNUNET_MESSENGER_Contact *contact; void *user_pointer; }; @@ -62,6 +63,10 @@ struct GNUNET_CHAT_Context* context_create_from_room (struct GNUNET_CHAT_Handle *handle, struct GNUNET_MESSENGER_Room *room); +struct GNUNET_CHAT_Context* +context_create_from_contact (struct GNUNET_CHAT_Handle *handle, + const struct GNUNET_MESSENGER_Contact *contact); + void context_destroy (struct GNUNET_CHAT_Context* context); diff --git a/src/gnunet_chat_handle.c b/src/gnunet_chat_handle.c @@ -164,3 +164,17 @@ handle_destroy (struct GNUNET_CHAT_Handle* handle) GNUNET_free(handle); } + +struct GNUNET_CHAT_Contact* +handle_get_contact_from_messenger (const struct GNUNET_CHAT_Handle *handle, + const struct GNUNET_MESSENGER_Contact *contact) +{ + GNUNET_assert((handle) && (handle->contacts) && (contact)); + + struct GNUNET_ShortHashCode shorthash; + util_shorthash_from_member(contact, &shorthash); + + return GNUNET_CONTAINER_multishortmap_get( + handle->contacts, &shorthash + ); +} diff --git a/src/gnunet_chat_handle.h b/src/gnunet_chat_handle.h @@ -73,4 +73,8 @@ handle_update_key (struct GNUNET_CHAT_Handle *handle); void handle_destroy (struct GNUNET_CHAT_Handle* handle); +struct GNUNET_CHAT_Contact* +handle_get_contact_from_messenger (const struct GNUNET_CHAT_Handle *handle, + const struct GNUNET_MESSENGER_Contact *contact); + #endif /* GNUNET_CHAT_HANDLE_H_ */ diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c @@ -293,7 +293,20 @@ GNUNET_CHAT_contact_get_context (struct GNUNET_CHAT_Contact *contact) if (!contact) return NULL; - return contact_find_context(contact); + if (contact->context) + return contact->context; + + struct GNUNET_CHAT_Context *context = contact_find_context(contact); + + if ((context) && (GNUNET_CHAT_CONTEXT_TYPE_CONTACT == context->type)) + return context; + + context = context_create_from_contact(contact->handle, contact->member); + + if (context) + contact->context = context; + + return context; } @@ -444,15 +457,79 @@ GNUNET_CHAT_group_get_context (struct GNUNET_CHAT_Group *group) } +int +GNUNET_CHAT_context_get_status (const struct GNUNET_CHAT_Context *context) +{ + if ((!context) || (!(context->room))) + return GNUNET_SYSERR; + + if (1 <= GNUNET_MESSENGER_iterate_members(context->room, NULL, NULL)) + return GNUNET_NO; + + return GNUNET_YES; +} + + +void +GNUNET_CHAT_context_request (struct GNUNET_CHAT_Context *context) +{ + if ((!context) || (context->room)) + return; + + struct GNUNET_CHAT_Handle *handle = context->handle; + + if ((!handle) || (!(context->contact))) + return; + + struct GNUNET_CHAT_Contact *contact = contact_create_from_member( + handle, context->contact + ); + + if (!contact) + return; + + struct GNUNET_CHAT_Context *other = contact_find_context(contact); + + if ((!other) || (!(other->room))) + return; + + struct GNUNET_HashCode key; + GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, &key, sizeof(key)); + + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains( + handle->contexts, &key)) + return; + + struct GNUNET_MESSENGER_Room *room = GNUNET_MESSENGER_open_room( + handle->messenger, &key + ); + + if (!room) + return; + + struct GNUNET_MESSENGER_Message msg; + msg.header.kind = GNUNET_MESSENGER_KIND_INVITE; + GNUNET_CRYPTO_get_peer_identity(handle->cfg, &(msg.body.invite.door)); + GNUNET_memcpy(&(msg.body.invite.key), &key, sizeof(msg.body.invite.key)); + + GNUNET_MESSENGER_send_message(other->room, &msg, context->contact); + context->room = room; +} + + const struct GNUNET_CHAT_Contact* GNUNET_CHAT_context_get_contact (const struct GNUNET_CHAT_Context *context) { if ((!context) || (GNUNET_CHAT_CONTEXT_TYPE_CONTACT != context->type)) return NULL; + if (context->contact) + return handle_get_contact_from_messenger(context->handle, context->contact); + struct GNUNET_MESSENGER_Room *room = context->room; struct GNUNET_CHAT_RoomFindContact find; + find.ignore_key = GNUNET_MESSENGER_get_key(context->handle->messenger); find.contact = NULL; GNUNET_MESSENGER_iterate_members( @@ -464,16 +541,7 @@ GNUNET_CHAT_context_get_contact (const struct GNUNET_CHAT_Context *context) if (!find.contact) return NULL; - struct GNUNET_ShortHashCode shorthash; - util_shorthash_from_member(find.contact, &shorthash); - - const struct GNUNET_CHAT_Contact *contact; - contact = GNUNET_CONTAINER_multishortmap_get( - context->handle->contacts, &shorthash - ); - - GNUNET_assert((contact == NULL) || (contact->context == context)); - return contact; + return handle_get_contact_from_messenger(context->handle, find.contact); } @@ -524,7 +592,7 @@ int GNUNET_CHAT_context_send_text (struct GNUNET_CHAT_Context *context, const char *text) { - if ((!context) || (!text)) + if ((!context) || (!text) || (!(context->room))) return GNUNET_SYSERR; struct GNUNET_MESSENGER_Message msg; @@ -544,7 +612,7 @@ GNUNET_CHAT_context_send_file (struct GNUNET_CHAT_Context *context, GNUNET_CHAT_FileUploadCallback callback, void *cls) { - if ((!context) || (!path)) + if ((!context) || (!path) || (!(context->room))) return GNUNET_SYSERR; if (!(context->handle->directory)) @@ -620,7 +688,8 @@ int GNUNET_CHAT_context_share_file (struct GNUNET_CHAT_Context *context, const struct GNUNET_CHAT_File *file) { - if ((!context) || (!file) || (strlen(file->name) > NAME_MAX)) + if ((!context) || (!file) || (strlen(file->name) > NAME_MAX) || + (!(context->room))) return GNUNET_SYSERR; struct GNUNET_MESSENGER_Message msg; @@ -741,12 +810,7 @@ GNUNET_CHAT_message_get_sender (const struct GNUNET_CHAT_Message *message) if (!sender) return NULL; - struct GNUNET_ShortHashCode shorthash; - util_shorthash_from_member(sender, &shorthash); - - return GNUNET_CONTAINER_multishortmap_get( - message->context->handle->contacts, &shorthash - ); + return handle_get_contact_from_messenger(message->context->handle, sender); } diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c @@ -95,6 +95,7 @@ it_handle_iterate_groups (void *cls, struct GNUNET_CHAT_RoomFindContact { + const struct GNUNET_IDENTITY_PublicKey *ignore_key; const struct GNUNET_MESSENGER_Contact *contact; }; @@ -105,7 +106,16 @@ it_room_find_contact (void *cls, { GNUNET_assert((cls) && (member)); + const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_contact_get_key( + member + ); + struct GNUNET_CHAT_RoomFindContact *find = cls; + + if ((find->ignore_key) && (key) && + (0 == GNUNET_memcmp(find->ignore_key, key))) + return GNUNET_YES; + find->contact = member; return GNUNET_NO; } @@ -129,14 +139,9 @@ it_group_iterate_contacts (void* cls, if (!(it->cb)) return GNUNET_YES; - struct GNUNET_ShortHashCode shorthash; - util_shorthash_from_member(member, &shorthash); - - struct GNUNET_CHAT_Contact *contact = GNUNET_CONTAINER_multishortmap_get( - it->group->handle->contacts, &shorthash - ); - - return it->cb(it->cls, it->group, contact); + return it->cb(it->cls, it->group, handle_get_contact_from_messenger( + it->group->handle, member + )); } struct GNUNET_CHAT_ContextIterateMessages