aboutsummaryrefslogtreecommitdiff
path: root/src/messenger
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger')
-rw-r--r--src/messenger/.gitignore14
-rw-r--r--src/messenger/Makefile.am222
-rw-r--r--src/messenger/gnunet-messenger.c325
-rw-r--r--src/messenger/gnunet-service-messenger.c399
-rw-r--r--src/messenger/gnunet-service-messenger.h137
-rw-r--r--src/messenger/gnunet-service-messenger_basement.c60
-rw-r--r--src/messenger/gnunet-service-messenger_basement.h66
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c295
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h152
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c672
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h238
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c101
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.h98
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.c150
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.h109
-rw-r--r--src/messenger/gnunet-service-messenger_member.c386
-rw-r--r--src/messenger/gnunet-service-messenger_member.h170
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c743
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h288
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c250
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.h151
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c136
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.h142
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.c239
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.h172
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c175
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.h81
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c68
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h89
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.c109
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.h63
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.c549
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.h162
-rw-r--r--src/messenger/gnunet-service-messenger_operation.c214
-rw-r--r--src/messenger/gnunet-service-messenger_operation.h129
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.c226
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.h131
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1210
-rw-r--r--src/messenger/gnunet-service-messenger_room.h348
-rw-r--r--src/messenger/gnunet-service-messenger_service.c306
-rw-r--r--src/messenger/gnunet-service-messenger_service.h201
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c383
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h186
-rw-r--r--src/messenger/messenger.conf.in13
-rw-r--r--src/messenger/messenger_api.c755
-rw-r--r--src/messenger/messenger_api_contact.c108
-rw-r--r--src/messenger/messenger_api_contact.h114
-rw-r--r--src/messenger/messenger_api_contact_store.c185
-rw-r--r--src/messenger/messenger_api_contact_store.h122
-rw-r--r--src/messenger/messenger_api_ego.h38
-rw-r--r--src/messenger/messenger_api_handle.c196
-rw-r--r--src/messenger/messenger_api_handle.h171
-rw-r--r--src/messenger/messenger_api_list_tunnels.c184
-rw-r--r--src/messenger/messenger_api_list_tunnels.h130
-rw-r--r--src/messenger/messenger_api_message.c877
-rw-r--r--src/messenger/messenger_api_message.h225
-rw-r--r--src/messenger/messenger_api_room.c341
-rw-r--r--src/messenger/messenger_api_room.h140
-rw-r--r--src/messenger/messenger_api_util.c100
-rw-r--r--src/messenger/messenger_api_util.h78
-rw-r--r--src/messenger/test_messenger.c177
-rw-r--r--src/messenger/test_messenger_adapt.c47
-rw-r--r--src/messenger/test_messenger_anonymous.c169
-rw-r--r--src/messenger/test_messenger_api.conf47
-rw-r--r--src/messenger/test_messenger_async_client.c47
-rw-r--r--src/messenger/test_messenger_async_p2p.c47
-rw-r--r--src/messenger/test_messenger_growth.c47
-rw-r--r--src/messenger/test_messenger_ring.c47
-rw-r--r--src/messenger/test_messenger_server.c47
-rw-r--r--src/messenger/test_messenger_sync_client.c47
-rw-r--r--src/messenger/test_messenger_sync_p2p.c47
-rw-r--r--src/messenger/test_messenger_worst_client.c47
-rw-r--r--src/messenger/test_messenger_worst_p2p.c47
-rw-r--r--src/messenger/testing_messenger_barrier.c170
-rw-r--r--src/messenger/testing_messenger_barrier.h131
-rw-r--r--src/messenger/testing_messenger_setup.c528
-rw-r--r--src/messenger/testing_messenger_setup.h39
77 files changed, 0 insertions, 15853 deletions
diff --git a/src/messenger/.gitignore b/src/messenger/.gitignore
deleted file mode 100644
index ed78c5562..000000000
--- a/src/messenger/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
1gnunet-service-messenger
2gnunet-messenger
3test_messenger_api
4test_messenger_anonymous
5test_messenger_sync_client
6test_messenger_async_client
7test_messenger_worst_client
8test_messenger_sync_p2p
9test_messenger_async_p2p
10test_messenger_worst_p2p
11test_messenger_server
12test_messenger_growth
13test_messenger_ring
14test_messenger_adapt
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am
deleted file mode 100644
index 3fc532e7e..000000000
--- a/src/messenger/Makefile.am
+++ /dev/null
@@ -1,222 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include
3
4if USE_COVERAGE
5 AM_CFLAGS = --coverage -O0
6 XLIB = -lgcov
7endif
8
9pkgcfgdir= $(pkgdatadir)/config.d/
10
11libexecdir= $(pkglibdir)/libexec/
12
13pkgcfg_DATA = \
14 messenger.conf
15
16plugindir = $(libdir)/gnunet
17
18AM_CLFAGS = -g
19
20libexec_PROGRAMS = \
21 gnunet-service-messenger \
22 $(EXP_LIBEXEC)
23
24bin_PROGRAMS = \
25 gnunet-messenger
26
27lib_LTLIBRARIES = \
28 libgnunetmessenger.la \
29 $(EXP_LIB)
30
31libgnunetmessenger_la_SOURCES = \
32 messenger_api.c \
33 messenger_api_ego.h \
34 messenger_api_contact.c messenger_api_contact.h \
35 messenger_api_contact_store.c messenger_api_contact_store.h \
36 messenger_api_message.c messenger_api_message.h \
37 messenger_api_list_tunnels.c messenger_api_list_tunnels.h \
38 messenger_api_util.c messenger_api_util.h \
39 messenger_api_handle.c messenger_api_handle.h \
40 messenger_api_room.c messenger_api_room.h
41libgnunetmessenger_la_LIBADD = \
42 $(top_builddir)/src/util/libgnunetutil.la \
43 $(top_builddir)/src/cadet/libgnunetcadet.la \
44 $(top_builddir)/src/identity/libgnunetidentity.la \
45 $(XLIB) \
46 $(LTLIBINTL)
47libgnunetmessenger_la_LDFLAGS = \
48 $(GN_LIB_LDFLAGS) \
49 -version-info 0:0:0
50
51gnunet_messenger_SOURCES = \
52 gnunet-messenger.c
53gnunet_messenger_LDADD = \
54 libgnunetmessenger.la \
55 $(top_builddir)/src/util/libgnunetutil.la
56gnunet_messenger_LDFLAGS = \
57 $(GN_LIBINTL)
58
59gnunet_service_messenger_SOURCES = \
60 gnunet-service-messenger.c gnunet-service-messenger.h \
61 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \
62 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \
63 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \
64 gnunet-service-messenger_member_session.c gnunet-service-messenger_member_session.h \
65 gnunet-service-messenger_member.c gnunet-service-messenger_member.h \
66 gnunet-service-messenger_member_store.c gnunet-service-messenger_member_store.h \
67 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \
68 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \
69 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \
70 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \
71 gnunet-service-messenger_message_state.c gnunet-service-messenger_message_state.h \
72 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \
73 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \
74 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
75 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \
76 gnunet-service-messenger_ego_store.c gnunet-service-messenger_ego_store.h \
77 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \
78 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \
79 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h
80gnunet_service_messenger_LDADD = \
81 libgnunetmessenger.la \
82 $(top_builddir)/src/util/libgnunetutil.la \
83 $(top_builddir)/src/cadet/libgnunetcadet.la \
84 $(top_builddir)/src/identity/libgnunetidentity.la \
85 $(GN_LIBINTL)
86
87check_PROGRAMS = \
88 test_messenger_api \
89 test_messenger_anonymous \
90 test_messenger_sync_client \
91 test_messenger_async_client \
92 test_messenger_worst_client \
93 test_messenger_sync_p2p \
94 test_messenger_async_p2p \
95 test_messenger_worst_p2p \
96 test_messenger_server \
97 test_messenger_growth \
98 test_messenger_ring \
99 test_messenger_adapt
100
101if ENABLE_TEST_RUN
102AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
103TESTS = \
104 $(check_PROGRAMS)
105endif
106
107test_messenger_api_SOURCES = \
108 test_messenger.c
109test_messenger_api_LDADD = \
110 libgnunetmessenger.la \
111 $(top_builddir)/src/testing/libgnunettesting.la \
112 $(top_builddir)/src/util/libgnunetutil.la
113
114test_messenger_anonymous_SOURCES = \
115 test_messenger_anonymous.c
116test_messenger_anonymous_LDADD = \
117 libgnunetmessenger.la \
118 $(top_builddir)/src/testing/libgnunettesting.la \
119 $(top_builddir)/src/util/libgnunetutil.la
120
121test_messenger_sync_client_SOURCES = \
122 test_messenger_sync_client.c \
123 testing_messenger_barrier.c testing_messenger_barrier.h \
124 testing_messenger_setup.c testing_messenger_setup.h
125test_messenger_sync_client_LDADD = \
126 libgnunetmessenger.la \
127 $(top_builddir)/src/testbed/libgnunettestbed.la \
128 $(top_builddir)/src/testing/libgnunettesting.la \
129 $(top_builddir)/src/util/libgnunetutil.la
130
131test_messenger_async_client_SOURCES = \
132 test_messenger_async_client.c \
133 testing_messenger_barrier.c testing_messenger_barrier.h \
134 testing_messenger_setup.c testing_messenger_setup.h
135test_messenger_async_client_LDADD = \
136 libgnunetmessenger.la \
137 $(top_builddir)/src/testbed/libgnunettestbed.la \
138 $(top_builddir)/src/testing/libgnunettesting.la \
139 $(top_builddir)/src/util/libgnunetutil.la
140
141test_messenger_worst_client_SOURCES = \
142 test_messenger_worst_client.c \
143 testing_messenger_barrier.c testing_messenger_barrier.h \
144 testing_messenger_setup.c testing_messenger_setup.h
145test_messenger_worst_client_LDADD = \
146 libgnunetmessenger.la \
147 $(top_builddir)/src/testbed/libgnunettestbed.la \
148 $(top_builddir)/src/testing/libgnunettesting.la \
149 $(top_builddir)/src/util/libgnunetutil.la
150
151test_messenger_sync_p2p_SOURCES = \
152 test_messenger_sync_p2p.c \
153 testing_messenger_barrier.c testing_messenger_barrier.h \
154 testing_messenger_setup.c testing_messenger_setup.h
155test_messenger_sync_p2p_LDADD = \
156 libgnunetmessenger.la \
157 $(top_builddir)/src/testbed/libgnunettestbed.la \
158 $(top_builddir)/src/testing/libgnunettesting.la \
159 $(top_builddir)/src/util/libgnunetutil.la
160
161test_messenger_async_p2p_SOURCES = \
162 test_messenger_async_p2p.c \
163 testing_messenger_barrier.c testing_messenger_barrier.h \
164 testing_messenger_setup.c testing_messenger_setup.h
165test_messenger_async_p2p_LDADD = \
166 libgnunetmessenger.la \
167 $(top_builddir)/src/testbed/libgnunettestbed.la \
168 $(top_builddir)/src/testing/libgnunettesting.la \
169 $(top_builddir)/src/util/libgnunetutil.la
170
171test_messenger_worst_p2p_SOURCES = \
172 test_messenger_worst_p2p.c \
173 testing_messenger_barrier.c testing_messenger_barrier.h \
174 testing_messenger_setup.c testing_messenger_setup.h
175test_messenger_worst_p2p_LDADD = \
176 libgnunetmessenger.la \
177 $(top_builddir)/src/testbed/libgnunettestbed.la \
178 $(top_builddir)/src/testing/libgnunettesting.la \
179 $(top_builddir)/src/util/libgnunetutil.la
180
181test_messenger_server_SOURCES = \
182 test_messenger_server.c \
183 testing_messenger_barrier.c testing_messenger_barrier.h \
184 testing_messenger_setup.c testing_messenger_setup.h
185test_messenger_server_LDADD = \
186 libgnunetmessenger.la \
187 $(top_builddir)/src/testbed/libgnunettestbed.la \
188 $(top_builddir)/src/testing/libgnunettesting.la \
189 $(top_builddir)/src/util/libgnunetutil.la
190
191test_messenger_growth_SOURCES = \
192 test_messenger_growth.c \
193 testing_messenger_barrier.c testing_messenger_barrier.h \
194 testing_messenger_setup.c testing_messenger_setup.h
195test_messenger_growth_LDADD = \
196 libgnunetmessenger.la \
197 $(top_builddir)/src/testbed/libgnunettestbed.la \
198 $(top_builddir)/src/testing/libgnunettesting.la \
199 $(top_builddir)/src/util/libgnunetutil.la
200
201test_messenger_ring_SOURCES = \
202 test_messenger_ring.c \
203 testing_messenger_barrier.c testing_messenger_barrier.h \
204 testing_messenger_setup.c testing_messenger_setup.h
205test_messenger_ring_LDADD = \
206 libgnunetmessenger.la \
207 $(top_builddir)/src/testbed/libgnunettestbed.la \
208 $(top_builddir)/src/testing/libgnunettesting.la \
209 $(top_builddir)/src/util/libgnunetutil.la
210
211test_messenger_adapt_SOURCES = \
212 test_messenger_adapt.c \
213 testing_messenger_barrier.c testing_messenger_barrier.h \
214 testing_messenger_setup.c testing_messenger_setup.h
215test_messenger_adapt_LDADD = \
216 libgnunetmessenger.la \
217 $(top_builddir)/src/testbed/libgnunettestbed.la \
218 $(top_builddir)/src/testing/libgnunettesting.la \
219 $(top_builddir)/src/util/libgnunetutil.la
220
221EXTRA_DIST = \
222 test_messenger_api.conf
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c
deleted file mode 100644
index 28fa4b147..000000000
--- a/src/messenger/gnunet-messenger.c
+++ /dev/null
@@ -1,325 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-messenger.c
23 * @brief Print information about messenger groups.
24 */
25
26#include <stdio.h>
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_messenger_service.h"
31
32struct GNUNET_MESSENGER_Handle *messenger;
33
34/**
35 * Function called whenever a message is received or sent.
36 *
37 * @param[in/out] cls Closure
38 * @param[in] room Room
39 * @param[in] sender Sender of message
40 * @param[in] message Message
41 * @param[in] hash Hash of message
42 * @param[in] flags Flags of message
43 */
44void
45on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
46 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
47 enum GNUNET_MESSENGER_MessageFlags flags)
48{
49 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
50
51 if (!sender_name)
52 sender_name = "anonymous";
53
54 printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
55
56 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
57 printf ("*");
58
59 switch (message->header.kind)
60 {
61 case GNUNET_MESSENGER_KIND_JOIN:
62 {
63 printf ("* '%s' joined the room!\n", sender_name);
64 break;
65 }
66 case GNUNET_MESSENGER_KIND_NAME:
67 {
68 printf ("* '%s' gets renamed to '%s'\n", sender_name, message->body.name.name);
69 break;
70 }
71 case GNUNET_MESSENGER_KIND_LEAVE:
72 {
73 printf ("* '%s' leaves the room!\n", sender_name);
74 break;
75 }
76 case GNUNET_MESSENGER_KIND_PEER:
77 {
78 printf ("* '%s' opened the room on: %s\n", sender_name, GNUNET_i2s_full (&(message->body.peer.peer)));
79 break;
80 }
81 case GNUNET_MESSENGER_KIND_TEXT:
82 {
83 if (flags & GNUNET_MESSENGER_FLAG_SENT)
84 printf (">");
85 else
86 printf ("<");
87
88 printf (" '%s' says: \"%s\"\n", sender_name, message->body.text.text);
89 break;
90 }
91 default:
92 {
93 printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
94 break;
95 }
96 }
97}
98
99struct GNUNET_SCHEDULER_Task *read_task;
100
101/**
102 * Task to shut down this application.
103 *
104 * @param[in/out] cls Closure
105 */
106static void
107shutdown_hook (void *cls)
108{
109 struct GNUNET_MESSENGER_Room *room = cls;
110
111 if (read_task)
112 GNUNET_SCHEDULER_cancel (read_task);
113
114 if (room)
115 GNUNET_MESSENGER_close_room (room);
116
117 if (messenger)
118 GNUNET_MESSENGER_disconnect (messenger);
119}
120
121static void
122listen_stdio (void *cls);
123
124#define MAX_BUFFER_SIZE 60000
125
126static int
127iterate_send_private_message (void *cls, struct GNUNET_MESSENGER_Room *room,
128 const struct GNUNET_MESSENGER_Contact *contact)
129{
130 struct GNUNET_MESSENGER_Message *message = cls;
131
132 if (GNUNET_MESSENGER_contact_get_key(contact))
133 GNUNET_MESSENGER_send_message (room, message, contact);
134
135 return GNUNET_YES;
136}
137
138int private_mode;
139
140/**
141 * Task run in stdio mode, after some data is available at stdin.
142 *
143 * @param[in/out] cls Closure
144 */
145static void
146read_stdio (void *cls)
147{
148 read_task = NULL;
149
150 char buffer[MAX_BUFFER_SIZE];
151 ssize_t length;
152
153 length = read (0, buffer, MAX_BUFFER_SIZE);
154
155 if ((length <= 0) || (length >= MAX_BUFFER_SIZE))
156 {
157 GNUNET_SCHEDULER_shutdown ();
158 return;
159 }
160
161 if (buffer[length - 1] == '\n')
162 buffer[length - 1] = '\0';
163 else
164 buffer[length] = '\0';
165
166 struct GNUNET_MESSENGER_Room *room = cls;
167
168 struct GNUNET_MESSENGER_Message message;
169 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
170 message.body.text.text = buffer;
171
172 if (GNUNET_YES == private_mode)
173 GNUNET_MESSENGER_iterate_members(room, iterate_send_private_message, &message);
174 else
175 GNUNET_MESSENGER_send_message (room, &message, NULL);
176
177 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
178}
179
180/**
181 * Wait for input on STDIO and send it out over the #ch.
182 *
183 * @param[in/out] cls Closure
184 */
185static void
186listen_stdio (void *cls)
187{
188 read_task = NULL;
189
190 struct GNUNET_NETWORK_FDSet *rs = GNUNET_NETWORK_fdset_create ();
191
192 GNUNET_NETWORK_fdset_set_native (rs, 0);
193
194 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
195 GNUNET_TIME_UNIT_FOREVER_REL, rs,
196 NULL, &read_stdio, cls);
197
198 GNUNET_NETWORK_fdset_destroy (rs);
199}
200
201/**
202 * Initial task to startup application.
203 *
204 * @param[in/out] cls Closure
205 */
206static void
207idle (void *cls)
208{
209 struct GNUNET_MESSENGER_Room *room = cls;
210
211 printf ("* You joined the room.\n");
212
213 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room);
214}
215
216char *door_id;
217char *ego_name;
218char *room_key;
219
220struct GNUNET_SCHEDULER_Task *shutdown_task;
221
222/**
223 * Function called when an identity is retrieved.
224 *
225 * @param[in/out] cls Closure
226 * @param[in/out] handle Handle of messenger service
227 */
228static void
229on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
230{
231 struct GNUNET_HashCode key;
232 memset (&key, 0, sizeof(key));
233
234 if (room_key)
235 GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
236
237 struct GNUNET_PeerIdentity door_peer;
238 struct GNUNET_PeerIdentity *door = NULL;
239
240 if ((door_id) &&
241 (GNUNET_OK == GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door_peer.public_key))))
242 door = &door_peer;
243
244 const char *name = GNUNET_MESSENGER_get_name (handle);
245
246 if (!name)
247 name = "anonymous";
248
249 printf ("* Welcome to the messenger, '%s'!\n", name);
250
251 struct GNUNET_MESSENGER_Room *room;
252
253 if (door)
254 {
255 printf ("* You try to entry a room...\n");
256
257 room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
258 }
259 else
260 {
261 printf ("* You try to open a room...\n");
262
263 room = GNUNET_MESSENGER_open_room (messenger, &key);
264 }
265
266 GNUNET_SCHEDULER_cancel (shutdown_task);
267
268 shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room);
269
270 if (!room)
271 GNUNET_SCHEDULER_shutdown ();
272 else
273 {
274 struct GNUNET_MESSENGER_Message message;
275 message.header.kind = GNUNET_MESSENGER_KIND_NAME;
276 message.body.name.name = GNUNET_strdup(name);
277
278 GNUNET_MESSENGER_send_message (room, &message, NULL);
279 GNUNET_free(message.body.name.name);
280
281 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
282 room);
283 }
284}
285
286/**
287 * Main function that will be run by the scheduler.
288 *
289 * @param[in/out] cls closure
290 * @param[in] args remaining command-line arguments
291 * @param[in] cfgfile name of the configuration file used (for saving, can be NULL!)
292 * @param[in] cfg configuration
293 */
294static void
295run (void *cls, char *const*args, const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *cfg)
296{
297 messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL);
298
299 shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
300}
301
302/**
303 * The main function to obtain messenger information.
304 *
305 * @param[in] argc number of arguments from the command line
306 * @param[in] argv command line arguments
307 * @return #EXIT_SUCCESS ok, #EXIT_FAILURE on error
308 */
309int
310main (int argc, char **argv)
311{
312 const char *description = "Open and connect to rooms using the MESSENGER to chat.";
313
314 struct GNUNET_GETOPT_CommandLineOption options[] =
315 {
316 GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
317 GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
318 GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
319 GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
320 GNUNET_GETOPT_OPTION_END
321 };
322
323 return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
324 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
325}
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
deleted file mode 100644
index 7edd76d32..000000000
--- a/src/messenger/gnunet-service-messenger.c
+++ /dev/null
@@ -1,399 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger.h"
27
28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_kind.h"
30#include "gnunet-service-messenger_service.h"
31#include "messenger_api_message.h"
32
33struct GNUNET_MESSENGER_Client
34{
35 struct GNUNET_SERVICE_Client *client;
36 struct GNUNET_MESSENGER_SrvHandle *handle;
37};
38
39struct GNUNET_MESSENGER_Service *messenger;
40
41static int
42check_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg)
43{
44 GNUNET_MQ_check_zero_termination(msg);
45 return GNUNET_OK;
46}
47
48static void
49handle_create (void *cls, const struct GNUNET_MESSENGER_CreateMessage *msg)
50{
51 struct GNUNET_MESSENGER_Client *msg_client = cls;
52
53 const char *name = ((const char*) msg) + sizeof(*msg);
54
55 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
56
57 setup_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
58
59 GNUNET_SERVICE_client_continue (msg_client->client);
60}
61
62static void
63handle_update (void *cls, const struct GNUNET_MESSENGER_UpdateMessage *msg)
64{
65 struct GNUNET_MESSENGER_Client *msg_client = cls;
66
67 update_handle (msg_client->handle);
68
69 GNUNET_SERVICE_client_continue (msg_client->client);
70}
71
72static void
73handle_destroy (void *cls, const struct GNUNET_MESSENGER_DestroyMessage *msg)
74{
75 struct GNUNET_MESSENGER_Client *msg_client = cls;
76
77 GNUNET_SERVICE_client_drop (msg_client->client);
78}
79
80static int
81check_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
82{
83 GNUNET_MQ_check_zero_termination(msg);
84 return GNUNET_OK;
85}
86
87static void
88handle_set_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
89{
90 struct GNUNET_MESSENGER_Client *msg_client = cls;
91
92 const char *name = ((const char*) msg) + sizeof(*msg);
93
94 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
95
96 set_handle_name (msg_client->handle, name);
97
98 GNUNET_SERVICE_client_continue (msg_client->client);
99}
100
101static void
102handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
103{
104 struct GNUNET_MESSENGER_Client *msg_client = cls;
105
106 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (&(msg->key)));
107
108 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key)))
109 {
110 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
111
112 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", GNUNET_sh2s (member_id));
113
114 struct GNUNET_MESSENGER_RoomMessage *response;
115 struct GNUNET_MQ_Envelope *env;
116
117 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
118 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
119 GNUNET_MQ_send (msg_client->handle->mq, env);
120 }
121 else
122 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", GNUNET_h2s (&(msg->key)));
123
124 GNUNET_SERVICE_client_continue (msg_client->client);
125}
126
127static void
128handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
129{
130 struct GNUNET_MESSENGER_Client *msg_client = cls;
131
132 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
133
134 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key)))
135 {
136 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
137
138 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", GNUNET_sh2s (member_id));
139
140 struct GNUNET_MESSENGER_RoomMessage *response;
141 struct GNUNET_MQ_Envelope *env;
142
143 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
144 GNUNET_memcpy(&(response->door), &(msg->door), sizeof(msg->door));
145 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
146 GNUNET_MQ_send (msg_client->handle->mq, env);
147 }
148 else
149 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", GNUNET_h2s (&(msg->key)),
150 GNUNET_i2s (&(msg->door)));
151
152 GNUNET_SERVICE_client_continue (msg_client->client);
153}
154
155static void
156handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
157{
158 struct GNUNET_MESSENGER_Client *msg_client = cls;
159
160 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room: %s\n", GNUNET_h2s (&(msg->key)));
161
162 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key)))
163 {
164 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
165
166 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", GNUNET_sh2s (member_id));
167
168 struct GNUNET_MESSENGER_RoomMessage *response;
169 struct GNUNET_MQ_Envelope *env;
170
171 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
172 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
173 GNUNET_MQ_send (msg_client->handle->mq, env);
174 }
175 else
176 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Closing room failed: %s\n", GNUNET_h2s (&(msg->key)));
177
178 GNUNET_SERVICE_client_continue (msg_client->client);
179}
180
181static int
182check_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
183{
184 const uint16_t full_length = ntohs (msg->header.size);
185
186 if (full_length < sizeof(*msg))
187 return GNUNET_NO;
188
189 const enum GNUNET_MESSENGER_MessageFlags flags = (
190 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
191 );
192
193 const uint16_t length = full_length - sizeof(*msg);
194 const char *buffer = ((const char*) msg) + sizeof(*msg);
195
196 ssize_t key_length = 0;
197
198 if (!(flags & GNUNET_MESSENGER_FLAG_PRIVATE))
199 goto check_for_message;
200
201 struct GNUNET_IDENTITY_PublicKey public_key;
202
203 key_length = GNUNET_IDENTITY_read_key_from_buffer(&public_key, buffer, length);
204
205check_for_message:
206 if (key_length < 0)
207 return GNUNET_NO;
208
209 const uint16_t msg_length = length - key_length;
210 const char* msg_buffer = buffer + key_length;
211
212 struct GNUNET_MESSENGER_Message message;
213
214 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
215 return GNUNET_NO;
216
217 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL))
218 return GNUNET_NO;
219
220 if (GNUNET_YES != filter_message_sending(&message))
221 return GNUNET_NO;
222
223 return GNUNET_OK;
224}
225
226static void
227handle_send_message (void *cls, const struct GNUNET_MESSENGER_SendMessage *msg)
228{
229 struct GNUNET_MESSENGER_Client *msg_client = cls;
230
231 const enum GNUNET_MESSENGER_MessageFlags flags = (
232 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
233 );
234
235 const struct GNUNET_HashCode *key = &(msg->key);
236 const char *buffer = ((const char*) msg) + sizeof(*msg);
237
238 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
239 ssize_t key_length = 0;
240
241 struct GNUNET_IDENTITY_PublicKey public_key;
242
243 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
244 key_length = GNUNET_IDENTITY_read_key_from_buffer(
245 &public_key, buffer, length
246 );
247
248 const uint16_t msg_length = length - key_length;
249 const char* msg_buffer = buffer + key_length;
250
251 struct GNUNET_MESSENGER_Message message;
252 decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
253
254 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
255 (GNUNET_YES != encrypt_message(&message, &public_key)))
256 {
257 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Encrypting message failed: Message got dropped!\n");
258
259 goto end_handling;
260 }
261
262 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
263 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
264
265 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message))
266 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
267 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
268
269end_handling:
270 GNUNET_SERVICE_client_continue (msg_client->client);
271}
272
273static void
274callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
275 const struct GNUNET_MESSENGER_Message *message,
276 const struct GNUNET_HashCode *hash)
277{
278 struct GNUNET_MESSENGER_Client *msg_client = cls;
279
280 if (!message)
281 {
282 send_room_message(room, msg_client->handle, create_message_request(hash));
283 return;
284 }
285
286 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
287
288 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message);
289
290 if (!member)
291 {
292 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (hash));
293 return;
294 }
295
296 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
297
298 if (session)
299 notify_handle_message (msg_client->handle, get_room_key(room), session, message, hash);
300}
301
302static void
303handle_get_message (void *cls, const struct GNUNET_MESSENGER_GetMessage *msg)
304{
305 struct GNUNET_MESSENGER_Client *msg_client = cls;
306
307 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", GNUNET_h2s (&(msg->key)));
308
309 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key));
310
311 if (!room)
312 {
313 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", GNUNET_h2s (&(msg->key)));
314 goto end_handling;
315 }
316
317 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
318
319 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, get_handle_member_id(
320 msg_client->handle, &(msg->key)
321 ));
322
323 if (!member)
324 {
325 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Member not valid to request a message!\n");
326 goto end_handling;
327 }
328
329 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(msg_client->handle)->pub));
330
331 if (!session)
332 {
333 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Session not valid to request a message!\n");
334 goto end_handling;
335 }
336
337 request_room_message (room, &(msg->hash), session, callback_found_message, msg_client);
338
339end_handling:
340 GNUNET_SERVICE_client_continue (msg_client->client);
341}
342
343static void*
344callback_client_connect (void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
345{
346 struct GNUNET_MESSENGER_Client *msg_client = GNUNET_new(struct GNUNET_MESSENGER_Client);
347
348 msg_client->client = client;
349 msg_client->handle = add_service_handle (messenger, mq);
350
351 return msg_client;
352}
353
354static void
355callback_client_disconnect (void *cls, struct GNUNET_SERVICE_Client *client, void *internal_cls)
356{
357 struct GNUNET_MESSENGER_Client *msg_client = internal_cls;
358
359 remove_service_handle (messenger, msg_client->handle);
360
361 GNUNET_free(msg_client);
362}
363
364/**
365 * Setup MESSENGER internals.
366 *
367 * @param[in/out] cls closure
368 * @param[in] config configuration to use
369 * @param[in/out] service the initialized service
370 */
371static void
372run (void *cls, const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service)
373{
374 messenger = create_service (config, service);
375
376 if (!messenger)
377 GNUNET_SCHEDULER_shutdown ();
378}
379
380/**
381 * Define "main" method using service macro.
382 */
383GNUNET_SERVICE_MAIN(
384 GNUNET_MESSENGER_SERVICE_NAME,
385 GNUNET_SERVICE_OPTION_NONE,
386 &run,
387 &callback_client_connect,
388 &callback_client_disconnect,
389 NULL,
390 GNUNET_MQ_hd_var_size( create, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, struct GNUNET_MESSENGER_CreateMessage, NULL ),
391 GNUNET_MQ_hd_fixed_size( update, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE, struct GNUNET_MESSENGER_UpdateMessage, NULL ),
392 GNUNET_MQ_hd_fixed_size( destroy, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY, struct GNUNET_MESSENGER_DestroyMessage, NULL ),
393 GNUNET_MQ_hd_var_size( set_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME, struct GNUNET_MESSENGER_NameMessage, NULL ),
394 GNUNET_MQ_hd_fixed_size( room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, struct GNUNET_MESSENGER_RoomMessage, NULL ),
395 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ),
396 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ),
397 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ),
398 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_GetMessage, NULL ),
399 GNUNET_MQ_handler_end());
diff --git a/src/messenger/gnunet-service-messenger.h b/src/messenger/gnunet-service-messenger.h
deleted file mode 100644
index 253fbaadb..000000000
--- a/src/messenger/gnunet-service-messenger.h
+++ /dev/null
@@ -1,137 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_H
27#define GNUNET_SERVICE_MESSENGER_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_mq_lib.h"
35#include "gnunet_peer_lib.h"
36#include "gnunet_protocols.h"
37#include "gnunet_util_lib.h"
38
39/**
40 * Message to create a handle for a client
41 */
42struct GNUNET_MESSENGER_CreateMessage
43{
44 struct GNUNET_MessageHeader header;
45};
46
47/**
48 * Message to update the handle (its EGO key) for a client
49 */
50struct GNUNET_MESSENGER_UpdateMessage
51{
52 struct GNUNET_MessageHeader header;
53};
54
55/**
56 * Message to destroy the handle for a client
57 */
58struct GNUNET_MESSENGER_DestroyMessage
59{
60 struct GNUNET_MessageHeader header;
61};
62
63/**
64 * Message to receive the current name of a handle
65 */
66struct GNUNET_MESSENGER_NameMessage
67{
68 struct GNUNET_MessageHeader header;
69};
70
71/**
72 * Message to receive the current public key of a handle
73 */
74struct GNUNET_MESSENGER_KeyMessage
75{
76 struct GNUNET_MessageHeader header;
77};
78
79/**
80 * General message to confirm interaction with a room
81 */
82struct GNUNET_MESSENGER_RoomMessage
83{
84 struct GNUNET_MessageHeader header;
85
86 struct GNUNET_PeerIdentity door;
87 struct GNUNET_HashCode key;
88};
89
90/**
91 * Message to receive the current member id of a handle in room
92 */
93struct GNUNET_MESSENGER_MemberMessage
94{
95 struct GNUNET_MessageHeader header;
96
97 struct GNUNET_HashCode key;
98 struct GNUNET_ShortHashCode id;
99};
100
101/**
102 * Message to send something into a room
103 */
104struct GNUNET_MESSENGER_SendMessage
105{
106 struct GNUNET_MessageHeader header;
107
108 struct GNUNET_HashCode key;
109 uint32_t flags;
110};
111
112/**
113 * Message to request something from a room
114 */
115struct GNUNET_MESSENGER_GetMessage
116{
117 struct GNUNET_MessageHeader header;
118
119 struct GNUNET_HashCode key;
120 struct GNUNET_HashCode hash;
121};
122
123/**
124 * Message to receive something from a room
125 */
126struct GNUNET_MESSENGER_RecvMessage
127{
128 struct GNUNET_MessageHeader header;
129
130 struct GNUNET_HashCode key;
131 struct GNUNET_HashCode sender;
132 struct GNUNET_HashCode context;
133 struct GNUNET_HashCode hash;
134 uint32_t flags;
135};
136
137#endif //GNUNET_SERVICE_MESSENGER_H
diff --git a/src/messenger/gnunet-service-messenger_basement.c b/src/messenger/gnunet-service-messenger_basement.c
deleted file mode 100644
index f302c8d66..000000000
--- a/src/messenger/gnunet-service-messenger_basement.c
+++ /dev/null
@@ -1,60 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_basement.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_basement.h"
27
28size_t
29count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels)
30{
31 GNUNET_assert(tunnels);
32
33 const struct GNUNET_MESSENGER_ListTunnel *element;
34 size_t count = 0;
35
36 for (element = tunnels->head; element; element = element->next)
37 count++;
38
39 return count;
40}
41
42int
43should_connect_tunnel_to (size_t count, size_t src, size_t dst)
44{
45 if ((src + 1) % count == dst % count)
46 return GNUNET_YES;
47
48 return GNUNET_NO;
49}
50
51int
52required_connection_between (size_t count, size_t src, size_t dst)
53{
54 if (GNUNET_YES == should_connect_tunnel_to (count, src, dst))
55 return GNUNET_YES;
56 if (GNUNET_YES == should_connect_tunnel_to (count, dst, src))
57 return GNUNET_YES;
58
59 return GNUNET_NO;
60}
diff --git a/src/messenger/gnunet-service-messenger_basement.h b/src/messenger/gnunet-service-messenger_basement.h
deleted file mode 100644
index b19aec405..000000000
--- a/src/messenger/gnunet-service-messenger_basement.h
+++ /dev/null
@@ -1,66 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_basement.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_BASEMENT_H
27#define GNUNET_SERVICE_MESSENGER_BASEMENT_H
28
29#include "messenger_api_list_tunnels.h"
30
31/**
32 * Returns the count of peers in a list (typically from the basement of a room).
33 *
34 * @param[in] tunnels List of peer identities
35 * @return Count of the entries in the list
36 */
37size_t
38count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels);
39
40/**
41 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peer at index <i>src</i> should
42 * or should not connect outgoing to the peer at index <i>dst</i> to construct a complete
43 * basement with a given <i>count</i> of peers.
44 *
45 * @param[in] count Count of peers
46 * @param[in] src Source index
47 * @param[in] dst Destination index
48 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
49 */
50int
51should_connect_tunnel_to (size_t count, size_t src, size_t dst);
52
53/**
54 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peers of index <i>src</i> and
55 * index <i>dst</i> should be connected in any direction to construct a complete
56 * basement with a given <i>count</i> of peers.
57 *
58 * @param[in] count Count of peers
59 * @param[in] src Source index
60 * @param[in] dst Destination index
61 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
62 */
63int
64required_connection_between (size_t count, size_t src, size_t dst);
65
66#endif //GNUNET_SERVICE_MESSENGER_BASEMENT_H
diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c
deleted file mode 100644
index 3b069fcf5..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.c
+++ /dev/null
@@ -1,295 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_ego_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_ego_store.h"
27
28#include "gnunet-service-messenger_handle.h"
29
30static void
31callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
32{
33 if ((!ego) || (!identifier))
34 return;
35
36 struct GNUNET_MESSENGER_EgoStore *store = cls;
37
38 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
39
40 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
41}
42
43void
44init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config)
45{
46 GNUNET_assert ((store) && (config));
47
48 store->cfg = config;
49 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
50 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
51
52 store->lu_start = NULL;
53 store->lu_end = NULL;
54
55 store->op_start = NULL;
56 store->op_end = NULL;
57}
58
59
60static int
61iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
62{
63 struct GNUNET_MESSENGER_Ego *ego = value;
64 GNUNET_free(ego);
65 return GNUNET_YES;
66}
67
68void
69clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
70{
71 GNUNET_assert (store);
72
73 struct GNUNET_MESSENGER_EgoOperation *op;
74
75 while (store->op_start)
76 {
77 op = store->op_start;
78
79 GNUNET_IDENTITY_cancel (op->operation);
80 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
81
82 if (op->identifier)
83 GNUNET_free (op->identifier);
84
85 GNUNET_free (op);
86 }
87
88 struct GNUNET_MESSENGER_EgoLookup *lu;
89
90 while (store->lu_start)
91 {
92 lu = store->lu_start;
93
94 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
95 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
96
97 if (lu->identifier)
98 GNUNET_free(lu->identifier);
99
100 GNUNET_free (lu);
101 }
102
103 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
104 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
105
106 if (store->identity)
107 {
108 GNUNET_IDENTITY_disconnect (store->identity);
109
110 store->identity = NULL;
111 }
112}
113
114static void
115callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg)
116{
117 struct GNUNET_MESSENGER_EgoOperation *element = cls;
118 struct GNUNET_MESSENGER_EgoStore *store = element->store;
119
120 GNUNET_assert(element->identifier);
121
122 if (emsg)
123 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
124
125 if (key)
126 {
127 struct GNUNET_MESSENGER_SrvHandle *handle = element->handle;
128
129 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
130
131 set_handle_ego (handle, msg_ego);
132 }
133 else
134 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
135
136 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
137 GNUNET_free (element->identifier);
138 GNUNET_free (element);
139}
140
141void
142create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
143 void *handle)
144{
145 GNUNET_assert ((store) && (identifier));
146
147 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
148
149 element->store = store;
150 element->handle = handle;
151
152 element->identifier = GNUNET_strdup (identifier);
153
154 element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL,
155 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element);
156
157 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
158}
159
160static void
161callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego)
162{
163 struct GNUNET_MESSENGER_EgoLookup *element = cls;
164 struct GNUNET_MESSENGER_EgoStore *store = element->store;
165
166 GNUNET_assert(element->identifier);
167
168 struct GNUNET_MESSENGER_Ego *msg_ego;
169
170 if (ego)
171 msg_ego = update_store_ego (
172 store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego)
173 );
174 else
175 msg_ego = NULL;
176
177 if (element->cb)
178 element->cb(element->cls, element->identifier, msg_ego);
179
180 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
181 GNUNET_free (element->identifier);
182 GNUNET_free (element);
183}
184
185void
186lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
187 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls)
188{
189 GNUNET_assert (store);
190
191 if (!identifier)
192 {
193 lookup(cls, identifier, NULL);
194 return;
195 }
196
197 struct GNUNET_HashCode hash;
198 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
199
200 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
201
202 if (ego)
203 lookup(cls, identifier, ego);
204 else
205 {
206 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
207
208 element->store = store;
209
210 element->cb = lookup;
211 element->cls = cls;
212
213 element->identifier = GNUNET_strdup (identifier);
214
215 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
216
217 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
218 }
219}
220
221struct GNUNET_MESSENGER_Ego*
222update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
223 const struct GNUNET_IDENTITY_PrivateKey *key)
224{
225 GNUNET_assert ((store) && (identifier) && (key));
226
227 struct GNUNET_HashCode hash;
228 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
229
230 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
231
232 if (!ego)
233 {
234 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
235 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
236 }
237
238 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
239
240 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
241 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
242
243 return ego;
244}
245
246static void
247callback_ego_rename (void *cls, const char *emsg)
248{
249 struct GNUNET_MESSENGER_EgoOperation *element = cls;
250 struct GNUNET_MESSENGER_EgoStore *store = element->store;
251
252 GNUNET_assert(element->identifier);
253
254 if (emsg)
255 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
256
257 struct GNUNET_HashCode hash;
258 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
259
260 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
261
262 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
263 {
264 GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash);
265
266 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
267 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
268 }
269 else
270 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
271
272 GNUNET_free (element->handle);
273
274 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
275 GNUNET_free (element->identifier);
276 GNUNET_free (element);
277}
278
279void
280rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
281 const char *new_identifier)
282{
283 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
284
285 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
286
287 element->store = store;
288 element->handle = GNUNET_strdup (new_identifier);
289
290 element->identifier = GNUNET_strdup (old_identifier);
291
292 element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element);
293
294 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
295}
diff --git a/src/messenger/gnunet-service-messenger_ego_store.h b/src/messenger/gnunet-service-messenger_ego_store.h
deleted file mode 100644
index 41f14fff2..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.h
+++ /dev/null
@@ -1,152 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_ego_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_EGO_STORE_H
27#define GNUNET_SERVICE_MESSENGER_EGO_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31
32#include "messenger_api_ego.h"
33
34struct GNUNET_MESSENGER_Ego;
35struct GNUNET_MESSENGER_EgoStore;
36
37typedef void
38(*GNUNET_MESSENGER_EgoLookupCallback) (void *cls, const char *identifier,
39 const struct GNUNET_MESSENGER_Ego *ego);
40
41struct GNUNET_MESSENGER_EgoLookup
42{
43 struct GNUNET_MESSENGER_EgoLookup *prev;
44 struct GNUNET_MESSENGER_EgoLookup *next;
45
46 struct GNUNET_IDENTITY_EgoLookup *lookup;
47
48 struct GNUNET_MESSENGER_EgoStore *store;
49
50 GNUNET_MESSENGER_EgoLookupCallback cb;
51 void *cls;
52
53 char *identifier;
54};
55
56struct GNUNET_MESSENGER_EgoOperation
57{
58 struct GNUNET_MESSENGER_EgoOperation *prev;
59 struct GNUNET_MESSENGER_EgoOperation *next;
60
61 struct GNUNET_IDENTITY_Operation *operation;
62
63 struct GNUNET_MESSENGER_EgoStore *store;
64 void *handle;
65
66 char *identifier;
67};
68
69struct GNUNET_MESSENGER_EgoStore
70{
71 const struct GNUNET_CONFIGURATION_Handle *cfg;
72
73 struct GNUNET_IDENTITY_Handle *identity;
74 struct GNUNET_CONTAINER_MultiHashMap *egos;
75
76 struct GNUNET_MESSENGER_EgoLookup *lu_start;
77 struct GNUNET_MESSENGER_EgoLookup *lu_end;
78
79 struct GNUNET_MESSENGER_EgoOperation *op_start;
80 struct GNUNET_MESSENGER_EgoOperation *op_end;
81};
82
83/**
84 * Initializes an EGO-store as fully empty.
85 *
86 * @param[out] store EGO-store
87 * @param[in] config Configuration handle
88 */
89void
90init_ego_store (struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config);
91
92/**
93 * Clears an EGO-store, wipes its content and deallocates its memory.
94 *
95 * @param[in/out] store EGO-store
96 */
97void
98clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store);
99
100/**
101 * Creates a new EGO which will be registered to a <i>store</i> under
102 * a specific <i>identifier</i>. A given <i>handle</i> will be informed
103 * about the creation and changes its EGO accordingly.
104 *
105 * @param[in/out] store EGO-store
106 * @param[in] identifier Identifier string
107 * @param[in/out] handle Handle or NULL
108 */
109void
110create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
111 void *handle);
112
113/**
114 * Lookups an EGO which was registered to a <i>store</i> under
115 * a specific <i>identifier</i>.
116 *
117 * @param[in/out] store EGO-store
118 * @param[in] identifier Identifier string
119 * @param[in] lookup Lookup callback (non-NULL)
120 * @param[in] cls Closure
121 */
122void
123lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
124 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls);
125
126/**
127 * Updates the registration of an EGO to a <i>store</i> under
128 * a specific <i>identifier</i> with a new <i>key</i>.
129 *
130 * @param[in/out] store EGO-store
131 * @param[in] identifier Identifier string
132 * @param[in] key Private EGO key
133 * @return Updated EGO
134 */
135struct GNUNET_MESSENGER_Ego*
136update_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
137 const struct GNUNET_IDENTITY_PrivateKey *key);
138
139/**
140 * Updates the location of a registered EGO in a <i>store</i> to
141 * a different one under a specific <i>new_identifier<i> replacing
142 * its old one.
143 *
144 * @param[in/out] store EGO-store
145 * @param[in] old_identifier Old identifier string
146 * @param[in] new_identifier New identifier string
147 */
148void
149rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
150 const char *new_identifier);
151
152#endif //GNUNET_SERVICE_MESSENGER_EGO_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_handle.c b/src/messenger/gnunet-service-messenger_handle.c
deleted file mode 100644
index d7007dbf6..000000000
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ /dev/null
@@ -1,672 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_handle.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_handle.h"
27
28#include "gnunet-service-messenger.h"
29#include "gnunet-service-messenger_message_kind.h"
30
31#include "messenger_api_util.h"
32
33struct GNUNET_MESSENGER_SrvHandle*
34create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
35{
36 GNUNET_assert((service) && (mq));
37
38 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
39
40 handle->service = service;
41 handle->mq = mq;
42
43 handle->name = NULL;
44 handle->ego = NULL;
45
46 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
47
48 return handle;
49}
50
51int
52iterate_free_member_ids (void *cls, const struct GNUNET_HashCode *key, void *value)
53{
54 GNUNET_free(value);
55
56 return GNUNET_YES;
57}
58
59void
60destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
61{
62 GNUNET_assert(handle);
63
64 if (handle->service->dir)
65 save_handle_configuration (handle);
66
67 if (handle->name)
68 GNUNET_free(handle->name);
69
70 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL);
71 GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
72
73 GNUNET_free(handle);
74}
75
76void
77get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir)
78{
79 GNUNET_assert((handle) && (dir));
80
81 if (name)
82 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
83 DIR_SEPARATOR, name, DIR_SEPARATOR);
84 else
85 GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous",
86 DIR_SEPARATOR);
87}
88
89static int
90create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
91{
92 GNUNET_assert((handle) && (key));
93
94 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
95
96 if (!random_id)
97 return GNUNET_NO;
98
99 generate_free_member_id (random_id, NULL);
100
101 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
102 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
103 {
104 GNUNET_free(random_id);
105 return GNUNET_NO;
106 }
107
108 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
109 GNUNET_h2s (key));
110
111 return GNUNET_YES;
112}
113
114const struct GNUNET_ShortHashCode*
115get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
116{
117 GNUNET_assert((handle) && (key));
118
119 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
120}
121
122int
123change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
124 const struct GNUNET_ShortHashCode *unique_id)
125{
126 GNUNET_assert((handle) && (key) && (unique_id));
127
128 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
129
130 if (!member_id)
131 {
132 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
133 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
134
135 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
136 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
137 {
138 GNUNET_free(member_id);
139 return GNUNET_SYSERR;
140 }
141 }
142
143 if (0 == GNUNET_memcmp(unique_id, member_id))
144 goto send_message_to_client;
145
146 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
147 GNUNET_h2s (key));
148
149 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
150
151 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
152
153 struct GNUNET_MESSENGER_MemberMessage *msg;
154 struct GNUNET_MQ_Envelope *env;
155
156send_message_to_client:
157
158 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
159
160 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
161 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
162
163 GNUNET_MQ_send (handle->mq, env);
164 return GNUNET_OK;
165}
166
167static void
168change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
169{
170 GNUNET_assert(handle);
171
172 if (handle->name)
173 GNUNET_free(handle->name);
174
175 handle->name = name ? GNUNET_strdup(name) : NULL;
176
177 const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
178
179 struct GNUNET_MESSENGER_NameMessage *msg;
180 struct GNUNET_MQ_Envelope *env;
181
182 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
183
184 char *extra = ((char*) msg) + sizeof(*msg);
185
186 if (name_len)
187 GNUNET_memcpy(extra, handle->name, name_len);
188
189 extra[name_len] = '\0';
190
191 GNUNET_MQ_send (handle->mq, env);
192}
193
194static void
195change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
196{
197 GNUNET_assert(handle);
198
199 handle->ego = ego;
200
201 ego = get_handle_ego (handle);
202
203 const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
204
205 struct GNUNET_MESSENGER_KeyMessage *msg;
206 struct GNUNET_MQ_Envelope *env;
207
208 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
209
210 char *extra = ((char*) msg) + sizeof(*msg);
211
212 if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
213 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
214
215 GNUNET_MQ_send (handle->mq, env);
216}
217
218struct GNUNET_MESSENGER_MessageHandle
219{
220 struct GNUNET_MESSENGER_SrvHandle *handle;
221 struct GNUNET_MESSENGER_Message *message;
222};
223
224static int
225iterate_send_message (void *cls, const struct GNUNET_HashCode *key, void *value)
226{
227 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
228
229 send_handle_message (msg_handle->handle, key, msg_handle->message);
230
231 return GNUNET_YES;
232}
233
234void
235set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego)
236{
237 GNUNET_assert((handle) && (ego));
238
239 struct GNUNET_MESSENGER_MessageHandle msg_handle;
240
241 msg_handle.handle = handle;
242 msg_handle.message = create_message_key (&(ego->priv));
243
244 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
245
246 destroy_message (msg_handle.message);
247
248 change_handle_ego (handle, ego);
249}
250
251const struct GNUNET_MESSENGER_Ego*
252get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
253{
254 GNUNET_assert(handle);
255
256 static struct GNUNET_MESSENGER_Ego anonymous;
257 static int read_keys = 0;
258
259 if (handle->ego)
260 return handle->ego;
261
262 if (!read_keys)
263 {
264 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
265 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
266 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
267 read_keys = 1;
268 }
269
270 return &anonymous;
271}
272
273static void
274callback_setup_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
275{
276 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
277
278 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
279
280 change_handle_name (handle, name);
281 change_handle_ego (handle, ego);
282
283 if (handle->service->dir)
284 load_handle_configuration (handle);
285}
286
287void
288setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
289{
290 GNUNET_assert(handle);
291
292 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
293
294 lookup_store_ego (store, name, callback_setup_handle_name, handle);
295}
296
297static void
298callback_update_handle (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
299{
300 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
301
302 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
303
304 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
305
306 if (!ego)
307 create_store_ego(store, handle->name, handle);
308 else
309 change_handle_ego (handle, ego);
310}
311
312void
313update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
314{
315 GNUNET_assert(handle);
316
317 if (!handle->name)
318 {
319 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
320 return;
321 }
322
323 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
324
325 lookup_store_ego (store, handle->name, callback_update_handle, handle);
326}
327
328static void
329callback_set_handle_name (void *cls, const char *name, const struct GNUNET_MESSENGER_Ego *ego)
330{
331 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
332
333 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
334
335 if (ego)
336 {
337 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
338 return;
339 }
340
341 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
342
343 int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
344
345 char *old_dir;
346 get_handle_data_subdir (handle, handle->name, &old_dir);
347
348 char *new_dir;
349 get_handle_data_subdir (handle, name, &new_dir);
350
351 int result = 0;
352
353 if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
354 {
355 GNUNET_DISK_directory_create_for_file (new_dir);
356
357 result = rename (old_dir, new_dir);
358 }
359 else if (GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO))
360 result = -1;
361
362 if (0 == result)
363 {
364 struct GNUNET_MESSENGER_MessageHandle msg_handle;
365
366 msg_handle.handle = handle;
367 msg_handle.message = create_message_name (name);
368
369 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
370
371 destroy_message (msg_handle.message);
372
373 change_handle_name (handle, name);
374 }
375 else
376 rename_ego_in_store = GNUNET_NO;
377
378 GNUNET_free(old_dir);
379 GNUNET_free(new_dir);
380
381 if (GNUNET_YES == rename_ego_in_store)
382 rename_store_ego(store, handle->name, name);
383}
384
385void
386set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name)
387{
388 GNUNET_assert(handle);
389
390 if (!name)
391 {
392 if (handle->ego)
393 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
394 else
395 change_handle_name (handle, name);
396
397 return;
398 }
399
400 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
401
402 lookup_store_ego (store, name, callback_set_handle_name, handle);
403}
404
405int
406open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
407{
408 GNUNET_assert((handle) && (key));
409
410 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
411 return GNUNET_NO;
412
413 return open_service_room (handle->service, handle, key);
414}
415
416int
417entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
418 const struct GNUNET_HashCode *key)
419{
420 GNUNET_assert((handle) && (door) && (key));
421
422 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
423 return GNUNET_NO;
424
425 return entry_service_room (handle->service, handle, door, key);
426}
427
428int
429close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
430{
431 GNUNET_assert((handle) && (key));
432
433 if (!get_handle_member_id (handle, key))
434 return GNUNET_NO;
435
436 return close_service_room (handle->service, handle, key);
437}
438
439int
440send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
441 const struct GNUNET_MESSENGER_Message *message)
442{
443 GNUNET_assert((handle) && (key) && (message));
444
445 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
446
447 if (!id)
448 {
449 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n");
450 return GNUNET_NO;
451 }
452
453 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key);
454
455 if (!room)
456 {
457 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key));
458 return GNUNET_NO;
459 }
460
461 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
462
463 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
464
465 return send_room_message (room, handle, msg);
466}
467
468static const struct GNUNET_HashCode*
469get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
470{
471 if (session->next)
472 return get_next_member_session_contect (session->next);
473 else
474 return get_member_session_context(session);
475}
476
477static const struct GNUNET_MESSENGER_MemberSession*
478get_handle_member_session (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
479{
480 GNUNET_assert((handle) && (key) && (handle->service));
481
482 const struct GNUNET_ShortHashCode *id = get_handle_member_id(handle, key);
483 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room(handle->service, key);
484
485 if ((!id) || (!room))
486 return NULL;
487
488 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
489 struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
490
491 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
492
493 if (!ego)
494 return NULL;
495
496 return get_member_session(member, &(ego->pub));
497}
498
499void
500notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
501 const struct GNUNET_MESSENGER_MemberSession *session,
502 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
503{
504 GNUNET_assert((handle) && (key) && (session) && (message) && (hash));
505
506 if ((!handle->mq) || (!get_handle_member_id (handle, key)))
507 {
508 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
509 return;
510 }
511
512 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
513
514 struct GNUNET_HashCode sender;
515 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
516
517 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
518
519 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
520
521 struct GNUNET_MESSENGER_Message *private_message = NULL;
522
523 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
524 {
525 private_message = copy_message(message);
526
527 if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
528 {
529 destroy_message(private_message);
530 private_message = NULL;
531 }
532 else
533 message = private_message;
534 }
535
536 struct GNUNET_MESSENGER_RecvMessage *msg;
537 struct GNUNET_MQ_Envelope *env;
538
539 uint16_t length = get_message_size (message, GNUNET_YES);
540
541 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
542
543 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
544 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
545 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
546 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
547
548 msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
549
550 if (get_handle_member_session(handle, key) == session)
551 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
552
553 if (private_message)
554 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
555
556 char *buffer = ((char*) msg) + sizeof(*msg);
557 encode_message (message, length, buffer, GNUNET_YES);
558
559 if (private_message)
560 destroy_message(private_message);
561
562 GNUNET_MQ_send (handle->mq, env);
563}
564
565static int
566callback_scan_for_rooms (void *cls, const char *filename)
567{
568 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
569
570 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
571
572 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
573 {
574 struct GNUNET_HashCode key;
575 struct GNUNET_ShortHashCode member_id;
576
577 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
578 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
579 change_handle_member_id (handle, &key, &member_id);
580 }
581
582 GNUNET_CONFIGURATION_destroy (cfg);
583 return GNUNET_OK;
584}
585
586void
587load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
588{
589 GNUNET_assert(handle);
590
591 char *id_dir;
592 get_handle_data_subdir (handle, handle->name, &id_dir);
593
594 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
595 {
596 char *scan_dir;
597 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
598
599 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
600 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
601
602 GNUNET_free(scan_dir);
603 }
604
605 GNUNET_free(id_dir);
606}
607
608static int
609iterate_save_rooms (void *cls, const struct GNUNET_HashCode *key, void *value)
610{
611 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
612 struct GNUNET_ShortHashCode *member_id = value;
613
614 char *id_dir;
615 get_handle_data_subdir (handle, handle->name, &id_dir);
616
617 char *filename;
618 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
619
620 GNUNET_free(id_dir);
621
622 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
623
624 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
625
626 if (key_data)
627 {
628 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
629
630 GNUNET_free(key_data);
631 }
632
633 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
634
635 if (member_id_data)
636 {
637 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
638
639 GNUNET_free(member_id_data);
640 }
641
642 GNUNET_CONFIGURATION_write (cfg, filename);
643 GNUNET_CONFIGURATION_destroy (cfg);
644
645 GNUNET_free(filename);
646
647 return GNUNET_YES;
648}
649
650void
651save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
652{
653 GNUNET_assert(handle);
654
655 char *id_dir;
656 get_handle_data_subdir (handle, handle->name, &id_dir);
657
658 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
659 == GNUNET_DISK_directory_create (id_dir)))
660 {
661 char *save_dir;
662 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
663
664 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
665 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
666 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
667
668 GNUNET_free(save_dir);
669 }
670
671 GNUNET_free(id_dir);
672}
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h
deleted file mode 100644
index d8ff3aaa8..000000000
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ /dev/null
@@ -1,238 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_handle.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_HANDLE_H
27#define GNUNET_SERVICE_MESSENGER_HANDLE_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_peer_lib.h"
35#include "gnunet_mq_lib.h"
36
37#include "gnunet-service-messenger_service.h"
38#include "gnunet-service-messenger_member_session.h"
39
40#include "messenger_api_ego.h"
41#include "messenger_api_message.h"
42
43struct GNUNET_MESSENGER_SrvHandle
44{
45 struct GNUNET_MESSENGER_Service *service;
46 struct GNUNET_MQ_Handle *mq;
47
48 char *name;
49
50 const struct GNUNET_MESSENGER_Ego *ego;
51
52 struct GNUNET_CONTAINER_MultiHashMap *member_ids;
53};
54
55/**
56 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue).
57 *
58 * @param[in/out] service MESSENGER Service
59 * @param[in/out] mq Message queue
60 * @return New handle
61 */
62struct GNUNET_MESSENGER_SrvHandle*
63create_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq);
64
65/**
66 * Destroys a handle and frees its memory fully.
67 *
68 * @param[in/out] handle Handle
69 */
70void
71destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
72
73/**
74 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter
75 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages.
76 *
77 * @param[in] handle Handle
78 * @param[in] name Potential name of the handle
79 * @param[out] dir Path to store data
80 */
81void
82get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle, const char *name, char **dir);
83
84/**
85 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>.
86 *
87 * If the handle is not a member of the specific <i>room</i>, NULL gets returned.
88 *
89 * @param[in] handle Handle
90 * @param[in] key Key of a room
91 * @return Member id or NULL
92 */
93const struct GNUNET_ShortHashCode*
94get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
95
96/**
97 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>
98 * and returns GNUNET_OK on success.
99 *
100 * The client connected to the <i>handle</i> will be informed afterwards automatically.
101 *
102 * @param[in/out] handle Handle
103 * @param[in] key Key of a room
104 * @param[in] unique_id Unique member id
105 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
106 */
107int
108change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
109 const struct GNUNET_ShortHashCode *unique_id);
110
111/**
112 * Sets the EGO used by a given <i>handle</i>.
113 *
114 * @param[in/out] handle Handle
115 * @param[in] ego EGO key pair
116 */
117void
118set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_MESSENGER_Ego *ego);
119
120/**
121 * Returns the EGO used by a given <i>handle</i>.
122 *
123 * @param[in] handle Handle
124 * @return EGO key pair
125 */
126const struct GNUNET_MESSENGER_Ego*
127get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
128
129/**
130 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>.
131 *
132 * @param[in/out] handle Handle
133 * @param[in] name Name (optionally: valid EGO name)
134 */
135void
136setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
137
138/**
139 * Tries to change the key pair of an EGO of a <i>handle</i> under the same name and informs all rooms
140 * about the change automatically.
141 *
142 * @param[in/out] handle Handle
143 */
144void
145update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
146
147/**
148 * Tries to rename the handle which implies renaming the EGO its using and moving all related data into
149 * the directory fitting to the changed <i>name</i>.
150 *
151 * The client connected to the <i>handle</i> will be informed afterwards automatically.
152 *
153 * @param[in/out] handle Handle
154 * @param[in] name New name
155 */
156void
157set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle, const char *name);
158
159/**
160 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the
161 * room from the handles service.
162 *
163 * @param[in/out] handle Handle
164 * @param[in] key Key of a room
165 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
166 */
167int
168open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
169
170/**
171 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room
172 * through a tunnel to a peer identified by a given <i>door</i> (peer identity).
173 *
174 * @param[in/out] handle Handle
175 * @param[in] door Peer identity
176 * @param[in] key Key of a room
177 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
178 */
179int
180entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_PeerIdentity *door,
181 const struct GNUNET_HashCode *key);
182
183/**
184 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle
185 * from this service is still a member of it.
186 *
187 * @param[in/out] handle Handle
188 * @param[in] key Key of a room
189 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
190 */
191int
192close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
193
194/**
195 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>.
196 *
197 * @param[in/out] handle Handle
198 * @param[in] key Key of a room
199 * @param[in] message Message
200 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
201 */
202int
203send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
204 const struct GNUNET_MESSENGER_Message *message);
205
206/**
207 * Notifies the handle that a new message was received or sent.
208 *
209 * @param[in/out] handle Handle
210 * @param[in] key Key of room
211 * @param[in] session Member session
212 * @param[in] message Message
213 * @param[in] hash Hash of message
214 */
215void
216notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key,
217 const struct GNUNET_MESSENGER_MemberSession *session,
218 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
219
220/**
221 * Loads member ids and other potential configuration from a given <i>handle</i> which
222 * depends on the given name the <i>handle</i> uses.
223 *
224 * @param[out] handle Handle
225 */
226void
227load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
228
229/**
230 * Saves member ids and other potential configuration from a given <i>handle</i> which
231 * depends on the given name the <i>handle</i> uses.
232 *
233 * @param[in] handle Handle
234 */
235void
236save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
237
238#endif //GNUNET_SERVICE_MESSENGER_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_list_handles.c b/src/messenger/gnunet-service-messenger_list_handles.c
deleted file mode 100644
index adcbf6a42..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.c
+++ /dev/null
@@ -1,101 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_list_handles.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_list_handles.h"
27
28#include "gnunet-service-messenger_handle.h"
29
30void
31init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
32{
33 GNUNET_assert(handles);
34
35 handles->head = NULL;
36 handles->tail = NULL;
37}
38
39void
40clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
41{
42 GNUNET_assert(handles);
43
44 while (handles->head)
45 {
46 struct GNUNET_MESSENGER_ListHandle *element = handles->head;
47
48 GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element);
49 destroy_handle (element->handle);
50 GNUNET_free(element);
51 }
52
53 handles->head = NULL;
54 handles->tail = NULL;
55}
56
57void
58add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
59{
60 GNUNET_assert((handles) && (handle));
61
62 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle);
63
64 element->handle = handle;
65
66 GNUNET_CONTAINER_DLL_insert_tail(handles->head, handles->tail, element);
67}
68
69int
70remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle)
71{
72 GNUNET_assert((handles) && (handle));
73
74 struct GNUNET_MESSENGER_ListHandle *element;
75
76 for (element = handles->head; element; element = element->next)
77 if (element->handle == handle)
78 break;
79
80 if (!element)
81 return GNUNET_NO;
82
83 GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element);
84 GNUNET_free(element);
85
86 return GNUNET_YES;
87}
88
89struct GNUNET_MESSENGER_SrvHandle*
90find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key)
91{
92 GNUNET_assert((handles) && (key));
93
94 struct GNUNET_MESSENGER_ListHandle *element;
95
96 for (element = handles->head; element; element = element->next)
97 if (get_handle_member_id ((struct GNUNET_MESSENGER_SrvHandle*) element->handle, key))
98 return element->handle;
99
100 return NULL;
101}
diff --git a/src/messenger/gnunet-service-messenger_list_handles.h b/src/messenger/gnunet-service-messenger_list_handles.h
deleted file mode 100644
index 9f7ca725f..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.h
+++ /dev/null
@@ -1,98 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_list_handles.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H
27#define GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32
33struct GNUNET_MESSENGER_SrvHandle;
34
35struct GNUNET_MESSENGER_ListHandle
36{
37 struct GNUNET_MESSENGER_ListHandle *prev;
38 struct GNUNET_MESSENGER_ListHandle *next;
39
40 struct GNUNET_MESSENGER_SrvHandle *handle;
41};
42
43struct GNUNET_MESSENGER_ListHandles
44{
45 struct GNUNET_MESSENGER_ListHandle *head;
46 struct GNUNET_MESSENGER_ListHandle *tail;
47};
48
49/**
50 * Initializes list of <i>handles</i> as empty list.
51 *
52 * @param[out] handles List of handles
53 */
54void
55init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
56
57/**
58 * Destroys remaining <i>handles</i> and clears the list.
59 *
60 * @param[in/out] handles List of handles
61 */
62void
63clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
64
65/**
66 * Adds a specific <i>handle</i> to the end of the list.
67 *
68 * @param[in/out] handles List of handles
69 * @param[in/out] handle Handle
70 */
71void
72add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
73
74/**
75 * Removes the first entry matching with a specific <i>handle</i> from the list of
76 * <i>handles</i> and returns #GNUNET_YES on success or #GNUNET_NO on failure.
77 *
78 * @param[in/out] handles List of handles
79 * @param[in/out] handle Handle
80 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
81 */
82int
83remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles, struct GNUNET_MESSENGER_SrvHandle *handle);
84
85/**
86 * Searches linearly through the list of <i>handles</i> for members of a specific room
87 * which is identified by a given <i>key</i>.
88 *
89 * If no handle is found which is a current member, NULL gets returned.
90 *
91 * @param[in] handles List of handles
92 * @param[in] key Common key of a room
93 * @return First handle which is a current member
94 */
95struct GNUNET_MESSENGER_SrvHandle*
96find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles, const struct GNUNET_HashCode *key);
97
98#endif //GNUNET_SERVICE_MESSENGER_LIST_HANDLES_H
diff --git a/src/messenger/gnunet-service-messenger_list_messages.c b/src/messenger/gnunet-service-messenger_list_messages.c
deleted file mode 100644
index 2666ccdab..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.c
+++ /dev/null
@@ -1,150 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_list_messages.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_list_messages.h"
27
28void
29init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
30{
31 GNUNET_assert(messages);
32
33 messages->head = NULL;
34 messages->tail = NULL;
35}
36
37void
38clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
39{
40 GNUNET_assert(messages);
41
42 while (messages->head)
43 {
44 struct GNUNET_MESSENGER_ListMessage *element = messages->head;
45
46 GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element);
47 GNUNET_free(element);
48 }
49
50 messages->head = NULL;
51 messages->tail = NULL;
52}
53
54void
55add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
56{
57 GNUNET_assert((messages) && (hash));
58
59 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage);
60
61 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
62
63 GNUNET_CONTAINER_DLL_insert_tail(messages->head, messages->tail, element);
64}
65
66void
67copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin)
68{
69 GNUNET_assert((messages) && (origin));
70
71 struct GNUNET_MESSENGER_ListMessage *element;
72
73 for (element = origin->head; element; element = element->next)
74 add_to_list_messages (messages, &(element->hash));
75}
76
77void
78remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
79{
80 GNUNET_assert((messages) && (hash));
81
82 struct GNUNET_MESSENGER_ListMessage *element;
83
84 for (element = messages->head; element; element = element->next)
85 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), hash))
86 {
87 GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element);
88 GNUNET_free(element);
89 break;
90 }
91}
92
93void
94load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
95{
96 GNUNET_assert((messages) && (path));
97
98 if (GNUNET_YES != GNUNET_DISK_file_test (path))
99 return;
100
101 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
102
103 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
104 path, GNUNET_DISK_OPEN_READ, permission
105 );
106
107 if (!handle)
108 return;
109
110 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
111
112 struct GNUNET_HashCode hash;
113 ssize_t len;
114
115 do {
116 len = GNUNET_DISK_file_read(handle, &hash, sizeof(hash));
117
118 if (len != sizeof(hash))
119 break;
120
121 add_to_list_messages(messages, &hash);
122 } while (len == sizeof(hash));
123
124 GNUNET_DISK_file_close(handle);
125}
126
127void
128save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages, const char *path)
129{
130 GNUNET_assert((messages) && (path));
131
132 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
133
134 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
135 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
136 );
137
138 if (!handle)
139 return;
140
141 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
142
143 struct GNUNET_MESSENGER_ListMessage *element;
144
145 for (element = messages->head; element; element = element->next)
146 GNUNET_DISK_file_write(handle, &(element->hash), sizeof(element->hash));
147
148 GNUNET_DISK_file_sync(handle);
149 GNUNET_DISK_file_close(handle);
150}
diff --git a/src/messenger/gnunet-service-messenger_list_messages.h b/src/messenger/gnunet-service-messenger_list_messages.h
deleted file mode 100644
index 93ec203ea..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.h
+++ /dev/null
@@ -1,109 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_list_messages.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H
27#define GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_disk_lib.h"
33
34struct GNUNET_MESSENGER_ListMessage
35{
36 struct GNUNET_MESSENGER_ListMessage *prev;
37 struct GNUNET_MESSENGER_ListMessage *next;
38
39 struct GNUNET_HashCode hash;
40};
41
42struct GNUNET_MESSENGER_ListMessages
43{
44 struct GNUNET_MESSENGER_ListMessage *head;
45 struct GNUNET_MESSENGER_ListMessage *tail;
46};
47
48/**
49 * Initializes list of message hashes as empty list.
50 *
51 * @param[out] messages List of hashes
52 */
53void
54init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
55
56/**
57 * Clears the list of message hashes.
58 *
59 * @param[in/out] messages List of hashes
60 */
61void
62clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
63
64/**
65 * Adds a specific <i>hash</i> from a message to the end of the list.
66 *
67 * @param[in/out] messages List of hashes
68 * @param[in] hash Hash of message
69 */
70void
71add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
72
73/**
74 * Copies all message hashes from an <i>origin</i> to another list.
75 *
76 * @param[in/out] messages Destination list of hashes
77 * @param[in] origin Source list of hashes
78 */
79void
80copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_MESSENGER_ListMessages *origin);
81
82/**
83 * Removes the first entry with a matching <i>hash</i> from the list.
84 *
85 * @param[in/out] messages List of hashes
86 * @param[in] hash Hash of message
87 */
88void
89remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash);
90
91/**
92 * Loads the list of message hashes from a file under a given <i>path</i>.
93 *
94 * @param[out] messages List of hashes
95 * @param[in] path Path of file
96 */
97void
98load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
99
100/**
101 * Saves the list of message hashes to a file under a given <i>path</i>.
102 *
103 * @param[in] messages List of hashes
104 * @param[in] path Path of file
105 */
106void
107save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages, const char *path);
108
109#endif //GNUNET_SERVICE_MESSENGER_LIST_MESSAGES_H
diff --git a/src/messenger/gnunet-service-messenger_member.c b/src/messenger/gnunet-service-messenger_member.c
deleted file mode 100644
index b0a735dbe..000000000
--- a/src/messenger/gnunet-service-messenger_member.c
+++ /dev/null
@@ -1,386 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_member.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member.h"
27
28#include "gnunet-service-messenger_member_session.h"
29
30struct GNUNET_MESSENGER_Member*
31create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
32{
33 GNUNET_assert (store);
34
35 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
36
37 member->store = store;
38
39 if (id)
40 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
41 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
42 {
43 GNUNET_free (member);
44 return NULL;
45 }
46
47 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
48
49 return member;
50}
51
52static int
53iterate_destroy_session (void *cls, const struct GNUNET_HashCode *key, void *value)
54{
55 struct GNUNET_MESSENGER_MemberSession *session = value;
56 destroy_member_session(session);
57 return GNUNET_YES;
58}
59
60void
61destroy_member (struct GNUNET_MESSENGER_Member *member)
62{
63 GNUNET_assert((member) && (member->sessions));
64
65 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
67
68 GNUNET_free (member);
69}
70
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member)
73{
74 GNUNET_assert (member);
75
76 return &(member->id);
77}
78
79static int
80callback_scan_for_sessions (void *cls, const char *filename)
81{
82 struct GNUNET_MESSENGER_Member *member = cls;
83
84 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
85 {
86 char *directory;
87
88 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
89
90 load_member_session(member, directory);
91 GNUNET_free (directory);
92 }
93
94 return GNUNET_OK;
95}
96
97void
98load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
99{
100 GNUNET_assert ((store) && (directory));
101
102 char *config_file;
103 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
104
105 struct GNUNET_MESSENGER_Member *member = NULL;
106
107 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
108 goto free_config;
109
110 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
111
112 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
113 {
114 struct GNUNET_ShortHashCode id;
115
116 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
117 goto destroy_config;
118
119 member = add_store_member(store, &id);
120 }
121
122destroy_config:
123
124 GNUNET_CONFIGURATION_destroy (cfg);
125
126free_config:
127 GNUNET_free(config_file);
128
129 if (!member)
130 return;
131
132 char *scan_dir;
133 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
134
135 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
136 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
137
138 GNUNET_free(scan_dir);
139}
140
141static int
142iterate_load_next_session (void *cls, const struct GNUNET_HashCode *key, void *value)
143{
144 const char* sessions_directory = cls;
145
146 char* load_dir;
147 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
148
149 struct GNUNET_MESSENGER_MemberSession *session = value;
150
151 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
152 load_member_session_next (session, load_dir);
153
154 GNUNET_free (load_dir);
155 return GNUNET_YES;
156}
157
158void
159load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory)
160{
161 GNUNET_assert ((member) && (directory));
162
163 char* load_dir;
164 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
165
166 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
167
168 GNUNET_free(load_dir);
169}
170
171static int
172iterate_save_session (void *cls, const struct GNUNET_HashCode *key, void *value)
173{
174 const char* sessions_directory = cls;
175
176 char* save_dir;
177 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
178
179 struct GNUNET_MESSENGER_MemberSession *session = value;
180
181 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
182 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
183 save_member_session (session, save_dir);
184
185 GNUNET_free (save_dir);
186 return GNUNET_YES;
187}
188
189void
190save_member (struct GNUNET_MESSENGER_Member *member, const char *directory)
191{
192 GNUNET_assert ((member) && (directory));
193
194 char *config_file;
195 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
196
197 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
198
199 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
200
201 if (id_data)
202 {
203 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
204
205 GNUNET_free(id_data);
206 }
207
208 GNUNET_CONFIGURATION_write (cfg, config_file);
209 GNUNET_CONFIGURATION_destroy (cfg);
210
211 GNUNET_free(config_file);
212
213 char* save_dir;
214 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
215
216 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
217 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
218 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
219
220 GNUNET_free(save_dir);
221}
222
223static void
224sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
225{
226 GNUNET_assert((session) && (next));
227
228 if (session == next)
229 return;
230
231 if (next->next)
232 sync_session_contact_from_next (session, next->next);
233 else
234 session->contact = next->contact;
235}
236
237static int
238iterate_sync_session_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
239{
240 struct GNUNET_MESSENGER_MemberSession *session = value;
241
242 if (session->next)
243 sync_session_contact_from_next (session, session->next);
244
245 return GNUNET_YES;
246}
247
248void
249sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
250{
251 GNUNET_assert ((member) && (member->sessions));
252
253 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
254}
255
256struct GNUNET_MESSENGER_MemberSession*
257get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
258{
259 GNUNET_assert ((member) && (public_key));
260
261 struct GNUNET_HashCode hash;
262 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
263
264 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
265}
266
267struct GNUNET_MESSENGER_ClosureSearchSession {
268 const struct GNUNET_MESSENGER_Message *message;
269 const struct GNUNET_HashCode *hash;
270
271 struct GNUNET_MESSENGER_MemberSession *match;
272};
273
274static int
275iterate_search_session (void *cls, const struct GNUNET_HashCode *key, void *value)
276{
277 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
278 struct GNUNET_MESSENGER_MemberSession *session = value;
279
280 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
281 return GNUNET_YES;
282
283 search->match = session;
284 return GNUNET_NO;
285}
286
287static struct GNUNET_MESSENGER_MemberSession*
288try_member_session (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
289{
290 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
291
292 if (session)
293 return session;
294
295 session = create_member_session(member, public_key);
296
297 if (session)
298 add_member_session(member, session);
299
300 return session;
301}
302
303struct GNUNET_MESSENGER_MemberSession*
304get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
305 const struct GNUNET_HashCode *hash)
306{
307 GNUNET_assert ((member) && (message) && (hash) &&
308 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
309
310 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
311 return try_member_session(member, &(message->body.info.host_key));
312 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
313 return try_member_session(member, &(message->body.join.key));
314
315 struct GNUNET_MESSENGER_ClosureSearchSession search;
316
317 search.message = message;
318 search.hash = hash;
319
320 search.match = NULL;
321 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
322
323 return search.match;
324}
325
326void
327add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
328{
329 if (!session)
330 return;
331
332 GNUNET_assert((member) && (session->member == member));
333
334 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
335
336 struct GNUNET_HashCode hash;
337 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
338
339 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
340 member->sessions, &hash, session,
341 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
342 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
343 GNUNET_h2s(&hash));
344}
345
346void
347remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
348{
349 GNUNET_assert ((member) && (session) && (session->member == member));
350
351 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
352
353 struct GNUNET_HashCode hash;
354 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
355
356 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
357 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
358 GNUNET_h2s(&hash));
359}
360
361struct GNUNET_MESSENGER_ClosureIterateSessions {
362 GNUNET_MESSENGER_MemberIteratorCallback it;
363 void *cls;
364};
365
366static int
367iterate_member_sessions_it (void *cls, const struct GNUNET_HashCode *key, void *value)
368{
369 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
370 struct GNUNET_MESSENGER_MemberSession *session = value;
371
372 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
373}
374
375int
376iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
377{
378 GNUNET_assert ((member) && (member->sessions) && (it));
379
380 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
381
382 iterate.it = it;
383 iterate.cls = cls;
384
385 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
386}
diff --git a/src/messenger/gnunet-service-messenger_member.h b/src/messenger/gnunet-service-messenger_member.h
deleted file mode 100644
index fb2e57cfb..000000000
--- a/src/messenger/gnunet-service-messenger_member.h
+++ /dev/null
@@ -1,170 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_member.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_H
28
29#include "messenger_api_contact.h"
30
31#include "gnunet-service-messenger_list_messages.h"
32#include "gnunet-service-messenger_member_store.h"
33#include "messenger_api_message.h"
34#include "messenger_api_util.h"
35
36struct GNUNET_MESSENGER_Member
37{
38 struct GNUNET_MESSENGER_MemberStore *store;
39 struct GNUNET_ShortHashCode id;
40
41 struct GNUNET_CONTAINER_MultiHashMap *sessions;
42};
43
44/**
45 * Creates and allocates a new member of a <i>room</i> with an optionally defined or
46 * random <i>id</i>.
47 *
48 * If the creation fails, NULL gets returned.
49 *
50 * @param[in/out] store Member store
51 * @param[in] id Member id or NULL
52 * @return New member or NULL
53 */
54struct GNUNET_MESSENGER_Member*
55create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
56
57/**
58 * Destroys a member and frees its memory fully.
59 *
60 * @param[in/out] member Member
61 */
62void
63destroy_member (struct GNUNET_MESSENGER_Member *member);
64
65/**
66 * Returns the current id of a given <i>member</i>.
67 *
68 * @param[in] member Member
69 * @return Member id
70 */
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member);
73
74/**
75 * Loads data from a <i>directory</i> into a new allocated and created member
76 * of a <i>store</i> if the required information can be read from the content
77 * of the given directory.
78 *
79 * @param[out] store Member store
80 * @param[in] directory Path to a directory
81 */
82void
83load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
84
85/**
86 * Loads data about next sessions from a <i>directory</i> into an empty loaded
87 * <i>member</i> which does not contain a fully built session graph yet.
88 *
89 * @param[in/out] member Member
90 * @param[in] directory Path to a directory
91 */
92void
93load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory);
94
95/**
96 * Saves data from a <i>member</i> into a directory which
97 * can be load to restore the member completely.
98 *
99 * @param[in] member Member
100 * @param[in] directory Path to a directory
101 */
102void
103save_member (struct GNUNET_MESSENGER_Member *member, const char *directory);
104
105/**
106 * Synchronizes contacts between all sessions from a given <i>member</i>
107 * and other sessions which are linked to them.
108 *
109 * @param[in/out] member Member
110 */
111void
112sync_member_contacts (struct GNUNET_MESSENGER_Member *member);
113
114/**
115 * Returns the member session of a <i>member</i> identified by a given public key.
116 * If the member does not provide a session with the given key, NULL gets returned.
117 *
118 * @param[in] member Member
119 * @param[in] public_key Public key of EGO
120 * @return Member session
121 */
122struct GNUNET_MESSENGER_MemberSession*
123get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key);
124
125/**
126 * Returns the member session of a <i>member</i> using a public key which can verify
127 * the signature of a given <i>message</i> and its <i>hash</i>. If the member does
128 * not provide a matching session, NULL gets returned.
129 *
130 * @param[in] member Member
131 * @param[in] message Message
132 * @param[in] hash Hash of message
133 * @return Member session
134 */
135struct GNUNET_MESSENGER_MemberSession*
136get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
137 const struct GNUNET_HashCode *hash);
138
139/**
140 * Adds a given member <i>session</i> to its <i>member</i>.
141 *
142 * @param[in/out] member Member
143 * @param[in/out] session Member session
144 */
145void
146add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
147
148/**
149 * Removes a given member <i>session</i> from its <i>member</i>.
150 *
151 * @param[in/out] member Member
152 * @param[in/out] session Member session
153 */
154void
155remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session);
156
157/**
158 * Iterate through all member sessions currently connected to a given <i>member</i>
159 * and call the provided iterator callback with a selected closure. The function
160 * will return the amount of member sessions it iterated through.
161 *
162 * @param[in/out] member Member
163 * @param[in] it Iterator callback
164 * @param[in/out] cls Closure
165 * @return Amount of sessions iterated through
166 */
167int
168iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void* cls);
169
170#endif //GNUNET_SERVICE_MESSENGER_MEMBER_H
diff --git a/src/messenger/gnunet-service-messenger_member_session.c b/src/messenger/gnunet-service-messenger_member_session.c
deleted file mode 100644
index 690c703b2..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ /dev/null
@@ -1,743 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_member_session.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_session.h"
27
28#include "gnunet-service-messenger_room.h"
29#include "gnunet-service-messenger_message_store.h"
30
31#include "messenger_api_contact_store.h"
32
33struct GNUNET_MESSENGER_MemberSession*
34create_member_session (struct GNUNET_MESSENGER_Member *member,
35 const struct GNUNET_IDENTITY_PublicKey *pubkey)
36{
37 if ((!member) || (!pubkey) || (!(member->store)))
38 return NULL;
39
40 struct GNUNET_MESSENGER_MemberSession *session = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
41 session->member = member;
42
43 GNUNET_memcpy(&(session->public_key), pubkey, sizeof(session->public_key));
44
45 get_context_from_member (
46 get_member_session_key (session),
47 get_member_session_id (session),
48 &(session->context)
49 );
50
51 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
52
53 session->contact = get_store_contact(
54 store,
55 get_member_session_context (session),
56 get_member_session_public_key (session)
57 );
58
59 if (!(session->contact))
60 {
61 GNUNET_free(session);
62 return NULL;
63 }
64
65 increase_contact_rc (session->contact);
66
67 session->history = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
68
69 init_list_messages(&(session->messages));
70
71 session->prev = NULL;
72 session->next = NULL;
73
74 session->start = GNUNET_TIME_absolute_get();
75
76 session->closed = GNUNET_NO;
77 session->completed = GNUNET_NO;
78
79 return session;
80}
81
82static void
83check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
84{
85 GNUNET_assert (session);
86
87 if (!session->messages.tail)
88 {
89 session->completed = GNUNET_YES;
90 goto completion;
91 }
92
93 const struct GNUNET_HashCode* start = &(session->messages.head->hash);
94 const struct GNUNET_HashCode* end = &(session->messages.tail->hash);
95
96 struct GNUNET_MESSENGER_ListMessages level;
97 init_list_messages(&level);
98
99 add_to_list_messages(&level, end);
100
101 struct GNUNET_MESSENGER_MessageStore *store = get_room_message_store(session->member->store->room);
102
103 struct GNUNET_MESSENGER_ListMessages list;
104 init_list_messages(&list);
105
106 while (level.head)
107 {
108 struct GNUNET_MESSENGER_ListMessage *element;
109
110 for (element = level.head; element; element = element->next)
111 {
112 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
113 store, &(element->hash), GNUNET_NO
114 );
115
116 if (!link)
117 continue;
118
119 add_to_list_messages(&list, &(link->first));
120
121 if (GNUNET_YES == link->multiple)
122 add_to_list_messages(&list, &(link->second));
123 }
124
125 clear_list_messages(&level);
126
127 for (element = list.head; element; element = element->next)
128 if (GNUNET_YES == check_member_session_history(session, &(element->hash), GNUNET_YES))
129 break;
130
131 if (element)
132 if (0 != GNUNET_CRYPTO_hash_cmp(&(element->hash), start))
133 add_to_list_messages(&level, &(element->hash));
134 else
135 session->completed = GNUNET_YES;
136 else
137 copy_list_messages(&level, &list);
138
139 clear_list_messages(&list);
140 }
141
142completion:
143 if (GNUNET_YES == is_member_session_completed(session))
144 {
145 GNUNET_CONTAINER_multihashmap_destroy (session->history);
146
147 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
148
149 if ((session->contact) && (GNUNET_YES == decrease_contact_rc (session->contact)))
150 remove_store_contact (
151 store,
152 session->contact,
153 get_member_session_context(session)
154 );
155
156 session->contact = NULL;
157 }
158}
159
160static int
161iterate_copy_history (void *cls, const struct GNUNET_HashCode *key, void *value)
162{
163 struct GNUNET_MESSENGER_MemberSession *next = cls;
164
165 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
166 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
167
168 return GNUNET_YES;
169}
170
171struct GNUNET_MESSENGER_MemberSession*
172switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
173 const struct GNUNET_MESSENGER_Message *message,
174 const struct GNUNET_HashCode *hash)
175{
176 if ((!session) || (!message) || (!hash))
177 return NULL;
178
179 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
180 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
181
182 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
183
184 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
185 next->member = add_store_member(session->member->store, &(message->body.id.id));
186 else
187 next->member = session->member;
188
189 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
190 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
191 else
192 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
193
194 get_context_from_member (
195 get_member_session_key (next),
196 get_member_session_id (next),
197 &(next->context)
198 );
199
200 update_store_contact(
201 get_member_contact_store(next->member->store),
202 get_member_session_contact(session),
203 get_member_session_context(session),
204 get_member_session_context(next),
205 get_member_session_public_key(next)
206 );
207
208 next->contact = get_member_session_contact(session);
209
210 if (!(next->contact))
211 {
212 GNUNET_free(next);
213 return NULL;
214 }
215
216 increase_contact_rc (next->contact);
217
218 next->history = GNUNET_CONTAINER_multihashmap_create(
219 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
220 );
221
222 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
223
224 init_list_messages(&(next->messages));
225 copy_list_messages(&(next->messages), &(session->messages));
226
227 session->next = next;
228 next->prev = session;
229 next->next = NULL;
230
231 next->start = GNUNET_TIME_absolute_get();
232
233 session->closed = GNUNET_YES;
234 next->closed = GNUNET_NO;
235 next->completed = GNUNET_NO;
236
237 check_member_session_completion (session);
238
239 return next;
240}
241
242void
243destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
244{
245 GNUNET_assert (session);
246
247 GNUNET_CONTAINER_multihashmap_destroy (session->history);
248
249 clear_list_messages (&(session->messages));
250
251 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
252
253 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
254 remove_store_contact (
255 get_member_contact_store(session->member->store),
256 contact,
257 get_member_session_context(session)
258 );
259
260 GNUNET_free(session);
261}
262
263int
264reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
265 const struct GNUNET_HashCode *hash)
266{
267 GNUNET_assert ((session) && (hash));
268
269 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
270 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
271 store,
272 get_member_session_context (session),
273 get_member_session_public_key (session)
274 );
275
276 if (!contact)
277 return GNUNET_SYSERR;
278
279 if (contact == session->contact)
280 goto clear_messages;
281
282 session->contact = contact;
283 increase_contact_rc (session->contact);
284
285clear_messages:
286 clear_list_messages(&(session->messages));
287 add_to_list_messages(&(session->messages), hash);
288
289 session->next = NULL;
290 session->closed = GNUNET_NO;
291 session->completed = GNUNET_NO;
292
293 return GNUNET_OK;
294}
295
296void
297close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
298{
299 GNUNET_assert (session);
300
301 session->closed = GNUNET_YES;
302 check_member_session_completion (session);
303}
304
305int
306is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
307{
308 GNUNET_assert(session);
309
310 return session->closed;
311}
312
313int
314is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
315{
316 GNUNET_assert(session);
317
318 return session->completed;
319}
320
321struct GNUNET_TIME_Absolute
322get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
323{
324 GNUNET_assert(session);
325
326 if (session->prev)
327 return get_member_session_start(session->prev);
328
329 return session->start;
330}
331
332const struct GNUNET_HashCode*
333get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
334{
335 GNUNET_assert((session) && (session->member));
336
337 return get_member_store_key(session->member->store);
338}
339
340const struct GNUNET_ShortHashCode*
341get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
342{
343 GNUNET_assert(session);
344
345 return get_member_id(session->member);
346}
347
348const struct GNUNET_IDENTITY_PublicKey*
349get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
350{
351 GNUNET_assert(session);
352
353 return &(session->public_key);
354}
355
356const struct GNUNET_HashCode*
357get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
358{
359 GNUNET_assert(session);
360
361 return &(session->context);
362}
363
364struct GNUNET_MESSENGER_Contact*
365get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
366{
367 GNUNET_assert (session);
368
369 return session->contact;
370}
371
372int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
373 const struct GNUNET_MESSENGER_Message *message,
374 const struct GNUNET_HashCode *hash)
375{
376 GNUNET_assert((session) && (message) && (hash));
377
378 if (GNUNET_YES == is_member_session_completed(session))
379 return GNUNET_SYSERR;
380
381 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
382 return GNUNET_SYSERR;
383
384 return verify_message(message, hash, get_member_session_public_key(session));
385}
386
387int
388check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
389 const struct GNUNET_HashCode *hash, int ownership)
390{
391 GNUNET_assert((session) && (hash));
392
393 if (GNUNET_YES == ownership)
394 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
395 else
396 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
397}
398
399static void
400update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
401 const struct GNUNET_HashCode *hash, int ownership)
402{
403 GNUNET_assert ((session) && (hash));
404
405 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
406 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
407 update_member_chain_history (session->next, hash, ownership);
408}
409
410void
411update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
412 const struct GNUNET_MESSENGER_Message *message,
413 const struct GNUNET_HashCode *hash)
414{
415 GNUNET_assert((session) && (message) && (hash));
416
417 if (GNUNET_YES == is_member_session_completed(session))
418 return;
419
420 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
421 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
422
423 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
424 {
425 if (GNUNET_YES == is_message_session_bound (message))
426 add_to_list_messages(&(session->messages), hash);
427
428 update_member_chain_history (session, hash, GNUNET_YES);
429 }
430 else
431 update_member_chain_history (session, hash, GNUNET_NO);
432
433 if (GNUNET_YES == session->closed)
434 check_member_session_completion(session);
435}
436
437static void
438clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
439 const struct GNUNET_HashCode *hash)
440{
441 GNUNET_assert ((session) && (hash));
442
443 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
444 clear_member_session_history(session->next, hash);
445}
446
447void
448clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
449 const struct GNUNET_HashCode *hash)
450{
451 GNUNET_assert((session) && (hash));
452
453 clear_member_chain_history (session, hash);
454}
455
456struct GNUNET_MESSENGER_MemberSessionHistoryEntry
457{
458 struct GNUNET_HashCode hash;
459 unsigned char ownership;
460};
461
462static void
463load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
464{
465 GNUNET_assert((session) && (path));
466
467 if (GNUNET_YES != GNUNET_DISK_file_test (path))
468 return;
469
470 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
471
472 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
473 path, GNUNET_DISK_OPEN_READ, permission
474 );
475
476 if (!handle)
477 return;
478
479 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
480
481 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
482 ssize_t len;
483
484 int status;
485
486 do {
487 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
488
489 if (len != sizeof(entry.hash))
490 break;
491
492 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
493
494 if (len != sizeof(entry.ownership))
495 break;
496
497 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
498 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
499 } while (status == GNUNET_OK);
500
501 GNUNET_DISK_file_close(handle);
502}
503
504void
505load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory)
506{
507 GNUNET_assert ((member) && (directory));
508
509 char *config_file;
510 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
511
512 struct GNUNET_MESSENGER_MemberSession *session = NULL;
513
514 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
515 goto free_config;
516
517 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
518
519 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
520 {
521 char *key_data;
522
523 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
524 goto destroy_config;
525
526 struct GNUNET_IDENTITY_PublicKey key;
527
528 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
529
530 GNUNET_free(key_data);
531
532 if (GNUNET_OK != key_return)
533 goto destroy_config;
534
535 session = create_member_session(member, &key);
536
537 unsigned long long numeric_value;
538
539 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
540 session->start.abs_value_us = numeric_value;
541
542 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
543 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
544
545 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "completed", &numeric_value))
546 session->completed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
547 }
548
549destroy_config:
550 GNUNET_CONFIGURATION_destroy (cfg);
551
552free_config:
553 GNUNET_free(config_file);
554
555 if (!session)
556 return;
557
558 char *history_file;
559 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
560
561 load_member_session_history (session, history_file);
562 GNUNET_free(history_file);
563
564 char *messages_file;
565 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
566
567 load_list_messages(&(session->messages), messages_file);
568 GNUNET_free(messages_file);
569
570 add_member_session(member, session);
571}
572
573static struct GNUNET_MESSENGER_MemberSession*
574get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
575{
576 if (!next)
577 return NULL;
578
579 struct GNUNET_MESSENGER_MemberSession *check = next;
580
581 do {
582 if (check == session)
583 return NULL;
584
585 check = check->next;
586 } while (check);
587
588 return next;
589}
590
591void
592load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
593{
594 GNUNET_assert ((session) && (directory));
595
596 char *config_file;
597 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
598
599 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
600 goto free_config;
601
602 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
603
604 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
605 {
606 char *key_data;
607
608 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
609 goto destroy_config;
610
611 struct GNUNET_IDENTITY_PublicKey next_key;
612
613 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
614
615 GNUNET_free(key_data);
616
617 if (GNUNET_OK != key_return)
618 goto destroy_config;
619
620 struct GNUNET_ShortHashCode next_id;
621
622 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
623 goto destroy_config;
624
625 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
626
627 session->next = get_cycle_safe_next_session(
628 session, member? get_member_session (member, &next_key) : NULL
629 );
630
631 if (session->next)
632 session->next->prev = session;
633 }
634
635destroy_config:
636 GNUNET_CONFIGURATION_destroy (cfg);
637
638free_config:
639 GNUNET_free(config_file);
640}
641
642static int
643iterate_save_member_session_history_hentries (void *cls, const struct GNUNET_HashCode *key, void *value)
644{
645 struct GNUNET_DISK_FileHandle *handle = cls;
646 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
647
648 GNUNET_DISK_file_write(handle, key, sizeof(*key));
649 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
650
651 return GNUNET_YES;
652}
653
654static void
655save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session, const char *path)
656{
657 GNUNET_assert((session) && (path));
658
659 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
660
661 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
662 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
663 );
664
665 if (!handle)
666 return;
667
668 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
669
670 GNUNET_CONTAINER_multihashmap_iterate(
671 session->history,
672 iterate_save_member_session_history_hentries,
673 handle
674 );
675
676 GNUNET_DISK_file_sync(handle);
677 GNUNET_DISK_file_close(handle);
678}
679
680void
681save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory)
682{
683 GNUNET_assert ((session) && (directory));
684
685 char *config_file;
686 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
687
688 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
689
690 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
691
692 if (key_data)
693 {
694 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
695
696 GNUNET_free(key_data);
697 }
698
699 if (session->next)
700 {
701 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
702
703 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
704
705 if (next_id_data)
706 {
707 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
708
709 GNUNET_free(next_id_data);
710 }
711
712 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
713
714 if (key_data)
715 {
716 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
717
718 GNUNET_free(key_data);
719 }
720 }
721
722 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
723
724 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
725 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
726
727 GNUNET_CONFIGURATION_write (cfg, config_file);
728 GNUNET_CONFIGURATION_destroy (cfg);
729
730 GNUNET_free(config_file);
731
732 char *history_file;
733 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
734
735 save_member_session_history (session, history_file);
736 GNUNET_free(history_file);
737
738 char *messages_file;
739 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
740
741 save_list_messages(&(session->messages), messages_file);
742 GNUNET_free(messages_file);
743}
diff --git a/src/messenger/gnunet-service-messenger_member_session.h b/src/messenger/gnunet-service-messenger_member_session.h
deleted file mode 100644
index bf4d10f67..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.h
+++ /dev/null
@@ -1,288 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_member_session.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
34
35#include "gnunet-service-messenger_member.h"
36
37#include "messenger_api_contact.h"
38
39struct GNUNET_MESSENGER_MemberSession {
40 struct GNUNET_MESSENGER_Member *member;
41
42 struct GNUNET_IDENTITY_PublicKey public_key;
43 struct GNUNET_HashCode context;
44
45 struct GNUNET_MESSENGER_Contact *contact;
46
47 struct GNUNET_CONTAINER_MultiHashMap *history;
48 struct GNUNET_MESSENGER_ListMessages messages;
49
50 struct GNUNET_MESSENGER_MemberSession* prev;
51 struct GNUNET_MESSENGER_MemberSession* next;
52
53 struct GNUNET_TIME_Absolute start;
54
55 int closed;
56 int completed;
57};
58
59/**
60 * Creates and allocates a new member session of a <i>member</i> with a given
61 * public key.
62 *
63 * If the creation fails, NULL gets returned.
64 *
65 * @param[in/out] member Member
66 * @param[in] pubkey Public key of EGO
67 * @return New member session
68 */
69struct GNUNET_MESSENGER_MemberSession*
70create_member_session (struct GNUNET_MESSENGER_Member *member,
71 const struct GNUNET_IDENTITY_PublicKey *pubkey);
72
73/**
74 * Creates and allocates a new member session closing and replacing a given
75 * other <i>session</i> of the same member. The new session could have significant
76 * changes to the members public key or its member id depending on the used
77 * <i>message</i> to switch session. The new session will be linked to the old
78 * one.
79 *
80 * @param[in/out] session Old member session
81 * @param[in] message Message
82 * @param[in] hash Hash of message
83 * @return New member session
84 */
85struct GNUNET_MESSENGER_MemberSession*
86switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
87 const struct GNUNET_MESSENGER_Message *message,
88 const struct GNUNET_HashCode *hash);
89
90/**
91 * Destroys a member session and frees its memory fully.
92 *
93 * @param[in/out] session Member session
94 */
95void
96destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session);
97
98/**
99 * Resets a given member <i>session</i> which re-opens a member
100 * session for new usage. Every connection to other sessions will be
101 * be dropped. The member sessions messages will be cleared but old
102 * history from uncompleted sessions however can be reused!
103 *
104 * @param[in/out] session Member session
105 * @param[in] hash Hash of initial message (JOIN message!)
106 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
107 */
108int
109reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
110 const struct GNUNET_HashCode *hash);
111
112/**
113 * Closes a given member <i>session</i> which opens the request
114 * for completion of the given member session.
115 *
116 * Closing a session may complete a session and can't be used without
117 * a reset! ( @see #reset_member_session() )
118 *
119 * @param[in/out] session Member session
120 */
121void
122close_member_session (struct GNUNET_MESSENGER_MemberSession* session);
123
124/**
125 * Returns if the given member <i>session</i> has been closed.
126 *
127 * @param[in] session Member session
128 * @return #GNUNET_YES or #GNUNET_NO
129 */
130int
131is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session);
132
133/**
134 * Returns if the given member <i>session</i> has been completed.
135 *
136 * A completed member session can't verify any message as its own and
137 * it won't add any message to its history.
138 *
139 * @param[in] session Member session
140 * @return #GNUNET_YES or #GNUNET_NO
141 */
142int
143is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session);
144
145/**
146 * Returns the timestamp of the member <i>session</i>'s start.
147 *
148 * @param[in] session Member session
149 * @return Absolute timestamp
150 */
151struct GNUNET_TIME_Absolute
152get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session);
153
154/**
155 * Returns the key of the room a given member <i>session</i> belongs to.
156 *
157 * @param[in] session Member session
158 * @return Key of room
159 */
160const struct GNUNET_HashCode*
161get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session);
162
163/**
164 * Returns the member id of a given member <i>session</i>.
165 *
166 * @param[in] session Member session
167 * @return Member id
168 */
169const struct GNUNET_ShortHashCode*
170get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session);
171
172/**
173 * Returns the public key from an EGO of a given member <i>session</i>.
174 *
175 * @param[in] session Member session
176 * @return Public key of EGO
177 */
178const struct GNUNET_IDENTITY_PublicKey*
179get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session);
180
181/**
182 * Returns the member context of a given member <i>session</i>.
183 *
184 * @param[in] session Member session
185 * @return Member context as hash
186 */
187const struct GNUNET_HashCode*
188get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session);
189
190/**
191 * Returns the contact which is connected to a given member <i>session</i>.
192 *
193 * @param[in] session Member session
194 * @return Contact
195 */
196struct GNUNET_MESSENGER_Contact*
197get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session);
198
199/**
200 * Verifies a given member <i>session</i> as sender of a selected <i>message</i> and
201 * its <i>hash</i>. The function returns #GNUNET_OK if the message session is verified
202 * as sender, otherwise #GNUNET_SYSERR.
203 *
204 * @see #is_member_session_completed() for verification.
205 *
206 * @param[in] session Member session
207 * @param[in] message Message
208 * @param[in] hash Hash of message
209 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
210 */
211int
212verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
213 const struct GNUNET_MESSENGER_Message *message,
214 const struct GNUNET_HashCode *hash);
215
216/**
217 * Checks the history of a <i>session</i> for a specific message which is identified
218 * by its <i>hash</i> and if the <i>ownership</i> flag is set, if the message is
219 * owned by the sessions contact.
220 *
221 * @param[in] session Member session
222 * @param[in] hash Hash of message
223 * @param[in] ownership Ownership flag
224 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
225 */
226int
227check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
228 const struct GNUNET_HashCode *hash, int ownership);
229
230/**
231 * Adds a given <i>message</i> to the history of a <i>session</i> using the messages
232 * <i>hash</i>. The ownership will be set automatically.
233 *
234 * @see #is_member_session_completed() for updating a history.
235 *
236 * @param[in/out] session Member session
237 * @param[in] message Message
238 * @param[in] hash Hash of message
239 */
240void
241update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
242 const struct GNUNET_MESSENGER_Message *message,
243 const struct GNUNET_HashCode *hash);
244
245/**
246 * Removes a message from the history of a <i>session</i> using the messages
247 * <i>hash</i>.
248 *
249 * @param[in/out] session Member session
250 * @param[in] hash Hash of message
251 */
252void
253clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
254 const struct GNUNET_HashCode *hash);
255
256/**
257 * Loads data from a <i>directory</i> into a new allocated and created member
258 * session of a <i>member</i> if the required information can be read from the
259 * content of the given directory.
260 *
261 * @param[out] member Member
262 * @param[in] directory Path to a directory
263 */
264void
265load_member_session (struct GNUNET_MESSENGER_Member *member, const char *directory);
266
267/**
268 * Loads the connection from one <i>session</i> to another through the
269 * next attribute. Necessary information will be loaded from a configuration
270 * file inside of a given <i>directory</i>.
271 *
272 * @param[in/out] session Member session
273 * @param[in] directory Path to a directory
274 */
275void
276load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
277
278/**
279 * Saves data from a member <i>session</i> into a <i>directory</i> which can be
280 * load to restore the member session completely.
281 *
282 * @param[in] session Member session
283 * @param[in] directory Path to a directory
284 */
285void
286save_member_session (struct GNUNET_MESSENGER_MemberSession *session, const char *directory);
287
288#endif //GNUNET_SERVICE_MESSENGER_MEMBER_SESSION_H
diff --git a/src/messenger/gnunet-service-messenger_member_store.c b/src/messenger/gnunet-service-messenger_member_store.c
deleted file mode 100644
index 2925965d4..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.c
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_member_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_store.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_service.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
34{
35 GNUNET_assert ((store) && (room));
36
37 store->room = room;
38 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
43{
44 struct GNUNET_MESSENGER_Member *member = value;
45 destroy_member(member);
46 return GNUNET_YES;
47}
48
49void
50clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
51{
52 GNUNET_assert ((store) && (store->members));
53
54 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
55 GNUNET_CONTAINER_multishortmap_destroy (store->members);
56}
57
58
59struct GNUNET_MESSENGER_ContactStore*
60get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
61{
62 GNUNET_assert ((store) && (store->room));
63
64 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
65
66 return get_service_contact_store(room->service);
67}
68
69const struct GNUNET_HashCode*
70get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
71{
72 GNUNET_assert (store);
73
74 return get_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
75}
76
77static int
78callback_scan_for_members (void *cls, const char *filename)
79{
80 struct GNUNET_MESSENGER_MemberStore *store = cls;
81
82 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
83 {
84 char *directory;
85
86 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
87
88 load_member(store, directory);
89
90 GNUNET_free(directory);
91 }
92
93 return GNUNET_OK;
94}
95
96static int
97iterate_load_next_member_sessions (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
98{
99 const char *sync_dir = cls;
100
101 struct GNUNET_MESSENGER_Member *member = value;
102
103 if (!member)
104 return GNUNET_YES;
105
106 char *member_dir;
107 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
108
109 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
110 load_member_next_sessions (member, member_dir);
111
112 GNUNET_free(member_dir);
113 return GNUNET_YES;
114}
115
116static int
117iterate_sync_member_contacts (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
118{
119 struct GNUNET_MESSENGER_Member *member = value;
120
121 if (!member)
122 return GNUNET_YES;
123
124 sync_member_contacts (member);
125 return GNUNET_YES;
126}
127
128void
129load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
130{
131 GNUNET_assert ((store) && (directory));
132
133 char *scan_dir;
134 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
135
136 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
137 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
138
139 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
140 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
141
142 GNUNET_free(scan_dir);
143}
144
145static int
146iterate_save_members (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
147{
148 const char *save_dir = cls;
149
150 struct GNUNET_MESSENGER_Member *member = value;
151
152 if (!member)
153 return GNUNET_YES;
154
155 char *member_dir;
156 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
157
158 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
159 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
160 save_member(member, member_dir);
161
162 GNUNET_free(member_dir);
163 return GNUNET_YES;
164}
165
166void
167save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
168{
169 GNUNET_assert ((store) && (directory));
170
171 char* save_dir;
172 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
173
174 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
175 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
176 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
177
178 GNUNET_free(save_dir);
179}
180
181struct GNUNET_MESSENGER_Member*
182get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
183{
184 GNUNET_assert ((store) && (store->members) && (id));
185
186 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
187}
188
189struct GNUNET_MESSENGER_Member*
190get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message)
191{
192 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
193 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
194 return add_store_member(store, &(message->header.sender_id));
195 else
196 return get_store_member(store, &(message->header.sender_id));
197}
198
199struct GNUNET_MESSENGER_Member*
200add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
201{
202 GNUNET_assert ((store) && (store->members));
203
204 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
205
206 if (member)
207 return member;
208
209 member = create_member(store, id);
210
211 if (!member)
212 return NULL;
213
214 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
215 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
216 {
217 destroy_member(member);
218 return NULL;
219 }
220
221 return member;
222}
223
224struct GNUNET_MESSENGER_ClosureIterateMembers {
225 GNUNET_MESSENGER_MemberIteratorCallback it;
226 void *cls;
227};
228
229static int
230iterate_store_members_it (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
231{
232 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
233 struct GNUNET_MESSENGER_Member *member = value;
234
235 return iterate_member_sessions(member, iterate->it, iterate->cls);
236}
237
238int
239iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
240 void* cls)
241{
242 GNUNET_assert ((store) && (store->members) && (it));
243
244 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
245
246 iterate.it = it;
247 iterate.cls = cls;
248
249 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
250}
diff --git a/src/messenger/gnunet-service-messenger_member_store.h b/src/messenger/gnunet-service-messenger_member_store.h
deleted file mode 100644
index 859e4683d..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.h
+++ /dev/null
@@ -1,151 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_member_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
27#define GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_identity_service.h"
33#include "messenger_api_message.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_Member;
38struct GNUNET_MESSENGER_MemberSession;
39
40struct GNUNET_MESSENGER_MemberStore
41{
42 struct GNUNET_MESSENGER_SrvRoom *room;
43
44 struct GNUNET_CONTAINER_MultiShortmap *members;
45};
46
47typedef int (*GNUNET_MESSENGER_MemberIteratorCallback) (
48 void *cls,
49 const struct GNUNET_IDENTITY_PublicKey *public_key,
50 struct GNUNET_MESSENGER_MemberSession *session);
51
52/**
53 * Initializes a member <i>store</i> as fully empty connected to a <i>room</i>.
54 *
55 * @param[out] store Member store
56 * @param room Room
57 */
58void
59init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
60
61/**
62 * Clears a member <i>store</i>, wipes its content and deallocates its memory.
63 *
64 * @param[in/out] store Member store
65 */
66void
67clear_member_store (struct GNUNET_MESSENGER_MemberStore *store);
68
69/**
70 * Returns the used contact store of a given member <i>store</i>.
71 *
72 * @param[in/out] store Member store
73 * @return Contact store
74 */
75struct GNUNET_MESSENGER_ContactStore*
76get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store);
77
78/**
79 * Returns the shared secret you need to access a room of the <i>store</i>.
80 *
81 * @param[in] store Member store
82 * @return Shared secret
83 */
84const struct GNUNET_HashCode*
85get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store);
86
87/**
88 * Loads members from a directory into a member <i>store</i>.
89 *
90 * @param[out] store Member store
91 * @param[in] directory Path to a directory
92 */
93void
94load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
95
96/**
97 * Saves members from a member <i>store</i> into a directory.
98 *
99 * @param[in] store Member store
100 * @param[in] directory Path to a directory
101 */
102void
103save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory);
104
105/**
106 * Returns the member in a <i>store</i> identified by a given <i>id</i>. If the <i>store</i>
107 * does not contain a member with the given <i>id</i>, NULL gets returned.
108 *
109 * @param[in] store Member store
110 * @param[in] id Member id
111 * @return Member or NULL
112 */
113struct GNUNET_MESSENGER_Member*
114get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
115
116/**
117 * Returns the member of a <i>store</i> using a sender id of a given <i>message</i>.
118 * If the member does not provide a matching session, NULL gets returned.
119 *
120 * @param[in/out] store Member store
121 * @param[in] message Message
122 * @return Member or NULL
123 */
124struct GNUNET_MESSENGER_Member*
125get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message);
126
127/**
128 * Adds a member to a <i>store</i> under a specific <i>id</i> and returns it on success.
129 *
130 * @param[in/out] store Member store
131 * @param[in] id Member id
132 * @return Member or NULL
133 */
134struct GNUNET_MESSENGER_Member*
135add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id);
136
137/**
138 * Iterate through all member sessions currently connected to the members of the given
139 * member <i>store</i> and call the provided iterator callback with a selected closure.
140 * The function will return the amount of members it iterated through.
141 *
142 * @param[in/out] store Member store
143 * @param[in] it Iterator callback
144 * @param[in/out] cls Closure
145 * @return Amount of members iterated through
146 */
147int
148iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
149 void* cls);
150
151#endif //GNUNET_SERVICE_MESSENGER_MEMBER_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c b/src/messenger/gnunet-service-messenger_message_handle.c
deleted file mode 100644
index 86f2b901a..000000000
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_handle.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_handle.h"
27
28static void
29handle_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
30 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
31{
32 struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, message, hash);
33
34 if (next != session)
35 add_member_session(next->member, next);
36}
37
38void
39handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
40 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
41{
42 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
43 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
44
45 if (GNUNET_OK != reset_member_session(session, hash))
46 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
47
48 solve_room_member_collisions (
49 room,
50 &(message->body.join.key),
51 &(message->header.sender_id),
52 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
53 );
54}
55
56void
57handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
58 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
59{
60 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
61 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
62
63 close_member_session(session);
64}
65
66void
67handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
68 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
69{
70 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact(session);
71
72 if (!contact)
73 return;
74
75 set_contact_name (contact, message->body.name.name);
76}
77
78void
79handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
80 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
81{
82 handle_session_switch (session, message, hash);
83}
84
85void
86handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
87 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
88{
89 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer)))
90 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
91
92 if (room->peer_message)
93 rebuild_room_basement_structure (room);
94}
95
96void
97handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
98 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
99{
100 handle_session_switch (session, message, hash);
101
102 solve_room_member_collisions (
103 room,
104 get_member_session_public_key(session),
105 &(message->body.id.id),
106 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
107 );
108}
109
110void
111handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
112 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
113{
114 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL);
115
116 if (!element)
117 return;
118
119 remove_from_list_tunnels (&(room->basement), element);
120
121 if (room->peer_message)
122 rebuild_room_basement_structure (room);
123}
124
125void
126handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
127 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
128{
129 struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_ntoh (message->body.deletion.delay);
130 struct GNUNET_TIME_Absolute action = GNUNET_TIME_absolute_ntoh (message->header.timestamp);
131
132 action = GNUNET_TIME_absolute_add (action, delay);
133 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
134
135 delete_room_message (room, session, &(message->body.deletion.hash), delay);
136}
diff --git a/src/messenger/gnunet-service-messenger_message_handle.h b/src/messenger/gnunet-service-messenger_message_handle.h
deleted file mode 100644
index 844142b77..000000000
--- a/src/messenger/gnunet-service-messenger_message_handle.h
+++ /dev/null
@@ -1,142 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_handle.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "gnunet-service-messenger_message_kind.h"
33
34#include "gnunet-service-messenger_member_session.h"
35#include "gnunet-service-messenger_tunnel.h"
36#include "messenger_api_message.h"
37
38/**
39 * Handles a received or sent join message to make changes of current member information.
40 * (add matching member and clear member info)
41 *
42 * @param[in/out] room Room of the message
43 * @param[in/out] session Member session
44 * @param[in] message JOIN-Message
45 * @param[in] hash Hash of the message
46 */
47void
48handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
49 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
50
51/**
52 * Handles a received or sent leave message to make changes of current member information.
53 * (remove matching member and clear member info)
54 *
55 * @param[in/out] room Room of the message
56 * @param[in/out] session Member session
57 * @param[in] message LEAVE-Message
58 * @param[in] hash Hash of the message
59 */
60void
61handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
62 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
63
64/**
65 * Handles a received or sent name message to rename a current member.
66 * (change name of matching member)
67 *
68 * @param[in/out] room Room of the message
69 * @param[in/out] session Member session
70 * @param[in] message NAME-Message
71 * @param[in] hash Hash of the message
72 */
73void
74handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
75 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
76
77/**
78 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly.
79 * (move the member in the contacts and change its key)
80 *
81 * @param[in/out] room Room of the message
82 * @param[in/out] session Member session
83 * @param[in] message KEY-Message
84 * @param[in] hash Hash of the message
85 */
86void
87handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
88 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
89
90/**
91 * Handles a received or sent peer message to make changes of the basement in the room.
92 * (add a new peer to the basement and restructure connections based on updated list of peers)
93 *
94 * @param[in/out] room Room of the message
95 * @param[in/out] session Member session
96 * @param[in] message PEER-Message
97 * @param[in] hash Hash of the message
98 */
99void
100handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
101 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
102
103/**
104 * Handles a received or sent id message to change a members id.
105 * (change id of matching member)
106 *
107 * @param[in/out] room Room of the message
108 * @param[in/out] session Member session
109 * @param[in] message ID-Message
110 * @param[in] hash Hash of the message
111 */
112void
113handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
114 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
115
116/**
117 * Handles a received or sent miss message to drop a peer from the basement in the room.
118 * (remove a peer from the basement and restructure connections based on updated list of peers)
119 *
120 * @param[in/out] room Room of the message
121 * @param[in/out] session Member session
122 * @param[in] message MISS-Message
123 * @param[in] hash Hash of the message
124 */
125void
126handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
127 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
128
129/**
130 * Handles a received or sent delete message to delete a specific message from the store.
131 * (remove a message from the store of a room under a given delay)
132 *
133 * @param[in/out] room Room of the message
134 * @param[in/out] session Member session
135 * @param[in] message DELETE-Message
136 * @param[in] hash Hash of the message
137 */
138void
139handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
140 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
141
142#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c b/src/messenger/gnunet-service-messenger_message_kind.c
deleted file mode 100644
index 3edcade91..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ /dev/null
@@ -1,239 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_kind.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_kind.h"
27
28#include "messenger_api_util.h"
29
30struct GNUNET_MESSENGER_Message*
31create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
32{
33 if (!ego)
34 return NULL;
35
36 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO);
37
38 if (!message)
39 return NULL;
40
41 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
42
43 message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
44
45 return message;
46}
47
48struct GNUNET_MESSENGER_Message*
49create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
50{
51 if (!ego)
52 return NULL;
53
54 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN);
55
56 if (!message)
57 return NULL;
58
59 GNUNET_memcpy(&(message->body.join.key), &(ego->pub), sizeof(ego->pub));
60
61 return message;
62}
63
64struct GNUNET_MESSENGER_Message*
65create_message_leave ()
66{
67 return create_message (GNUNET_MESSENGER_KIND_LEAVE);
68}
69
70struct GNUNET_MESSENGER_Message*
71create_message_name (const char *name)
72{
73 if (!name)
74 return NULL;
75
76 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME);
77
78 if (!message)
79 return NULL;
80
81 message->body.name.name = GNUNET_strdup(name);
82 return message;
83}
84
85struct GNUNET_MESSENGER_Message*
86create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
87{
88 if (!key)
89 return NULL;
90
91 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY);
92
93 if (!message)
94 return NULL;
95
96 GNUNET_IDENTITY_key_get_public (key, &(message->body.key.key));
97 return message;
98}
99
100struct GNUNET_MESSENGER_Message*
101create_message_peer (const struct GNUNET_MESSENGER_Service *service)
102{
103 if (!service)
104 return NULL;
105
106 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER);
107
108 if (!message)
109 return NULL;
110
111 if (GNUNET_OK == get_service_peer_identity (service, &(message->body.peer.peer)))
112 return message;
113 else
114 {
115 destroy_message (message);
116 return NULL;
117 }
118}
119
120struct GNUNET_MESSENGER_Message*
121create_message_id (const struct GNUNET_ShortHashCode *unique_id)
122{
123 if (!unique_id)
124 return NULL;
125
126 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID);
127
128 if (!message)
129 return NULL;
130
131 GNUNET_memcpy(&(message->body.id.id), unique_id, sizeof(struct GNUNET_ShortHashCode));
132
133 return message;
134}
135
136struct GNUNET_MESSENGER_Message*
137create_message_miss (const struct GNUNET_PeerIdentity *peer)
138{
139 if (!peer)
140 return NULL;
141
142 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS);
143
144 if (!message)
145 {
146 return NULL;
147 }
148
149 GNUNET_memcpy(&(message->body.miss.peer), peer, sizeof(struct GNUNET_PeerIdentity));
150
151 return message;
152}
153
154struct GNUNET_MESSENGER_Message*
155create_message_merge (const struct GNUNET_HashCode *previous)
156{
157 if (!previous)
158 return NULL;
159
160 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE);
161
162 if (!message)
163 return NULL;
164
165 GNUNET_memcpy(&(message->body.merge.previous), previous, sizeof(struct GNUNET_HashCode));
166
167 return message;
168}
169
170struct GNUNET_MESSENGER_Message*
171create_message_request (const struct GNUNET_HashCode *hash)
172{
173 if (!hash)
174 return NULL;
175
176 struct GNUNET_HashCode zero;
177 memset (&zero, 0, sizeof(zero));
178
179 if (0 == GNUNET_CRYPTO_hash_cmp (hash, &zero))
180 return NULL;
181
182 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_REQUEST);
183
184 if (!message)
185 return NULL;
186
187 GNUNET_memcpy(&(message->body.request.hash), hash, sizeof(struct GNUNET_HashCode));
188
189 return message;
190}
191
192struct GNUNET_MESSENGER_Message*
193create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
194{
195 if ((!door) || (!key))
196 return NULL;
197
198 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE);
199
200 if (!message)
201 return NULL;
202
203 GNUNET_memcpy(&(message->body.invite.door), door, sizeof(struct GNUNET_PeerIdentity));
204 GNUNET_memcpy(&(message->body.invite.key), key, sizeof(struct GNUNET_HashCode));
205
206 return message;
207}
208
209struct GNUNET_MESSENGER_Message*
210create_message_text (const char *text)
211{
212 if (!text)
213 return NULL;
214
215 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT);
216
217 if (!message)
218 return NULL;
219
220 message->body.text.text = GNUNET_strdup(text);
221 return message;
222}
223
224struct GNUNET_MESSENGER_Message*
225create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
226{
227 if (!hash)
228 return NULL;
229
230 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_DELETE);
231
232 if (!message)
233 return NULL;
234
235 GNUNET_memcpy(&(message->body.deletion.hash), hash, sizeof(struct GNUNET_HashCode));
236 message->body.deletion.delay = GNUNET_TIME_relative_hton (delay);
237
238 return message;
239}
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h b/src/messenger/gnunet-service-messenger_message_kind.h
deleted file mode 100644
index c098868c0..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ /dev/null
@@ -1,172 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_kind.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h"
33#include "gnunet_time_lib.h"
34
35#include "messenger_api_message.h"
36#include "gnunet-service-messenger_service.h"
37#include "messenger_api_ego.h"
38
39/**
40 * Creates and allocates a new info message containing the hosts EGO public key and a newly generated unique member id.
41 * (all values are stored as copy)
42 *
43 * @param[in] ego EGO of the host
44 * @param[in] members Map of all assigned member ids
45 * @return New message
46 */
47struct GNUNET_MESSENGER_Message*
48create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
49
50/**
51 * Creates and allocates a new join message containing the clients EGO public key.
52 * (all values are stored as copy)
53 *
54 * @param[in] ego EGO of the client
55 * @return New message
56 */
57struct GNUNET_MESSENGER_Message*
58create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
59
60/**
61 * Creates and allocates a new leave message.
62 *
63 * @return New message
64 */
65struct GNUNET_MESSENGER_Message*
66create_message_leave ();
67
68/**
69 * Creates and allocates a new name message containing the <i>name</i> to change to.
70 * (all values are stored as copy)
71 *
72 * @param[in] name New name
73 * @return New message
74 */
75struct GNUNET_MESSENGER_Message*
76create_message_name (const char *name);
77
78/**
79 * Creates and allocates a new key message containing the public <i>key</i> to change to derived
80 * from its private counterpart. (all values are stored as copy)
81 *
82 * @param[in] key Private key of EGO
83 * @return New message
84 */
85struct GNUNET_MESSENGER_Message*
86create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
87
88/**
89 * Creates and allocates a new peer message containing a services peer identity.
90 * (all values are stored as copy)
91 *
92 * @param[in] service Service
93 * @return New message
94 */
95struct GNUNET_MESSENGER_Message*
96create_message_peer (const struct GNUNET_MESSENGER_Service *service);
97
98/**
99 * Creates and allocates a new id message containing the unique member id to change to.
100 * (all values are stored as copy)
101 *
102 * @param[in] unique_id Unique member id
103 * @return New message
104 */
105struct GNUNET_MESSENGER_Message*
106create_message_id (const struct GNUNET_ShortHashCode *unique_id);
107
108/**
109 * Creates and allocates a new miss message containing the missing <i>peer</i> identity.
110 * (all values are stored as copy)
111 *
112 * @param[in] peer Missing peer identity
113 * @return New message
114 */
115struct GNUNET_MESSENGER_Message*
116create_message_miss (const struct GNUNET_PeerIdentity *peer);
117
118/**
119 * Creates and allocates a new merge message containing the hash of a second <i>previous</i> message
120 * besides the regular previous message mentioned in a messages header.
121 * (all values are stored as copy)
122 *
123 * @param[in] previous Hash of message
124 * @return New message
125 */
126struct GNUNET_MESSENGER_Message*
127create_message_merge (const struct GNUNET_HashCode *previous);
128
129/**
130 * Creates and allocates a new request message containing the <i>hash</i> of a missing message.
131 * (all values are stored as copy)
132 *
133 * @param[in] hash Hash of message
134 * @return New message
135 */
136struct GNUNET_MESSENGER_Message*
137create_message_request (const struct GNUNET_HashCode *hash);
138
139/**
140 * Creates and allocates a new invite message containing the peer identity of an entrance peer
141 * to a room using a given <i>key</i> as shared secret for communication.
142 * (all values are stored as copy)
143 *
144 * @param[in] door Peer identity
145 * @param[in] key Shared secret of a room
146 * @return New message
147 */
148struct GNUNET_MESSENGER_Message*
149create_message_invite (const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key);
150
151/**
152 * Creates and allocates a new <i>text message containing a string representing text.
153 * (all values are stored as copy)
154 *
155 * @param[in] text Text
156 * @return New message
157 */
158struct GNUNET_MESSENGER_Message*
159create_message_text (const char *text);
160
161/**
162 * Creates and allocates a new delete message containing the <i>hash</i> of a message to delete after a specific <i>delay</i>.
163 * (all values are stored as copy)
164 *
165 * @param[in] hash Hash of message
166 * @param[in] delay Delay of deletion
167 * @return New message
168 */
169struct GNUNET_MESSENGER_Message*
170create_message_delete (const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
171
172#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c b/src/messenger/gnunet-service-messenger_message_recv.c
deleted file mode 100644
index b2a5052d2..000000000
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ /dev/null
@@ -1,175 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_recv.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_recv.h"
27
28#include "gnunet-service-messenger_operation.h"
29
30static void
31forward_about_members (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
32 struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_CONTAINER_MultiHashMap *map)
33{
34 if (session->prev)
35 forward_about_members (room, tunnel, session->prev, map);
36
37 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
38 struct GNUNET_MESSENGER_ListMessage *element;
39
40 for (element = session->messages.head; element; element = element->next)
41 {
42 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
43 continue;
44
45 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
46 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
47 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Forwarding of session message could be duplicated!\n");
48
49 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
50
51 if (message)
52 forward_tunnel_message(tunnel, message, &(element->hash));
53 }
54}
55
56static int
57iterate_forward_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
58 struct GNUNET_MESSENGER_MemberSession *session)
59{
60 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
61
62 if (GNUNET_YES == is_member_session_completed(session))
63 return GNUNET_YES;
64
65 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
66
67 forward_about_members (tunnel->room, tunnel, session, map);
68
69 GNUNET_CONTAINER_multihashmap_destroy(map);
70 return GNUNET_YES;
71}
72
73int
74recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
75 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
76{
77 const uint32_t version = get_tunnel_messenger_version(tunnel);
78
79 if (GNUNET_OK != update_tunnel_messenger_version(tunnel, message->body.info.messenger_version))
80 {
81 disconnect_tunnel(tunnel);
82 return GNUNET_NO;
83 }
84
85 if (version == get_tunnel_messenger_version(tunnel))
86 return GNUNET_NO;
87
88 if (room->host)
89 {
90 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(room->host);
91
92 send_tunnel_message (tunnel, room->host, create_message_info(ego));
93 }
94
95 struct GNUNET_PeerIdentity peer;
96 get_tunnel_peer_identity(tunnel, &peer);
97
98 if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
99 {
100 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
101
102 iterate_store_members(member_store, iterate_forward_members, tunnel);
103 }
104
105 check_room_peer_status(room, tunnel);
106
107 return GNUNET_NO;
108}
109
110int
111recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
112 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
113{
114 struct GNUNET_PeerIdentity peer;
115 GNUNET_PEER_resolve (tunnel->peer, &peer);
116
117 if (0 == GNUNET_memcmp(&peer, &(message->body.peer.peer)))
118 {
119 if (!tunnel->peer_message)
120 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode);
121
122 GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
123 }
124
125 return GNUNET_YES;
126}
127
128static void
129callback_found_message (void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
130 const struct GNUNET_MESSENGER_Message *message,
131 const struct GNUNET_HashCode *hash)
132{
133 struct GNUNET_MESSENGER_SrvTunnel *tunnel = tunnel;
134
135 if (!message)
136 {
137 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
138
139 use_store_operation(
140 operation_store,
141 hash,
142 GNUNET_MESSENGER_OP_REQUEST,
143 GNUNET_MESSENGER_REQUEST_DELAY
144 );
145 }
146 else
147 forward_tunnel_message (tunnel, message, hash);
148}
149
150/*
151 * Function returns GNUNET_NO to drop forwarding the request.
152 * It will only be forwarded if it can't be answered!
153 */
154int
155recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
156 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
157{
158 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
159 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
160
161 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Request for message (%s)\n", GNUNET_h2s (hash));
162
163 if (!member)
164 return GNUNET_NO;
165
166 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
167
168 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
169 return GNUNET_NO;
170
171 if (GNUNET_NO == request_room_message(room, &(message->body.request.hash), session, callback_found_message, tunnel))
172 return GNUNET_YES;
173
174 return GNUNET_NO;
175}
diff --git a/src/messenger/gnunet-service-messenger_message_recv.h b/src/messenger/gnunet-service-messenger_message_recv.h
deleted file mode 100644
index 9cb36c466..000000000
--- a/src/messenger/gnunet-service-messenger_message_recv.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_recv.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "gnunet-service-messenger_message_kind.h"
33
34#include "gnunet-service-messenger_member_session.h"
35#include "gnunet-service-messenger_tunnel.h"
36#include "messenger_api_message.h"
37
38/**
39 * Handles a received info message to change the current member id to the one generated by
40 * the host connected to. (all current tunnels will be informed about the id change)
41 *
42 * @param[in/out] room Room of the message
43 * @param[in/out] tunnel Receiving connection
44 * @param[in] message INFO-Message
45 * @param[in] hash Hash of the message
46 * @return #GNUNET_NO to not forward the message
47 */
48int
49recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
50 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
51
52/**
53 * Handles a received peer message to link it to its origin tunnel if the peer identity matches.
54 * (the peer message and the member id can potentially be linked to the tunnel)
55 *
56 * @param[in/out] room Room of the message
57 * @param[in/out] tunnel Receiving connection
58 * @param[in] message PEER-Message
59 * @param[in] hash Hash of the message
60 * @return #GNUNET_YES to forward the message
61 */
62int
63recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
64 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
65
66/**
67 * Handles a received request message by checking for the requested message and forwarding it back
68 * if the message was found.
69 * (this can also cause this peer to send a new request instead of only forwarding the received one)
70 *
71 * @param[in/out] room Room of the message
72 * @param[in/out] tunnel Receiving connection
73 * @param[in] message REQUEST-Message
74 * @param[in] hash Hash of the message
75 * @return #GNUNET_YES or #GNUNET_NO depending on required forwarding
76 */
77int
78recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
79 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
80
81#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_RECV_H
diff --git a/src/messenger/gnunet-service-messenger_message_send.c b/src/messenger/gnunet-service-messenger_message_send.c
deleted file mode 100644
index a59a178cc..000000000
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ /dev/null
@@ -1,68 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_send.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_send.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_member_session.h"
30#include "gnunet-service-messenger_operation.h"
31
32void
33send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
34 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
35{
36 check_room_peer_status(room, NULL);
37}
38
39void
40send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
41 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
42{
43 if (!room->peer_message)
44 room->peer_message = GNUNET_new(struct GNUNET_HashCode);
45
46 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode));
47}
48
49void
50send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
51 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
52{
53 change_handle_member_id (handle, get_room_key(room), &(message->body.id.id));
54}
55
56void
57send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
58 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
59{
60 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
61
62 use_store_operation(
63 operation_store,
64 &(message->body.request.hash),
65 GNUNET_MESSENGER_OP_REQUEST,
66 GNUNET_MESSENGER_REQUEST_DELAY
67 );
68}
diff --git a/src/messenger/gnunet-service-messenger_message_send.h b/src/messenger/gnunet-service-messenger_message_send.h
deleted file mode 100644
index 63320ab17..000000000
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ /dev/null
@@ -1,89 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_send.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "gnunet-service-messenger_message_kind.h"
33
34#include "gnunet-service-messenger_tunnel.h"
35#include "messenger_api_message.h"
36
37/**
38 * Handles a sent join message to ensure growth of the decentralized room structure.
39 * (if the service provides a peer message for this room currently, it will be forwarded)
40 *
41 * @param[in/out] room Room of the message
42 * @param[in/out] handle Sending handle
43 * @param[in] message JOIN-Message
44 * @param[in] hash Hash of the message
45 */
46void
47send_message_join (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
48 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
49
50/**
51 * Handles a sent peer message to update the rooms peer message of this service.
52 * (a set peer message indicates this service being a part of the decentralized room structure)
53 *
54 * @param[in/out] room Room of the message
55 * @param[in/out] handle Sending handle
56 * @param[in] message PEER-Message
57 * @param[in] hash Hash of the message
58 */
59void
60send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
61 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
62
63/**
64 * Handles a sent id message to update the handles member id in the room.
65 * (changing member id is useful to prevent collisions)
66 *
67 * @param[in/out] room Room of the message
68 * @param[in/out] handle Sending handle
69 * @param[in] message ID-Message
70 * @param[in] hash Hash of the message
71 */
72void
73send_message_id (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
74 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
75
76/**
77 * Handles a sent request message to trigger the request operation for this service.
78 * (the request operation will deactivate the possibility of spamming requests)
79 *
80 * @param[in/out] room Room of the message
81 * @param[in/out] handle Sending handle
82 * @param[in] message PEER-Message
83 * @param[in] hash Hash of the message
84 */
85void
86send_message_request (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
87 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
88
89#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_SEND_H
diff --git a/src/messenger/gnunet-service-messenger_message_state.c b/src/messenger/gnunet-service-messenger_message_state.c
deleted file mode 100644
index cdd2d9712..000000000
--- a/src/messenger/gnunet-service-messenger_message_state.c
+++ /dev/null
@@ -1,109 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_state.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_state.h"
27
28void
29init_message_state (struct GNUNET_MESSENGER_MessageState *state)
30{
31 GNUNET_assert(state);
32
33 init_list_messages (&(state->last_messages));
34}
35
36void
37clear_message_state (struct GNUNET_MESSENGER_MessageState *state)
38{
39 GNUNET_assert(state);
40
41 clear_list_messages (&(state->last_messages));
42}
43
44void
45get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
46 struct GNUNET_HashCode *hash)
47{
48 GNUNET_assert((state) && (hash));
49
50 if (state->last_messages.head)
51 GNUNET_memcpy(hash, &(state->last_messages.head->hash), sizeof(*hash));
52 else
53 memset (hash, 0, sizeof(*hash));
54}
55
56const struct GNUNET_HashCode*
57get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state)
58{
59 GNUNET_assert(state);
60
61 if (state->last_messages.head == state->last_messages.tail)
62 return NULL;
63
64 return &(state->last_messages.tail->hash);
65}
66
67void
68update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
69 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
70{
71 GNUNET_assert((state) && (message) && (hash));
72
73 if ((GNUNET_YES == requested) ||
74 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
75 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
76 return;
77
78 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
79 remove_from_list_messages(&(state->last_messages), &(message->body.merge.previous));
80 remove_from_list_messages(&(state->last_messages), &(message->header.previous));
81
82 add_to_list_messages (&(state->last_messages), hash);
83}
84
85void
86load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path)
87{
88 GNUNET_assert((state) && (path));
89
90 char *last_messages_file;
91 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
92
93 load_list_messages(&(state->last_messages), last_messages_file);
94 GNUNET_free(last_messages_file);
95}
96
97void
98save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path)
99{
100 GNUNET_assert((state) && (path));
101
102 char *last_messages_file;
103 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
104
105 save_list_messages(&(state->last_messages), last_messages_file);
106 GNUNET_free(last_messages_file);
107}
108
109
diff --git a/src/messenger/gnunet-service-messenger_message_state.h b/src/messenger/gnunet-service-messenger_message_state.h
deleted file mode 100644
index dc8671df4..000000000
--- a/src/messenger/gnunet-service-messenger_message_state.h
+++ /dev/null
@@ -1,63 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_state.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31
32#include "messenger_api_message.h"
33#include "gnunet-service-messenger_list_messages.h"
34
35struct GNUNET_MESSENGER_MessageState
36{
37 struct GNUNET_MESSENGER_ListMessages last_messages;
38};
39
40void
41init_message_state (struct GNUNET_MESSENGER_MessageState *state);
42
43void
44clear_message_state (struct GNUNET_MESSENGER_MessageState *state);
45
46void
47get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
48 struct GNUNET_HashCode *hash);
49
50const struct GNUNET_HashCode*
51get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state);
52
53void
54update_message_state (struct GNUNET_MESSENGER_MessageState *state, int requested,
55 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
56
57void
58load_message_state (struct GNUNET_MESSENGER_MessageState *state, const char *path);
59
60void
61save_message_state (const struct GNUNET_MESSENGER_MessageState *state, const char *path);
62
63#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STATE_H
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c
deleted file mode 100644
index 1984eba21..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ /dev/null
@@ -1,549 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_message_store.h"
27#include "messenger_api_message.h"
28
29void
30init_message_store (struct GNUNET_MESSENGER_MessageStore *store)
31{
32 GNUNET_assert(store);
33
34 store->storage_messages = NULL;
35
36 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
37 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39
40 store->rewrite_entries = GNUNET_NO;
41 store->write_links = GNUNET_NO;
42}
43
44static int
45iterate_destroy_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
46{
47 struct GNUNET_MESSENGER_MessageEntry *entry = value;
48
49 GNUNET_free(entry);
50
51 return GNUNET_YES;
52}
53
54static int
55iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
56{
57 struct GNUNET_MESSENGER_Message *message = value;
58
59 destroy_message (message);
60
61 return GNUNET_YES;
62}
63
64static int
65iterate_destroy_links (void *cls, const struct GNUNET_HashCode *key, void *value)
66{
67 struct GNUNET_HashCode *previous = value;
68
69 GNUNET_free(previous);
70
71 return GNUNET_YES;
72}
73
74void
75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
76{
77 GNUNET_assert(store);
78
79 if (store->storage_messages)
80 {
81 GNUNET_DISK_file_close (store->storage_messages);
82
83 store->storage_messages = NULL;
84 }
85
86 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
87 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
88 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
89
90 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
91 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
92 GNUNET_CONTAINER_multihashmap_destroy (store->links);
93}
94
95struct GNUNET_MESSENGER_MessageEntryStorage
96{
97 struct GNUNET_HashCode hash;
98 struct GNUNET_MESSENGER_MessageEntry entry;
99};
100
101static void
102load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
103{
104 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
105
106 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
107
108 if (!entries)
109 return;
110
111 struct GNUNET_MESSENGER_MessageEntryStorage storage;
112 struct GNUNET_MESSENGER_MessageEntry *entry;
113
114 do
115 {
116 entry = GNUNET_new(struct GNUNET_MESSENGER_MessageEntry);
117
118 if (GNUNET_DISK_file_read (entries, &storage, sizeof(storage)) == sizeof(storage))
119 {
120 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
121
122 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
123 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
125 {
126 store->rewrite_entries = GNUNET_YES;
127 GNUNET_free(entry);
128 }
129 }
130 else
131 {
132 GNUNET_free(entry);
133
134 entry = NULL;
135 }
136 }
137 while (entry);
138
139 GNUNET_DISK_file_close (entries);
140}
141
142struct GNUNET_MESSENGER_MessageLinkStorage
143{
144 struct GNUNET_HashCode hash;
145 struct GNUNET_MESSENGER_MessageLink link;
146};
147
148static void
149load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
150{
151 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
152
153 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
154
155 if (!entries)
156 return;
157
158 struct GNUNET_MESSENGER_MessageLinkStorage storage;
159 struct GNUNET_MESSENGER_MessageLink *link = NULL;
160
161 memset(&storage, 0, sizeof(storage));
162
163 do
164 {
165 if ((sizeof(storage.hash) != GNUNET_DISK_file_read (entries, &(storage.hash), sizeof(storage.hash))) ||
166 (sizeof(storage.link.multiple) != GNUNET_DISK_file_read (entries, &(storage.link.multiple), sizeof(storage.link.multiple))) ||
167 (sizeof(storage.link.first) != GNUNET_DISK_file_read (entries, &(storage.link.first), sizeof(storage.link.first))) ||
168 ((GNUNET_YES == storage.link.multiple) &&
169 (sizeof(storage.link.second) != GNUNET_DISK_file_read (entries, &(storage.link.second), sizeof(storage.link.second)))))
170 break;
171
172 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
173
174 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
175
176 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
177 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
178 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
179 break;
180 }
181 while (link);
182
183 if (link)
184 GNUNET_free(link);
185
186 GNUNET_DISK_file_close (entries);
187}
188
189void
190load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
191{
192 GNUNET_assert((store) && (directory));
193
194 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
195
196 if (store->storage_messages)
197 GNUNET_DISK_file_close (store->storage_messages);
198
199 char *filename;
200 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
201
202 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
203 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
204 else
205 store->storage_messages = NULL;
206
207 GNUNET_free(filename);
208
209 if (!store->storage_messages)
210 return;
211
212 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
213
214 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
215 load_message_store_entries(store, filename);
216
217 GNUNET_free(filename);
218
219 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
220
221 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
222 load_message_store_links(store, filename);
223
224 GNUNET_free(filename);
225}
226
227struct GNUNET_MESSENGER_ClosureMessageSave
228{
229 struct GNUNET_MESSENGER_MessageStore *store;
230
231 struct GNUNET_DISK_FileHandle *storage;
232};
233
234static int
235iterate_save_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
236{
237 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
238 struct GNUNET_MESSENGER_MessageEntry *entry = value;
239
240 struct GNUNET_MESSENGER_MessageEntryStorage storage;
241
242 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
243 GNUNET_memcpy(&(storage.entry), entry, sizeof(*entry));
244
245 GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage));
246
247 return GNUNET_YES;
248}
249
250static int
251iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
252{
253 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
254
255 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
256 return GNUNET_YES;
257
258 struct GNUNET_MESSENGER_Message *message = value;
259 struct GNUNET_MESSENGER_MessageEntryStorage storage;
260
261 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
262
263 storage.entry.length = get_message_size (message, GNUNET_YES);
264 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
265
266 if ((GNUNET_SYSERR == storage.entry.offset) || (sizeof(storage)
267 != GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage))))
268 return GNUNET_YES;
269
270 char *buffer = GNUNET_malloc(storage.entry.length);
271
272 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
273
274 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
275
276 GNUNET_free(buffer);
277
278 return GNUNET_YES;
279}
280
281static int
282iterate_save_links (void *cls, const struct GNUNET_HashCode *key, void *value)
283{
284 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
285 struct GNUNET_MESSENGER_MessageLink *link = value;
286
287 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
288 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
289 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
290
291 if (GNUNET_YES == link->multiple)
292 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
293
294 return GNUNET_YES;
295}
296
297void
298save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
299{
300 GNUNET_assert((store) && (directory));
301
302 struct GNUNET_MESSENGER_ClosureMessageSave save;
303
304 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
305
306 char *filename;
307
308 if (GNUNET_YES != store->write_links)
309 goto save_entries;
310
311 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
312
313 save.store = store;
314 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
315
316 GNUNET_free(filename);
317
318 if (!save.storage)
319 goto save_entries;
320
321 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
322 goto close_links;
323
324 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
325 store->write_links = GNUNET_NO;
326
327close_links:
328 GNUNET_DISK_file_close (save.storage);
329
330save_entries:
331 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
332
333 save.store = store;
334 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
335
336 GNUNET_free(filename);
337
338 if (!save.storage)
339 return;
340
341 if (GNUNET_YES == store->rewrite_entries)
342 {
343 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
344 goto close_entries;
345
346 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
347 store->rewrite_entries = GNUNET_NO;
348 }
349 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
350 goto close_entries;
351
352 if (store->storage_messages)
353 GNUNET_DISK_file_close (store->storage_messages);
354
355 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
356
357 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
358 permission);
359
360 GNUNET_free(filename);
361
362 if (store->storage_messages)
363 {
364 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
365
366 GNUNET_DISK_file_sync (store->storage_messages);
367 GNUNET_DISK_file_sync (save.storage);
368 }
369
370close_entries:
371 GNUNET_DISK_file_close (save.storage);
372}
373
374int
375contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
376{
377 GNUNET_assert((store) && (hash));
378
379 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
380 return GNUNET_YES;
381
382 return GNUNET_CONTAINER_multihashmap_contains (store->entries, hash);
383}
384
385const struct GNUNET_MESSENGER_Message*
386get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
387{
388 GNUNET_assert((store) && (hash));
389
390 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
391
392 if (message)
393 return message;
394
395 if (!store->storage_messages)
396 return NULL;
397
398 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
399
400 if (!entry)
401 return NULL;
402
403 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
404 return message;
405
406 char *buffer = GNUNET_malloc(entry->length);
407
408 if (!buffer)
409 return NULL;
410
411 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) ||
412 (entry->length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)))
413 goto free_buffer;
414
415 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
416
417 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
418
419 struct GNUNET_HashCode check;
420 hash_message (message, entry->length, buffer, &check);
421
422 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
423 {
424 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
425 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Corrupted entry could not be removed from store: %s\n",
426 GNUNET_h2s(hash));
427
428 store->rewrite_entries = GNUNET_YES;
429
430 goto free_message;
431 }
432
433 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
434 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
435 goto free_buffer;
436
437free_message: destroy_message (message);
438 message = NULL;
439
440free_buffer:
441 GNUNET_free(buffer);
442
443 return message;
444}
445
446const struct GNUNET_MESSENGER_MessageLink*
447get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
448 int deleted_only)
449{
450 if (deleted_only)
451 goto get_link;
452
453 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
454
455 if (!message)
456 goto get_link;
457
458 static struct GNUNET_MESSENGER_MessageLink link;
459
460 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
461
462 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
463
464 if (GNUNET_YES == link.multiple)
465 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
466 else
467 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
468
469 return &link;
470
471get_link:
472 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
473}
474
475int
476put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
477 struct GNUNET_MESSENGER_Message *message)
478{
479 GNUNET_assert((store) && (hash) && (message));
480
481 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
482 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
483}
484
485static void
486add_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
487 const struct GNUNET_MESSENGER_Message *message)
488{
489 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
490
491 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
492
493 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
494
495 if (GNUNET_YES == link->multiple)
496 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
497 else
498 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
499
500 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
502 GNUNET_free(link);
503}
504
505int
506delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
507{
508 GNUNET_assert((store) && (hash));
509
510 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
511
512 if (!entry)
513 goto clear_memory;
514
515 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
516
517 if (message)
518 add_link (store, hash, message);
519
520 if (!store->storage_messages)
521 goto clear_entry;
522
523 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
524 return GNUNET_SYSERR;
525
526 char *clear_buffer = GNUNET_malloc(entry->length);
527
528 if (!clear_buffer)
529 return GNUNET_SYSERR;
530
531 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
532
533 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
534 != GNUNET_DISK_file_sync (store->storage_messages)))
535 {
536 GNUNET_free(clear_buffer);
537 return GNUNET_SYSERR;
538 }
539
540 GNUNET_free(clear_buffer);
541
542clear_entry:
543 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
544 store->rewrite_entries = GNUNET_YES;
545
546clear_memory:
547 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
548 return GNUNET_OK;
549}
diff --git a/src/messenger/gnunet-service-messenger_message_store.h b/src/messenger/gnunet-service-messenger_message_store.h
deleted file mode 100644
index 87305826a..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.h
+++ /dev/null
@@ -1,162 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_message_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H
27#define GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_disk_lib.h"
32
33struct GNUNET_MESSENGER_MessageEntry
34{
35 off_t offset;
36 uint16_t length;
37};
38
39struct GNUNET_MESSENGER_Message;
40
41struct GNUNET_MESSENGER_MessageLink
42{
43 uint8_t multiple;
44
45 struct GNUNET_HashCode first;
46 struct GNUNET_HashCode second;
47};
48
49struct GNUNET_MESSENGER_MessageStore
50{
51 struct GNUNET_DISK_FileHandle *storage_messages;
52
53 struct GNUNET_CONTAINER_MultiHashMap *entries;
54 struct GNUNET_CONTAINER_MultiHashMap *messages;
55 struct GNUNET_CONTAINER_MultiHashMap *links;
56
57 int rewrite_entries;
58 int write_links;
59};
60
61/**
62 * Initializes a message <i>store</i> as fully empty.
63 *
64 * @param[out] store Message store
65 */
66void
67init_message_store (struct GNUNET_MESSENGER_MessageStore *store);
68
69/**
70 * Clears a message <i>store</i>, wipes its content and deallocates its memory.
71 *
72 * @param[in/out] store Message store
73 */
74void
75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store);
76
77/**
78 * Loads messages from a <i>directory</i> into a message <i>store</i>.
79 *
80 * @param[out] store Message store
81 * @param[in] directory Path to a directory
82 */
83void
84load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
85
86/**
87 * Saves messages from a message <i>store</i> into a <i>directory</i>.
88 *
89 * @param[in] store Message store
90 * @param[in] directory Path to a directory
91 */
92void
93save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory);
94
95/**
96 * Checks if a message matching a given <i>hash</i> is stored in a message <i>store</i>.
97 * The function returns #GNUNET_YES if a match is found, #GNUNET_NO otherwise.
98 *
99 * The message has not to be loaded from disk into memory for this check!
100 *
101 * @param[in] store Message store
102 * @param[in] hash Hash of message
103 * @return #GNUNET_YES on match, otherwise #GNUNET_NO
104 */
105int
106contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
107
108/**
109 * Returns the message from a message <i>store</i> matching a given <i>hash</i>. If no matching
110 * message is found, NULL gets returned.
111 *
112 * This function requires the message to be loaded into memory!
113 * @see contains_store_message()
114 *
115 * @param[in/out] store Message store
116 * @param[in] hash Hash of message
117 * @return Message or NULL
118 */
119const struct GNUNET_MESSENGER_Message*
120get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
121
122/**
123 * Returns the message link from a message <i>store</i> matching a given <i>hash</i>. If the
124 * flag is set to #GNUNET_YES, only links from deleted messages will be returned or NULL.
125 *
126 * Otherwise message links will also returned for messages found in the store under the given
127 * hash. The link which will be returned copies link information from the message for
128 * temporary usage.
129 *
130 * @param[in/out] store Message store
131 * @param[in] hash Hash of message
132 * @param[in] deleted_only Flag
133 * @return Message link or NULL
134 */
135const struct GNUNET_MESSENGER_MessageLink*
136get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
137 int deleted_only);
138
139/**
140 * Stores a message into the message store. The result indicates if the operation was successful.
141 *
142 * @param[in/out] store Message store
143 * @param[in] hash Hash of message
144 * @param[in/out] message Message
145 * @return #GNUNET_OK on success, otherwise #GNUNET_NO
146 */
147int
148put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
149 struct GNUNET_MESSENGER_Message *message);
150
151/**
152 * Deletes a message in the message store. It will be removed from disk space and memory. The result
153 * indicates if the operation was successful.
154 *
155 * @param[in/out] store Message store
156 * @param[in] hash Hash of message
157 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
158 */
159int
160delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash);
161
162#endif //GNUNET_SERVICE_MESSENGER_MESSAGE_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_operation.c b/src/messenger/gnunet-service-messenger_operation.c
deleted file mode 100644
index d0c378699..000000000
--- a/src/messenger/gnunet-service-messenger_operation.c
+++ /dev/null
@@ -1,214 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_operation.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation.h"
27
28#include "gnunet-service-messenger_operation_store.h"
29
30struct GNUNET_MESSENGER_Operation*
31create_operation (const struct GNUNET_HashCode *hash)
32{
33 GNUNET_assert(hash);
34
35 struct GNUNET_MESSENGER_Operation *op = GNUNET_new(struct GNUNET_MESSENGER_Operation);
36
37 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
38 GNUNET_memcpy(&(op->hash), hash, sizeof(*hash));
39 op->timestamp = GNUNET_TIME_absolute_get_zero_();
40 op->store = NULL;
41 op->task = NULL;
42
43 return op;
44}
45
46void
47destroy_operation (struct GNUNET_MESSENGER_Operation *op)
48{
49 GNUNET_assert(op);
50
51 if (op->task)
52 GNUNET_SCHEDULER_cancel(op->task);
53
54 GNUNET_free(op);
55}
56
57static void
58callback_operation (void *cls);
59
60struct GNUNET_MESSENGER_Operation*
61load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path)
62{
63 GNUNET_assert((store) && (path));
64
65 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
66 struct GNUNET_MESSENGER_Operation* op = NULL;
67
68 if (GNUNET_OK != GNUNET_CONFIGURATION_parse(cfg, path))
69 goto destroy_config;
70
71 struct GNUNET_HashCode hash;
72
73 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "hash", &hash, sizeof(hash)))
74 goto destroy_config;
75
76 op = create_operation(&hash);
77
78 unsigned long long type_number;
79 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg, "operation", "type", &type_number))
80 switch (type_number)
81 {
82 case GNUNET_MESSENGER_OP_REQUEST:
83 op->type = GNUNET_MESSENGER_OP_REQUEST;
84 break;
85 case GNUNET_MESSENGER_OP_DELETE:
86 op->type = GNUNET_MESSENGER_OP_DELETE;
87 break;
88 case GNUNET_MESSENGER_OP_MERGE:
89 op->type = GNUNET_MESSENGER_OP_MERGE;
90 break;
91 default:
92 break;
93 }
94
95 if ((GNUNET_MESSENGER_OP_UNKNOWN == op->type) ||
96 (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "timestamp", &(op->timestamp), sizeof(op->timestamp))))
97 {
98 destroy_operation(op);
99 op = NULL;
100 goto destroy_config;
101 }
102
103 const struct GNUNET_TIME_Relative delay = GNUNET_TIME_absolute_get_remaining(op->timestamp);
104
105 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
106 delay,
107 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
108 callback_operation,
109 op
110 );
111
112 op->store = store;
113
114destroy_config:
115 GNUNET_CONFIGURATION_destroy (cfg);
116
117 return op;
118}
119
120void
121save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path)
122{
123 GNUNET_assert((path) && (op));
124
125 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
126
127 char *hash_data;
128 hash_data = GNUNET_STRINGS_data_to_string_alloc (&(op->hash), sizeof(op->hash));
129
130 if (hash_data)
131 {
132 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "hash", hash_data);
133
134 GNUNET_free(hash_data);
135 }
136
137 GNUNET_CONFIGURATION_set_value_number(cfg, "operation", "type", op->type);
138
139 char *timestamp_data;
140 timestamp_data = GNUNET_STRINGS_data_to_string_alloc (&(op->timestamp), sizeof(op->timestamp));
141
142 if (timestamp_data)
143 {
144 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "timestamp", timestamp_data);
145
146 GNUNET_free(timestamp_data);
147 }
148
149 GNUNET_CONFIGURATION_write (cfg, path);
150 GNUNET_CONFIGURATION_destroy (cfg);
151}
152
153extern void
154callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
155 enum GNUNET_MESSENGER_OperationType type,
156 const struct GNUNET_HashCode *hash);
157
158static void
159callback_operation (void *cls)
160{
161 struct GNUNET_MESSENGER_Operation *op = cls;
162
163 op->task = NULL;
164
165 callback_store_operation (op->store, op->type, &(op->hash));
166}
167
168int
169start_operation (struct GNUNET_MESSENGER_Operation *op,
170 enum GNUNET_MESSENGER_OperationType type,
171 struct GNUNET_MESSENGER_OperationStore *store,
172 struct GNUNET_TIME_Relative delay)
173{
174 GNUNET_assert((op) && (store));
175
176 if (op->task)
177 return GNUNET_SYSERR;
178
179 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_add(
180 GNUNET_TIME_absolute_get(),
181 delay
182 );
183
184 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
185 delay,
186 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
187 callback_operation,
188 op
189 );
190
191 op->type = type;
192 op->timestamp = timestamp;
193 op->store = store;
194
195 return GNUNET_OK;
196}
197
198int
199stop_operation (struct GNUNET_MESSENGER_Operation *op)
200{
201 GNUNET_assert(op);
202
203 if (!op->task)
204 return GNUNET_SYSERR;
205
206 GNUNET_SCHEDULER_cancel(op->task);
207 op->task = NULL;
208
209 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
210 op->timestamp = GNUNET_TIME_absolute_get_zero_();
211 op->store = NULL;
212
213 return GNUNET_OK;
214}
diff --git a/src/messenger/gnunet-service-messenger_operation.h b/src/messenger/gnunet-service-messenger_operation.h
deleted file mode 100644
index f1e06f4a7..000000000
--- a/src/messenger/gnunet-service-messenger_operation.h
+++ /dev/null
@@ -1,129 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_operation.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_H
28
29#include "platform.h"
30#include "gnunet_configuration_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_strings_lib.h"
34#include "gnunet_time_lib.h"
35
36enum GNUNET_MESSENGER_OperationType
37{
38 GNUNET_MESSENGER_OP_REQUEST = 1,
39 GNUNET_MESSENGER_OP_DELETE = 2,
40 GNUNET_MESSENGER_OP_MERGE = 3,
41
42 GNUNET_MESSENGER_OP_UNKNOWN = 0
43};
44
45struct GNUNET_MESSENGER_OperationStore;
46
47struct GNUNET_MESSENGER_Operation
48{
49 enum GNUNET_MESSENGER_OperationType type;
50
51 struct GNUNET_HashCode hash;
52 struct GNUNET_TIME_Absolute timestamp;
53
54 struct GNUNET_MESSENGER_OperationStore *store;
55 struct GNUNET_SCHEDULER_Task* task;
56};
57
58/**
59 * Creates and allocates a new operation under a given <i>hash</i>.
60 *
61 * @param[in] hash Hash of message
62 */
63struct GNUNET_MESSENGER_Operation*
64create_operation (const struct GNUNET_HashCode *hash);
65
66/**
67 * Destroys an operation and frees its memory fully.
68 *
69 * @param[in/out] op Operation
70 */
71void
72destroy_operation (struct GNUNET_MESSENGER_Operation *op);
73
74/**
75 * Loads data from a configuration file at a selected <i>path</i> into
76 * a new allocated and created operation for a specific operation
77 * <i>store</i> if the required information could be read successfully.
78 *
79 * The method will return the new operation and it will be started
80 * automatically to match its timestamp of execution.
81 *
82 * If the method fails to restore any valid operation from the file,
83 * NULL gets returned instead.
84 *
85 * @param[in/out] store Operation store
86 * @param[in] path Path of a configuration file
87 */
88struct GNUNET_MESSENGER_Operation*
89load_operation (struct GNUNET_MESSENGER_OperationStore *store, const char *path);
90
91/**
92 * Saves data from an <i>operation</i> into a configuration file at a
93 * selected <i>path</i> which can be load to restore the operation
94 * completely and continue its process.
95 *
96 * @param[in] op Operation
97 * @param[in] path Path of a configuration file
98 */
99void
100save_operation (const struct GNUNET_MESSENGER_Operation *op, const char *path);
101
102/**
103 * Starts an inactive operation with a given <i>delay</i> in a
104 * specific operation <i>store</i>. The method will replace the
105 * operations type to process it correctly. An operation can't be
106 * started twice, it has to be stopped or fully processed first.
107 *
108 * @param[in/out] op Operation
109 * @param[in] type Type of operation
110 * @param[in/out] store Operation store
111 * @param[in] delay Delay
112 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
113 */
114int
115start_operation (struct GNUNET_MESSENGER_Operation *op,
116 enum GNUNET_MESSENGER_OperationType type,
117 struct GNUNET_MESSENGER_OperationStore *store,
118 struct GNUNET_TIME_Relative delay);
119
120/**
121 * Stops an active operation and resets its type to be
122 * #GNUNET_MESSENGER_OP_UNKNOWN.
123 *
124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
125 */
126int
127stop_operation (struct GNUNET_MESSENGER_Operation *op);
128
129#endif //GNUNET_SERVICE_MESSENGER_OPERATION_H
diff --git a/src/messenger/gnunet-service-messenger_operation_store.c b/src/messenger/gnunet-service-messenger_operation_store.c
deleted file mode 100644
index a32fbad2c..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.c
+++ /dev/null
@@ -1,226 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_operation_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_operation_store.h"
27
28#include "gnunet-service-messenger_operation.h"
29#include "gnunet-service-messenger_room.h"
30
31void
32init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
33{
34 GNUNET_assert((store) && (room));
35
36 store->room = room;
37 store->operations = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Operation *op = value;
44
45 destroy_operation(op);
46
47 return GNUNET_YES;
48}
49
50void
51clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
52{
53 GNUNET_assert(store);
54
55 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_destroy_operations, NULL);
56 GNUNET_CONTAINER_multihashmap_destroy(store->operations);
57}
58
59static int
60callback_scan_for_operations (void *cls, const char *filename)
61{
62 struct GNUNET_MESSENGER_OperationStore *store = cls;
63
64 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
65 {
66 char *path;
67
68 GNUNET_asprintf (&path, "%s%c", filename, DIR_SEPARATOR);
69
70 struct GNUNET_MESSENGER_Operation *op = load_operation(store, path);
71
72 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
73 store->operations,
74 &(op->hash), op,
75 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
76 {
77 destroy_operation(op);
78 }
79
80 GNUNET_free(path);
81 }
82
83 return GNUNET_OK;
84}
85
86void
87load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
88 const char *directory)
89{
90 GNUNET_assert ((store) && (directory));
91
92 if (GNUNET_OK == GNUNET_DISK_directory_test (directory, GNUNET_YES))
93 GNUNET_DISK_directory_scan (directory, callback_scan_for_operations, store);
94}
95
96static int
97iterate_save_operations (void *cls, const struct GNUNET_HashCode *key, void *value)
98{
99 const char *save_dir = cls;
100
101 struct GNUNET_MESSENGER_Operation *op = value;
102
103 if (!op)
104 return GNUNET_YES;
105
106 char *op_dir;
107 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s(key));
108 save_operation(op, op_dir);
109
110 GNUNET_free(op_dir);
111 return GNUNET_YES;
112}
113
114void
115save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
116 const char *directory)
117{
118 GNUNET_assert ((store) && (directory));
119
120 char* save_dir;
121 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
122
123 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
124 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
125 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_save_operations, save_dir);
126
127 GNUNET_free(save_dir);
128}
129
130enum GNUNET_MESSENGER_OperationType
131get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
132 const struct GNUNET_HashCode *hash)
133{
134 GNUNET_assert((store) && (hash));
135
136 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
137
138 if (!op)
139 return GNUNET_MESSENGER_OP_UNKNOWN;
140
141 return op->type;
142}
143
144int
145use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
146 const struct GNUNET_HashCode *hash,
147 enum GNUNET_MESSENGER_OperationType type,
148 struct GNUNET_TIME_Relative delay)
149{
150 GNUNET_assert((store) && (hash));
151
152 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
153
154 if (op)
155 goto use_op;
156
157 op = create_operation(hash);
158
159 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->operations, hash, op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
160 {
161 destroy_operation(op);
162
163 return GNUNET_SYSERR;
164 }
165
166use_op:
167 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
168 (type == GNUNET_MESSENGER_OP_DELETE))
169 stop_operation (op);
170
171 return start_operation(op, type, store, delay);
172}
173
174void
175cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
176 const struct GNUNET_HashCode *hash)
177{
178 GNUNET_assert((store) && (hash));
179
180 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
181
182 if (!op)
183 return;
184
185 stop_operation(op);
186
187 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(store->operations, hash, op))
188 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Canceled operation could not be removed: %s\n",
189 GNUNET_h2s(hash));
190
191 destroy_operation(op);
192}
193
194extern void
195callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
196
197extern void
198callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash);
199
200void
201callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
202 enum GNUNET_MESSENGER_OperationType type,
203 const struct GNUNET_HashCode *hash)
204{
205 GNUNET_assert((store) && (hash));
206
207 struct GNUNET_HashCode op_hash;
208 GNUNET_memcpy(&op_hash, hash, sizeof(op_hash));
209 cancel_store_operation (store, &op_hash);
210
211 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
212
213 switch (type)
214 {
215 case GNUNET_MESSENGER_OP_REQUEST:
216 break;
217 case GNUNET_MESSENGER_OP_DELETE:
218 callback_room_deletion (room, &op_hash);
219 break;
220 case GNUNET_MESSENGER_OP_MERGE:
221 callback_room_merge (room, &op_hash);
222 break;
223 default:
224 break;
225 }
226}
diff --git a/src/messenger/gnunet-service-messenger_operation_store.h b/src/messenger/gnunet-service-messenger_operation_store.h
deleted file mode 100644
index 4c613437c..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.h
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 src/messenger/gnunet-service-messenger_operation_store.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
27#define GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_time_lib.h"
34
35struct GNUNET_MESSENGER_SrvRoom;
36
37struct GNUNET_MESSENGER_OperationStore
38{
39 struct GNUNET_MESSENGER_SrvRoom *room;
40
41 struct GNUNET_CONTAINER_MultiHashMap *operations;
42};
43
44/**
45 * Initializes an operation <i>store</i> as fully empty with a given <i>room</i>.
46 *
47 * @param[out] store Operation store
48 * @param[in/out] room Room
49 */
50void
51init_operation_store (struct GNUNET_MESSENGER_OperationStore *store, struct GNUNET_MESSENGER_SrvRoom *room);
52
53/**
54 * Clears an operation <i>store</i>, stops all operations and deallocates its memory.
55 *
56 * @param[in/out] store Operation store
57 */
58void
59clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store);
60
61/**
62 * Loads operations from a <i>directory</i> into an operation <i>store</i>.
63 *
64 * @param[out] store Operation store
65 * @param[in] directory Path to a directory
66 */
67void
68load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
69 const char *directory);
70
71/**
72 * Saves operations from an operation <i>store</i> into a <i>directory</i>.
73 *
74 * @param[in] store Operation store
75 * @param[in] directory Path to a directory
76 */
77void
78save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
79 const char *directory);
80
81/**
82 * Returns the type of the active operation under a given <i>hash</i> in
83 * a specific operation <i>store</i>. If there is no active operation under
84 * the given <i>hash</i>, #GNUNET_MESSENGER_OP_UNKNOWN gets returned instead.
85 *
86 * @param[in] store Operation store
87 * @param[in] hash Hash of message
88 * @return Type of operation or #GNUNET_MESSENGER_OP_UNKNOWN
89 */
90enum GNUNET_MESSENGER_OperationType
91get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
92 const struct GNUNET_HashCode *hash);
93
94/**
95 * Tries to use an operation under a given <i>hash</i> in a specific
96 * operation <i>store</i>. The operation will use the selected <i>type</i>
97 * if successful. The operation will be delayed by a given <i>delay</i>.
98 *
99 * If the selected type is #GNUNET_MESSENGER_OP_DELETE any active operation
100 * under the given hash will be stopped and replaced.
101 *
102 * If the new operation could be started successfully the method returns
103 * #GNUNET_OK, otherwise #GNUNET_SYSERR.
104 *
105 * @param[in/out] store Operation store
106 * @param[in] hash Hash of message
107 * @param[in] type Operation type
108 * @param[in] delay Delay
109 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
110 */
111int
112use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
113 const struct GNUNET_HashCode *hash,
114 enum GNUNET_MESSENGER_OperationType type,
115 struct GNUNET_TIME_Relative delay);
116
117/**
118 * Stops any active operation under a given <i>hash</i> in a specific
119 * operation <i>store</i>.
120 *
121 * Beware that calling this method will also implicitly free the memory
122 * of any active operation under the given hash!
123 *
124 * @param[in/out] store Operation store
125 * @param[in] hash Hash of message
126 */
127void
128cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
129 const struct GNUNET_HashCode *hash);
130
131#endif //GNUNET_SERVICE_MESSENGER_OPERATION_STORE_H
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
deleted file mode 100644
index 73e94908f..000000000
--- a/src/messenger/gnunet-service-messenger_room.c
+++ /dev/null
@@ -1,1210 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_room.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_room.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_member_session.h"
30
31#include "gnunet-service-messenger_message_kind.h"
32#include "gnunet-service-messenger_message_handle.h"
33#include "gnunet-service-messenger_message_send.h"
34
35#include "gnunet-service-messenger_operation.h"
36
37#include "gnunet-service-messenger.h"
38#include "gnunet-service-messenger_service.h"
39#include "gnunet-service-messenger_tunnel.h"
40#include "messenger_api_util.h"
41
42static void
43idle_request_room_messages (void *cls);
44
45struct GNUNET_MESSENGER_SrvRoom*
46create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
47{
48 GNUNET_assert((handle) && (key));
49
50 struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new(struct GNUNET_MESSENGER_SrvRoom);
51
52 room->service = handle->service;
53 room->host = handle;
54 room->port = NULL;
55
56 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
57
58 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
59
60 init_member_store(get_room_member_store(room), room);
61 init_message_store (get_room_message_store(room));
62 init_operation_store(get_room_operation_store(room), room);
63
64 init_list_tunnels (&(room->basement));
65 init_message_state(&(room->state));
66
67 room->peer_message = NULL;
68
69 init_list_messages (&(room->handling));
70 room->idle = NULL;
71
72 if (room->service->dir)
73 load_room (room);
74
75 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
76
77 return room;
78}
79
80static int
81iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
82{
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
84 destroy_tunnel (tunnel);
85 return GNUNET_YES;
86}
87
88static void
89handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
90
91void
92destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
93{
94 GNUNET_assert(room);
95
96 if (room->idle)
97 {
98 GNUNET_SCHEDULER_cancel (room->idle);
99
100 room->idle = NULL;
101 }
102
103 if (room->port)
104 GNUNET_CADET_close_port (room->port);
105
106 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
107
108 handle_room_messages (room);
109
110 if (room->service->dir)
111 save_room (room);
112
113 clear_member_store (get_room_member_store(room));
114 clear_message_store (get_room_message_store(room));
115 clear_operation_store(get_room_operation_store(room));
116
117 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
118
119 clear_list_tunnels (&(room->basement));
120 clear_message_state(&(room->state));
121
122 if (room->peer_message)
123 GNUNET_free(room->peer_message);
124
125 GNUNET_free(room);
126}
127
128struct GNUNET_MESSENGER_MemberStore*
129get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
130{
131 GNUNET_assert(room);
132
133 return &(room->member_store);
134}
135
136struct GNUNET_MESSENGER_MessageStore*
137get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
138{
139 GNUNET_assert(room);
140
141 return &(room->message_store);
142}
143
144struct GNUNET_MESSENGER_OperationStore*
145get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
146{
147 GNUNET_assert(room);
148
149 return &(room->operation_store);
150}
151
152static int
153send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
154 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
155{
156 if ((!handle) || (!is_tunnel_connected (tunnel)))
157 return GNUNET_NO;
158
159 return send_tunnel_message (tunnel, handle, create_message_info (get_handle_ego (handle)));
160}
161
162static void*
163callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *source)
164{
165 struct GNUNET_MESSENGER_SrvRoom *room = cls;
166
167 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
168
169 if ((tunnel) &&
170 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
172 {
173 destroy_tunnel (tunnel);
174 tunnel = NULL;
175 }
176
177 if (!tunnel)
178 {
179 delayed_disconnect_channel (channel);
180 return NULL;
181 }
182
183 bind_tunnel(tunnel, channel);
184
185 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
186 GNUNET_h2s(get_room_key(room)), GNUNET_i2s (source));
187
188 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
189 return tunnel;
190
191 disconnect_tunnel (tunnel);
192
193 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
194 destroy_tunnel (tunnel);
195
196 return NULL;
197}
198
199static int
200join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
201 struct GNUNET_MESSENGER_Member *member)
202{
203 GNUNET_assert((room) && (handle) && (member));
204
205 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_room_key (room)),
206 GNUNET_sh2s (get_member_id(member)));
207
208 if (GNUNET_OK != change_handle_member_id (handle, get_room_key(room), get_member_id(member)))
209 return GNUNET_NO;
210
211 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego (handle));
212
213 if (!message)
214 {
215 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be created!\n");
216
217 return GNUNET_NO;
218 }
219
220 return send_room_message (room, handle, message);
221}
222
223struct GNUNET_MESSENGER_MemberNotify
224{
225 struct GNUNET_MESSENGER_SrvRoom *room;
226 struct GNUNET_MESSENGER_SrvHandle *handle;
227 struct GNUNET_MESSENGER_MemberSession *session;
228};
229
230static void
231notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify, struct GNUNET_MESSENGER_MemberSession *session,
232 struct GNUNET_CONTAINER_MultiHashMap *map, int check_permission)
233{
234 if (session->prev)
235 notify_about_members (notify, session->prev, map, GNUNET_YES);
236
237 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(notify->room);
238 struct GNUNET_MESSENGER_ListMessage *element;
239
240 for (element = session->messages.head; element; element = element->next)
241 {
242 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
243 continue;
244
245 if ((GNUNET_YES == check_permission) &&
246 (GNUNET_YES != check_member_session_history(notify->session, &(element->hash), GNUNET_NO)))
247 continue;
248
249 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
250 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
251 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message could be duplicated!\n");
252
253 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
254
255 if (message)
256 notify_handle_message (notify->handle, get_room_key(notify->room), session, message, &(element->hash));
257 }
258}
259
260static int
261iterate_notify_about_members (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
262 struct GNUNET_MESSENGER_MemberSession *session)
263{
264 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
265
266 if ((notify->session == session) || (GNUNET_YES == is_member_session_completed(session)))
267 return GNUNET_YES;
268
269 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
270
271 notify_about_members (notify, session, map, GNUNET_NO);
272
273 GNUNET_CONTAINER_multihashmap_destroy(map);
274 return GNUNET_YES;
275}
276
277static int
278join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
279{
280 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
281
282 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
283 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
284
285 if (GNUNET_NO == join_room (room, handle, member))
286 return GNUNET_NO;
287
288 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
289 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
290
291 if (!session)
292 {
293 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
294 return GNUNET_NO;
295 }
296
297 struct GNUNET_MESSENGER_MemberNotify notify;
298
299 notify.room = room;
300 notify.handle = handle;
301 notify.session = session;
302
303 iterate_store_members(get_room_member_store(room), iterate_notify_about_members, &notify);
304
305 return GNUNET_YES;
306}
307
308extern int
309check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
310
311extern void
312handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
313
314extern void
315callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel);
316
317int
318open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
319{
320 GNUNET_assert((room) && (handle));
321
322 if (room->port)
323 return join_room_locally (room, handle);
324
325 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
326 const struct GNUNET_HashCode *key = get_room_key (room);
327
328 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
329 struct GNUNET_MessageHeader, NULL),
330 GNUNET_MQ_handler_end() };
331
332 struct GNUNET_HashCode port;
333 convert_messenger_key_to_port(key, &port);
334 room->port = GNUNET_CADET_open_port (cadet, &port, callback_room_connect, room, NULL, callback_tunnel_disconnect,
335 handlers);
336
337 if (room->port)
338 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
339 GNUNET_h2s(get_room_key(room)));
340 else
341 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
342 GNUNET_h2s(get_room_key(room)));
343
344 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
345
346 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
347 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
348
349 if (member)
350 goto exit_open_room;
351
352 member = add_store_member(member_store, member_id);
353
354 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
355 {
356 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
357
358 GNUNET_CADET_close_port (room->port);
359 room->port = NULL;
360
361 return GNUNET_NO;
362 }
363
364exit_open_room:
365 return (room->port ? send_room_message (room, handle, create_message_peer (room->service)) : GNUNET_NO);
366}
367
368int
369enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
370 const struct GNUNET_PeerIdentity *door)
371{
372 GNUNET_assert((room) && (handle) && (door));
373
374 struct GNUNET_PeerIdentity peer;
375
376 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
377 (0 == GNUNET_memcmp(&peer, door)))
378 return join_room_locally (room, handle);
379
380 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
381
382 if (!tunnel)
383 {
384 tunnel = create_tunnel (room, door);
385
386 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
387 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
388 {
389 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
390 destroy_tunnel (tunnel);
391 return GNUNET_NO;
392 }
393 }
394
395 if (GNUNET_SYSERR == connect_tunnel (tunnel))
396 {
397 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
398 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
399 destroy_tunnel (tunnel);
400 return GNUNET_NO;
401 }
402
403 return join_room_locally (room, handle);
404}
405
406struct GNUNET_MQ_Envelope*
407pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
408 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode)
409{
410 GNUNET_assert((room) && (handle) && (message) && (hash));
411
412 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
413
414 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, get_room_key(room));
415
416 GNUNET_assert(id);
417
418 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
419 get_message_state_chain_hash (&(room->state), &(message->header.previous));
420
421 return pack_message (message, hash, get_handle_ego (handle), mode);
422}
423
424struct GNUNET_MESSENGER_ClosureSendRoom
425{
426 struct GNUNET_MESSENGER_SrvRoom *room;
427 struct GNUNET_MESSENGER_SrvHandle *handle;
428 struct GNUNET_MESSENGER_SrvTunnel *exclude;
429 struct GNUNET_MESSENGER_Message *message;
430 struct GNUNET_HashCode *hash;
431 int packed;
432};
433
434static int
435iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
436{
437 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
438
439 if ((!is_tunnel_connected (tunnel)) ||
440 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
441 return GNUNET_YES;
442
443 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
444
445 if (tunnel == closure->exclude)
446 return GNUNET_YES;
447
448 struct GNUNET_MQ_Envelope *env = NULL;
449
450 if (closure->packed == GNUNET_NO)
451 {
452 env = pack_room_message (closure->room, closure->handle, closure->message, closure->hash,
453 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
454
455 if (env)
456 closure->packed = GNUNET_YES;
457 }
458 else
459 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
460
461 if (env)
462 send_tunnel_envelope (tunnel, env, closure->hash);
463
464 return GNUNET_YES;
465}
466
467int
468update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
469 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
470
471void
472callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
473 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
474
475int
476send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
477 struct GNUNET_MESSENGER_Message *message)
478{
479 GNUNET_assert((room) && (handle));
480
481 if (!message)
482 return GNUNET_NO;
483
484 if (GNUNET_YES == is_message_session_bound(message))
485 merge_room_last_messages(room, handle);
486
487 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
488 GNUNET_sh2s(get_handle_member_id(handle, get_room_key(room))));
489
490 struct GNUNET_HashCode hash;
491 struct GNUNET_MESSENGER_ClosureSendRoom closure;
492
493 closure.room = room;
494 closure.handle = handle;
495 closure.exclude = NULL;
496 closure.message = message;
497 closure.hash = &hash;
498 closure.packed = GNUNET_NO;
499
500 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
501
502 if (GNUNET_NO == closure.packed)
503 pack_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
504
505 const int new_message = update_room_message (room, message, &hash);
506
507 if (GNUNET_YES != new_message)
508 return GNUNET_SYSERR;
509
510 switch (message->header.kind)
511 {
512 case GNUNET_MESSENGER_KIND_JOIN:
513 send_message_join (room, handle, message, &hash);
514 break;
515 case GNUNET_MESSENGER_KIND_PEER:
516 send_message_peer (room, handle, message, &hash);
517 break;
518 case GNUNET_MESSENGER_KIND_ID:
519 send_message_id (room, handle, message, &hash);
520 break;
521 case GNUNET_MESSENGER_KIND_REQUEST:
522 send_message_request (room, handle, message, &hash);
523 break;
524 default:
525 break;
526 }
527
528 callback_room_handle_message (room, handle, message, &hash);
529 return GNUNET_YES;
530}
531
532void
533forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
534 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
535{
536 GNUNET_assert((room) && (tunnel));
537
538 if (!message)
539 return;
540
541 struct GNUNET_MESSENGER_ClosureSendRoom closure;
542 struct GNUNET_HashCode message_hash;
543
544 GNUNET_memcpy(&message_hash, hash, sizeof(struct GNUNET_HashCode));
545
546 closure.room = room;
547 closure.handle = NULL;
548 closure.exclude = tunnel;
549 closure.message = message;
550 closure.hash = &message_hash;
551 closure.packed = GNUNET_YES;
552
553 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
554}
555
556void
557check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel)
558{
559 if (!room->peer_message)
560 return;
561
562 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
563
564 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, room->peer_message);
565
566 if (!message)
567 {
568 GNUNET_free(room->peer_message);
569 room->peer_message = NULL;
570 return;
571 }
572
573 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
574 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
575
576 if (!member)
577 goto resend_peer_message;
578
579 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
580
581 if (GNUNET_YES == is_member_session_closed(session))
582 goto resend_peer_message;
583
584 if (tunnel)
585 forward_tunnel_message(tunnel, message, room->peer_message);
586
587 return;
588
589resend_peer_message:
590 if (room->host)
591 send_room_message (room, room->host, create_message_peer (room->service));
592}
593
594void
595merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
596{
597 GNUNET_assert(room);
598
599 if (!handle)
600 return;
601
602 const struct GNUNET_HashCode *hash;
603
604merge_next:
605 hash = get_message_state_merge_hash (&(room->state));
606
607 if (!hash)
608 return;
609
610 send_room_message (room, handle, create_message_merge (hash));
611 goto merge_next;
612}
613
614void
615callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
616{
617 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
618 {
619 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
620 return;
621 }
622}
623
624void
625callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
626{
627 if (!room->host)
628 return;
629
630 send_room_message (room, room->host, create_message_merge (hash));
631}
632
633int
634delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
635 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay)
636{
637 GNUNET_assert((room) && (session) && (hash));
638
639 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
640
641 if (0 == GNUNET_memcmp(&forever, &delay))
642 {
643 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
644 return GNUNET_SYSERR;
645 }
646
647 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
648
649 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
650
651 if (!message)
652 return GNUNET_YES;
653
654 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
655 {
656 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
657 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
658
659 return GNUNET_NO;
660 }
661
662 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
663
664 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
665 {
666 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
667 return GNUNET_SYSERR;
668 }
669
670 return GNUNET_YES;
671}
672
673struct GNUNET_CADET_Handle*
674get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
675{
676 GNUNET_assert(room);
677
678 return room->service->cadet;
679}
680
681const struct GNUNET_HashCode*
682get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
683{
684 GNUNET_assert(room);
685
686 return &(room->key);
687}
688
689const struct GNUNET_MESSENGER_SrvTunnel*
690get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer)
691{
692 GNUNET_assert((room) && (peer));
693
694 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
695}
696
697static int
698request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
699 const struct GNUNET_MESSENGER_MemberSession *session,
700 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
701{
702 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
703
704 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
705 message_store, hash, GNUNET_YES
706 );
707
708 if (!link)
709 goto forward;
710
711 int result = request_room_message_step(room, &(link->first), session, callback, cls);
712
713 if ((GNUNET_YES == link->multiple) &&
714 (GNUNET_YES == request_room_message_step(room, &(link->second), session, callback, cls)))
715 return GNUNET_YES;
716 else
717 return result;
718
719forward:
720 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))
721 return GNUNET_YES;
722
723 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
724
725 if (!message)
726 return GNUNET_NO;
727
728 if (callback)
729 callback (cls, room, message, hash);
730
731 return GNUNET_YES;
732}
733
734int
735request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
736 const struct GNUNET_MESSENGER_MemberSession *session,
737 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls)
738{
739 GNUNET_assert((room) && (hash));
740
741 int result = request_room_message_step (room, hash, session, callback, cls);
742
743 if ((GNUNET_NO == result) && (callback))
744 callback (cls, room, NULL, hash);
745
746 return result;
747}
748
749void
750callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls)
751{
752 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
753
754 if (!room->host)
755 return;
756
757 struct GNUNET_PeerIdentity identity;
758 get_tunnel_peer_identity(tunnel, &identity);
759
760 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
761 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
762 return;
763
764 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
765 send_room_message (room, room->host, create_message_miss (&identity));
766}
767
768int
769callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
770 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
771{
772 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
773 {
774 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
775 return GNUNET_SYSERR;
776 }
777
778 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
779
780 const struct GNUNET_MESSENGER_Message *previous = get_store_message(message_store, &(message->header.previous));
781
782 if (!previous)
783 goto skip_time_comparison;
784
785 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(message->header.timestamp);
786 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh(previous->header.timestamp);
787
788 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(timestamp, last).rel_value_us)
789 {
790 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Timestamp does not check out!\n");
791 return GNUNET_SYSERR;
792 }
793
794skip_time_comparison:
795 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
796 GNUNET_MESSENGER_name_of_kind(message->header.kind));
797
798 return GNUNET_OK;
799}
800
801static void
802idle_request_room_messages (void *cls)
803{
804 struct GNUNET_MESSENGER_SrvRoom *room = cls;
805
806 room->idle = NULL;
807
808 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
809 const struct GNUNET_HashCode *hash = get_message_state_merge_hash(&(room->state));
810
811 if ((hash) &&
812 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, hash)))
813 use_store_operation(
814 operation_store,
815 hash,
816 GNUNET_MESSENGER_OP_MERGE,
817 GNUNET_MESSENGER_MERGE_DELAY
818 );
819
820 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
821 GNUNET_MESSENGER_IDLE_DELAY,
822 GNUNET_SCHEDULER_PRIORITY_IDLE,
823 idle_request_room_messages,
824 cls
825 );
826}
827
828void
829solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
830 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp)
831{
832 GNUNET_assert ((room) && (public_key) && (member_id));
833
834 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
835 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
836
837 if ((!member) || (1 >= GNUNET_CONTAINER_multihashmap_size(member->sessions)))
838 return;
839
840 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
841 struct GNUNET_MESSENGER_ListHandle* element;
842
843 for (element = handles->head; element; element = element->next)
844 {
845 if (0 != GNUNET_memcmp(member_id, get_handle_member_id(element->handle, get_room_key(room))))
846 continue;
847
848 if (0 == GNUNET_memcmp(public_key, &(get_handle_ego(element->handle)->pub)))
849 continue;
850
851 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(element->handle)->pub));
852
853 if (!session)
854 continue;
855
856 struct GNUNET_TIME_Absolute start = get_member_session_start(session);
857
858 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(start, timestamp).rel_value_us)
859 continue;
860
861 struct GNUNET_ShortHashCode random_id;
862 generate_free_member_id (&random_id, member_store->members);
863
864 send_room_message(room, element->handle, create_message_id(&random_id));
865 }
866}
867
868void
869rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
870{
871 GNUNET_assert(room);
872
873 struct GNUNET_PeerIdentity peer;
874 size_t src;
875
876 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
877 (!find_list_tunnels (&(room->basement), &peer, &src)))
878 return;
879
880 size_t count = count_of_tunnels (&(room->basement));
881
882 struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head;
883 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
884
885 size_t dst = 0;
886
887 while (element)
888 {
889 GNUNET_PEER_resolve (element->peer, &peer);
890
891 tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer);
892
893 if (!tunnel)
894 {
895 element = remove_from_list_tunnels (&(room->basement), element);
896 continue;
897 }
898
899 if (GNUNET_YES == required_connection_between (count, src, dst))
900 {
901 if (GNUNET_SYSERR == connect_tunnel (tunnel))
902 {
903 element = remove_from_list_tunnels (&(room->basement), element);
904 continue;
905 }
906 }
907 else
908 disconnect_tunnel (tunnel);
909
910 element = element->next;
911 dst++;
912 }
913}
914
915static void
916handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
917{
918 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
919 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
920
921 while (room->handling.head)
922 {
923 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
924
925 const struct GNUNET_MESSENGER_Message *message = get_store_message (message_store, &(element->hash));
926
927 if (!message)
928 goto finish_handling;
929
930 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
931
932 if (!member)
933 goto finish_handling;
934
935 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(element->hash));
936
937 if (session)
938 handle_service_message (room->service, room, session, message, &(element->hash));
939
940finish_handling:
941 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
942 GNUNET_free(element);
943 }
944}
945
946int
947update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
948 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
949{
950 GNUNET_assert((room) && (message) && (hash));
951
952 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
953
954 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
955 GNUNET_YES : GNUNET_NO
956 );
957
958 if (GNUNET_YES == requested)
959 cancel_store_operation(operation_store, hash);
960
961 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
962
963 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (message_store, hash);
964
965 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
966
967 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash, message)))
968 {
969 if (old_message != message)
970 destroy_message(message);
971
972 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
973 return GNUNET_NO;
974 }
975
976 update_message_state(&(room->state), requested, message, hash);
977
978 if ((GNUNET_YES == requested) ||
979 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
980 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
981 return GNUNET_YES;
982
983 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
984 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->body.merge.previous))))
985 cancel_store_operation(operation_store, &(message->body.merge.previous));
986
987 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->header.previous)))
988 cancel_store_operation(operation_store, &(message->header.previous));
989
990 return GNUNET_YES;
991}
992
993struct GNUNET_MESSENGER_MemberSessionCompletion
994{
995 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
996 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
997
998 struct GNUNET_MESSENGER_MemberSession *session;
999};
1000
1001struct GNUNET_MESSENGER_MemberUpdate
1002{
1003 const struct GNUNET_MESSENGER_Message *message;
1004 const struct GNUNET_HashCode *hash;
1005
1006 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
1007 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
1008};
1009
1010static int
1011iterate_update_member_sessions (void *cls, const struct GNUNET_IDENTITY_PublicKey *public_key,
1012 struct GNUNET_MESSENGER_MemberSession *session)
1013{
1014 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
1015
1016 update_member_session_history(session, update->message, update->hash);
1017
1018 if (GNUNET_YES == is_member_session_completed(session))
1019 {
1020 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
1021 struct GNUNET_MESSENGER_MemberSessionCompletion
1022 );
1023
1024 element->session = session;
1025
1026 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
1027 }
1028
1029 return GNUNET_YES;
1030}
1031
1032static void
1033remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session);
1034
1035void
1036callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
1037 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
1038{
1039 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
1040 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
1041
1042 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
1043
1044 if (!member)
1045 {
1046 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
1047 return;
1048 }
1049
1050 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
1051
1052 if (!session)
1053 {
1054 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
1055 return;
1056 }
1057
1058 struct GNUNET_MESSENGER_MemberUpdate update;
1059 update.message = message;
1060 update.hash = hash;
1061
1062 update.head = NULL;
1063 update.tail = NULL;
1064
1065 iterate_store_members(member_store, iterate_update_member_sessions, &update);
1066
1067 while (update.head)
1068 {
1069 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
1070
1071 remove_room_member_session (room, element->session);
1072
1073 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
1074 GNUNET_free (element);
1075 }
1076
1077 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
1078
1079 add_to_list_messages (&(room->handling), hash);
1080
1081 switch (message->header.kind)
1082 {
1083 case GNUNET_MESSENGER_KIND_JOIN:
1084 handle_message_join (room, session, message, hash);
1085 break;
1086 case GNUNET_MESSENGER_KIND_LEAVE:
1087 handle_message_leave (room, session, message, hash);
1088 break;
1089 case GNUNET_MESSENGER_KIND_NAME:
1090 handle_message_name (room, session, message, hash);
1091 break;
1092 case GNUNET_MESSENGER_KIND_KEY:
1093 handle_message_key (room, session, message, hash);
1094 break;
1095 case GNUNET_MESSENGER_KIND_PEER:
1096 handle_message_peer (room, session, message, hash);
1097 break;
1098 case GNUNET_MESSENGER_KIND_ID:
1099 handle_message_id (room, session, message, hash);
1100 break;
1101 case GNUNET_MESSENGER_KIND_MISS:
1102 handle_message_miss (room, session, message, hash);
1103 break;
1104 case GNUNET_MESSENGER_KIND_DELETE:
1105 handle_message_delete (room, session, message, hash);
1106 break;
1107 default:
1108 break;
1109 }
1110
1111 if (GNUNET_YES == start_handle)
1112 handle_room_messages (room);
1113}
1114
1115static void
1116get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room, char **dir)
1117{
1118 GNUNET_assert((room) && (dir));
1119
1120 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_room_key(room)), DIR_SEPARATOR);
1121}
1122
1123void
1124load_room (struct GNUNET_MESSENGER_SrvRoom *room)
1125{
1126 GNUNET_assert(room);
1127
1128 char *room_dir;
1129 get_room_data_subdir (room, &room_dir);
1130
1131 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1132 {
1133 load_member_store (get_room_member_store(room), room_dir);
1134 load_message_store (get_room_message_store(room), room_dir);
1135 load_operation_store(get_room_operation_store(room), room_dir);
1136
1137 char *basement_file;
1138 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1139
1140 load_list_tunnels(&(room->basement), basement_file);
1141 GNUNET_free(basement_file);
1142
1143 char *last_messages_file;
1144 GNUNET_asprintf (&last_messages_file, "%s%s", room_dir, "last_messages.list");
1145
1146 load_message_state(&(room->state), room_dir);
1147 GNUNET_free (last_messages_file);
1148 }
1149
1150 GNUNET_free(room_dir);
1151}
1152
1153void
1154save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1155{
1156 GNUNET_assert(room);
1157
1158 char *room_dir;
1159 get_room_data_subdir (room, &room_dir);
1160
1161 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1162 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1163 {
1164 save_member_store(get_room_member_store(room), room_dir);
1165 save_message_store (get_room_message_store(room), room_dir);
1166 save_operation_store(get_room_operation_store(room), room_dir);
1167
1168 char *basement_file;
1169 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1170
1171 save_list_tunnels(&(room->basement), basement_file);
1172 GNUNET_free(basement_file);
1173
1174 save_message_state(&(room->state), room_dir);
1175 }
1176
1177 GNUNET_free(room_dir);
1178}
1179
1180static void
1181remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session)
1182{
1183 GNUNET_assert ((room) && (session));
1184
1185 remove_member_session (session->member, session);
1186
1187 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
1188
1189 struct GNUNET_HashCode hash;
1190 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
1191
1192 char *room_dir;
1193 get_room_data_subdir (room, &room_dir);
1194
1195 char* session_dir;
1196 GNUNET_asprintf (
1197 &session_dir, "%s%s%c%s%c%s%c%s%c", room_dir,
1198 "members", DIR_SEPARATOR,
1199 GNUNET_sh2s(get_member_session_id(session)), DIR_SEPARATOR,
1200 "sessions", DIR_SEPARATOR,
1201 GNUNET_h2s(&hash), DIR_SEPARATOR
1202 );
1203
1204 GNUNET_free (room_dir);
1205
1206 GNUNET_DISK_directory_remove(session_dir);
1207 GNUNET_free (session_dir);
1208
1209 destroy_member_session(session);
1210}
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
deleted file mode 100644
index 31ec877af..000000000
--- a/src/messenger/gnunet-service-messenger_room.h
+++ /dev/null
@@ -1,348 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_room.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_ROOM_H
27#define GNUNET_SERVICE_MESSENGER_ROOM_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_mq_lib.h"
35
36#include "gnunet_messenger_service.h"
37#include "gnunet-service-messenger_basement.h"
38#include "gnunet-service-messenger_handle.h"
39#include "gnunet-service-messenger_message_state.h"
40#include "gnunet-service-messenger_list_messages.h"
41
42#include "messenger_api_list_tunnels.h"
43
44#include "gnunet-service-messenger_member_store.h"
45#include "gnunet-service-messenger_message_store.h"
46#include "gnunet-service-messenger_operation_store.h"
47#include "messenger_api_ego.h"
48
49#define GNUNET_MESSENGER_IDLE_DELAY GNUNET_TIME_relative_multiply \
50 (GNUNET_TIME_relative_get_second_ (), 5)
51
52#define GNUNET_MESSENGER_REQUEST_DELAY GNUNET_TIME_relative_multiply \
53 (GNUNET_TIME_relative_get_minute_ (), 5)
54
55#define GNUNET_MESSENGER_MERGE_DELAY GNUNET_TIME_relative_multiply \
56 (GNUNET_TIME_relative_get_second_ (), 30)
57
58struct GNUNET_MESSENGER_SrvTunnel;
59struct GNUNET_MESSENGER_MemberSession;
60
61struct GNUNET_MESSENGER_SrvRoom
62{
63 struct GNUNET_MESSENGER_Service *service;
64 struct GNUNET_MESSENGER_SrvHandle *host;
65 struct GNUNET_CADET_Port *port;
66
67 struct GNUNET_HashCode key;
68
69 struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
70
71 struct GNUNET_MESSENGER_MemberStore member_store;
72 struct GNUNET_MESSENGER_MessageStore message_store;
73 struct GNUNET_MESSENGER_OperationStore operation_store;
74
75 struct GNUNET_MESSENGER_ListTunnels basement;
76 struct GNUNET_MESSENGER_MessageState state;
77
78 struct GNUNET_HashCode *peer_message;
79
80 struct GNUNET_MESSENGER_ListMessages handling;
81 struct GNUNET_SCHEDULER_Task *idle;
82};
83
84/**
85 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>.
86 *
87 * @param[in/out] handle Handle
88 * @param[in] key Key of room
89 * @return New room
90 */
91struct GNUNET_MESSENGER_SrvRoom*
92create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key);
93
94/**
95 * Destroys a room and frees its memory fully.
96 *
97 * @param[in/out] room Room
98 */
99void
100destroy_room (struct GNUNET_MESSENGER_SrvRoom *room);
101
102/**
103 * Returns the used member store of a given <i>room</i>.
104 *
105 * @param[in/out] room Room
106 * @return Member store
107 */
108struct GNUNET_MESSENGER_MemberStore*
109get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room);
110
111/**
112 * Returns the used message store of a given <i>room</i>.
113 *
114 * @param[in/out] room Room
115 * @return Message store
116 */
117struct GNUNET_MESSENGER_MessageStore*
118get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room);
119
120/**
121 * Returns the used operation store of a given <i>room</i>.
122 *
123 * @param[in/out] room Room
124 * @return Operation store
125 */
126struct GNUNET_MESSENGER_OperationStore*
127get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
128
129/**
130 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle
131 * will locally join the room.
132 *
133 * Calling this method should result in joining a room and sending a peer message as well for this peer.
134 *
135 * If the function returns #GNUNET_YES the port for this room is guaranteed to be open for incoming connections.
136 *
137 * @param[in/out] room Room
138 * @param[in/out] handle Handle
139 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
140 */
141int
142open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
143
144/**
145 * Connects a tunnel to a hosting peer of a <i>room</i> through a so called <i>door</i> which is represented by
146 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for
147 * an info message from the selected host.
148 *
149 * @param[in/out] room Room
150 * @param[in/out] handle Handle
151 * @param[in] door Peer identity
152 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
153 */
154int
155enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
156 const struct GNUNET_PeerIdentity *door);
157
158/**
159 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the
160 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message
161 * will be signed by the handles EGO.
162 *
163 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overridden by the signed messages hash.
164 *
165 * If <i>mode</i> is set to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send
166 * through a message queue, otherwise NULL.
167 *
168 * @param[in] room Room
169 * @param[in] handle Handle
170 * @param[in/out] message Message
171 * @param[out] hash Hash of message
172 * @param[in] mode Packing mode
173 * @return New envelope or NULL
174 */
175struct GNUNET_MQ_Envelope*
176pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_SrvHandle *handle,
177 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode);
178
179/**
180 * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i>. The <i>hash</i> parameter will be
181 * updated with the hash-value resulting from the sent message.
182 *
183 * The function handles packing the message automatically and will call linked message-events locally even if
184 * the message won't be sent to another peer.
185 *
186 * The function returns #GNUNET_YES on success, #GNUNET_NO if message is null and
187 * #GNUNET_SYSERR if the message was known already.
188 *
189 * @param[in/out] room Room
190 * @param[in/out] handle Handle
191 * @param[in/out] message Message
192 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
193 */
194int
195send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
196 struct GNUNET_MESSENGER_Message *message);
197
198/**
199 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>.
200 *
201 * @param[in/out] room Room
202 * @param[in/out] tunnel Tunnel
203 * @param[in/out] message Message
204 * @param[in] hash Hash of message
205 */
206void
207forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
208 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
209
210/**
211 * Checks the current state of opening a given <i>room</i> from this peer and re-publishes it
212 * if necessary to a selected <i>tunnel</i> or to all connected tunnels if necessary or if the
213 * selected tunnel is NULL.
214 *
215 * @param[in/out] room Room
216 * @param[in/out] tunnel Tunnel
217 */
218void
219check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel);
220
221/**
222 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message
223 * by merging them down. All merge messages will be sent from a given <i>handle</i>.
224 *
225 * @param[in/out] room Room
226 * @param[in/out] handle Handle
227 */
228void
229merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle);
230
231/**
232 * Deletes a message from the <i>room</i> with a given <i>hash</i> in a specific <i>delay</i> if
233 * the provided member by its session is permitted to do so.
234 *
235 * @param[in/out] room Room
236 * @param[in/out] session Member session
237 * @param[in] hash Hash of message
238 * @param[in] delay Delay of deletion
239 * @return #GNUNET_YES on success, #GNUNET_NO if permission gets denied, #GNUNET_SYSERR on operation failure
240 */
241int
242delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_MemberSession *session,
243 const struct GNUNET_HashCode *hash, const struct GNUNET_TIME_Relative delay);
244
245/**
246 * Returns the CADET handle from a rooms service.
247 *
248 * @param[in/out] room Room
249 * @return CADET handle
250 */
251struct GNUNET_CADET_Handle*
252get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room);
253
254/**
255 * Returns the shared secret you need to access a <i>room</i>.
256 *
257 * @param[in] room Room
258 * @return Shared secret
259 */
260const struct GNUNET_HashCode*
261get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room);
262
263/**
264 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists,
265 * otherwise NULL.
266 *
267 * @param[in] room Room
268 * @param[in] peer Peer identity
269 * @return Tunnel or NULL
270 */
271const struct GNUNET_MESSENGER_SrvTunnel*
272get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer);
273
274/**
275 * Method called whenever a <i>message</i> is found during a request in a <i>room</i>.
276 *
277 * @param[in/out] cls Closure from #request_room_message
278 * @param[in/out] room Room
279 * @param[in] message Message or NULL
280 * @param[in] hash Hash of message
281 */
282typedef void (GNUNET_MESSENGER_MessageRequestCallback) (
283 void *cls, struct GNUNET_MESSENGER_SrvRoom *room,
284 const struct GNUNET_MESSENGER_Message *message,
285 const struct GNUNET_HashCode *hash
286);
287
288/**
289 * Requests a message from a <i>room</i> identified by a given <i>hash</i>. If the message is found,
290 * the selected <i>callback</i> will be called with it and the provided closure. If no matching message
291 * is found but it wasn't deleted the selected callback will be called with #NULL as message instead.
292 * In case of deletion the next available previous message will be used to call the callback.
293 *
294 * It is also possible that the given callback will not be called if the requesting session is not
295 * permitted!
296 *
297 * @param[in/out] room Room
298 * @param[in] hash Hash of message
299 * @param[in] callback Callback to process result
300 * @param[in] cls Closure for the <i>callback</i>
301 * @return #GNUNET_YES if the request could be processed, otherwise #GNUNET_NO
302 */
303int
304request_room_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash,
305 const struct GNUNET_MESSENGER_MemberSession *session,
306 GNUNET_MESSENGER_MessageRequestCallback callback, void* cls);
307
308/**
309 * Checks for potential collisions with member ids and solves them changing active handles ids if they
310 * use an already used member id (comparing public key and timestamp).
311 *
312 * @param[in/out] room Room
313 * @param[in] public_key Public key of EGO
314 * @param[in] member_id Member ID
315 * @param[in] timestamp Timestamp
316 */
317void
318solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_IDENTITY_PublicKey *public_key,
319 const struct GNUNET_ShortHashCode *member_id, struct GNUNET_TIME_Absolute timestamp);
320
321/**
322 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
323 * depending on the amount of peers and this peers index in the list of them.
324 *
325 * @param[in/out] room Room
326 */
327void
328rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room);
329
330/**
331 * Loads the local configuration for a given <i>room</i> of a service which contains the last messages hash
332 * and the ruleset for general access of new members.
333 *
334 * @param[out] room Room
335 */
336void
337load_room (struct GNUNET_MESSENGER_SrvRoom *room);
338
339/**
340 * Saves the configuration for a given <i>room</i> of a service which contains the last messages hash
341 * and the ruleset for general access of new members locally.
342 *
343 * @param[in] room Room
344 */
345void
346save_room (struct GNUNET_MESSENGER_SrvRoom *room);
347
348#endif //GNUNET_SERVICE_MESSENGER_ROOM_H
diff --git a/src/messenger/gnunet-service-messenger_service.c b/src/messenger/gnunet-service-messenger_service.c
deleted file mode 100644
index 8c63e9bf4..000000000
--- a/src/messenger/gnunet-service-messenger_service.c
+++ /dev/null
@@ -1,306 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_service.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_service.h"
27#include "gnunet-service-messenger_message_kind.h"
28#include "gnunet-service-messenger.h"
29
30static void
31callback_shutdown_service (void *cls)
32{
33 struct GNUNET_MESSENGER_Service *service = cls;
34
35 if (service)
36 {
37 service->shutdown = NULL;
38
39 destroy_service (service);
40 }
41}
42
43struct GNUNET_MESSENGER_Service*
44create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle)
45{
46 GNUNET_assert((config) && (service_handle));
47
48 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service);
49
50 service->config = config;
51 service->service = service_handle;
52
53 service->shutdown = GNUNET_SCHEDULER_add_shutdown (&callback_shutdown_service, service);
54
55 service->dir = NULL;
56
57 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config,
58 GNUNET_MESSENGER_SERVICE_NAME,
59 "MESSENGER_DIR", &(service->dir)))
60 {
61 if (service->dir)
62 GNUNET_free(service->dir);
63
64 service->dir = NULL;
65 }
66 else
67 {
68 if ((GNUNET_YES != GNUNET_DISK_directory_test (service->dir, GNUNET_YES)) && (GNUNET_OK
69 != GNUNET_DISK_directory_create (service->dir)))
70 {
71 GNUNET_free(service->dir);
72
73 service->dir = NULL;
74 }
75 }
76
77 service->cadet = GNUNET_CADET_connect (service->config);
78
79 init_ego_store(get_service_ego_store(service), service->config);
80
81 init_list_handles (&(service->handles));
82
83 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
84
85 init_contact_store(get_service_contact_store(service));
86
87 return service;
88}
89
90static int
91iterate_destroy_rooms (void *cls, const struct GNUNET_HashCode *key, void *value)
92{
93 struct GNUNET_MESSENGER_SrvRoom *room = value;
94 destroy_room (room);
95 return GNUNET_YES;
96}
97
98void
99destroy_service (struct GNUNET_MESSENGER_Service *service)
100{
101 GNUNET_assert(service);
102
103 if (service->shutdown)
104 {
105 GNUNET_SCHEDULER_cancel (service->shutdown);
106
107 service->shutdown = NULL;
108 }
109
110 clear_ego_store(get_service_ego_store(service));
111 clear_list_handles (&(service->handles));
112
113 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL);
114 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
115
116 clear_contact_store(get_service_contact_store(service));
117
118 if (service->cadet)
119 {
120 GNUNET_CADET_disconnect (service->cadet);
121
122 service->cadet = NULL;
123 }
124
125 if (service->dir)
126 {
127 GNUNET_free(service->dir);
128
129 service->dir = NULL;
130 }
131
132 GNUNET_SERVICE_shutdown (service->service);
133
134 GNUNET_free(service);
135}
136
137struct GNUNET_MESSENGER_EgoStore*
138get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
139{
140 GNUNET_assert(service);
141
142 return &(service->ego_store);
143}
144
145struct GNUNET_MESSENGER_ContactStore*
146get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
147{
148 GNUNET_assert(service);
149
150 return &(service->contact_store);
151}
152
153struct GNUNET_MESSENGER_SrvHandle*
154add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq)
155{
156 GNUNET_assert((service) && (mq));
157
158 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq);
159
160 if (handle)
161 {
162 add_list_handle (&(service->handles), handle);
163 }
164
165 return handle;
166}
167
168void
169remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle)
170{
171 GNUNET_assert((service) && (handle));
172
173 if (!handle)
174 return;
175
176 if (GNUNET_YES == remove_list_handle (&(service->handles), handle))
177 destroy_handle (handle);
178}
179
180int
181get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer)
182{
183 GNUNET_assert((service) && (peer));
184
185 return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
186}
187
188struct GNUNET_MESSENGER_SrvRoom*
189get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key)
190{
191 GNUNET_assert((service) && (key));
192
193 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
194}
195
196int
197open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
198 const struct GNUNET_HashCode *key)
199{
200 GNUNET_assert((service) && (handle) && (key));
201
202 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
203
204 if (room)
205 return open_room (room, handle);
206
207 room = create_room (handle, key);
208
209 if ((GNUNET_YES == open_room (room, handle)) &&
210 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
211 key, room,
212 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
213 return GNUNET_YES;
214
215 destroy_room (room);
216 return GNUNET_NO;
217}
218
219int
220entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
221 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key)
222{
223 GNUNET_assert((service) && (handle) && (door) && (key));
224
225 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
226
227 if (room)
228 {
229 if (GNUNET_YES == enter_room_at (room, handle, door))
230 return GNUNET_YES;
231 else
232 return GNUNET_NO;
233 }
234
235 room = create_room (handle, key);
236
237 if ((GNUNET_YES == enter_room_at (room, handle, door)) &&
238 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
239 key, room,
240 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
241 {
242 return GNUNET_YES;
243 }
244 else
245 {
246 destroy_room (room);
247 return GNUNET_NO;
248 }
249
250}
251
252int
253close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
254 const struct GNUNET_HashCode *key)
255{
256 GNUNET_assert((service) && (handle) && (key));
257
258 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
259
260 if (!room)
261 return GNUNET_NO;
262
263 send_room_message (room, handle, create_message_leave ());
264
265 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
266
267 GNUNET_assert(id);
268
269 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (handle->member_ids, key, id))
270 return GNUNET_NO;
271
272 struct GNUNET_MESSENGER_SrvHandle *member_handle = (struct GNUNET_MESSENGER_SrvHandle*) find_list_handle_by_member (
273 &(service->handles), key);
274
275 if (!member_handle)
276 {
277 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room))
278 {
279 destroy_room (room);
280 return GNUNET_YES;
281 }
282 else
283 return GNUNET_NO;
284 }
285
286 if (room->host == handle)
287 room->host = member_handle;
288
289 return GNUNET_YES;
290}
291
292void
293handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
294 const struct GNUNET_MESSENGER_MemberSession *session,
295 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
296{
297 GNUNET_assert((service) && (room) && (session) && (message) && (hash));
298
299 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
300
301 while (element)
302 {
303 notify_handle_message (element->handle, get_room_key(room), session, message, hash);
304 element = element->next;
305 }
306}
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h
deleted file mode 100644
index aa43fa457..000000000
--- a/src/messenger/gnunet-service-messenger_service.h
+++ /dev/null
@@ -1,201 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_service.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_SERVICE_H
27#define GNUNET_SERVICE_MESSENGER_SERVICE_H
28
29#include "platform.h"
30#include "gnunet_configuration_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_container_lib.h"
33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h"
35
36#include "gnunet-service-messenger_ego_store.h"
37#include "gnunet-service-messenger_list_handles.h"
38
39#include "messenger_api_contact_store.h"
40#include "gnunet-service-messenger_room.h"
41
42#include "gnunet-service-messenger_member_session.h"
43
44struct GNUNET_MESSENGER_Service
45{
46 const struct GNUNET_CONFIGURATION_Handle *config;
47 struct GNUNET_SERVICE_Handle *service;
48
49 struct GNUNET_SCHEDULER_Task *shutdown;
50
51 char *dir;
52
53 struct GNUNET_CADET_Handle *cadet;
54
55 struct GNUNET_MESSENGER_EgoStore ego_store;
56 struct GNUNET_MESSENGER_ContactStore contact_store;
57
58 struct GNUNET_MESSENGER_ListHandles handles;
59
60 struct GNUNET_CONTAINER_MultiHashMap *rooms;
61};
62
63/**
64 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle.
65 *
66 * @param[in] config Configuration
67 * @param[in/out] service_handle GNUnet service handle
68 * @return New service
69 */
70struct GNUNET_MESSENGER_Service*
71create_service (const struct GNUNET_CONFIGURATION_Handle *config, struct GNUNET_SERVICE_Handle *service_handle);
72
73/**
74 * Destroys a <i>service</i> and frees its memory fully.
75 *
76 * @param[in/out] service Service
77 */
78void
79destroy_service (struct GNUNET_MESSENGER_Service *service);
80
81/**
82 * Returns the used EGO-store of a given <i>service</i>.
83 *
84 * @param[in/out] service Service
85 * @return EGO-store
86 */
87struct GNUNET_MESSENGER_EgoStore*
88get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
89
90/**
91 * Returns the used contact store of a given <i>service</i>.
92 *
93 * @param[in/out] service Service
94 * @return Contact store
95 */
96struct GNUNET_MESSENGER_ContactStore*
97get_service_contact_store (struct GNUNET_MESSENGER_Service *service);
98
99/**
100 * Creates and adds a new handle to a <i>service</i> using a given message queue.
101 *
102 * @param[in/out] service Service
103 * @param[in/out] mq Message queue
104 * @return New handle
105 */
106struct GNUNET_MESSENGER_SrvHandle*
107add_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MQ_Handle *mq);
108
109/**
110 * Removes a <i>handle</i> from a <i>service</i> and destroys it.
111 *
112 * @param[in/out] service Service
113 * @param[in/out] handle Handle
114 */
115void
116remove_service_handle (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle);
117
118/**
119 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i>
120 * parameter. The functions returns #GNUNET_OK on success, otherwise #GNUNET_SYSERR.
121 *
122 * @param[in] service Service
123 * @param[out] peer Peer identity
124 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
125 */
126int
127get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service, struct GNUNET_PeerIdentity *peer);
128
129/**
130 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room
131 * using the given key, NULL gets returned.
132 *
133 * @param[in] service Service
134 * @param[in] key Key of room
135 * @return Room or NULL
136 */
137struct GNUNET_MESSENGER_SrvRoom*
138get_service_room (const struct GNUNET_MESSENGER_Service *service, const struct GNUNET_HashCode *key);
139
140/**
141 * Tries to open a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will be
142 * created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
143 *
144 * @param[in/out] service Service
145 * @param[in/out] handle Handle
146 * @param[in] key Key of room
147 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
148 */
149int
150open_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
151 const struct GNUNET_HashCode *key);
152
153/**
154 * Tries to enter a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
155 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
156 *
157 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and
158 * a new connection will be made.
159 *
160 * @param[in/out] service Service
161 * @param[in/out] handle Handle
162 * @param[in] door Peer identity
163 * @param[in] key Key of room
164 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
165 */
166int
167entry_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
168 const struct GNUNET_PeerIdentity *door, const struct GNUNET_HashCode *key);
169
170/**
171 * Tries to close a room using a given <i>key</i> for a <i>service</i> by a specific <i>handle</i>. The room will
172 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
173 *
174 * If the specific handle is currently the host of the room for this service, a new handle which is a member will
175 * take its place. Otherwise the room will be destroyed for this service.
176 *
177 * @param[in/out] service Service
178 * @param[in/out] handle Handle
179 * @param[in] key Key of room
180 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
181 */
182int
183close_service_room (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvHandle *handle,
184 const struct GNUNET_HashCode *key);
185
186/**
187 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which
188 * is currently member of a specific <i>room</i> for handling it in the client API.
189 *
190 * @param[in/out] service Service
191 * @param[in/out] room Room
192 * @param[in] session Member session
193 * @param[in] message Message
194 * @param[in] hash Hash of message
195 */
196void
197handle_service_message (struct GNUNET_MESSENGER_Service *service, struct GNUNET_MESSENGER_SrvRoom *room,
198 const struct GNUNET_MESSENGER_MemberSession *session,
199 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
200
201#endif //GNUNET_SERVICE_MESSENGER_SERVICE_H
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c b/src/messenger/gnunet-service-messenger_tunnel.c
deleted file mode 100644
index b9d063813..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ /dev/null
@@ -1,383 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_tunnel.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_tunnel.h"
27
28#include "gnunet-service-messenger_handle.h"
29#include "gnunet-service-messenger_message_recv.h"
30#include "gnunet-service-messenger_message_store.h"
31#include "gnunet-service-messenger_operation_store.h"
32#include "gnunet-service-messenger_operation.h"
33#include "messenger_api_util.h"
34
35struct GNUNET_MESSENGER_SrvTunnel*
36create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door)
37{
38 GNUNET_assert((room) && (door));
39
40 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new(struct GNUNET_MESSENGER_SrvTunnel);
41
42 tunnel->room = room;
43 tunnel->channel = NULL;
44
45 tunnel->peer = GNUNET_PEER_intern (door);
46
47 tunnel->messenger_version = 0;
48
49 tunnel->peer_message = NULL;
50
51 init_message_state(&(tunnel->state));
52
53 return tunnel;
54}
55
56void
57destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
58{
59 GNUNET_assert(tunnel);
60
61 if (tunnel->channel)
62 GNUNET_CADET_channel_destroy (tunnel->channel);
63
64 GNUNET_PEER_change_rc (tunnel->peer, -1);
65
66 if (tunnel->peer_message)
67 GNUNET_free(tunnel->peer_message);
68
69 clear_message_state(&(tunnel->state));
70
71 GNUNET_free(tunnel);
72}
73
74void
75bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel)
76{
77 GNUNET_assert(tunnel);
78
79 if (tunnel->channel)
80 delayed_disconnect_channel (tunnel->channel);
81
82 tunnel->channel = channel;
83}
84
85extern void
86callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls);
87
88void
89callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel)
90{
91 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
92
93 if (tunnel)
94 {
95 tunnel->channel = NULL;
96
97 callback_room_disconnect (tunnel->room, cls);
98 }
99}
100
101extern int
102callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
103 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash);
104
105int
106check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
107{
108 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
109
110 if (!tunnel)
111 return GNUNET_SYSERR;
112
113 const uint16_t length = ntohs (header->size) - sizeof(*header);
114 const char *buffer = (const char*) &header[1];
115
116 struct GNUNET_MESSENGER_Message message;
117
118 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
119 {
120 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Message too short! (%d)\n", length);
121 return GNUNET_SYSERR;
122 }
123
124 uint16_t padding = 0;
125
126 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, &padding))
127 {
128 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
129 return GNUNET_SYSERR;
130 }
131
132 struct GNUNET_HashCode hash;
133 hash_message (&message, length - padding, buffer, &hash);
134
135 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
136}
137
138extern int
139update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
140 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
141
142extern void
143callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
144 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
145
146static void
147update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_HashCode *hash)
148{
149 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(tunnel->room);
150
151 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
152 GNUNET_YES : GNUNET_NO
153 );
154
155 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(tunnel->room);
156
157 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
158
159 if (message)
160 update_message_state(&(tunnel->state), requested, message, hash);
161}
162
163void
164handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
165{
166 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
167
168 const uint16_t length = ntohs (header->size) - sizeof(*header);
169 const char *buffer = (const char*) &header[1];
170
171 struct GNUNET_MESSENGER_Message message;
172 struct GNUNET_HashCode hash;
173
174 uint16_t padding = 0;
175
176 decode_message (&message, length, buffer, GNUNET_YES, &padding);
177 hash_message (&message, length - padding, buffer, &hash);
178
179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
180 GNUNET_MESSENGER_name_of_kind(message.header.kind));
181
182 if (!tunnel)
183 return;
184
185 const int new_message = update_room_message (
186 tunnel->room, copy_message (&message), &hash
187 );
188
189 if (GNUNET_YES != new_message)
190 goto receive_done;
191
192 update_tunnel_last_message (tunnel, &hash);
193
194 int forward_message = GNUNET_YES;
195
196 switch (message.header.kind)
197 {
198 case GNUNET_MESSENGER_KIND_INFO:
199 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
200 break;
201 case GNUNET_MESSENGER_KIND_PEER:
202 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
203 break;
204 case GNUNET_MESSENGER_KIND_REQUEST:
205 forward_message = recv_message_request (tunnel->room, tunnel, &message, &hash);
206 break;
207 default:
208 break;
209 }
210
211 if (GNUNET_YES == forward_message)
212 {
213 forward_room_message (tunnel->room, tunnel, &message, &hash);
214 callback_room_handle_message (tunnel->room, NULL, &message, &hash);
215 }
216
217receive_done:
218 GNUNET_CADET_receive_done (tunnel->channel);
219}
220
221int
222connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
223{
224 GNUNET_assert(tunnel);
225
226 if (tunnel->channel)
227 return GNUNET_NO;
228
229 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
230
231 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room);
232 const struct GNUNET_HashCode *key = get_room_key (tunnel->room);
233
234 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
235 struct GNUNET_MessageHeader, NULL),
236 GNUNET_MQ_handler_end() };
237
238 struct GNUNET_HashCode port;
239 convert_messenger_key_to_port(key, &port);
240 tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, &port, NULL, callback_tunnel_disconnect, handlers);
241
242 return GNUNET_YES;
243}
244
245void
246disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
247{
248 GNUNET_assert(tunnel);
249
250 if (tunnel->channel)
251 {
252 delayed_disconnect_channel (tunnel->channel);
253
254 tunnel->channel = NULL;
255 }
256}
257
258int
259is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
260{
261 GNUNET_assert(tunnel);
262
263 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
264}
265
266struct GNUNET_MESSENGER_MessageSent
267{
268 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
269 struct GNUNET_HashCode hash;
270};
271
272static void
273callback_tunnel_sent (void *cls)
274{
275 struct GNUNET_MESSENGER_MessageSent *sent = cls;
276
277 if (sent->tunnel)
278 update_tunnel_last_message (sent->tunnel, &(sent->hash));
279
280 GNUNET_free(sent);
281}
282
283void
284send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
285 const struct GNUNET_HashCode *hash)
286{
287 GNUNET_assert((tunnel) && (env) && (hash));
288
289 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
290
291 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
292
293 GNUNET_memcpy(&(sent->hash), hash, sizeof(struct GNUNET_HashCode));
294
295 sent->tunnel = tunnel;
296
297 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
298 GNUNET_MQ_send (mq, env);
299}
300
301int
302send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message)
303{
304 GNUNET_assert((tunnel) && (handle));
305
306 if (!message)
307 return GNUNET_NO;
308
309 struct GNUNET_HashCode hash;
310 struct GNUNET_MQ_Envelope *env = pack_room_message (
311 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
312 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
313 );
314
315 destroy_message(message);
316
317 if (!env)
318 return GNUNET_NO;
319
320 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
321 GNUNET_h2s(&hash));
322
323 send_tunnel_envelope (tunnel, env, &hash);
324 return GNUNET_YES;
325}
326
327void
328forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
329 const struct GNUNET_HashCode *hash)
330{
331 GNUNET_assert((tunnel) && (message) && (hash));
332
333 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
334 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
335
336 destroy_message(copy);
337
338 if (!env)
339 return;
340
341 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
342 GNUNET_h2s(hash));
343
344 send_tunnel_envelope (tunnel, env, hash);
345}
346
347const struct GNUNET_HashCode*
348get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
349{
350 GNUNET_assert(tunnel);
351
352 return tunnel->peer_message;
353}
354
355void
356get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer)
357{
358 GNUNET_assert(tunnel);
359
360 GNUNET_PEER_resolve(tunnel->peer, peer);
361}
362
363uint32_t
364get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
365{
366 GNUNET_assert(tunnel);
367
368 return tunnel->messenger_version;
369}
370
371int
372update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version)
373{
374 GNUNET_assert(tunnel);
375
376 if (version != GNUNET_MESSENGER_VERSION)
377 return GNUNET_SYSERR;
378
379 if (version > tunnel->messenger_version)
380 tunnel->messenger_version = version;
381
382 return GNUNET_OK;
383}
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
deleted file mode 100644
index 96d98546d..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ /dev/null
@@ -1,186 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/gnunet-service-messenger_tunnel.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_TUNNEL_H
27#define GNUNET_SERVICE_MESSENGER_TUNNEL_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_peer_lib.h"
32#include "gnunet_crypto_lib.h"
33
34#include "gnunet-service-messenger_room.h"
35#include "gnunet-service-messenger_message_state.h"
36
37struct GNUNET_MESSENGER_SrvTunnel
38{
39 struct GNUNET_MESSENGER_SrvRoom *room;
40 struct GNUNET_CADET_Channel *channel;
41
42 GNUNET_PEER_Id peer;
43
44 uint32_t messenger_version;
45
46 struct GNUNET_HashCode *peer_message;
47 struct GNUNET_MESSENGER_MessageState state;
48};
49
50/**
51 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity (called <i>door</i>).
52 *
53 * @param[in/out] room Room
54 * @param[in] door Peer identity
55 * @return New tunnel
56 */
57struct GNUNET_MESSENGER_SrvTunnel*
58create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *door);
59
60/**
61 * Destroys a <i>tunnel</i> and frees its memory fully.
62 *
63 * @param[in/out] tunnel
64 */
65void
66destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
67
68/**
69 * Binds a CADET <i>channel</i> to a <i>tunnel</i> and replaces its channel
70 * the tunnel is currently bound to if necessary.
71 *
72 * @param[in/out] tunnel Tunnel
73 * @param[in/out] channel CADET channel
74 */
75void
76bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_CADET_Channel *channel);
77
78/**
79 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it.
80 * The function returns #GNUNET_YES on success, otherwise #GNUNET_NO.
81 *
82 * @param[in/out] tunnel Tunnel
83 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
84 */
85int
86connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
87
88/**
89 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection
90 * will be asynchronous.
91 *
92 * @param[in/out] tunnel Tunnel
93 */
94void
95disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
96
97/**
98 * Returns the status of a currently bound channel of a <i>tunnel</i>.
99 *
100 * @param[in] tunnel Tunnel
101 * @return #GNUNET_YES or #GNUNET_NO
102 */
103int
104is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
105
106/**
107 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through
108 * a <i>tunnel</i>.
109 *
110 * @param[in/out] tunnel Tunnel
111 * @param[in/out] env Envelope
112 * @param[in] hash Hash of message
113 */
114void
115send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_MQ_Envelope *env,
116 const struct GNUNET_HashCode *hash);
117
118/**
119 * Sends a <i>message</i> by packing it automatically into an envelope and passing it
120 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and
121 * the <i>hash</i> will be calculated and stored.
122 *
123 * @param[in/out] tunnel Tunnel
124 * @param[in/out] handle Handle
125 * @param[in/out] message Message
126 * @return #GNUNET_YES on success, GNUNET_NO otherwise
127 */
128int
129send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, void *handle, struct GNUNET_MESSENGER_Message *message);
130
131/**
132 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>.
133 *
134 * @param[in/out] tunnel Tunnel
135 * @param[in] message Message
136 * @param[in] hash Hash of message
137 */
138void
139forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel, const struct GNUNET_MESSENGER_Message *message,
140 const struct GNUNET_HashCode *hash);
141
142/**
143 * Returns the hash of the latest peer message published through a given <i>tunnel</i>
144 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel
145 * yet, NULL gets returned.
146 *
147 * @param[in] tunnel Tunnel
148 * @return Hash of peer message or NULL
149 */
150const struct GNUNET_HashCode*
151get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
152
153/**
154 * Writes the peer identity of the peer connected via <i>tunnel</i> to this peer into
155 * the <i>peer</i> parameter.
156 *
157 * @param[in] tunnel Tunnel
158 * @param[out] peer Peer identity
159 */
160void
161get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel, struct GNUNET_PeerIdentity *peer);
162
163/**
164 * Returns the current messenger version the peer connected via a given <i>tunnel</i>
165 * has reported to be using if it was compatible during updating.
166 *
167 * @see update_tunnel_messenger_version
168 *
169 * @param[in] tunnel Tunnel
170 * @return Version of messenger
171 */
172uint32_t
173get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
174
175/**
176 * Updates the messenger version of the <i>tunnel</i> to a given <i>version</i> if
177 * it is compatible to the running peer of the service. Depending on success it
178 * returns #GNUNET_OK or #GNUNET_SYSERR on failure.
179 *
180 * @param[in/out] tunnel Tunnel
181 * @param[in] version Version of messenger
182 */
183int
184update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel, uint32_t version);
185
186#endif //GNUNET_SERVICE_MESSENGER_TUNNEL_H
diff --git a/src/messenger/messenger.conf.in b/src/messenger/messenger.conf.in
deleted file mode 100644
index 59e11b166..000000000
--- a/src/messenger/messenger.conf.in
+++ /dev/null
@@ -1,13 +0,0 @@
1[messenger]
2START_ON_DEMAND = YES
3PORT = 2097
4HOSTNAME = localhost
5BINARY = gnunet-service-messenger
6ACCEPT_FROM = 127.0.0.1;
7ACCEPT_FROM6 = ::1;
8UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-messenger.sock
9UNIX_MATCH_UID = NO
10UNIX_MATCH_GID = YES
11
12# Directory to store messages and contacts
13MESSENGER_DIR = $GNUNET_DATA_HOME/messenger/ \ No newline at end of file
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
deleted file mode 100644
index f7c73f769..000000000
--- a/src/messenger/messenger_api.c
+++ /dev/null
@@ -1,755 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "gnunet_messenger_service.h"
27
28#include "gnunet-service-messenger.h"
29
30#include "messenger_api_handle.h"
31#include "messenger_api_message.h"
32#include "messenger_api_util.h"
33
34const char*
35GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
36{
37 switch (kind)
38 {
39 case GNUNET_MESSENGER_KIND_INFO:
40 return "INFO";
41 case GNUNET_MESSENGER_KIND_JOIN:
42 return "JOIN";
43 case GNUNET_MESSENGER_KIND_LEAVE:
44 return "LEAVE";
45 case GNUNET_MESSENGER_KIND_NAME:
46 return "NAME";
47 case GNUNET_MESSENGER_KIND_KEY:
48 return "KEY";
49 case GNUNET_MESSENGER_KIND_PEER:
50 return "PEER";
51 case GNUNET_MESSENGER_KIND_ID:
52 return "ID";
53 case GNUNET_MESSENGER_KIND_MISS:
54 return "MISS";
55 case GNUNET_MESSENGER_KIND_MERGE:
56 return "MERGE";
57 case GNUNET_MESSENGER_KIND_REQUEST:
58 return "REQUEST";
59 case GNUNET_MESSENGER_KIND_INVITE:
60 return "INVITE";
61 case GNUNET_MESSENGER_KIND_TEXT:
62 return "TEXT";
63 case GNUNET_MESSENGER_KIND_FILE:
64 return "FILE";
65 case GNUNET_MESSENGER_KIND_PRIVATE:
66 return "PRIVATE";
67 default:
68 return "UNKNOWN";
69 }
70}
71
72static int
73check_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
74{
75 GNUNET_MQ_check_zero_termination(msg);
76 return GNUNET_OK;
77}
78
79static void
80handle_get_name (void *cls, const struct GNUNET_MESSENGER_NameMessage *msg)
81{
82 struct GNUNET_MESSENGER_Handle *handle = cls;
83
84 const char *name = ((const char*) msg) + sizeof(*msg);
85
86 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
87
88 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
89}
90
91static int
92check_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
93{
94 const uint16_t full_length = ntohs (msg->header.size);
95
96 if (full_length < sizeof(*msg))
97 return GNUNET_NO;
98
99 const uint16_t length = full_length - sizeof(*msg);
100 const char *buffer = ((const char*) msg) + sizeof(*msg);
101
102 struct GNUNET_IDENTITY_PublicKey pubkey;
103 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
104 return GNUNET_NO;
105
106 return GNUNET_OK;
107}
108
109static void
110handle_get_key (void *cls, const struct GNUNET_MESSENGER_KeyMessage *msg)
111{
112 struct GNUNET_MESSENGER_Handle *handle = cls;
113
114 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
115 const char *buffer = ((const char*) msg) + sizeof(*msg);
116
117 struct GNUNET_IDENTITY_PublicKey pubkey;
118 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
119 return;
120
121 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
122 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
123 GNUNET_free(str);
124
125 set_handle_key (handle, &pubkey);
126
127 if (handle->identity_callback)
128 handle->identity_callback (handle->identity_cls, handle);
129}
130
131static void
132handle_member_id (void *cls, const struct GNUNET_MESSENGER_MemberMessage *msg)
133{
134 struct GNUNET_MESSENGER_Handle *handle = cls;
135
136 const struct GNUNET_HashCode *key = &(msg->key);
137 const struct GNUNET_ShortHashCode *id = &(msg->id);
138
139 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key));
140
141 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
142
143 if (room)
144 {
145 if (!room->contact_id)
146 room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
147
148 GNUNET_memcpy(room->contact_id, id, sizeof(*id));
149 }
150}
151
152static void
153handle_room_open (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
154{
155 struct GNUNET_MESSENGER_Handle *handle = cls;
156
157 const struct GNUNET_HashCode *key = &(msg->key);
158
159 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
160
161 open_handle_room (handle, key);
162}
163
164static void
165handle_room_entry (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
166{
167 struct GNUNET_MESSENGER_Handle *handle = cls;
168
169 const struct GNUNET_PeerIdentity *door = &(msg->door);
170 const struct GNUNET_HashCode *key = &(msg->key);
171
172 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
173
174 entry_handle_room_at (handle, door, key);
175}
176
177static void
178handle_room_close (void *cls, const struct GNUNET_MESSENGER_RoomMessage *msg)
179{
180 struct GNUNET_MESSENGER_Handle *handle = cls;
181
182 const struct GNUNET_HashCode *key = &(msg->key);
183
184 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
185
186 close_handle_room (handle, key);
187}
188
189static int
190check_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
191{
192 const uint16_t full_length = ntohs (msg->header.size);
193
194 if (full_length < sizeof(*msg))
195 return GNUNET_NO;
196
197 const uint16_t length = full_length - sizeof(*msg);
198 const char *buffer = ((const char*) msg) + sizeof(*msg);
199
200 struct GNUNET_MESSENGER_Message message;
201
202 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN))
203 return GNUNET_NO;
204
205 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
206 return GNUNET_NO;
207
208 return GNUNET_OK;
209}
210
211static void
212handle_recv_message (void *cls, const struct GNUNET_MESSENGER_RecvMessage *msg)
213{
214 struct GNUNET_MESSENGER_Handle *handle = cls;
215
216 const struct GNUNET_HashCode *key = &(msg->key);
217 const struct GNUNET_HashCode *sender = &(msg->sender);
218 const struct GNUNET_HashCode *context = &(msg->context);
219 const struct GNUNET_HashCode *hash = &(msg->hash);
220 const enum GNUNET_MESSENGER_MessageFlags flags = (
221 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
222 );
223
224 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
225 const char *buffer = ((const char*) msg) + sizeof(*msg);
226
227 struct GNUNET_MESSENGER_Message message;
228 decode_message (&message, length, buffer, GNUNET_YES, NULL);
229
230 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
231
232 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
233
234 if (room)
235 {
236 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
237
238 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
239 GNUNET_h2s(sender), GNUNET_h2s_full(context));
240
241 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
242 store, context, sender
243 );
244
245 handle_room_message (room, contact, &message, hash);
246
247 if (handle->msg_callback)
248 handle->msg_callback (handle->msg_cls, room, contact, &message, hash, flags);
249 }
250 else
251 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found\n");
252}
253
254static void
255reconnect (struct GNUNET_MESSENGER_Handle *handle);
256
257static void
258send_open_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room)
259{
260 struct GNUNET_MESSENGER_RoomMessage *msg;
261 struct GNUNET_MQ_Envelope *env;
262
263 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
264 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
265 GNUNET_MQ_send (handle->mq, env);
266}
267
268static void
269send_enter_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room,
270 const struct GNUNET_PeerIdentity *door)
271{
272 struct GNUNET_MESSENGER_RoomMessage *msg;
273 struct GNUNET_MQ_Envelope *env;
274
275 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
276 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
277 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
278 GNUNET_MQ_send (handle->mq, env);
279}
280
281static void
282send_close_room (struct GNUNET_MESSENGER_Handle *handle, struct GNUNET_MESSENGER_Room *room)
283{
284 struct GNUNET_MESSENGER_RoomMessage *msg;
285 struct GNUNET_MQ_Envelope *env;
286
287 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
288 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
289 GNUNET_MQ_send (handle->mq, env);
290}
291
292static int
293iterate_reset_room (void *cls, const struct GNUNET_HashCode *key, void *value)
294{
295 struct GNUNET_MESSENGER_Handle *handle = cls;
296 struct GNUNET_MESSENGER_Room *room = value;
297
298 if (GNUNET_YES == room->opened)
299 send_open_room (handle, room);
300
301 struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
302
303 struct GNUNET_PeerIdentity door;
304
305 while (entry)
306 {
307 GNUNET_PEER_resolve (entry->peer, &door);
308
309 send_enter_room (handle, room, &door);
310
311 entry = entry->next;
312 }
313
314 return GNUNET_YES;
315}
316
317static void
318callback_reconnect (void *cls)
319{
320 struct GNUNET_MESSENGER_Handle *handle = cls;
321
322 handle->reconnect_task = NULL;
323 handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
324 ;
325
326 reconnect (handle);
327
328 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle);
329}
330
331static int
332iterate_close_room (void *cls, const struct GNUNET_HashCode *key, void *value)
333{
334 struct GNUNET_MESSENGER_Handle *handle = cls;
335 struct GNUNET_MESSENGER_Room *room = value;
336
337 send_close_room (handle, room);
338
339 return GNUNET_YES;
340}
341
342static void
343callback_mq_error (void *cls, enum GNUNET_MQ_Error error)
344{
345 struct GNUNET_MESSENGER_Handle *handle = cls;
346
347 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
348
349 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
350
351 if (handle->mq)
352 {
353 GNUNET_MQ_destroy (handle->mq);
354 handle->mq = NULL;
355 }
356
357 handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle);
358}
359
360static void
361reconnect (struct GNUNET_MESSENGER_Handle *handle)
362{
363 const struct GNUNET_MQ_MessageHandler handlers[] =
364 {
365 GNUNET_MQ_hd_var_size(
366 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
367 struct GNUNET_MESSENGER_NameMessage, handle
368 ),
369 GNUNET_MQ_hd_var_size(
370 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
371 struct GNUNET_MESSENGER_KeyMessage, handle
372 ),
373 GNUNET_MQ_hd_fixed_size(
374 member_id,
375 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
376 struct GNUNET_MESSENGER_MemberMessage, handle
377 ),
378 GNUNET_MQ_hd_fixed_size(
379 room_open,
380 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
381 struct GNUNET_MESSENGER_RoomMessage, handle
382 ),
383 GNUNET_MQ_hd_fixed_size(
384 room_entry,
385 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
386 struct GNUNET_MESSENGER_RoomMessage, handle
387 ),
388 GNUNET_MQ_hd_fixed_size(
389 room_close,
390 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
391 struct GNUNET_MESSENGER_RoomMessage, handle
392 ),
393 GNUNET_MQ_hd_var_size(
394 recv_message,
395 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
396 struct GNUNET_MESSENGER_RecvMessage, handle
397 ),
398 GNUNET_MQ_handler_end()
399 };
400
401 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
402}
403
404struct GNUNET_MESSENGER_Handle*
405GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, const char *name,
406 GNUNET_MESSENGER_IdentityCallback identity_callback, void *identity_cls,
407 GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls)
408{
409 struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls);
410
411 reconnect (handle);
412
413 if (handle->mq)
414 {
415 const uint16_t name_len = name ? strlen (name) : 0;
416
417 struct GNUNET_MESSENGER_CreateMessage *msg;
418 struct GNUNET_MQ_Envelope *env;
419
420 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
421
422 char *extra = ((char*) msg) + sizeof(*msg);
423
424 if (name_len)
425 GNUNET_memcpy(extra, name, name_len);
426
427 extra[name_len] = '\0';
428
429 GNUNET_MQ_send (handle->mq, env);
430 return handle;
431 }
432 else
433 {
434 destroy_handle (handle);
435 return NULL;
436 }
437}
438
439int
440GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
441{
442 if ((!handle) || (!get_handle_name (handle)))
443 return GNUNET_SYSERR;
444
445 struct GNUNET_MESSENGER_UpdateMessage *msg;
446 struct GNUNET_MQ_Envelope *env;
447
448 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
449 GNUNET_MQ_send (handle->mq, env);
450 return GNUNET_OK;
451}
452
453void
454GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
455{
456 if (!handle)
457 return;
458
459 struct GNUNET_MESSENGER_DestroyMessage *msg;
460 struct GNUNET_MQ_Envelope *env;
461
462 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
463 GNUNET_MQ_send (handle->mq, env);
464
465 destroy_handle (handle);
466}
467
468const char*
469GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
470{
471 if (!handle)
472 return NULL;
473
474 return get_handle_name (handle);
475}
476
477int
478GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle, const char *name)
479{
480 if (!handle)
481 return GNUNET_SYSERR;
482
483 const uint16_t name_len = name ? strlen (name) : 0;
484
485 struct GNUNET_MESSENGER_NameMessage *msg;
486 struct GNUNET_MQ_Envelope *env;
487
488 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
489
490 char *extra = ((char*) msg) + sizeof(*msg);
491
492 if (name_len)
493 GNUNET_memcpy(extra, name, name_len);
494
495 extra[name_len] = '\0';
496
497 GNUNET_MQ_send (handle->mq, env);
498 return GNUNET_YES;
499}
500
501static const struct GNUNET_IDENTITY_PublicKey*
502get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
503{
504 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
505 return NULL;
506
507 return public_key;
508}
509
510const struct GNUNET_IDENTITY_PublicKey*
511GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
512{
513 if (!handle)
514 return NULL;
515
516 return get_non_anonymous_key (get_handle_key (handle));
517}
518
519struct GNUNET_MESSENGER_Room*
520GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
521{
522 if ((!handle) || (!key))
523 return NULL;
524
525 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
526
527 if (!room)
528 {
529 room = create_room (handle, key);
530
531 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
532 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
533 {
534 destroy_room (room);
535 return NULL;
536 }
537 }
538
539 send_open_room (handle, room);
540 return room;
541}
542
543struct GNUNET_MESSENGER_Room*
544GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
545 const struct GNUNET_HashCode *key)
546{
547 if ((!handle) || (!door) || (!key))
548 return NULL;
549
550 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
551
552 if (!room)
553 {
554 room = create_room (handle, key);
555
556 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
557 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
558 {
559 destroy_room (room);
560 return NULL;
561 }
562 }
563
564 send_enter_room (handle, room, door);
565 return room;
566}
567
568void
569GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
570{
571 if (!room)
572 return;
573
574 send_close_room (room->handle, room);
575}
576
577struct GNUNET_MESSENGER_RoomFind
578{
579 const struct GNUNET_MESSENGER_Contact *contact;
580 GNUNET_MESSENGER_MemberCallback callback;
581 size_t counter;
582 void *cls;
583};
584
585static int
586iterate_find_room (void* cls, const struct GNUNET_HashCode *key, void *value)
587{
588 struct GNUNET_MESSENGER_RoomFind *find = cls;
589 struct GNUNET_MESSENGER_Room *room = value;
590
591 if ((find->counter > 0) && ((!find->contact) || (GNUNET_YES == find_room_member(room, find->contact))))
592 {
593 find->counter--;
594
595 if (!find->callback)
596 return GNUNET_YES;
597
598 return find->callback(find->cls, room, find->contact);
599 }
600 else
601 return GNUNET_NO;
602}
603
604int
605GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_MESSENGER_Contact *contact,
606 GNUNET_MESSENGER_MemberCallback callback, void *cls)
607{
608 if (!handle)
609 return GNUNET_SYSERR;
610
611 struct GNUNET_MESSENGER_RoomFind find;
612
613 find.contact = contact;
614 find.callback = callback;
615 find.counter = (contact? contact->rc : SIZE_MAX);
616 find.cls = cls;
617
618 return GNUNET_CONTAINER_multihashmap_iterate(handle->rooms, iterate_find_room, &find);
619}
620
621const struct GNUNET_HashCode*
622GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
623{
624 if (!room)
625 return NULL;
626
627 return &(room->key);
628}
629
630const struct GNUNET_MESSENGER_Contact*
631GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
632{
633 if ((!room) || (!hash))
634 return NULL;
635
636 return get_room_sender(room, hash);
637}
638
639const char*
640GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact)
641{
642 if (!contact)
643 return NULL;
644
645 return get_contact_name (contact);
646}
647
648const struct GNUNET_IDENTITY_PublicKey*
649GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact)
650{
651 if (!contact)
652 return NULL;
653
654 return get_non_anonymous_key (get_contact_key (contact));
655}
656
657void
658GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Message *message,
659 const struct GNUNET_MESSENGER_Contact *contact)
660{
661 if ((!room) || (!message))
662 return;
663
664 switch (filter_message_sending (message))
665 {
666 case GNUNET_SYSERR:
667 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
668 return;
669 case GNUNET_NO:
670 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
671 return;
672 default:
673 break;
674 }
675
676 ssize_t key_length = 0;
677
678 if (contact)
679 {
680 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
681 get_contact_key(contact)
682 );
683
684 if (public_key)
685 key_length = GNUNET_IDENTITY_key_get_length(public_key);
686 else
687 key_length = -1;
688 }
689
690 if (key_length < 0)
691 {
692 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
693 return;
694 }
695
696 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
697
698 struct GNUNET_MESSENGER_SendMessage *msg;
699 struct GNUNET_MQ_Envelope *env;
700
701 const uint16_t length = (uint16_t) key_length + msg_length;
702
703 env = GNUNET_MQ_msg_extra(
704 msg, length,
705 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
706 );
707
708 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
709
710 msg->flags = (uint32_t) (
711 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
712 );
713
714 char *buffer = ((char*) msg) + sizeof(*msg);
715 char *msg_buffer = buffer + key_length;
716
717 if (key_length > 0)
718 GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
719
720 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
721
722 GNUNET_MQ_send (room->handle->mq, env);
723}
724
725const struct GNUNET_MESSENGER_Message*
726GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
727{
728 if ((!room) || (!hash))
729 return NULL;
730
731 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
732
733 if (!message)
734 {
735 struct GNUNET_MESSENGER_GetMessage *msg;
736 struct GNUNET_MQ_Envelope *env;
737
738 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
739 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
740 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
741 GNUNET_MQ_send (room->handle->mq, env);
742 }
743
744 return message;
745}
746
747int
748GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
749 void *cls)
750{
751 if (!room)
752 return GNUNET_SYSERR;
753
754 return iterate_room_members(room, callback, cls);
755}
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c
deleted file mode 100644
index 04e1f60c1..000000000
--- a/src/messenger/messenger_api_contact.c
+++ /dev/null
@@ -1,108 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_contact.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_contact.h"
27
28struct GNUNET_MESSENGER_Contact*
29create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
30{
31 GNUNET_assert(key);
32
33 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact);
34
35 contact->name = NULL;
36 contact->rc = 0;
37
38 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
39
40 return contact;
41}
42
43void
44destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
45{
46 GNUNET_assert(contact);
47
48 if (contact->name)
49 GNUNET_free(contact->name);
50
51 GNUNET_free(contact);
52}
53
54const char*
55get_contact_name (const struct GNUNET_MESSENGER_Contact *contact)
56{
57 GNUNET_assert(contact);
58
59 return contact->name;
60}
61
62void
63set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name)
64{
65 GNUNET_assert(contact);
66
67 if (contact->name)
68 GNUNET_free(contact->name);
69
70 contact->name = name ? GNUNET_strdup(name) : NULL;
71}
72
73const struct GNUNET_IDENTITY_PublicKey*
74get_contact_key (const struct GNUNET_MESSENGER_Contact *contact)
75{
76 GNUNET_assert(contact);
77
78 return &(contact->public_key);
79}
80
81void
82increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
83{
84 GNUNET_assert(contact);
85
86 contact->rc++;
87}
88
89int
90decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
91{
92 GNUNET_assert(contact);
93
94 if (contact->rc > 0)
95 contact->rc--;
96
97 return contact->rc ? GNUNET_NO : GNUNET_YES;
98}
99
100void
101get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
102 struct GNUNET_HashCode *context)
103{
104 GNUNET_assert((key) && (id) && (context));
105
106 GNUNET_CRYPTO_hash (id, sizeof(*id), context);
107 GNUNET_CRYPTO_hash_xor (key, context, context);
108}
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h
deleted file mode 100644
index e94d1fcd0..000000000
--- a/src/messenger/messenger_api_contact.h
+++ /dev/null
@@ -1,114 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_contact.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_CONTACT_H
27#define GNUNET_MESSENGER_API_CONTACT_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_identity_service.h"
32
33struct GNUNET_MESSENGER_Contact
34{
35 char *name;
36 size_t rc;
37
38 struct GNUNET_IDENTITY_PublicKey public_key;
39};
40
41/**
42 * Creates and allocates a new contact with a given public <i>key</i> from an EGO.
43 *
44 * @param[in] key Public key
45 * @return New contact
46 */
47struct GNUNET_MESSENGER_Contact*
48create_contact (const struct GNUNET_IDENTITY_PublicKey *key);
49
50/**
51 * Destroys a contact and frees its memory fully.
52 *
53 * @param[in/out] contact Contact
54 */
55void
56destroy_contact (struct GNUNET_MESSENGER_Contact *contact);
57
58/**
59 * Returns the current name of a given <i>contact</i> or NULL if no valid name was assigned yet.
60 *
61 * @param[in] contact Contact
62 * @return Name of the contact or NULL
63 */
64const char*
65get_contact_name (const struct GNUNET_MESSENGER_Contact *contact);
66
67/**
68 * Changes the current name of a given <i>contact</i> by copying it from the parameter <i>name</i>.
69 *
70 * @param[in/out] contact Contact
71 * @param[in] name Name
72 */
73void
74set_contact_name (struct GNUNET_MESSENGER_Contact *contact, const char *name);
75
76/**
77 * Returns the public key of a given <i>contact</i>.
78 *
79 * @param[in] contact Contact
80 * @return Public key of the contact
81 */
82const struct GNUNET_IDENTITY_PublicKey*
83get_contact_key (const struct GNUNET_MESSENGER_Contact *contact);
84
85/**
86 * Increases the reference counter of a given <i>contact</i> which is zero as default.
87 *
88 * @param[in/out] contact Contact
89 */
90void
91increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
92
93/**
94 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
95 * and returns #GNUNET_YES if the counter is equal to zero, otherwise #GNUNET_NO.
96 *
97 * @param[in/out] contact Contact
98 * @return #GNUNET_YES or #GNUNET_NO depending on the reference counter
99 */
100int
101decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
102
103/**
104 * Calculates the context <i>hash</i> of a member in a room and returns it.
105 *
106 * @param[in] key Key of room
107 * @param[in] id Member id
108 * @param[out] hash Member context
109 */
110void
111get_context_from_member (const struct GNUNET_HashCode *key, const struct GNUNET_ShortHashCode *id,
112 struct GNUNET_HashCode *context);
113
114#endif //GNUNET_MESSENGER_API_CONTACT_H
diff --git a/src/messenger/messenger_api_contact_store.c b/src/messenger/messenger_api_contact_store.c
deleted file mode 100644
index 6a517c2e0..000000000
--- a/src/messenger/messenger_api_contact_store.c
+++ /dev/null
@@ -1,185 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_contact_store.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_contact_store.h"
27
28#include "messenger_api_contact.h"
29#include "messenger_api_util.h"
30
31void
32init_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
33{
34 GNUNET_assert (store);
35
36 store->anonymous = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
37 store->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Contact *contact = value;
44 destroy_contact (contact);
45 return GNUNET_YES;
46}
47
48void
49clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
50{
51 GNUNET_assert ((store) && (store->contacts));
52
53 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
54 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
55
56 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
57 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
58}
59
60static struct GNUNET_CONTAINER_MultiHashMap*
61select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
62 struct GNUNET_HashCode *hash)
63{
64 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
65
66 struct GNUNET_HashCode anonHash;
67 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
68
69 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
70 {
71 GNUNET_memcpy(hash, context, sizeof(*context));
72 return store->anonymous;
73 }
74 else
75 return store->contacts;
76}
77
78struct GNUNET_MESSENGER_Contact*
79get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
80 const struct GNUNET_HashCode *key_hash)
81{
82 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
83
84 struct GNUNET_HashCode hash;
85 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
86
87 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
88 store, context, &hash
89 );
90
91 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
92}
93
94struct GNUNET_MESSENGER_Contact*
95get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
96 const struct GNUNET_IDENTITY_PublicKey *pubkey)
97{
98 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
99
100 struct GNUNET_HashCode hash;
101 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
102
103 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
104 store, context, &hash
105 );
106
107 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
108
109 if (contact)
110 {
111 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
112 {
113 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
114 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
115 GNUNET_free (str);
116 return NULL;
117 }
118
119 return contact;
120 }
121
122 contact = create_contact (pubkey);
123
124 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
126 return contact;
127
128 destroy_contact (contact);
129 return NULL;
130}
131
132void
133update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
134 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
135 const struct GNUNET_IDENTITY_PublicKey *pubkey)
136{
137 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
138
139 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
140
141 struct GNUNET_HashCode hash;
142 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
143
144 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
145 store, context, &hash
146 );
147
148 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
149 {
150 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
151
152 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
153
154 map = select_store_contact_map (
155 store, next_context, &hash
156 );
157
158 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
159 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
160 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating a contact failed: %s\n",
161 GNUNET_h2s(&hash));
162 }
163}
164
165void
166remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
167 const struct GNUNET_HashCode *context)
168{
169 GNUNET_assert ((store) && (store->contacts) && (contact));
170
171 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
172
173 struct GNUNET_HashCode hash;
174 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
175
176 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
177 store, context, &hash
178 );
179
180 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
181 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a contact failed: %s\n",
182 GNUNET_h2s(&hash));
183
184 destroy_contact (contact);
185}
diff --git a/src/messenger/messenger_api_contact_store.h b/src/messenger/messenger_api_contact_store.h
deleted file mode 100644
index f2dad9f84..000000000
--- a/src/messenger/messenger_api_contact_store.h
+++ /dev/null
@@ -1,122 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_contact_store.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_CONTACT_STORE_H
27#define GNUNET_MESSENGER_API_CONTACT_STORE_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_identity_service.h"
33
34struct GNUNET_MESSENGER_Contact;
35
36struct GNUNET_MESSENGER_ContactStore
37{
38 struct GNUNET_CONTAINER_MultiHashMap *anonymous;
39 struct GNUNET_CONTAINER_MultiHashMap *contacts;
40};
41
42/**
43 * Initializes a contact store as fully empty.
44 *
45 * @param[out] store Contact store
46 */
47void
48init_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
49
50/**
51 * Clears a contact store, wipes its content and deallocates its memory.
52 *
53 * @param[in/out] store Contact store
54 */
55void
56clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
57
58/**
59 * Returns a contact using the hash of a specific public key. In case the anonymous
60 * key gets used by the requested contact, it will use its provided member
61 * <i>context</i> to select the matching contact from the <i>store</i>.
62 *
63 * In case there is no contact stored which uses the given key or context,
64 * NULL gets returned.
65 *
66 * @param[in/out] store Contact store
67 * @param[in] context Member context
68 * @param[in] key_hash Hash of public key
69 */
70struct GNUNET_MESSENGER_Contact*
71get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
72 const struct GNUNET_HashCode *key_hash);
73
74/**
75 * Returns a contact using a specific public key. In case the anonymous
76 * key gets used by the requested contact, it will use its provided member
77 * <i>context</i> to select the matching contact from the <i>store</i>.
78 *
79 * In case there is no contact stored which uses the given key or context,
80 * a new contact will be created automatically.
81 *
82 * The function returns NULL if an error occurs during allocation
83 * or validation of the contacts key.
84 *
85 * @param[in/out] store Contact store
86 * @param[in] context Member context
87 * @param[in] pubkey Public key of EGO
88 */
89struct GNUNET_MESSENGER_Contact*
90get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
91 const struct GNUNET_IDENTITY_PublicKey *pubkey);
92
93/**
94 * Moves a <i>contact</i> from the <i>store</i> to another location
95 * matching a given public key and member <i>context</i>.
96 *
97 * This function allows changes of keys or changes of member contexts!
98 *
99 * @param[in/out] store Contact store
100 * @param[in/out] contact Contact
101 * @param[in] context Member context
102 * @param[in] next_context Member context
103 * @param[in] pubkey Public key of EGO
104 */
105void
106update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
107 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
108 const struct GNUNET_IDENTITY_PublicKey *pubkey);
109
110/**
111 * Removes a <i>contact</i> from the <i>store</i> which uses
112 * a given member <i>context</i>.
113 *
114 * @param[in/out] store Contact store
115 * @param[in/out] contact Contact
116 * @param[in] context Member context
117 */
118void
119remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
120 const struct GNUNET_HashCode *context);
121
122#endif //GNUNET_MESSENGER_API_CONTACT_STORE_H
diff --git a/src/messenger/messenger_api_ego.h b/src/messenger/messenger_api_ego.h
deleted file mode 100644
index b52b895f2..000000000
--- a/src/messenger/messenger_api_ego.h
+++ /dev/null
@@ -1,38 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_ego.h
23 * @brief GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_EGO_H
27#define GNUNET_MESSENGER_API_EGO_H
28
29#include "platform.h"
30#include "gnunet_identity_service.h"
31
32struct GNUNET_MESSENGER_Ego
33{
34 struct GNUNET_IDENTITY_PrivateKey priv;
35 struct GNUNET_IDENTITY_PublicKey pub;
36};
37
38#endif //GNUNET_MESSENGER_API_EGO_H
diff --git a/src/messenger/messenger_api_handle.c b/src/messenger/messenger_api_handle.c
deleted file mode 100644
index ab57f82cc..000000000
--- a/src/messenger/messenger_api_handle.c
+++ /dev/null
@@ -1,196 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_handle.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_handle.h"
27
28#include "messenger_api_util.h"
29
30struct GNUNET_MESSENGER_Handle*
31create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback,
32 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls)
33{
34 GNUNET_assert(cfg);
35
36 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle);
37
38 handle->cfg = cfg;
39 handle->mq = NULL;
40
41 handle->identity_callback = identity_callback;
42 handle->identity_cls = identity_cls;
43
44 handle->msg_callback = msg_callback;
45 handle->msg_cls = msg_cls;
46
47 handle->name = NULL;
48 handle->pubkey = NULL;
49
50 handle->reconnect_time = GNUNET_TIME_relative_get_zero_ ();
51 handle->reconnect_task = NULL;
52
53 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
54
55 init_contact_store(get_handle_contact_store(handle));
56
57 return handle;
58}
59
60static int
61iterate_destroy_room (void *cls, const struct GNUNET_HashCode *key, void *value)
62{
63 struct GNUNET_MESSENGER_Room *room = value;
64
65 destroy_room (room);
66
67 return GNUNET_YES;
68}
69
70void
71destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
72{
73 GNUNET_assert(handle);
74
75 if (handle->reconnect_task)
76 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
77
78 if (handle->mq)
79 GNUNET_MQ_destroy (handle->mq);
80
81 if (handle->name)
82 GNUNET_free(handle->name);
83
84 if (handle->pubkey)
85 GNUNET_free(handle->pubkey);
86
87 if (handle->rooms)
88 {
89 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_destroy_room, NULL);
90
91 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms);
92 }
93
94 clear_contact_store(get_handle_contact_store(handle));
95
96 GNUNET_free(handle->name);
97}
98
99void
100set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name)
101{
102 GNUNET_assert(handle);
103
104 if (handle->name)
105 GNUNET_free(handle->name);
106
107 handle->name = name ? GNUNET_strdup(name) : NULL;
108}
109
110const char*
111get_handle_name (const struct GNUNET_MESSENGER_Handle *handle)
112{
113 GNUNET_assert(handle);
114
115 return handle->name;
116}
117
118void
119set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey)
120{
121 GNUNET_assert(handle);
122
123 if (!handle->pubkey)
124 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
125
126 GNUNET_memcpy(handle->pubkey, pubkey, sizeof(*pubkey));
127}
128
129const struct GNUNET_IDENTITY_PublicKey*
130get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
131{
132 GNUNET_assert(handle);
133
134 if (handle->pubkey)
135 return handle->pubkey;
136
137 return get_anonymous_public_key ();
138}
139
140struct GNUNET_MESSENGER_ContactStore*
141get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle)
142{
143 GNUNET_assert(handle);
144
145 return &(handle->contact_store);
146}
147
148struct GNUNET_MESSENGER_Contact*
149get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
150{
151 GNUNET_assert((handle) && (key));
152
153 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
154
155 if ((!room) || (!(room->contact_id)))
156 return NULL;
157
158 struct GNUNET_HashCode context;
159 get_context_from_member (key, room->contact_id, &context);
160
161 return get_store_contact(get_handle_contact_store(handle), &context, get_handle_key(handle));
162}
163
164void
165open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
166{
167 GNUNET_assert((handle) && (key));
168
169 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
170
171 if (room)
172 room->opened = GNUNET_YES;
173}
174
175void
176entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
177 const struct GNUNET_HashCode *key)
178{
179 GNUNET_assert((handle) && (door) && (key));
180
181 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
182
183 if (room)
184 add_to_list_tunnels (&(room->entries), door);
185}
186
187void
188close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
189{
190 GNUNET_assert((handle) && (key));
191
192 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
193
194 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room)))
195 destroy_room (room);
196}
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h
deleted file mode 100644
index e6ca474f2..000000000
--- a/src/messenger/messenger_api_handle.h
+++ /dev/null
@@ -1,171 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_handle.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_HANDLE_H
27#define GNUNET_MESSENGER_API_HANDLE_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_identity_service.h"
34#include "gnunet_peer_lib.h"
35
36#include "gnunet_messenger_service.h"
37
38#include "messenger_api_contact_store.h"
39#include "messenger_api_room.h"
40
41struct GNUNET_MESSENGER_Handle
42{
43 const struct GNUNET_CONFIGURATION_Handle *cfg;
44
45 struct GNUNET_MQ_Handle *mq;
46
47 GNUNET_MESSENGER_IdentityCallback identity_callback;
48 void *identity_cls;
49
50 GNUNET_MESSENGER_MessageCallback msg_callback;
51 void *msg_cls;
52
53 char *name;
54 struct GNUNET_IDENTITY_PublicKey *pubkey;
55
56 struct GNUNET_TIME_Relative reconnect_time;
57 struct GNUNET_SCHEDULER_Task *reconnect_task;
58
59 struct GNUNET_MESSENGER_ContactStore contact_store;
60
61 struct GNUNET_CONTAINER_MultiHashMap *rooms;
62};
63
64/**
65 * Creates and allocates a new handle using a given configuration and a custom message callback
66 * with a given closure for the client API.
67 *
68 * @param[in] cfg Configuration
69 * @param[in] msg_callback Message callback
70 * @param[in/out] msg_cls Closure
71 * @return New handle
72 */
73struct GNUNET_MESSENGER_Handle*
74create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_MESSENGER_IdentityCallback identity_callback,
75 void *identity_cls, GNUNET_MESSENGER_MessageCallback msg_callback, void *msg_cls);
76
77/**
78 * Destroys a <i>handle</i> and frees its memory fully from the client API.
79 *
80 * @param[in/out] handle Handle
81 */
82void
83destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
84
85/**
86 * Sets the name of a <i>handle</i> to a specific <i>name</i>.
87 *
88 * @param[in/out] handle Handle
89 * @param[in] name New name
90 */
91void
92set_handle_name (struct GNUNET_MESSENGER_Handle *handle, const char *name);
93
94/**
95 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet.
96 *
97 * @param[in] handle Handle
98 * @return Name of the handle or NULL
99 */
100const char*
101get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
102
103/**
104 * Sets the public key of a given <i>handle</i> to a specific public key.
105 *
106 * @param[in/out] handle Handle
107 * @param[in] pubkey Public key
108 */
109void
110set_handle_key (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_IDENTITY_PublicKey *pubkey);
111
112/**
113 * Returns the public key of a given <i>handle</i>.
114 *
115 * @param[in] handle Handle
116 * @return Public key of the handle
117 */
118const struct GNUNET_IDENTITY_PublicKey*
119get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
120
121/**
122 * Returns the used contact store of a given <i>handle</i>.
123 *
124 * @param[in/out] handle Handle
125 * @return Contact store
126 */
127struct GNUNET_MESSENGER_ContactStore*
128get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle);
129
130/**
131 * Returns the contact of a given <i>handle</i> in a room identified by a
132 * given <i>key</i>.
133 *
134 * @param[in/out] handle Handle
135 * @param[in] key Key of room
136 * @return Contact
137 */
138struct GNUNET_MESSENGER_Contact*
139get_handle_contact (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
140
141/**
142 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open.
143 *
144 * @param[in/out] handle Handle
145 * @param[in] key Key of room
146 */
147void
148open_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
149
150/**
151 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a
152 * list of opened connections.
153 *
154 * @param[in/out] handle Handle
155 * @param[in] door Peer identity
156 * @param[in] key Key of room
157 */
158void
159entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_PeerIdentity *door,
160 const struct GNUNET_HashCode *key);
161
162/**
163 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>.
164 *
165 * @param[in/out] handle Handle
166 * @param[in] key Key of room
167 */
168void
169close_handle_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
170
171#endif //GNUNET_MESSENGER_API_HANDLE_H
diff --git a/src/messenger/messenger_api_list_tunnels.c b/src/messenger/messenger_api_list_tunnels.c
deleted file mode 100644
index 990e36878..000000000
--- a/src/messenger/messenger_api_list_tunnels.c
+++ /dev/null
@@ -1,184 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_list_tunnels.c
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_list_tunnels.h"
27
28void
29init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels)
30{
31 GNUNET_assert(tunnels);
32
33 tunnels->head = NULL;
34 tunnels->tail = NULL;
35}
36
37void
38clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels)
39{
40 GNUNET_assert(tunnels);
41
42 struct GNUNET_MESSENGER_ListTunnel *element;
43
44 for (element = tunnels->head; element; element = tunnels->head)
45 {
46 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
47 GNUNET_PEER_change_rc (element->peer, -1);
48 GNUNET_free(element);
49 }
50
51 tunnels->head = NULL;
52 tunnels->tail = NULL;
53}
54
55static int
56compare_list_tunnels (void *cls, struct GNUNET_MESSENGER_ListTunnel *element0,
57 struct GNUNET_MESSENGER_ListTunnel *element1)
58{
59 return ((int) element0->peer) - ((int) element1->peer);
60}
61
62void
63add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
64{
65 GNUNET_assert((tunnels) && (peer));
66
67 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel);
68
69 element->peer = GNUNET_PEER_intern (peer);
70
71 GNUNET_CONTAINER_DLL_insert_sorted(struct GNUNET_MESSENGER_ListTunnel, compare_list_tunnels, NULL, tunnels->head,
72 tunnels->tail, element);
73}
74
75struct GNUNET_MESSENGER_ListTunnel*
76find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index)
77{
78 GNUNET_assert((tunnels) && (peer));
79
80 struct GNUNET_MESSENGER_ListTunnel *element;
81 struct GNUNET_PeerIdentity pid;
82
83 if (index)
84 *index = 0;
85
86 for (element = tunnels->head; element; element = element->next)
87 {
88 GNUNET_PEER_resolve (element->peer, &pid);
89
90 if (0 == GNUNET_memcmp(&pid, peer))
91 return element;
92
93 if (index)
94 (*index) = (*index) + 1;
95 }
96
97 return NULL;
98}
99
100int
101contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer)
102{
103 GNUNET_assert((tunnels) && (peer));
104
105 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO;
106}
107
108struct GNUNET_MESSENGER_ListTunnel*
109remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element)
110{
111 GNUNET_assert((tunnels) && (element));
112
113 struct GNUNET_MESSENGER_ListTunnel *next = element->next;
114
115 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
116 GNUNET_PEER_change_rc (element->peer, -1);
117 GNUNET_free(element);
118
119 return next;
120}
121
122void
123load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
124{
125 GNUNET_assert((tunnels) && (path));
126
127 if (GNUNET_YES != GNUNET_DISK_file_test (path))
128 return;
129
130 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
131
132 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
133 path, GNUNET_DISK_OPEN_READ, permission
134 );
135
136 if (!handle)
137 return;
138
139 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
140
141 struct GNUNET_PeerIdentity peer;
142 ssize_t len;
143
144 do {
145 len = GNUNET_DISK_file_read(handle, &peer, sizeof(peer));
146
147 if (len != sizeof(peer))
148 break;
149
150 add_to_list_tunnels(tunnels, &peer);
151 } while (len == sizeof(peer));
152
153 GNUNET_DISK_file_close(handle);
154}
155
156void
157save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path)
158{
159 GNUNET_assert((tunnels) && (path));
160
161 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
162
163 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
164 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
165 );
166
167 if (!handle)
168 return;
169
170 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
171
172 struct GNUNET_MESSENGER_ListTunnel *element;
173 struct GNUNET_PeerIdentity pid;
174
175 for (element = tunnels->head; element; element = element->next)
176 {
177 GNUNET_PEER_resolve (element->peer, &pid);
178
179 GNUNET_DISK_file_write(handle, &pid, sizeof(pid));
180 }
181
182 GNUNET_DISK_file_sync(handle);
183 GNUNET_DISK_file_close(handle);
184}
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h
deleted file mode 100644
index c952da3c2..000000000
--- a/src/messenger/messenger_api_list_tunnels.h
+++ /dev/null
@@ -1,130 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_list_tunnels.h
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_LIST_TUNNELS_H
27#define GNUNET_MESSENGER_API_LIST_TUNNELS_H
28
29#include "platform.h"
30#include "gnunet_peer_lib.h"
31#include "gnunet_container_lib.h"
32
33struct GNUNET_MESSENGER_ListTunnel
34{
35 struct GNUNET_MESSENGER_ListTunnel *prev;
36 struct GNUNET_MESSENGER_ListTunnel *next;
37
38 GNUNET_PEER_Id peer;
39};
40
41struct GNUNET_MESSENGER_ListTunnels
42{
43 struct GNUNET_MESSENGER_ListTunnel *head;
44 struct GNUNET_MESSENGER_ListTunnel *tail;
45};
46
47/**
48 * Initializes list of tunnels peer identities as empty list.
49 *
50 * @param[out] tunnels List of peer identities
51 */
52void
53init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
54
55/**
56 * Clears the list of tunnels peer identities.
57 *
58 * @param[in/out] tunnels List of peer identities
59 */
60void
61clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
62
63/**
64 * Adds a specific <i>peer</i> from a tunnel to the end of the list.
65 *
66 * @param[in/out] tunnels List of peer identities
67 * @param[in] peer Peer identity of tunnel
68 */
69void
70add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
71
72/**
73 * Searches linearly through the list of tunnels peer identities for matching a
74 * specific <i>peer</i> identity and returns the matching element of the list.
75 *
76 * If no matching element is found, NULL gets returned.
77 *
78 * If <i>index</i> is not NULL, <i>index</i> will be overridden with the numeric index of
79 * the found element in the list. If no matching element is found, <i>index</i> will
80 * contain the total amount of elements in the list.
81 *
82 * @param[in/out] tunnels List of peer identities
83 * @param[in] peer Peer identity of tunnel
84 * @param[out] index Index of found element (optional)
85 * @return Element in the list with matching peer identity
86 */
87struct GNUNET_MESSENGER_ListTunnel*
88find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer, size_t *index);
89
90/**
91 * Tests linearly if the list of tunnels peer identities contains a specific
92 * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise #GNUNET_NO.
93 *
94 * @param[in/out] tunnels List of peer identities
95 * @param[in] peer Peer identity of tunnel
96 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
97 */
98int
99contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const struct GNUNET_PeerIdentity *peer);
100
101/**
102 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns
103 * the next element in the list.
104 *
105 * @param[in/out] tunnels List of peer identities
106 * @param[in/out] element Element of the list
107 * @return Next element in the list
108 */
109struct GNUNET_MESSENGER_ListTunnel*
110remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, struct GNUNET_MESSENGER_ListTunnel *element);
111
112/**
113 * Loads the list of tunnels peer identities from a file under a given <i>path</i>.
114 *
115 * @param[out] messages List of hashes
116 * @param[in] path Path of file
117 */
118void
119load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
120
121/**
122 * Saves the list of tunnels peer identities to a file under a given <i>path</i>.
123 *
124 * @param[in] messages List of hashes
125 * @param[in] path Path of file
126 */
127void
128save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels, const char *path);
129
130#endif //GNUNET_MESSENGER_API_LIST_TUNNELS_H
diff --git a/src/messenger/messenger_api_message.c b/src/messenger/messenger_api_message.c
deleted file mode 100644
index c7364d51c..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,877 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_message.c
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_message.h"
27
28struct GNUNET_MESSENGER_MessageSignature
29{
30 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
31 struct GNUNET_HashCode hash;
32};
33
34struct GNUNET_MESSENGER_ShortMessage
35{
36 enum GNUNET_MESSENGER_MessageKind kind;
37 struct GNUNET_MESSENGER_MessageBody body;
38};
39
40struct GNUNET_MESSENGER_Message*
41create_message (enum GNUNET_MESSENGER_MessageKind kind)
42{
43 struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct GNUNET_MESSENGER_Message);
44
45 message->header.kind = kind;
46
47 switch (message->header.kind)
48 {
49 case GNUNET_MESSENGER_KIND_NAME:
50 message->body.name.name = NULL;
51 break;
52 case GNUNET_MESSENGER_KIND_TEXT:
53 message->body.text.text = NULL;
54 break;
55 case GNUNET_MESSENGER_KIND_FILE:
56 message->body.file.uri = NULL;
57 break;
58 case GNUNET_MESSENGER_KIND_PRIVATE:
59 message->body.privacy.length = 0;
60 message->body.privacy.data = NULL;
61 break;
62 default:
63 break;
64 }
65
66 return message;
67}
68
69struct GNUNET_MESSENGER_Message*
70copy_message (const struct GNUNET_MESSENGER_Message *message)
71{
72 GNUNET_assert(message);
73
74 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
75
76 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
77
78 switch (message->header.kind)
79 {
80 case GNUNET_MESSENGER_KIND_NAME:
81 copy->body.name.name = GNUNET_strdup(message->body.name.name);
82 break;
83 case GNUNET_MESSENGER_KIND_TEXT:
84 copy->body.text.text = GNUNET_strdup(message->body.text.text);
85 break;
86 case GNUNET_MESSENGER_KIND_FILE:
87 copy->body.file.uri = GNUNET_strdup(message->body.file.uri);
88 break;
89 case GNUNET_MESSENGER_KIND_PRIVATE:
90 copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc(copy->body.privacy.length) : NULL;
91
92 if (copy->body.privacy.data)
93 {
94 GNUNET_memcpy(copy->body.privacy.data, message->body.privacy.data, copy->body.privacy.length);
95 }
96
97 break;
98 default:
99 break;
100 }
101
102 return copy;
103}
104
105static void
106destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind, struct GNUNET_MESSENGER_MessageBody *body)
107{
108 switch (kind)
109 {
110 case GNUNET_MESSENGER_KIND_NAME:
111 GNUNET_free(body->name.name);
112 break;
113 case GNUNET_MESSENGER_KIND_TEXT:
114 GNUNET_free(body->text.text);
115 break;
116 case GNUNET_MESSENGER_KIND_FILE:
117 GNUNET_free(body->file.uri);
118 break;
119 case GNUNET_MESSENGER_KIND_PRIVATE:
120 GNUNET_free(body->privacy.data);
121 break;
122 default:
123 break;
124 }
125}
126
127void
128destroy_message (struct GNUNET_MESSENGER_Message *message)
129{
130 GNUNET_assert(message);
131
132 destroy_message_body (message->header.kind, &(message->body));
133
134 GNUNET_free(message);
135}
136
137int
138is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
139{
140 GNUNET_assert(message);
141
142 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
143 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
144 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
145 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
146 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
147 return GNUNET_YES;
148 else
149 return GNUNET_NO;
150}
151
152static void
153fold_short_message (const struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_ShortMessage *shortened)
154{
155 shortened->kind = message->header.kind;
156
157 GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
158}
159
160static void
161unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened, struct GNUNET_MESSENGER_Message *message)
162{
163 destroy_message_body (message->header.kind, &(message->body));
164
165 message->header.kind = shortened->kind;
166
167 GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
168}
169
170#define member_size(type, member) sizeof(((type*) NULL)->member)
171
172static uint16_t
173get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
174{
175 uint16_t length = 0;
176
177 switch (kind)
178 {
179 case GNUNET_MESSENGER_KIND_INFO:
180 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
181 break;
182 case GNUNET_MESSENGER_KIND_PEER:
183 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
184 break;
185 case GNUNET_MESSENGER_KIND_ID:
186 length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
187 break;
188 case GNUNET_MESSENGER_KIND_MISS:
189 length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
190 break;
191 case GNUNET_MESSENGER_KIND_MERGE:
192 length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous);
193 break;
194 case GNUNET_MESSENGER_KIND_REQUEST:
195 length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
196 break;
197 case GNUNET_MESSENGER_KIND_INVITE:
198 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
199 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
200 break;
201 case GNUNET_MESSENGER_KIND_TEXT:
202 break;
203 case GNUNET_MESSENGER_KIND_FILE:
204 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
205 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
206 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
207 break;
208 case GNUNET_MESSENGER_KIND_PRIVATE:
209 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
210 break;
211 default:
212 break;
213 }
214
215 return length;
216}
217
218typedef uint32_t kind_t;
219
220uint16_t
221get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
222{
223 uint16_t length = 0;
224
225 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
226 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
227 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
228 length += sizeof(kind_t);
229
230 return length + get_message_body_kind_size (kind);
231}
232
233static uint16_t
234get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body)
235{
236 uint16_t length = 0;
237
238 switch (kind)
239 {
240 case GNUNET_MESSENGER_KIND_INFO:
241 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
242 break;
243 case GNUNET_MESSENGER_KIND_JOIN:
244 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
245 break;
246 case GNUNET_MESSENGER_KIND_NAME:
247 length += (body->name.name ? strlen (body->name.name) : 0);
248 break;
249 case GNUNET_MESSENGER_KIND_KEY:
250 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
251 break;
252 case GNUNET_MESSENGER_KIND_TEXT:
253 length += strlen (body->text.text);
254 break;
255 case GNUNET_MESSENGER_KIND_FILE:
256 length += strlen (body->file.uri);
257 break;
258 case GNUNET_MESSENGER_KIND_PRIVATE:
259 length += body->privacy.length;
260 break;
261 default:
262 break;
263 }
264
265 return length;
266}
267
268uint16_t
269get_message_size (const struct GNUNET_MESSENGER_Message *message,
270 int include_signature)
271{
272 GNUNET_assert(message);
273
274 uint16_t length = 0;
275
276 if (GNUNET_YES == include_signature)
277 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
278
279 length += get_message_kind_size (message->header.kind);
280 length += get_message_body_size (message->header.kind, &(message->body));
281
282 return length;
283}
284
285static uint16_t
286get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message, int include_body)
287{
288 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
289
290 if (message)
291 return minimum_size + get_message_body_kind_size (message->kind)
292 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
293 else
294 return minimum_size;
295}
296
297static uint16_t
298calc_usual_padding ()
299{
300 uint16_t padding = 0;
301 uint16_t kind_size;
302
303 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
304 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i);
305
306 if (kind_size > padding)
307 padding = kind_size;
308 }
309
310 return padding + GNUNET_MESSENGER_PADDING_MIN;
311}
312
313#define max(x, y) (x > y? x : y)
314
315static uint16_t
316calc_padded_length (uint16_t length)
317{
318 static uint16_t usual_padding = 0;
319
320 if (!usual_padding)
321 usual_padding = calc_usual_padding();
322
323 const uint16_t padded_length = max(
324 length + GNUNET_MESSENGER_PADDING_MIN,
325 usual_padding
326 );
327
328 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
329 return GNUNET_MESSENGER_PADDING_LEVEL0;
330
331 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
332 return GNUNET_MESSENGER_PADDING_LEVEL1;
333
334 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
335 return GNUNET_MESSENGER_PADDING_LEVEL2;
336
337 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
338
339}
340
341#define min(x, y) (x < y? x : y)
342
343#define encode_step_ext(dst, offset, src, size) do { \
344 GNUNET_memcpy(dst + offset, src, size); \
345 offset += size; \
346} while (0)
347
348#define encode_step(dst, offset, src) do { \
349 encode_step_ext(dst, offset, src, sizeof(*src)); \
350} while (0)
351
352#define encode_step_key(dst, offset, src, length) do { \
353 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
354 src, dst + offset, length - offset \
355 ); \
356 if (result < 0) \
357 GNUNET_break (0); \
358 else \
359 offset += result; \
360} while (0)
361
362#define encode_step_signature(dst, offset, src, length) do { \
363 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
364 src, dst + offset, length - offset \
365 ); \
366 if (result < 0) \
367 GNUNET_break (0); \
368 else \
369 offset += result; \
370} while (0)
371
372static void
373encode_message_body (enum GNUNET_MESSENGER_MessageKind kind, const struct GNUNET_MESSENGER_MessageBody *body,
374 uint16_t length, char *buffer, uint16_t offset)
375{
376 uint32_t version;
377 switch (kind)
378 {
379 case GNUNET_MESSENGER_KIND_INFO:
380 version = GNUNET_htobe32(body->info.messenger_version);
381
382 encode_step_key(buffer, offset, &(body->info.host_key), length);
383 encode_step(buffer, offset, &version);
384 break;
385 case GNUNET_MESSENGER_KIND_JOIN:
386 encode_step_key(buffer, offset, &(body->join.key), length);
387 break;
388 case GNUNET_MESSENGER_KIND_NAME:
389 if (body->name.name)
390 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
391 break;
392 case GNUNET_MESSENGER_KIND_KEY:
393 encode_step_key(buffer, offset, &(body->key.key), length);
394 break;
395 case GNUNET_MESSENGER_KIND_PEER:
396 encode_step(buffer, offset, &(body->peer.peer));
397 break;
398 case GNUNET_MESSENGER_KIND_ID:
399 encode_step(buffer, offset, &(body->id.id));
400 break;
401 case GNUNET_MESSENGER_KIND_MISS:
402 encode_step(buffer, offset, &(body->miss.peer));
403 break;
404 case GNUNET_MESSENGER_KIND_MERGE:
405 encode_step(buffer, offset, &(body->merge.previous));
406 break;
407 case GNUNET_MESSENGER_KIND_REQUEST:
408 encode_step(buffer, offset, &(body->request.hash));
409 break;
410 case GNUNET_MESSENGER_KIND_INVITE:
411 encode_step(buffer, offset, &(body->invite.door));
412 encode_step(buffer, offset, &(body->invite.key));
413 break;
414 case GNUNET_MESSENGER_KIND_TEXT:
415 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
416 break;
417 case GNUNET_MESSENGER_KIND_FILE:
418 encode_step(buffer, offset, &(body->file.key));
419 encode_step(buffer, offset, &(body->file.hash));
420 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
421 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
422 break;
423 case GNUNET_MESSENGER_KIND_PRIVATE:
424 encode_step(buffer, offset, &(body->privacy.key));
425 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
426 break;
427 default:
428 break;
429 }
430
431 if (offset >= length)
432 return;
433
434 const uint16_t padding = length - offset;
435 const uint16_t used_padding = sizeof(padding) + sizeof(char);
436
437 GNUNET_assert(padding >= used_padding);
438
439 buffer[offset++] = '\0';
440
441 if (padding > used_padding)
442 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
443
444 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
445}
446
447void
448encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
449 int include_signature)
450{
451 GNUNET_assert((message) && (buffer));
452
453 uint16_t offset = 0;
454
455 if (GNUNET_YES == include_signature)
456 encode_step_signature(buffer, offset, &(message->header.signature), length);
457
458 const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
459
460 encode_step(buffer, offset, &(message->header.timestamp));
461 encode_step(buffer, offset, &(message->header.sender_id));
462 encode_step(buffer, offset, &(message->header.previous));
463 encode_step(buffer, offset, &kind);
464
465 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
466}
467
468static void
469encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, char *buffer)
470{
471 struct GNUNET_HashCode hash;
472 uint16_t offset = sizeof(hash);
473
474 const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
475
476 encode_step(buffer, offset, &kind);
477
478 encode_message_body (message->kind, &(message->body), length, buffer, offset);
479
480 GNUNET_CRYPTO_hash(
481 buffer + sizeof(hash),
482 length - sizeof(hash),
483 &hash
484 );
485
486 GNUNET_memcpy(buffer, &hash, sizeof(hash));
487}
488
489#define decode_step_ext(src, offset, dst, size) do { \
490 GNUNET_memcpy(dst, src + offset, size); \
491 offset += size; \
492} while (0)
493
494#define decode_step(src, offset, dst) do { \
495 decode_step_ext(src, offset, dst, sizeof(*dst)); \
496} while (0)
497
498#define decode_step_malloc(src, offset, dst, size, zero) do { \
499 dst = GNUNET_malloc(size + zero); \
500 if (zero) dst[size] = 0; \
501 decode_step_ext(src, offset, dst, size); \
502} while (0)
503
504#define decode_step_key(src, offset, dst, length) do { \
505 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
506 dst, src + offset, length - offset \
507 ); \
508 if (result < 0) \
509 GNUNET_break(0); \
510 else \
511 offset += result; \
512} while (0)
513
514static uint16_t
515decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind, struct GNUNET_MESSENGER_MessageBody *body,
516 uint16_t length, const char *buffer, uint16_t offset)
517{
518 uint16_t padding = 0;
519
520 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
521
522 if (padding > length - offset)
523 padding = 0;
524
525 const uint16_t end_zero = length - padding;
526
527 if ((padding) && (buffer[end_zero] != '\0'))
528 padding = 0;
529
530 length -= padding;
531
532 uint32_t version;
533 switch (*kind)
534 {
535 case GNUNET_MESSENGER_KIND_INFO: {
536 decode_step_key(buffer, offset, &(body->info.host_key), length);
537 decode_step(buffer, offset, &version);
538
539 body->info.messenger_version = GNUNET_be32toh(version);
540 break;
541 } case GNUNET_MESSENGER_KIND_JOIN: {
542 decode_step_key(buffer, offset, &(body->join.key), length);
543 break;
544 } case GNUNET_MESSENGER_KIND_NAME:
545 if (length - offset > 0)
546 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
547 else
548 body->name.name = NULL;
549 break;
550 case GNUNET_MESSENGER_KIND_KEY:
551 decode_step_key(buffer, offset, &(body->key.key), length);
552 break;
553 case GNUNET_MESSENGER_KIND_PEER:
554 decode_step(buffer, offset, &(body->peer.peer));
555 break;
556 case GNUNET_MESSENGER_KIND_ID:
557 decode_step(buffer, offset, &(body->id.id));
558 break;
559 case GNUNET_MESSENGER_KIND_MISS:
560 decode_step(buffer, offset, &(body->miss.peer));
561 break;
562 case GNUNET_MESSENGER_KIND_MERGE:
563 decode_step(buffer, offset, &(body->merge.previous));
564 break;
565 case GNUNET_MESSENGER_KIND_REQUEST:
566 decode_step(buffer, offset, &(body->request.hash));
567 break;
568 case GNUNET_MESSENGER_KIND_INVITE:
569 decode_step(buffer, offset, &(body->invite.door));
570 decode_step(buffer, offset, &(body->invite.key));
571 break;
572 case GNUNET_MESSENGER_KIND_TEXT:
573 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
574 break;
575 case GNUNET_MESSENGER_KIND_FILE:
576 decode_step(buffer, offset, &(body->file.key));
577 decode_step(buffer, offset, &(body->file.hash));
578 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
579 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
580 break;
581 case GNUNET_MESSENGER_KIND_PRIVATE:
582 decode_step(buffer, offset, &(body->privacy.key));
583
584 body->privacy.length = (length - offset);
585 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
586 break;
587 default:
588 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
589 break;
590 }
591
592 return padding;
593}
594
595int
596decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
597 int include_signature, uint16_t *padding)
598{
599 GNUNET_assert((message) && (buffer) && (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN)));
600
601 uint16_t offset = 0;
602
603 if (GNUNET_YES == include_signature)
604 {
605 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
606 &(message->header.signature), buffer, length - offset
607 );
608
609 if (result < 0)
610 return GNUNET_NO;
611 else
612 offset += result;
613 }
614
615 const uint16_t count = length - offset;
616
617 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN))
618 return GNUNET_NO;
619
620 kind_t kind;
621
622 decode_step(buffer, offset, &(message->header.timestamp));
623 decode_step(buffer, offset, &(message->header.sender_id));
624 decode_step(buffer, offset, &(message->header.previous));
625 decode_step(buffer, offset, &kind);
626
627 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
628
629 if (count < get_message_kind_size (message->header.kind))
630 return GNUNET_NO;
631
632 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
633
634 if (padding)
635 *padding = result;
636
637 return GNUNET_YES;
638}
639
640static int
641decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message, uint16_t length, const char *buffer)
642{
643 struct GNUNET_HashCode expected, hash;
644 uint16_t offset = sizeof(hash);
645
646 if (length < get_short_message_size (NULL, GNUNET_NO))
647 return GNUNET_NO;
648
649 GNUNET_memcpy(&hash, buffer, sizeof(hash));
650
651 GNUNET_CRYPTO_hash(
652 buffer + sizeof(hash),
653 length - sizeof(hash),
654 &expected
655 );
656
657 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
658 return GNUNET_NO;
659
660 kind_t kind;
661
662 decode_step(buffer, offset, &kind);
663
664 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
665
666 if (length < get_short_message_size (message, GNUNET_NO))
667 return GNUNET_NO;
668
669 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
670
671 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
672 return GNUNET_NO;
673
674 return GNUNET_YES;
675}
676
677void
678hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
679 struct GNUNET_HashCode *hash)
680{
681 GNUNET_assert((message) && (buffer) && (hash));
682
683 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
684 &(message->header.signature)
685 );
686
687 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
688}
689
690void
691sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
692 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego)
693{
694 GNUNET_assert((message) && (buffer) && (hash) && (ego));
695
696 struct GNUNET_MESSENGER_MessageSignature signature;
697
698 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
699 signature.purpose.size = htonl (sizeof(signature));
700
701 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
702 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
703
704 uint16_t offset = 0;
705 encode_step_signature(buffer, offset, &(message->header.signature), length);
706}
707
708int
709verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
710 const struct GNUNET_IDENTITY_PublicKey *key)
711{
712 GNUNET_assert((message) && (hash) && (key));
713
714 if (ntohl (key->type) != ntohl (message->header.signature.type))
715 return GNUNET_SYSERR;
716
717 struct GNUNET_MESSENGER_MessageSignature signature;
718
719 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
720 signature.purpose.size = htonl (sizeof(signature));
721
722 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
723
724 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
725 &(message->header.signature), key);
726}
727
728int
729encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key)
730{
731 GNUNET_assert((message) && (key));
732
733 struct GNUNET_MESSENGER_ShortMessage shortened;
734
735 fold_short_message (message, &shortened);
736
737 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
738 const uint16_t padded_length = calc_padded_length(length);
739
740 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
741 message->body.privacy.data = GNUNET_malloc(padded_length);
742 message->body.privacy.length = padded_length;
743
744 encode_short_message (&shortened, padded_length, message->body.privacy.data);
745
746 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key,
747 &(message->body.privacy.key),
748 message->body.privacy.data))
749 {
750 destroy_message_body (shortened.kind, &(shortened.body));
751 return GNUNET_YES;
752 }
753 else
754 {
755 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
756
757 unfold_short_message (&shortened, message);
758 return GNUNET_NO;
759 }
760}
761
762int
763decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key)
764{
765 GNUNET_assert((message) && (key));
766
767 if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length,
768 key, &(message->body.privacy.key),
769 message->body.privacy.data))
770 {
771 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
772
773 return GNUNET_NO;
774 }
775
776 struct GNUNET_MESSENGER_ShortMessage shortened;
777
778 if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data))
779 {
780 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
781
782 return GNUNET_NO;
783 }
784
785 unfold_short_message (&shortened, message);
786
787 return GNUNET_YES;
788}
789
790struct GNUNET_MQ_Envelope*
791pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
792 const struct GNUNET_MESSENGER_Ego *ego, int mode)
793{
794 GNUNET_assert(message);
795
796 if (ego)
797 message->header.signature.type = ego->priv.type;
798
799 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
800 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
801
802 struct GNUNET_MessageHeader *header;
803
804 const uint16_t length = get_message_size (message, GNUNET_YES);
805 const uint16_t padded_length = calc_padded_length(length);
806
807 struct GNUNET_MQ_Envelope *env;
808 char *buffer;
809
810 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
811 {
812 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
813
814 buffer = (char*) &(header[1]);
815 }
816 else
817 {
818 env = NULL;
819
820 buffer = GNUNET_malloc(padded_length);
821 }
822
823 encode_message (message, padded_length, buffer, GNUNET_YES);
824
825 if (hash)
826 {
827 hash_message (message, length, buffer, hash);
828
829 if (ego)
830 sign_message (message, length, buffer, hash, ego);
831 }
832
833 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
834 GNUNET_free(buffer);
835
836 return env;
837}
838
839int
840filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
841{
842 switch (message->header.kind)
843 {
844 case GNUNET_MESSENGER_KIND_INFO:
845 return GNUNET_SYSERR; // Reserved for connection handling only!
846 case GNUNET_MESSENGER_KIND_JOIN:
847 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
848 case GNUNET_MESSENGER_KIND_LEAVE:
849 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
850 case GNUNET_MESSENGER_KIND_NAME:
851 return GNUNET_YES;
852 case GNUNET_MESSENGER_KIND_KEY:
853 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
854 case GNUNET_MESSENGER_KIND_PEER:
855 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
856 case GNUNET_MESSENGER_KIND_ID:
857 return GNUNET_SYSERR; // Reserved for member id handling only!
858 case GNUNET_MESSENGER_KIND_MISS:
859 return GNUNET_SYSERR; // Reserved for connection handling only!
860 case GNUNET_MESSENGER_KIND_MERGE:
861 return GNUNET_YES;
862 case GNUNET_MESSENGER_KIND_REQUEST:
863 return GNUNET_YES;
864 case GNUNET_MESSENGER_KIND_INVITE:
865 return GNUNET_YES;
866 case GNUNET_MESSENGER_KIND_TEXT:
867 return GNUNET_YES;
868 case GNUNET_MESSENGER_KIND_FILE:
869 return GNUNET_YES;
870 case GNUNET_MESSENGER_KIND_PRIVATE:
871 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
872 case GNUNET_MESSENGER_KIND_DELETE:
873 return GNUNET_YES;
874 default:
875 return GNUNET_SYSERR;
876 }
877}
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h
deleted file mode 100644
index 7ce30dc92..000000000
--- a/src/messenger/messenger_api_message.h
+++ /dev/null
@@ -1,225 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_message.h
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_MESSAGE_H
27#define GNUNET_MESSENGER_API_MESSAGE_H
28
29#include "platform.h"
30#include "gnunet_crypto_lib.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_mq_lib.h"
33#include "gnunet_signatures.h"
34
35#include "gnunet_messenger_service.h"
36
37#include "messenger_api_ego.h"
38
39#define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - GNUNET_MIN_MESSAGE_SIZE)
40
41#define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
42#define GNUNET_MESSENGER_PADDING_LEVEL0 (512)
43#define GNUNET_MESSENGER_PADDING_LEVEL1 (4096)
44#define GNUNET_MESSENGER_PADDING_LEVEL2 (32768)
45
46/**
47 * Creates and allocates a new message with a specific <i>kind</i>.
48 *
49 * @param[in] kind Kind of message
50 * @return New message
51 */
52struct GNUNET_MESSENGER_Message*
53create_message (enum GNUNET_MESSENGER_MessageKind kind);
54
55/**
56 * Creates and allocates a copy of a given <i>message</i>.
57 *
58 * @param[in] message Message
59 * @return New message
60 */
61struct GNUNET_MESSENGER_Message*
62copy_message (const struct GNUNET_MESSENGER_Message *message);
63
64/**
65 * Destroys a message and frees its memory fully.
66 *
67 * @param[in/out] message Message
68 */
69void
70destroy_message (struct GNUNET_MESSENGER_Message *message);
71
72/**
73 * Returns if the message should be bound to a member session.
74 *
75 * @param[in] message Message
76 * @return #GNUNET_YES or #GNUNET_NO
77 */
78int
79is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
80
81/**
82 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>.
83 *
84 * @param[in] kind Kind of message
85 * @return Minimal size to encode
86 */
87uint16_t
88get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind);
89
90/**
91 * Returns the exact size in bytes to encode a given <i>message</i>.
92 *
93 * @param[in] message Message
94 * @param[in] encode_signature Flag to include signature
95 * @return Size to encode
96 */
97uint16_t
98get_message_size (const struct GNUNET_MESSENGER_Message *message,
99 int include_signature);
100
101/**
102 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes.
103 *
104 * @param[in] message Message
105 * @param[in] length Maximal length to encode
106 * @param[out] buffer Buffer
107 * @param[in] encode_signature Flag to include signature
108 */
109void
110encode_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
111 int include_signature);
112
113/**
114 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes.
115 *
116 * If the buffer is too small for a message of its decoded kind the function fails with
117 * resulting #GNUNET_NO after decoding only the messages header.
118 *
119 * On success the function returns #GNUNET_YES.
120 *
121 * @param[out] message Message
122 * @param[in] length Maximal length to decode
123 * @param[in] buffer Buffer
124 * @param[out] padding Padding
125 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
126 */
127int
128decode_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
129 int include_signature, uint16_t *padding);
130
131/**
132 * Calculates a <i>hash</i> of a given <i>buffer</i> with a <i>length</i> in bytes
133 * from a <i>message</i>.
134 *
135 * @param[in] message Message
136 * @param[in] length Length of buffer
137 * @param[in] buffer Buffer
138 * @param[out] hash Hash
139 */
140void
141hash_message (const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer,
142 struct GNUNET_HashCode *hash);
143
144/**
145 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature
146 * into the <i>buffer</i> as well.
147 *
148 * @param[in/out] message Message
149 * @param[in] length Length of buffer
150 * @param[out] buffer Buffer
151 * @param[in] hash Hash of message
152 * @param[in] ego EGO
153 */
154void
155sign_message (struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer,
156 const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Ego *ego);
157
158/**
159 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific
160 * public key. The function returns #GNUNET_OK if the signature was valid, otherwise
161 * #GNUNET_SYSERR.
162 *
163 * @param[in] message Message
164 * @param[in] hash Hash of message
165 * @param[in] key Public key of EGO
166 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
167 */
168int
169verify_message (const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
170 const struct GNUNET_IDENTITY_PublicKey *key);
171
172/**
173 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body
174 * and kind with the now private encrypted <i>message</i>. The function returns
175 * #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
176 *
177 * @param[in/out] message Message
178 * @param[in] key Public key of EGO
179 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
180 */
181int
182encrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PublicKey *key);
183
184/**
185 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body
186 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
187 * operation succeeded, otherwise #GNUNET_NO.
188 *
189 * @param[in/out] message Message
190 * @param[in] key Private key of EGO
191 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
192 */
193int
194decrypt_message (struct GNUNET_MESSENGER_Message *message, const struct GNUNET_IDENTITY_PrivateKey *key);
195
196#define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1
197#define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0
198
199/**
200 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i>
201 * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
202 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is
203 * not NULL.
204 *
205 * @param[out] message Message
206 * @param[out] hash Hash of message
207 * @param[in] ego EGO to sign
208 * @param[in] mode Mode of packing
209 * @return Envelope or NULL
210 */
211struct GNUNET_MQ_Envelope*
212pack_message (struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
213 const struct GNUNET_MESSENGER_Ego *ego, int mode);
214
215/**
216 * Returns if a specific kind of message should be sent by a client. The function returns
217 * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
218 * of messages which should not be sent manually at all.
219 *
220 * @param[in] message Message
221 */
222int
223filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
224
225#endif //GNUNET_MESSENGER_API_MESSAGE_H
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c
deleted file mode 100644
index 0d9237a2e..000000000
--- a/src/messenger/messenger_api_room.c
+++ /dev/null
@@ -1,341 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_room.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_room.h"
27
28#include "messenger_api_handle.h"
29
30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
32{
33 GNUNET_assert((handle) && (key));
34
35 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
36
37 room->handle = handle;
38 GNUNET_memcpy(&(room->key), key, sizeof(*key));
39
40 room->opened = GNUNET_NO;
41 room->contact_id = NULL;
42
43 init_list_tunnels (&(room->entries));
44
45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
46 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
47
48 return room;
49}
50
51static int
52iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value)
53{
54 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
55
56 destroy_message (entry->message);
57 GNUNET_free(entry);
58
59 return GNUNET_YES;
60}
61
62void
63destroy_room (struct GNUNET_MESSENGER_Room *room)
64{
65 GNUNET_assert(room);
66
67 clear_list_tunnels (&(room->entries));
68
69 if (room->messages)
70 {
71 GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL);
72
73 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
74 }
75
76 if (room->members)
77 GNUNET_CONTAINER_multishortmap_destroy (room->members);
78
79 if (room->contact_id)
80 GNUNET_free(room->contact_id);
81
82 GNUNET_free(room);
83}
84
85const struct GNUNET_MESSENGER_Message*
86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
87{
88 GNUNET_assert((room) && (hash));
89
90 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
91 room->messages, hash
92 );
93
94 return (entry? entry->message : NULL);
95}
96
97struct GNUNET_MESSENGER_Contact*
98get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
99{
100 GNUNET_assert((room) && (hash));
101
102 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
103 room->messages, hash
104 );
105
106 return (entry? entry->sender : NULL);
107}
108
109static struct GNUNET_MESSENGER_Contact*
110handle_join_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
111 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
112{
113 if (!sender)
114 {
115 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
116 struct GNUNET_HashCode context;
117
118 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
119
120 sender = get_store_contact(store, &context, &(message->body.join.key));
121 }
122
123 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
124 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
126 increase_contact_rc(sender);
127
128 return sender;
129}
130
131static void
132handle_leave_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
133 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
134{
135 if ((!sender) ||
136 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
137 return;
138
139 struct GNUNET_HashCode context;
140 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
141
142 if (GNUNET_YES == decrease_contact_rc(sender))
143 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
144}
145
146static void
147handle_name_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
148 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
149{
150 if (!sender)
151 return;
152
153 set_contact_name (sender, message->body.name.name);
154}
155
156static void
157handle_key_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
158 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
159{
160 if (!sender)
161 return;
162
163 struct GNUNET_HashCode context;
164 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
165
166 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
167
168 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
169}
170
171static void
172handle_id_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
173 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
174{
175 if ((!sender) ||
176 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
177 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
178 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
179 return;
180
181 struct GNUNET_HashCode context, next_context;
182 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
183 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
184
185 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
186
187 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
188}
189
190static void
191handle_miss_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
192 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
193{
194 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
195 {
196 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
197
198 if (match)
199 remove_from_list_tunnels (&(room->entries), match);
200 }
201}
202
203static void
204handle_delete_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
205 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
206{
207 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
208 room->messages, &(message->body.deletion.hash)
209 );
210
211 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
212 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.deletion.hash), entry)))
213 {
214 destroy_message (entry->message);
215 GNUNET_free(entry);
216 }
217}
218
219struct GNUNET_MESSENGER_Contact*
220handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
221 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
222{
223 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
224 return sender;
225
226 switch (message->header.kind)
227 {
228 case GNUNET_MESSENGER_KIND_JOIN:
229 sender = handle_join_message (room, sender, message, hash);
230 break;
231 case GNUNET_MESSENGER_KIND_LEAVE:
232 handle_leave_message (room, sender, message, hash);
233 break;
234 case GNUNET_MESSENGER_KIND_NAME:
235 handle_name_message (room, sender, message, hash);
236 break;
237 case GNUNET_MESSENGER_KIND_KEY:
238 handle_key_message (room, sender, message, hash);
239 break;
240 case GNUNET_MESSENGER_KIND_ID:
241 handle_id_message (room, sender, message, hash);
242 break;
243 case GNUNET_MESSENGER_KIND_MISS:
244 handle_miss_message (room, sender, message, hash);
245 break;
246 case GNUNET_MESSENGER_KIND_DELETE:
247 handle_delete_message (room, sender, message, hash);
248 break;
249 default:
250 break;
251 }
252
253 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
254
255 if (!entry)
256 return sender;
257
258 entry->sender = sender;
259 entry->message = copy_message (message);
260
261 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
263 {
264 destroy_message (entry->message);
265 GNUNET_free(entry);
266 }
267
268 return sender;
269}
270
271struct GNUNET_MESSENGER_MemberCall
272{
273 struct GNUNET_MESSENGER_Room *room;
274 GNUNET_MESSENGER_MemberCallback callback;
275 void *cls;
276};
277
278static int
279iterate_local_members (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
280{
281 struct GNUNET_MESSENGER_MemberCall *call = cls;
282 struct GNUNET_MESSENGER_Contact *contact = value;
283
284 return call->callback(call->cls, call->room, contact);
285}
286
287int
288iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
289 void* cls)
290{
291 GNUNET_assert(room);
292
293 if (!callback)
294 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
295
296 struct GNUNET_MESSENGER_MemberCall call;
297
298 call.room = room;
299 call.callback = callback;
300 call.cls = cls;
301
302 GNUNET_assert(callback);
303
304 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
305}
306
307struct GNUNET_MESSENGER_MemberFind
308{
309 const struct GNUNET_MESSENGER_Contact *contact;
310 int result;
311};
312
313static int
314iterate_find_member (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
315{
316 struct GNUNET_MESSENGER_MemberFind *find = cls;
317 struct GNUNET_MESSENGER_Contact *contact = value;
318
319 if (contact == find->contact)
320 {
321 find->result = GNUNET_YES;
322 return GNUNET_NO;
323 }
324
325 return GNUNET_YES;
326}
327
328int
329find_room_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact)
330{
331 GNUNET_assert(room);
332
333 struct GNUNET_MESSENGER_MemberFind find;
334
335 find.contact = contact;
336 find.result = GNUNET_NO;
337
338 GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_find_member, &find);
339
340 return find.result;
341}
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h
deleted file mode 100644
index 634052272..000000000
--- a/src/messenger/messenger_api_room.h
+++ /dev/null
@@ -1,140 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_room.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_MESSENGER_API_ROOM_H
27#define GNUNET_MESSENGER_API_ROOM_H
28
29#include "platform.h"
30#include "gnunet_container_lib.h"
31#include "gnunet_crypto_lib.h"
32
33#include "gnunet_messenger_service.h"
34
35#include "messenger_api_list_tunnels.h"
36#include "messenger_api_contact.h"
37#include "messenger_api_message.h"
38
39struct GNUNET_MESSENGER_RoomMessageEntry {
40 struct GNUNET_MESSENGER_Contact* sender;
41 struct GNUNET_MESSENGER_Message* message;
42};
43
44struct GNUNET_MESSENGER_Room
45{
46 struct GNUNET_MESSENGER_Handle *handle;
47 struct GNUNET_HashCode key;
48
49 int opened;
50
51 struct GNUNET_ShortHashCode *contact_id;
52
53 struct GNUNET_MESSENGER_ListTunnels entries;
54
55 struct GNUNET_CONTAINER_MultiHashMap *messages;
56 struct GNUNET_CONTAINER_MultiShortmap *members;
57};
58
59/**
60 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API.
61 *
62 * @param[in/out] handle Handle
63 * @param[in] key Key of room
64 * @return New room
65 */
66struct GNUNET_MESSENGER_Room*
67create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key);
68
69/**
70 * Destroys a room and frees its memory fully from the client API.
71 *
72 * @param[in/out] room Room
73 */
74void
75destroy_room (struct GNUNET_MESSENGER_Room *room);
76
77/**
78 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching
79 * message is found, NULL gets returned.
80 *
81 * @param[in] room Room
82 * @param[in] hash Hash of message
83 * @return Message or NULL
84 */
85const struct GNUNET_MESSENGER_Message*
86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
87
88/**
89 * Returns a messages sender locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no
90 * matching message is found, NULL gets returned.
91 *
92 * @param[in] room Room
93 * @param[in] hash Hash of message
94 * @return Contact of sender or NULL
95 */
96struct GNUNET_MESSENGER_Contact*
97get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash);
98
99/**
100 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
101 * members and its information. The function also stores the message in map locally for access afterwards.
102 *
103 * The contact of the message's sender could be updated or even created. It may not be freed or destroyed though!
104 * (The contact may still be in use for old messages...)
105 *
106 * @param[in/out] room Room
107 * @param[in/out] sender Contact of sender
108 * @param[in] message Message
109 * @param[in] hash Hash of message
110 * @return Contact of sender
111 */
112struct GNUNET_MESSENGER_Contact*
113handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
114 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
115
116/**
117 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
118 * <i>callback</i> with a custom closure.
119 *
120 * @param[in/out] room Room
121 * @param[in] callback Function called for each member
122 * @param[in/out] cls Closure
123 * @return Amount of members iterated
124 */
125int
126iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
127 void* cls);
128
129/**
130 * Checks through all members of a given <i>room</i> if a specific <i>contact</i> is found and
131 * returns a result depending on that.
132 *
133 * @param[in] room Room
134 * @param[in] contact
135 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
136 */
137int
138find_room_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact);
139
140#endif //GNUNET_MESSENGER_API_ROOM_H
diff --git a/src/messenger/messenger_api_util.c b/src/messenger/messenger_api_util.c
deleted file mode 100644
index 4ad00c45e..000000000
--- a/src/messenger/messenger_api_util.c
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_util.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_util.h"
27
28static void
29callback_close_channel (void *cls)
30{
31 struct GNUNET_CADET_Channel *channel = cls;
32
33 if (channel)
34 GNUNET_CADET_channel_destroy (channel);
35}
36
37void
38delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel)
39{
40 GNUNET_assert(channel);
41
42 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (),
43 GNUNET_SCHEDULER_PRIORITY_URGENT,
44 callback_close_channel, channel);
45}
46
47int
48generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members)
49{
50 GNUNET_assert(id);
51
52 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0);
53
54 do
55 {
56 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, id, sizeof(struct GNUNET_ShortHashCode));
57
58 if ((members) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (members, id)))
59 counter--;
60 else
61 break;
62 }
63 while (counter > 0);
64
65 if (counter)
66 return GNUNET_YES;
67
68 return GNUNET_NO;
69}
70
71const struct GNUNET_IDENTITY_PublicKey*
72get_anonymous_public_key ()
73{
74 static struct GNUNET_IDENTITY_PublicKey public_key;
75 static struct GNUNET_IDENTITY_Ego* ego = NULL;
76
77 if (!ego)
78 {
79 ego = GNUNET_IDENTITY_ego_get_anonymous();
80 GNUNET_IDENTITY_ego_get_public_key(ego, &public_key);
81 }
82
83 return &public_key;
84}
85
86void
87convert_messenger_key_to_port(const struct GNUNET_HashCode *key, struct GNUNET_HashCode *port)
88{
89 static uint32_t version_value = 0;
90 static struct GNUNET_HashCode version;
91
92 if (!version_value) {
93 version_value = (uint32_t) (GNUNET_MESSENGER_VERSION);
94 version_value = ((version_value >> 16) & 0xFFFF);
95 version_value = GNUNET_htole32(version_value);
96 GNUNET_CRYPTO_hash(&version_value, sizeof(version_value), &version);
97 }
98
99 GNUNET_CRYPTO_hash_sum(key, &version, port);
100}
diff --git a/src/messenger/messenger_api_util.h b/src/messenger/messenger_api_util.h
deleted file mode 100644
index af562a1e8..000000000
--- a/src/messenger/messenger_api_util.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 src/messenger/messenger_api_util.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H
27#define GNUNET_SERVICE_MESSENGER_UTIL_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_container_lib.h"
32#include "gnunet_crypto_lib.h"
33#include "gnunet_disk_lib.h"
34#include "gnunet_identity_service.h"
35#include "gnunet_messenger_service.h"
36
37/**
38 * Starts an urgent task to close a CADET channel asynchronously.
39 *
40 * @param[in/out] channel Channel
41 */
42void
43delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel);
44
45/**
46 * Tries to generate an unused member id and store it into the <i>id</i> parameter.
47 * A map containing all currently used member ids is used to check against.
48 *
49 * @param[out] id New member id
50 * @param[in] members Map of member ids
51 * @return #GNUNET_YES on success, #GNUNET_NO on failure
52 */
53int
54generate_free_member_id (struct GNUNET_ShortHashCode *id, const struct GNUNET_CONTAINER_MultiShortmap *members);
55
56/**
57 * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() without
58 * recalculating it every time.
59 *
60 * @return anonymous public key
61 */
62const struct GNUNET_IDENTITY_PublicKey*
63get_anonymous_public_key ();
64
65/**
66 * Converts a Messenger service key of a room to the specific port which
67 * gets used for the CADET channels.
68 *
69 * The port includes upper bits of the #GNUNET_MESSENGER_VERSION to
70 * reduce the chance of incompatible connections.
71 *
72 * @param[in] key Messenger service room key
73 * @param[out] port CADET service port
74 */
75void
76convert_messenger_key_to_port(const struct GNUNET_HashCode *key, struct GNUNET_HashCode *port);
77
78#endif //GNUNET_SERVICE_MESSENGER_UTIL_H
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
deleted file mode 100644
index fb3e3e1bc..000000000
--- a/src/messenger/test_messenger.c
+++ /dev/null
@@ -1,177 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 * @file messenger/test_messenger.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_messenger_service.h"
30
31/**
32 * How long until we really give up on a particular testcase portion?
33 */
34#define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
35 60)
36
37/**
38 * How long until we give up on any particular operation (and retry)?
39 */
40#define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
41
42#define TESTER_NAME "tester"
43
44static int status = 1;
45
46static struct GNUNET_SCHEDULER_Task *die_task = NULL;
47static struct GNUNET_SCHEDULER_Task *op_task = NULL;
48
49struct GNUNET_MESSENGER_Handle *messenger = NULL;
50
51static void
52end (void *cls)
53{
54 die_task = NULL;
55
56 if (op_task)
57 {
58 GNUNET_SCHEDULER_cancel (op_task);
59 op_task = NULL;
60 }
61
62 if (messenger)
63 {
64 GNUNET_MESSENGER_disconnect (messenger);
65 messenger = NULL;
66 }
67
68 status = 0;
69}
70
71static void
72end_badly (void *cls)
73{
74 fprintf (stderr, "Testcase failed (timeout).\n");
75
76 end (NULL);
77 status = 1;
78}
79
80static void
81end_operation (void *cls)
82{
83 op_task = NULL;
84
85 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
86
87 if (die_task)
88 GNUNET_SCHEDULER_cancel (die_task);
89
90 end (NULL);
91 status = 1;
92}
93
94static int identity_counter = 0;
95
96/**
97 * Function called when an identity is retrieved.
98 *
99 * @param cls Closure
100 * @param handle Handle of messenger service
101 */
102static void
103on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
104{
105 if (op_task)
106 {
107 GNUNET_SCHEDULER_cancel (op_task);
108 op_task = NULL;
109 }
110
111 const char *name = GNUNET_MESSENGER_get_name (handle);
112
113 if (0 != strcmp (name, TESTER_NAME))
114 {
115 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name");
116 return;
117 }
118
119 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
120
121 if (((!identity_counter) && (key)) || ((identity_counter) && (!key)))
122 {
123 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key");
124 return;
125 }
126
127 if (identity_counter)
128 {
129 GNUNET_MESSENGER_disconnect (handle);
130
131 op_task = NULL;
132 messenger = NULL;
133
134 if (die_task)
135 GNUNET_SCHEDULER_cancel (die_task);
136
137 die_task = GNUNET_SCHEDULER_add_now (&end, NULL);
138 return;
139 }
140
141 GNUNET_MESSENGER_update (messenger);
142 identity_counter++;
143}
144
145/**
146 * Main function for testcase.
147 *
148 * @param cls Closure
149 * @param cfg Configuration
150 * @param peer Peer for testing
151 */
152static void
153run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
154{
155 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
156
157 identity_counter = 0;
158
159 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
160 messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL);
161}
162
163/**
164 * The main function.
165 *
166 * @param argc number of arguments from the command line
167 * @param argv command line arguments
168 * @return 0 ok, 1 on error
169 */
170int
171main (int argc, char **argv)
172{
173 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
174 return 1;
175
176 return status;
177}
diff --git a/src/messenger/test_messenger_adapt.c b/src/messenger/test_messenger_adapt.c
deleted file mode 100644
index 90e8ac28d..000000000
--- a/src/messenger/test_messenger_adapt.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_adapt.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 5, 1, 2, 3, 6, 7, 8, 4 };
39 unsigned int stages [] = { 0x21, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_adapt", &cfg);
47}
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c
deleted file mode 100644
index a70121a30..000000000
--- a/src/messenger/test_messenger_anonymous.c
+++ /dev/null
@@ -1,169 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 * @file messenger/test_messenger_anonymous.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25#include <stdio.h>
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_messenger_service.h"
30
31/**
32 * How long until we really give up on a particular testcase portion?
33 */
34#define TOTAL_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, \
35 60)
36
37/**
38 * How long until we give up on any particular operation (and retry)?
39 */
40#define BASE_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
41
42static int status = 1;
43
44static struct GNUNET_SCHEDULER_Task *die_task = NULL;
45static struct GNUNET_SCHEDULER_Task *op_task = NULL;
46
47struct GNUNET_MESSENGER_Handle *messenger = NULL;
48
49static void
50end (void *cls)
51{
52 die_task = NULL;
53
54 if (op_task)
55 {
56 GNUNET_SCHEDULER_cancel (op_task);
57 op_task = NULL;
58 }
59
60 if (messenger)
61 {
62 GNUNET_MESSENGER_disconnect (messenger);
63 messenger = NULL;
64 }
65
66 status = 0;
67}
68
69static void
70end_badly (void *cls)
71{
72 fprintf (stderr, "Testcase failed (timeout).\n");
73
74 end (NULL);
75 status = 1;
76}
77
78static void
79end_operation (void *cls)
80{
81 op_task = NULL;
82
83 fprintf (stderr, "Testcase failed (operation: '%s').\n", cls ? (const char*) cls : "unknown");
84
85 if (die_task)
86 GNUNET_SCHEDULER_cancel (die_task);
87
88 end (NULL);
89 status = 1;
90}
91
92/**
93 * Function called when an identity is retrieved.
94 *
95 * @param cls Closure
96 * @param handle Handle of messenger service
97 */
98static void
99on_identity (void *cls, struct GNUNET_MESSENGER_Handle *handle)
100{
101 if (op_task)
102 {
103 GNUNET_SCHEDULER_cancel (op_task);
104 op_task = NULL;
105 }
106
107 const char *name = GNUNET_MESSENGER_get_name (handle);
108
109 if (NULL != name)
110 {
111 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name-anonymous");
112 return;
113 }
114
115 if (GNUNET_SYSERR != GNUNET_MESSENGER_update (handle))
116 {
117 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail");
118 return;
119 }
120
121 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
122
123 if (key)
124 {
125 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous");
126 return;
127 }
128
129 GNUNET_MESSENGER_disconnect (handle);
130
131 messenger = NULL;
132
133 if (die_task)
134 GNUNET_SCHEDULER_cancel (die_task);
135
136 die_task = GNUNET_SCHEDULER_add_now (&end, NULL);
137}
138
139/**
140 * Main function for testcase.
141 *
142 * @param cls Closure
143 * @param cfg Configuration
144 * @param peer Peer for testing
145 */
146static void
147run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, struct GNUNET_TESTING_Peer *peer)
148{
149 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
150
151 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
152 messenger = GNUNET_MESSENGER_connect (cfg, NULL, &on_identity, NULL, NULL, NULL);
153}
154
155/**
156 * The main function.
157 *
158 * @param argc number of arguments from the command line
159 * @param argv command line arguments
160 * @return 0 ok, 1 on error
161 */
162int
163main (int argc, char **argv)
164{
165 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
166 return 1;
167
168 return status;
169}
diff --git a/src/messenger/test_messenger_api.conf b/src/messenger/test_messenger_api.conf
deleted file mode 100644
index 968f56f6d..000000000
--- a/src/messenger/test_messenger_api.conf
+++ /dev/null
@@ -1,47 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf
3
4[testbed]
5HOSTNAME = localhost
6OVERLAY_TOPOLOGY = CLIQUE
7
8[arm]
9GLOBAL_POSTFIX = -l $GNUNET_CACHE_HOME/{}-logs -L verbose
10
11[transport]
12IMMEDIATE_START = YES
13
14[core]
15START_ON_DEMAND = YES
16IMMEDIATE_START = YES
17USE_EPHEMERAL_KEYS = NO
18
19[PATHS]
20GNUNET_TEST_HOME = $GNUNET_TMP/test-messenger-api/
21
22[peerinfo]
23NO_IO = YES
24
25[cadet]
26START_ON_DEMAND = YES
27REFRESH_CONNECTION_TIME = 1 s
28ID_ANNOUNCE_TIME = 5 s
29CONNECT_TIMEOUT = 30 s
30DEFAULT_TTL = 16
31DHT_REPLICATION_LEVEL = 10
32MAX_TUNNELS = 10
33MAX_CONNECTIONS = 10
34MAX_MSGS_QUEUE = 20
35DISABLE_TRY_CONNECT = YES
36REKEY_PERIOD = 2 s
37
38[identity]
39START_ON_DEMAND = YES
40
41[messenger]
42START_ON_DEMAND = YES
43
44[nat]
45ENABLE_UPNP = NO
46RETURN_LOCAL_ADDRESSES = YES
47IMMEDIATE_START = NO \ No newline at end of file
diff --git a/src/messenger/test_messenger_async_client.c b/src/messenger/test_messenger_async_client.c
deleted file mode 100644
index 1067b9a6d..000000000
--- a/src/messenger/test_messenger_async_client.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_async_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_async_p2p.c b/src/messenger/test_messenger_async_p2p.c
deleted file mode 100644
index d827aae16..000000000
--- a/src/messenger/test_messenger_async_p2p.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_async_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x30, 0x30 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_async_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_growth.c b/src/messenger/test_messenger_growth.c
deleted file mode 100644
index 3781f3ee5..000000000
--- a/src/messenger/test_messenger_growth.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_growth.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_growth", &cfg);
47}
diff --git a/src/messenger/test_messenger_ring.c b/src/messenger/test_messenger_ring.c
deleted file mode 100644
index 07cfd0c47..000000000
--- a/src/messenger/test_messenger_ring.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_ring.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 8, 1, 2, 3, 4, 5, 6, 7 };
39 unsigned int stages [] = { 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_ring", &cfg);
47}
diff --git a/src/messenger/test_messenger_server.c b/src/messenger/test_messenger_server.c
deleted file mode 100644
index 1cf2fcc27..000000000
--- a/src/messenger/test_messenger_server.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_server.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
39 unsigned int stages [] = { 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 8;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_server", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_client.c b/src/messenger/test_messenger_sync_client.c
deleted file mode 100644
index 99f26b018..000000000
--- a/src/messenger/test_messenger_sync_client.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_sync_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x01, 0x20 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_sync_p2p.c b/src/messenger/test_messenger_sync_p2p.c
deleted file mode 100644
index 77ce280a1..000000000
--- a/src/messenger/test_messenger_sync_p2p.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_sync_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x21, 0x21 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_sync_p2p", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_client.c b/src/messenger/test_messenger_worst_client.c
deleted file mode 100644
index 63826631c..000000000
--- a/src/messenger/test_messenger_worst_client.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_worst_client.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 0, 1 };
39 unsigned int stages [] = { 0x10, 0x02 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_client", &cfg);
47}
diff --git a/src/messenger/test_messenger_worst_p2p.c b/src/messenger/test_messenger_worst_p2p.c
deleted file mode 100644
index c89288eea..000000000
--- a/src/messenger/test_messenger_worst_p2p.c
+++ /dev/null
@@ -1,47 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/test_messenger_worst_p2p.c
22 * @author Tobias Frisch
23 * @brief Test for the messenger service using cadet API.
24 */
25
26#include "testing_messenger_setup.h"
27
28/**
29 * The main function.
30 *
31 * @param argc number of arguments from the command line
32 * @param argv command line arguments
33 * @return 0 ok, 1 on error
34 */
35int
36main (int argc, char **argv)
37{
38 unsigned int doors [] = { 2, 1 };
39 unsigned int stages [] = { 0x12, 0x12 };
40
41 struct test_configuration cfg;
42 cfg.count = 2;
43 cfg.doors = doors;
44 cfg.stages = stages;
45
46 return GNUNET_run_messenger_setup ("test_messenger_worst_p2p", &cfg);
47}
diff --git a/src/messenger/testing_messenger_barrier.c b/src/messenger/testing_messenger_barrier.c
deleted file mode 100644
index 618d255b7..000000000
--- a/src/messenger/testing_messenger_barrier.c
+++ /dev/null
@@ -1,170 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#include "testing_messenger_barrier.h"
27
28struct GNUNET_BarrierHandle
29{
30 unsigned int requirement;
31 GNUNET_BarrierStatusCallback cb;
32 void *cls;
33
34 struct GNUNET_BarrierWaitHandle *head;
35 struct GNUNET_BarrierWaitHandle *tail;
36
37 struct GNUNET_SCHEDULER_Task* task;
38};
39
40struct GNUNET_BarrierHandle*
41GNUNET_init_barrier (unsigned int requirement,
42 GNUNET_BarrierStatusCallback cb,
43 void *cb_cls)
44{
45 if (0 == requirement)
46 return NULL;
47
48 struct GNUNET_BarrierHandle *barrier = GNUNET_new(struct GNUNET_BarrierHandle);
49
50 if (!barrier)
51 return NULL;
52
53 barrier->requirement = requirement;
54 barrier->cb = cb;
55 barrier->cls = cb_cls;
56 barrier->head = NULL;
57 barrier->tail = NULL;
58 barrier->task = NULL;
59
60 return barrier;
61}
62
63static void
64exit_status (struct GNUNET_BarrierHandle *barrier, int status);
65
66static void
67cancel_barrier (void *cls)
68{
69 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR);
70}
71
72static void
73complete_barrier (void *cls)
74{
75 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK);
76}
77
78void
79GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier)
80{
81 if ((!barrier) || (barrier->task))
82 return;
83
84 barrier->task = GNUNET_SCHEDULER_add_now(cancel_barrier, barrier);
85}
86
87struct GNUNET_BarrierWaitHandle
88{
89 GNUNET_BarrierWaitStatusCallback cb;
90 void *cls;
91
92 struct GNUNET_BarrierWaitHandle *prev;
93 struct GNUNET_BarrierWaitHandle *next;
94
95 struct GNUNET_BarrierHandle *barrier;
96};
97
98static void
99exit_status (struct GNUNET_BarrierHandle *barrier, int status)
100{
101 struct GNUNET_BarrierWaitHandle *waiting = barrier->head;
102 while (waiting)
103 {
104 struct GNUNET_BarrierWaitHandle *current = waiting;
105
106 if (current->cb)
107 current->cb(current->cls, current, status);
108
109 waiting = waiting->next;
110
111 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, current);
112 GNUNET_free(current);
113 }
114
115 if (barrier->cb)
116 barrier->cb(barrier->cls, barrier, status);
117
118 GNUNET_free(barrier);
119}
120
121struct GNUNET_BarrierWaitHandle*
122GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
123 GNUNET_BarrierWaitStatusCallback cb,
124 void *cb_cls)
125{
126 if ((!barrier) || (0 == barrier->requirement))
127 return NULL;
128
129 struct GNUNET_BarrierWaitHandle *waiting = GNUNET_new(struct GNUNET_BarrierWaitHandle);
130
131 if (!waiting)
132 return NULL;
133
134 waiting->cb = cb;
135 waiting->cls = cb_cls;
136 waiting->prev = NULL;
137 waiting->next = NULL;
138 waiting->barrier = barrier;
139
140 GNUNET_CONTAINER_DLL_insert_tail(barrier->head, barrier->tail, waiting);
141 barrier->requirement--;
142
143 if ((barrier->requirement == 0) && (!barrier->task))
144 barrier->task = GNUNET_SCHEDULER_add_now(complete_barrier, barrier);
145
146 return waiting;
147}
148
149void
150GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting)
151{
152 if (!waiting)
153 return;
154
155 struct GNUNET_BarrierHandle *barrier = waiting->barrier;
156
157 if (!barrier)
158 return;
159
160 if ((barrier->requirement == 0) && (barrier->task))
161 {
162 GNUNET_SCHEDULER_cancel(barrier->task);
163 barrier->task = NULL;
164 }
165
166 barrier->requirement++;
167 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, waiting);
168
169 GNUNET_free(waiting);
170}
diff --git a/src/messenger/testing_messenger_barrier.h b/src/messenger/testing_messenger_barrier.h
deleted file mode 100644
index 3062a393a..000000000
--- a/src/messenger/testing_messenger_barrier.h
+++ /dev/null
@@ -1,131 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/testing_messenger_barrier.h
22 * @author Tobias Frisch
23 * @brief Pseudo-barriers for simple event handling
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_BARRIER_H_
27#define GNUNET_TESTING_MESSENGER_BARRIER_H_
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31
32/**
33 * Handle for pseudo-barrier
34 */
35struct GNUNET_BarrierHandle;
36
37
38/**
39 * Functions of this type are to be given as callback argument to
40 * GNUNET_init_barrier(). The callback will be called when status
41 * information is available for the pseudo-barrier.
42 *
43 * @param cls the closure given to GNUNET_init_barrier()
44 * @param barrier the pseudo-barrier handle
45 * @param status status of the pseudo-barrier. The pseudo-barrier is removed
46 * once it has been crossed or an error occurs while processing it.
47 * Therefore it is invalid to call GNUNET_cancel_barrier() on a
48 * crossed or errored pseudo-barrier.
49 */
50typedef void
51(*GNUNET_BarrierStatusCallback) (void *cls,
52 struct GNUNET_BarrierHandle *barrier,
53 int status);
54
55
56/**
57 * Initialise a pseudo-barrier and call the given callback when the required
58 * amount of peers (requirement) reach the pseudo-barrier OR upon error.
59 *
60 * @param requirement the amount of peers that is required to reach the
61 * pseudo-barrier. Peers signal reaching a pseudo-barrier by calling
62 * GNUNET_wait_barrier().
63 * @param cb the callback to call when the pseudo-barrier is reached or upon
64 * error. Can be NULL.
65 * @param cls closure for the above callback
66 * @return pseudo-barrier handle; NULL upon error
67 */
68struct GNUNET_BarrierHandle*
69GNUNET_init_barrier (unsigned int requirement,
70 GNUNET_BarrierStatusCallback cb,
71 void *cb_cls);
72
73
74/**
75 * Cancel a pseudo-barrier.
76 *
77 * @param barrier the pseudo-barrier handle
78 */
79void
80GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier);
81
82
83/**
84 * Handle for pseudo-barrier wait
85 */
86struct GNUNET_BarrierWaitHandle;
87
88
89/**
90 * Functions of this type are to be given as acallback argument to
91 * GNUNET_wait_barrier(). The callback will be called when the pseudo-barrier
92 * corresponding given in GNUNET_wait_barrier() is crossed or cancelled.
93 *
94 * @param cls closure pointer given to GNUNET_wait_barrier()
95 * @param waiting the pseudo-barrier wait handle
96 * @param status #GNUNET_SYSERR in case of error while waiting for the
97 * pseudo-barrier; #GNUNET_OK if the pseudo-barrier is crossed
98 */
99typedef void
100(*GNUNET_BarrierWaitStatusCallback) (void *cls,
101 struct GNUNET_BarrierWaitHandle *waiting,
102 int status);
103
104
105/**
106 * Wait for a pseudo-barrier to be crossed. This function should be called for
107 * the peers which have been started by the testbed.
108 *
109 * @param barrier the pseudo-barrier handle
110 * @param cb the pseudo-barrier wait callback
111 * @param cls the closure for the above callback
112 * @return pseudo-barrier wait handle which can be used to cancel the waiting
113 * at anytime before the callback is called. NULL upon error.
114 */
115struct GNUNET_BarrierWaitHandle*
116GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
117 GNUNET_BarrierWaitStatusCallback cb,
118 void *cb_cls);
119
120
121/**
122 * Cancel a pseudo-barrier wait handle. Should not be called in or after the
123 * callback given to GNUNET_wait_barrier() has been called.
124 *
125 * @param waiting the pseudo-barrier wait handle
126 */
127void
128GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting);
129
130
131#endif /* GNUNET_TESTING_MESSENGER_BARRIER_H_ */
diff --git a/src/messenger/testing_messenger_setup.c b/src/messenger/testing_messenger_setup.c
deleted file mode 100644
index 98241fa08..000000000
--- a/src/messenger/testing_messenger_setup.c
+++ /dev/null
@@ -1,528 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 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 * @file messenger/testing_messenger_barrier.c
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#include "testing_messenger_setup.h"
27
28#include <stdio.h>
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_testbed_logger_service.h"
32#include "gnunet_testbed_service.h"
33#include "gnunet_testing_lib.h"
34#include "gnunet_messenger_service.h"
35#include "testing_messenger_barrier.h"
36
37#define TEST_ROOM "test"
38#define TEST_NAME "tester"
39
40struct test_properties;
41
42struct test_peer {
43 struct test_properties *props;
44 unsigned int num;
45
46 struct GNUNET_SCHEDULER_Task *op_task;
47 struct GNUNET_TESTBED_Operation *op;
48
49 struct GNUNET_TESTBED_Peer *peer;
50 struct GNUNET_PeerIdentity peer_id;
51 struct GNUNET_BarrierWaitHandle *wait;
52
53 struct GNUNET_MESSENGER_Handle *handle;
54 struct GNUNET_MESSENGER_Room *room;
55
56 unsigned int peer_messages;
57
58 const char *message;
59};
60
61struct test_properties {
62 const struct test_configuration *cfg;
63
64 unsigned int num_hosts;
65
66 struct GNUNET_SCHEDULER_Task *die_task;
67 struct GNUNET_SCHEDULER_Task *end_task;
68
69 struct GNUNET_BarrierHandle *barrier;
70
71 struct test_peer *peers;
72 unsigned int num_peer;
73
74 int status;
75};
76
77static void
78shutdown_cb (void *cls)
79{
80 struct test_properties *properties = cls;
81
82
83 for (unsigned int i = 0; i < properties->num_peer; i++)
84 {
85 struct test_peer *peer = &properties->peers[i];
86
87 GNUNET_assert(peer != NULL);
88
89 if (peer->op_task)
90 GNUNET_SCHEDULER_cancel(peer->op_task);
91
92 peer->op_task = NULL;
93
94 if (peer->op)
95 GNUNET_TESTBED_operation_done (peer->op);
96
97 peer->op = NULL;
98
99 if (peer->wait)
100 GNUNET_cancel_wait_barrier(peer->wait);
101
102 peer->wait = NULL;
103
104 if (peer->room)
105 GNUNET_MESSENGER_close_room (peer->room);
106
107 peer->room = NULL;
108
109 if (peer->handle)
110 GNUNET_MESSENGER_disconnect (peer->handle);
111
112 peer->handle = NULL;
113 }
114
115 if (properties->die_task)
116 GNUNET_SCHEDULER_cancel(properties->die_task);
117
118 properties->die_task = NULL;
119 properties->end_task = NULL;
120
121 if (properties->barrier)
122 GNUNET_cancel_barrier(properties->barrier);
123
124 properties->barrier = NULL;
125}
126
127
128
129static void
130end_cb (void *cls)
131{
132 struct test_properties *properties = cls;
133
134 GNUNET_assert(properties != NULL);
135
136 properties->die_task = NULL;
137
138 int status = 0;
139
140 for (unsigned int i = 0; i < properties->num_peer; i++)
141 {
142 struct test_peer *peer = &properties->peers[i];
143
144 GNUNET_assert(peer != NULL);
145
146 const int members = GNUNET_MESSENGER_iterate_members(peer->room, NULL, NULL);
147
148 GNUNET_assert (members >= 0);
149
150 if (peer->props->num_peer != (unsigned int) members)
151 {
152 fprintf (stderr, "Testcase failed (members: %d/%u).\n", members, peer->props->num_peer);
153 status = 1;
154 break;
155 }
156 }
157
158 GNUNET_SCHEDULER_shutdown ();
159
160 properties->status = status;
161}
162
163static void
164end_badly_cb (void *cls)
165{
166 struct test_properties *properties = cls;
167
168 GNUNET_assert(properties != NULL);
169
170 fprintf (stderr, "Testcase failed (timeout).\n");
171
172 end_cb (properties);
173
174 properties->status = 1;
175}
176
177static void
178end_operation_cb (void *cls)
179{
180 struct test_peer *peer = cls;
181
182 GNUNET_assert(peer != NULL);
183
184 peer->op_task = NULL;
185
186 fprintf (stderr, "Testcase failed (operation: '%s').\n", peer->message);
187
188 GNUNET_SCHEDULER_shutdown ();
189}
190
191static void
192end_error_cb (void *cls)
193{
194 struct test_peer *peer = cls;
195
196 GNUNET_assert(peer != NULL);
197
198 peer->op_task = NULL;
199
200 fprintf (stderr, "Testcase failed (error: '%s').\n", peer->message);
201 GNUNET_free (peer);
202
203 GNUNET_SCHEDULER_shutdown ();
204}
205
206static void
207barrier2_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
208{
209 struct test_peer *peer = cls;
210
211 GNUNET_assert(peer != NULL);
212
213 if (peer->wait == waiting)
214 peer->wait = NULL;
215}
216
217static void
218barrier_wait_cb (void *cls, struct GNUNET_BarrierWaitHandle *waiting, int status)
219{
220 struct test_peer *peer = cls;
221
222 GNUNET_assert(peer != NULL);
223
224 if (peer->wait == waiting)
225 peer->wait = NULL;
226
227 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x02))
228 {
229 unsigned int door = peer->props->cfg->doors[peer->num - 1];
230
231 if (door == 0)
232 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
233 else
234 door = door - 1;
235
236 struct GNUNET_HashCode hash;
237 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
238
239 struct GNUNET_MESSENGER_Room *room;
240 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
241
242 if (peer->room)
243 GNUNET_assert(room == peer->room);
244 else
245 GNUNET_assert(room != NULL);
246
247 peer->room = room;
248 }
249}
250
251/**
252 * Function called whenever a message is received or sent.
253 *
254 * @param cls Closure
255 * @param room Room
256 * @param sender Sender
257 * @param message Message
258 * @param hash Hash of message
259 * @param flags Flags of message
260 */
261static void
262on_message (void *cls, struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *sender,
263 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash,
264 enum GNUNET_MESSENGER_MessageFlags flags)
265{
266 struct test_peer *peer = cls;
267
268 GNUNET_assert(peer != NULL);
269
270 fprintf (stderr, "Peer: %s; [%s] Message: %s (%s)\n",
271 GNUNET_i2s(&(peer->peer_id)),
272 GNUNET_sh2s(&(message->header.sender_id)),
273 GNUNET_MESSENGER_name_of_kind(message->header.kind),
274 GNUNET_h2s(hash));
275
276 if (GNUNET_MESSENGER_KIND_PEER == message->header.kind)
277 peer->peer_messages++;
278
279 if (peer->props->num_hosts == peer->peer_messages)
280 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier2_wait_cb, peer);
281 else if (peer->props->num_hosts < peer->peer_messages)
282 {
283 if (peer->wait)
284 GNUNET_cancel_wait_barrier(peer->wait);
285
286 peer->wait = NULL;
287
288 if (peer->op_task)
289 GNUNET_SCHEDULER_cancel(peer->op_task);
290
291 peer->message = "peer";
292 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
293 }
294}
295
296static void
297second_stage (void *cls)
298{
299 struct test_peer *peer = cls;
300
301 GNUNET_assert(peer != NULL);
302
303 peer->op_task = NULL;
304
305 struct GNUNET_HashCode hash;
306 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
307
308 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x10))
309 {
310 struct GNUNET_MESSENGER_Room *room;
311 room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
312
313 if (peer->room)
314 GNUNET_assert(room == peer->room);
315 else
316 GNUNET_assert(room != NULL);
317
318 peer->room = room;
319 }
320
321 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x20))
322 {
323 unsigned int door = peer->props->cfg->doors[peer->num - 1];
324
325 if (door == 0)
326 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
327 else
328 door = door - 1;
329
330 struct GNUNET_MESSENGER_Room *room;
331 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
332
333 if (peer->room)
334 GNUNET_assert(room == peer->room);
335 else
336 GNUNET_assert(room != NULL);
337
338 peer->room = room;
339 }
340}
341
342static void
343on_peer (void *cb_cls, struct GNUNET_TESTBED_Operation *op, const struct GNUNET_TESTBED_PeerInformation *pinfo,
344 const char *emsg)
345{
346 struct test_peer *peer = cb_cls;
347
348 GNUNET_assert(peer != NULL);
349
350 if (emsg)
351 {
352 peer->message = GNUNET_strdup(emsg);
353 peer->op_task = GNUNET_SCHEDULER_add_now (&end_error_cb, peer);
354 return;
355 }
356
357 if (!pinfo)
358 {
359 peer->message = "info";
360 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
361 return;
362 }
363
364 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
365 {
366 peer->message = "config";
367 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
368 return;
369 }
370
371 peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, NULL, &on_message, peer);
372
373 GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_get_peer_identity(
374 pinfo->result.cfg, &(peer->peer_id)
375 ));
376
377 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x01))
378 {
379 struct GNUNET_HashCode hash;
380 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
381
382 peer->room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
383
384 GNUNET_assert(peer->room != NULL);
385 }
386 else
387 peer->room = NULL;
388
389 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier_wait_cb, peer);
390}
391
392/**
393 * Main function for a peer of the testcase.
394 *
395 * @param cls Closure
396 * @param event Information about the event
397 */
398static void
399run (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
400{
401 struct test_properties *properties = cls;
402
403 GNUNET_assert(properties != NULL);
404
405 if (GNUNET_TESTBED_ET_PEER_START != event->type)
406 {
407 fprintf (stderr, "Testcase failed (operation: 'start').\n");
408
409 GNUNET_SCHEDULER_shutdown ();
410 return;
411 }
412
413 struct test_peer *peer = &(properties->peers[properties->num_peer++]);
414
415 peer->props = properties;
416 peer->num = properties->num_peer;
417
418 peer->peer = event->details.peer_start.peer;
419 peer->op = GNUNET_TESTBED_peer_get_information (peer->peer, GNUNET_TESTBED_PIT_CONFIGURATION, on_peer, peer);
420}
421
422static void
423barrier2_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
424{
425 struct test_properties *properties = cls;
426
427 GNUNET_assert(properties != NULL);
428
429 if (properties->barrier == barrier)
430 properties->barrier = NULL;
431
432 if (GNUNET_SYSERR == status)
433 {
434 fprintf (stderr, "Testcase failed (operation: 'barrier2').\n");
435
436 GNUNET_SCHEDULER_shutdown ();
437 return;
438 }
439 else if (GNUNET_OK == status)
440 {
441 if (properties->die_task)
442 GNUNET_SCHEDULER_cancel(properties->die_task);
443
444 properties->die_task = GNUNET_SCHEDULER_add_delayed (
445 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count),
446 &end_cb, properties
447 );
448 }
449}
450
451static void
452barrier_cb (void *cls, struct GNUNET_BarrierHandle *barrier, int status)
453{
454 struct test_properties *properties = cls;
455
456 GNUNET_assert(properties != NULL);
457
458 if (properties->barrier == barrier)
459 properties->barrier = NULL;
460 else if (!properties->barrier)
461 return;
462
463 if (properties->num_peer != properties->cfg->count)
464 {
465 fprintf (stderr, "Testcase failed (operation: 'process').\n");
466
467 GNUNET_SCHEDULER_shutdown ();
468 return;
469 }
470
471 if (GNUNET_SYSERR == status)
472 {
473 fprintf (stderr, "Testcase failed (operation: 'barrier').\n");
474
475 GNUNET_SCHEDULER_shutdown ();
476 return;
477 }
478 else if (GNUNET_OK == status)
479 {
480 properties->barrier = GNUNET_init_barrier (properties->num_peer, &barrier2_cb, properties);
481
482 for (unsigned int i = 0; i < properties->num_peer; i++)
483 properties->peers[i].op_task = GNUNET_SCHEDULER_add_now (&second_stage, &(properties->peers[i]));
484 }
485}
486
487static void
488init (void *cls, struct GNUNET_TESTBED_RunHandle *h, unsigned int num_peers, struct GNUNET_TESTBED_Peer **peers,
489 unsigned int links_succeeded, unsigned int links_failed)
490{
491 struct test_properties *properties = cls;
492
493 GNUNET_assert(properties != NULL);
494
495 properties->end_task = GNUNET_SCHEDULER_add_shutdown(&shutdown_cb, properties);
496 properties->die_task = GNUNET_SCHEDULER_add_delayed (
497 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count * 5),
498 &end_badly_cb, properties
499 );
500}
501
502int
503GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg)
504{
505 struct test_properties properties;
506 memset(&properties, 0, sizeof(properties));
507
508 properties.cfg = cfg;
509 properties.peers = GNUNET_new_array(cfg->count, struct test_peer);
510
511 for (unsigned int i = 0; i < cfg->count; i++)
512 if (0 != (cfg->stages[i] & 0x11))
513 properties.num_hosts++;
514
515 properties.status = 1;
516 properties.barrier = GNUNET_init_barrier (cfg->count, &barrier_cb, &properties);
517
518 if (GNUNET_OK != GNUNET_TESTBED_test_run (test_name, "test_messenger_api.conf",
519 cfg->count,
520 (1LL << GNUNET_TESTBED_ET_PEER_START),
521 &run, &properties,
522 &init, &properties))
523 return 1;
524
525 GNUNET_free(properties.peers);
526
527 return properties.status;
528}
diff --git a/src/messenger/testing_messenger_setup.h b/src/messenger/testing_messenger_setup.h
deleted file mode 100644
index 5e6b5d461..000000000
--- a/src/messenger/testing_messenger_setup.h
+++ /dev/null
@@ -1,39 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021 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 * @file messenger/testing_messenger_setup.h
22 * @author Tobias Frisch
23 * @brief A simple test-case setup for the messenger service
24 */
25
26#ifndef GNUNET_TESTING_MESSENGER_SETUP_H_
27#define GNUNET_TESTING_MESSENGER_SETUP_H_
28
29struct test_configuration
30{
31 unsigned int count;
32 unsigned int *doors;
33 unsigned int *stages;
34};
35
36int
37GNUNET_run_messenger_setup (const char* test_name, const struct test_configuration *cfg);
38
39#endif /* GNUNET_TESTING_MESSENGER_SETUP_H_ */