From 8bf864c25bda97c1448b709a76a168834753ff86 Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Thu, 1 Oct 2020 21:13:43 +0200 Subject: adding the messenger service and its client-side library Signed-off-by: TheJackiMonster --- src/messenger/gnunet-service-messenger_tunnel.c | 300 ++++++++++++++++++++++++ 1 file changed, 300 insertions(+) create mode 100644 src/messenger/gnunet-service-messenger_tunnel.c (limited to 'src/messenger/gnunet-service-messenger_tunnel.c') diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c new file mode 100644 index 000000000..df9e5c4c7 --- /dev/null +++ b/src/messenger/gnunet-service-messenger_tunnel.c @@ -0,0 +1,300 @@ +/* + This file is part of GNUnet. + Copyright (C) 2020 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_tunnel.c + * @brief GNUnet MESSENGER service + */ + +#include "gnunet-service-messenger_tunnel.h" + +#include "gnunet-service-messenger_handle.h" +#include "gnunet-service-messenger_util.h" + +struct GNUNET_MESSENGER_SrvTunnel* +create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door) +{ + GNUNET_assert((room) && (door)); + + struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new(struct GNUNET_MESSENGER_SrvTunnel); + + tunnel->room = room; + tunnel->channel = NULL; + + tunnel->peer = GNUNET_PEER_intern (door); + tunnel->contact_id = NULL; + + tunnel->peer_message = NULL; + tunnel->last_message = NULL; + + return tunnel; +} + +void +destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) +{ + GNUNET_assert(tunnel); + + if (tunnel->channel) + GNUNET_CADET_channel_destroy (tunnel->channel); + + GNUNET_PEER_change_rc (tunnel->peer, -1); + + if (tunnel->contact_id) + GNUNET_free(tunnel->contact_id); + + if (tunnel->peer_message) + GNUNET_free(tunnel->peer_message); + + if (tunnel->last_message) + GNUNET_free(tunnel->last_message); + + GNUNET_free(tunnel); +} + +int +bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel) +{ + GNUNET_assert(tunnel); + + if (tunnel->channel) + { + if (tunnel->contact_id) + return GNUNET_NO; + + delayed_disconnect_channel (tunnel->channel); + } + + tunnel->channel = channel; + + return GNUNET_YES; +} + +extern void +callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls); + +void +callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel) +{ + struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; + + if (tunnel) + { + tunnel->channel = NULL; + + callback_room_disconnect (tunnel->room, cls); + } +} + +extern int +callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, + struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash); + +int +check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header) +{ + struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; + + if (!tunnel) + return GNUNET_NO; + + const uint16_t length = ntohs (header->size) - sizeof(*header); + const char *buffer = (const char*) &header[1]; + + struct GNUNET_MESSENGER_Message message; + + if (length < sizeof(message.header)) + return GNUNET_NO; + + if (GNUNET_YES != decode_message (&message, length, buffer)) + return GNUNET_NO; + + struct GNUNET_HashCode hash; + hash_message (length, buffer, &hash); + + int result = callback_verify_room_message (tunnel->room, cls, &message, &hash); + + if (GNUNET_MESSENGER_KIND_PEER == message.header.kind) + { + struct GNUNET_PeerIdentity identity; + + GNUNET_PEER_resolve (tunnel->peer, &identity); + + if (0 == GNUNET_memcmp(&(message.body.peer.peer), &(identity))) + { + if (tunnel->contact_id) + { + if (0 != GNUNET_memcmp(tunnel->contact_id, &(message.header.sender_id))) + result = GNUNET_SYSERR; + } + else + { + tunnel->contact_id = GNUNET_new(struct GNUNET_ShortHashCode); + + GNUNET_memcpy(tunnel->contact_id, &(message.header.sender_id), sizeof(struct GNUNET_ShortHashCode)); + } + } + } + + return (result == GNUNET_YES ? GNUNET_OK : GNUNET_NO); +} + +extern void +callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message, + const struct GNUNET_HashCode *hash); + +void +handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header) +{ + struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; + + const uint16_t length = ntohs (header->size) - sizeof(*header); + const char *buffer = (const char*) &header[1]; + + struct GNUNET_MESSENGER_Message message; + struct GNUNET_HashCode hash; + + decode_message (&message, length, buffer); + hash_message (length, buffer, &hash); + + if (tunnel) + { + if (!tunnel->last_message) + tunnel->last_message = GNUNET_new(struct GNUNET_HashCode); + + GNUNET_memcpy(tunnel->last_message, &hash, sizeof(struct GNUNET_HashCode)); + + callback_room_recv (tunnel->room, cls, copy_message (&message), &hash); + } + + GNUNET_CADET_receive_done (tunnel->channel); +} + +int +connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) +{ + GNUNET_assert(tunnel); + + if (tunnel->channel) + return GNUNET_NO; + + const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer); + + struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room); + struct GNUNET_HashCode *key = get_room_key (tunnel->room); + + struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI, + struct GNUNET_MessageHeader, NULL), + GNUNET_MQ_handler_end() }; + + tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, key, NULL, callback_tunnel_disconnect, handlers); + + return GNUNET_YES; +} + +void +disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel) +{ + if (tunnel->channel) + { + delayed_disconnect_channel (tunnel->channel); + + tunnel->channel = NULL; + } +} + +int +is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) +{ + return (tunnel->channel ? GNUNET_YES : GNUNET_NO); +} + +struct GNUNET_MESSENGER_MessageSent +{ + struct GNUNET_MESSENGER_SrvTunnel *tunnel; + struct GNUNET_HashCode hash; +}; + +extern void +callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls, + struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash); + +static void +callback_tunnel_sent (void *cls) +{ + struct GNUNET_MESSENGER_MessageSent *sent = cls; + + if (sent->tunnel) + { + if (!sent->tunnel->last_message) + sent->tunnel->last_message = GNUNET_new(struct GNUNET_HashCode); + + GNUNET_memcpy(sent->tunnel->last_message, &(sent->hash), sizeof(struct GNUNET_HashCode)); + } + + GNUNET_free(sent); +} + +void +send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MQ_Envelope *env, + struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash) +{ + struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel); + + struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent); + + GNUNET_memcpy(&(sent->hash), hash, sizeof(struct GNUNET_HashCode)); + + sent->tunnel = tunnel; + + GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent); + GNUNET_MQ_send (mq, env); + + callback_room_sent (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, tunnel, message, hash); +} + +void +send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message, + struct GNUNET_HashCode *hash) +{ + struct GNUNET_MQ_Envelope *env = pack_room_message (tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle, + message, hash, + GNUNET_MESSENGER_PACK_MODE_ENVELOPE); + + if (env) + send_tunnel_envelope (tunnel, handle, env, copy_message (message), hash); +} + +void +forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message, + const struct GNUNET_HashCode *hash) +{ + struct GNUNET_MESSENGER_Message *clone = copy_message (message); + struct GNUNET_MQ_Envelope *env = pack_message (clone, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE); + + if (env) + send_tunnel_envelope (tunnel, NULL, env, clone, hash); +} + +const struct GNUNET_HashCode* +get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel) +{ + return tunnel->peer_message; +} -- cgit v1.2.3