From 2925310d67483aca6e055e1ce0593c6463cd6c72 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Sun, 1 Nov 2020 22:57:28 +0100 Subject: -added core functionality of the messenger service Signed-off-by: TheJackiMonster formatting messenger code Signed-off-by: TheJackiMonster -completed core functionality of messenger service Signed-off-by: TheJackiMonster -code cleanup and reuse Signed-off-by: TheJackiMonster +added structure to memberships of rooms Signed-off-by: TheJackiMonster -implemented member permission checks and deletion of messages Signed-off-by: TheJackiMonster -moved solving requests out of updating last messages (also forward before update) Signed-off-by: TheJackiMonster -reduced complexity of permisson check and changed load/save of rooms Signed-off-by: TheJackiMonster -added save/load for accessed keys and basement peers of a room Signed-off-by: TheJackiMonster -implemented save/load for members with their history and session Signed-off-by: TheJackiMonster -abstracted management of egos and contacts Signed-off-by: TheJackiMonster -fix warning Signed-off-by: TheJackiMonster -abstracted management of members Signed-off-by: TheJackiMonster -fixed and adjusted test case Signed-off-by: TheJackiMonster -separated handling of direct and anonymous contacts Signed-off-by: TheJackiMonster -messenger added member-sessions which fix multiple edge cases, also additional cleanup Signed-off-by: TheJackiMonster -updated docs and fixed memory leak Signed-off-by: TheJackiMonster -changed info messages and added protocol version exchange Signed-off-by: TheJackiMonster -adjusted client api to use contacts from sessions Signed-off-by: TheJackiMonster -added more logging and fixed wrong session usage Signed-off-by: TheJackiMonster -adjusted comm0 test case and removed adding members from checking messages Signed-off-by: TheJackiMonster -fixed test-case for peer exchange Signed-off-by: TheJackiMonster -getting multiple peers connected in test-case with cadet Signed-off-by: TheJackiMonster -fixed wrong assert and added tunnel version check -simplified handling and forwarding Signed-off-by: TheJackiMonster -fixed merging last messages and cycling info messages Signed-off-by: TheJackiMonster -automated adding sessions and members Signed-off-by: TheJackiMonster -corrected use of identity keys and signatures Signed-off-by: TheJackiMonster -adding local joining on entering external room Signed-off-by: TheJackiMonster -fixed test-case comm0 Signed-off-by: TheJackiMonster -added more test-cases with generic setup Signed-off-by: TheJackiMonster -fixed multiple simultaneous channels blocking each other Signed-off-by: TheJackiMonster -making test-cases more precise Signed-off-by: TheJackiMonster -added check of members in test-cases, reduced merge messages Signed-off-by: TheJackiMonster -unified delayed operations: requests, deletions and merges Signed-off-by: TheJackiMonster -finished handling of operations Signed-off-by: TheJackiMonster -fixed member session historystorage, added request permission check and padding for transmission Signed-off-by: TheJackiMonster -improved padding and removed automatic recursive requests Signed-off-by: TheJackiMonster -implemented filter for sending messages and added private messages to API level Signed-off-by: TheJackiMonster -wrong setups fixed with proper ego lookups Signed-off-by: TheJackiMonster -fixed problem with anonymous ego and changed to discrete-level padding Signed-off-by: TheJackiMonster -added links to replace deleted messages, added local deletion and fixed anonymous id changing Signed-off-by: TheJackiMonster -added session completion and removal through completion process Signed-off-by: TheJackiMonster --- src/messenger/gnunet-service-messenger_ego_store.c | 295 +++++++++++++++++++++ 1 file changed, 295 insertions(+) create mode 100644 src/messenger/gnunet-service-messenger_ego_store.c (limited to 'src/messenger/gnunet-service-messenger_ego_store.c') diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c new file mode 100644 index 000000000..3b069fcf5 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_ego_store.c @@ -0,0 +1,295 @@ +/* + This file is part of GNUnet. + Copyright (C) 2020--2021 GNUnet e.V. + + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + + SPDX-License-Identifier: AGPL3.0-or-later + */ +/** + * @author Tobias Frisch + * @file src/messenger/gnunet-service-messenger_ego_store.c + * @brief GNUnet MESSENGER service + */ + +#include "gnunet-service-messenger_ego_store.h" + +#include "gnunet-service-messenger_handle.h" + +static void +callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier) +{ + if ((!ego) || (!identifier)) + return; + + struct GNUNET_MESSENGER_EgoStore *store = cls; + + GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier); + + update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego)); +} + +void +init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config) +{ + GNUNET_assert ((store) && (config)); + + store->cfg = config; + store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store); + store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); + + store->lu_start = NULL; + store->lu_end = NULL; + + store->op_start = NULL; + store->op_end = NULL; +} + + +static int +iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value) +{ + struct GNUNET_MESSENGER_Ego *ego = value; + GNUNET_free(ego); + return GNUNET_YES; +} + +void +clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store) +{ + GNUNET_assert (store); + + struct GNUNET_MESSENGER_EgoOperation *op; + + while (store->op_start) + { + op = store->op_start; + + GNUNET_IDENTITY_cancel (op->operation); + GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op); + + if (op->identifier) + GNUNET_free (op->identifier); + + GNUNET_free (op); + } + + struct GNUNET_MESSENGER_EgoLookup *lu; + + while (store->lu_start) + { + lu = store->lu_start; + + GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup); + GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu); + + if (lu->identifier) + GNUNET_free(lu->identifier); + + GNUNET_free (lu); + } + + GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL); + GNUNET_CONTAINER_multihashmap_destroy (store->egos); + + if (store->identity) + { + GNUNET_IDENTITY_disconnect (store->identity); + + store->identity = NULL; + } +} + +static void +callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg) +{ + struct GNUNET_MESSENGER_EgoOperation *element = cls; + struct GNUNET_MESSENGER_EgoStore *store = element->store; + + GNUNET_assert(element->identifier); + + if (emsg) + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); + + if (key) + { + struct GNUNET_MESSENGER_SrvHandle *handle = element->handle; + + struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key); + + set_handle_ego (handle, msg_ego); + } + else + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n"); + + GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element); + GNUNET_free (element->identifier); + GNUNET_free (element); +} + +void +create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, + void *handle) +{ + GNUNET_assert ((store) && (identifier)); + + struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation); + + element->store = store; + element->handle = handle; + + element->identifier = GNUNET_strdup (identifier); + + element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL, + GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element); + + GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element); +} + +static void +callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego) +{ + struct GNUNET_MESSENGER_EgoLookup *element = cls; + struct GNUNET_MESSENGER_EgoStore *store = element->store; + + GNUNET_assert(element->identifier); + + struct GNUNET_MESSENGER_Ego *msg_ego; + + if (ego) + msg_ego = update_store_ego ( + store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego) + ); + else + msg_ego = NULL; + + if (element->cb) + element->cb(element->cls, element->identifier, msg_ego); + + GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element); + GNUNET_free (element->identifier); + GNUNET_free (element); +} + +void +lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, + GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls) +{ + GNUNET_assert (store); + + if (!identifier) + { + lookup(cls, identifier, NULL); + return; + } + + struct GNUNET_HashCode hash; + GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash); + + struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); + + if (ego) + lookup(cls, identifier, ego); + else + { + struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup); + + element->store = store; + + element->cb = lookup; + element->cls = cls; + + element->identifier = GNUNET_strdup (identifier); + + element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element); + + GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element); + } +} + +struct GNUNET_MESSENGER_Ego* +update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier, + const struct GNUNET_IDENTITY_PrivateKey *key) +{ + GNUNET_assert ((store) && (identifier) && (key)); + + struct GNUNET_HashCode hash; + GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash); + + struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); + + if (!ego) + { + ego = GNUNET_new(struct GNUNET_MESSENGER_Ego); + GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + } + + GNUNET_memcpy(&(ego->priv), key, sizeof(*key)); + + if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub))) + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n"); + + return ego; +} + +static void +callback_ego_rename (void *cls, const char *emsg) +{ + struct GNUNET_MESSENGER_EgoOperation *element = cls; + struct GNUNET_MESSENGER_EgoStore *store = element->store; + + GNUNET_assert(element->identifier); + + if (emsg) + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg); + + struct GNUNET_HashCode hash; + GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash); + + struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash); + + if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego)) + { + GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash); + + GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, + GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); + } + else + GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n"); + + GNUNET_free (element->handle); + + GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element); + GNUNET_free (element->identifier); + GNUNET_free (element); +} + +void +rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier, + const char *new_identifier) +{ + GNUNET_assert ((store) && (old_identifier) && (new_identifier)); + + struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation); + + element->store = store; + element->handle = GNUNET_strdup (new_identifier); + + element->identifier = GNUNET_strdup (old_identifier); + + element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element); + + GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element); +} -- cgit v1.2.3