gnunet_chat_tagging.c (4232B)
1 /* 2 This file is part of GNUnet. 3 Copyright (C) 2024 GNUnet e.V. 4 5 GNUnet is free software: you can redistribute it and/or modify it 6 under the terms of the GNU Affero General Public License as published 7 by the Free Software Foundation, either version 3 of the License, 8 or (at your option) any later version. 9 10 GNUnet is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Affero General Public License for more details. 14 15 You should have received a copy of the GNU Affero General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. 17 18 SPDX-License-Identifier: AGPL3.0-or-later 19 */ 20 /* 21 * @author Tobias Frisch 22 * @file gnunet_chat_tagging.c 23 */ 24 25 #include "gnunet_chat_tagging.h" 26 #include "gnunet_chat_message.h" 27 28 #include <gnunet/gnunet_common.h> 29 #include <gnunet/gnunet_messenger_service.h> 30 #include <gnunet/gnunet_util_lib.h> 31 #include <string.h> 32 33 static const unsigned int initial_map_size_of_tagging = 4; 34 35 struct GNUNET_CHAT_InternalTagging* 36 internal_tagging_create () 37 { 38 struct GNUNET_CHAT_InternalTagging* tagging = GNUNET_new(struct GNUNET_CHAT_InternalTagging); 39 40 tagging->tags = GNUNET_CONTAINER_multihashmap_create( 41 initial_map_size_of_tagging, GNUNET_NO); 42 43 return tagging; 44 } 45 46 void 47 internal_tagging_destroy (struct GNUNET_CHAT_InternalTagging *tagging) 48 { 49 GNUNET_assert( 50 (tagging) && 51 (tagging->tags) 52 ); 53 54 GNUNET_CONTAINER_multihashmap_destroy(tagging->tags); 55 56 GNUNET_free(tagging); 57 } 58 59 static void 60 convert_tag_to_hash (const char *tag, struct GNUNET_HashCode *hash) 61 { 62 GNUNET_assert(hash); 63 64 if (tag) 65 GNUNET_CRYPTO_hash(tag, strlen(tag), hash); 66 else 67 memset(hash, 0, sizeof(*hash)); 68 } 69 70 enum GNUNET_GenericReturnValue 71 internal_tagging_add (struct GNUNET_CHAT_InternalTagging *tagging, 72 struct GNUNET_CHAT_Message *message) 73 { 74 GNUNET_assert((tagging) && (message)); 75 76 if ((GNUNET_YES != message_has_msg(message)) || 77 (GNUNET_MESSENGER_KIND_TAG != message->msg->header.kind)) 78 return GNUNET_SYSERR; 79 80 const char *tag = message->msg->body.tag.tag; 81 82 struct GNUNET_HashCode hash; 83 convert_tag_to_hash(tag, &hash); 84 85 return GNUNET_CONTAINER_multihashmap_put( 86 tagging->tags, 87 &hash, 88 message, 89 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE 90 ); 91 } 92 93 enum GNUNET_GenericReturnValue 94 internal_tagging_remove (struct GNUNET_CHAT_InternalTagging *tagging, 95 const struct GNUNET_CHAT_Message *message) 96 { 97 GNUNET_assert((tagging) && (message)); 98 99 if ((GNUNET_YES != message_has_msg(message)) || 100 (GNUNET_MESSENGER_KIND_TAG != message->msg->header.kind)) 101 return GNUNET_SYSERR; 102 103 const char *tag = message->msg->body.tag.tag; 104 105 struct GNUNET_HashCode hash; 106 convert_tag_to_hash(tag, &hash); 107 108 return GNUNET_CONTAINER_multihashmap_remove( 109 tagging->tags, 110 &hash, 111 message 112 ); 113 } 114 115 struct GNUNET_CHAT_InternalTaggingIterator 116 { 117 GNUNET_CHAT_TaggingCallback cb; 118 void *cls; 119 }; 120 121 static enum GNUNET_GenericReturnValue 122 internal_tagging_iterate_message (void *cls, 123 const struct GNUNET_HashCode *key, 124 void *value) 125 { 126 struct GNUNET_CHAT_InternalTaggingIterator *it = cls; 127 struct GNUNET_CHAT_Message *message = value; 128 129 if (!(it->cb)) 130 return GNUNET_YES; 131 132 return it->cb(it->cls, message); 133 } 134 135 int 136 internal_tagging_iterate (const struct GNUNET_CHAT_InternalTagging *tagging, 137 enum GNUNET_GenericReturnValue ignore_tag, 138 const char *tag, 139 GNUNET_CHAT_TaggingCallback cb, 140 void *cls) 141 { 142 GNUNET_assert(tagging); 143 144 struct GNUNET_CHAT_InternalTaggingIterator it; 145 it.cb = cb; 146 it.cls = cls; 147 148 if (GNUNET_YES == ignore_tag) 149 return GNUNET_CONTAINER_multihashmap_iterate( 150 tagging->tags, 151 internal_tagging_iterate_message, 152 &it 153 ); 154 155 struct GNUNET_HashCode hash; 156 convert_tag_to_hash(tag, &hash); 157 158 return GNUNET_CONTAINER_multihashmap_get_multiple( 159 tagging->tags, 160 &hash, 161 internal_tagging_iterate_message, 162 &it 163 ); 164 }