libgnunetchat

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

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 }