commit 43485ce71b4eb227d934c5726bc234195e0cbafa
parent 7d43dc0a81ff20c11ae497fece2b414fd241a00c
Author: Jacki <jacki@thejackimonster.de>
Date: Sat, 10 Feb 2024 23:34:12 +0100
Implement blocking and unblocking via rejection tags
Signed-off-by: Jacki <jacki@thejackimonster.de>
Diffstat:
9 files changed, 426 insertions(+), 19 deletions(-)
diff --git a/src/gnunet_chat_contact.c b/src/gnunet_chat_contact.c
@@ -28,6 +28,11 @@
#include "gnunet_chat_ticket.h"
#include "gnunet_chat_contact_intern.c"
+#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_messenger_service.h>
+#include <gnunet/gnunet_time_lib.h>
+
+static const unsigned int initial_map_size_of_contact = 8;
struct GNUNET_CHAT_Contact*
contact_create_from_member (struct GNUNET_CHAT_Handle *handle,
@@ -41,18 +46,63 @@ contact_create_from_member (struct GNUNET_CHAT_Handle *handle,
contact->context = NULL;
contact->member = member;
+ contact->joined = GNUNET_CONTAINER_multihashmap_create(
+ initial_map_size_of_contact, GNUNET_NO);
+
+ contact->tickets_head = NULL;
+ contact->tickets_tail = NULL;
contact->public_key = NULL;
contact->user_pointer = NULL;
contact->owned = GNUNET_NO;
- contact->blocked = GNUNET_NO;
contact_update_key (contact);
return contact;
}
void
+contact_update_join (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_HashCode *hash,
+ enum GNUNET_MESSENGER_MessageFlags flags)
+{
+ GNUNET_assert(
+ (contact) &&
+ (contact->joined) &&
+ (context) &&
+ (context->room) &&
+ (hash)
+ );
+
+ const struct GNUNET_HashCode *key = GNUNET_MESSENGER_room_get_key(
+ context->room
+ );
+
+ struct GNUNET_HashCode *current = GNUNET_CONTAINER_multihashmap_get(
+ contact->joined,
+ key
+ );
+
+ if (! current)
+ {
+ current = GNUNET_new(struct GNUNET_HashCode);
+
+ if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
+ contact->joined, key, current, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+ {
+ GNUNET_free(current);
+ return;
+ }
+ }
+ else if (0 == (flags & GNUNET_MESSENGER_FLAG_RECENT))
+ return;
+
+ GNUNET_memcpy(current, hash,
+ sizeof(struct GNUNET_HashCode));
+}
+
+void
contact_update_key (struct GNUNET_CHAT_Contact *contact)
{
GNUNET_assert(contact);
@@ -100,6 +150,134 @@ contact_find_context (const struct GNUNET_CHAT_Contact *contact)
);
}
+enum GNUNET_GenericReturnValue
+contact_is_blocked (const struct GNUNET_CHAT_Contact *contact,
+ const struct GNUNET_CHAT_Context *context)
+{
+ GNUNET_assert(
+ (contact) &&
+ (contact->joined) &&
+ (context)
+ );
+
+ if (!(context->room))
+ return GNUNET_NO;
+
+ const struct GNUNET_HashCode *hash;
+ hash = GNUNET_CONTAINER_multihashmap_get(
+ contact->joined,
+ GNUNET_MESSENGER_room_get_key(context->room)
+ );
+
+ if (! hash)
+ return GNUNET_YES;
+
+ struct GNUNET_CHAT_ContactFindJoin find;
+ find.hash = NULL;
+
+ GNUNET_CONTAINER_multihashmap_get_multiple(
+ context->rejections,
+ hash,
+ it_contact_find_rejection,
+ &find
+ );
+
+ if (find.hash)
+ return GNUNET_YES;
+ else
+ return GNUNET_NO;
+}
+
+void
+contact_unblock (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context)
+{
+ GNUNET_assert(
+ (contact) &&
+ (contact->joined) &&
+ (context)
+ );
+
+ if (!(context->room))
+ return;
+
+ const struct GNUNET_HashCode *hash;
+ hash = GNUNET_CONTAINER_multihashmap_get(
+ contact->joined,
+ GNUNET_MESSENGER_room_get_key(context->room)
+ );
+
+ if (! hash)
+ return;
+
+ struct GNUNET_CHAT_ContactFindJoin find;
+ find.hash = NULL;
+
+ GNUNET_CONTAINER_multihashmap_get_multiple(
+ context->rejections,
+ hash,
+ it_contact_find_rejection,
+ &find
+ );
+
+ if ((! find.hash) || (! context->room))
+ return;
+
+ GNUNET_MESSENGER_delete_message(
+ context->room,
+ find.hash,
+ GNUNET_TIME_relative_get_zero_()
+ );
+}
+
+void
+contact_block (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context)
+{
+ GNUNET_assert(
+ (contact) &&
+ (contact->joined) &&
+ (context)
+ );
+
+ if (!(context->room))
+ return;
+
+ const struct GNUNET_HashCode *hash;
+ hash = GNUNET_CONTAINER_multihashmap_get(
+ contact->joined,
+ GNUNET_MESSENGER_room_get_key(context->room)
+ );
+
+ if (! hash)
+ return;
+
+ struct GNUNET_CHAT_ContactFindJoin find;
+ find.hash = NULL;
+
+ GNUNET_CONTAINER_multihashmap_get_multiple(
+ context->rejections,
+ hash,
+ it_contact_find_rejection,
+ &find
+ );
+
+ if ((find.hash) || (! context->room))
+ return;
+
+ struct GNUNET_MESSENGER_Message msg;
+ msg.header.kind = GNUNET_MESSENGER_KIND_TAG;
+ GNUNET_memcpy(&(msg.body.tag.hash), hash,
+ sizeof(struct GNUNET_HashCode));
+ msg.body.tag.tag = NULL;
+
+ GNUNET_MESSENGER_send_message(
+ context->room,
+ &msg,
+ contact->member
+ );
+}
+
void
contact_destroy (struct GNUNET_CHAT_Contact* contact)
{
@@ -124,6 +302,9 @@ contact_destroy (struct GNUNET_CHAT_Contact* contact)
if (contact->public_key)
GNUNET_free(contact->public_key);
+ if (contact->joined)
+ GNUNET_CONTAINER_multihashmap_destroy(contact->joined);
+
if ((contact->context) && (!contact->context->room))
context_destroy(contact->context);
diff --git a/src/gnunet_chat_contact.h b/src/gnunet_chat_contact.h
@@ -46,6 +46,7 @@ struct GNUNET_CHAT_Contact
struct GNUNET_CHAT_Context *context;
const struct GNUNET_MESSENGER_Contact *member;
+ struct GNUNET_CONTAINER_MultiHashMap *joined;
struct GNUNET_CHAT_InternalTickets *tickets_head;
struct GNUNET_CHAT_InternalTickets *tickets_tail;
@@ -54,7 +55,6 @@ struct GNUNET_CHAT_Contact
void *user_pointer;
enum GNUNET_GenericReturnValue owned;
- enum GNUNET_GenericReturnValue blocked;
};
/**
@@ -70,6 +70,21 @@ contact_create_from_member (struct GNUNET_CHAT_Handle *handle,
const struct GNUNET_MESSENGER_Contact *member);
/**
+ * Updates the latest <i>hash</i> of a join message from a given
+ * chat <i>contact</i> in a current chat <i>context</i>.
+ *
+ * @param[in,out] contact Chat contact
+ * @param[in,out] context Chat context
+ * @param[in] hash Join message hash
+ * @param[in] flags Join message flags
+ */
+void
+contact_update_join (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_HashCode *hash,
+ enum GNUNET_MESSENGER_MessageFlags flags);
+
+/**
* Updates the string representation of the public key from
* a given chat <i>contact</i>.
*
@@ -89,6 +104,40 @@ struct GNUNET_CHAT_Context*
contact_find_context (const struct GNUNET_CHAT_Contact *contact);
/**
+ * Returns whether a chat <i>contact</i> is blocked in
+ * a given chat <i>context</i>.
+ *
+ * @param[in] contact Chat contact
+ * @param[in] context Chat context
+ * @return #GNUNET_YES if blocked, otherwise #GNUNET_NO
+ */
+enum GNUNET_GenericReturnValue
+contact_is_blocked (const struct GNUNET_CHAT_Contact *contact,
+ const struct GNUNET_CHAT_Context *context);
+
+/**
+ * Unblocks a given chat <i>contact</i> in
+ * a given chat <i>context</i>.
+ *
+ * @param[in,out] contact Chat contact
+ * @param[in,out] context Chat context
+ */
+void
+contact_unblock (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context);
+
+/**
+ * Blocks a given chat <i>contact</i> in
+ * a given chat <i>context</i>.
+ *
+ * @param[in,out] contact Chat contact
+ * @param[in,out] context Chat context
+ */
+void
+contact_block (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context);
+
+/**
* Destroys a chat <i>contact</i> and frees its memory.
*
* @param[in,out] contact Chat contact
diff --git a/src/gnunet_chat_contact_intern.c b/src/gnunet_chat_contact_intern.c
@@ -22,6 +22,11 @@
* @file gnunet_chat_contact_intern.c
*/
+#include "gnunet_chat_context.h"
+#include "gnunet_chat_message.h"
+
+#include <gnunet/gnunet_common.h>
+#include <gnunet/gnunet_messenger_service.h>
#include <stdlib.h>
#define GNUNET_UNUSED __attribute__ ((unused))
@@ -32,7 +37,7 @@ struct GNUNET_CHAT_ContactFindRoom
struct GNUNET_MESSENGER_Room *room;
};
-int
+enum GNUNET_GenericReturnValue
it_contact_find_room (void *cls,
struct GNUNET_MESSENGER_Room *room,
GNUNET_UNUSED const struct GNUNET_MESSENGER_Contact *member)
@@ -52,3 +57,33 @@ it_contact_find_room (void *cls,
return GNUNET_YES;
}
+
+struct GNUNET_CHAT_ContactFindJoin
+{
+ const struct GNUNET_HashCode *hash;
+};
+
+enum GNUNET_GenericReturnValue
+it_contact_find_rejection (void *cls,
+ const struct GNUNET_HashCode *key,
+ void *value)
+{
+ GNUNET_assert((cls) && (key) && (value));
+
+ struct GNUNET_CHAT_ContactFindJoin *find = cls;
+
+ const struct GNUNET_CHAT_Message *message = value;
+
+ if (GNUNET_YES != message_has_msg(message))
+ return GNUNET_YES;
+
+ if (message->flags & GNUNET_MESSENGER_FLAG_SENT)
+ {
+ find->hash = &(message->hash);
+ return GNUNET_NO;
+ }
+
+ return GNUNET_YES;
+}
+
+
diff --git a/src/gnunet_chat_context.c b/src/gnunet_chat_context.c
@@ -23,10 +23,13 @@
*/
#include "gnunet_chat_context.h"
+#include "gnunet_chat_file.h"
#include "gnunet_chat_handle.h"
+#include "gnunet_chat_message.h"
#include "gnunet_chat_util.h"
#include "gnunet_chat_context_intern.c"
+#include <gnunet/gnunet_messenger_service.h>
#include <gnunet/gnunet_namestore_service.h>
static const unsigned int initial_map_size_of_room = 8;
@@ -274,6 +277,64 @@ context_read_records (struct GNUNET_CHAT_Context *context,
}
void
+context_delete_message (struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_CHAT_Message *message)
+{
+ GNUNET_assert((context) && (message));
+
+ if (GNUNET_YES != message_has_msg(message))
+ return;
+
+ switch (message->msg->header.kind)
+ {
+ case GNUNET_MESSENGER_KIND_INVITE:
+ {
+ struct GNUNET_CHAT_Invitation *invite = GNUNET_CONTAINER_multihashmap_get(
+ context->invites, &(message->hash)
+ );
+
+ if (! invite)
+ break;
+
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(
+ context->invites, &(message->hash), invite))
+ invitation_destroy(invite);
+
+ break;
+ }
+ case GNUNET_MESSENGER_KIND_FILE:
+ {
+ struct GNUNET_CHAT_File *file = GNUNET_CONTAINER_multihashmap_get(
+ context->files, &(message->hash)
+ );
+
+ if (! file)
+ break;
+
+ if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(
+ context->files, &(message->hash), file))
+ file_destroy(file);
+
+ break;
+ }
+ case GNUNET_MESSENGER_KIND_TAG:
+ {
+ if (message->msg->body.tag.tag)
+ break;
+
+ GNUNET_CONTAINER_multihashmap_remove(
+ context->rejections,
+ &(message->msg->body.tag.hash),
+ message);
+
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+void
context_write_records (struct GNUNET_CHAT_Context *context)
{
GNUNET_assert((context) && (context->handle) && (context->room));
diff --git a/src/gnunet_chat_context.h b/src/gnunet_chat_context.h
@@ -32,6 +32,7 @@
#include "gnunet_chat_util.h"
struct GNUNET_CHAT_Handle;
+struct GNUNET_CHAT_Message;
struct GNUNET_CHAT_Context
{
@@ -113,6 +114,17 @@ context_update_nick (struct GNUNET_CHAT_Context *context,
const char *nick);
/**
+ * Deletes linked content from a given chat <i>context</i>
+ * of a specific chat <i>message</i>.
+ *
+ * @param[in,out] context Chat context
+ * @param[in] message Chat message
+ */
+void
+context_delete_message (struct GNUNET_CHAT_Context *context,
+ const struct GNUNET_CHAT_Message *message);
+
+/**
* Reads the <i>data</i> of records under a given <i>label</i>
* and updates the chat <i>context</i> with it.
*
diff --git a/src/gnunet_chat_handle_intern.c b/src/gnunet_chat_handle_intern.c
@@ -897,6 +897,13 @@ on_handle_message_callback(void *cls)
switch (message->msg->header.kind)
{
+ case GNUNET_MESSENGER_KIND_JOIN:
+ {
+ contact_update_join(contact, context,
+ &(message->hash), message->flags);
+
+ break;
+ }
case GNUNET_MESSENGER_KIND_KEY:
{
contact_update_key(contact);
@@ -932,7 +939,7 @@ on_handle_message_callback(void *cls)
break;
}
- if (GNUNET_YES == contact->blocked)
+ if (GNUNET_YES == contact_is_blocked(contact, context))
goto clear_dependencies;
handle->msg_cb(handle->msg_cls, context, message);
@@ -1029,10 +1036,10 @@ on_handle_message (void *cls,
{
message_update_msg (message, flags, msg);
- if (message->flags & GNUNET_MESSENGER_FLAG_UPDATE)
- goto handle_callback;
- else
+ if (0 != (message->flags & GNUNET_MESSENGER_FLAG_UPDATE))
return;
+
+ goto handle_callback;
}
else if (msg->header.kind == GNUNET_MESSENGER_KIND_DELETE)
{
diff --git a/src/gnunet_chat_lib.c b/src/gnunet_chat_lib.c
@@ -830,7 +830,8 @@ GNUNET_CHAT_contact_set_name (struct GNUNET_CHAT_Contact *contact,
{
GNUNET_CHAT_VERSION_ASSERT();
- if ((!contact) || (!(contact->context)))
+ if ((!contact) || (!(contact->context)) ||
+ (contact->context->topic))
return;
context_update_nick(contact->context, name);
@@ -848,7 +849,8 @@ GNUNET_CHAT_contact_get_name (const struct GNUNET_CHAT_Contact *contact)
if (!contact)
return NULL;
- if ((contact->context) && (contact->context->nick[0]))
+ if ((contact->context) && (! contact->context->topic) &&
+ (contact->context->nick[0]))
return contact->context->nick;
return GNUNET_MESSENGER_contact_get_name(contact->member);
@@ -936,10 +938,24 @@ GNUNET_CHAT_contact_set_blocked (struct GNUNET_CHAT_Contact *contact,
{
GNUNET_CHAT_VERSION_ASSERT();
- if ((!contact) || ((GNUNET_YES != blocked) && (GNUNET_NO != blocked)))
+ if (!contact)
+ return;
+
+ struct GNUNET_CHAT_ContactIterateContexts it;
+ it.contact = contact;
+
+ if (GNUNET_NO == blocked)
+ it.cb = contact_unblock;
+ else if (GNUNET_YES == blocked)
+ it.cb = contact_block;
+ else
return;
- contact->blocked = blocked;
+ GNUNET_CONTAINER_multihashmap_iterate(
+ contact->joined,
+ it_contact_iterate_contexts,
+ &it
+ );
}
@@ -951,7 +967,12 @@ GNUNET_CHAT_contact_is_blocked (const struct GNUNET_CHAT_Contact *contact)
if (!contact)
return GNUNET_SYSERR;
- return contact->blocked;
+ struct GNUNET_CHAT_Context *context = contact_find_context(contact);
+
+ if (!context)
+ return GNUNET_SYSERR;
+
+ return contact_is_blocked(contact, context);
}
diff --git a/src/gnunet_chat_lib_intern.c b/src/gnunet_chat_lib_intern.c
@@ -22,6 +22,9 @@
* @file gnunet_chat_lib_intern.c
*/
+#include "gnunet_chat_contact.h"
+#include "gnunet_chat_handle.h"
+
#include <gnunet/gnunet_common.h>
#include <stdlib.h>
@@ -105,7 +108,7 @@ struct GNUNET_CHAT_HandleIterateContacts
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_handle_iterate_contacts (void *cls,
GNUNET_UNUSED const struct GNUNET_ShortHashCode *key,
void *value)
@@ -129,7 +132,7 @@ struct GNUNET_CHAT_HandleIterateGroups
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_handle_iterate_groups (void *cls,
GNUNET_UNUSED const struct GNUNET_HashCode *key,
void *value)
@@ -146,13 +149,46 @@ it_handle_iterate_groups (void *cls,
return it->cb(it->cls, it->handle, group);
}
+typedef void
+(*GNUNET_CHAT_ContactIterateContextCallback) (struct GNUNET_CHAT_Contact *contact,
+ struct GNUNET_CHAT_Context *context);
+
+struct GNUNET_CHAT_ContactIterateContexts
+{
+ struct GNUNET_CHAT_Contact *contact;
+ GNUNET_CHAT_ContactIterateContextCallback cb;
+};
+
+enum GNUNET_GenericReturnValue
+it_contact_iterate_contexts (void *cls,
+ const struct GNUNET_HashCode *key,
+ GNUNET_UNUSED void *value)
+{
+ GNUNET_assert((cls) && (key));
+
+ struct GNUNET_CHAT_ContactIterateContexts *it = cls;
+
+ if (!(it->cb))
+ return GNUNET_YES;
+
+ struct GNUNET_CHAT_Handle *handle = it->contact->handle;
+ struct GNUNET_CHAT_Context *context = GNUNET_CONTAINER_multihashmap_get(
+ handle->contexts, key);
+
+ if (! context)
+ return GNUNET_YES;
+
+ it->cb(it->contact, context);
+ return GNUNET_YES;
+}
+
struct GNUNET_CHAT_RoomFindContact
{
const struct GNUNET_CRYPTO_PublicKey *ignore_key;
const struct GNUNET_MESSENGER_Contact *contact;
};
-int
+enum GNUNET_GenericReturnValue
it_room_find_contact (void *cls,
GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
const struct GNUNET_MESSENGER_Contact *member)
@@ -180,7 +216,7 @@ struct GNUNET_CHAT_GroupIterateContacts
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_group_iterate_contacts (void* cls,
GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
const struct GNUNET_MESSENGER_Contact *member)
@@ -204,7 +240,7 @@ struct GNUNET_CHAT_ContextIterateMessages
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_context_iterate_messages (void *cls,
GNUNET_UNUSED const struct GNUNET_HashCode *key,
void *value)
@@ -228,7 +264,7 @@ struct GNUNET_CHAT_ContextIterateFiles
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_context_iterate_files (void *cls,
const struct GNUNET_HashCode *key,
GNUNET_UNUSED void *value)
@@ -264,7 +300,7 @@ struct GNUNET_CHAT_MessageIterateReadReceipts
void *cls;
};
-int
+enum GNUNET_GenericReturnValue
it_message_iterate_read_receipts (void *cls,
GNUNET_UNUSED struct GNUNET_MESSENGER_Room *room,
const struct GNUNET_MESSENGER_Contact *member)
diff --git a/src/gnunet_chat_message.c b/src/gnunet_chat_message.c
@@ -23,6 +23,8 @@
*/
#include "gnunet_chat_message.h"
+#include "gnunet_chat_context.h"
+
#include <gnunet/gnunet_messenger_service.h>
struct GNUNET_CHAT_Message*
@@ -93,7 +95,10 @@ message_update_msg (struct GNUNET_CHAT_Message* message,
if (flags & GNUNET_MESSENGER_FLAG_UPDATE)
message->msg = msg;
else if (flags & GNUNET_MESSENGER_FLAG_DELETE)
+ {
+ context_delete_message(message->context, message);
message->msg = NULL;
+ }
else
return;