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:
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