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.am235
-rw-r--r--src/messenger/gnunet-messenger.c334
-rw-r--r--src/messenger/gnunet-service-messenger.c420
-rw-r--r--src/messenger/gnunet-service-messenger.h137
-rw-r--r--src/messenger/gnunet-service-messenger_basement.c64
-rw-r--r--src/messenger/gnunet-service-messenger_basement.h70
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c310
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h159
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c711
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h252
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c104
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.h101
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.c155
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.h114
-rw-r--r--src/messenger/gnunet-service-messenger_member.c415
-rw-r--r--src/messenger/gnunet-service-messenger_member.h180
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c759
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h292
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c268
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.h158
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c153
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.h158
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.c241
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.h174
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c185
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.h87
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c76
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h97
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.c113
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.h67
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.c582
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.h169
-rw-r--r--src/messenger/gnunet-service-messenger_operation.c220
-rw-r--r--src/messenger/gnunet-service-messenger_operation.h131
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.c236
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.h132
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1255
-rw-r--r--src/messenger/gnunet-service-messenger_room.h367
-rw-r--r--src/messenger/gnunet-service-messenger_service.c319
-rw-r--r--src/messenger/gnunet-service-messenger_service.h212
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c402
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h194
-rw-r--r--src/messenger/messenger.conf.in14
-rw-r--r--src/messenger/messenger_api.c792
-rw-r--r--src/messenger/messenger_api_contact.c110
-rw-r--r--src/messenger/messenger_api_contact.h116
-rw-r--r--src/messenger/messenger_api_contact_store.c193
-rw-r--r--src/messenger/messenger_api_contact_store.h127
-rw-r--r--src/messenger/messenger_api_ego.h38
-rw-r--r--src/messenger/messenger_api_handle.c207
-rw-r--r--src/messenger/messenger_api_handle.h180
-rw-r--r--src/messenger/messenger_api_list_tunnels.c192
-rw-r--r--src/messenger/messenger_api_list_tunnels.h137
-rw-r--r--src/messenger/messenger_api_message.c932
-rw-r--r--src/messenger/messenger_api_message.h251
-rw-r--r--src/messenger/messenger_api_room.c368
-rw-r--r--src/messenger/messenger_api_room.h147
-rw-r--r--src/messenger/messenger_api_util.c102
-rw-r--r--src/messenger/messenger_api_util.h80
-rw-r--r--src/messenger/plugin_gnsrecord_messenger.c243
-rw-r--r--src/messenger/test_messenger.c181
-rw-r--r--src/messenger/test_messenger_adapt.c48
-rw-r--r--src/messenger/test_messenger_anonymous.c173
-rw-r--r--src/messenger/test_messenger_api.conf47
-rw-r--r--src/messenger/test_messenger_async_client.c48
-rw-r--r--src/messenger/test_messenger_async_p2p.c48
-rw-r--r--src/messenger/test_messenger_growth.c48
-rw-r--r--src/messenger/test_messenger_ring.c48
-rw-r--r--src/messenger/test_messenger_server.c48
-rw-r--r--src/messenger/test_messenger_sync_client.c48
-rw-r--r--src/messenger/test_messenger_sync_p2p.c48
-rw-r--r--src/messenger/test_messenger_worst_client.c48
-rw-r--r--src/messenger/test_messenger_worst_p2p.c48
-rw-r--r--src/messenger/testing_messenger_barrier.c172
-rw-r--r--src/messenger/testing_messenger_barrier.h131
-rw-r--r--src/messenger/testing_messenger_setup.c547
-rw-r--r--src/messenger/testing_messenger_setup.h40
78 files changed, 0 insertions, 16822 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 4be11f3aa..000000000
--- a/src/messenger/Makefile.am
+++ /dev/null
@@ -1,235 +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
13plugin_LTLIBRARIES = \
14 libgnunet_plugin_gnsrecord_messenger.la
15
16
17libgnunet_plugin_gnsrecord_messenger_la_SOURCES = \
18 plugin_gnsrecord_messenger.c
19libgnunet_plugin_gnsrecord_messenger_la_LIBADD = \
20 $(top_builddir)/src/util/libgnunetutil.la \
21 $(LTLIBINTL)
22libgnunet_plugin_gnsrecord_messenger_la_LDFLAGS = \
23 $(GN_PLUGIN_LDFLAGS)
24
25
26pkgcfg_DATA = \
27 messenger.conf
28
29plugindir = $(libdir)/gnunet
30
31AM_CLFAGS = -g
32
33libexec_PROGRAMS = \
34 gnunet-service-messenger \
35 $(EXP_LIBEXEC)
36
37bin_PROGRAMS = \
38 gnunet-messenger
39
40lib_LTLIBRARIES = \
41 libgnunetmessenger.la \
42 $(EXP_LIB)
43
44libgnunetmessenger_la_SOURCES = \
45 messenger_api.c \
46 messenger_api_ego.h \
47 messenger_api_contact.c messenger_api_contact.h \
48 messenger_api_contact_store.c messenger_api_contact_store.h \
49 messenger_api_message.c messenger_api_message.h \
50 messenger_api_list_tunnels.c messenger_api_list_tunnels.h \
51 messenger_api_util.c messenger_api_util.h \
52 messenger_api_handle.c messenger_api_handle.h \
53 messenger_api_room.c messenger_api_room.h
54libgnunetmessenger_la_LIBADD = \
55 $(top_builddir)/src/util/libgnunetutil.la \
56 $(top_builddir)/src/cadet/libgnunetcadet.la \
57 $(top_builddir)/src/identity/libgnunetidentity.la \
58 $(XLIB) \
59 $(LTLIBINTL)
60libgnunetmessenger_la_LDFLAGS = \
61 $(GN_LIB_LDFLAGS) \
62 -version-info 0:0:0
63
64gnunet_messenger_SOURCES = \
65 gnunet-messenger.c
66gnunet_messenger_LDADD = \
67 libgnunetmessenger.la \
68 $(top_builddir)/src/util/libgnunetutil.la
69gnunet_messenger_LDFLAGS = \
70 $(GN_LIBINTL)
71
72gnunet_service_messenger_SOURCES = \
73 gnunet-service-messenger.c gnunet-service-messenger.h \
74 gnunet-service-messenger_service.c gnunet-service-messenger_service.h \
75 gnunet-service-messenger_list_handles.c gnunet-service-messenger_list_handles.h \
76 gnunet-service-messenger_list_messages.c gnunet-service-messenger_list_messages.h \
77 gnunet-service-messenger_member_session.c gnunet-service-messenger_member_session.h \
78 gnunet-service-messenger_member.c gnunet-service-messenger_member.h \
79 gnunet-service-messenger_member_store.c gnunet-service-messenger_member_store.h \
80 gnunet-service-messenger_message_handle.c gnunet-service-messenger_message_handle.h \
81 gnunet-service-messenger_message_kind.c gnunet-service-messenger_message_kind.h \
82 gnunet-service-messenger_message_recv.c gnunet-service-messenger_message_recv.h \
83 gnunet-service-messenger_message_send.c gnunet-service-messenger_message_send.h \
84 gnunet-service-messenger_message_state.c gnunet-service-messenger_message_state.h \
85 gnunet-service-messenger_message_store.c gnunet-service-messenger_message_store.h \
86 gnunet-service-messenger_operation_store.c gnunet-service-messenger_operation_store.h \
87 gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
88 gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \
89 gnunet-service-messenger_ego_store.c gnunet-service-messenger_ego_store.h \
90 gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \
91 gnunet-service-messenger_room.c gnunet-service-messenger_room.h \
92 gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h
93gnunet_service_messenger_LDADD = \
94 libgnunetmessenger.la \
95 $(top_builddir)/src/util/libgnunetutil.la \
96 $(top_builddir)/src/cadet/libgnunetcadet.la \
97 $(top_builddir)/src/identity/libgnunetidentity.la \
98 $(GN_LIBINTL)
99
100check_PROGRAMS = \
101 test_messenger_api \
102 test_messenger_anonymous \
103 test_messenger_sync_client \
104 test_messenger_async_client \
105 test_messenger_worst_client \
106 test_messenger_sync_p2p \
107 test_messenger_async_p2p \
108 test_messenger_worst_p2p \
109 test_messenger_server \
110 test_messenger_growth \
111 test_messenger_ring \
112 test_messenger_adapt
113
114if ENABLE_TEST_RUN
115AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
116TESTS = \
117 $(check_PROGRAMS)
118endif
119
120test_messenger_api_SOURCES = \
121 test_messenger.c
122test_messenger_api_LDADD = \
123 libgnunetmessenger.la \
124 $(top_builddir)/src/testing/libgnunettesting.la \
125 $(top_builddir)/src/util/libgnunetutil.la
126
127test_messenger_anonymous_SOURCES = \
128 test_messenger_anonymous.c
129test_messenger_anonymous_LDADD = \
130 libgnunetmessenger.la \
131 $(top_builddir)/src/testing/libgnunettesting.la \
132 $(top_builddir)/src/util/libgnunetutil.la
133
134test_messenger_sync_client_SOURCES = \
135 test_messenger_sync_client.c \
136 testing_messenger_barrier.c testing_messenger_barrier.h \
137 testing_messenger_setup.c testing_messenger_setup.h
138test_messenger_sync_client_LDADD = \
139 libgnunetmessenger.la \
140 $(top_builddir)/src/testbed/libgnunettestbed.la \
141 $(top_builddir)/src/testing/libgnunettesting.la \
142 $(top_builddir)/src/util/libgnunetutil.la
143
144test_messenger_async_client_SOURCES = \
145 test_messenger_async_client.c \
146 testing_messenger_barrier.c testing_messenger_barrier.h \
147 testing_messenger_setup.c testing_messenger_setup.h
148test_messenger_async_client_LDADD = \
149 libgnunetmessenger.la \
150 $(top_builddir)/src/testbed/libgnunettestbed.la \
151 $(top_builddir)/src/testing/libgnunettesting.la \
152 $(top_builddir)/src/util/libgnunetutil.la
153
154test_messenger_worst_client_SOURCES = \
155 test_messenger_worst_client.c \
156 testing_messenger_barrier.c testing_messenger_barrier.h \
157 testing_messenger_setup.c testing_messenger_setup.h
158test_messenger_worst_client_LDADD = \
159 libgnunetmessenger.la \
160 $(top_builddir)/src/testbed/libgnunettestbed.la \
161 $(top_builddir)/src/testing/libgnunettesting.la \
162 $(top_builddir)/src/util/libgnunetutil.la
163
164test_messenger_sync_p2p_SOURCES = \
165 test_messenger_sync_p2p.c \
166 testing_messenger_barrier.c testing_messenger_barrier.h \
167 testing_messenger_setup.c testing_messenger_setup.h
168test_messenger_sync_p2p_LDADD = \
169 libgnunetmessenger.la \
170 $(top_builddir)/src/testbed/libgnunettestbed.la \
171 $(top_builddir)/src/testing/libgnunettesting.la \
172 $(top_builddir)/src/util/libgnunetutil.la
173
174test_messenger_async_p2p_SOURCES = \
175 test_messenger_async_p2p.c \
176 testing_messenger_barrier.c testing_messenger_barrier.h \
177 testing_messenger_setup.c testing_messenger_setup.h
178test_messenger_async_p2p_LDADD = \
179 libgnunetmessenger.la \
180 $(top_builddir)/src/testbed/libgnunettestbed.la \
181 $(top_builddir)/src/testing/libgnunettesting.la \
182 $(top_builddir)/src/util/libgnunetutil.la
183
184test_messenger_worst_p2p_SOURCES = \
185 test_messenger_worst_p2p.c \
186 testing_messenger_barrier.c testing_messenger_barrier.h \
187 testing_messenger_setup.c testing_messenger_setup.h
188test_messenger_worst_p2p_LDADD = \
189 libgnunetmessenger.la \
190 $(top_builddir)/src/testbed/libgnunettestbed.la \
191 $(top_builddir)/src/testing/libgnunettesting.la \
192 $(top_builddir)/src/util/libgnunetutil.la
193
194test_messenger_server_SOURCES = \
195 test_messenger_server.c \
196 testing_messenger_barrier.c testing_messenger_barrier.h \
197 testing_messenger_setup.c testing_messenger_setup.h
198test_messenger_server_LDADD = \
199 libgnunetmessenger.la \
200 $(top_builddir)/src/testbed/libgnunettestbed.la \
201 $(top_builddir)/src/testing/libgnunettesting.la \
202 $(top_builddir)/src/util/libgnunetutil.la
203
204test_messenger_growth_SOURCES = \
205 test_messenger_growth.c \
206 testing_messenger_barrier.c testing_messenger_barrier.h \
207 testing_messenger_setup.c testing_messenger_setup.h
208test_messenger_growth_LDADD = \
209 libgnunetmessenger.la \
210 $(top_builddir)/src/testbed/libgnunettestbed.la \
211 $(top_builddir)/src/testing/libgnunettesting.la \
212 $(top_builddir)/src/util/libgnunetutil.la
213
214test_messenger_ring_SOURCES = \
215 test_messenger_ring.c \
216 testing_messenger_barrier.c testing_messenger_barrier.h \
217 testing_messenger_setup.c testing_messenger_setup.h
218test_messenger_ring_LDADD = \
219 libgnunetmessenger.la \
220 $(top_builddir)/src/testbed/libgnunettestbed.la \
221 $(top_builddir)/src/testing/libgnunettesting.la \
222 $(top_builddir)/src/util/libgnunetutil.la
223
224test_messenger_adapt_SOURCES = \
225 test_messenger_adapt.c \
226 testing_messenger_barrier.c testing_messenger_barrier.h \
227 testing_messenger_setup.c testing_messenger_setup.h
228test_messenger_adapt_LDADD = \
229 libgnunetmessenger.la \
230 $(top_builddir)/src/testbed/libgnunettestbed.la \
231 $(top_builddir)/src/testing/libgnunettesting.la \
232 $(top_builddir)/src/util/libgnunetutil.la
233
234EXTRA_DIST = \
235 test_messenger_api.conf
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c
deleted file mode 100644
index e2d106be8..000000000
--- a/src/messenger/gnunet-messenger.c
+++ /dev/null
@@ -1,334 +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,
46 struct GNUNET_MESSENGER_Room *room,
47 const struct GNUNET_MESSENGER_Contact *sender,
48 const struct GNUNET_MESSENGER_Message *message,
49 const struct GNUNET_HashCode *hash,
50 enum GNUNET_MESSENGER_MessageFlags flags)
51{
52 const char *sender_name = GNUNET_MESSENGER_contact_get_name (sender);
53
54 if (!sender_name)
55 sender_name = "anonymous";
56
57 printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
58
59 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
60 printf ("*");
61
62 switch (message->header.kind)
63 {
64 case GNUNET_MESSENGER_KIND_JOIN:
65 {
66 printf ("* '%s' joined the room!\n", sender_name);
67 break;
68 }
69 case GNUNET_MESSENGER_KIND_NAME:
70 {
71 printf ("* '%s' gets renamed to '%s'\n", sender_name, message->body.name.name);
72 break;
73 }
74 case GNUNET_MESSENGER_KIND_LEAVE:
75 {
76 printf ("* '%s' leaves the room!\n", sender_name);
77 break;
78 }
79 case GNUNET_MESSENGER_KIND_PEER:
80 {
81 printf ("* '%s' opened the room on: %s\n", sender_name, GNUNET_i2s_full (&(message->body.peer.peer)));
82 break;
83 }
84 case GNUNET_MESSENGER_KIND_TEXT:
85 {
86 if (flags & GNUNET_MESSENGER_FLAG_SENT)
87 printf (">");
88 else
89 printf ("<");
90
91 printf (" '%s' says: \"%s\"\n", sender_name, message->body.text.text);
92 break;
93 }
94 default:
95 {
96 printf ("~ message: %s\n", GNUNET_MESSENGER_name_of_kind(message->header.kind));
97 break;
98 }
99 }
100}
101
102struct GNUNET_SCHEDULER_Task *read_task;
103
104/**
105 * Task to shut down this application.
106 *
107 * @param[in/out] cls Closure
108 */
109static void
110shutdown_hook (void *cls)
111{
112 struct GNUNET_MESSENGER_Room *room = cls;
113
114 if (read_task)
115 GNUNET_SCHEDULER_cancel (read_task);
116
117 if (room)
118 GNUNET_MESSENGER_close_room (room);
119
120 if (messenger)
121 GNUNET_MESSENGER_disconnect (messenger);
122}
123
124static void
125listen_stdio (void *cls);
126
127#define MAX_BUFFER_SIZE 60000
128
129static int
130iterate_send_private_message (void *cls,
131 struct GNUNET_MESSENGER_Room *room,
132 const struct GNUNET_MESSENGER_Contact *contact)
133{
134 struct GNUNET_MESSENGER_Message *message = cls;
135
136 if (GNUNET_MESSENGER_contact_get_key(contact))
137 GNUNET_MESSENGER_send_message (room, message, contact);
138
139 return GNUNET_YES;
140}
141
142int private_mode;
143
144/**
145 * Task run in stdio mode, after some data is available at stdin.
146 *
147 * @param[in/out] cls Closure
148 */
149static void
150read_stdio (void *cls)
151{
152 read_task = NULL;
153
154 char buffer[MAX_BUFFER_SIZE];
155 ssize_t length;
156
157 length = read (0, buffer, MAX_BUFFER_SIZE);
158
159 if ((length <= 0) || (length >= MAX_BUFFER_SIZE))
160 {
161 GNUNET_SCHEDULER_shutdown ();
162 return;
163 }
164
165 if (buffer[length - 1] == '\n')
166 buffer[length - 1] = '\0';
167 else
168 buffer[length] = '\0';
169
170 struct GNUNET_MESSENGER_Room *room = cls;
171
172 struct GNUNET_MESSENGER_Message message;
173 message.header.kind = GNUNET_MESSENGER_KIND_TEXT;
174 message.body.text.text = buffer;
175
176 if (GNUNET_YES == private_mode)
177 GNUNET_MESSENGER_iterate_members(room, iterate_send_private_message, &message);
178 else
179 GNUNET_MESSENGER_send_message (room, &message, NULL);
180
181 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, cls);
182}
183
184/**
185 * Wait for input on STDIO and send it out over the #ch.
186 *
187 * @param[in/out] cls Closure
188 */
189static void
190listen_stdio (void *cls)
191{
192 read_task = NULL;
193
194 struct GNUNET_NETWORK_FDSet *rs = GNUNET_NETWORK_fdset_create ();
195
196 GNUNET_NETWORK_fdset_set_native (rs, 0);
197
198 read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
199 GNUNET_TIME_UNIT_FOREVER_REL, rs,
200 NULL, &read_stdio, cls);
201
202 GNUNET_NETWORK_fdset_destroy (rs);
203}
204
205/**
206 * Initial task to startup application.
207 *
208 * @param[in/out] cls Closure
209 */
210static void
211idle (void *cls)
212{
213 struct GNUNET_MESSENGER_Room *room = cls;
214
215 printf ("* You joined the room.\n");
216
217 read_task = GNUNET_SCHEDULER_add_now (listen_stdio, room);
218}
219
220char *door_id;
221char *ego_name;
222char *room_key;
223
224struct GNUNET_SCHEDULER_Task *shutdown_task;
225
226/**
227 * Function called when an identity is retrieved.
228 *
229 * @param[in/out] cls Closure
230 * @param[in/out] handle Handle of messenger service
231 */
232static void
233on_identity (void *cls,
234 struct GNUNET_MESSENGER_Handle *handle)
235{
236 struct GNUNET_HashCode key;
237 memset (&key, 0, sizeof(key));
238
239 if (room_key)
240 GNUNET_CRYPTO_hash (room_key, strlen (room_key), &key);
241
242 struct GNUNET_PeerIdentity door_peer;
243 struct GNUNET_PeerIdentity *door = NULL;
244
245 if ((door_id) &&
246 (GNUNET_OK == GNUNET_CRYPTO_eddsa_public_key_from_string (door_id, strlen (door_id), &(door_peer.public_key))))
247 door = &door_peer;
248
249 const char *name = GNUNET_MESSENGER_get_name (handle);
250
251 if (!name)
252 name = "anonymous";
253
254 printf ("* Welcome to the messenger, '%s'!\n", name);
255
256 struct GNUNET_MESSENGER_Room *room;
257
258 if (door)
259 {
260 printf ("* You try to entry a room...\n");
261
262 room = GNUNET_MESSENGER_enter_room (messenger, door, &key);
263 }
264 else
265 {
266 printf ("* You try to open a room...\n");
267
268 room = GNUNET_MESSENGER_open_room (messenger, &key);
269 }
270
271 GNUNET_SCHEDULER_cancel (shutdown_task);
272
273 shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, room);
274
275 if (!room)
276 GNUNET_SCHEDULER_shutdown ();
277 else
278 {
279 struct GNUNET_MESSENGER_Message message;
280 message.header.kind = GNUNET_MESSENGER_KIND_NAME;
281 message.body.name.name = GNUNET_strdup(name);
282
283 GNUNET_MESSENGER_send_message (room, &message, NULL);
284 GNUNET_free(message.body.name.name);
285
286 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
287 room);
288 }
289}
290
291/**
292 * Main function that will be run by the scheduler.
293 *
294 * @param[in/out] cls closure
295 * @param[in] args remaining command-line arguments
296 * @param[in] cfgfile name of the configuration file used (for saving, can be NULL!)
297 * @param[in] cfg configuration
298 */
299static void
300run (void *cls,
301 char *const*args,
302 const char *cfgfile,
303 const struct GNUNET_CONFIGURATION_Handle *cfg)
304{
305 messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, &on_message, NULL);
306
307 shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
308}
309
310/**
311 * The main function to obtain messenger information.
312 *
313 * @param[in] argc number of arguments from the command line
314 * @param[in] argv command line arguments
315 * @return #EXIT_SUCCESS ok, #EXIT_FAILURE on error
316 */
317int
318main (int argc,
319 char **argv)
320{
321 const char *description = "Open and connect to rooms using the MESSENGER to chat.";
322
323 struct GNUNET_GETOPT_CommandLineOption options[] =
324 {
325 GNUNET_GETOPT_option_string ('d', "door", "PEERIDENTITY", "peer identity to entry into the room", &door_id),
326 GNUNET_GETOPT_option_string ('e', "ego", "IDENTITY", "identity to use for messaging", &ego_name),
327 GNUNET_GETOPT_option_string ('r', "room", "ROOMKEY", "key of the room to connect to", &room_key),
328 GNUNET_GETOPT_option_flag ('p', "private", "flag to enable private mode", &private_mode),
329 GNUNET_GETOPT_OPTION_END
330 };
331
332 return (GNUNET_OK == GNUNET_PROGRAM_run (argc, argv, "gnunet-messenger\0", gettext_noop(description), options, &run,
333 NULL) ? EXIT_SUCCESS : EXIT_FAILURE);
334}
diff --git a/src/messenger/gnunet-service-messenger.c b/src/messenger/gnunet-service-messenger.c
deleted file mode 100644
index 546f4c0d2..000000000
--- a/src/messenger/gnunet-service-messenger.c
+++ /dev/null
@@ -1,420 +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,
43 const struct GNUNET_MESSENGER_CreateMessage *msg)
44{
45 GNUNET_MQ_check_zero_termination(msg);
46 return GNUNET_OK;
47}
48
49static void
50handle_create (void *cls,
51 const struct GNUNET_MESSENGER_CreateMessage *msg)
52{
53 struct GNUNET_MESSENGER_Client *msg_client = cls;
54
55 const char *name = ((const char*) msg) + sizeof(*msg);
56
57 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
58
59 setup_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
60
61 GNUNET_SERVICE_client_continue (msg_client->client);
62}
63
64static void
65handle_update (void *cls,
66 const struct GNUNET_MESSENGER_UpdateMessage *msg)
67{
68 struct GNUNET_MESSENGER_Client *msg_client = cls;
69
70 update_handle (msg_client->handle);
71
72 GNUNET_SERVICE_client_continue (msg_client->client);
73}
74
75static void
76handle_destroy (void *cls,
77 const struct GNUNET_MESSENGER_DestroyMessage *msg)
78{
79 struct GNUNET_MESSENGER_Client *msg_client = cls;
80
81 GNUNET_SERVICE_client_drop (msg_client->client);
82}
83
84static int
85check_set_name (void *cls,
86 const struct GNUNET_MESSENGER_NameMessage *msg)
87{
88 GNUNET_MQ_check_zero_termination(msg);
89 return GNUNET_OK;
90}
91
92static void
93handle_set_name (void *cls,
94 const struct GNUNET_MESSENGER_NameMessage *msg)
95{
96 struct GNUNET_MESSENGER_Client *msg_client = cls;
97
98 const char *name = ((const char*) msg) + sizeof(*msg);
99
100 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
101
102 set_handle_name (msg_client->handle, name);
103
104 GNUNET_SERVICE_client_continue (msg_client->client);
105}
106
107static void
108handle_room_open (void *cls,
109 const struct GNUNET_MESSENGER_RoomMessage *msg)
110{
111 struct GNUNET_MESSENGER_Client *msg_client = cls;
112
113 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (&(msg->key)));
114
115 if (GNUNET_YES == open_handle_room (msg_client->handle, &(msg->key)))
116 {
117 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
118
119 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n", GNUNET_sh2s (member_id));
120
121 struct GNUNET_MESSENGER_RoomMessage *response;
122 struct GNUNET_MQ_Envelope *env;
123
124 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
125 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
126 GNUNET_MQ_send (msg_client->handle->mq, env);
127 }
128 else
129 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n", GNUNET_h2s (&(msg->key)));
130
131 GNUNET_SERVICE_client_continue (msg_client->client);
132}
133
134static void
135handle_room_entry (void *cls,
136 const struct GNUNET_MESSENGER_RoomMessage *msg)
137{
138 struct GNUNET_MESSENGER_Client *msg_client = cls;
139
140 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (&(msg->key)), GNUNET_i2s (&(msg->door)));
141
142 if (GNUNET_YES == entry_handle_room (msg_client->handle, &(msg->door), &(msg->key)))
143 {
144 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
145
146 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n", GNUNET_sh2s (member_id));
147
148 struct GNUNET_MESSENGER_RoomMessage *response;
149 struct GNUNET_MQ_Envelope *env;
150
151 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
152 GNUNET_memcpy(&(response->door), &(msg->door), sizeof(msg->door));
153 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
154 GNUNET_MQ_send (msg_client->handle->mq, env);
155 }
156 else
157 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n", GNUNET_h2s (&(msg->key)),
158 GNUNET_i2s (&(msg->door)));
159
160 GNUNET_SERVICE_client_continue (msg_client->client);
161}
162
163static void
164handle_room_close (void *cls,
165 const struct GNUNET_MESSENGER_RoomMessage *msg)
166{
167 struct GNUNET_MESSENGER_Client *msg_client = cls;
168
169 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room: %s\n", GNUNET_h2s (&(msg->key)));
170
171 if (GNUNET_YES == close_handle_room (msg_client->handle, &(msg->key)))
172 {
173 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (msg_client->handle, &(msg->key));
174
175 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closing room with member id: %s\n", GNUNET_sh2s (member_id));
176
177 struct GNUNET_MESSENGER_RoomMessage *response;
178 struct GNUNET_MQ_Envelope *env;
179
180 env = GNUNET_MQ_msg(response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
181 GNUNET_memcpy(&(response->key), &(msg->key), sizeof(msg->key));
182 GNUNET_MQ_send (msg_client->handle->mq, env);
183 }
184 else
185 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Closing room failed: %s\n", GNUNET_h2s (&(msg->key)));
186
187 GNUNET_SERVICE_client_continue (msg_client->client);
188}
189
190static int
191check_send_message (void *cls,
192 const struct GNUNET_MESSENGER_SendMessage *msg)
193{
194 const uint16_t full_length = ntohs (msg->header.size);
195
196 if (full_length < sizeof(*msg))
197 return GNUNET_NO;
198
199 const enum GNUNET_MESSENGER_MessageFlags flags = (
200 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
201 );
202
203 const uint16_t length = full_length - sizeof(*msg);
204 const char *buffer = ((const char*) msg) + sizeof(*msg);
205
206 ssize_t key_length = 0;
207
208 if (!(flags & GNUNET_MESSENGER_FLAG_PRIVATE))
209 goto check_for_message;
210
211 struct GNUNET_IDENTITY_PublicKey public_key;
212
213 key_length = GNUNET_IDENTITY_read_key_from_buffer(&public_key, buffer, length);
214
215check_for_message:
216 if (key_length < 0)
217 return GNUNET_NO;
218
219 const uint16_t msg_length = length - key_length;
220 const char* msg_buffer = buffer + key_length;
221
222 struct GNUNET_MESSENGER_Message message;
223
224 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_NO))
225 return GNUNET_NO;
226
227 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL))
228 return GNUNET_NO;
229
230 const int allowed = filter_message_sending(&message);
231
232 cleanup_message(&message);
233 return GNUNET_YES == allowed? GNUNET_OK : GNUNET_NO;
234}
235
236static void
237handle_send_message (void *cls,
238 const struct GNUNET_MESSENGER_SendMessage *msg)
239{
240 struct GNUNET_MESSENGER_Client *msg_client = cls;
241
242 const enum GNUNET_MESSENGER_MessageFlags flags = (
243 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
244 );
245
246 const struct GNUNET_HashCode *key = &(msg->key);
247 const char *buffer = ((const char*) msg) + sizeof(*msg);
248
249 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
250 ssize_t key_length = 0;
251
252 struct GNUNET_IDENTITY_PublicKey public_key;
253
254 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
255 key_length = GNUNET_IDENTITY_read_key_from_buffer(
256 &public_key, buffer, length
257 );
258
259 const uint16_t msg_length = length - key_length;
260 const char* msg_buffer = buffer + key_length;
261
262 struct GNUNET_MESSENGER_Message message;
263 decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
264
265 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
266 (GNUNET_YES != encrypt_message(&message, &public_key)))
267 {
268 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Encrypting message failed: Message got dropped!\n");
269
270 goto end_handling;
271 }
272
273 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
274 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
275
276 if (GNUNET_YES != send_handle_message (msg_client->handle, key, &message))
277 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
278 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (key));
279
280end_handling:
281 cleanup_message(&message);
282
283 GNUNET_SERVICE_client_continue (msg_client->client);
284}
285
286static void
287callback_found_message (void *cls,
288 struct GNUNET_MESSENGER_SrvRoom *room,
289 const struct GNUNET_MESSENGER_Message *message,
290 const struct GNUNET_HashCode *hash)
291{
292 struct GNUNET_MESSENGER_Client *msg_client = cls;
293
294 if (!message)
295 {
296 send_room_message(room, msg_client->handle, create_message_request(hash));
297 return;
298 }
299
300 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
301
302 struct GNUNET_MESSENGER_Member *member = get_store_member_of(store, message);
303
304 if (!member)
305 {
306 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n", GNUNET_h2s (hash));
307 return;
308 }
309
310 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
311
312 if (session)
313 notify_handle_message (msg_client->handle, room, session, message, hash);
314}
315
316static void
317handle_get_message (void *cls,
318 const struct GNUNET_MESSENGER_GetMessage *msg)
319{
320 struct GNUNET_MESSENGER_Client *msg_client = cls;
321
322 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n", GNUNET_h2s (&(msg->key)));
323
324 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger, &(msg->key));
325
326 if (!room)
327 {
328 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", GNUNET_h2s (&(msg->key)));
329 goto end_handling;
330 }
331
332 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
333
334 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, get_handle_member_id(
335 msg_client->handle, &(msg->key)
336 ));
337
338 if (!member)
339 {
340 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Member not valid to request a message!\n");
341 goto end_handling;
342 }
343
344 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(msg_client->handle)->pub));
345
346 if (!session)
347 {
348 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Session not valid to request a message!\n");
349 goto end_handling;
350 }
351
352 request_room_message (room, &(msg->hash), session, callback_found_message, msg_client);
353
354end_handling:
355 GNUNET_SERVICE_client_continue (msg_client->client);
356}
357
358static void*
359callback_client_connect (void *cls,
360 struct GNUNET_SERVICE_Client *client,
361 struct GNUNET_MQ_Handle *mq)
362{
363 struct GNUNET_MESSENGER_Client *msg_client = GNUNET_new(struct GNUNET_MESSENGER_Client);
364
365 msg_client->client = client;
366 msg_client->handle = add_service_handle (messenger, mq);
367
368 return msg_client;
369}
370
371static void
372callback_client_disconnect (void *cls,
373 struct GNUNET_SERVICE_Client *client,
374 void *internal_cls)
375{
376 struct GNUNET_MESSENGER_Client *msg_client = internal_cls;
377
378 remove_service_handle (messenger, msg_client->handle);
379
380 GNUNET_free(msg_client);
381}
382
383/**
384 * Setup MESSENGER internals.
385 *
386 * @param[in/out] cls closure
387 * @param[in] config configuration to use
388 * @param[in/out] service the initialized service
389 */
390static void
391run (void *cls,
392 const struct GNUNET_CONFIGURATION_Handle *config,
393 struct GNUNET_SERVICE_Handle *service)
394{
395 messenger = create_service (config, service);
396
397 if (!messenger)
398 GNUNET_SCHEDULER_shutdown ();
399}
400
401/**
402 * Define "main" method using service macro.
403 */
404GNUNET_SERVICE_MAIN(
405 GNUNET_MESSENGER_SERVICE_NAME,
406 GNUNET_SERVICE_OPTION_NONE,
407 &run,
408 &callback_client_connect,
409 &callback_client_disconnect,
410 NULL,
411 GNUNET_MQ_hd_var_size( create, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, struct GNUNET_MESSENGER_CreateMessage, NULL ),
412 GNUNET_MQ_hd_fixed_size( update, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE, struct GNUNET_MESSENGER_UpdateMessage, NULL ),
413 GNUNET_MQ_hd_fixed_size( destroy, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY, struct GNUNET_MESSENGER_DestroyMessage, NULL ),
414 GNUNET_MQ_hd_var_size( set_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME, struct GNUNET_MESSENGER_NameMessage, NULL ),
415 GNUNET_MQ_hd_fixed_size( room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN, struct GNUNET_MESSENGER_RoomMessage, NULL ),
416 GNUNET_MQ_hd_fixed_size( room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY, struct GNUNET_MESSENGER_RoomMessage, NULL ),
417 GNUNET_MQ_hd_fixed_size( room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE, struct GNUNET_MESSENGER_RoomMessage, NULL ),
418 GNUNET_MQ_hd_var_size( send_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct GNUNET_MESSENGER_SendMessage, NULL ),
419 GNUNET_MQ_hd_fixed_size( get_message, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE, struct GNUNET_MESSENGER_GetMessage, NULL ),
420 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 89aa103ee..000000000
--- a/src/messenger/gnunet-service-messenger_basement.c
+++ /dev/null
@@ -1,64 +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,
44 size_t src,
45 size_t dst)
46{
47 if ((src + 1) % count == dst % count)
48 return GNUNET_YES;
49
50 return GNUNET_NO;
51}
52
53int
54required_connection_between (size_t count,
55 size_t src,
56 size_t dst)
57{
58 if (GNUNET_YES == should_connect_tunnel_to (count, src, dst))
59 return GNUNET_YES;
60 if (GNUNET_YES == should_connect_tunnel_to (count, dst, src))
61 return GNUNET_YES;
62
63 return GNUNET_NO;
64}
diff --git a/src/messenger/gnunet-service-messenger_basement.h b/src/messenger/gnunet-service-messenger_basement.h
deleted file mode 100644
index a097b482f..000000000
--- a/src/messenger/gnunet-service-messenger_basement.h
+++ /dev/null
@@ -1,70 +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,
52 size_t src,
53 size_t dst);
54
55/**
56 * Returns #GNUNET_YES or #GNUNET_NO to determine if the peers of index <i>src</i> and
57 * index <i>dst</i> should be connected in any direction to construct a complete
58 * basement with a given <i>count</i> of peers.
59 *
60 * @param[in] count Count of peers
61 * @param[in] src Source index
62 * @param[in] dst Destination index
63 * @return #GNUNET_YES or #GNUNET_NO based on topologic requirement
64 */
65int
66required_connection_between (size_t count,
67 size_t src,
68 size_t dst);
69
70#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 c460ac1c7..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.c
+++ /dev/null
@@ -1,310 +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,
32 struct GNUNET_IDENTITY_Ego *ego,
33 void **ctx,
34 const char *identifier)
35{
36 if ((!ego) || (!identifier))
37 return;
38
39 struct GNUNET_MESSENGER_EgoStore *store = cls;
40
41 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
42
43 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
44}
45
46void
47init_ego_store(struct GNUNET_MESSENGER_EgoStore *store,
48 const struct GNUNET_CONFIGURATION_Handle *config)
49{
50 GNUNET_assert ((store) && (config));
51
52 store->cfg = config;
53 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
54 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
55
56 store->lu_start = NULL;
57 store->lu_end = NULL;
58
59 store->op_start = NULL;
60 store->op_end = NULL;
61}
62
63
64static int
65iterate_destroy_egos (void *cls,
66 const struct GNUNET_HashCode *key,
67 void *value)
68{
69 struct GNUNET_MESSENGER_Ego *ego = value;
70 GNUNET_free(ego);
71 return GNUNET_YES;
72}
73
74void
75clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
76{
77 GNUNET_assert (store);
78
79 struct GNUNET_MESSENGER_EgoOperation *op;
80
81 while (store->op_start)
82 {
83 op = store->op_start;
84
85 GNUNET_IDENTITY_cancel (op->operation);
86 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
87
88 if (op->identifier)
89 GNUNET_free (op->identifier);
90
91 GNUNET_free (op);
92 }
93
94 struct GNUNET_MESSENGER_EgoLookup *lu;
95
96 while (store->lu_start)
97 {
98 lu = store->lu_start;
99
100 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
101 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
102
103 if (lu->identifier)
104 GNUNET_free(lu->identifier);
105
106 GNUNET_free (lu);
107 }
108
109 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
110 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
111
112 if (store->identity)
113 {
114 GNUNET_IDENTITY_disconnect (store->identity);
115
116 store->identity = NULL;
117 }
118}
119
120static void
121callback_ego_create (void *cls,
122 const struct GNUNET_IDENTITY_PrivateKey *key,
123 const char *emsg)
124{
125 struct GNUNET_MESSENGER_EgoOperation *element = cls;
126 struct GNUNET_MESSENGER_EgoStore *store = element->store;
127
128 GNUNET_assert(element->identifier);
129
130 if (emsg)
131 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
132
133 if (key)
134 {
135 struct GNUNET_MESSENGER_SrvHandle *handle = element->handle;
136
137 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
138
139 set_handle_ego (handle, msg_ego);
140 }
141 else
142 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
143
144 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
145 GNUNET_free (element->identifier);
146 GNUNET_free (element);
147}
148
149void
150create_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
151 const char *identifier,
152 void *handle)
153{
154 GNUNET_assert ((store) && (identifier));
155
156 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
157
158 element->store = store;
159 element->handle = handle;
160
161 element->identifier = GNUNET_strdup (identifier);
162
163 element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL,
164 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element);
165
166 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
167}
168
169static void
170callback_ego_lookup (void *cls,
171 struct GNUNET_IDENTITY_Ego *ego)
172{
173 struct GNUNET_MESSENGER_EgoLookup *element = cls;
174 struct GNUNET_MESSENGER_EgoStore *store = element->store;
175
176 GNUNET_assert(element->identifier);
177
178 struct GNUNET_MESSENGER_Ego *msg_ego;
179
180 if (ego)
181 msg_ego = update_store_ego (
182 store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego)
183 );
184 else
185 msg_ego = NULL;
186
187 if (element->cb)
188 element->cb(element->cls, element->identifier, msg_ego);
189
190 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
191 GNUNET_free (element->identifier);
192 GNUNET_free (element);
193}
194
195void
196lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store,
197 const char *identifier,
198 GNUNET_MESSENGER_EgoLookupCallback lookup,
199 void *cls)
200{
201 GNUNET_assert (store);
202
203 if (!identifier)
204 {
205 lookup(cls, identifier, NULL);
206 return;
207 }
208
209 struct GNUNET_HashCode hash;
210 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
211
212 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
213
214 if (ego)
215 lookup(cls, identifier, ego);
216 else
217 {
218 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
219
220 element->store = store;
221
222 element->cb = lookup;
223 element->cls = cls;
224
225 element->identifier = GNUNET_strdup (identifier);
226
227 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
228
229 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
230 }
231}
232
233struct GNUNET_MESSENGER_Ego*
234update_store_ego(struct GNUNET_MESSENGER_EgoStore *store,
235 const char *identifier,
236 const struct GNUNET_IDENTITY_PrivateKey *key)
237{
238 GNUNET_assert ((store) && (identifier) && (key));
239
240 struct GNUNET_HashCode hash;
241 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
242
243 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
244
245 if (!ego)
246 {
247 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
248 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
249 }
250
251 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
252
253 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
254 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
255
256 return ego;
257}
258
259static void
260callback_ego_rename (void *cls,
261 const char *emsg)
262{
263 struct GNUNET_MESSENGER_EgoOperation *element = cls;
264 struct GNUNET_MESSENGER_EgoStore *store = element->store;
265
266 GNUNET_assert(element->identifier);
267
268 if (emsg)
269 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
270
271 struct GNUNET_HashCode hash;
272 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
273
274 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
275
276 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
277 {
278 GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash);
279
280 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
281 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
282 }
283 else
284 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
285
286 GNUNET_free (element->handle);
287
288 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
289 GNUNET_free (element->identifier);
290 GNUNET_free (element);
291}
292
293void
294rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
295 const char *old_identifier,
296 const char *new_identifier)
297{
298 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
299
300 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
301
302 element->store = store;
303 element->handle = GNUNET_strdup (new_identifier);
304
305 element->identifier = GNUNET_strdup (old_identifier);
306
307 element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element);
308
309 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
310}
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 4222a4e91..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.h
+++ /dev/null
@@ -1,159 +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,
39 const char *identifier,
40 const struct GNUNET_MESSENGER_Ego *ego);
41
42struct GNUNET_MESSENGER_EgoLookup
43{
44 struct GNUNET_MESSENGER_EgoLookup *prev;
45 struct GNUNET_MESSENGER_EgoLookup *next;
46
47 struct GNUNET_IDENTITY_EgoLookup *lookup;
48
49 struct GNUNET_MESSENGER_EgoStore *store;
50
51 GNUNET_MESSENGER_EgoLookupCallback cb;
52 void *cls;
53
54 char *identifier;
55};
56
57struct GNUNET_MESSENGER_EgoOperation
58{
59 struct GNUNET_MESSENGER_EgoOperation *prev;
60 struct GNUNET_MESSENGER_EgoOperation *next;
61
62 struct GNUNET_IDENTITY_Operation *operation;
63
64 struct GNUNET_MESSENGER_EgoStore *store;
65 void *handle;
66
67 char *identifier;
68};
69
70struct GNUNET_MESSENGER_EgoStore
71{
72 const struct GNUNET_CONFIGURATION_Handle *cfg;
73
74 struct GNUNET_IDENTITY_Handle *identity;
75 struct GNUNET_CONTAINER_MultiHashMap *egos;
76
77 struct GNUNET_MESSENGER_EgoLookup *lu_start;
78 struct GNUNET_MESSENGER_EgoLookup *lu_end;
79
80 struct GNUNET_MESSENGER_EgoOperation *op_start;
81 struct GNUNET_MESSENGER_EgoOperation *op_end;
82};
83
84/**
85 * Initializes an EGO-store as fully empty.
86 *
87 * @param[out] store EGO-store
88 * @param[in] config Configuration handle
89 */
90void
91init_ego_store (struct GNUNET_MESSENGER_EgoStore *store,
92 const struct GNUNET_CONFIGURATION_Handle *config);
93
94/**
95 * Clears an EGO-store, wipes its content and deallocates its memory.
96 *
97 * @param[in/out] store EGO-store
98 */
99void
100clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store);
101
102/**
103 * Creates a new EGO which will be registered to a <i>store</i> under
104 * a specific <i>identifier</i>. A given <i>handle</i> will be informed
105 * about the creation and changes its EGO accordingly.
106 *
107 * @param[in/out] store EGO-store
108 * @param[in] identifier Identifier string
109 * @param[in/out] handle Handle or NULL
110 */
111void
112create_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
113 const char *identifier,
114 void *handle);
115
116/**
117 * Lookups an EGO which was registered to a <i>store</i> under
118 * a specific <i>identifier</i>.
119 *
120 * @param[in/out] store EGO-store
121 * @param[in] identifier Identifier string
122 * @param[in] lookup Lookup callback (non-NULL)
123 * @param[in] cls Closure
124 */
125void
126lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
127 const char *identifier,
128 GNUNET_MESSENGER_EgoLookupCallback lookup,
129 void *cls);
130
131/**
132 * Updates the registration of an EGO to a <i>store</i> under
133 * a specific <i>identifier</i> with a new <i>key</i>.
134 *
135 * @param[in/out] store EGO-store
136 * @param[in] identifier Identifier string
137 * @param[in] key Private EGO key
138 * @return Updated EGO
139 */
140struct GNUNET_MESSENGER_Ego*
141update_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
142 const char *identifier,
143 const struct GNUNET_IDENTITY_PrivateKey *key);
144
145/**
146 * Updates the location of a registered EGO in a <i>store</i> to
147 * a different one under a specific <i>new_identifier<i> replacing
148 * its old one.
149 *
150 * @param[in/out] store EGO-store
151 * @param[in] old_identifier Old identifier string
152 * @param[in] new_identifier New identifier string
153 */
154void
155rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
156 const char *old_identifier,
157 const char *new_identifier);
158
159#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 341bb7251..000000000
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ /dev/null
@@ -1,711 +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,
35 struct GNUNET_MQ_Handle *mq)
36{
37 GNUNET_assert((service) && (mq));
38
39 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
40
41 handle->service = service;
42 handle->mq = mq;
43
44 handle->name = NULL;
45 handle->ego = NULL;
46
47 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
48
49 return handle;
50}
51
52int
53iterate_free_member_ids (void *cls,
54 const struct GNUNET_HashCode *key,
55 void *value)
56{
57 GNUNET_free(value);
58
59 return GNUNET_YES;
60}
61
62void
63destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
64{
65 GNUNET_assert(handle);
66
67 if (handle->service->dir)
68 save_handle_configuration (handle);
69
70 if (handle->name)
71 GNUNET_free(handle->name);
72
73 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL);
74 GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
75
76 GNUNET_free(handle);
77}
78
79void
80get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
81 const char *name,
82 char **dir)
83{
84 GNUNET_assert((handle) && (dir));
85
86 if (name)
87 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
88 DIR_SEPARATOR, name, DIR_SEPARATOR);
89 else
90 GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous",
91 DIR_SEPARATOR);
92}
93
94static int
95create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
96 const struct GNUNET_HashCode *key)
97{
98 GNUNET_assert((handle) && (key));
99
100 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
101
102 if (!random_id)
103 return GNUNET_NO;
104
105 generate_free_member_id (random_id, NULL);
106
107 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
108 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
109 {
110 GNUNET_free(random_id);
111 return GNUNET_NO;
112 }
113
114 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
115 GNUNET_h2s (key));
116
117 return GNUNET_YES;
118}
119
120const struct GNUNET_ShortHashCode*
121get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
122 const struct GNUNET_HashCode *key)
123{
124 GNUNET_assert((handle) && (key));
125
126 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
127}
128
129int
130change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
131 const struct GNUNET_HashCode *key,
132 const struct GNUNET_ShortHashCode *unique_id)
133{
134 GNUNET_assert((handle) && (key) && (unique_id));
135
136 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
137
138 if (!member_id)
139 {
140 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
141 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
142
143 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
144 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
145 {
146 GNUNET_free(member_id);
147 return GNUNET_SYSERR;
148 }
149 }
150
151 if (0 == GNUNET_memcmp(unique_id, member_id))
152 goto send_message_to_client;
153
154 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
155 GNUNET_h2s (key));
156
157 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
158
159 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
160
161 struct GNUNET_MESSENGER_MemberMessage *msg;
162 struct GNUNET_MQ_Envelope *env;
163
164send_message_to_client:
165
166 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
167
168 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
169 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
170
171 GNUNET_MQ_send (handle->mq, env);
172 return GNUNET_OK;
173}
174
175static void
176change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
177 const char *name)
178{
179 GNUNET_assert(handle);
180
181 if (handle->name)
182 GNUNET_free(handle->name);
183
184 handle->name = name ? GNUNET_strdup(name) : NULL;
185
186 const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
187
188 struct GNUNET_MESSENGER_NameMessage *msg;
189 struct GNUNET_MQ_Envelope *env;
190
191 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
192
193 char *extra = ((char*) msg) + sizeof(*msg);
194
195 if (name_len)
196 GNUNET_memcpy(extra, handle->name, name_len);
197
198 extra[name_len] = '\0';
199
200 GNUNET_MQ_send (handle->mq, env);
201}
202
203static void
204change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
205 const struct GNUNET_MESSENGER_Ego *ego)
206{
207 GNUNET_assert(handle);
208
209 handle->ego = ego;
210
211 ego = get_handle_ego (handle);
212
213 const uint16_t length = GNUNET_IDENTITY_key_get_length(&(ego->pub));
214
215 struct GNUNET_MESSENGER_KeyMessage *msg;
216 struct GNUNET_MQ_Envelope *env;
217
218 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
219
220 char *extra = ((char*) msg) + sizeof(*msg);
221
222 if (GNUNET_IDENTITY_write_key_to_buffer(&(ego->pub), extra, length) < 0)
223 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
224
225 GNUNET_MQ_send (handle->mq, env);
226}
227
228struct GNUNET_MESSENGER_MessageHandle
229{
230 struct GNUNET_MESSENGER_SrvHandle *handle;
231 struct GNUNET_MESSENGER_Message *message;
232};
233
234static int
235iterate_send_message (void *cls,
236 const struct GNUNET_HashCode *key,
237 void *value)
238{
239 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
240
241 send_handle_message (msg_handle->handle, key, msg_handle->message);
242
243 return GNUNET_YES;
244}
245
246void
247set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
248 const struct GNUNET_MESSENGER_Ego *ego)
249{
250 GNUNET_assert((handle) && (ego));
251
252 struct GNUNET_MESSENGER_MessageHandle msg_handle;
253
254 msg_handle.handle = handle;
255 msg_handle.message = create_message_key (&(ego->priv));
256
257 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
258
259 destroy_message (msg_handle.message);
260
261 change_handle_ego (handle, ego);
262}
263
264const struct GNUNET_MESSENGER_Ego*
265get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
266{
267 GNUNET_assert(handle);
268
269 static struct GNUNET_MESSENGER_Ego anonymous;
270 static int read_keys = 0;
271
272 if (handle->ego)
273 return handle->ego;
274
275 if (!read_keys)
276 {
277 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
278 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
279 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
280 read_keys = 1;
281 }
282
283 return &anonymous;
284}
285
286static void
287callback_setup_handle_name (void *cls,
288 const char *name,
289 const struct GNUNET_MESSENGER_Ego *ego)
290{
291 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
292
293 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
294
295 change_handle_name (handle, name);
296 change_handle_ego (handle, ego);
297
298 if (handle->service->dir)
299 load_handle_configuration (handle);
300}
301
302void
303setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
304 const char *name)
305{
306 GNUNET_assert(handle);
307
308 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
309
310 lookup_store_ego (store, name, callback_setup_handle_name, handle);
311}
312
313static void
314callback_update_handle (void *cls,
315 const char *name,
316 const struct GNUNET_MESSENGER_Ego *ego)
317{
318 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
319
320 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
321
322 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
323
324 if (!ego)
325 create_store_ego(store, handle->name, handle);
326 else
327 change_handle_ego (handle, ego);
328}
329
330void
331update_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
332{
333 GNUNET_assert(handle);
334
335 if (!handle->name)
336 {
337 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
338 return;
339 }
340
341 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
342
343 lookup_store_ego (store, handle->name, callback_update_handle, handle);
344}
345
346static void
347callback_set_handle_name (void *cls,
348 const char *name,
349 const struct GNUNET_MESSENGER_Ego *ego)
350{
351 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
352
353 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
354
355 if (ego)
356 {
357 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
358 return;
359 }
360
361 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
362
363 int rename_ego_in_store = handle->ego? GNUNET_YES : GNUNET_NO;
364
365 char *old_dir;
366 get_handle_data_subdir (handle, handle->name, &old_dir);
367
368 char *new_dir;
369 get_handle_data_subdir (handle, name, &new_dir);
370
371 int result = 0;
372
373 if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
374 {
375 GNUNET_DISK_directory_create_for_file (new_dir);
376
377 result = rename (old_dir, new_dir);
378 }
379 else if (GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO))
380 result = -1;
381
382 if (0 == result)
383 {
384 struct GNUNET_MESSENGER_MessageHandle msg_handle;
385
386 msg_handle.handle = handle;
387 msg_handle.message = create_message_name (name);
388
389 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
390
391 destroy_message (msg_handle.message);
392
393 change_handle_name (handle, name);
394 }
395 else
396 rename_ego_in_store = GNUNET_NO;
397
398 GNUNET_free(old_dir);
399 GNUNET_free(new_dir);
400
401 if (GNUNET_YES == rename_ego_in_store)
402 rename_store_ego(store, handle->name, name);
403}
404
405void
406set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
407 const char *name)
408{
409 GNUNET_assert(handle);
410
411 if (!name)
412 {
413 if (handle->ego)
414 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
415 else
416 change_handle_name (handle, name);
417
418 return;
419 }
420
421 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
422
423 lookup_store_ego (store, name, callback_set_handle_name, handle);
424}
425
426int
427open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
428 const struct GNUNET_HashCode *key)
429{
430 GNUNET_assert((handle) && (key));
431
432 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
433 return GNUNET_NO;
434
435 return open_service_room (handle->service, handle, key);
436}
437
438int
439entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
440 const struct GNUNET_PeerIdentity *door,
441 const struct GNUNET_HashCode *key)
442{
443 GNUNET_assert((handle) && (door) && (key));
444
445 if ((!get_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
446 return GNUNET_NO;
447
448 return entry_service_room (handle->service, handle, door, key);
449}
450
451int
452close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
453 const struct GNUNET_HashCode *key)
454{
455 GNUNET_assert((handle) && (key));
456
457 if (!get_handle_member_id (handle, key))
458 return GNUNET_NO;
459
460 return close_service_room (handle->service, handle, key);
461}
462
463int
464send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
465 const struct GNUNET_HashCode *key,
466 const struct GNUNET_MESSENGER_Message *message)
467{
468 GNUNET_assert((handle) && (key) && (message));
469
470 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
471
472 if (!id)
473 {
474 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n");
475 return GNUNET_NO;
476 }
477
478 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key);
479
480 if (!room)
481 {
482 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key));
483 return GNUNET_NO;
484 }
485
486 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
487
488 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
489
490 return send_room_message (room, handle, msg);
491}
492
493static const struct GNUNET_HashCode*
494get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
495{
496 if (session->next)
497 return get_next_member_session_contect (session->next);
498 else
499 return get_member_session_context(session);
500}
501
502static const struct GNUNET_MESSENGER_MemberSession*
503get_handle_member_session (struct GNUNET_MESSENGER_SrvHandle *handle,
504 struct GNUNET_MESSENGER_SrvRoom *room,
505 const struct GNUNET_HashCode *key)
506{
507 GNUNET_assert((handle) && (room) && (key) && (handle->service));
508
509 const struct GNUNET_ShortHashCode *id = get_handle_member_id(handle, key);
510
511 if (!id)
512 return NULL;
513
514 struct GNUNET_MESSENGER_MemberStore *store = get_room_member_store(room);
515 struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
516
517 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
518
519 if (!ego)
520 return NULL;
521
522 return get_member_session(member, &(ego->pub));
523}
524
525void
526notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
527 struct GNUNET_MESSENGER_SrvRoom *room,
528 const struct GNUNET_MESSENGER_MemberSession *session,
529 const struct GNUNET_MESSENGER_Message *message,
530 const struct GNUNET_HashCode *hash)
531{
532 GNUNET_assert((handle) && (room) && (session) && (message) && (hash));
533
534 const struct GNUNET_HashCode *key = get_room_key(room);
535
536 if ((!handle->mq) || (!get_handle_member_id (handle, key)))
537 {
538 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
539 return;
540 }
541
542 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
543
544 struct GNUNET_HashCode sender;
545 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
546
547 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
548
549 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
550
551 struct GNUNET_MESSENGER_Message *private_message = NULL;
552
553 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
554 {
555 private_message = copy_message(message);
556
557 if (GNUNET_YES != decrypt_message(private_message, &(get_handle_ego(handle)->priv)))
558 {
559 destroy_message(private_message);
560 private_message = NULL;
561 }
562 else
563 message = private_message;
564 }
565
566 struct GNUNET_MESSENGER_RecvMessage *msg;
567 struct GNUNET_MQ_Envelope *env;
568
569 uint16_t length = get_message_size (message, GNUNET_YES);
570
571 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
572
573 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
574 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
575 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
576 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
577
578 msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
579
580 if (get_handle_member_session(handle, room, key) == session)
581 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
582
583 if (private_message)
584 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
585
586 char *buffer = ((char*) msg) + sizeof(*msg);
587 encode_message (message, length, buffer, GNUNET_YES);
588
589 if (private_message)
590 destroy_message(private_message);
591
592 GNUNET_MQ_send (handle->mq, env);
593}
594
595static int
596callback_scan_for_rooms (void *cls,
597 const char *filename)
598{
599 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
600
601 if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, ".cfg")))
602 return GNUNET_OK;
603
604 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load room configuration of handle: %s\n", filename);
605
606 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
607
608 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
609 {
610 struct GNUNET_HashCode key;
611 struct GNUNET_ShortHashCode member_id;
612
613 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
614 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
615 change_handle_member_id (handle, &key, &member_id);
616 }
617
618 GNUNET_CONFIGURATION_destroy (cfg);
619 return GNUNET_OK;
620}
621
622void
623load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
624{
625 GNUNET_assert(handle);
626
627 char *id_dir;
628 get_handle_data_subdir (handle, handle->name, &id_dir);
629
630 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
631 {
632 char *scan_dir;
633 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
634
635 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
636 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
637
638 GNUNET_free(scan_dir);
639 }
640
641 GNUNET_free(id_dir);
642}
643
644static int
645iterate_save_rooms (void *cls,
646 const struct GNUNET_HashCode *key,
647 void *value)
648{
649 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
650 struct GNUNET_ShortHashCode *member_id = value;
651
652 char *id_dir;
653 get_handle_data_subdir (handle, handle->name, &id_dir);
654
655 char *filename;
656 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
657 GNUNET_free(id_dir);
658
659 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save room configuration of handle: %s\n", filename);
660
661 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
662
663 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
664
665 if (key_data)
666 {
667 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
668
669 GNUNET_free(key_data);
670 }
671
672 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
673
674 if (member_id_data)
675 {
676 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
677
678 GNUNET_free(member_id_data);
679 }
680
681 GNUNET_CONFIGURATION_write (cfg, filename);
682 GNUNET_CONFIGURATION_destroy (cfg);
683
684 GNUNET_free(filename);
685
686 return GNUNET_YES;
687}
688
689void
690save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
691{
692 GNUNET_assert(handle);
693
694 char *id_dir;
695 get_handle_data_subdir (handle, handle->name, &id_dir);
696
697 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
698 == GNUNET_DISK_directory_create (id_dir)))
699 {
700 char *save_dir;
701 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
702
703 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
704 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
705 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
706
707 GNUNET_free(save_dir);
708 }
709
710 GNUNET_free(id_dir);
711}
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h
deleted file mode 100644
index 4438570b9..000000000
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ /dev/null
@@ -1,252 +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,
64 struct GNUNET_MQ_Handle *mq);
65
66/**
67 * Destroys a handle and frees its memory fully.
68 *
69 * @param[in/out] handle Handle
70 */
71void
72destroy_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
73
74/**
75 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter
76 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages.
77 *
78 * @param[in] handle Handle
79 * @param[in] name Potential name of the handle
80 * @param[out] dir Path to store data
81 */
82void
83get_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
84 const char *name,
85 char **dir);
86
87/**
88 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>.
89 *
90 * If the handle is not a member of the specific <i>room</i>, NULL gets returned.
91 *
92 * @param[in] handle Handle
93 * @param[in] key Key of a room
94 * @return Member id or NULL
95 */
96const struct GNUNET_ShortHashCode*
97get_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
98 const struct GNUNET_HashCode *key);
99
100/**
101 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>
102 * and returns GNUNET_OK on success.
103 *
104 * The client connected to the <i>handle</i> will be informed afterwards automatically.
105 *
106 * @param[in/out] handle Handle
107 * @param[in] key Key of a room
108 * @param[in] unique_id Unique member id
109 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
110 */
111int
112change_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
113 const struct GNUNET_HashCode *key,
114 const struct GNUNET_ShortHashCode *unique_id);
115
116/**
117 * Sets the EGO used by a given <i>handle</i>.
118 *
119 * @param[in/out] handle Handle
120 * @param[in] ego EGO key pair
121 */
122void
123set_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
124 const struct GNUNET_MESSENGER_Ego *ego);
125
126/**
127 * Returns the EGO used by a given <i>handle</i>.
128 *
129 * @param[in] handle Handle
130 * @return EGO key pair
131 */
132const struct GNUNET_MESSENGER_Ego*
133get_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
134
135/**
136 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>.
137 *
138 * @param[in/out] handle Handle
139 * @param[in] name Name (optionally: valid EGO name)
140 */
141void
142setup_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
143 const char *name);
144
145/**
146 * Tries to change the key pair of an EGO of a <i>handle</i> under the same name and informs all rooms
147 * about the change automatically.
148 *
149 * @param[in/out] handle Handle
150 */
151void
152update_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
153
154/**
155 * Tries to rename the handle which implies renaming the EGO its using and moving all related data into
156 * the directory fitting to the changed <i>name</i>.
157 *
158 * The client connected to the <i>handle</i> will be informed afterwards automatically.
159 *
160 * @param[in/out] handle Handle
161 * @param[in] name New name
162 */
163void
164set_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
165 const char *name);
166
167/**
168 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the
169 * room from the handles service.
170 *
171 * @param[in/out] handle Handle
172 * @param[in] key Key of a room
173 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
174 */
175int
176open_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
177 const struct GNUNET_HashCode *key);
178
179/**
180 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room
181 * through a tunnel to a peer identified by a given <i>door</i> (peer identity).
182 *
183 * @param[in/out] handle Handle
184 * @param[in] door Peer identity
185 * @param[in] key Key of a room
186 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
187 */
188int
189entry_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
190 const struct GNUNET_PeerIdentity *door,
191 const struct GNUNET_HashCode *key);
192
193/**
194 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle
195 * from this service is still a member of it.
196 *
197 * @param[in/out] handle Handle
198 * @param[in] key Key of a room
199 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
200 */
201int
202close_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
203 const struct GNUNET_HashCode *key);
204
205/**
206 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>.
207 *
208 * @param[in/out] handle Handle
209 * @param[in] key Key of a room
210 * @param[in] message Message
211 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
212 */
213int
214send_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
215 const struct GNUNET_HashCode *key,
216 const struct GNUNET_MESSENGER_Message *message);
217
218/**
219 * Notifies the handle that a new message was received or sent.
220 *
221 * @param[in/out] handle Handle
222 * @param[in] room Room of the message
223 * @param[in] session Member session
224 * @param[in] message Message
225 * @param[in] hash Hash of message
226 */
227void
228notify_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
229 struct GNUNET_MESSENGER_SrvRoom *room,
230 const struct GNUNET_MESSENGER_MemberSession *session,
231 const struct GNUNET_MESSENGER_Message *message,
232 const struct GNUNET_HashCode *hash);
233
234/**
235 * Loads member ids and other potential configuration from a given <i>handle</i> which
236 * depends on the given name the <i>handle</i> uses.
237 *
238 * @param[out] handle Handle
239 */
240void
241load_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
242
243/**
244 * Saves member ids and other potential configuration from a given <i>handle</i> which
245 * depends on the given name the <i>handle</i> uses.
246 *
247 * @param[in] handle Handle
248 */
249void
250save_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
251
252#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 c0ae18716..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.c
+++ /dev/null
@@ -1,104 +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,
59 struct GNUNET_MESSENGER_SrvHandle *handle)
60{
61 GNUNET_assert((handles) && (handle));
62
63 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle);
64
65 element->handle = handle;
66
67 GNUNET_CONTAINER_DLL_insert_tail(handles->head, handles->tail, element);
68}
69
70int
71remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
72 struct GNUNET_MESSENGER_SrvHandle *handle)
73{
74 GNUNET_assert((handles) && (handle));
75
76 struct GNUNET_MESSENGER_ListHandle *element;
77
78 for (element = handles->head; element; element = element->next)
79 if (element->handle == handle)
80 break;
81
82 if (!element)
83 return GNUNET_NO;
84
85 GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element);
86 GNUNET_free(element);
87
88 return GNUNET_YES;
89}
90
91struct GNUNET_MESSENGER_SrvHandle*
92find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles,
93 const struct GNUNET_HashCode *key)
94{
95 GNUNET_assert((handles) && (key));
96
97 struct GNUNET_MESSENGER_ListHandle *element;
98
99 for (element = handles->head; element; element = element->next)
100 if (get_handle_member_id ((struct GNUNET_MESSENGER_SrvHandle*) element->handle, key))
101 return element->handle;
102
103 return NULL;
104}
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 f4d7ca5c0..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.h
+++ /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.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,
73 struct GNUNET_MESSENGER_SrvHandle *handle);
74
75/**
76 * Removes the first entry matching with a specific <i>handle</i> from the list of
77 * <i>handles</i> and returns #GNUNET_YES on success or #GNUNET_NO on failure.
78 *
79 * @param[in/out] handles List of handles
80 * @param[in/out] handle Handle
81 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
82 */
83int
84remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
85 struct GNUNET_MESSENGER_SrvHandle *handle);
86
87/**
88 * Searches linearly through the list of <i>handles</i> for members of a specific room
89 * which is identified by a given <i>key</i>.
90 *
91 * If no handle is found which is a current member, NULL gets returned.
92 *
93 * @param[in] handles List of handles
94 * @param[in] key Common key of a room
95 * @return First handle which is a current member
96 */
97struct GNUNET_MESSENGER_SrvHandle*
98find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles,
99 const struct GNUNET_HashCode *key);
100
101#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 7092dc76f..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.c
+++ /dev/null
@@ -1,155 +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,
56 const struct GNUNET_HashCode *hash)
57{
58 GNUNET_assert((messages) && (hash));
59
60 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage);
61
62 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
63
64 GNUNET_CONTAINER_DLL_insert_tail(messages->head, messages->tail, element);
65}
66
67void
68copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
69 const struct GNUNET_MESSENGER_ListMessages *origin)
70{
71 GNUNET_assert((messages) && (origin));
72
73 struct GNUNET_MESSENGER_ListMessage *element;
74
75 for (element = origin->head; element; element = element->next)
76 add_to_list_messages (messages, &(element->hash));
77}
78
79void
80remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
81 const struct GNUNET_HashCode *hash)
82{
83 GNUNET_assert((messages) && (hash));
84
85 struct GNUNET_MESSENGER_ListMessage *element;
86
87 for (element = messages->head; element; element = element->next)
88 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), hash))
89 {
90 GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element);
91 GNUNET_free(element);
92 break;
93 }
94}
95
96void
97load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
98 const char *path)
99{
100 GNUNET_assert((messages) && (path));
101
102 if (GNUNET_YES != GNUNET_DISK_file_test (path))
103 return;
104
105 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
106
107 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
108 path, GNUNET_DISK_OPEN_READ, permission
109 );
110
111 if (!handle)
112 return;
113
114 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
115
116 struct GNUNET_HashCode hash;
117 ssize_t len;
118
119 do {
120 len = GNUNET_DISK_file_read(handle, &hash, sizeof(hash));
121
122 if (len != sizeof(hash))
123 break;
124
125 add_to_list_messages(messages, &hash);
126 } while (len == sizeof(hash));
127
128 GNUNET_DISK_file_close(handle);
129}
130
131void
132save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages,
133 const char *path)
134{
135 GNUNET_assert((messages) && (path));
136
137 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
138
139 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
140 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
141 );
142
143 if (!handle)
144 return;
145
146 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
147
148 struct GNUNET_MESSENGER_ListMessage *element;
149
150 for (element = messages->head; element; element = element->next)
151 GNUNET_DISK_file_write(handle, &(element->hash), sizeof(element->hash));
152
153 GNUNET_DISK_file_sync(handle);
154 GNUNET_DISK_file_close(handle);
155}
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 7abc8c00f..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.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/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,
72 const struct GNUNET_HashCode *hash);
73
74/**
75 * Copies all message hashes from an <i>origin</i> to another list.
76 *
77 * @param[in/out] messages Destination list of hashes
78 * @param[in] origin Source list of hashes
79 */
80void
81copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
82 const struct GNUNET_MESSENGER_ListMessages *origin);
83
84/**
85 * Removes the first entry with a matching <i>hash</i> from the list.
86 *
87 * @param[in/out] messages List of hashes
88 * @param[in] hash Hash of message
89 */
90void
91remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
92 const struct GNUNET_HashCode *hash);
93
94/**
95 * Loads the list of message hashes from a file under a given <i>path</i>.
96 *
97 * @param[out] messages List of hashes
98 * @param[in] path Path of file
99 */
100void
101load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
102 const char *path);
103
104/**
105 * Saves the list of message hashes to a file under a given <i>path</i>.
106 *
107 * @param[in] messages List of hashes
108 * @param[in] path Path of file
109 */
110void
111save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages,
112 const char *path);
113
114#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 976b68fe6..000000000
--- a/src/messenger/gnunet-service-messenger_member.c
+++ /dev/null
@@ -1,415 +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,
32 const struct GNUNET_ShortHashCode *id)
33{
34 GNUNET_assert (store);
35
36 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
37
38 member->store = store;
39
40 if (id)
41 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
42 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
43 {
44 GNUNET_free (member);
45 return NULL;
46 }
47
48 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
49
50 return member;
51}
52
53static int
54iterate_destroy_session (void *cls,
55 const struct GNUNET_HashCode *key,
56 void *value)
57{
58 struct GNUNET_MESSENGER_MemberSession *session = value;
59 destroy_member_session(session);
60 return GNUNET_YES;
61}
62
63void
64destroy_member (struct GNUNET_MESSENGER_Member *member)
65{
66 GNUNET_assert((member) && (member->sessions));
67
68 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
69 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
70
71 GNUNET_free (member);
72}
73
74const struct GNUNET_ShortHashCode*
75get_member_id (const struct GNUNET_MESSENGER_Member *member)
76{
77 GNUNET_assert (member);
78
79 return &(member->id);
80}
81
82static int
83callback_scan_for_sessions (void *cls,
84 const char *filename)
85{
86 struct GNUNET_MESSENGER_Member *member = cls;
87
88 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
89 {
90 char *directory;
91
92 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
93
94 load_member_session(member, directory);
95 GNUNET_free (directory);
96 }
97
98 return GNUNET_OK;
99}
100
101void
102load_member (struct GNUNET_MESSENGER_MemberStore *store,
103 const char *directory)
104{
105 GNUNET_assert ((store) && (directory));
106
107 char *config_file;
108 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
109
110 struct GNUNET_MESSENGER_Member *member = NULL;
111
112 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
113 goto free_config;
114
115 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load member configuration: %s\n", config_file);
116
117 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
118
119 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
120 {
121 struct GNUNET_ShortHashCode id;
122
123 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
124 goto destroy_config;
125
126 member = add_store_member(store, &id);
127 }
128
129destroy_config:
130
131 GNUNET_CONFIGURATION_destroy (cfg);
132
133free_config:
134 GNUNET_free(config_file);
135
136 if (!member)
137 return;
138
139 char *scan_dir;
140 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
141
142 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
143 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
144
145 GNUNET_free(scan_dir);
146}
147
148static int
149iterate_load_next_session (void *cls,
150 const struct GNUNET_HashCode *key,
151 void *value)
152{
153 const char* sessions_directory = cls;
154
155 char* load_dir;
156 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
157
158 struct GNUNET_MESSENGER_MemberSession *session = value;
159
160 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
161 load_member_session_next (session, load_dir);
162
163 GNUNET_free (load_dir);
164 return GNUNET_YES;
165}
166
167void
168load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member,
169 const char *directory)
170{
171 GNUNET_assert ((member) && (directory));
172
173 char* load_dir;
174 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
175
176 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
177
178 GNUNET_free(load_dir);
179}
180
181static int
182iterate_save_session (void *cls,
183 const struct GNUNET_HashCode *key,
184 void *value)
185{
186 const char* sessions_directory = cls;
187
188 char* save_dir;
189 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
190
191 struct GNUNET_MESSENGER_MemberSession *session = value;
192
193 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
194 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
195 save_member_session (session, save_dir);
196
197 GNUNET_free (save_dir);
198 return GNUNET_YES;
199}
200
201void
202save_member (struct GNUNET_MESSENGER_Member *member,
203 const char *directory)
204{
205 GNUNET_assert ((member) && (directory));
206
207 char *config_file;
208 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
209
210 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save member configuration: %s\n", config_file);
211
212 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
213
214 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
215
216 if (id_data)
217 {
218 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
219
220 GNUNET_free(id_data);
221 }
222
223 GNUNET_CONFIGURATION_write (cfg, config_file);
224 GNUNET_CONFIGURATION_destroy (cfg);
225
226 GNUNET_free(config_file);
227
228 char* save_dir;
229 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
230
231 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
232 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
233 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
234
235 GNUNET_free(save_dir);
236}
237
238static void
239sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session,
240 struct GNUNET_MESSENGER_MemberSession *next)
241{
242 GNUNET_assert((session) && (next));
243
244 if (session == next)
245 return;
246
247 if (next->next)
248 sync_session_contact_from_next (session, next->next);
249 else
250 session->contact = next->contact;
251}
252
253static int
254iterate_sync_session_contact (void *cls,
255 const struct GNUNET_HashCode *key,
256 void *value)
257{
258 struct GNUNET_MESSENGER_MemberSession *session = value;
259
260 if (session->next)
261 sync_session_contact_from_next (session, session->next);
262
263 return GNUNET_YES;
264}
265
266void
267sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
268{
269 GNUNET_assert ((member) && (member->sessions));
270
271 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
272}
273
274struct GNUNET_MESSENGER_MemberSession*
275get_member_session (const struct GNUNET_MESSENGER_Member *member,
276 const struct GNUNET_IDENTITY_PublicKey *public_key)
277{
278 GNUNET_assert ((member) && (public_key));
279
280 struct GNUNET_HashCode hash;
281 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
282
283 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
284}
285
286struct GNUNET_MESSENGER_ClosureSearchSession {
287 const struct GNUNET_MESSENGER_Message *message;
288 const struct GNUNET_HashCode *hash;
289
290 struct GNUNET_MESSENGER_MemberSession *match;
291};
292
293static int
294iterate_search_session (void *cls,
295 const struct GNUNET_HashCode *key,
296 void *value)
297{
298 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
299 struct GNUNET_MESSENGER_MemberSession *session = value;
300
301 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
302 return GNUNET_YES;
303
304 search->match = session;
305 return GNUNET_NO;
306}
307
308static struct GNUNET_MESSENGER_MemberSession*
309try_member_session (struct GNUNET_MESSENGER_Member *member,
310 const struct GNUNET_IDENTITY_PublicKey *public_key)
311{
312 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
313
314 if (session)
315 return session;
316
317 session = create_member_session(member, public_key);
318
319 if (session)
320 add_member_session(member, session);
321
322 return session;
323}
324
325struct GNUNET_MESSENGER_MemberSession*
326get_member_session_of (struct GNUNET_MESSENGER_Member *member,
327 const struct GNUNET_MESSENGER_Message *message,
328 const struct GNUNET_HashCode *hash)
329{
330 GNUNET_assert ((member) && (message) && (hash) &&
331 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
332
333 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
334 return try_member_session(member, &(message->body.info.host_key));
335 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
336 return try_member_session(member, &(message->body.join.key));
337
338 struct GNUNET_MESSENGER_ClosureSearchSession search;
339
340 search.message = message;
341 search.hash = hash;
342
343 search.match = NULL;
344 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
345
346 return search.match;
347}
348
349void
350add_member_session (struct GNUNET_MESSENGER_Member *member,
351 struct GNUNET_MESSENGER_MemberSession *session)
352{
353 if (!session)
354 return;
355
356 GNUNET_assert((member) && (session->member == member));
357
358 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
359
360 struct GNUNET_HashCode hash;
361 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
362
363 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
364 member->sessions, &hash, session,
365 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
366 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
367 GNUNET_h2s(&hash));
368}
369
370void
371remove_member_session (struct GNUNET_MESSENGER_Member *member,
372 struct GNUNET_MESSENGER_MemberSession *session)
373{
374 GNUNET_assert ((member) && (session) && (session->member == member));
375
376 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
377
378 struct GNUNET_HashCode hash;
379 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
380
381 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
382 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
383 GNUNET_h2s(&hash));
384}
385
386struct GNUNET_MESSENGER_ClosureIterateSessions {
387 GNUNET_MESSENGER_MemberIteratorCallback it;
388 void *cls;
389};
390
391static int
392iterate_member_sessions_it (void *cls,
393 const struct GNUNET_HashCode *key,
394 void *value)
395{
396 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
397 struct GNUNET_MESSENGER_MemberSession *session = value;
398
399 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
400}
401
402int
403iterate_member_sessions (struct GNUNET_MESSENGER_Member *member,
404 GNUNET_MESSENGER_MemberIteratorCallback it,
405 void *cls)
406{
407 GNUNET_assert ((member) && (member->sessions) && (it));
408
409 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
410
411 iterate.it = it;
412 iterate.cls = cls;
413
414 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
415}
diff --git a/src/messenger/gnunet-service-messenger_member.h b/src/messenger/gnunet-service-messenger_member.h
deleted file mode 100644
index 46269315a..000000000
--- a/src/messenger/gnunet-service-messenger_member.h
+++ /dev/null
@@ -1,180 +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,
56 const struct GNUNET_ShortHashCode *id);
57
58/**
59 * Destroys a member and frees its memory fully.
60 *
61 * @param[in/out] member Member
62 */
63void
64destroy_member (struct GNUNET_MESSENGER_Member *member);
65
66/**
67 * Returns the current id of a given <i>member</i>.
68 *
69 * @param[in] member Member
70 * @return Member id
71 */
72const struct GNUNET_ShortHashCode*
73get_member_id (const struct GNUNET_MESSENGER_Member *member);
74
75/**
76 * Loads data from a <i>directory</i> into a new allocated and created member
77 * of a <i>store</i> if the required information can be read from the content
78 * of the given directory.
79 *
80 * @param[out] store Member store
81 * @param[in] directory Path to a directory
82 */
83void
84load_member (struct GNUNET_MESSENGER_MemberStore *store,
85 const char *directory);
86
87/**
88 * Loads data about next sessions from a <i>directory</i> into an empty loaded
89 * <i>member</i> which does not contain a fully built session graph yet.
90 *
91 * @param[in/out] member Member
92 * @param[in] directory Path to a directory
93 */
94void
95load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member,
96 const char *directory);
97
98/**
99 * Saves data from a <i>member</i> into a directory which
100 * can be load to restore the member completely.
101 *
102 * @param[in] member Member
103 * @param[in] directory Path to a directory
104 */
105void
106save_member (struct GNUNET_MESSENGER_Member *member,
107 const char *directory);
108
109/**
110 * Synchronizes contacts between all sessions from a given <i>member</i>
111 * and other sessions which are linked to them.
112 *
113 * @param[in/out] member Member
114 */
115void
116sync_member_contacts (struct GNUNET_MESSENGER_Member *member);
117
118/**
119 * Returns the member session of a <i>member</i> identified by a given public key.
120 * If the member does not provide a session with the given key, NULL gets returned.
121 *
122 * @param[in] member Member
123 * @param[in] public_key Public key of EGO
124 * @return Member session
125 */
126struct GNUNET_MESSENGER_MemberSession*
127get_member_session (const struct GNUNET_MESSENGER_Member *member,
128 const struct GNUNET_IDENTITY_PublicKey *public_key);
129
130/**
131 * Returns the member session of a <i>member</i> using a public key which can verify
132 * the signature of a given <i>message</i> and its <i>hash</i>. If the member does
133 * not provide a matching session, NULL gets returned.
134 *
135 * @param[in] member Member
136 * @param[in] message Message
137 * @param[in] hash Hash of message
138 * @return Member session
139 */
140struct GNUNET_MESSENGER_MemberSession*
141get_member_session_of (struct GNUNET_MESSENGER_Member *member,
142 const struct GNUNET_MESSENGER_Message *message,
143 const struct GNUNET_HashCode *hash);
144
145/**
146 * Adds a given member <i>session</i> to its <i>member</i>.
147 *
148 * @param[in/out] member Member
149 * @param[in/out] session Member session
150 */
151void
152add_member_session (struct GNUNET_MESSENGER_Member *member,
153 struct GNUNET_MESSENGER_MemberSession *session);
154
155/**
156 * Removes a given member <i>session</i> from its <i>member</i>.
157 *
158 * @param[in/out] member Member
159 * @param[in/out] session Member session
160 */
161void
162remove_member_session (struct GNUNET_MESSENGER_Member *member,
163 struct GNUNET_MESSENGER_MemberSession *session);
164
165/**
166 * Iterate through all member sessions currently connected to a given <i>member</i>
167 * and call the provided iterator callback with a selected closure. The function
168 * will return the amount of member sessions it iterated through.
169 *
170 * @param[in/out] member Member
171 * @param[in] it Iterator callback
172 * @param[in/out] cls Closure
173 * @return Amount of sessions iterated through
174 */
175int
176iterate_member_sessions (struct GNUNET_MESSENGER_Member *member,
177 GNUNET_MESSENGER_MemberIteratorCallback it,
178 void* cls);
179
180#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 846dbbe2b..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ /dev/null
@@ -1,759 +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,
162 const struct GNUNET_HashCode *key,
163 void *value)
164{
165 struct GNUNET_MESSENGER_MemberSession *next = cls;
166
167 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
168 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
169
170 return GNUNET_YES;
171}
172
173struct GNUNET_MESSENGER_MemberSession*
174switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
175 const struct GNUNET_MESSENGER_Message *message,
176 const struct GNUNET_HashCode *hash)
177{
178 if ((!session) || (!message) || (!hash))
179 return NULL;
180
181 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
182 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
183
184 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
185
186 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
187 next->member = add_store_member(session->member->store, &(message->body.id.id));
188 else
189 next->member = session->member;
190
191 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
192 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
193 else
194 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
195
196 get_context_from_member (
197 get_member_session_key (next),
198 get_member_session_id (next),
199 &(next->context)
200 );
201
202 update_store_contact(
203 get_member_contact_store(next->member->store),
204 get_member_session_contact(session),
205 get_member_session_context(session),
206 get_member_session_context(next),
207 get_member_session_public_key(next)
208 );
209
210 next->contact = get_member_session_contact(session);
211
212 if (!(next->contact))
213 {
214 GNUNET_free(next);
215 return NULL;
216 }
217
218 increase_contact_rc (next->contact);
219
220 next->history = GNUNET_CONTAINER_multihashmap_create(
221 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
222 );
223
224 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
225
226 init_list_messages(&(next->messages));
227 copy_list_messages(&(next->messages), &(session->messages));
228
229 session->next = next;
230 next->prev = session;
231 next->next = NULL;
232
233 next->start = GNUNET_TIME_absolute_get();
234
235 session->closed = GNUNET_YES;
236 next->closed = GNUNET_NO;
237 next->completed = GNUNET_NO;
238
239 check_member_session_completion (session);
240
241 return next;
242}
243
244void
245destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
246{
247 GNUNET_assert (session);
248
249 GNUNET_CONTAINER_multihashmap_destroy (session->history);
250
251 clear_list_messages (&(session->messages));
252
253 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
254
255 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
256 remove_store_contact (
257 get_member_contact_store(session->member->store),
258 contact,
259 get_member_session_context(session)
260 );
261
262 GNUNET_free(session);
263}
264
265int
266reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
267 const struct GNUNET_HashCode *hash)
268{
269 GNUNET_assert ((session) && (hash));
270
271 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
272 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
273 store,
274 get_member_session_context (session),
275 get_member_session_public_key (session)
276 );
277
278 if (!contact)
279 return GNUNET_SYSERR;
280
281 if (contact == session->contact)
282 goto clear_messages;
283
284 session->contact = contact;
285 increase_contact_rc (session->contact);
286
287clear_messages:
288 clear_list_messages(&(session->messages));
289 add_to_list_messages(&(session->messages), hash);
290
291 session->next = NULL;
292 session->closed = GNUNET_NO;
293 session->completed = GNUNET_NO;
294
295 return GNUNET_OK;
296}
297
298void
299close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
300{
301 GNUNET_assert (session);
302
303 session->closed = GNUNET_YES;
304 check_member_session_completion (session);
305}
306
307int
308is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
309{
310 GNUNET_assert(session);
311
312 return session->closed;
313}
314
315int
316is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
317{
318 GNUNET_assert(session);
319
320 return session->completed;
321}
322
323struct GNUNET_TIME_Absolute
324get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
325{
326 GNUNET_assert(session);
327
328 if (session->prev)
329 return get_member_session_start(session->prev);
330
331 return session->start;
332}
333
334const struct GNUNET_HashCode*
335get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
336{
337 GNUNET_assert((session) && (session->member));
338
339 return get_member_store_key(session->member->store);
340}
341
342const struct GNUNET_ShortHashCode*
343get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
344{
345 GNUNET_assert(session);
346
347 return get_member_id(session->member);
348}
349
350const struct GNUNET_IDENTITY_PublicKey*
351get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
352{
353 GNUNET_assert(session);
354
355 return &(session->public_key);
356}
357
358const struct GNUNET_HashCode*
359get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
360{
361 GNUNET_assert(session);
362
363 return &(session->context);
364}
365
366struct GNUNET_MESSENGER_Contact*
367get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
368{
369 GNUNET_assert (session);
370
371 return session->contact;
372}
373
374int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
375 const struct GNUNET_MESSENGER_Message *message,
376 const struct GNUNET_HashCode *hash)
377{
378 GNUNET_assert((session) && (message) && (hash));
379
380 if (GNUNET_YES == is_member_session_completed(session))
381 return GNUNET_SYSERR;
382
383 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
384 return GNUNET_SYSERR;
385
386 return verify_message(message, hash, get_member_session_public_key(session));
387}
388
389int
390check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
391 const struct GNUNET_HashCode *hash, int ownership)
392{
393 GNUNET_assert((session) && (hash));
394
395 if (GNUNET_YES == ownership)
396 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
397 else
398 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
399}
400
401static void
402update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
403 const struct GNUNET_HashCode *hash, int ownership)
404{
405 GNUNET_assert ((session) && (hash));
406
407 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
408 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
409 update_member_chain_history (session->next, hash, ownership);
410}
411
412void
413update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
414 const struct GNUNET_MESSENGER_Message *message,
415 const struct GNUNET_HashCode *hash)
416{
417 GNUNET_assert((session) && (message) && (hash));
418
419 if (GNUNET_YES == is_member_session_completed(session))
420 return;
421
422 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
423 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
424
425 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
426 {
427 if (GNUNET_YES == is_message_session_bound (message))
428 add_to_list_messages(&(session->messages), hash);
429
430 update_member_chain_history (session, hash, GNUNET_YES);
431 }
432 else
433 update_member_chain_history (session, hash, GNUNET_NO);
434
435 if (GNUNET_YES == session->closed)
436 check_member_session_completion(session);
437}
438
439static void
440clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
441 const struct GNUNET_HashCode *hash)
442{
443 GNUNET_assert ((session) && (hash));
444
445 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
446 clear_member_session_history(session->next, hash);
447}
448
449void
450clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
451 const struct GNUNET_HashCode *hash)
452{
453 GNUNET_assert((session) && (hash));
454
455 clear_member_chain_history (session, hash);
456}
457
458struct GNUNET_MESSENGER_MemberSessionHistoryEntry
459{
460 struct GNUNET_HashCode hash;
461 unsigned char ownership;
462};
463
464static void
465load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
466 const char *path)
467{
468 GNUNET_assert((session) && (path));
469
470 if (GNUNET_YES != GNUNET_DISK_file_test (path))
471 return;
472
473 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
474
475 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
476 path, GNUNET_DISK_OPEN_READ, permission
477 );
478
479 if (!handle)
480 return;
481
482 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
483
484 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
485 ssize_t len;
486
487 int status;
488
489 do {
490 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
491
492 if (len != sizeof(entry.hash))
493 break;
494
495 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
496
497 if (len != sizeof(entry.ownership))
498 break;
499
500 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
501 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
502 } while (status == GNUNET_OK);
503
504 GNUNET_DISK_file_close(handle);
505}
506
507void
508load_member_session (struct GNUNET_MESSENGER_Member *member,
509 const char *directory)
510{
511 GNUNET_assert ((member) && (directory));
512
513 char *config_file;
514 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
515
516 struct GNUNET_MESSENGER_MemberSession *session = NULL;
517
518 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
519 goto free_config;
520
521 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load session configuration of member: %s\n", config_file);
522
523 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
524
525 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
526 {
527 char *key_data;
528
529 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
530 goto destroy_config;
531
532 struct GNUNET_IDENTITY_PublicKey key;
533
534 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
535
536 GNUNET_free(key_data);
537
538 if (GNUNET_OK != key_return)
539 goto destroy_config;
540
541 session = create_member_session(member, &key);
542
543 unsigned long long numeric_value;
544
545 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
546 session->start.abs_value_us = numeric_value;
547
548 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
549 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
550
551 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "completed", &numeric_value))
552 session->completed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
553 }
554
555destroy_config:
556 GNUNET_CONFIGURATION_destroy (cfg);
557
558free_config:
559 GNUNET_free(config_file);
560
561 if (!session)
562 return;
563
564 char *history_file;
565 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
566
567 load_member_session_history (session, history_file);
568 GNUNET_free(history_file);
569
570 char *messages_file;
571 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
572
573 load_list_messages(&(session->messages), messages_file);
574 GNUNET_free(messages_file);
575
576 add_member_session(member, session);
577}
578
579static struct GNUNET_MESSENGER_MemberSession*
580get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session,
581 struct GNUNET_MESSENGER_MemberSession *next)
582{
583 if (!next)
584 return NULL;
585
586 struct GNUNET_MESSENGER_MemberSession *check = next;
587
588 do {
589 if (check == session)
590 return NULL;
591
592 check = check->next;
593 } while (check);
594
595 return next;
596}
597
598void
599load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session,
600 const char *directory)
601{
602 GNUNET_assert ((session) && (directory));
603
604 char *config_file;
605 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
606
607 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
608 goto free_config;
609
610 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load next session configuration of member: %s\n", config_file);
611
612 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
613
614 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
615 {
616 char *key_data;
617
618 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
619 goto destroy_config;
620
621 struct GNUNET_IDENTITY_PublicKey next_key;
622
623 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
624
625 GNUNET_free(key_data);
626
627 if (GNUNET_OK != key_return)
628 goto destroy_config;
629
630 struct GNUNET_ShortHashCode next_id;
631
632 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
633 goto destroy_config;
634
635 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
636
637 session->next = get_cycle_safe_next_session(
638 session, member? get_member_session (member, &next_key) : NULL
639 );
640
641 if (session->next)
642 session->next->prev = session;
643 }
644
645destroy_config:
646 GNUNET_CONFIGURATION_destroy (cfg);
647
648free_config:
649 GNUNET_free(config_file);
650}
651
652static int
653iterate_save_member_session_history_hentries (void *cls,
654 const struct GNUNET_HashCode *key,
655 void *value)
656{
657 struct GNUNET_DISK_FileHandle *handle = cls;
658 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
659
660 GNUNET_DISK_file_write(handle, key, sizeof(*key));
661 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
662
663 return GNUNET_YES;
664}
665
666static void
667save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
668 const char *path)
669{
670 GNUNET_assert((session) && (path));
671
672 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
673
674 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
675 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
676 );
677
678 if (!handle)
679 return;
680
681 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
682
683 GNUNET_CONTAINER_multihashmap_iterate(
684 session->history,
685 iterate_save_member_session_history_hentries,
686 handle
687 );
688
689 GNUNET_DISK_file_sync(handle);
690 GNUNET_DISK_file_close(handle);
691}
692
693void
694save_member_session (struct GNUNET_MESSENGER_MemberSession *session,
695 const char *directory)
696{
697 GNUNET_assert ((session) && (directory));
698
699 char *config_file;
700 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
701
702 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save session configuration of member: %s\n", config_file);
703
704 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
705
706 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
707
708 if (key_data)
709 {
710 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
711
712 GNUNET_free(key_data);
713 }
714
715 if (session->next)
716 {
717 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
718
719 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
720
721 if (next_id_data)
722 {
723 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
724
725 GNUNET_free(next_id_data);
726 }
727
728 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
729
730 if (key_data)
731 {
732 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
733
734 GNUNET_free(key_data);
735 }
736 }
737
738 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
739
740 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
741 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
742
743 GNUNET_CONFIGURATION_write (cfg, config_file);
744 GNUNET_CONFIGURATION_destroy (cfg);
745
746 GNUNET_free(config_file);
747
748 char *history_file;
749 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
750
751 save_member_session_history (session, history_file);
752 GNUNET_free(history_file);
753
754 char *messages_file;
755 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
756
757 save_list_messages(&(session->messages), messages_file);
758 GNUNET_free(messages_file);
759}
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 9ba801776..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.h
+++ /dev/null
@@ -1,292 +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,
229 int ownership);
230
231/**
232 * Adds a given <i>message</i> to the history of a <i>session</i> using the messages
233 * <i>hash</i>. The ownership will be set automatically.
234 *
235 * @see #is_member_session_completed() for updating a history.
236 *
237 * @param[in/out] session Member session
238 * @param[in] message Message
239 * @param[in] hash Hash of message
240 */
241void
242update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
243 const struct GNUNET_MESSENGER_Message *message,
244 const struct GNUNET_HashCode *hash);
245
246/**
247 * Removes a message from the history of a <i>session</i> using the messages
248 * <i>hash</i>.
249 *
250 * @param[in/out] session Member session
251 * @param[in] hash Hash of message
252 */
253void
254clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
255 const struct GNUNET_HashCode *hash);
256
257/**
258 * Loads data from a <i>directory</i> into a new allocated and created member
259 * session of a <i>member</i> if the required information can be read from the
260 * content of the given directory.
261 *
262 * @param[out] member Member
263 * @param[in] directory Path to a directory
264 */
265void
266load_member_session (struct GNUNET_MESSENGER_Member *member,
267 const char *directory);
268
269/**
270 * Loads the connection from one <i>session</i> to another through the
271 * next attribute. Necessary information will be loaded from a configuration
272 * file inside of a given <i>directory</i>.
273 *
274 * @param[in/out] session Member session
275 * @param[in] directory Path to a directory
276 */
277void
278load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session,
279 const char *directory);
280
281/**
282 * Saves data from a member <i>session</i> into a <i>directory</i> which can be
283 * load to restore the member session completely.
284 *
285 * @param[in] session Member session
286 * @param[in] directory Path to a directory
287 */
288void
289save_member_session (struct GNUNET_MESSENGER_MemberSession *session,
290 const char *directory);
291
292#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 e96ee3883..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.c
+++ /dev/null
@@ -1,268 +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,
34 struct GNUNET_MESSENGER_SrvRoom *room)
35{
36 GNUNET_assert ((store) && (room));
37
38 store->room = room;
39 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
40}
41
42static int
43iterate_destroy_members (void *cls,
44 const struct GNUNET_ShortHashCode *key,
45 void *value)
46{
47 struct GNUNET_MESSENGER_Member *member = value;
48 destroy_member(member);
49 return GNUNET_YES;
50}
51
52void
53clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
54{
55 GNUNET_assert ((store) && (store->members));
56
57 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
58 GNUNET_CONTAINER_multishortmap_destroy (store->members);
59}
60
61
62struct GNUNET_MESSENGER_ContactStore*
63get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
64{
65 GNUNET_assert ((store) && (store->room));
66
67 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
68
69 return get_service_contact_store(room->service);
70}
71
72const struct GNUNET_HashCode*
73get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
74{
75 GNUNET_assert (store);
76
77 return get_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
78}
79
80static int
81callback_scan_for_members (void *cls,
82 const char *filename)
83{
84 struct GNUNET_MESSENGER_MemberStore *store = cls;
85
86 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
87 {
88 char *directory;
89
90 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
91
92 load_member(store, directory);
93
94 GNUNET_free(directory);
95 }
96
97 return GNUNET_OK;
98}
99
100static int
101iterate_load_next_member_sessions (void *cls,
102 const struct GNUNET_ShortHashCode *id,
103 void *value)
104{
105 const char *sync_dir = cls;
106
107 struct GNUNET_MESSENGER_Member *member = value;
108
109 if (!member)
110 return GNUNET_YES;
111
112 char *member_dir;
113 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
114
115 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
116 load_member_next_sessions (member, member_dir);
117
118 GNUNET_free(member_dir);
119 return GNUNET_YES;
120}
121
122static int
123iterate_sync_member_contacts (void *cls,
124 const struct GNUNET_ShortHashCode *id,
125 void *value)
126{
127 struct GNUNET_MESSENGER_Member *member = value;
128
129 if (!member)
130 return GNUNET_YES;
131
132 sync_member_contacts (member);
133 return GNUNET_YES;
134}
135
136void
137load_member_store (struct GNUNET_MESSENGER_MemberStore *store,
138 const char *directory)
139{
140 GNUNET_assert ((store) && (directory));
141
142 char *scan_dir;
143 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
144
145 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
146 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
147
148 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
149 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
150
151 GNUNET_free(scan_dir);
152}
153
154static int
155iterate_save_members (void *cls,
156 const struct GNUNET_ShortHashCode *id,
157 void *value)
158{
159 const char *save_dir = cls;
160
161 struct GNUNET_MESSENGER_Member *member = value;
162
163 if (!member)
164 return GNUNET_YES;
165
166 char *member_dir;
167 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
168
169 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
170 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
171 save_member(member, member_dir);
172
173 GNUNET_free(member_dir);
174 return GNUNET_YES;
175}
176
177void
178save_member_store (struct GNUNET_MESSENGER_MemberStore *store,
179 const char *directory)
180{
181 GNUNET_assert ((store) && (directory));
182
183 char* save_dir;
184 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
185
186 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
187 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
188 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
189
190 GNUNET_free(save_dir);
191}
192
193struct GNUNET_MESSENGER_Member*
194get_store_member (const struct GNUNET_MESSENGER_MemberStore *store,
195 const struct GNUNET_ShortHashCode *id)
196{
197 GNUNET_assert ((store) && (store->members) && (id));
198
199 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
200}
201
202struct GNUNET_MESSENGER_Member*
203get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
204 const struct GNUNET_MESSENGER_Message *message)
205{
206 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
207 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
208 return add_store_member(store, &(message->header.sender_id));
209 else
210 return get_store_member(store, &(message->header.sender_id));
211}
212
213struct GNUNET_MESSENGER_Member*
214add_store_member (struct GNUNET_MESSENGER_MemberStore *store,
215 const struct GNUNET_ShortHashCode *id)
216{
217 GNUNET_assert ((store) && (store->members));
218
219 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
220
221 if (member)
222 return member;
223
224 member = create_member(store, id);
225
226 if (!member)
227 return NULL;
228
229 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
230 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
231 {
232 destroy_member(member);
233 return NULL;
234 }
235
236 return member;
237}
238
239struct GNUNET_MESSENGER_ClosureIterateMembers {
240 GNUNET_MESSENGER_MemberIteratorCallback it;
241 void *cls;
242};
243
244static int
245iterate_store_members_it (void *cls,
246 const struct GNUNET_ShortHashCode *key,
247 void *value)
248{
249 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
250 struct GNUNET_MESSENGER_Member *member = value;
251
252 return iterate_member_sessions(member, iterate->it, iterate->cls);
253}
254
255int
256iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store,
257 GNUNET_MESSENGER_MemberIteratorCallback it,
258 void* cls)
259{
260 GNUNET_assert ((store) && (store->members) && (it));
261
262 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
263
264 iterate.it = it;
265 iterate.cls = cls;
266
267 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
268}
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 af50f0d36..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.h
+++ /dev/null
@@ -1,158 +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,
60 struct GNUNET_MESSENGER_SrvRoom *room);
61
62/**
63 * Clears a member <i>store</i>, wipes its content and deallocates its memory.
64 *
65 * @param[in/out] store Member store
66 */
67void
68clear_member_store (struct GNUNET_MESSENGER_MemberStore *store);
69
70/**
71 * Returns the used contact store of a given member <i>store</i>.
72 *
73 * @param[in/out] store Member store
74 * @return Contact store
75 */
76struct GNUNET_MESSENGER_ContactStore*
77get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store);
78
79/**
80 * Returns the shared secret you need to access a room of the <i>store</i>.
81 *
82 * @param[in] store Member store
83 * @return Shared secret
84 */
85const struct GNUNET_HashCode*
86get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store);
87
88/**
89 * Loads members from a directory into a member <i>store</i>.
90 *
91 * @param[out] store Member store
92 * @param[in] directory Path to a directory
93 */
94void
95load_member_store (struct GNUNET_MESSENGER_MemberStore *store,
96 const char *directory);
97
98/**
99 * Saves members from a member <i>store</i> into a directory.
100 *
101 * @param[in] store Member store
102 * @param[in] directory Path to a directory
103 */
104void
105save_member_store (struct GNUNET_MESSENGER_MemberStore *store,
106 const char *directory);
107
108/**
109 * Returns the member in a <i>store</i> identified by a given <i>id</i>. If the <i>store</i>
110 * does not contain a member with the given <i>id</i>, NULL gets returned.
111 *
112 * @param[in] store Member store
113 * @param[in] id Member id
114 * @return Member or NULL
115 */
116struct GNUNET_MESSENGER_Member*
117get_store_member (const struct GNUNET_MESSENGER_MemberStore *store,
118 const struct GNUNET_ShortHashCode *id);
119
120/**
121 * Returns the member of a <i>store</i> using a sender id of a given <i>message</i>.
122 * If the member does not provide a matching session, NULL gets returned.
123 *
124 * @param[in/out] store Member store
125 * @param[in] message Message
126 * @return Member or NULL
127 */
128struct GNUNET_MESSENGER_Member*
129get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
130 const struct GNUNET_MESSENGER_Message *message);
131
132/**
133 * Adds a member to a <i>store</i> under a specific <i>id</i> and returns it on success.
134 *
135 * @param[in/out] store Member store
136 * @param[in] id Member id
137 * @return Member or NULL
138 */
139struct GNUNET_MESSENGER_Member*
140add_store_member (struct GNUNET_MESSENGER_MemberStore *store,
141 const struct GNUNET_ShortHashCode *id);
142
143/**
144 * Iterate through all member sessions currently connected to the members of the given
145 * member <i>store</i> and call the provided iterator callback with a selected closure.
146 * The function will return the amount of members it iterated through.
147 *
148 * @param[in/out] store Member store
149 * @param[in] it Iterator callback
150 * @param[in/out] cls Closure
151 * @return Amount of members iterated through
152 */
153int
154iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store,
155 GNUNET_MESSENGER_MemberIteratorCallback it,
156 void* cls);
157
158#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 701d78c89..000000000
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ /dev/null
@@ -1,153 +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,
31 const struct GNUNET_HashCode *hash)
32{
33 struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, message, hash);
34
35 if (next != session)
36 add_member_session(next->member, next);
37}
38
39void
40handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
41 struct GNUNET_MESSENGER_MemberSession *session,
42 const struct GNUNET_MESSENGER_Message *message,
43 const struct GNUNET_HashCode *hash)
44{
45 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
46 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
47
48 if (GNUNET_OK != reset_member_session(session, hash))
49 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
50
51 solve_room_member_collisions (
52 room,
53 &(message->body.join.key),
54 &(message->header.sender_id),
55 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
56 );
57}
58
59void
60handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
61 struct GNUNET_MESSENGER_MemberSession *session,
62 const struct GNUNET_MESSENGER_Message *message,
63 const struct GNUNET_HashCode *hash)
64{
65 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
66 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_room_key(room)));
67
68 close_member_session(session);
69}
70
71void
72handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
73 struct GNUNET_MESSENGER_MemberSession *session,
74 const struct GNUNET_MESSENGER_Message *message,
75 const struct GNUNET_HashCode *hash)
76{
77 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact(session);
78
79 if (!contact)
80 return;
81
82 set_contact_name (contact, message->body.name.name);
83}
84
85void
86handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
87 struct GNUNET_MESSENGER_MemberSession *session,
88 const struct GNUNET_MESSENGER_Message *message,
89 const struct GNUNET_HashCode *hash)
90{
91 handle_session_switch (session, message, hash);
92}
93
94void
95handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
96 struct GNUNET_MESSENGER_MemberSession *session,
97 const struct GNUNET_MESSENGER_Message *message,
98 const struct GNUNET_HashCode *hash)
99{
100 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer)))
101 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
102
103 if (room->peer_message)
104 rebuild_room_basement_structure (room);
105}
106
107void
108handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
109 struct GNUNET_MESSENGER_MemberSession *session,
110 const struct GNUNET_MESSENGER_Message *message,
111 const struct GNUNET_HashCode *hash)
112{
113 handle_session_switch (session, message, hash);
114
115 solve_room_member_collisions (
116 room,
117 get_member_session_public_key(session),
118 &(message->body.id.id),
119 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
120 );
121}
122
123void
124handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
125 struct GNUNET_MESSENGER_MemberSession *session,
126 const struct GNUNET_MESSENGER_Message *message,
127 const struct GNUNET_HashCode *hash)
128{
129 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL);
130
131 if (!element)
132 return;
133
134 remove_from_list_tunnels (&(room->basement), element);
135
136 if (room->peer_message)
137 rebuild_room_basement_structure (room);
138}
139
140void
141handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room,
142 struct GNUNET_MESSENGER_MemberSession *session,
143 const struct GNUNET_MESSENGER_Message *message,
144 const struct GNUNET_HashCode *hash)
145{
146 struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_ntoh (message->body.deletion.delay);
147 struct GNUNET_TIME_Absolute action = GNUNET_TIME_absolute_ntoh (message->header.timestamp);
148
149 action = GNUNET_TIME_absolute_add (action, delay);
150 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
151
152 delete_room_message (room, session, &(message->body.deletion.hash), delay);
153}
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 0e5be3408..000000000
--- a/src/messenger/gnunet-service-messenger_message_handle.h
+++ /dev/null
@@ -1,158 +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,
49 struct GNUNET_MESSENGER_MemberSession *session,
50 const struct GNUNET_MESSENGER_Message *message,
51 const struct GNUNET_HashCode *hash);
52
53/**
54 * Handles a received or sent leave message to make changes of current member information.
55 * (remove matching member and clear member info)
56 *
57 * @param[in/out] room Room of the message
58 * @param[in/out] session Member session
59 * @param[in] message LEAVE-Message
60 * @param[in] hash Hash of the message
61 */
62void
63handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
64 struct GNUNET_MESSENGER_MemberSession *session,
65 const struct GNUNET_MESSENGER_Message *message,
66 const struct GNUNET_HashCode *hash);
67
68/**
69 * Handles a received or sent name message to rename a current member.
70 * (change name of matching member)
71 *
72 * @param[in/out] room Room of the message
73 * @param[in/out] session Member session
74 * @param[in] message NAME-Message
75 * @param[in] hash Hash of the message
76 */
77void
78handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
79 struct GNUNET_MESSENGER_MemberSession *session,
80 const struct GNUNET_MESSENGER_Message *message,
81 const struct GNUNET_HashCode *hash);
82
83/**
84 * Handles a received or sent key message to change the key of a member and rearrange the contacts accordingly.
85 * (move the member in the contacts and change its key)
86 *
87 * @param[in/out] room Room of the message
88 * @param[in/out] session Member session
89 * @param[in] message KEY-Message
90 * @param[in] hash Hash of the message
91 */
92void
93handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
94 struct GNUNET_MESSENGER_MemberSession *session,
95 const struct GNUNET_MESSENGER_Message *message,
96 const struct GNUNET_HashCode *hash);
97
98/**
99 * Handles a received or sent peer message to make changes of the basement in the room.
100 * (add a new peer to the basement and restructure connections based on updated list of peers)
101 *
102 * @param[in/out] room Room of the message
103 * @param[in/out] session Member session
104 * @param[in] message PEER-Message
105 * @param[in] hash Hash of the message
106 */
107void
108handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
109 struct GNUNET_MESSENGER_MemberSession *session,
110 const struct GNUNET_MESSENGER_Message *message,
111 const struct GNUNET_HashCode *hash);
112
113/**
114 * Handles a received or sent id message to change a members id.
115 * (change id of matching member)
116 *
117 * @param[in/out] room Room of the message
118 * @param[in/out] session Member session
119 * @param[in] message ID-Message
120 * @param[in] hash Hash of the message
121 */
122void
123handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
124 struct GNUNET_MESSENGER_MemberSession *session,
125 const struct GNUNET_MESSENGER_Message *message,
126 const struct GNUNET_HashCode *hash);
127
128/**
129 * Handles a received or sent miss message to drop a peer from the basement in the room.
130 * (remove a peer from the basement and restructure connections based on updated list of peers)
131 *
132 * @param[in/out] room Room of the message
133 * @param[in/out] session Member session
134 * @param[in] message MISS-Message
135 * @param[in] hash Hash of the message
136 */
137void
138handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
139 struct GNUNET_MESSENGER_MemberSession *session,
140 const struct GNUNET_MESSENGER_Message *message,
141 const struct GNUNET_HashCode *hash);
142
143/**
144 * Handles a received or sent delete message to delete a specific message from the store.
145 * (remove a message from the store of a room under a given delay)
146 *
147 * @param[in/out] room Room of the message
148 * @param[in/out] session Member session
149 * @param[in] message DELETE-Message
150 * @param[in] hash Hash of the message
151 */
152void
153handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room,
154 struct GNUNET_MESSENGER_MemberSession *session,
155 const struct GNUNET_MESSENGER_Message *message,
156 const struct GNUNET_HashCode *hash);
157
158#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 2449b9230..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ /dev/null
@@ -1,241 +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,
194 const struct GNUNET_HashCode *key)
195{
196 if ((!door) || (!key))
197 return NULL;
198
199 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE);
200
201 if (!message)
202 return NULL;
203
204 GNUNET_memcpy(&(message->body.invite.door), door, sizeof(struct GNUNET_PeerIdentity));
205 GNUNET_memcpy(&(message->body.invite.key), key, sizeof(struct GNUNET_HashCode));
206
207 return message;
208}
209
210struct GNUNET_MESSENGER_Message*
211create_message_text (const char *text)
212{
213 if (!text)
214 return NULL;
215
216 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT);
217
218 if (!message)
219 return NULL;
220
221 message->body.text.text = GNUNET_strdup(text);
222 return message;
223}
224
225struct GNUNET_MESSENGER_Message*
226create_message_delete (const struct GNUNET_HashCode *hash,
227 const struct GNUNET_TIME_Relative delay)
228{
229 if (!hash)
230 return NULL;
231
232 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_DELETE);
233
234 if (!message)
235 return NULL;
236
237 GNUNET_memcpy(&(message->body.deletion.hash), hash, sizeof(struct GNUNET_HashCode));
238 message->body.deletion.delay = GNUNET_TIME_relative_hton (delay);
239
240 return message;
241}
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 508f19074..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ /dev/null
@@ -1,174 +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,
150 const struct GNUNET_HashCode *key);
151
152/**
153 * Creates and allocates a new <i>text message containing a string representing text.
154 * (all values are stored as copy)
155 *
156 * @param[in] text Text
157 * @return New message
158 */
159struct GNUNET_MESSENGER_Message*
160create_message_text (const char *text);
161
162/**
163 * Creates and allocates a new delete message containing the <i>hash</i> of a message to delete after a specific <i>delay</i>.
164 * (all values are stored as copy)
165 *
166 * @param[in] hash Hash of message
167 * @param[in] delay Delay of deletion
168 * @return New message
169 */
170struct GNUNET_MESSENGER_Message*
171create_message_delete (const struct GNUNET_HashCode *hash,
172 const struct GNUNET_TIME_Relative delay);
173
174#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 bb6ee6f17..000000000
--- a/src/messenger/gnunet-service-messenger_message_recv.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/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,
32 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
33 struct GNUNET_MESSENGER_MemberSession *session,
34 struct GNUNET_CONTAINER_MultiHashMap *map)
35{
36 if (session->prev)
37 forward_about_members (room, tunnel, session->prev, map);
38
39 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
40 struct GNUNET_MESSENGER_ListMessage *element;
41
42 for (element = session->messages.head; element; element = element->next)
43 {
44 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
45 continue;
46
47 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
48 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
49 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Forwarding of session message could be duplicated!\n");
50
51 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
52
53 if (message)
54 forward_tunnel_message(tunnel, message, &(element->hash));
55 }
56}
57
58static int
59iterate_forward_members (void *cls,
60 const struct GNUNET_IDENTITY_PublicKey *public_key,
61 struct GNUNET_MESSENGER_MemberSession *session)
62{
63 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
64
65 if (GNUNET_YES == is_member_session_completed(session))
66 return GNUNET_YES;
67
68 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
69
70 forward_about_members (tunnel->room, tunnel, session, map);
71
72 GNUNET_CONTAINER_multihashmap_destroy(map);
73 return GNUNET_YES;
74}
75
76int
77recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room,
78 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
79 const struct GNUNET_MESSENGER_Message *message,
80 const struct GNUNET_HashCode *hash)
81{
82 const uint32_t version = get_tunnel_messenger_version(tunnel);
83
84 if (GNUNET_OK != update_tunnel_messenger_version(tunnel, message->body.info.messenger_version))
85 {
86 disconnect_tunnel(tunnel);
87 return GNUNET_NO;
88 }
89
90 if (version == get_tunnel_messenger_version(tunnel))
91 return GNUNET_NO;
92
93 if (room->host)
94 {
95 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(room->host);
96
97 send_tunnel_message (tunnel, room->host, create_message_info(ego));
98 }
99
100 struct GNUNET_PeerIdentity peer;
101 get_tunnel_peer_identity(tunnel, &peer);
102
103 if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
104 {
105 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
106
107 iterate_store_members(member_store, iterate_forward_members, tunnel);
108 }
109
110 check_room_peer_status(room, tunnel);
111
112 return GNUNET_NO;
113}
114
115int
116recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
117 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
118 const struct GNUNET_MESSENGER_Message *message,
119 const struct GNUNET_HashCode *hash)
120{
121 struct GNUNET_PeerIdentity peer;
122 GNUNET_PEER_resolve (tunnel->peer, &peer);
123
124 if (0 == GNUNET_memcmp(&peer, &(message->body.peer.peer)))
125 {
126 if (!tunnel->peer_message)
127 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode);
128
129 GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
130 }
131
132 return GNUNET_YES;
133}
134
135static void
136callback_found_message (void *cls,
137 struct GNUNET_MESSENGER_SrvRoom *room,
138 const struct GNUNET_MESSENGER_Message *message,
139 const struct GNUNET_HashCode *hash)
140{
141 struct GNUNET_MESSENGER_SrvTunnel *tunnel = tunnel;
142
143 if (!message)
144 {
145 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
146
147 use_store_operation(
148 operation_store,
149 hash,
150 GNUNET_MESSENGER_OP_REQUEST,
151 GNUNET_MESSENGER_REQUEST_DELAY
152 );
153 }
154 else
155 forward_tunnel_message (tunnel, message, hash);
156}
157
158/*
159 * Function returns GNUNET_NO to drop forwarding the request.
160 * It will only be forwarded if it can't be answered!
161 */
162int
163recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
164 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
165 const struct GNUNET_MESSENGER_Message *message,
166 const struct GNUNET_HashCode *hash)
167{
168 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
169 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
170
171 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Request for message (%s)\n", GNUNET_h2s (hash));
172
173 if (!member)
174 return GNUNET_NO;
175
176 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
177
178 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
179 return GNUNET_NO;
180
181 if (GNUNET_NO == request_room_message(room, &(message->body.request.hash), session, callback_found_message, tunnel))
182 return GNUNET_YES;
183
184 return GNUNET_NO;
185}
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 400c10245..000000000
--- a/src/messenger/gnunet-service-messenger_message_recv.h
+++ /dev/null
@@ -1,87 +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,
50 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
51 const struct GNUNET_MESSENGER_Message *message,
52 const struct GNUNET_HashCode *hash);
53
54/**
55 * Handles a received peer message to link it to its origin tunnel if the peer identity matches.
56 * (the peer message and the member id can potentially be linked to the tunnel)
57 *
58 * @param[in/out] room Room of the message
59 * @param[in/out] tunnel Receiving connection
60 * @param[in] message PEER-Message
61 * @param[in] hash Hash of the message
62 * @return #GNUNET_YES to forward the message
63 */
64int
65recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
66 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
67 const struct GNUNET_MESSENGER_Message *message,
68 const struct GNUNET_HashCode *hash);
69
70/**
71 * Handles a received request message by checking for the requested message and forwarding it back
72 * if the message was found.
73 * (this can also cause this peer to send a new request instead of only forwarding the received one)
74 *
75 * @param[in/out] room Room of the message
76 * @param[in/out] tunnel Receiving connection
77 * @param[in] message REQUEST-Message
78 * @param[in] hash Hash of the message
79 * @return #GNUNET_YES or #GNUNET_NO depending on required forwarding
80 */
81int
82recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
83 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
84 const struct GNUNET_MESSENGER_Message *message,
85 const struct GNUNET_HashCode *hash);
86
87#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 8cc2466d7..000000000
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ /dev/null
@@ -1,76 +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,
34 struct GNUNET_MESSENGER_SrvHandle *handle,
35 const struct GNUNET_MESSENGER_Message *message,
36 const struct GNUNET_HashCode *hash)
37{
38 check_room_peer_status(room, NULL);
39}
40
41void
42send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
43 struct GNUNET_MESSENGER_SrvHandle *handle,
44 const struct GNUNET_MESSENGER_Message *message,
45 const struct GNUNET_HashCode *hash)
46{
47 if (!room->peer_message)
48 room->peer_message = GNUNET_new(struct GNUNET_HashCode);
49
50 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode));
51}
52
53void
54send_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
55 struct GNUNET_MESSENGER_SrvHandle *handle,
56 const struct GNUNET_MESSENGER_Message *message,
57 const struct GNUNET_HashCode *hash)
58{
59 change_handle_member_id (handle, get_room_key(room), &(message->body.id.id));
60}
61
62void
63send_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
64 struct GNUNET_MESSENGER_SrvHandle *handle,
65 const struct GNUNET_MESSENGER_Message *message,
66 const struct GNUNET_HashCode *hash)
67{
68 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
69
70 use_store_operation(
71 operation_store,
72 &(message->body.request.hash),
73 GNUNET_MESSENGER_OP_REQUEST,
74 GNUNET_MESSENGER_REQUEST_DELAY
75 );
76}
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 232355c41..000000000
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ /dev/null
@@ -1,97 +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,
48 struct GNUNET_MESSENGER_SrvHandle *handle,
49 const struct GNUNET_MESSENGER_Message *message,
50 const struct GNUNET_HashCode *hash);
51
52/**
53 * Handles a sent peer message to update the rooms peer message of this service.
54 * (a set peer message indicates this service being a part of the decentralized room structure)
55 *
56 * @param[in/out] room Room of the message
57 * @param[in/out] handle Sending handle
58 * @param[in] message PEER-Message
59 * @param[in] hash Hash of the message
60 */
61void
62send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
63 struct GNUNET_MESSENGER_SrvHandle *handle,
64 const struct GNUNET_MESSENGER_Message *message,
65 const struct GNUNET_HashCode *hash);
66
67/**
68 * Handles a sent id message to update the handles member id in the room.
69 * (changing member id is useful to prevent collisions)
70 *
71 * @param[in/out] room Room of the message
72 * @param[in/out] handle Sending handle
73 * @param[in] message ID-Message
74 * @param[in] hash Hash of the message
75 */
76void
77send_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
78 struct GNUNET_MESSENGER_SrvHandle *handle,
79 const struct GNUNET_MESSENGER_Message *message,
80 const struct GNUNET_HashCode *hash);
81
82/**
83 * Handles a sent request message to trigger the request operation for this service.
84 * (the request operation will deactivate the possibility of spamming requests)
85 *
86 * @param[in/out] room Room of the message
87 * @param[in/out] handle Sending handle
88 * @param[in] message PEER-Message
89 * @param[in] hash Hash of the message
90 */
91void
92send_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
93 struct GNUNET_MESSENGER_SrvHandle *handle,
94 const struct GNUNET_MESSENGER_Message *message,
95 const struct GNUNET_HashCode *hash);
96
97#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 344962d11..000000000
--- a/src/messenger/gnunet-service-messenger_message_state.c
+++ /dev/null
@@ -1,113 +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,
69 int requested,
70 const struct GNUNET_MESSENGER_Message *message,
71 const struct GNUNET_HashCode *hash)
72{
73 GNUNET_assert((state) && (message) && (hash));
74
75 if ((GNUNET_YES == requested) ||
76 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
77 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
78 return;
79
80 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
81 remove_from_list_messages(&(state->last_messages), &(message->body.merge.previous));
82 remove_from_list_messages(&(state->last_messages), &(message->header.previous));
83
84 add_to_list_messages (&(state->last_messages), hash);
85}
86
87void
88load_message_state (struct GNUNET_MESSENGER_MessageState *state,
89 const char *path)
90{
91 GNUNET_assert((state) && (path));
92
93 char *last_messages_file;
94 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
95
96 load_list_messages(&(state->last_messages), last_messages_file);
97 GNUNET_free(last_messages_file);
98}
99
100void
101save_message_state (const struct GNUNET_MESSENGER_MessageState *state,
102 const char *path)
103{
104 GNUNET_assert((state) && (path));
105
106 char *last_messages_file;
107 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
108
109 save_list_messages(&(state->last_messages), last_messages_file);
110 GNUNET_free(last_messages_file);
111}
112
113
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 af52b26b6..000000000
--- a/src/messenger/gnunet-service-messenger_message_state.h
+++ /dev/null
@@ -1,67 +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,
55 int requested,
56 const struct GNUNET_MESSENGER_Message *message,
57 const struct GNUNET_HashCode *hash);
58
59void
60load_message_state (struct GNUNET_MESSENGER_MessageState *state,
61 const char *path);
62
63void
64save_message_state (const struct GNUNET_MESSENGER_MessageState *state,
65 const char *path);
66
67#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 ddad266ad..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ /dev/null
@@ -1,582 +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,
46 const struct GNUNET_HashCode *key,
47 void *value)
48{
49 struct GNUNET_MESSENGER_MessageEntry *entry = value;
50
51 GNUNET_free(entry);
52
53 return GNUNET_YES;
54}
55
56static int
57iterate_destroy_messages (void *cls,
58 const struct GNUNET_HashCode *key,
59 void *value)
60{
61 struct GNUNET_MESSENGER_Message *message = value;
62
63 destroy_message (message);
64
65 return GNUNET_YES;
66}
67
68static int
69iterate_destroy_links (void *cls,
70 const struct GNUNET_HashCode *key,
71 void *value)
72{
73 struct GNUNET_HashCode *previous = value;
74
75 GNUNET_free(previous);
76
77 return GNUNET_YES;
78}
79
80void
81clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
82{
83 GNUNET_assert(store);
84
85 if (store->storage_messages)
86 {
87 GNUNET_DISK_file_close (store->storage_messages);
88
89 store->storage_messages = NULL;
90 }
91
92 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
93 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
94 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
95
96 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
97 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
98 GNUNET_CONTAINER_multihashmap_destroy (store->links);
99}
100
101struct GNUNET_MESSENGER_MessageEntryStorage
102{
103 struct GNUNET_HashCode hash;
104 struct GNUNET_MESSENGER_MessageEntry entry;
105};
106
107#define load_message_store_attribute_failed(file, attribute) \
108 sizeof(attribute) != GNUNET_DISK_file_read(file, &(attribute), sizeof(attribute))
109
110#define save_message_store_attribute_failed(file, attribute) \
111 sizeof(attribute) != GNUNET_DISK_file_write(file, &(attribute), sizeof(attribute))
112
113static void
114load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store,
115 const char *filename)
116{
117 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
118
119 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
120
121 if (!entries)
122 return;
123
124 struct GNUNET_MESSENGER_MessageEntryStorage storage;
125 struct GNUNET_MESSENGER_MessageEntry *entry;
126
127 memset(&storage, 0, sizeof(storage));
128
129 do
130 {
131 entry = NULL;
132
133 if ((load_message_store_attribute_failed(entries, storage.hash)) ||
134 (load_message_store_attribute_failed(entries, storage.entry.offset)) ||
135 (load_message_store_attribute_failed(entries, storage.entry.length)))
136 break;
137
138 entry = GNUNET_new(struct GNUNET_MESSENGER_MessageEntry);
139
140 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
141
142 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
143 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
144 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
145 {
146 store->rewrite_entries = GNUNET_YES;
147 break;
148 }
149 }
150 while (entry);
151
152 if (entry)
153 GNUNET_free(entry);
154
155 GNUNET_DISK_file_close (entries);
156}
157
158struct GNUNET_MESSENGER_MessageLinkStorage
159{
160 struct GNUNET_HashCode hash;
161 struct GNUNET_MESSENGER_MessageLink link;
162};
163
164static void
165load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store,
166 const char *filename)
167{
168 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
169
170 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
171
172 if (!entries)
173 return;
174
175 struct GNUNET_MESSENGER_MessageLinkStorage storage;
176 struct GNUNET_MESSENGER_MessageLink *link;
177
178 memset(&storage, 0, sizeof(storage));
179
180 do
181 {
182 link = NULL;
183
184 if ((load_message_store_attribute_failed(entries, storage.hash)) ||
185 (load_message_store_attribute_failed(entries, storage.link.multiple)) ||
186 (load_message_store_attribute_failed(entries, storage.link.first)) ||
187 ((GNUNET_YES == storage.link.multiple) &&
188 (load_message_store_attribute_failed(entries, storage.link.second))))
189 break;
190
191 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
192
193 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
194
195 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
196 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
197 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
198 break;
199 }
200 while (link);
201
202 if (link)
203 GNUNET_free(link);
204
205 GNUNET_DISK_file_close (entries);
206}
207
208void
209load_message_store (struct GNUNET_MESSENGER_MessageStore *store,
210 const char *directory)
211{
212 GNUNET_assert((store) && (directory));
213
214 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
215
216 if (store->storage_messages)
217 GNUNET_DISK_file_close (store->storage_messages);
218
219 char *filename;
220 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
221
222 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
223 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
224 else
225 store->storage_messages = NULL;
226
227 GNUNET_free(filename);
228
229 if (!store->storage_messages)
230 return;
231
232 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
233
234 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
235 load_message_store_entries(store, filename);
236
237 GNUNET_free(filename);
238
239 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
240
241 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
242 load_message_store_links(store, filename);
243
244 GNUNET_free(filename);
245}
246
247struct GNUNET_MESSENGER_ClosureMessageSave
248{
249 struct GNUNET_MESSENGER_MessageStore *store;
250
251 struct GNUNET_DISK_FileHandle *storage;
252};
253
254static int
255iterate_save_entries (void *cls,
256 const struct GNUNET_HashCode *key,
257 void *value)
258{
259 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
260 struct GNUNET_MESSENGER_MessageEntry *entry = value;
261
262 struct GNUNET_MESSENGER_MessageEntryStorage storage;
263
264 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
265 GNUNET_DISK_file_write (save->storage, &(entry->offset), sizeof(entry->offset));
266 GNUNET_DISK_file_write (save->storage, &(entry->length), sizeof(entry->length));
267
268 return GNUNET_YES;
269}
270
271static int
272iterate_save_messages (void *cls,
273 const struct GNUNET_HashCode *key,
274 void *value)
275{
276 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
277
278 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
279 return GNUNET_YES;
280
281 struct GNUNET_MESSENGER_Message *message = value;
282 struct GNUNET_MESSENGER_MessageEntryStorage storage;
283
284 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
285
286 storage.entry.length = get_message_size (message, GNUNET_YES);
287 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
288
289 if ((GNUNET_SYSERR == storage.entry.offset) ||
290 (save_message_store_attribute_failed(save->storage, storage.hash)) ||
291 (save_message_store_attribute_failed(save->storage, storage.entry.offset)) ||
292 (save_message_store_attribute_failed(save->storage, storage.entry.length)))
293 return GNUNET_YES;
294
295 char *buffer = GNUNET_malloc(storage.entry.length);
296
297 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
298
299 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
300
301 GNUNET_free(buffer);
302 return GNUNET_YES;
303}
304
305static int
306iterate_save_links (void *cls,
307 const struct GNUNET_HashCode *key,
308 void *value)
309{
310 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
311 struct GNUNET_MESSENGER_MessageLink *link = value;
312
313 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
314 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
315 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
316
317 if (GNUNET_YES == link->multiple)
318 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
319
320 return GNUNET_YES;
321}
322
323void
324save_message_store (struct GNUNET_MESSENGER_MessageStore *store,
325 const char *directory)
326{
327 GNUNET_assert((store) && (directory));
328
329 struct GNUNET_MESSENGER_ClosureMessageSave save;
330
331 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
332
333 char *filename;
334
335 if (GNUNET_YES != store->write_links)
336 goto save_entries;
337
338 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
339
340 save.store = store;
341 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
342
343 GNUNET_free(filename);
344
345 if (!save.storage)
346 goto save_entries;
347
348 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
349 goto close_links;
350
351 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
352 store->write_links = GNUNET_NO;
353
354close_links:
355 GNUNET_DISK_file_close (save.storage);
356
357save_entries:
358 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
359
360 save.store = store;
361 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
362
363 GNUNET_free(filename);
364
365 if (!save.storage)
366 return;
367
368 if (GNUNET_YES == store->rewrite_entries)
369 {
370 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
371 goto close_entries;
372
373 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
374 store->rewrite_entries = GNUNET_NO;
375 }
376 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
377 goto close_entries;
378
379 if (store->storage_messages)
380 GNUNET_DISK_file_close (store->storage_messages);
381
382 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
383
384 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
385 permission);
386
387 GNUNET_free(filename);
388
389 if (store->storage_messages)
390 {
391 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
392
393 GNUNET_DISK_file_sync (store->storage_messages);
394 GNUNET_DISK_file_sync (save.storage);
395 }
396
397close_entries:
398 GNUNET_DISK_file_close (save.storage);
399}
400
401int
402contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store,
403 const struct GNUNET_HashCode *hash)
404{
405 GNUNET_assert((store) && (hash));
406
407 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
408 return GNUNET_YES;
409
410 return GNUNET_CONTAINER_multihashmap_contains (store->entries, hash);
411}
412
413const struct GNUNET_MESSENGER_Message*
414get_store_message (struct GNUNET_MESSENGER_MessageStore *store,
415 const struct GNUNET_HashCode *hash)
416{
417 GNUNET_assert((store) && (hash));
418
419 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
420
421 if (message)
422 return message;
423
424 if (!store->storage_messages)
425 return NULL;
426
427 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
428
429 if (!entry)
430 return NULL;
431
432 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
433 return message;
434
435 char *buffer = GNUNET_malloc(entry->length);
436
437 if (!buffer)
438 return NULL;
439
440 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) ||
441 (entry->length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES)))
442 goto free_buffer;
443
444 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
445
446 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
447
448 struct GNUNET_HashCode check;
449 hash_message (message, entry->length, buffer, &check);
450
451 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
452 {
453 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
454 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Corrupted entry could not be removed from store: %s\n",
455 GNUNET_h2s(hash));
456
457 store->rewrite_entries = GNUNET_YES;
458
459 goto free_message;
460 }
461
462 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
463 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
464 goto free_buffer;
465
466free_message: destroy_message (message);
467 message = NULL;
468
469free_buffer:
470 GNUNET_free(buffer);
471
472 return message;
473}
474
475const struct GNUNET_MESSENGER_MessageLink*
476get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store,
477 const struct GNUNET_HashCode *hash,
478 int deleted_only)
479{
480 if (deleted_only)
481 goto get_link;
482
483 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
484
485 if (!message)
486 goto get_link;
487
488 static struct GNUNET_MESSENGER_MessageLink link;
489
490 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
491
492 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
493
494 if (GNUNET_YES == link.multiple)
495 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
496 else
497 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
498
499 return &link;
500
501get_link:
502 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
503}
504
505int
506put_store_message (struct GNUNET_MESSENGER_MessageStore *store,
507 const struct GNUNET_HashCode *hash,
508 struct GNUNET_MESSENGER_Message *message)
509{
510 GNUNET_assert((store) && (hash) && (message));
511
512 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
513 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
514}
515
516static void
517add_link (struct GNUNET_MESSENGER_MessageStore *store,
518 const struct GNUNET_HashCode *hash,
519 const struct GNUNET_MESSENGER_Message *message)
520{
521 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
522
523 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
524
525 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
526
527 if (GNUNET_YES == link->multiple)
528 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
529 else
530 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
531
532 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
533 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
534 GNUNET_free(link);
535}
536
537int
538delete_store_message (struct GNUNET_MESSENGER_MessageStore *store,
539 const struct GNUNET_HashCode *hash)
540{
541 GNUNET_assert((store) && (hash));
542
543 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
544
545 if (!entry)
546 goto clear_memory;
547
548 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
549
550 if (message)
551 add_link (store, hash, message);
552
553 if (!store->storage_messages)
554 goto clear_entry;
555
556 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
557 return GNUNET_SYSERR;
558
559 char *clear_buffer = GNUNET_malloc(entry->length);
560
561 if (!clear_buffer)
562 return GNUNET_SYSERR;
563
564 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
565
566 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
567 != GNUNET_DISK_file_sync (store->storage_messages)))
568 {
569 GNUNET_free(clear_buffer);
570 return GNUNET_SYSERR;
571 }
572
573 GNUNET_free(clear_buffer);
574
575clear_entry:
576 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
577 store->rewrite_entries = GNUNET_YES;
578
579clear_memory:
580 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
581 return GNUNET_OK;
582}
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 476d98dd5..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.h
+++ /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 * @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,
85 const char *directory);
86
87/**
88 * Saves messages from a message <i>store</i> into a <i>directory</i>.
89 *
90 * @param[in] store Message store
91 * @param[in] directory Path to a directory
92 */
93void
94save_message_store (struct GNUNET_MESSENGER_MessageStore *store,
95 const char *directory);
96
97/**
98 * Checks if a message matching a given <i>hash</i> is stored in a message <i>store</i>.
99 * The function returns #GNUNET_YES if a match is found, #GNUNET_NO otherwise.
100 *
101 * The message has not to be loaded from disk into memory for this check!
102 *
103 * @param[in] store Message store
104 * @param[in] hash Hash of message
105 * @return #GNUNET_YES on match, otherwise #GNUNET_NO
106 */
107int
108contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store,
109 const struct GNUNET_HashCode *hash);
110
111/**
112 * Returns the message from a message <i>store</i> matching a given <i>hash</i>. If no matching
113 * message is found, NULL gets returned.
114 *
115 * This function requires the message to be loaded into memory!
116 * @see contains_store_message()
117 *
118 * @param[in/out] store Message store
119 * @param[in] hash Hash of message
120 * @return Message or NULL
121 */
122const struct GNUNET_MESSENGER_Message*
123get_store_message (struct GNUNET_MESSENGER_MessageStore *store,
124 const struct GNUNET_HashCode *hash);
125
126/**
127 * Returns the message link from a message <i>store</i> matching a given <i>hash</i>. If the
128 * flag is set to #GNUNET_YES, only links from deleted messages will be returned or NULL.
129 *
130 * Otherwise message links will also returned for messages found in the store under the given
131 * hash. The link which will be returned copies link information from the message for
132 * temporary usage.
133 *
134 * @param[in/out] store Message store
135 * @param[in] hash Hash of message
136 * @param[in] deleted_only Flag
137 * @return Message link or NULL
138 */
139const struct GNUNET_MESSENGER_MessageLink*
140get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store,
141 const struct GNUNET_HashCode *hash,
142 int deleted_only);
143
144/**
145 * Stores a message into the message store. The result indicates if the operation was successful.
146 *
147 * @param[in/out] store Message store
148 * @param[in] hash Hash of message
149 * @param[in/out] message Message
150 * @return #GNUNET_OK on success, otherwise #GNUNET_NO
151 */
152int
153put_store_message (struct GNUNET_MESSENGER_MessageStore *store,
154 const struct GNUNET_HashCode *hash,
155 struct GNUNET_MESSENGER_Message *message);
156
157/**
158 * Deletes a message in the message store. It will be removed from disk space and memory. The result
159 * indicates if the operation was successful.
160 *
161 * @param[in/out] store Message store
162 * @param[in] hash Hash of message
163 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
164 */
165int
166delete_store_message (struct GNUNET_MESSENGER_MessageStore *store,
167 const struct GNUNET_HashCode *hash);
168
169#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 2b92d0c1d..000000000
--- a/src/messenger/gnunet-service-messenger_operation.c
+++ /dev/null
@@ -1,220 +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,
62 const char *path)
63{
64 GNUNET_assert((store) && (path));
65
66 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load operation configuration: %s\n", path);
67
68 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
69 struct GNUNET_MESSENGER_Operation* op = NULL;
70
71 if (GNUNET_OK != GNUNET_CONFIGURATION_parse(cfg, path))
72 goto destroy_config;
73
74 struct GNUNET_HashCode hash;
75
76 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "hash", &hash, sizeof(hash)))
77 goto destroy_config;
78
79 op = create_operation(&hash);
80
81 unsigned long long type_number;
82 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg, "operation", "type", &type_number))
83 switch (type_number)
84 {
85 case GNUNET_MESSENGER_OP_REQUEST:
86 op->type = GNUNET_MESSENGER_OP_REQUEST;
87 break;
88 case GNUNET_MESSENGER_OP_DELETE:
89 op->type = GNUNET_MESSENGER_OP_DELETE;
90 break;
91 case GNUNET_MESSENGER_OP_MERGE:
92 op->type = GNUNET_MESSENGER_OP_MERGE;
93 break;
94 default:
95 break;
96 }
97
98 if ((GNUNET_MESSENGER_OP_UNKNOWN == op->type) ||
99 (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "timestamp", &(op->timestamp), sizeof(op->timestamp))))
100 {
101 destroy_operation(op);
102 op = NULL;
103 goto destroy_config;
104 }
105
106 const struct GNUNET_TIME_Relative delay = GNUNET_TIME_absolute_get_remaining(op->timestamp);
107
108 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
109 delay,
110 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
111 callback_operation,
112 op
113 );
114
115 op->store = store;
116
117destroy_config:
118 GNUNET_CONFIGURATION_destroy (cfg);
119
120 return op;
121}
122
123void
124save_operation (const struct GNUNET_MESSENGER_Operation *op,
125 const char *path)
126{
127 GNUNET_assert((path) && (op));
128
129 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save operation configuration: %s\n", path);
130
131 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
132
133 char *hash_data;
134 hash_data = GNUNET_STRINGS_data_to_string_alloc (&(op->hash), sizeof(op->hash));
135
136 if (hash_data)
137 {
138 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "hash", hash_data);
139
140 GNUNET_free(hash_data);
141 }
142
143 GNUNET_CONFIGURATION_set_value_number(cfg, "operation", "type", op->type);
144
145 char *timestamp_data;
146 timestamp_data = GNUNET_STRINGS_data_to_string_alloc (&(op->timestamp), sizeof(op->timestamp));
147
148 if (timestamp_data)
149 {
150 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "timestamp", timestamp_data);
151
152 GNUNET_free(timestamp_data);
153 }
154
155 GNUNET_CONFIGURATION_write (cfg, path);
156 GNUNET_CONFIGURATION_destroy (cfg);
157}
158
159extern void
160callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
161 enum GNUNET_MESSENGER_OperationType type,
162 const struct GNUNET_HashCode *hash);
163
164static void
165callback_operation (void *cls)
166{
167 struct GNUNET_MESSENGER_Operation *op = cls;
168
169 op->task = NULL;
170
171 callback_store_operation (op->store, op->type, &(op->hash));
172}
173
174int
175start_operation (struct GNUNET_MESSENGER_Operation *op,
176 enum GNUNET_MESSENGER_OperationType type,
177 struct GNUNET_MESSENGER_OperationStore *store,
178 struct GNUNET_TIME_Relative delay)
179{
180 GNUNET_assert((op) && (store));
181
182 if (op->task)
183 return GNUNET_SYSERR;
184
185 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_add(
186 GNUNET_TIME_absolute_get(),
187 delay
188 );
189
190 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
191 delay,
192 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
193 callback_operation,
194 op
195 );
196
197 op->type = type;
198 op->timestamp = timestamp;
199 op->store = store;
200
201 return GNUNET_OK;
202}
203
204int
205stop_operation (struct GNUNET_MESSENGER_Operation *op)
206{
207 GNUNET_assert(op);
208
209 if (!op->task)
210 return GNUNET_SYSERR;
211
212 GNUNET_SCHEDULER_cancel(op->task);
213 op->task = NULL;
214
215 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
216 op->timestamp = GNUNET_TIME_absolute_get_zero_();
217 op->store = NULL;
218
219 return GNUNET_OK;
220}
diff --git a/src/messenger/gnunet-service-messenger_operation.h b/src/messenger/gnunet-service-messenger_operation.h
deleted file mode 100644
index 485668548..000000000
--- a/src/messenger/gnunet-service-messenger_operation.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.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,
90 const char *path);
91
92/**
93 * Saves data from an <i>operation</i> into a configuration file at a
94 * selected <i>path</i> which can be load to restore the operation
95 * completely and continue its process.
96 *
97 * @param[in] op Operation
98 * @param[in] path Path of a configuration file
99 */
100void
101save_operation (const struct GNUNET_MESSENGER_Operation *op,
102 const char *path);
103
104/**
105 * Starts an inactive operation with a given <i>delay</i> in a
106 * specific operation <i>store</i>. The method will replace the
107 * operations type to process it correctly. An operation can't be
108 * started twice, it has to be stopped or fully processed first.
109 *
110 * @param[in/out] op Operation
111 * @param[in] type Type of operation
112 * @param[in/out] store Operation store
113 * @param[in] delay Delay
114 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
115 */
116int
117start_operation (struct GNUNET_MESSENGER_Operation *op,
118 enum GNUNET_MESSENGER_OperationType type,
119 struct GNUNET_MESSENGER_OperationStore *store,
120 struct GNUNET_TIME_Relative delay);
121
122/**
123 * Stops an active operation and resets its type to be
124 * #GNUNET_MESSENGER_OP_UNKNOWN.
125 *
126 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
127 */
128int
129stop_operation (struct GNUNET_MESSENGER_Operation *op);
130
131#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 276f0b92b..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.c
+++ /dev/null
@@ -1,236 +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,
33 struct GNUNET_MESSENGER_SrvRoom *room)
34{
35 GNUNET_assert((store) && (room));
36
37 store->room = room;
38 store->operations = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_operations (void *cls,
43 const struct GNUNET_HashCode *key,
44 void *value)
45{
46 struct GNUNET_MESSENGER_Operation *op = value;
47
48 destroy_operation(op);
49
50 return GNUNET_YES;
51}
52
53void
54clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
55{
56 GNUNET_assert(store);
57
58 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_destroy_operations, NULL);
59 GNUNET_CONTAINER_multihashmap_destroy(store->operations);
60}
61
62static int
63callback_scan_for_operations (void *cls,
64 const char *filename)
65{
66 struct GNUNET_MESSENGER_OperationStore *store = cls;
67
68 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
69 return GNUNET_OK;
70
71 if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, ".cfg")))
72 return GNUNET_OK;
73
74 struct GNUNET_MESSENGER_Operation *op = load_operation(store, filename);
75
76 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
77 store->operations,
78 &(op->hash), op,
79 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
80 {
81 destroy_operation(op);
82 }
83
84 return GNUNET_OK;
85}
86
87void
88load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
89 const char *directory)
90{
91 GNUNET_assert ((store) && (directory));
92
93 char* load_dir;
94 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
95
96 if (GNUNET_OK == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
97 GNUNET_DISK_directory_scan (load_dir, callback_scan_for_operations, store);
98
99 GNUNET_free(load_dir);
100}
101
102static int
103iterate_save_operations (void *cls,
104 const struct GNUNET_HashCode *key,
105 void *value)
106{
107 const char *save_dir = cls;
108
109 struct GNUNET_MESSENGER_Operation *op = value;
110
111 if (!op)
112 return GNUNET_YES;
113
114 char *op_dir;
115 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s(key));
116 save_operation(op, op_dir);
117
118 GNUNET_free(op_dir);
119 return GNUNET_YES;
120}
121
122void
123save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
124 const char *directory)
125{
126 GNUNET_assert ((store) && (directory));
127
128 char* save_dir;
129 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
130
131 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
132 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
133 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_save_operations, save_dir);
134
135 GNUNET_free(save_dir);
136}
137
138enum GNUNET_MESSENGER_OperationType
139get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
140 const struct GNUNET_HashCode *hash)
141{
142 GNUNET_assert((store) && (hash));
143
144 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
145
146 if (!op)
147 return GNUNET_MESSENGER_OP_UNKNOWN;
148
149 return op->type;
150}
151
152int
153use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
154 const struct GNUNET_HashCode *hash,
155 enum GNUNET_MESSENGER_OperationType type,
156 struct GNUNET_TIME_Relative delay)
157{
158 GNUNET_assert((store) && (hash));
159
160 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
161
162 if (op)
163 goto use_op;
164
165 op = create_operation(hash);
166
167 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->operations, hash, op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
168 {
169 destroy_operation(op);
170
171 return GNUNET_SYSERR;
172 }
173
174use_op:
175 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
176 (type == GNUNET_MESSENGER_OP_DELETE))
177 stop_operation (op);
178
179 return start_operation(op, type, store, delay);
180}
181
182void
183cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
184 const struct GNUNET_HashCode *hash)
185{
186 GNUNET_assert((store) && (hash));
187
188 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
189
190 if (!op)
191 return;
192
193 stop_operation(op);
194
195 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(store->operations, hash, op))
196 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Canceled operation could not be removed: %s\n",
197 GNUNET_h2s(hash));
198
199 destroy_operation(op);
200}
201
202extern void
203callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
204 const struct GNUNET_HashCode *hash);
205
206extern void
207callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
208 const struct GNUNET_HashCode *hash);
209
210void
211callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
212 enum GNUNET_MESSENGER_OperationType type,
213 const struct GNUNET_HashCode *hash)
214{
215 GNUNET_assert((store) && (hash));
216
217 struct GNUNET_HashCode op_hash;
218 GNUNET_memcpy(&op_hash, hash, sizeof(op_hash));
219 cancel_store_operation (store, &op_hash);
220
221 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
222
223 switch (type)
224 {
225 case GNUNET_MESSENGER_OP_REQUEST:
226 break;
227 case GNUNET_MESSENGER_OP_DELETE:
228 callback_room_deletion (room, &op_hash);
229 break;
230 case GNUNET_MESSENGER_OP_MERGE:
231 callback_room_merge (room, &op_hash);
232 break;
233 default:
234 break;
235 }
236}
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 18eb7f8a1..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.h
+++ /dev/null
@@ -1,132 +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,
52 struct GNUNET_MESSENGER_SrvRoom *room);
53
54/**
55 * Clears an operation <i>store</i>, stops all operations and deallocates its memory.
56 *
57 * @param[in/out] store Operation store
58 */
59void
60clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store);
61
62/**
63 * Loads operations from a <i>directory</i> into an operation <i>store</i>.
64 *
65 * @param[out] store Operation store
66 * @param[in] directory Path to a directory
67 */
68void
69load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
70 const char *directory);
71
72/**
73 * Saves operations from an operation <i>store</i> into a <i>directory</i>.
74 *
75 * @param[in] store Operation store
76 * @param[in] directory Path to a directory
77 */
78void
79save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
80 const char *directory);
81
82/**
83 * Returns the type of the active operation under a given <i>hash</i> in
84 * a specific operation <i>store</i>. If there is no active operation under
85 * the given <i>hash</i>, #GNUNET_MESSENGER_OP_UNKNOWN gets returned instead.
86 *
87 * @param[in] store Operation store
88 * @param[in] hash Hash of message
89 * @return Type of operation or #GNUNET_MESSENGER_OP_UNKNOWN
90 */
91enum GNUNET_MESSENGER_OperationType
92get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
93 const struct GNUNET_HashCode *hash);
94
95/**
96 * Tries to use an operation under a given <i>hash</i> in a specific
97 * operation <i>store</i>. The operation will use the selected <i>type</i>
98 * if successful. The operation will be delayed by a given <i>delay</i>.
99 *
100 * If the selected type is #GNUNET_MESSENGER_OP_DELETE any active operation
101 * under the given hash will be stopped and replaced.
102 *
103 * If the new operation could be started successfully the method returns
104 * #GNUNET_OK, otherwise #GNUNET_SYSERR.
105 *
106 * @param[in/out] store Operation store
107 * @param[in] hash Hash of message
108 * @param[in] type Operation type
109 * @param[in] delay Delay
110 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
111 */
112int
113use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
114 const struct GNUNET_HashCode *hash,
115 enum GNUNET_MESSENGER_OperationType type,
116 struct GNUNET_TIME_Relative delay);
117
118/**
119 * Stops any active operation under a given <i>hash</i> in a specific
120 * operation <i>store</i>.
121 *
122 * Beware that calling this method will also implicitly free the memory
123 * of any active operation under the given hash!
124 *
125 * @param[in/out] store Operation store
126 * @param[in] hash Hash of message
127 */
128void
129cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
130 const struct GNUNET_HashCode *hash);
131
132#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 7f2fd0ca6..000000000
--- a/src/messenger/gnunet-service-messenger_room.c
+++ /dev/null
@@ -1,1255 +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,
47 const struct GNUNET_HashCode *key)
48{
49 GNUNET_assert((handle) && (key));
50
51 struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new(struct GNUNET_MESSENGER_SrvRoom);
52
53 room->service = handle->service;
54 room->host = handle;
55 room->port = NULL;
56
57 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
58
59 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
60
61 init_member_store(get_room_member_store(room), room);
62 init_message_store (get_room_message_store(room));
63 init_operation_store(get_room_operation_store(room), room);
64
65 init_list_tunnels (&(room->basement));
66 init_message_state(&(room->state));
67
68 room->peer_message = NULL;
69
70 init_list_messages (&(room->handling));
71 room->idle = NULL;
72
73 if (room->service->dir)
74 load_room (room);
75
76 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
77
78 return room;
79}
80
81static int
82iterate_destroy_tunnels (void *cls,
83 const struct GNUNET_PeerIdentity *key,
84 void *value)
85{
86 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
87 destroy_tunnel (tunnel);
88 return GNUNET_YES;
89}
90
91static void
92handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
93
94void
95destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
96{
97 GNUNET_assert(room);
98
99 if (room->idle)
100 {
101 GNUNET_SCHEDULER_cancel (room->idle);
102
103 room->idle = NULL;
104 }
105
106 if (room->port)
107 GNUNET_CADET_close_port (room->port);
108
109 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
110
111 handle_room_messages (room);
112
113 if (room->service->dir)
114 save_room (room);
115
116 clear_member_store (get_room_member_store(room));
117 clear_message_store (get_room_message_store(room));
118 clear_operation_store(get_room_operation_store(room));
119
120 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
121
122 clear_list_tunnels (&(room->basement));
123 clear_message_state(&(room->state));
124
125 if (room->peer_message)
126 GNUNET_free(room->peer_message);
127
128 GNUNET_free(room);
129}
130
131struct GNUNET_MESSENGER_MemberStore*
132get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
133{
134 GNUNET_assert(room);
135
136 return &(room->member_store);
137}
138
139struct GNUNET_MESSENGER_MessageStore*
140get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
141{
142 GNUNET_assert(room);
143
144 return &(room->message_store);
145}
146
147struct GNUNET_MESSENGER_OperationStore*
148get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
149{
150 GNUNET_assert(room);
151
152 return &(room->operation_store);
153}
154
155static int
156send_room_info (struct GNUNET_MESSENGER_SrvRoom *room,
157 struct GNUNET_MESSENGER_SrvHandle *handle,
158 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
159{
160 if ((!handle) || (!is_tunnel_connected (tunnel)))
161 return GNUNET_NO;
162
163 return send_tunnel_message (tunnel, handle, create_message_info (get_handle_ego (handle)));
164}
165
166static void*
167callback_room_connect (void *cls,
168 struct GNUNET_CADET_Channel *channel,
169 const struct GNUNET_PeerIdentity *source)
170{
171 struct GNUNET_MESSENGER_SrvRoom *room = cls;
172
173 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
174
175 if ((tunnel) &&
176 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
177 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
178 {
179 destroy_tunnel (tunnel);
180 tunnel = NULL;
181 }
182
183 if (!tunnel)
184 {
185 delayed_disconnect_channel (channel);
186 return NULL;
187 }
188
189 bind_tunnel(tunnel, channel);
190
191 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
192 GNUNET_h2s(get_room_key(room)), GNUNET_i2s (source));
193
194 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
195 return tunnel;
196
197 disconnect_tunnel (tunnel);
198
199 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
200 destroy_tunnel (tunnel);
201
202 return NULL;
203}
204
205static int
206join_room (struct GNUNET_MESSENGER_SrvRoom *room,
207 struct GNUNET_MESSENGER_SrvHandle *handle,
208 struct GNUNET_MESSENGER_Member *member)
209{
210 GNUNET_assert((room) && (handle) && (member));
211
212 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_room_key (room)),
213 GNUNET_sh2s (get_member_id(member)));
214
215 const struct GNUNET_ShortHashCode *member_id = get_member_id(member);
216
217 if (GNUNET_OK != change_handle_member_id (handle, get_room_key(room), member_id))
218 return GNUNET_NO;
219
220 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego (handle));
221
222 if (!message)
223 {
224 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be created!\n");
225
226 return GNUNET_NO;
227 }
228
229 GNUNET_memcpy(&(message->header.sender_id), member_id, sizeof(*member_id));
230 return send_room_message (room, handle, message);
231}
232
233struct GNUNET_MESSENGER_MemberNotify
234{
235 struct GNUNET_MESSENGER_SrvRoom *room;
236 struct GNUNET_MESSENGER_SrvHandle *handle;
237 struct GNUNET_MESSENGER_MemberSession *session;
238};
239
240static void
241notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify,
242 struct GNUNET_MESSENGER_MemberSession *session,
243 struct GNUNET_CONTAINER_MultiHashMap *map,
244 int check_permission)
245{
246 if (session->prev)
247 notify_about_members (notify, session->prev, map, GNUNET_YES);
248
249 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(notify->room);
250 struct GNUNET_MESSENGER_ListMessage *element;
251
252 for (element = session->messages.head; element; element = element->next)
253 {
254 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
255 continue;
256
257 if ((GNUNET_YES == check_permission) &&
258 (GNUNET_YES != check_member_session_history(notify->session, &(element->hash), GNUNET_NO)))
259 continue;
260
261 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
263 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message could be duplicated!\n");
264
265 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
266
267 if (message)
268 notify_handle_message (notify->handle, notify->room, session, message, &(element->hash));
269 }
270}
271
272static int
273iterate_notify_about_members (void *cls,
274 const struct GNUNET_IDENTITY_PublicKey *public_key,
275 struct GNUNET_MESSENGER_MemberSession *session)
276{
277 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
278
279 if ((notify->session == session) || (GNUNET_YES == is_member_session_completed(session)))
280 return GNUNET_YES;
281
282 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
283
284 notify_about_members (notify, session, map, GNUNET_NO);
285
286 GNUNET_CONTAINER_multihashmap_destroy(map);
287 return GNUNET_YES;
288}
289
290static int
291join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room,
292 struct GNUNET_MESSENGER_SrvHandle *handle)
293{
294 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
295
296 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
297 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
298
299 if (GNUNET_NO == join_room (room, handle, member))
300 return GNUNET_NO;
301
302 const struct GNUNET_MESSENGER_Ego *ego = get_handle_ego(handle);
303 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
304
305 if (!session)
306 {
307 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
308 return GNUNET_NO;
309 }
310
311 struct GNUNET_MESSENGER_MemberNotify notify;
312
313 notify.room = room;
314 notify.handle = handle;
315 notify.session = session;
316
317 iterate_store_members(get_room_member_store(room), iterate_notify_about_members, &notify);
318
319 return GNUNET_YES;
320}
321
322extern int
323check_tunnel_message (void *cls,
324 const struct GNUNET_MessageHeader *header);
325
326extern void
327handle_tunnel_message (void *cls,
328 const struct GNUNET_MessageHeader *header);
329
330extern void
331callback_tunnel_disconnect (void *cls,
332 const struct GNUNET_CADET_Channel *channel);
333
334int
335open_room (struct GNUNET_MESSENGER_SrvRoom *room,
336 struct GNUNET_MESSENGER_SrvHandle *handle)
337{
338 GNUNET_assert((room) && (handle));
339
340 if (room->port)
341 return join_room_locally (room, handle);
342
343 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
344 const struct GNUNET_HashCode *key = get_room_key (room);
345
346 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
347 struct GNUNET_MessageHeader, NULL),
348 GNUNET_MQ_handler_end() };
349
350 struct GNUNET_HashCode port;
351 convert_messenger_key_to_port(key, &port);
352 room->port = GNUNET_CADET_open_port (cadet, &port, callback_room_connect, room, NULL, callback_tunnel_disconnect,
353 handlers);
354
355 if (room->port)
356 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
357 GNUNET_h2s(get_room_key(room)));
358 else
359 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
360 GNUNET_h2s(get_room_key(room)));
361
362 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, get_room_key(room));
363
364 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
365 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
366
367 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
368 {
369 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
370
371 GNUNET_CADET_close_port (room->port);
372 room->port = NULL;
373
374 return GNUNET_NO;
375 }
376
377 struct GNUNET_MESSENGER_Message *peer_msg = create_message_peer (room->service);
378 GNUNET_memcpy(&(peer_msg->header.sender_id), member_id, sizeof(*member_id));
379 return (room->port ? send_room_message (room, handle, peer_msg) : GNUNET_NO);
380}
381
382int
383enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
384 struct GNUNET_MESSENGER_SrvHandle *handle,
385 const struct GNUNET_PeerIdentity *door)
386{
387 GNUNET_assert((room) && (handle) && (door));
388
389 struct GNUNET_PeerIdentity peer;
390
391 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
392 (0 == GNUNET_memcmp(&peer, door)))
393 return join_room_locally (room, handle);
394
395 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
396
397 if (!tunnel)
398 {
399 tunnel = create_tunnel (room, door);
400
401 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
402 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
403 {
404 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
405 destroy_tunnel (tunnel);
406 return GNUNET_NO;
407 }
408 }
409
410 if (GNUNET_SYSERR == connect_tunnel (tunnel))
411 {
412 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
413 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
414 destroy_tunnel (tunnel);
415 return GNUNET_NO;
416 }
417
418 return join_room_locally (room, handle);
419}
420
421struct GNUNET_MQ_Envelope*
422pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
423 const struct GNUNET_MESSENGER_SrvHandle *handle,
424 struct GNUNET_MESSENGER_Message *message,
425 struct GNUNET_HashCode *hash,
426 int mode)
427{
428 GNUNET_assert((room) && (handle) && (message) && (hash));
429
430 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
431
432 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, get_room_key(room));
433
434 GNUNET_assert(id);
435
436 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
437 get_message_state_chain_hash (&(room->state), &(message->header.previous));
438
439 return pack_message (message, hash, get_handle_ego (handle), mode);
440}
441
442struct GNUNET_MESSENGER_ClosureSendRoom
443{
444 struct GNUNET_MESSENGER_SrvRoom *room;
445 struct GNUNET_MESSENGER_SrvHandle *handle;
446 struct GNUNET_MESSENGER_SrvTunnel *exclude;
447 struct GNUNET_MESSENGER_Message *message;
448 struct GNUNET_HashCode *hash;
449 int packed;
450};
451
452static int
453iterate_send_room_message (void *cls,
454 const struct GNUNET_PeerIdentity *key,
455 void *value)
456{
457 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
458
459 if ((!is_tunnel_connected (tunnel)) ||
460 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
461 return GNUNET_YES;
462
463 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
464
465 if (tunnel == closure->exclude)
466 return GNUNET_YES;
467
468 struct GNUNET_MQ_Envelope *env = NULL;
469
470 if (closure->packed == GNUNET_NO)
471 {
472 env = pack_room_message (closure->room, closure->handle, closure->message, closure->hash,
473 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
474
475 if (env)
476 closure->packed = GNUNET_YES;
477 }
478 else
479 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
480
481 if (env)
482 send_tunnel_envelope (tunnel, env, closure->hash);
483
484 return GNUNET_YES;
485}
486
487int
488update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
489 struct GNUNET_MESSENGER_Message *message,
490 const struct GNUNET_HashCode *hash);
491
492void
493callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
494 struct GNUNET_MESSENGER_SrvHandle *handle,
495 const struct GNUNET_MESSENGER_Message *message,
496 const struct GNUNET_HashCode *hash);
497
498int
499send_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
500 struct GNUNET_MESSENGER_SrvHandle *handle,
501 struct GNUNET_MESSENGER_Message *message)
502{
503 GNUNET_assert((room) && (handle));
504
505 if (!message)
506 return GNUNET_NO;
507
508 if (GNUNET_YES == is_message_session_bound(message))
509 merge_room_last_messages(room, handle);
510
511 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
512 GNUNET_sh2s(get_handle_member_id(handle, get_room_key(room))));
513
514 struct GNUNET_HashCode hash;
515 struct GNUNET_MESSENGER_ClosureSendRoom closure;
516
517 closure.room = room;
518 closure.handle = handle;
519 closure.exclude = NULL;
520 closure.message = message;
521 closure.hash = &hash;
522 closure.packed = GNUNET_NO;
523
524 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
525
526 if (GNUNET_NO == closure.packed)
527 pack_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
528
529 const int new_message = update_room_message (room, message, &hash);
530
531 if (GNUNET_YES != new_message)
532 return GNUNET_SYSERR;
533
534 switch (message->header.kind)
535 {
536 case GNUNET_MESSENGER_KIND_JOIN:
537 send_message_join (room, handle, message, &hash);
538 break;
539 case GNUNET_MESSENGER_KIND_PEER:
540 send_message_peer (room, handle, message, &hash);
541 break;
542 case GNUNET_MESSENGER_KIND_ID:
543 send_message_id (room, handle, message, &hash);
544 break;
545 case GNUNET_MESSENGER_KIND_REQUEST:
546 send_message_request (room, handle, message, &hash);
547 break;
548 default:
549 break;
550 }
551
552 callback_room_handle_message (room, handle, message, &hash);
553 return GNUNET_YES;
554}
555
556void
557forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
558 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
559 struct GNUNET_MESSENGER_Message *message,
560 const struct GNUNET_HashCode *hash)
561{
562 GNUNET_assert((room) && (tunnel));
563
564 if (!message)
565 return;
566
567 struct GNUNET_MESSENGER_ClosureSendRoom closure;
568 struct GNUNET_HashCode message_hash;
569
570 GNUNET_memcpy(&message_hash, hash, sizeof(struct GNUNET_HashCode));
571
572 closure.room = room;
573 closure.handle = NULL;
574 closure.exclude = tunnel;
575 closure.message = message;
576 closure.hash = &message_hash;
577 closure.packed = GNUNET_YES;
578
579 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
580}
581
582void
583check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room,
584 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
585{
586 if (!room->peer_message)
587 return;
588
589 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
590
591 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, room->peer_message);
592
593 if (!message)
594 {
595 GNUNET_free(room->peer_message);
596 room->peer_message = NULL;
597 return;
598 }
599
600 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
601 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
602
603 if (!member)
604 goto resend_peer_message;
605
606 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
607
608 if (GNUNET_YES == is_member_session_closed(session))
609 goto resend_peer_message;
610
611 if (tunnel)
612 forward_tunnel_message(tunnel, message, room->peer_message);
613
614 return;
615
616resend_peer_message:
617 if (room->host)
618 send_room_message (room, room->host, create_message_peer (room->service));
619}
620
621void
622merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room,
623 struct GNUNET_MESSENGER_SrvHandle *handle)
624{
625 GNUNET_assert(room);
626
627 if (!handle)
628 return;
629
630 const struct GNUNET_HashCode *hash;
631
632merge_next:
633 hash = get_message_state_merge_hash (&(room->state));
634
635 if (!hash)
636 return;
637
638 send_room_message (room, handle, create_message_merge (hash));
639 goto merge_next;
640}
641
642void
643callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
644 const struct GNUNET_HashCode *hash)
645{
646 if (GNUNET_OK != delete_store_message (get_room_message_store(room), hash))
647 {
648 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
649 return;
650 }
651}
652
653void
654callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
655 const struct GNUNET_HashCode *hash)
656{
657 if (!room->host)
658 return;
659
660 send_room_message (room, room->host, create_message_merge (hash));
661}
662
663int
664delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
665 struct GNUNET_MESSENGER_MemberSession *session,
666 const struct GNUNET_HashCode *hash,
667 const struct GNUNET_TIME_Relative delay)
668{
669 GNUNET_assert((room) && (session) && (hash));
670
671 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
672
673 if (0 == GNUNET_memcmp(&forever, &delay))
674 {
675 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
676 return GNUNET_SYSERR;
677 }
678
679 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
680
681 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
682
683 if (!message)
684 return GNUNET_YES;
685
686 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
687 {
688 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
689 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
690
691 return GNUNET_NO;
692 }
693
694 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
695
696 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
697 {
698 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
699 return GNUNET_SYSERR;
700 }
701
702 return GNUNET_YES;
703}
704
705struct GNUNET_CADET_Handle*
706get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
707{
708 GNUNET_assert(room);
709
710 return room->service->cadet;
711}
712
713const struct GNUNET_HashCode*
714get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
715{
716 GNUNET_assert(room);
717
718 return &(room->key);
719}
720
721const struct GNUNET_MESSENGER_SrvTunnel*
722get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room,
723 const struct GNUNET_PeerIdentity *peer)
724{
725 GNUNET_assert((room) && (peer));
726
727 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
728}
729
730static int
731request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room,
732 const struct GNUNET_HashCode *hash,
733 const struct GNUNET_MESSENGER_MemberSession *session,
734 GNUNET_MESSENGER_MessageRequestCallback callback,
735 void* cls)
736{
737 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
738
739 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
740 message_store, hash, GNUNET_YES
741 );
742
743 if (!link)
744 goto forward;
745
746 int result = request_room_message_step(room, &(link->first), session, callback, cls);
747
748 if ((GNUNET_YES == link->multiple) &&
749 (GNUNET_YES == request_room_message_step(room, &(link->second), session, callback, cls)))
750 return GNUNET_YES;
751 else
752 return result;
753
754forward:
755 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))
756 return GNUNET_YES;
757
758 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
759
760 if (!message)
761 return GNUNET_NO;
762
763 if (callback)
764 callback (cls, room, message, hash);
765
766 return GNUNET_YES;
767}
768
769int
770request_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
771 const struct GNUNET_HashCode *hash,
772 const struct GNUNET_MESSENGER_MemberSession *session,
773 GNUNET_MESSENGER_MessageRequestCallback callback,
774 void* cls)
775{
776 GNUNET_assert((room) && (hash));
777
778 int result = request_room_message_step (room, hash, session, callback, cls);
779
780 if ((GNUNET_NO == result) && (callback))
781 callback (cls, room, NULL, hash);
782
783 return result;
784}
785
786void
787callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
788 void *cls)
789{
790 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
791
792 if (!room->host)
793 return;
794
795 struct GNUNET_PeerIdentity identity;
796 get_tunnel_peer_identity(tunnel, &identity);
797
798 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
799 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
800 return;
801
802 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
803 send_room_message (room, room->host, create_message_miss (&identity));
804}
805
806int
807callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
808 void *cls,
809 struct GNUNET_MESSENGER_Message *message,
810 struct GNUNET_HashCode *hash)
811{
812 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
813 {
814 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
815 return GNUNET_SYSERR;
816 }
817
818 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
819
820 const struct GNUNET_MESSENGER_Message *previous = get_store_message(message_store, &(message->header.previous));
821
822 if (!previous)
823 goto skip_time_comparison;
824
825 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(message->header.timestamp);
826 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh(previous->header.timestamp);
827
828 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(timestamp, last).rel_value_us)
829 {
830 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Timestamp does not check out!\n");
831 return GNUNET_SYSERR;
832 }
833
834skip_time_comparison:
835 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
836 GNUNET_MESSENGER_name_of_kind(message->header.kind));
837
838 return GNUNET_OK;
839}
840
841static void
842idle_request_room_messages (void *cls)
843{
844 struct GNUNET_MESSENGER_SrvRoom *room = cls;
845
846 room->idle = NULL;
847
848 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
849 const struct GNUNET_HashCode *hash = get_message_state_merge_hash(&(room->state));
850
851 if ((hash) &&
852 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, hash)))
853 use_store_operation(
854 operation_store,
855 hash,
856 GNUNET_MESSENGER_OP_MERGE,
857 GNUNET_MESSENGER_MERGE_DELAY
858 );
859
860 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
861 GNUNET_MESSENGER_IDLE_DELAY,
862 GNUNET_SCHEDULER_PRIORITY_IDLE,
863 idle_request_room_messages,
864 cls
865 );
866}
867
868void
869solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room,
870 const struct GNUNET_IDENTITY_PublicKey *public_key,
871 const struct GNUNET_ShortHashCode *member_id,
872 struct GNUNET_TIME_Absolute timestamp)
873{
874 GNUNET_assert ((room) && (public_key) && (member_id));
875
876 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
877 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
878
879 if ((!member) || (1 >= GNUNET_CONTAINER_multihashmap_size(member->sessions)))
880 return;
881
882 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
883 struct GNUNET_MESSENGER_ListHandle* element;
884
885 for (element = handles->head; element; element = element->next)
886 {
887 if (0 != GNUNET_memcmp(member_id, get_handle_member_id(element->handle, get_room_key(room))))
888 continue;
889
890 if (0 == GNUNET_memcmp(public_key, &(get_handle_ego(element->handle)->pub)))
891 continue;
892
893 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_handle_ego(element->handle)->pub));
894
895 if (!session)
896 continue;
897
898 struct GNUNET_TIME_Absolute start = get_member_session_start(session);
899
900 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(start, timestamp).rel_value_us)
901 continue;
902
903 struct GNUNET_ShortHashCode random_id;
904 generate_free_member_id (&random_id, member_store->members);
905
906 send_room_message(room, element->handle, create_message_id(&random_id));
907 }
908}
909
910void
911rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
912{
913 GNUNET_assert(room);
914
915 struct GNUNET_PeerIdentity peer;
916 size_t src;
917
918 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
919 (!find_list_tunnels (&(room->basement), &peer, &src)))
920 return;
921
922 size_t count = count_of_tunnels (&(room->basement));
923
924 struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head;
925 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
926
927 size_t dst = 0;
928
929 while (element)
930 {
931 GNUNET_PEER_resolve (element->peer, &peer);
932
933 tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer);
934
935 if (!tunnel)
936 {
937 element = remove_from_list_tunnels (&(room->basement), element);
938 continue;
939 }
940
941 if (GNUNET_YES == required_connection_between (count, src, dst))
942 {
943 if (GNUNET_SYSERR == connect_tunnel (tunnel))
944 {
945 element = remove_from_list_tunnels (&(room->basement), element);
946 continue;
947 }
948 }
949 else
950 disconnect_tunnel (tunnel);
951
952 element = element->next;
953 dst++;
954 }
955}
956
957static void
958handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
959{
960 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
961 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
962
963 while (room->handling.head)
964 {
965 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
966
967 const struct GNUNET_MESSENGER_Message *message = get_store_message (message_store, &(element->hash));
968
969 if (!message)
970 goto finish_handling;
971
972 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
973
974 if (!member)
975 goto finish_handling;
976
977 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(element->hash));
978
979 if (session)
980 handle_service_message (room->service, room, session, message, &(element->hash));
981
982finish_handling:
983 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
984 GNUNET_free(element);
985 }
986}
987
988int
989update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
990 struct GNUNET_MESSENGER_Message *message,
991 const struct GNUNET_HashCode *hash)
992{
993 GNUNET_assert((room) && (message) && (hash));
994
995 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(room);
996
997 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
998 GNUNET_YES : GNUNET_NO
999 );
1000
1001 if (GNUNET_YES == requested)
1002 cancel_store_operation(operation_store, hash);
1003
1004 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(room);
1005
1006 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (message_store, hash);
1007
1008 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_room_key(room)));
1009
1010 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash, message)))
1011 {
1012 if (old_message != message)
1013 destroy_message(message);
1014
1015 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
1016 return GNUNET_NO;
1017 }
1018
1019 update_message_state(&(room->state), requested, message, hash);
1020
1021 if ((GNUNET_YES == requested) ||
1022 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
1023 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
1024 return GNUNET_YES;
1025
1026 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
1027 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->body.merge.previous))))
1028 cancel_store_operation(operation_store, &(message->body.merge.previous));
1029
1030 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->header.previous)))
1031 cancel_store_operation(operation_store, &(message->header.previous));
1032
1033 return GNUNET_YES;
1034}
1035
1036struct GNUNET_MESSENGER_MemberSessionCompletion
1037{
1038 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
1039 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
1040
1041 struct GNUNET_MESSENGER_MemberSession *session;
1042};
1043
1044struct GNUNET_MESSENGER_MemberUpdate
1045{
1046 const struct GNUNET_MESSENGER_Message *message;
1047 const struct GNUNET_HashCode *hash;
1048
1049 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
1050 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
1051};
1052
1053static int
1054iterate_update_member_sessions (void *cls,
1055 const struct GNUNET_IDENTITY_PublicKey *public_key,
1056 struct GNUNET_MESSENGER_MemberSession *session)
1057{
1058 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
1059
1060 update_member_session_history(session, update->message, update->hash);
1061
1062 if (GNUNET_YES == is_member_session_completed(session))
1063 {
1064 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
1065 struct GNUNET_MESSENGER_MemberSessionCompletion
1066 );
1067
1068 element->session = session;
1069
1070 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
1071 }
1072
1073 return GNUNET_YES;
1074}
1075
1076static void
1077remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1078 struct GNUNET_MESSENGER_MemberSession *session);
1079
1080void
1081callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
1082 struct GNUNET_MESSENGER_SrvHandle *handle,
1083 const struct GNUNET_MESSENGER_Message *message,
1084 const struct GNUNET_HashCode *hash)
1085{
1086 struct GNUNET_MESSENGER_MemberStore *member_store = get_room_member_store(room);
1087 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
1088
1089 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
1090
1091 if (!member)
1092 {
1093 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
1094 return;
1095 }
1096
1097 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
1098
1099 if (!session)
1100 {
1101 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
1102 return;
1103 }
1104
1105 struct GNUNET_MESSENGER_MemberUpdate update;
1106 update.message = message;
1107 update.hash = hash;
1108
1109 update.head = NULL;
1110 update.tail = NULL;
1111
1112 iterate_store_members(member_store, iterate_update_member_sessions, &update);
1113
1114 while (update.head)
1115 {
1116 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
1117
1118 remove_room_member_session (room, element->session);
1119
1120 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
1121 GNUNET_free (element);
1122 }
1123
1124 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
1125
1126 add_to_list_messages (&(room->handling), hash);
1127
1128 switch (message->header.kind)
1129 {
1130 case GNUNET_MESSENGER_KIND_JOIN:
1131 handle_message_join (room, session, message, hash);
1132 break;
1133 case GNUNET_MESSENGER_KIND_LEAVE:
1134 handle_message_leave (room, session, message, hash);
1135 break;
1136 case GNUNET_MESSENGER_KIND_NAME:
1137 handle_message_name (room, session, message, hash);
1138 break;
1139 case GNUNET_MESSENGER_KIND_KEY:
1140 handle_message_key (room, session, message, hash);
1141 break;
1142 case GNUNET_MESSENGER_KIND_PEER:
1143 handle_message_peer (room, session, message, hash);
1144 break;
1145 case GNUNET_MESSENGER_KIND_ID:
1146 handle_message_id (room, session, message, hash);
1147 break;
1148 case GNUNET_MESSENGER_KIND_MISS:
1149 handle_message_miss (room, session, message, hash);
1150 break;
1151 case GNUNET_MESSENGER_KIND_DELETE:
1152 handle_message_delete (room, session, message, hash);
1153 break;
1154 default:
1155 break;
1156 }
1157
1158 if (GNUNET_YES == start_handle)
1159 handle_room_messages (room);
1160}
1161
1162static void
1163get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room,
1164 char **dir)
1165{
1166 GNUNET_assert((room) && (dir));
1167
1168 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_room_key(room)), DIR_SEPARATOR);
1169}
1170
1171void
1172load_room (struct GNUNET_MESSENGER_SrvRoom *room)
1173{
1174 GNUNET_assert(room);
1175
1176 char *room_dir;
1177 get_room_data_subdir (room, &room_dir);
1178
1179 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1180 {
1181 load_member_store (get_room_member_store(room), room_dir);
1182 load_message_store (get_room_message_store(room), room_dir);
1183 load_operation_store(get_room_operation_store(room), room_dir);
1184
1185 char *basement_file;
1186 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1187
1188 load_list_tunnels(&(room->basement), basement_file);
1189 GNUNET_free(basement_file);
1190
1191 load_message_state(&(room->state), room_dir);
1192 }
1193
1194 GNUNET_free(room_dir);
1195}
1196
1197void
1198save_room (struct GNUNET_MESSENGER_SrvRoom *room)
1199{
1200 GNUNET_assert(room);
1201
1202 char *room_dir;
1203 get_room_data_subdir (room, &room_dir);
1204
1205 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1206 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1207 {
1208 save_member_store(get_room_member_store(room), room_dir);
1209 save_message_store (get_room_message_store(room), room_dir);
1210 save_operation_store(get_room_operation_store(room), room_dir);
1211
1212 char *basement_file;
1213 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1214
1215 save_list_tunnels(&(room->basement), basement_file);
1216 GNUNET_free(basement_file);
1217
1218 save_message_state(&(room->state), room_dir);
1219 }
1220
1221 GNUNET_free(room_dir);
1222}
1223
1224static void
1225remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1226 struct GNUNET_MESSENGER_MemberSession *session)
1227{
1228 GNUNET_assert ((room) && (session));
1229
1230 remove_member_session (session->member, session);
1231
1232 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
1233
1234 struct GNUNET_HashCode hash;
1235 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
1236
1237 char *room_dir;
1238 get_room_data_subdir (room, &room_dir);
1239
1240 char* session_dir;
1241 GNUNET_asprintf (
1242 &session_dir, "%s%s%c%s%c%s%c%s%c", room_dir,
1243 "members", DIR_SEPARATOR,
1244 GNUNET_sh2s(get_member_session_id(session)), DIR_SEPARATOR,
1245 "sessions", DIR_SEPARATOR,
1246 GNUNET_h2s(&hash), DIR_SEPARATOR
1247 );
1248
1249 GNUNET_free (room_dir);
1250
1251 GNUNET_DISK_directory_remove(session_dir);
1252 GNUNET_free (session_dir);
1253
1254 destroy_member_session(session);
1255}
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
deleted file mode 100644
index 4b3811104..000000000
--- a/src/messenger/gnunet-service-messenger_room.h
+++ /dev/null
@@ -1,367 +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,
93 const struct GNUNET_HashCode *key);
94
95/**
96 * Destroys a room and frees its memory fully.
97 *
98 * @param[in/out] room Room
99 */
100void
101destroy_room (struct GNUNET_MESSENGER_SrvRoom *room);
102
103/**
104 * Returns the used member store of a given <i>room</i>.
105 *
106 * @param[in/out] room Room
107 * @return Member store
108 */
109struct GNUNET_MESSENGER_MemberStore*
110get_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room);
111
112/**
113 * Returns the used message store of a given <i>room</i>.
114 *
115 * @param[in/out] room Room
116 * @return Message store
117 */
118struct GNUNET_MESSENGER_MessageStore*
119get_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room);
120
121/**
122 * Returns the used operation store of a given <i>room</i>.
123 *
124 * @param[in/out] room Room
125 * @return Operation store
126 */
127struct GNUNET_MESSENGER_OperationStore*
128get_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
129
130/**
131 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle
132 * will locally join the room.
133 *
134 * Calling this method should result in joining a room and sending a peer message as well for this peer.
135 *
136 * If the function returns #GNUNET_YES the port for this room is guaranteed to be open for incoming connections.
137 *
138 * @param[in/out] room Room
139 * @param[in/out] handle Handle
140 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
141 */
142int
143open_room (struct GNUNET_MESSENGER_SrvRoom *room,
144 struct GNUNET_MESSENGER_SrvHandle *handle);
145
146/**
147 * Connects a tunnel to a hosting peer of a <i>room</i> through a so called <i>door</i> which is represented by
148 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for
149 * an info message from the selected host.
150 *
151 * @param[in/out] room Room
152 * @param[in/out] handle Handle
153 * @param[in] door Peer identity
154 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
155 */
156int
157enter_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
158 struct GNUNET_MESSENGER_SrvHandle *handle,
159 const struct GNUNET_PeerIdentity *door);
160
161/**
162 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the
163 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message
164 * will be signed by the handles EGO.
165 *
166 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overridden by the signed messages hash.
167 *
168 * If <i>mode</i> is set to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send
169 * through a message queue, otherwise NULL.
170 *
171 * @param[in] room Room
172 * @param[in] handle Handle
173 * @param[in/out] message Message
174 * @param[out] hash Hash of message
175 * @param[in] mode Packing mode
176 * @return New envelope or NULL
177 */
178struct GNUNET_MQ_Envelope*
179pack_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
180 const struct GNUNET_MESSENGER_SrvHandle *handle,
181 struct GNUNET_MESSENGER_Message *message,
182 struct GNUNET_HashCode *hash,
183 int mode);
184
185/**
186 * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i>. The <i>hash</i> parameter will be
187 * updated with the hash-value resulting from the sent message.
188 *
189 * The function handles packing the message automatically and will call linked message-events locally even if
190 * the message won't be sent to another peer.
191 *
192 * The function returns #GNUNET_YES on success, #GNUNET_NO if message is null and
193 * #GNUNET_SYSERR if the message was known already.
194 *
195 * @param[in/out] room Room
196 * @param[in/out] handle Handle
197 * @param[in/out] message Message
198 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
199 */
200int
201send_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
202 struct GNUNET_MESSENGER_SrvHandle *handle,
203 struct GNUNET_MESSENGER_Message *message);
204
205/**
206 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>.
207 *
208 * @param[in/out] room Room
209 * @param[in/out] tunnel Tunnel
210 * @param[in/out] message Message
211 * @param[in] hash Hash of message
212 */
213void
214forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
215 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
216 struct GNUNET_MESSENGER_Message *message,
217 const struct GNUNET_HashCode *hash);
218
219/**
220 * Checks the current state of opening a given <i>room</i> from this peer and re-publishes it
221 * if necessary to a selected <i>tunnel</i> or to all connected tunnels if necessary or if the
222 * selected tunnel is NULL.
223 *
224 * @param[in/out] room Room
225 * @param[in/out] tunnel Tunnel
226 */
227void
228check_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room,
229 struct GNUNET_MESSENGER_SrvTunnel *tunnel);
230
231/**
232 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message
233 * by merging them down. All merge messages will be sent from a given <i>handle</i>.
234 *
235 * @param[in/out] room Room
236 * @param[in/out] handle Handle
237 */
238void
239merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room,
240 struct GNUNET_MESSENGER_SrvHandle *handle);
241
242/**
243 * Deletes a message from the <i>room</i> with a given <i>hash</i> in a specific <i>delay</i> if
244 * the provided member by its session is permitted to do so.
245 *
246 * @param[in/out] room Room
247 * @param[in/out] session Member session
248 * @param[in] hash Hash of message
249 * @param[in] delay Delay of deletion
250 * @return #GNUNET_YES on success, #GNUNET_NO if permission gets denied, #GNUNET_SYSERR on operation failure
251 */
252int
253delete_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
254 struct GNUNET_MESSENGER_MemberSession *session,
255 const struct GNUNET_HashCode *hash,
256 const struct GNUNET_TIME_Relative delay);
257
258/**
259 * Returns the CADET handle from a rooms service.
260 *
261 * @param[in/out] room Room
262 * @return CADET handle
263 */
264struct GNUNET_CADET_Handle*
265get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room);
266
267/**
268 * Returns the shared secret you need to access a <i>room</i>.
269 *
270 * @param[in] room Room
271 * @return Shared secret
272 */
273const struct GNUNET_HashCode*
274get_room_key (const struct GNUNET_MESSENGER_SrvRoom *room);
275
276/**
277 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists,
278 * otherwise NULL.
279 *
280 * @param[in] room Room
281 * @param[in] peer Peer identity
282 * @return Tunnel or NULL
283 */
284const struct GNUNET_MESSENGER_SrvTunnel*
285get_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room,
286 const struct GNUNET_PeerIdentity *peer);
287
288/**
289 * Method called whenever a <i>message</i> is found during a request in a <i>room</i>.
290 *
291 * @param[in/out] cls Closure from #request_room_message
292 * @param[in/out] room Room
293 * @param[in] message Message or NULL
294 * @param[in] hash Hash of message
295 */
296typedef void (GNUNET_MESSENGER_MessageRequestCallback) (
297 void *cls,
298 struct GNUNET_MESSENGER_SrvRoom *room,
299 const struct GNUNET_MESSENGER_Message *message,
300 const struct GNUNET_HashCode *hash
301);
302
303/**
304 * Requests a message from a <i>room</i> identified by a given <i>hash</i>. If the message is found,
305 * the selected <i>callback</i> will be called with it and the provided closure. If no matching message
306 * is found but it wasn't deleted the selected callback will be called with #NULL as message instead.
307 * In case of deletion the next available previous message will be used to call the callback.
308 *
309 * It is also possible that the given callback will not be called if the requesting session is not
310 * permitted!
311 *
312 * @param[in/out] room Room
313 * @param[in] hash Hash of message
314 * @param[in] callback Callback to process result
315 * @param[in] cls Closure for the <i>callback</i>
316 * @return #GNUNET_YES if the request could be processed, otherwise #GNUNET_NO
317 */
318int
319request_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
320 const struct GNUNET_HashCode *hash,
321 const struct GNUNET_MESSENGER_MemberSession *session,
322 GNUNET_MESSENGER_MessageRequestCallback callback,
323 void* cls);
324
325/**
326 * Checks for potential collisions with member ids and solves them changing active handles ids if they
327 * use an already used member id (comparing public key and timestamp).
328 *
329 * @param[in/out] room Room
330 * @param[in] public_key Public key of EGO
331 * @param[in] member_id Member ID
332 * @param[in] timestamp Timestamp
333 */
334void
335solve_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room,
336 const struct GNUNET_IDENTITY_PublicKey *public_key,
337 const struct GNUNET_ShortHashCode *member_id,
338 struct GNUNET_TIME_Absolute timestamp);
339
340/**
341 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
342 * depending on the amount of peers and this peers index in the list of them.
343 *
344 * @param[in/out] room Room
345 */
346void
347rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room);
348
349/**
350 * Loads the local configuration for a given <i>room</i> of a service which contains the last messages hash
351 * and the ruleset for general access of new members.
352 *
353 * @param[out] room Room
354 */
355void
356load_room (struct GNUNET_MESSENGER_SrvRoom *room);
357
358/**
359 * Saves the configuration for a given <i>room</i> of a service which contains the last messages hash
360 * and the ruleset for general access of new members locally.
361 *
362 * @param[in] room Room
363 */
364void
365save_room (struct GNUNET_MESSENGER_SrvRoom *room);
366
367#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 b53b72af8..000000000
--- a/src/messenger/gnunet-service-messenger_service.c
+++ /dev/null
@@ -1,319 +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,
45 struct GNUNET_SERVICE_Handle *service_handle)
46{
47 GNUNET_assert((config) && (service_handle));
48
49 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service);
50
51 service->config = config;
52 service->service = service_handle;
53
54 service->shutdown = GNUNET_SCHEDULER_add_shutdown (&callback_shutdown_service, service);
55
56 service->dir = NULL;
57
58 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config,
59 GNUNET_MESSENGER_SERVICE_NAME,
60 "MESSENGER_DIR", &(service->dir)))
61 {
62 if (service->dir)
63 GNUNET_free(service->dir);
64
65 service->dir = NULL;
66 }
67 else
68 {
69 if ((GNUNET_YES != GNUNET_DISK_directory_test (service->dir, GNUNET_YES)) && (GNUNET_OK
70 != GNUNET_DISK_directory_create (service->dir)))
71 {
72 GNUNET_free(service->dir);
73
74 service->dir = NULL;
75 }
76 }
77
78 service->cadet = GNUNET_CADET_connect (service->config);
79
80 init_ego_store(get_service_ego_store(service), service->config);
81
82 init_list_handles (&(service->handles));
83
84 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
85
86 init_contact_store(get_service_contact_store(service));
87
88 return service;
89}
90
91static int
92iterate_destroy_rooms (void *cls,
93 const struct GNUNET_HashCode *key,
94 void *value)
95{
96 struct GNUNET_MESSENGER_SrvRoom *room = value;
97 destroy_room (room);
98 return GNUNET_YES;
99}
100
101void
102destroy_service (struct GNUNET_MESSENGER_Service *service)
103{
104 GNUNET_assert(service);
105
106 if (service->shutdown)
107 {
108 GNUNET_SCHEDULER_cancel (service->shutdown);
109
110 service->shutdown = NULL;
111 }
112
113 clear_ego_store(get_service_ego_store(service));
114 clear_list_handles (&(service->handles));
115
116 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL);
117 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
118
119 clear_contact_store(get_service_contact_store(service));
120
121 if (service->cadet)
122 {
123 GNUNET_CADET_disconnect (service->cadet);
124
125 service->cadet = NULL;
126 }
127
128 if (service->dir)
129 {
130 GNUNET_free(service->dir);
131
132 service->dir = NULL;
133 }
134
135 GNUNET_SERVICE_shutdown (service->service);
136
137 GNUNET_free(service);
138}
139
140struct GNUNET_MESSENGER_EgoStore*
141get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
142{
143 GNUNET_assert(service);
144
145 return &(service->ego_store);
146}
147
148struct GNUNET_MESSENGER_ContactStore*
149get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
150{
151 GNUNET_assert(service);
152
153 return &(service->contact_store);
154}
155
156struct GNUNET_MESSENGER_SrvHandle*
157add_service_handle (struct GNUNET_MESSENGER_Service *service,
158 struct GNUNET_MQ_Handle *mq)
159{
160 GNUNET_assert((service) && (mq));
161
162 struct GNUNET_MESSENGER_SrvHandle *handle = create_handle (service, mq);
163
164 if (handle)
165 {
166 add_list_handle (&(service->handles), handle);
167 }
168
169 return handle;
170}
171
172void
173remove_service_handle (struct GNUNET_MESSENGER_Service *service,
174 struct GNUNET_MESSENGER_SrvHandle *handle)
175{
176 GNUNET_assert((service) && (handle));
177
178 if (!handle)
179 return;
180
181 if (GNUNET_YES == remove_list_handle (&(service->handles), handle))
182 destroy_handle (handle);
183}
184
185int
186get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
187 struct GNUNET_PeerIdentity *peer)
188{
189 GNUNET_assert((service) && (peer));
190
191 return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
192}
193
194struct GNUNET_MESSENGER_SrvRoom*
195get_service_room (const struct GNUNET_MESSENGER_Service *service,
196 const struct GNUNET_HashCode *key)
197{
198 GNUNET_assert((service) && (key));
199
200 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
201}
202
203int
204open_service_room (struct GNUNET_MESSENGER_Service *service,
205 struct GNUNET_MESSENGER_SrvHandle *handle,
206 const struct GNUNET_HashCode *key)
207{
208 GNUNET_assert((service) && (handle) && (key));
209
210 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
211
212 if (room)
213 return open_room (room, handle);
214
215 room = create_room (handle, key);
216
217 if ((GNUNET_YES == open_room (room, handle)) &&
218 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
219 key, room,
220 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
221 return GNUNET_YES;
222
223 destroy_room (room);
224 return GNUNET_NO;
225}
226
227int
228entry_service_room (struct GNUNET_MESSENGER_Service *service,
229 struct GNUNET_MESSENGER_SrvHandle *handle,
230 const struct GNUNET_PeerIdentity *door,
231 const struct GNUNET_HashCode *key)
232{
233 GNUNET_assert((service) && (handle) && (door) && (key));
234
235 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
236
237 if (room)
238 {
239 if (GNUNET_YES == enter_room_at (room, handle, door))
240 return GNUNET_YES;
241 else
242 return GNUNET_NO;
243 }
244
245 room = create_room (handle, key);
246
247 if ((GNUNET_YES == enter_room_at (room, handle, door)) &&
248 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
249 key, room,
250 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
251 {
252 return GNUNET_YES;
253 }
254 else
255 {
256 destroy_room (room);
257 return GNUNET_NO;
258 }
259
260}
261
262int
263close_service_room (struct GNUNET_MESSENGER_Service *service,
264 struct GNUNET_MESSENGER_SrvHandle *handle,
265 const struct GNUNET_HashCode *key)
266{
267 GNUNET_assert((service) && (handle) && (key));
268
269 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
270
271 if (!room)
272 return GNUNET_NO;
273
274 send_room_message (room, handle, create_message_leave ());
275
276 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, key);
277
278 GNUNET_assert(id);
279
280 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (handle->member_ids, key, id))
281 return GNUNET_NO;
282
283 struct GNUNET_MESSENGER_SrvHandle *member_handle = (struct GNUNET_MESSENGER_SrvHandle*) find_list_handle_by_member (
284 &(service->handles), key);
285
286 if (!member_handle)
287 {
288 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room))
289 {
290 destroy_room (room);
291 return GNUNET_YES;
292 }
293 else
294 return GNUNET_NO;
295 }
296
297 if (room->host == handle)
298 room->host = member_handle;
299
300 return GNUNET_YES;
301}
302
303void
304handle_service_message (struct GNUNET_MESSENGER_Service *service,
305 struct GNUNET_MESSENGER_SrvRoom *room,
306 const struct GNUNET_MESSENGER_MemberSession *session,
307 const struct GNUNET_MESSENGER_Message *message,
308 const struct GNUNET_HashCode *hash)
309{
310 GNUNET_assert((service) && (room) && (session) && (message) && (hash));
311
312 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
313
314 while (element)
315 {
316 notify_handle_message (element->handle, room, session, message, hash);
317 element = element->next;
318 }
319}
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h
deleted file mode 100644
index d364a93c0..000000000
--- a/src/messenger/gnunet-service-messenger_service.h
+++ /dev/null
@@ -1,212 +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,
72 struct GNUNET_SERVICE_Handle *service_handle);
73
74/**
75 * Destroys a <i>service</i> and frees its memory fully.
76 *
77 * @param[in/out] service Service
78 */
79void
80destroy_service (struct GNUNET_MESSENGER_Service *service);
81
82/**
83 * Returns the used EGO-store of a given <i>service</i>.
84 *
85 * @param[in/out] service Service
86 * @return EGO-store
87 */
88struct GNUNET_MESSENGER_EgoStore*
89get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
90
91/**
92 * Returns the used contact store of a given <i>service</i>.
93 *
94 * @param[in/out] service Service
95 * @return Contact store
96 */
97struct GNUNET_MESSENGER_ContactStore*
98get_service_contact_store (struct GNUNET_MESSENGER_Service *service);
99
100/**
101 * Creates and adds a new handle to a <i>service</i> using a given message queue.
102 *
103 * @param[in/out] service Service
104 * @param[in/out] mq Message queue
105 * @return New handle
106 */
107struct GNUNET_MESSENGER_SrvHandle*
108add_service_handle (struct GNUNET_MESSENGER_Service *service,
109 struct GNUNET_MQ_Handle *mq);
110
111/**
112 * Removes a <i>handle</i> from a <i>service</i> and destroys it.
113 *
114 * @param[in/out] service Service
115 * @param[in/out] handle Handle
116 */
117void
118remove_service_handle (struct GNUNET_MESSENGER_Service *service,
119 struct GNUNET_MESSENGER_SrvHandle *handle);
120
121/**
122 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i>
123 * parameter. The functions returns #GNUNET_OK on success, otherwise #GNUNET_SYSERR.
124 *
125 * @param[in] service Service
126 * @param[out] peer Peer identity
127 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
128 */
129int
130get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
131 struct GNUNET_PeerIdentity *peer);
132
133/**
134 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room
135 * using the given key, NULL gets returned.
136 *
137 * @param[in] service Service
138 * @param[in] key Key of room
139 * @return Room or NULL
140 */
141struct GNUNET_MESSENGER_SrvRoom*
142get_service_room (const struct GNUNET_MESSENGER_Service *service,
143 const struct GNUNET_HashCode *key);
144
145/**
146 * 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
147 * created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
148 *
149 * @param[in/out] service Service
150 * @param[in/out] handle Handle
151 * @param[in] key Key of room
152 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
153 */
154int
155open_service_room (struct GNUNET_MESSENGER_Service *service,
156 struct GNUNET_MESSENGER_SrvHandle *handle,
157 const struct GNUNET_HashCode *key);
158
159/**
160 * 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
161 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
162 *
163 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and
164 * a new connection will be made.
165 *
166 * @param[in/out] service Service
167 * @param[in/out] handle Handle
168 * @param[in] door Peer identity
169 * @param[in] key Key of room
170 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
171 */
172int
173entry_service_room (struct GNUNET_MESSENGER_Service *service,
174 struct GNUNET_MESSENGER_SrvHandle *handle,
175 const struct GNUNET_PeerIdentity *door,
176 const struct GNUNET_HashCode *key);
177
178/**
179 * 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
180 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
181 *
182 * If the specific handle is currently the host of the room for this service, a new handle which is a member will
183 * take its place. Otherwise the room will be destroyed for this service.
184 *
185 * @param[in/out] service Service
186 * @param[in/out] handle Handle
187 * @param[in] key Key of room
188 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
189 */
190int
191close_service_room (struct GNUNET_MESSENGER_Service *service,
192 struct GNUNET_MESSENGER_SrvHandle *handle,
193 const struct GNUNET_HashCode *key);
194
195/**
196 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which
197 * is currently member of a specific <i>room</i> for handling it in the client API.
198 *
199 * @param[in/out] service Service
200 * @param[in/out] room Room
201 * @param[in] session Member session
202 * @param[in] message Message
203 * @param[in] hash Hash of message
204 */
205void
206handle_service_message (struct GNUNET_MESSENGER_Service *service,
207 struct GNUNET_MESSENGER_SrvRoom *room,
208 const struct GNUNET_MESSENGER_MemberSession *session,
209 const struct GNUNET_MESSENGER_Message *message,
210 const struct GNUNET_HashCode *hash);
211
212#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 45c10c1af..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ /dev/null
@@ -1,402 +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,
37 const struct GNUNET_PeerIdentity *door)
38{
39 GNUNET_assert((room) && (door));
40
41 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new(struct GNUNET_MESSENGER_SrvTunnel);
42
43 tunnel->room = room;
44 tunnel->channel = NULL;
45
46 tunnel->peer = GNUNET_PEER_intern (door);
47
48 tunnel->messenger_version = 0;
49
50 tunnel->peer_message = NULL;
51
52 init_message_state(&(tunnel->state));
53
54 return tunnel;
55}
56
57void
58destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
59{
60 GNUNET_assert(tunnel);
61
62 if (tunnel->channel)
63 GNUNET_CADET_channel_destroy (tunnel->channel);
64
65 GNUNET_PEER_change_rc (tunnel->peer, -1);
66
67 if (tunnel->peer_message)
68 GNUNET_free(tunnel->peer_message);
69
70 clear_message_state(&(tunnel->state));
71
72 GNUNET_free(tunnel);
73}
74
75void
76bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
77 struct GNUNET_CADET_Channel *channel)
78{
79 GNUNET_assert(tunnel);
80
81 if (tunnel->channel)
82 delayed_disconnect_channel (tunnel->channel);
83
84 tunnel->channel = channel;
85}
86
87extern void
88callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
89 void *cls);
90
91void
92callback_tunnel_disconnect (void *cls,
93 const struct GNUNET_CADET_Channel *channel)
94{
95 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
96
97 if (tunnel)
98 {
99 tunnel->channel = NULL;
100
101 callback_room_disconnect (tunnel->room, cls);
102 }
103}
104
105extern int
106callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
107 void *cls,
108 struct GNUNET_MESSENGER_Message *message,
109 struct GNUNET_HashCode *hash);
110
111int
112check_tunnel_message (void *cls,
113 const struct GNUNET_MessageHeader *header)
114{
115 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
116
117 if (!tunnel)
118 return GNUNET_SYSERR;
119
120 const uint16_t length = ntohs (header->size) - sizeof(*header);
121 const char *buffer = (const char*) &header[1];
122
123 struct GNUNET_MESSENGER_Message message;
124
125 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES))
126 {
127 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Message too short! (%d)\n", length);
128 return GNUNET_SYSERR;
129 }
130
131 uint16_t padding = 0;
132
133 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, &padding))
134 {
135 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
136 return GNUNET_SYSERR;
137 }
138
139 struct GNUNET_HashCode hash;
140 hash_message (&message, length - padding, buffer, &hash);
141
142 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
143}
144
145extern int
146update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
147 struct GNUNET_MESSENGER_Message *message,
148 const struct GNUNET_HashCode *hash);
149
150extern void
151callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
152 struct GNUNET_MESSENGER_SrvHandle *handle,
153 const struct GNUNET_MESSENGER_Message *message,
154 const struct GNUNET_HashCode *hash);
155
156static void
157update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
158 const struct GNUNET_HashCode *hash)
159{
160 struct GNUNET_MESSENGER_OperationStore *operation_store = get_room_operation_store(tunnel->room);
161
162 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
163 GNUNET_YES : GNUNET_NO
164 );
165
166 struct GNUNET_MESSENGER_MessageStore *message_store = get_room_message_store(tunnel->room);
167
168 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
169
170 if (message)
171 update_message_state(&(tunnel->state), requested, message, hash);
172}
173
174void
175handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
176{
177 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
178
179 if (!tunnel)
180 return;
181
182 const uint16_t length = ntohs (header->size) - sizeof(*header);
183 const char *buffer = (const char*) &header[1];
184
185 struct GNUNET_MESSENGER_Message message;
186 struct GNUNET_HashCode hash;
187
188 uint16_t padding = 0;
189
190 decode_message (&message, length, buffer, GNUNET_YES, &padding);
191 hash_message (&message, length - padding, buffer, &hash);
192
193 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
194 GNUNET_MESSENGER_name_of_kind(message.header.kind));
195
196 const int new_message = update_room_message (
197 tunnel->room, copy_message (&message), &hash
198 );
199
200 if (GNUNET_YES != new_message)
201 goto receive_done;
202
203 update_tunnel_last_message (tunnel, &hash);
204
205 int forward_message = GNUNET_YES;
206
207 switch (message.header.kind)
208 {
209 case GNUNET_MESSENGER_KIND_INFO:
210 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
211 break;
212 case GNUNET_MESSENGER_KIND_PEER:
213 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
214 break;
215 case GNUNET_MESSENGER_KIND_REQUEST:
216 forward_message = recv_message_request (tunnel->room, tunnel, &message, &hash);
217 break;
218 default:
219 break;
220 }
221
222 if (GNUNET_YES == forward_message)
223 {
224 forward_room_message (tunnel->room, tunnel, &message, &hash);
225 callback_room_handle_message (tunnel->room, NULL, &message, &hash);
226 }
227
228receive_done:
229 cleanup_message(&message);
230
231 GNUNET_CADET_receive_done (tunnel->channel);
232}
233
234int
235connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
236{
237 GNUNET_assert(tunnel);
238
239 if (tunnel->channel)
240 return GNUNET_NO;
241
242 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
243
244 struct GNUNET_CADET_Handle *cadet = get_room_cadet (tunnel->room);
245 const struct GNUNET_HashCode *key = get_room_key (tunnel->room);
246
247 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
248 struct GNUNET_MessageHeader, NULL),
249 GNUNET_MQ_handler_end() };
250
251 struct GNUNET_HashCode port;
252 convert_messenger_key_to_port(key, &port);
253 tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, &port, NULL, callback_tunnel_disconnect, handlers);
254
255 return GNUNET_YES;
256}
257
258void
259disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
260{
261 GNUNET_assert(tunnel);
262
263 if (tunnel->channel)
264 {
265 delayed_disconnect_channel (tunnel->channel);
266
267 tunnel->channel = NULL;
268 }
269}
270
271int
272is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
273{
274 GNUNET_assert(tunnel);
275
276 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
277}
278
279struct GNUNET_MESSENGER_MessageSent
280{
281 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
282 struct GNUNET_HashCode hash;
283};
284
285static void
286callback_tunnel_sent (void *cls)
287{
288 struct GNUNET_MESSENGER_MessageSent *sent = cls;
289
290 if (sent->tunnel)
291 update_tunnel_last_message (sent->tunnel, &(sent->hash));
292
293 GNUNET_free(sent);
294}
295
296void
297send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
298 struct GNUNET_MQ_Envelope *env,
299 const struct GNUNET_HashCode *hash)
300{
301 GNUNET_assert((tunnel) && (env) && (hash));
302
303 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
304
305 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
306
307 GNUNET_memcpy(&(sent->hash), hash, sizeof(struct GNUNET_HashCode));
308
309 sent->tunnel = tunnel;
310
311 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
312 GNUNET_MQ_send (mq, env);
313}
314
315int
316send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
317 void *handle,
318 struct GNUNET_MESSENGER_Message *message)
319{
320 GNUNET_assert((tunnel) && (handle));
321
322 if (!message)
323 return GNUNET_NO;
324
325 struct GNUNET_HashCode hash;
326 struct GNUNET_MQ_Envelope *env = pack_room_message (
327 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
328 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
329 );
330
331 destroy_message(message);
332
333 if (!env)
334 return GNUNET_NO;
335
336 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
337 GNUNET_h2s(&hash));
338
339 send_tunnel_envelope (tunnel, env, &hash);
340 return GNUNET_YES;
341}
342
343void
344forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
345 const struct GNUNET_MESSENGER_Message *message,
346 const struct GNUNET_HashCode *hash)
347{
348 GNUNET_assert((tunnel) && (message) && (hash));
349
350 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
351 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
352
353 destroy_message(copy);
354
355 if (!env)
356 return;
357
358 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
359 GNUNET_h2s(hash));
360
361 send_tunnel_envelope (tunnel, env, hash);
362}
363
364const struct GNUNET_HashCode*
365get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
366{
367 GNUNET_assert(tunnel);
368
369 return tunnel->peer_message;
370}
371
372void
373get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel,
374 struct GNUNET_PeerIdentity *peer)
375{
376 GNUNET_assert(tunnel);
377
378 GNUNET_PEER_resolve(tunnel->peer, peer);
379}
380
381uint32_t
382get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
383{
384 GNUNET_assert(tunnel);
385
386 return tunnel->messenger_version;
387}
388
389int
390update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
391 uint32_t version)
392{
393 GNUNET_assert(tunnel);
394
395 if (version != GNUNET_MESSENGER_VERSION)
396 return GNUNET_SYSERR;
397
398 if (version > tunnel->messenger_version)
399 tunnel->messenger_version = version;
400
401 return GNUNET_OK;
402}
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
deleted file mode 100644
index 7bd749281..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ /dev/null
@@ -1,194 +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,
59 const struct GNUNET_PeerIdentity *door);
60
61/**
62 * Destroys a <i>tunnel</i> and frees its memory fully.
63 *
64 * @param[in/out] tunnel
65 */
66void
67destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
68
69/**
70 * Binds a CADET <i>channel</i> to a <i>tunnel</i> and replaces its channel
71 * the tunnel is currently bound to if necessary.
72 *
73 * @param[in/out] tunnel Tunnel
74 * @param[in/out] channel CADET channel
75 */
76void
77bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
78 struct GNUNET_CADET_Channel *channel);
79
80/**
81 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it.
82 * The function returns #GNUNET_YES on success, otherwise #GNUNET_NO.
83 *
84 * @param[in/out] tunnel Tunnel
85 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
86 */
87int
88connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
89
90/**
91 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection
92 * will be asynchronous.
93 *
94 * @param[in/out] tunnel Tunnel
95 */
96void
97disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
98
99/**
100 * Returns the status of a currently bound channel of a <i>tunnel</i>.
101 *
102 * @param[in] tunnel Tunnel
103 * @return #GNUNET_YES or #GNUNET_NO
104 */
105int
106is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
107
108/**
109 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through
110 * a <i>tunnel</i>.
111 *
112 * @param[in/out] tunnel Tunnel
113 * @param[in/out] env Envelope
114 * @param[in] hash Hash of message
115 */
116void
117send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
118 struct GNUNET_MQ_Envelope *env,
119 const struct GNUNET_HashCode *hash);
120
121/**
122 * Sends a <i>message</i> by packing it automatically into an envelope and passing it
123 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and
124 * the <i>hash</i> will be calculated and stored.
125 *
126 * @param[in/out] tunnel Tunnel
127 * @param[in/out] handle Handle
128 * @param[in/out] message Message
129 * @return #GNUNET_YES on success, GNUNET_NO otherwise
130 */
131int
132send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
133 void *handle,
134 struct GNUNET_MESSENGER_Message *message);
135
136/**
137 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>.
138 *
139 * @param[in/out] tunnel Tunnel
140 * @param[in] message Message
141 * @param[in] hash Hash of message
142 */
143void
144forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
145 const struct GNUNET_MESSENGER_Message *message,
146 const struct GNUNET_HashCode *hash);
147
148/**
149 * Returns the hash of the latest peer message published through a given <i>tunnel</i>
150 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel
151 * yet, NULL gets returned.
152 *
153 * @param[in] tunnel Tunnel
154 * @return Hash of peer message or NULL
155 */
156const struct GNUNET_HashCode*
157get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
158
159/**
160 * Writes the peer identity of the peer connected via <i>tunnel</i> to this peer into
161 * the <i>peer</i> parameter.
162 *
163 * @param[in] tunnel Tunnel
164 * @param[out] peer Peer identity
165 */
166void
167get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel,
168 struct GNUNET_PeerIdentity *peer);
169
170/**
171 * Returns the current messenger version the peer connected via a given <i>tunnel</i>
172 * has reported to be using if it was compatible during updating.
173 *
174 * @see update_tunnel_messenger_version
175 *
176 * @param[in] tunnel Tunnel
177 * @return Version of messenger
178 */
179uint32_t
180get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
181
182/**
183 * Updates the messenger version of the <i>tunnel</i> to a given <i>version</i> if
184 * it is compatible to the running peer of the service. Depending on success it
185 * returns #GNUNET_OK or #GNUNET_SYSERR on failure.
186 *
187 * @param[in/out] tunnel Tunnel
188 * @param[in] version Version of messenger
189 */
190int
191update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
192 uint32_t version);
193
194#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 6b54550ea..000000000
--- a/src/messenger/messenger.conf.in
+++ /dev/null
@@ -1,14 +0,0 @@
1[messenger]
2START_ON_DEMAND = YES
3RUN_PER_USER = YES
4PORT = 2097
5HOSTNAME = localhost
6BINARY = gnunet-service-messenger
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-messenger.sock
10UNIX_MATCH_UID = NO
11UNIX_MATCH_GID = YES
12
13# Directory to store messages and contacts
14MESSENGER_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 a37b1b10b..000000000
--- a/src/messenger/messenger_api.c
+++ /dev/null
@@ -1,792 +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,
74 const struct GNUNET_MESSENGER_NameMessage *msg)
75{
76 GNUNET_MQ_check_zero_termination(msg);
77 return GNUNET_OK;
78}
79
80static void
81handle_get_name (void *cls,
82 const struct GNUNET_MESSENGER_NameMessage *msg)
83{
84 struct GNUNET_MESSENGER_Handle *handle = cls;
85
86 const char *name = ((const char*) msg) + sizeof(*msg);
87
88 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
89
90 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
91}
92
93static int
94check_get_key (void *cls,
95 const struct GNUNET_MESSENGER_KeyMessage *msg)
96{
97 const uint16_t full_length = ntohs (msg->header.size);
98
99 if (full_length < sizeof(*msg))
100 return GNUNET_NO;
101
102 const uint16_t length = full_length - sizeof(*msg);
103 const char *buffer = ((const char*) msg) + sizeof(*msg);
104
105 struct GNUNET_IDENTITY_PublicKey pubkey;
106 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
107 return GNUNET_NO;
108
109 return GNUNET_OK;
110}
111
112static void
113handle_get_key (void *cls,
114 const struct GNUNET_MESSENGER_KeyMessage *msg)
115{
116 struct GNUNET_MESSENGER_Handle *handle = cls;
117
118 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
119 const char *buffer = ((const char*) msg) + sizeof(*msg);
120
121 struct GNUNET_IDENTITY_PublicKey pubkey;
122 if (GNUNET_IDENTITY_read_key_from_buffer(&pubkey, buffer, length) < 0)
123 return;
124
125 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
126 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
127 GNUNET_free(str);
128
129 set_handle_key (handle, &pubkey);
130
131 if (handle->identity_callback)
132 handle->identity_callback (handle->identity_cls, handle);
133}
134
135static void
136handle_member_id (void *cls,
137 const struct GNUNET_MESSENGER_MemberMessage *msg)
138{
139 struct GNUNET_MESSENGER_Handle *handle = cls;
140
141 const struct GNUNET_HashCode *key = &(msg->key);
142 const struct GNUNET_ShortHashCode *id = &(msg->id);
143
144 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key));
145
146 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
147
148 if (room)
149 {
150 if (!room->contact_id)
151 room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
152
153 GNUNET_memcpy(room->contact_id, id, sizeof(*id));
154 }
155}
156
157static void
158handle_room_open (void *cls,
159 const struct GNUNET_MESSENGER_RoomMessage *msg)
160{
161 struct GNUNET_MESSENGER_Handle *handle = cls;
162
163 const struct GNUNET_HashCode *key = &(msg->key);
164
165 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
166
167 open_handle_room (handle, key);
168}
169
170static void
171handle_room_entry (void *cls,
172 const struct GNUNET_MESSENGER_RoomMessage *msg)
173{
174 struct GNUNET_MESSENGER_Handle *handle = cls;
175
176 const struct GNUNET_PeerIdentity *door = &(msg->door);
177 const struct GNUNET_HashCode *key = &(msg->key);
178
179 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
180
181 entry_handle_room_at (handle, door, key);
182}
183
184static void
185handle_room_close (void *cls,
186 const struct GNUNET_MESSENGER_RoomMessage *msg)
187{
188 struct GNUNET_MESSENGER_Handle *handle = cls;
189
190 const struct GNUNET_HashCode *key = &(msg->key);
191
192 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
193
194 close_handle_room (handle, key);
195}
196
197static int
198check_recv_message (void *cls,
199 const struct GNUNET_MESSENGER_RecvMessage *msg)
200{
201 const uint16_t full_length = ntohs (msg->header.size);
202
203 if (full_length < sizeof(*msg))
204 return GNUNET_NO;
205
206 const uint16_t length = full_length - sizeof(*msg);
207 const char *buffer = ((const char*) msg) + sizeof(*msg);
208
209 struct GNUNET_MESSENGER_Message message;
210
211 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES))
212 return GNUNET_NO;
213
214 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
215 return GNUNET_NO;
216
217 cleanup_message(&message);
218 return GNUNET_OK;
219}
220
221static void
222handle_recv_message (void *cls,
223 const struct GNUNET_MESSENGER_RecvMessage *msg)
224{
225 struct GNUNET_MESSENGER_Handle *handle = cls;
226
227 const struct GNUNET_HashCode *key = &(msg->key);
228 const struct GNUNET_HashCode *sender = &(msg->sender);
229 const struct GNUNET_HashCode *context = &(msg->context);
230 const struct GNUNET_HashCode *hash = &(msg->hash);
231 const enum GNUNET_MESSENGER_MessageFlags flags = (
232 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
233 );
234
235 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
236 const char *buffer = ((const char*) msg) + sizeof(*msg);
237
238 struct GNUNET_MESSENGER_Message message;
239 decode_message (&message, length, buffer, GNUNET_YES, NULL);
240
241 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
242
243 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
244
245 if (room)
246 {
247 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
248
249 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
250 GNUNET_h2s(sender), GNUNET_h2s_full(context));
251
252 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
253 store, context, sender
254 );
255
256 handle_room_message (room, contact, &message, hash);
257
258 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message(room, hash);
259
260 if (handle->msg_callback)
261 handle->msg_callback (handle->msg_cls, room, contact, stored_message, hash, flags);
262 }
263 else
264 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", GNUNET_h2s (key));
265
266 cleanup_message(&message);
267}
268
269static void
270reconnect (struct GNUNET_MESSENGER_Handle *handle);
271
272static void
273send_open_room (struct GNUNET_MESSENGER_Handle *handle,
274 struct GNUNET_MESSENGER_Room *room)
275{
276 struct GNUNET_MESSENGER_RoomMessage *msg;
277 struct GNUNET_MQ_Envelope *env;
278
279 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
280 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
281 GNUNET_MQ_send (handle->mq, env);
282}
283
284static void
285send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
286 struct GNUNET_MESSENGER_Room *room,
287 const struct GNUNET_PeerIdentity *door)
288{
289 struct GNUNET_MESSENGER_RoomMessage *msg;
290 struct GNUNET_MQ_Envelope *env;
291
292 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
293 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
294 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
295 GNUNET_MQ_send (handle->mq, env);
296}
297
298static void
299send_close_room (struct GNUNET_MESSENGER_Handle *handle,
300 struct GNUNET_MESSENGER_Room *room)
301{
302 struct GNUNET_MESSENGER_RoomMessage *msg;
303 struct GNUNET_MQ_Envelope *env;
304
305 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
306 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
307 GNUNET_MQ_send (handle->mq, env);
308}
309
310static int
311iterate_reset_room (void *cls,
312 const struct GNUNET_HashCode *key,
313 void *value)
314{
315 struct GNUNET_MESSENGER_Handle *handle = cls;
316 struct GNUNET_MESSENGER_Room *room = value;
317
318 if (GNUNET_YES == room->opened)
319 send_open_room (handle, room);
320
321 struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
322
323 struct GNUNET_PeerIdentity door;
324
325 while (entry)
326 {
327 GNUNET_PEER_resolve (entry->peer, &door);
328
329 send_enter_room (handle, room, &door);
330
331 entry = entry->next;
332 }
333
334 return GNUNET_YES;
335}
336
337static void
338callback_reconnect (void *cls)
339{
340 struct GNUNET_MESSENGER_Handle *handle = cls;
341
342 handle->reconnect_task = NULL;
343 handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
344 ;
345
346 reconnect (handle);
347
348 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle);
349}
350
351static int
352iterate_close_room (void *cls,
353 const struct GNUNET_HashCode *key,
354 void *value)
355{
356 struct GNUNET_MESSENGER_Handle *handle = cls;
357 struct GNUNET_MESSENGER_Room *room = value;
358
359 send_close_room (handle, room);
360
361 return GNUNET_YES;
362}
363
364static void
365callback_mq_error (void *cls,
366 enum GNUNET_MQ_Error error)
367{
368 struct GNUNET_MESSENGER_Handle *handle = cls;
369
370 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
371
372 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
373
374 if (handle->mq)
375 {
376 GNUNET_MQ_destroy (handle->mq);
377 handle->mq = NULL;
378 }
379
380 handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle);
381}
382
383static void
384reconnect (struct GNUNET_MESSENGER_Handle *handle)
385{
386 const struct GNUNET_MQ_MessageHandler handlers[] =
387 {
388 GNUNET_MQ_hd_var_size(
389 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
390 struct GNUNET_MESSENGER_NameMessage, handle
391 ),
392 GNUNET_MQ_hd_var_size(
393 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
394 struct GNUNET_MESSENGER_KeyMessage, handle
395 ),
396 GNUNET_MQ_hd_fixed_size(
397 member_id,
398 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
399 struct GNUNET_MESSENGER_MemberMessage, handle
400 ),
401 GNUNET_MQ_hd_fixed_size(
402 room_open,
403 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
404 struct GNUNET_MESSENGER_RoomMessage, handle
405 ),
406 GNUNET_MQ_hd_fixed_size(
407 room_entry,
408 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
409 struct GNUNET_MESSENGER_RoomMessage, handle
410 ),
411 GNUNET_MQ_hd_fixed_size(
412 room_close,
413 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
414 struct GNUNET_MESSENGER_RoomMessage, handle
415 ),
416 GNUNET_MQ_hd_var_size(
417 recv_message,
418 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
419 struct GNUNET_MESSENGER_RecvMessage, handle
420 ),
421 GNUNET_MQ_handler_end()
422 };
423
424 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
425}
426
427struct GNUNET_MESSENGER_Handle*
428GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
429 const char *name,
430 GNUNET_MESSENGER_IdentityCallback identity_callback,
431 void *identity_cls,
432 GNUNET_MESSENGER_MessageCallback msg_callback,
433 void *msg_cls)
434{
435 struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls);
436
437 reconnect (handle);
438
439 if (handle->mq)
440 {
441 const uint16_t name_len = name ? strlen (name) : 0;
442
443 struct GNUNET_MESSENGER_CreateMessage *msg;
444 struct GNUNET_MQ_Envelope *env;
445
446 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
447
448 char *extra = ((char*) msg) + sizeof(*msg);
449
450 if (name_len)
451 GNUNET_memcpy(extra, name, name_len);
452
453 extra[name_len] = '\0';
454
455 GNUNET_MQ_send (handle->mq, env);
456 return handle;
457 }
458 else
459 {
460 destroy_handle (handle);
461 return NULL;
462 }
463}
464
465int
466GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
467{
468 if ((!handle) || (!get_handle_name (handle)))
469 return GNUNET_SYSERR;
470
471 struct GNUNET_MESSENGER_UpdateMessage *msg;
472 struct GNUNET_MQ_Envelope *env;
473
474 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
475 GNUNET_MQ_send (handle->mq, env);
476 return GNUNET_OK;
477}
478
479void
480GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
481{
482 if (!handle)
483 return;
484
485 struct GNUNET_MESSENGER_DestroyMessage *msg;
486 struct GNUNET_MQ_Envelope *env;
487
488 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
489 GNUNET_MQ_send (handle->mq, env);
490
491 destroy_handle (handle);
492}
493
494const char*
495GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
496{
497 if (!handle)
498 return NULL;
499
500 return get_handle_name (handle);
501}
502
503int
504GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
505 const char *name)
506{
507 if (!handle)
508 return GNUNET_SYSERR;
509
510 const uint16_t name_len = name ? strlen (name) : 0;
511
512 struct GNUNET_MESSENGER_NameMessage *msg;
513 struct GNUNET_MQ_Envelope *env;
514
515 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
516
517 char *extra = ((char*) msg) + sizeof(*msg);
518
519 if (name_len)
520 GNUNET_memcpy(extra, name, name_len);
521
522 extra[name_len] = '\0';
523
524 GNUNET_MQ_send (handle->mq, env);
525 return GNUNET_YES;
526}
527
528static const struct GNUNET_IDENTITY_PublicKey*
529get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
530{
531 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
532 return NULL;
533
534 return public_key;
535}
536
537const struct GNUNET_IDENTITY_PublicKey*
538GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
539{
540 if (!handle)
541 return NULL;
542
543 return get_non_anonymous_key (get_handle_key (handle));
544}
545
546struct GNUNET_MESSENGER_Room*
547GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle,
548 const struct GNUNET_HashCode *key)
549{
550 if ((!handle) || (!key))
551 return NULL;
552
553 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
554
555 if (!room)
556 {
557 room = create_room (handle, key);
558
559 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
560 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
561 {
562 destroy_room (room);
563 return NULL;
564 }
565 }
566
567 send_open_room (handle, room);
568 return room;
569}
570
571struct GNUNET_MESSENGER_Room*
572GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle,
573 const struct GNUNET_PeerIdentity *door,
574 const struct GNUNET_HashCode *key)
575{
576 if ((!handle) || (!door) || (!key))
577 return NULL;
578
579 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
580
581 if (!room)
582 {
583 room = create_room (handle, key);
584
585 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
586 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
587 {
588 destroy_room (room);
589 return NULL;
590 }
591 }
592
593 send_enter_room (handle, room, door);
594 return room;
595}
596
597void
598GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
599{
600 if (!room)
601 return;
602
603 send_close_room (room->handle, room);
604}
605
606struct GNUNET_MESSENGER_RoomFind
607{
608 const struct GNUNET_MESSENGER_Contact *contact;
609 GNUNET_MESSENGER_MemberCallback callback;
610 size_t counter;
611 void *cls;
612};
613
614static int
615iterate_find_room (void* cls,
616 const struct GNUNET_HashCode *key,
617 void *value)
618{
619 struct GNUNET_MESSENGER_RoomFind *find = cls;
620 struct GNUNET_MESSENGER_Room *room = value;
621
622 if ((find->counter > 0) && ((!find->contact) || (GNUNET_YES == find_room_member(room, find->contact))))
623 {
624 find->counter--;
625
626 if (!find->callback)
627 return GNUNET_YES;
628
629 return find->callback(find->cls, room, find->contact);
630 }
631 else
632 return GNUNET_NO;
633}
634
635int
636GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle,
637 const struct GNUNET_MESSENGER_Contact *contact,
638 GNUNET_MESSENGER_MemberCallback callback,
639 void *cls)
640{
641 if (!handle)
642 return GNUNET_SYSERR;
643
644 struct GNUNET_MESSENGER_RoomFind find;
645
646 find.contact = contact;
647 find.callback = callback;
648 find.counter = (contact? contact->rc : SIZE_MAX);
649 find.cls = cls;
650
651 return GNUNET_CONTAINER_multihashmap_iterate(handle->rooms, iterate_find_room, &find);
652}
653
654const struct GNUNET_HashCode*
655GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
656{
657 if (!room)
658 return NULL;
659
660 return &(room->key);
661}
662
663const struct GNUNET_MESSENGER_Contact*
664GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room,
665 const struct GNUNET_HashCode *hash)
666{
667 if ((!room) || (!hash))
668 return NULL;
669
670 return get_room_sender(room, hash);
671}
672
673const char*
674GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact)
675{
676 if (!contact)
677 return NULL;
678
679 return get_contact_name (contact);
680}
681
682const struct GNUNET_IDENTITY_PublicKey*
683GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact)
684{
685 if (!contact)
686 return NULL;
687
688 return get_non_anonymous_key (get_contact_key (contact));
689}
690
691void
692GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
693 const struct GNUNET_MESSENGER_Message *message,
694 const struct GNUNET_MESSENGER_Contact *contact)
695{
696 if ((!room) || (!message))
697 return;
698
699 switch (filter_message_sending (message))
700 {
701 case GNUNET_SYSERR:
702 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
703 return;
704 case GNUNET_NO:
705 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
706 return;
707 default:
708 break;
709 }
710
711 ssize_t key_length = 0;
712
713 if (contact)
714 {
715 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
716 get_contact_key(contact)
717 );
718
719 if (public_key)
720 key_length = GNUNET_IDENTITY_key_get_length(public_key);
721 else
722 key_length = -1;
723 }
724
725 if (key_length < 0)
726 {
727 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
728 return;
729 }
730
731 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
732
733 struct GNUNET_MESSENGER_SendMessage *msg;
734 struct GNUNET_MQ_Envelope *env;
735
736 const uint16_t length = (uint16_t) key_length + msg_length;
737
738 env = GNUNET_MQ_msg_extra(
739 msg, length,
740 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
741 );
742
743 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
744
745 msg->flags = (uint32_t) (
746 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
747 );
748
749 char *buffer = ((char*) msg) + sizeof(*msg);
750 char *msg_buffer = buffer + key_length;
751
752 if (key_length > 0)
753 GNUNET_IDENTITY_write_key_to_buffer(get_contact_key(contact), buffer, key_length);
754
755 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
756
757 GNUNET_MQ_send (room->handle->mq, env);
758}
759
760const struct GNUNET_MESSENGER_Message*
761GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room,
762 const struct GNUNET_HashCode *hash)
763{
764 if ((!room) || (!hash))
765 return NULL;
766
767 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
768
769 if (!message)
770 {
771 struct GNUNET_MESSENGER_GetMessage *msg;
772 struct GNUNET_MQ_Envelope *env;
773
774 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
775 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
776 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
777 GNUNET_MQ_send (room->handle->mq, env);
778 }
779
780 return message;
781}
782
783int
784GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room,
785 GNUNET_MESSENGER_MemberCallback callback,
786 void *cls)
787{
788 if (!room)
789 return GNUNET_SYSERR;
790
791 return iterate_room_members(room, callback, cls);
792}
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c
deleted file mode 100644
index cbca17640..000000000
--- a/src/messenger/messenger_api_contact.c
+++ /dev/null
@@ -1,110 +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,
64 const char *name)
65{
66 GNUNET_assert(contact);
67
68 if (contact->name)
69 GNUNET_free(contact->name);
70
71 contact->name = name ? GNUNET_strdup(name) : NULL;
72}
73
74const struct GNUNET_IDENTITY_PublicKey*
75get_contact_key (const struct GNUNET_MESSENGER_Contact *contact)
76{
77 GNUNET_assert(contact);
78
79 return &(contact->public_key);
80}
81
82void
83increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
84{
85 GNUNET_assert(contact);
86
87 contact->rc++;
88}
89
90int
91decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
92{
93 GNUNET_assert(contact);
94
95 if (contact->rc > 0)
96 contact->rc--;
97
98 return contact->rc ? GNUNET_NO : GNUNET_YES;
99}
100
101void
102get_context_from_member (const struct GNUNET_HashCode *key,
103 const struct GNUNET_ShortHashCode *id,
104 struct GNUNET_HashCode *context)
105{
106 GNUNET_assert((key) && (id) && (context));
107
108 GNUNET_CRYPTO_hash (id, sizeof(*id), context);
109 GNUNET_CRYPTO_hash_xor (key, context, context);
110}
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h
deleted file mode 100644
index b5410f998..000000000
--- a/src/messenger/messenger_api_contact.h
+++ /dev/null
@@ -1,116 +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,
75 const char *name);
76
77/**
78 * Returns the public key of a given <i>contact</i>.
79 *
80 * @param[in] contact Contact
81 * @return Public key of the contact
82 */
83const struct GNUNET_IDENTITY_PublicKey*
84get_contact_key (const struct GNUNET_MESSENGER_Contact *contact);
85
86/**
87 * Increases the reference counter of a given <i>contact</i> which is zero as default.
88 *
89 * @param[in/out] contact Contact
90 */
91void
92increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
93
94/**
95 * Decreases the reference counter if possible (can not underflow!) of a given <i>contact</i>
96 * and returns #GNUNET_YES if the counter is equal to zero, otherwise #GNUNET_NO.
97 *
98 * @param[in/out] contact Contact
99 * @return #GNUNET_YES or #GNUNET_NO depending on the reference counter
100 */
101int
102decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact);
103
104/**
105 * Calculates the context <i>hash</i> of a member in a room and returns it.
106 *
107 * @param[in] key Key of room
108 * @param[in] id Member id
109 * @param[out] hash Member context
110 */
111void
112get_context_from_member (const struct GNUNET_HashCode *key,
113 const struct GNUNET_ShortHashCode *id,
114 struct GNUNET_HashCode *context);
115
116#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 1c10a8fbf..000000000
--- a/src/messenger/messenger_api_contact_store.c
+++ /dev/null
@@ -1,193 +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,
42 const struct GNUNET_HashCode *key,
43 void *value)
44{
45 struct GNUNET_MESSENGER_Contact *contact = value;
46 destroy_contact (contact);
47 return GNUNET_YES;
48}
49
50void
51clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
52{
53 GNUNET_assert ((store) && (store->contacts));
54
55 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
56 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
57
58 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
59 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
60}
61
62static struct GNUNET_CONTAINER_MultiHashMap*
63select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store,
64 const struct GNUNET_HashCode *context,
65 struct GNUNET_HashCode *hash)
66{
67 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
68
69 struct GNUNET_HashCode anonHash;
70 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
71
72 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
73 {
74 GNUNET_memcpy(hash, context, sizeof(*context));
75 return store->anonymous;
76 }
77 else
78 return store->contacts;
79}
80
81struct GNUNET_MESSENGER_Contact*
82get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store,
83 const struct GNUNET_HashCode *context,
84 const struct GNUNET_HashCode *key_hash)
85{
86 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
87
88 struct GNUNET_HashCode hash;
89 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
90
91 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
92 store, context, &hash
93 );
94
95 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
96}
97
98struct GNUNET_MESSENGER_Contact*
99get_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
100 const struct GNUNET_HashCode *context,
101 const struct GNUNET_IDENTITY_PublicKey *pubkey)
102{
103 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
104
105 struct GNUNET_HashCode hash;
106 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
107
108 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
109 store, context, &hash
110 );
111
112 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
113
114 if (contact)
115 {
116 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
117 {
118 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
119 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
120 GNUNET_free (str);
121 return NULL;
122 }
123
124 return contact;
125 }
126
127 contact = create_contact (pubkey);
128
129 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
130 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
131 return contact;
132
133 destroy_contact (contact);
134 return NULL;
135}
136
137void
138update_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
139 struct GNUNET_MESSENGER_Contact* contact,
140 const struct GNUNET_HashCode *context,
141 const struct GNUNET_HashCode *next_context,
142 const struct GNUNET_IDENTITY_PublicKey *pubkey)
143{
144 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
145
146 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
147
148 struct GNUNET_HashCode hash;
149 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
150
151 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
152 store, context, &hash
153 );
154
155 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
156 {
157 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
158
159 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
160
161 map = select_store_contact_map (
162 store, next_context, &hash
163 );
164
165 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
166 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
167 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating a contact failed: %s\n",
168 GNUNET_h2s(&hash));
169 }
170}
171
172void
173remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
174 struct GNUNET_MESSENGER_Contact* contact,
175 const struct GNUNET_HashCode *context)
176{
177 GNUNET_assert ((store) && (store->contacts) && (contact));
178
179 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
180
181 struct GNUNET_HashCode hash;
182 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
183
184 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
185 store, context, &hash
186 );
187
188 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
189 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a contact failed: %s\n",
190 GNUNET_h2s(&hash));
191
192 destroy_contact (contact);
193}
diff --git a/src/messenger/messenger_api_contact_store.h b/src/messenger/messenger_api_contact_store.h
deleted file mode 100644
index bdab2ceeb..000000000
--- a/src/messenger/messenger_api_contact_store.h
+++ /dev/null
@@ -1,127 +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,
72 const struct GNUNET_HashCode *context,
73 const struct GNUNET_HashCode *key_hash);
74
75/**
76 * Returns a contact using a specific public key. In case the anonymous
77 * key gets used by the requested contact, it will use its provided member
78 * <i>context</i> to select the matching contact from the <i>store</i>.
79 *
80 * In case there is no contact stored which uses the given key or context,
81 * a new contact will be created automatically.
82 *
83 * The function returns NULL if an error occurs during allocation
84 * or validation of the contacts key.
85 *
86 * @param[in/out] store Contact store
87 * @param[in] context Member context
88 * @param[in] pubkey Public key of EGO
89 */
90struct GNUNET_MESSENGER_Contact*
91get_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
92 const struct GNUNET_HashCode *context,
93 const struct GNUNET_IDENTITY_PublicKey *pubkey);
94
95/**
96 * Moves a <i>contact</i> from the <i>store</i> to another location
97 * matching a given public key and member <i>context</i>.
98 *
99 * This function allows changes of keys or changes of member contexts!
100 *
101 * @param[in/out] store Contact store
102 * @param[in/out] contact Contact
103 * @param[in] context Member context
104 * @param[in] next_context Member context
105 * @param[in] pubkey Public key of EGO
106 */
107void
108update_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
109 struct GNUNET_MESSENGER_Contact* contact,
110 const struct GNUNET_HashCode *context,
111 const struct GNUNET_HashCode *next_context,
112 const struct GNUNET_IDENTITY_PublicKey *pubkey);
113
114/**
115 * Removes a <i>contact</i> from the <i>store</i> which uses
116 * a given member <i>context</i>.
117 *
118 * @param[in/out] store Contact store
119 * @param[in/out] contact Contact
120 * @param[in] context Member context
121 */
122void
123remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
124 struct GNUNET_MESSENGER_Contact* contact,
125 const struct GNUNET_HashCode *context);
126
127#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 242389040..000000000
--- a/src/messenger/messenger_api_handle.c
+++ /dev/null
@@ -1,207 +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,
32 GNUNET_MESSENGER_IdentityCallback identity_callback,
33 void *identity_cls,
34 GNUNET_MESSENGER_MessageCallback msg_callback,
35 void *msg_cls)
36{
37 GNUNET_assert(cfg);
38
39 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle);
40
41 handle->cfg = cfg;
42 handle->mq = NULL;
43
44 handle->identity_callback = identity_callback;
45 handle->identity_cls = identity_cls;
46
47 handle->msg_callback = msg_callback;
48 handle->msg_cls = msg_cls;
49
50 handle->name = NULL;
51 handle->pubkey = NULL;
52
53 handle->reconnect_time = GNUNET_TIME_relative_get_zero_ ();
54 handle->reconnect_task = NULL;
55
56 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
57
58 init_contact_store(get_handle_contact_store(handle));
59
60 return handle;
61}
62
63static int
64iterate_destroy_room (void *cls,
65 const struct GNUNET_HashCode *key,
66 void *value)
67{
68 struct GNUNET_MESSENGER_Room *room = value;
69
70 destroy_room (room);
71
72 return GNUNET_YES;
73}
74
75void
76destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
77{
78 GNUNET_assert(handle);
79
80 if (handle->reconnect_task)
81 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
82
83 if (handle->mq)
84 GNUNET_MQ_destroy (handle->mq);
85
86 if (handle->name)
87 GNUNET_free(handle->name);
88
89 if (handle->pubkey)
90 GNUNET_free(handle->pubkey);
91
92 if (handle->rooms)
93 {
94 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_destroy_room, NULL);
95
96 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms);
97 }
98
99 clear_contact_store(get_handle_contact_store(handle));
100
101 GNUNET_free(handle);
102}
103
104void
105set_handle_name (struct GNUNET_MESSENGER_Handle *handle,
106 const char *name)
107{
108 GNUNET_assert(handle);
109
110 if (handle->name)
111 GNUNET_free(handle->name);
112
113 handle->name = name ? GNUNET_strdup(name) : NULL;
114}
115
116const char*
117get_handle_name (const struct GNUNET_MESSENGER_Handle *handle)
118{
119 GNUNET_assert(handle);
120
121 return handle->name;
122}
123
124void
125set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
126 const struct GNUNET_IDENTITY_PublicKey *pubkey)
127{
128 GNUNET_assert(handle);
129
130 if (!handle->pubkey)
131 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
132
133 GNUNET_memcpy(handle->pubkey, pubkey, sizeof(*pubkey));
134}
135
136const struct GNUNET_IDENTITY_PublicKey*
137get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
138{
139 GNUNET_assert(handle);
140
141 if (handle->pubkey)
142 return handle->pubkey;
143
144 return get_anonymous_public_key ();
145}
146
147struct GNUNET_MESSENGER_ContactStore*
148get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle)
149{
150 GNUNET_assert(handle);
151
152 return &(handle->contact_store);
153}
154
155struct GNUNET_MESSENGER_Contact*
156get_handle_contact (struct GNUNET_MESSENGER_Handle *handle,
157 const struct GNUNET_HashCode *key)
158{
159 GNUNET_assert((handle) && (key));
160
161 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
162
163 if ((!room) || (!(room->contact_id)))
164 return NULL;
165
166 struct GNUNET_HashCode context;
167 get_context_from_member (key, room->contact_id, &context);
168
169 return get_store_contact(get_handle_contact_store(handle), &context, get_handle_key(handle));
170}
171
172void
173open_handle_room (struct GNUNET_MESSENGER_Handle *handle,
174 const struct GNUNET_HashCode *key)
175{
176 GNUNET_assert((handle) && (key));
177
178 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
179
180 if (room)
181 room->opened = GNUNET_YES;
182}
183
184void
185entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle,
186 const struct GNUNET_PeerIdentity *door,
187 const struct GNUNET_HashCode *key)
188{
189 GNUNET_assert((handle) && (door) && (key));
190
191 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
192
193 if (room)
194 add_to_list_tunnels (&(room->entries), door);
195}
196
197void
198close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
199 const struct GNUNET_HashCode *key)
200{
201 GNUNET_assert((handle) && (key));
202
203 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
204
205 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room)))
206 destroy_room (room);
207}
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h
deleted file mode 100644
index 6a43f13a6..000000000
--- a/src/messenger/messenger_api_handle.h
+++ /dev/null
@@ -1,180 +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,
75 GNUNET_MESSENGER_IdentityCallback identity_callback,
76 void *identity_cls,
77 GNUNET_MESSENGER_MessageCallback msg_callback,
78 void *msg_cls);
79
80/**
81 * Destroys a <i>handle</i> and frees its memory fully from the client API.
82 *
83 * @param[in/out] handle Handle
84 */
85void
86destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
87
88/**
89 * Sets the name of a <i>handle</i> to a specific <i>name</i>.
90 *
91 * @param[in/out] handle Handle
92 * @param[in] name New name
93 */
94void
95set_handle_name (struct GNUNET_MESSENGER_Handle *handle,
96 const char *name);
97
98/**
99 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet.
100 *
101 * @param[in] handle Handle
102 * @return Name of the handle or NULL
103 */
104const char*
105get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
106
107/**
108 * Sets the public key of a given <i>handle</i> to a specific public key.
109 *
110 * @param[in/out] handle Handle
111 * @param[in] pubkey Public key
112 */
113void
114set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
115 const struct GNUNET_IDENTITY_PublicKey *pubkey);
116
117/**
118 * Returns the public key of a given <i>handle</i>.
119 *
120 * @param[in] handle Handle
121 * @return Public key of the handle
122 */
123const struct GNUNET_IDENTITY_PublicKey*
124get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
125
126/**
127 * Returns the used contact store of a given <i>handle</i>.
128 *
129 * @param[in/out] handle Handle
130 * @return Contact store
131 */
132struct GNUNET_MESSENGER_ContactStore*
133get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle);
134
135/**
136 * Returns the contact of a given <i>handle</i> in a room identified by a
137 * given <i>key</i>.
138 *
139 * @param[in/out] handle Handle
140 * @param[in] key Key of room
141 * @return Contact
142 */
143struct GNUNET_MESSENGER_Contact*
144get_handle_contact (struct GNUNET_MESSENGER_Handle *handle,
145 const struct GNUNET_HashCode *key);
146
147/**
148 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open.
149 *
150 * @param[in/out] handle Handle
151 * @param[in] key Key of room
152 */
153void
154open_handle_room (struct GNUNET_MESSENGER_Handle *handle,
155 const struct GNUNET_HashCode *key);
156
157/**
158 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a
159 * list of opened connections.
160 *
161 * @param[in/out] handle Handle
162 * @param[in] door Peer identity
163 * @param[in] key Key of room
164 */
165void
166entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle,
167 const struct GNUNET_PeerIdentity *door,
168 const struct GNUNET_HashCode *key);
169
170/**
171 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>.
172 *
173 * @param[in/out] handle Handle
174 * @param[in] key Key of room
175 */
176void
177close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
178 const struct GNUNET_HashCode *key);
179
180#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 7e77d8f2f..000000000
--- a/src/messenger/messenger_api_list_tunnels.c
+++ /dev/null
@@ -1,192 +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,
57 struct GNUNET_MESSENGER_ListTunnel *element0,
58 struct GNUNET_MESSENGER_ListTunnel *element1)
59{
60 return ((int) element0->peer) - ((int) element1->peer);
61}
62
63void
64add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
65 const struct GNUNET_PeerIdentity *peer)
66{
67 GNUNET_assert((tunnels) && (peer));
68
69 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel);
70
71 element->peer = GNUNET_PEER_intern (peer);
72
73 GNUNET_CONTAINER_DLL_insert_sorted(struct GNUNET_MESSENGER_ListTunnel, compare_list_tunnels, NULL, tunnels->head,
74 tunnels->tail, element);
75}
76
77struct GNUNET_MESSENGER_ListTunnel*
78find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
79 const struct GNUNET_PeerIdentity *peer,
80 size_t *index)
81{
82 GNUNET_assert((tunnels) && (peer));
83
84 struct GNUNET_MESSENGER_ListTunnel *element;
85 struct GNUNET_PeerIdentity pid;
86
87 if (index)
88 *index = 0;
89
90 for (element = tunnels->head; element; element = element->next)
91 {
92 GNUNET_PEER_resolve (element->peer, &pid);
93
94 if (0 == GNUNET_memcmp(&pid, peer))
95 return element;
96
97 if (index)
98 (*index) = (*index) + 1;
99 }
100
101 return NULL;
102}
103
104int
105contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
106 const struct GNUNET_PeerIdentity *peer)
107{
108 GNUNET_assert((tunnels) && (peer));
109
110 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO;
111}
112
113struct GNUNET_MESSENGER_ListTunnel*
114remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
115 struct GNUNET_MESSENGER_ListTunnel *element)
116{
117 GNUNET_assert((tunnels) && (element));
118
119 struct GNUNET_MESSENGER_ListTunnel *next = element->next;
120
121 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
122 GNUNET_PEER_change_rc (element->peer, -1);
123 GNUNET_free(element);
124
125 return next;
126}
127
128void
129load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
130 const char *path)
131{
132 GNUNET_assert((tunnels) && (path));
133
134 if (GNUNET_YES != GNUNET_DISK_file_test (path))
135 return;
136
137 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
138
139 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
140 path, GNUNET_DISK_OPEN_READ, permission
141 );
142
143 if (!handle)
144 return;
145
146 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
147
148 struct GNUNET_PeerIdentity peer;
149 ssize_t len;
150
151 do {
152 len = GNUNET_DISK_file_read(handle, &peer, sizeof(peer));
153
154 if (len != sizeof(peer))
155 break;
156
157 add_to_list_tunnels(tunnels, &peer);
158 } while (len == sizeof(peer));
159
160 GNUNET_DISK_file_close(handle);
161}
162
163void
164save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
165 const char *path)
166{
167 GNUNET_assert((tunnels) && (path));
168
169 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
170
171 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
172 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
173 );
174
175 if (!handle)
176 return;
177
178 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
179
180 struct GNUNET_MESSENGER_ListTunnel *element;
181 struct GNUNET_PeerIdentity pid;
182
183 for (element = tunnels->head; element; element = element->next)
184 {
185 GNUNET_PEER_resolve (element->peer, &pid);
186
187 GNUNET_DISK_file_write(handle, &pid, sizeof(pid));
188 }
189
190 GNUNET_DISK_file_sync(handle);
191 GNUNET_DISK_file_close(handle);
192}
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h
deleted file mode 100644
index 0e086ee5e..000000000
--- a/src/messenger/messenger_api_list_tunnels.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/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,
71 const struct GNUNET_PeerIdentity *peer);
72
73/**
74 * Searches linearly through the list of tunnels peer identities for matching a
75 * specific <i>peer</i> identity and returns the matching element of the list.
76 *
77 * If no matching element is found, NULL gets returned.
78 *
79 * If <i>index</i> is not NULL, <i>index</i> will be overridden with the numeric index of
80 * the found element in the list. If no matching element is found, <i>index</i> will
81 * contain the total amount of elements in the list.
82 *
83 * @param[in/out] tunnels List of peer identities
84 * @param[in] peer Peer identity of tunnel
85 * @param[out] index Index of found element (optional)
86 * @return Element in the list with matching peer identity
87 */
88struct GNUNET_MESSENGER_ListTunnel*
89find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
90 const struct GNUNET_PeerIdentity *peer,
91 size_t *index);
92
93/**
94 * Tests linearly if the list of tunnels peer identities contains a specific
95 * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise #GNUNET_NO.
96 *
97 * @param[in/out] tunnels List of peer identities
98 * @param[in] peer Peer identity of tunnel
99 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
100 */
101int
102contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
103 const struct GNUNET_PeerIdentity *peer);
104
105/**
106 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns
107 * the next element in the list.
108 *
109 * @param[in/out] tunnels List of peer identities
110 * @param[in/out] element Element of the list
111 * @return Next element in the list
112 */
113struct GNUNET_MESSENGER_ListTunnel*
114remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
115 struct GNUNET_MESSENGER_ListTunnel *element);
116
117/**
118 * Loads the list of tunnels peer identities from a file under a given <i>path</i>.
119 *
120 * @param[out] messages List of hashes
121 * @param[in] path Path of file
122 */
123void
124load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
125 const char *path);
126
127/**
128 * Saves the list of tunnels peer identities to a file under a given <i>path</i>.
129 *
130 * @param[in] messages List of hashes
131 * @param[in] path Path of file
132 */
133void
134save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
135 const char *path);
136
137#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 496c98dbf..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,932 +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,
107 struct GNUNET_MESSENGER_MessageBody *body)
108{
109 switch (kind)
110 {
111 case GNUNET_MESSENGER_KIND_NAME:
112 GNUNET_free(body->name.name);
113 break;
114 case GNUNET_MESSENGER_KIND_TEXT:
115 GNUNET_free(body->text.text);
116 break;
117 case GNUNET_MESSENGER_KIND_FILE:
118 GNUNET_free(body->file.uri);
119 break;
120 case GNUNET_MESSENGER_KIND_PRIVATE:
121 GNUNET_free(body->privacy.data);
122 break;
123 default:
124 break;
125 }
126}
127
128void
129cleanup_message (struct GNUNET_MESSENGER_Message *message)
130{
131 GNUNET_assert(message);
132
133 destroy_message_body (message->header.kind, &(message->body));
134}
135
136void
137destroy_message (struct GNUNET_MESSENGER_Message *message)
138{
139 GNUNET_assert(message);
140
141 destroy_message_body (message->header.kind, &(message->body));
142
143 GNUNET_free(message);
144}
145
146int
147is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
148{
149 GNUNET_assert(message);
150
151 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
152 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
153 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
154 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
155 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
156 return GNUNET_YES;
157 else
158 return GNUNET_NO;
159}
160
161static void
162fold_short_message (const struct GNUNET_MESSENGER_Message *message,
163 struct GNUNET_MESSENGER_ShortMessage *shortened)
164{
165 shortened->kind = message->header.kind;
166
167 GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
168}
169
170static void
171unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened,
172 struct GNUNET_MESSENGER_Message *message)
173{
174 destroy_message_body (message->header.kind, &(message->body));
175
176 message->header.kind = shortened->kind;
177
178 GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
179}
180
181#define member_size(type, member) sizeof(((type*) NULL)->member)
182
183static uint16_t
184get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
185{
186 uint16_t length = 0;
187
188 switch (kind)
189 {
190 case GNUNET_MESSENGER_KIND_INFO:
191 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
192 break;
193 case GNUNET_MESSENGER_KIND_PEER:
194 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
195 break;
196 case GNUNET_MESSENGER_KIND_ID:
197 length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
198 break;
199 case GNUNET_MESSENGER_KIND_MISS:
200 length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
201 break;
202 case GNUNET_MESSENGER_KIND_MERGE:
203 length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous);
204 break;
205 case GNUNET_MESSENGER_KIND_REQUEST:
206 length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
207 break;
208 case GNUNET_MESSENGER_KIND_INVITE:
209 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
210 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
211 break;
212 case GNUNET_MESSENGER_KIND_TEXT:
213 break;
214 case GNUNET_MESSENGER_KIND_FILE:
215 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
216 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
217 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
218 break;
219 case GNUNET_MESSENGER_KIND_PRIVATE:
220 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
221 break;
222 default:
223 break;
224 }
225
226 return length;
227}
228
229typedef uint32_t kind_t;
230
231uint16_t
232get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
233 int include_header)
234{
235 uint16_t length = 0;
236
237 if (GNUNET_YES == include_header)
238 {
239 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
240 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
241 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
242 }
243
244 length += sizeof(kind_t);
245
246 return length + get_message_body_kind_size (kind);
247}
248
249static uint16_t
250get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
251 const struct GNUNET_MESSENGER_MessageBody *body)
252{
253 uint16_t length = 0;
254
255 switch (kind)
256 {
257 case GNUNET_MESSENGER_KIND_INFO:
258 length += GNUNET_IDENTITY_key_get_length(&(body->info.host_key));
259 break;
260 case GNUNET_MESSENGER_KIND_JOIN:
261 length += GNUNET_IDENTITY_key_get_length(&(body->join.key));
262 break;
263 case GNUNET_MESSENGER_KIND_NAME:
264 length += (body->name.name ? strlen (body->name.name) : 0);
265 break;
266 case GNUNET_MESSENGER_KIND_KEY:
267 length += GNUNET_IDENTITY_key_get_length(&(body->key.key));
268 break;
269 case GNUNET_MESSENGER_KIND_TEXT:
270 length += strlen (body->text.text);
271 break;
272 case GNUNET_MESSENGER_KIND_FILE:
273 length += strlen (body->file.uri);
274 break;
275 case GNUNET_MESSENGER_KIND_PRIVATE:
276 length += body->privacy.length;
277 break;
278 default:
279 break;
280 }
281
282 return length;
283}
284
285uint16_t
286get_message_size (const struct GNUNET_MESSENGER_Message *message,
287 int include_header)
288{
289 GNUNET_assert(message);
290
291 uint16_t length = 0;
292
293 if (GNUNET_YES == include_header)
294 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
295
296 length += get_message_kind_size (message->header.kind, include_header);
297 length += get_message_body_size (message->header.kind, &(message->body));
298
299 return length;
300}
301
302static uint16_t
303get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
304 int include_body)
305{
306 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
307
308 if (message)
309 return minimum_size + get_message_body_kind_size (message->kind)
310 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
311 else
312 return minimum_size;
313}
314
315static uint16_t
316calc_usual_padding ()
317{
318 uint16_t padding = 0;
319 uint16_t kind_size;
320
321 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
322 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, GNUNET_YES);
323
324 if (kind_size > padding)
325 padding = kind_size;
326 }
327
328 return padding + GNUNET_MESSENGER_PADDING_MIN;
329}
330
331#define max(x, y) (x > y? x : y)
332
333static uint16_t
334calc_padded_length (uint16_t length)
335{
336 static uint16_t usual_padding = 0;
337
338 if (!usual_padding)
339 usual_padding = calc_usual_padding();
340
341 const uint16_t padded_length = max(
342 length + GNUNET_MESSENGER_PADDING_MIN,
343 usual_padding
344 );
345
346 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
347 return GNUNET_MESSENGER_PADDING_LEVEL0;
348
349 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
350 return GNUNET_MESSENGER_PADDING_LEVEL1;
351
352 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
353 return GNUNET_MESSENGER_PADDING_LEVEL2;
354
355 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
356
357}
358
359#define min(x, y) (x < y? x : y)
360
361#define encode_step_ext(dst, offset, src, size) do { \
362 GNUNET_memcpy(dst + offset, src, size); \
363 offset += size; \
364} while (0)
365
366#define encode_step(dst, offset, src) do { \
367 encode_step_ext(dst, offset, src, sizeof(*src)); \
368} while (0)
369
370#define encode_step_key(dst, offset, src, length) do { \
371 ssize_t result = GNUNET_IDENTITY_write_key_to_buffer( \
372 src, dst + offset, length - offset \
373 ); \
374 if (result < 0) \
375 GNUNET_break (0); \
376 else \
377 offset += result; \
378} while (0)
379
380#define encode_step_signature(dst, offset, src, length) do { \
381 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
382 src, dst + offset, length - offset \
383 ); \
384 if (result < 0) \
385 GNUNET_break (0); \
386 else \
387 offset += result; \
388} while (0)
389
390static void
391encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
392 const struct GNUNET_MESSENGER_MessageBody *body,
393 uint16_t length,
394 char *buffer,
395 uint16_t offset)
396{
397 uint32_t version;
398 switch (kind)
399 {
400 case GNUNET_MESSENGER_KIND_INFO:
401 version = GNUNET_htobe32(body->info.messenger_version);
402
403 encode_step_key(buffer, offset, &(body->info.host_key), length);
404 encode_step(buffer, offset, &version);
405 break;
406 case GNUNET_MESSENGER_KIND_JOIN:
407 encode_step_key(buffer, offset, &(body->join.key), length);
408 break;
409 case GNUNET_MESSENGER_KIND_NAME:
410 if (body->name.name)
411 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
412 break;
413 case GNUNET_MESSENGER_KIND_KEY:
414 encode_step_key(buffer, offset, &(body->key.key), length);
415 break;
416 case GNUNET_MESSENGER_KIND_PEER:
417 encode_step(buffer, offset, &(body->peer.peer));
418 break;
419 case GNUNET_MESSENGER_KIND_ID:
420 encode_step(buffer, offset, &(body->id.id));
421 break;
422 case GNUNET_MESSENGER_KIND_MISS:
423 encode_step(buffer, offset, &(body->miss.peer));
424 break;
425 case GNUNET_MESSENGER_KIND_MERGE:
426 encode_step(buffer, offset, &(body->merge.previous));
427 break;
428 case GNUNET_MESSENGER_KIND_REQUEST:
429 encode_step(buffer, offset, &(body->request.hash));
430 break;
431 case GNUNET_MESSENGER_KIND_INVITE:
432 encode_step(buffer, offset, &(body->invite.door));
433 encode_step(buffer, offset, &(body->invite.key));
434 break;
435 case GNUNET_MESSENGER_KIND_TEXT:
436 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
437 break;
438 case GNUNET_MESSENGER_KIND_FILE:
439 encode_step(buffer, offset, &(body->file.key));
440 encode_step(buffer, offset, &(body->file.hash));
441 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
442 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
443 break;
444 case GNUNET_MESSENGER_KIND_PRIVATE:
445 encode_step(buffer, offset, &(body->privacy.key));
446 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
447 break;
448 default:
449 break;
450 }
451
452 if (offset >= length)
453 return;
454
455 const uint16_t padding = length - offset;
456 const uint16_t used_padding = sizeof(padding) + sizeof(char);
457
458 GNUNET_assert(padding >= used_padding);
459
460 buffer[offset++] = '\0';
461
462 if (padding > used_padding)
463 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
464
465 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
466}
467
468void
469encode_message (const struct GNUNET_MESSENGER_Message *message,
470 uint16_t length,
471 char *buffer,
472 int include_header)
473{
474 GNUNET_assert((message) && (buffer));
475
476 uint16_t offset = 0;
477
478 if (GNUNET_YES == include_header)
479 encode_step_signature(buffer, offset, &(message->header.signature), length);
480
481 const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
482
483 if (GNUNET_YES == include_header)
484 {
485 encode_step(buffer, offset, &(message->header.timestamp));
486 encode_step(buffer, offset, &(message->header.sender_id));
487 encode_step(buffer, offset, &(message->header.previous));
488 }
489
490 encode_step(buffer, offset, &kind);
491
492 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
493}
494
495static void
496encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
497 uint16_t length,
498 char *buffer)
499{
500 struct GNUNET_HashCode hash;
501 uint16_t offset = sizeof(hash);
502
503 const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
504
505 encode_step(buffer, offset, &kind);
506
507 encode_message_body (message->kind, &(message->body), length, buffer, offset);
508
509 GNUNET_CRYPTO_hash(
510 buffer + sizeof(hash),
511 length - sizeof(hash),
512 &hash
513 );
514
515 GNUNET_memcpy(buffer, &hash, sizeof(hash));
516}
517
518#define decode_step_ext(src, offset, dst, size) do { \
519 GNUNET_memcpy(dst, src + offset, size); \
520 offset += size; \
521} while (0)
522
523#define decode_step(src, offset, dst) do { \
524 decode_step_ext(src, offset, dst, sizeof(*dst)); \
525} while (0)
526
527#define decode_step_malloc(src, offset, dst, size, zero) do { \
528 dst = GNUNET_malloc(size + zero); \
529 if (zero) dst[size] = 0; \
530 decode_step_ext(src, offset, dst, size); \
531} while (0)
532
533#define decode_step_key(src, offset, dst, length) do { \
534 ssize_t result = GNUNET_IDENTITY_read_key_from_buffer( \
535 dst, src + offset, length - offset \
536 ); \
537 if (result < 0) \
538 GNUNET_break(0); \
539 else \
540 offset += result; \
541} while (0)
542
543static uint16_t
544decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
545 struct GNUNET_MESSENGER_MessageBody *body,
546 uint16_t length,
547 const char *buffer,
548 uint16_t offset)
549{
550 uint16_t padding = 0;
551
552 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
553
554 if (padding > length - offset)
555 padding = 0;
556
557 const uint16_t end_zero = length - padding;
558
559 if ((padding) && (buffer[end_zero] != '\0'))
560 padding = 0;
561
562 length -= padding;
563
564 uint32_t version;
565 switch (*kind)
566 {
567 case GNUNET_MESSENGER_KIND_INFO: {
568 decode_step_key(buffer, offset, &(body->info.host_key), length);
569 decode_step(buffer, offset, &version);
570
571 body->info.messenger_version = GNUNET_be32toh(version);
572 break;
573 } case GNUNET_MESSENGER_KIND_JOIN: {
574 decode_step_key(buffer, offset, &(body->join.key), length);
575 break;
576 } case GNUNET_MESSENGER_KIND_NAME:
577 if (length - offset > 0)
578 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
579 else
580 body->name.name = NULL;
581 break;
582 case GNUNET_MESSENGER_KIND_KEY:
583 decode_step_key(buffer, offset, &(body->key.key), length);
584 break;
585 case GNUNET_MESSENGER_KIND_PEER:
586 decode_step(buffer, offset, &(body->peer.peer));
587 break;
588 case GNUNET_MESSENGER_KIND_ID:
589 decode_step(buffer, offset, &(body->id.id));
590 break;
591 case GNUNET_MESSENGER_KIND_MISS:
592 decode_step(buffer, offset, &(body->miss.peer));
593 break;
594 case GNUNET_MESSENGER_KIND_MERGE:
595 decode_step(buffer, offset, &(body->merge.previous));
596 break;
597 case GNUNET_MESSENGER_KIND_REQUEST:
598 decode_step(buffer, offset, &(body->request.hash));
599 break;
600 case GNUNET_MESSENGER_KIND_INVITE:
601 decode_step(buffer, offset, &(body->invite.door));
602 decode_step(buffer, offset, &(body->invite.key));
603 break;
604 case GNUNET_MESSENGER_KIND_TEXT:
605 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
606 break;
607 case GNUNET_MESSENGER_KIND_FILE:
608 decode_step(buffer, offset, &(body->file.key));
609 decode_step(buffer, offset, &(body->file.hash));
610 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
611 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
612 break;
613 case GNUNET_MESSENGER_KIND_PRIVATE:
614 decode_step(buffer, offset, &(body->privacy.key));
615
616 body->privacy.length = (length - offset);
617 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
618 break;
619 default:
620 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
621 break;
622 }
623
624 return padding;
625}
626
627int
628decode_message (struct GNUNET_MESSENGER_Message *message,
629 uint16_t length,
630 const char *buffer,
631 int include_header,
632 uint16_t *padding)
633{
634 GNUNET_assert(
635 (message) &&
636 (buffer) &&
637 (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
638 );
639
640 uint16_t offset = 0;
641
642 if (GNUNET_YES == include_header)
643 {
644 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
645 &(message->header.signature), buffer, length - offset
646 );
647
648 if (result < 0)
649 return GNUNET_NO;
650 else
651 offset += result;
652 }
653
654 const uint16_t count = length - offset;
655
656 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
657 return GNUNET_NO;
658
659 kind_t kind;
660
661 if (GNUNET_YES == include_header)
662 {
663 decode_step(buffer, offset, &(message->header.timestamp));
664 decode_step(buffer, offset, &(message->header.sender_id));
665 decode_step(buffer, offset, &(message->header.previous));
666 }
667
668 decode_step(buffer, offset, &kind);
669
670 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
671
672 if (count < get_message_kind_size (message->header.kind, include_header))
673 return GNUNET_NO;
674
675 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
676
677 if (padding)
678 *padding = result;
679
680 return GNUNET_YES;
681}
682
683static int
684decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
685 uint16_t length,
686 const char *buffer)
687{
688 struct GNUNET_HashCode expected, hash;
689 uint16_t offset = sizeof(hash);
690
691 if (length < get_short_message_size (NULL, GNUNET_NO))
692 return GNUNET_NO;
693
694 GNUNET_memcpy(&hash, buffer, sizeof(hash));
695
696 GNUNET_CRYPTO_hash(
697 buffer + sizeof(hash),
698 length - sizeof(hash),
699 &expected
700 );
701
702 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
703 return GNUNET_NO;
704
705 kind_t kind;
706
707 decode_step(buffer, offset, &kind);
708
709 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
710
711 if (length < get_short_message_size (message, GNUNET_NO))
712 return GNUNET_NO;
713
714 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
715
716 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
717 return GNUNET_NO;
718
719 return GNUNET_YES;
720}
721
722void
723hash_message (const struct GNUNET_MESSENGER_Message *message,
724 uint16_t length,
725 const char *buffer,
726 struct GNUNET_HashCode *hash)
727{
728 GNUNET_assert((message) && (buffer) && (hash));
729
730 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
731 &(message->header.signature)
732 );
733
734 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
735}
736
737void
738sign_message (struct GNUNET_MESSENGER_Message *message,
739 uint16_t length,
740 char *buffer,
741 const struct GNUNET_HashCode *hash,
742 const struct GNUNET_MESSENGER_Ego *ego)
743{
744 GNUNET_assert((message) && (buffer) && (hash) && (ego));
745
746 struct GNUNET_MESSENGER_MessageSignature signature;
747
748 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
749 signature.purpose.size = htonl (sizeof(signature));
750
751 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
752 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
753
754 uint16_t offset = 0;
755 encode_step_signature(buffer, offset, &(message->header.signature), length);
756}
757
758int
759verify_message (const struct GNUNET_MESSENGER_Message *message,
760 const struct GNUNET_HashCode *hash,
761 const struct GNUNET_IDENTITY_PublicKey *key)
762{
763 GNUNET_assert((message) && (hash) && (key));
764
765 if (ntohl (key->type) != ntohl (message->header.signature.type))
766 return GNUNET_SYSERR;
767
768 struct GNUNET_MESSENGER_MessageSignature signature;
769
770 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
771 signature.purpose.size = htonl (sizeof(signature));
772
773 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
774
775 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
776 &(message->header.signature), key);
777}
778
779int
780encrypt_message (struct GNUNET_MESSENGER_Message *message,
781 const struct GNUNET_IDENTITY_PublicKey *key)
782{
783 GNUNET_assert((message) && (key));
784
785 struct GNUNET_MESSENGER_ShortMessage shortened;
786
787 fold_short_message (message, &shortened);
788
789 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
790 const uint16_t padded_length = calc_padded_length(length);
791
792 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
793 message->body.privacy.data = GNUNET_malloc(padded_length);
794 message->body.privacy.length = padded_length;
795
796 encode_short_message (&shortened, padded_length, message->body.privacy.data);
797
798 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key,
799 &(message->body.privacy.key),
800 message->body.privacy.data))
801 {
802 destroy_message_body (shortened.kind, &(shortened.body));
803 return GNUNET_YES;
804 }
805 else
806 {
807 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
808
809 unfold_short_message (&shortened, message);
810 return GNUNET_NO;
811 }
812}
813
814int
815decrypt_message (struct GNUNET_MESSENGER_Message *message,
816 const struct GNUNET_IDENTITY_PrivateKey *key)
817{
818 GNUNET_assert((message) && (key));
819
820 if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length,
821 key, &(message->body.privacy.key),
822 message->body.privacy.data))
823 {
824 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
825
826 return GNUNET_NO;
827 }
828
829 struct GNUNET_MESSENGER_ShortMessage shortened;
830
831 if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data))
832 {
833 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
834
835 return GNUNET_NO;
836 }
837
838 unfold_short_message (&shortened, message);
839
840 return GNUNET_YES;
841}
842
843struct GNUNET_MQ_Envelope*
844pack_message (struct GNUNET_MESSENGER_Message *message,
845 struct GNUNET_HashCode *hash,
846 const struct GNUNET_MESSENGER_Ego *ego,
847 int mode)
848{
849 GNUNET_assert(message);
850
851 if (ego)
852 message->header.signature.type = ego->priv.type;
853
854 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
855 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
856
857 struct GNUNET_MessageHeader *header;
858
859 const uint16_t length = get_message_size (message, GNUNET_YES);
860 const uint16_t padded_length = calc_padded_length(length);
861
862 struct GNUNET_MQ_Envelope *env;
863 char *buffer;
864
865 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
866 {
867 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
868
869 buffer = (char*) &(header[1]);
870 }
871 else
872 {
873 env = NULL;
874
875 buffer = GNUNET_malloc(padded_length);
876 }
877
878 encode_message (message, padded_length, buffer, GNUNET_YES);
879
880 if (hash)
881 {
882 hash_message (message, length, buffer, hash);
883
884 if (ego)
885 sign_message (message, length, buffer, hash, ego);
886 }
887
888 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
889 GNUNET_free(buffer);
890
891 return env;
892}
893
894int
895filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
896{
897 switch (message->header.kind)
898 {
899 case GNUNET_MESSENGER_KIND_INFO:
900 return GNUNET_SYSERR; // Reserved for connection handling only!
901 case GNUNET_MESSENGER_KIND_JOIN:
902 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
903 case GNUNET_MESSENGER_KIND_LEAVE:
904 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
905 case GNUNET_MESSENGER_KIND_NAME:
906 return GNUNET_YES;
907 case GNUNET_MESSENGER_KIND_KEY:
908 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
909 case GNUNET_MESSENGER_KIND_PEER:
910 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
911 case GNUNET_MESSENGER_KIND_ID:
912 return GNUNET_SYSERR; // Reserved for member id handling only!
913 case GNUNET_MESSENGER_KIND_MISS:
914 return GNUNET_SYSERR; // Reserved for connection handling only!
915 case GNUNET_MESSENGER_KIND_MERGE:
916 return GNUNET_YES;
917 case GNUNET_MESSENGER_KIND_REQUEST:
918 return GNUNET_YES;
919 case GNUNET_MESSENGER_KIND_INVITE:
920 return GNUNET_YES;
921 case GNUNET_MESSENGER_KIND_TEXT:
922 return GNUNET_YES;
923 case GNUNET_MESSENGER_KIND_FILE:
924 return GNUNET_YES;
925 case GNUNET_MESSENGER_KIND_PRIVATE:
926 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
927 case GNUNET_MESSENGER_KIND_DELETE:
928 return GNUNET_YES;
929 default:
930 return GNUNET_SYSERR;
931 }
932}
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h
deleted file mode 100644
index 46c5cb024..000000000
--- a/src/messenger/messenger_api_message.h
+++ /dev/null
@@ -1,251 +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 * Frees the messages body memory.
66 *
67 * @param[in/out] message Message
68 */
69void
70cleanup_message (struct GNUNET_MESSENGER_Message *message);
71
72/**
73 * Destroys a message and frees its memory fully.
74 *
75 * @param[in/out] message Message
76 */
77void
78destroy_message (struct GNUNET_MESSENGER_Message *message);
79
80/**
81 * Returns if the message should be bound to a member session.
82 *
83 * @param[in] message Message
84 * @return #GNUNET_YES or #GNUNET_NO
85 */
86int
87is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
88
89/**
90 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>.
91 *
92 * @param[in] kind Kind of message
93 * @param[in] include_header Flag to include header
94 * @return Minimal size to encode
95 */
96uint16_t
97get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
98 int include_header);
99
100/**
101 * Returns the exact size in bytes to encode a given <i>message</i>.
102 *
103 * @param[in] message Message
104 * @param[in] include_header Flag to include header
105 * @return Size to encode
106 */
107uint16_t
108get_message_size (const struct GNUNET_MESSENGER_Message *message,
109 int include_header);
110
111/**
112 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes.
113 *
114 * @param[in] message Message
115 * @param[in] length Maximal length to encode
116 * @param[out] buffer Buffer
117 * @param[in] include_header Flag to include header
118 */
119void
120encode_message (const struct GNUNET_MESSENGER_Message *message,
121 uint16_t length,
122 char *buffer,
123 int include_header);
124
125/**
126 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes.
127 *
128 * If the buffer is too small for a message of its decoded kind the function fails with
129 * resulting #GNUNET_NO after decoding only the messages header.
130 *
131 * On success the function returns #GNUNET_YES.
132 *
133 * @param[out] message Message
134 * @param[in] length Maximal length to decode
135 * @param[in] buffer Buffer
136 * @param[in] include_header Flag to include header
137 * @param[out] padding Padding
138 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
139 */
140int
141decode_message (struct GNUNET_MESSENGER_Message *message,
142 uint16_t length,
143 const char *buffer,
144 int include_header,
145 uint16_t *padding);
146
147/**
148 * Calculates a <i>hash</i> of a given <i>buffer</i> with a <i>length</i> in bytes
149 * from a <i>message</i>.
150 *
151 * @param[in] message Message
152 * @param[in] length Length of buffer
153 * @param[in] buffer Buffer
154 * @param[out] hash Hash
155 */
156void
157hash_message (const struct GNUNET_MESSENGER_Message *message,
158 uint16_t length,
159 const char *buffer,
160 struct GNUNET_HashCode *hash);
161
162/**
163 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature
164 * into the <i>buffer</i> as well.
165 *
166 * @param[in/out] message Message
167 * @param[in] length Length of buffer
168 * @param[out] buffer Buffer
169 * @param[in] hash Hash of message
170 * @param[in] ego EGO
171 */
172void
173sign_message (struct GNUNET_MESSENGER_Message *message,
174 uint16_t length,
175 char *buffer,
176 const struct GNUNET_HashCode *hash,
177 const struct GNUNET_MESSENGER_Ego *ego);
178
179/**
180 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific
181 * public key. The function returns #GNUNET_OK if the signature was valid, otherwise
182 * #GNUNET_SYSERR.
183 *
184 * @param[in] message Message
185 * @param[in] hash Hash of message
186 * @param[in] key Public key of EGO
187 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
188 */
189int
190verify_message (const struct GNUNET_MESSENGER_Message *message,
191 const struct GNUNET_HashCode *hash,
192 const struct GNUNET_IDENTITY_PublicKey *key);
193
194/**
195 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body
196 * and kind with the now private encrypted <i>message</i>. The function returns
197 * #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
198 *
199 * @param[in/out] message Message
200 * @param[in] key Public key of EGO
201 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
202 */
203int
204encrypt_message (struct GNUNET_MESSENGER_Message *message,
205 const struct GNUNET_IDENTITY_PublicKey *key);
206
207/**
208 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body
209 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
210 * operation succeeded, otherwise #GNUNET_NO.
211 *
212 * @param[in/out] message Message
213 * @param[in] key Private key of EGO
214 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
215 */
216int
217decrypt_message (struct GNUNET_MESSENGER_Message *message,
218 const struct GNUNET_IDENTITY_PrivateKey *key);
219
220#define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1
221#define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0
222
223/**
224 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i>
225 * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
226 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is
227 * not NULL.
228 *
229 * @param[out] message Message
230 * @param[out] hash Hash of message
231 * @param[in] ego EGO to sign
232 * @param[in] mode Mode of packing
233 * @return Envelope or NULL
234 */
235struct GNUNET_MQ_Envelope*
236pack_message (struct GNUNET_MESSENGER_Message *message,
237 struct GNUNET_HashCode *hash,
238 const struct GNUNET_MESSENGER_Ego *ego,
239 int mode);
240
241/**
242 * Returns if a specific kind of message should be sent by a client. The function returns
243 * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
244 * of messages which should not be sent manually at all.
245 *
246 * @param[in] message Message
247 */
248int
249filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
250
251#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 6e2d33f48..000000000
--- a/src/messenger/messenger_api_room.c
+++ /dev/null
@@ -1,368 +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,
32 const struct GNUNET_HashCode *key)
33{
34 GNUNET_assert((handle) && (key));
35
36 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
37
38 room->handle = handle;
39 GNUNET_memcpy(&(room->key), key, sizeof(*key));
40
41 room->opened = GNUNET_NO;
42 room->contact_id = NULL;
43
44 init_list_tunnels (&(room->entries));
45
46 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
47 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
48
49 return room;
50}
51
52static int
53iterate_destroy_message (void *cls,
54 const struct GNUNET_HashCode *key,
55 void *value)
56{
57 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
58
59 destroy_message (entry->message);
60 GNUNET_free(entry);
61
62 return GNUNET_YES;
63}
64
65void
66destroy_room (struct GNUNET_MESSENGER_Room *room)
67{
68 GNUNET_assert(room);
69
70 clear_list_tunnels (&(room->entries));
71
72 if (room->messages)
73 {
74 GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL);
75
76 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
77 }
78
79 if (room->members)
80 GNUNET_CONTAINER_multishortmap_destroy (room->members);
81
82 if (room->contact_id)
83 GNUNET_free(room->contact_id);
84
85 GNUNET_free(room);
86}
87
88const struct GNUNET_MESSENGER_Message*
89get_room_message (const struct GNUNET_MESSENGER_Room *room,
90 const struct GNUNET_HashCode *hash)
91{
92 GNUNET_assert((room) && (hash));
93
94 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
95 room->messages, hash
96 );
97
98 return (entry? entry->message : NULL);
99}
100
101struct GNUNET_MESSENGER_Contact*
102get_room_sender (const struct GNUNET_MESSENGER_Room *room,
103 const struct GNUNET_HashCode *hash)
104{
105 GNUNET_assert((room) && (hash));
106
107 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
108 room->messages, hash
109 );
110
111 return (entry? entry->sender : NULL);
112}
113
114static struct GNUNET_MESSENGER_Contact*
115handle_join_message (struct GNUNET_MESSENGER_Room *room,
116 struct GNUNET_MESSENGER_Contact *sender,
117 const struct GNUNET_MESSENGER_Message *message,
118 const struct GNUNET_HashCode *hash)
119{
120 if (!sender)
121 {
122 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
123 struct GNUNET_HashCode context;
124
125 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
126
127 sender = get_store_contact(store, &context, &(message->body.join.key));
128 }
129
130 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
131 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
132 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
133 increase_contact_rc(sender);
134
135 return sender;
136}
137
138static void
139handle_leave_message (struct GNUNET_MESSENGER_Room *room,
140 struct GNUNET_MESSENGER_Contact *sender,
141 const struct GNUNET_MESSENGER_Message *message,
142 const struct GNUNET_HashCode *hash)
143{
144 if ((!sender) ||
145 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
146 return;
147
148 struct GNUNET_HashCode context;
149 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
150
151 if (GNUNET_YES == decrease_contact_rc(sender))
152 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
153}
154
155static void
156handle_name_message (struct GNUNET_MESSENGER_Room *room,
157 struct GNUNET_MESSENGER_Contact *sender,
158 const struct GNUNET_MESSENGER_Message *message,
159 const struct GNUNET_HashCode *hash)
160{
161 if (!sender)
162 return;
163
164 set_contact_name (sender, message->body.name.name);
165}
166
167static void
168handle_key_message (struct GNUNET_MESSENGER_Room *room,
169 struct GNUNET_MESSENGER_Contact *sender,
170 const struct GNUNET_MESSENGER_Message *message,
171 const struct GNUNET_HashCode *hash)
172{
173 if (!sender)
174 return;
175
176 struct GNUNET_HashCode context;
177 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
178
179 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
180
181 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
182}
183
184static void
185handle_id_message (struct GNUNET_MESSENGER_Room *room,
186 struct GNUNET_MESSENGER_Contact *sender,
187 const struct GNUNET_MESSENGER_Message *message,
188 const struct GNUNET_HashCode *hash)
189{
190 if ((!sender) ||
191 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
192 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
193 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
194 return;
195
196 struct GNUNET_HashCode context, next_context;
197 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
198 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
199
200 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
201
202 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
203}
204
205static void
206handle_miss_message (struct GNUNET_MESSENGER_Room *room,
207 struct GNUNET_MESSENGER_Contact *sender,
208 const struct GNUNET_MESSENGER_Message *message,
209 const struct GNUNET_HashCode *hash)
210{
211 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
212 {
213 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
214
215 if (match)
216 remove_from_list_tunnels (&(room->entries), match);
217 }
218}
219
220static void
221handle_delete_message (struct GNUNET_MESSENGER_Room *room,
222 struct GNUNET_MESSENGER_Contact *sender,
223 const struct GNUNET_MESSENGER_Message *message,
224 const struct GNUNET_HashCode *hash)
225{
226 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
227 room->messages, &(message->body.deletion.hash)
228 );
229
230 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
231 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.deletion.hash), entry)))
232 {
233 destroy_message (entry->message);
234 GNUNET_free(entry);
235 }
236}
237
238struct GNUNET_MESSENGER_Contact*
239handle_room_message (struct GNUNET_MESSENGER_Room *room,
240 struct GNUNET_MESSENGER_Contact *sender,
241 const struct GNUNET_MESSENGER_Message *message,
242 const struct GNUNET_HashCode *hash)
243{
244 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
245 return sender;
246
247 switch (message->header.kind)
248 {
249 case GNUNET_MESSENGER_KIND_JOIN:
250 sender = handle_join_message (room, sender, message, hash);
251 break;
252 case GNUNET_MESSENGER_KIND_LEAVE:
253 handle_leave_message (room, sender, message, hash);
254 break;
255 case GNUNET_MESSENGER_KIND_NAME:
256 handle_name_message (room, sender, message, hash);
257 break;
258 case GNUNET_MESSENGER_KIND_KEY:
259 handle_key_message (room, sender, message, hash);
260 break;
261 case GNUNET_MESSENGER_KIND_ID:
262 handle_id_message (room, sender, message, hash);
263 break;
264 case GNUNET_MESSENGER_KIND_MISS:
265 handle_miss_message (room, sender, message, hash);
266 break;
267 case GNUNET_MESSENGER_KIND_DELETE:
268 handle_delete_message (room, sender, message, hash);
269 break;
270 default:
271 break;
272 }
273
274 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
275
276 if (!entry)
277 return sender;
278
279 entry->sender = sender;
280 entry->message = copy_message (message);
281
282 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
283 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
284 {
285 destroy_message (entry->message);
286 GNUNET_free(entry);
287 }
288
289 return sender;
290}
291
292struct GNUNET_MESSENGER_MemberCall
293{
294 struct GNUNET_MESSENGER_Room *room;
295 GNUNET_MESSENGER_MemberCallback callback;
296 void *cls;
297};
298
299static int
300iterate_local_members (void* cls,
301 const struct GNUNET_ShortHashCode *key,
302 void *value)
303{
304 struct GNUNET_MESSENGER_MemberCall *call = cls;
305 struct GNUNET_MESSENGER_Contact *contact = value;
306
307 return call->callback(call->cls, call->room, contact);
308}
309
310int
311iterate_room_members (struct GNUNET_MESSENGER_Room *room,
312 GNUNET_MESSENGER_MemberCallback callback,
313 void* cls)
314{
315 GNUNET_assert(room);
316
317 if (!callback)
318 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
319
320 struct GNUNET_MESSENGER_MemberCall call;
321
322 call.room = room;
323 call.callback = callback;
324 call.cls = cls;
325
326 GNUNET_assert(callback);
327
328 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
329}
330
331struct GNUNET_MESSENGER_MemberFind
332{
333 const struct GNUNET_MESSENGER_Contact *contact;
334 int result;
335};
336
337static int
338iterate_find_member (void* cls,
339 const struct GNUNET_ShortHashCode *key,
340 void *value)
341{
342 struct GNUNET_MESSENGER_MemberFind *find = cls;
343 struct GNUNET_MESSENGER_Contact *contact = value;
344
345 if (contact == find->contact)
346 {
347 find->result = GNUNET_YES;
348 return GNUNET_NO;
349 }
350
351 return GNUNET_YES;
352}
353
354int
355find_room_member (const struct GNUNET_MESSENGER_Room *room,
356 const struct GNUNET_MESSENGER_Contact *contact)
357{
358 GNUNET_assert(room);
359
360 struct GNUNET_MESSENGER_MemberFind find;
361
362 find.contact = contact;
363 find.result = GNUNET_NO;
364
365 GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_find_member, &find);
366
367 return find.result;
368}
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h
deleted file mode 100644
index 320312f0c..000000000
--- a/src/messenger/messenger_api_room.h
+++ /dev/null
@@ -1,147 +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,
68 const struct GNUNET_HashCode *key);
69
70/**
71 * Destroys a room and frees its memory fully from the client API.
72 *
73 * @param[in/out] room Room
74 */
75void
76destroy_room (struct GNUNET_MESSENGER_Room *room);
77
78/**
79 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching
80 * message is found, NULL gets returned.
81 *
82 * @param[in] room Room
83 * @param[in] hash Hash of message
84 * @return Message or NULL
85 */
86const struct GNUNET_MESSENGER_Message*
87get_room_message (const struct GNUNET_MESSENGER_Room *room,
88 const struct GNUNET_HashCode *hash);
89
90/**
91 * Returns a messages sender locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no
92 * matching message is found, NULL gets returned.
93 *
94 * @param[in] room Room
95 * @param[in] hash Hash of message
96 * @return Contact of sender or NULL
97 */
98struct GNUNET_MESSENGER_Contact*
99get_room_sender (const struct GNUNET_MESSENGER_Room *room,
100 const struct GNUNET_HashCode *hash);
101
102/**
103 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
104 * members and its information. The function also stores the message in map locally for access afterwards.
105 *
106 * The contact of the message's sender could be updated or even created. It may not be freed or destroyed though!
107 * (The contact may still be in use for old messages...)
108 *
109 * @param[in/out] room Room
110 * @param[in/out] sender Contact of sender
111 * @param[in] message Message
112 * @param[in] hash Hash of message
113 * @return Contact of sender
114 */
115struct GNUNET_MESSENGER_Contact*
116handle_room_message (struct GNUNET_MESSENGER_Room *room,
117 struct GNUNET_MESSENGER_Contact *sender,
118 const struct GNUNET_MESSENGER_Message *message,
119 const struct GNUNET_HashCode *hash);
120
121/**
122 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
123 * <i>callback</i> with a custom closure.
124 *
125 * @param[in/out] room Room
126 * @param[in] callback Function called for each member
127 * @param[in/out] cls Closure
128 * @return Amount of members iterated
129 */
130int
131iterate_room_members (struct GNUNET_MESSENGER_Room *room,
132 GNUNET_MESSENGER_MemberCallback callback,
133 void* cls);
134
135/**
136 * Checks through all members of a given <i>room</i> if a specific <i>contact</i> is found and
137 * returns a result depending on that.
138 *
139 * @param[in] room Room
140 * @param[in] contact
141 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
142 */
143int
144find_room_member (const struct GNUNET_MESSENGER_Room *room,
145 const struct GNUNET_MESSENGER_Contact *contact);
146
147#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 52b4e934a..000000000
--- a/src/messenger/messenger_api_util.c
+++ /dev/null
@@ -1,102 +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,
49 const struct GNUNET_CONTAINER_MultiShortmap *members)
50{
51 GNUNET_assert(id);
52
53 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0);
54
55 do
56 {
57 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, id, sizeof(struct GNUNET_ShortHashCode));
58
59 if ((members) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (members, id)))
60 counter--;
61 else
62 break;
63 }
64 while (counter > 0);
65
66 if (counter)
67 return GNUNET_YES;
68
69 return GNUNET_NO;
70}
71
72const struct GNUNET_IDENTITY_PublicKey*
73get_anonymous_public_key ()
74{
75 static struct GNUNET_IDENTITY_PublicKey public_key;
76 static struct GNUNET_IDENTITY_Ego* ego = NULL;
77
78 if (!ego)
79 {
80 ego = GNUNET_IDENTITY_ego_get_anonymous();
81 GNUNET_IDENTITY_ego_get_public_key(ego, &public_key);
82 }
83
84 return &public_key;
85}
86
87void
88convert_messenger_key_to_port(const struct GNUNET_HashCode *key,
89 struct GNUNET_HashCode *port)
90{
91 static uint32_t version_value = 0;
92 static struct GNUNET_HashCode version;
93
94 if (!version_value) {
95 version_value = (uint32_t) (GNUNET_MESSENGER_VERSION);
96 version_value = ((version_value >> 16) & 0xFFFF);
97 version_value = GNUNET_htole32(version_value);
98 GNUNET_CRYPTO_hash(&version_value, sizeof(version_value), &version);
99 }
100
101 GNUNET_CRYPTO_hash_sum(key, &version, port);
102}
diff --git a/src/messenger/messenger_api_util.h b/src/messenger/messenger_api_util.h
deleted file mode 100644
index af64790b6..000000000
--- a/src/messenger/messenger_api_util.h
+++ /dev/null
@@ -1,80 +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,
55 const struct GNUNET_CONTAINER_MultiShortmap *members);
56
57/**
58 * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() without
59 * recalculating it every time.
60 *
61 * @return anonymous public key
62 */
63const struct GNUNET_IDENTITY_PublicKey*
64get_anonymous_public_key ();
65
66/**
67 * Converts a Messenger service key of a room to the specific port which
68 * gets used for the CADET channels.
69 *
70 * The port includes upper bits of the #GNUNET_MESSENGER_VERSION to
71 * reduce the chance of incompatible connections.
72 *
73 * @param[in] key Messenger service room key
74 * @param[out] port CADET service port
75 */
76void
77convert_messenger_key_to_port(const struct GNUNET_HashCode *key,
78 struct GNUNET_HashCode *port);
79
80#endif //GNUNET_SERVICE_MESSENGER_UTIL_H
diff --git a/src/messenger/plugin_gnsrecord_messenger.c b/src/messenger/plugin_gnsrecord_messenger.c
deleted file mode 100644
index 2219f0bde..000000000
--- a/src/messenger/plugin_gnsrecord_messenger.c
+++ /dev/null
@@ -1,243 +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/plugin_gnsrecord_messenger.c
23 * @brief Plugin to provide the API for useful GNS records to improve
24 * the usability of the messenger service.
25 */
26
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_messenger_service.h"
31#include "gnunet_gnsrecord_plugin.h"
32
33
34/**
35 * Convert the 'value' of a record to a string.
36 *
37 * @param cls closure, unused
38 * @param type type of the record
39 * @param data value in binary encoding
40 * @param data_size number of bytes in @a data
41 * @return NULL on error, otherwise human-readable representation of the value
42 */
43static char *
44messenger_value_to_string (void *cls,
45 uint32_t type,
46 const void *data,
47 size_t data_size)
48{
49 (void) cls;
50 switch (type)
51 {
52 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY:
53 {
54 if (data_size != sizeof(struct GNUNET_MESSENGER_RoomEntryRecord))
55 {
56 GNUNET_break_op (0);
57 return NULL;
58 }
59
60 const struct GNUNET_MESSENGER_RoomEntryRecord *record = data;
61
62 char *door = GNUNET_CRYPTO_eddsa_public_key_to_string (&(record->door.public_key));
63 char *key = GNUNET_STRINGS_data_to_string_alloc (&(record->key), sizeof(struct GNUNET_HashCode));
64
65 char *ret;
66 GNUNET_asprintf (&ret, "%s-%s", door, key);
67 GNUNET_free (key);
68 GNUNET_free (door);
69 return ret;
70 }
71
72 default:
73 return NULL;
74 }
75}
76
77
78/**
79 * Convert human-readable version of a 'value' of a record to the binary
80 * representation.
81 *
82 * @param cls closure, unused
83 * @param type type of the record
84 * @param s human-readable string
85 * @param data set to value in binary encoding (will be allocated)
86 * @param data_size set to number of bytes in @a data
87 * @return #GNUNET_OK on success
88 */
89static int
90messenger_string_to_value (void *cls,
91 uint32_t type,
92 const char *s,
93 void **data,
94 size_t *data_size)
95{
96 (void) cls;
97 if (NULL == s)
98 {
99 GNUNET_break (0);
100 return GNUNET_SYSERR;
101 }
102
103 switch (type)
104 {
105 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY:
106 {
107 char key [103];
108 const char *dash;
109 struct GNUNET_PeerIdentity door;
110
111 if ((NULL == (dash = strchr (s, '-'))) ||
112 (1 != sscanf (s, "%103s-", key)) ||
113 (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
114 strlen (dash + 1),
115 &(door.public_key))))
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 _ ("Unable to parse MESSENGER_ROOM_ENTRY record `%s'\n"),
119 s);
120 return GNUNET_SYSERR;
121 }
122
123 struct GNUNET_MESSENGER_RoomEntryRecord *record = GNUNET_new (
124 struct GNUNET_MESSENGER_RoomEntryRecord
125 );
126
127 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (key,
128 strlen (key),
129 &(record->key),
130 sizeof(struct GNUNET_HashCode)))
131 {
132 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
133 _ ("Unable to parse MESSENGER_ROOM_ENTRY record `%s'\n"),
134 s);
135 GNUNET_free (record);
136 return GNUNET_SYSERR;
137 }
138
139 record->door = door;
140 *data = record;
141 *data_size = sizeof(struct GNUNET_MESSENGER_RoomEntryRecord);
142 return GNUNET_OK;
143 }
144
145 default:
146 return GNUNET_SYSERR;
147 }
148}
149
150
151/**
152 * Mapping of record type numbers to human-readable
153 * record type names.
154 */
155static struct
156{
157 const char *name;
158 uint32_t number;
159} name_map[] = {
160 { "MESSENGER_ROOM_ENTRY", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY },
161 { NULL, UINT32_MAX }
162};
163
164
165/**
166 * Convert a type name (e.g. "AAAA") to the corresponding number.
167 *
168 * @param cls closure, unused
169 * @param gns_typename name to convert
170 * @return corresponding number, UINT32_MAX on error
171 */
172static uint32_t
173messenger_typename_to_number (void *cls,
174 const char *gns_typename)
175{
176 unsigned int i;
177
178 (void) cls;
179 i = 0;
180 while ((name_map[i].name != NULL) &&
181 (0 != strcasecmp (gns_typename, name_map[i].name)))
182 i++;
183 return name_map[i].number;
184}
185
186
187/**
188 * Convert a type number to the corresponding type string (e.g. 1 to "A")
189 *
190 * @param cls closure, unused
191 * @param type number of a type to convert
192 * @return corresponding typestring, NULL on error
193 */
194static const char *
195messenger_number_to_typename (void *cls,
196 uint32_t type)
197{
198 unsigned int i;
199
200 (void) cls;
201 i = 0;
202 while ((name_map[i].name != NULL) &&
203 (type != name_map[i].number))
204 i++;
205 return name_map[i].name;
206}
207
208
209/**
210 * Entry point for the plugin.
211 *
212 * @param cls NULL
213 * @return the exported block API
214 */
215void *
216libgnunet_plugin_gnsrecord_messenger_init (void *cls)
217{
218 struct GNUNET_GNSRECORD_PluginFunctions *api;
219
220 (void) cls;
221 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
222 api->value_to_string = &messenger_value_to_string;
223 api->string_to_value = &messenger_string_to_value;
224 api->typename_to_number = &messenger_typename_to_number;
225 api->number_to_typename = &messenger_number_to_typename;
226 return api;
227}
228
229
230/**
231 * Exit point from the plugin.
232 *
233 * @param cls the return value from #libgnunet_plugin_block_test_init
234 * @return NULL
235 */
236void *
237libgnunet_plugin_gnsrecord_messenger_done (void *cls)
238{
239 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
240
241 GNUNET_free (api);
242 return NULL;
243}
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
deleted file mode 100644
index 5784dfd82..000000000
--- a/src/messenger/test_messenger.c
+++ /dev/null
@@ -1,181 +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,
104 struct GNUNET_MESSENGER_Handle *handle)
105{
106 if (op_task)
107 {
108 GNUNET_SCHEDULER_cancel (op_task);
109 op_task = NULL;
110 }
111
112 const char *name = GNUNET_MESSENGER_get_name (handle);
113
114 if (0 != strcmp (name, TESTER_NAME))
115 {
116 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name");
117 return;
118 }
119
120 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
121
122 if (((!identity_counter) && (key)) || ((identity_counter) && (!key)))
123 {
124 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key");
125 return;
126 }
127
128 if (identity_counter)
129 {
130 GNUNET_MESSENGER_disconnect (handle);
131
132 op_task = NULL;
133 messenger = NULL;
134
135 if (die_task)
136 GNUNET_SCHEDULER_cancel (die_task);
137
138 die_task = GNUNET_SCHEDULER_add_now (&end, NULL);
139 return;
140 }
141
142 GNUNET_MESSENGER_update (messenger);
143 identity_counter++;
144}
145
146/**
147 * Main function for testcase.
148 *
149 * @param cls Closure
150 * @param cfg Configuration
151 * @param peer Peer for testing
152 */
153static void
154run (void *cls,
155 const struct GNUNET_CONFIGURATION_Handle *cfg,
156 struct GNUNET_TESTING_Peer *peer)
157{
158 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
159
160 identity_counter = 0;
161
162 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
163 messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, &on_identity, NULL, NULL, NULL);
164}
165
166/**
167 * The main function.
168 *
169 * @param argc number of arguments from the command line
170 * @param argv command line arguments
171 * @return 0 ok, 1 on error
172 */
173int
174main (int argc,
175 char **argv)
176{
177 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
178 return 1;
179
180 return status;
181}
diff --git a/src/messenger/test_messenger_adapt.c b/src/messenger/test_messenger_adapt.c
deleted file mode 100644
index 3230af6b7..000000000
--- a/src/messenger/test_messenger_adapt.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 5, 1, 2, 3, 6, 7, 8, 4 };
40 unsigned int stages [] = { 0x21, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x21 };
41
42 struct test_configuration cfg;
43 cfg.count = 8;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_adapt", &cfg);
48}
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c
deleted file mode 100644
index 8cb339f0e..000000000
--- a/src/messenger/test_messenger_anonymous.c
+++ /dev/null
@@ -1,173 +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,
100 struct GNUNET_MESSENGER_Handle *handle)
101{
102 if (op_task)
103 {
104 GNUNET_SCHEDULER_cancel (op_task);
105 op_task = NULL;
106 }
107
108 const char *name = GNUNET_MESSENGER_get_name (handle);
109
110 if (NULL != name)
111 {
112 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name-anonymous");
113 return;
114 }
115
116 if (GNUNET_SYSERR != GNUNET_MESSENGER_update (handle))
117 {
118 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail");
119 return;
120 }
121
122 const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key (handle);
123
124 if (key)
125 {
126 op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key-anonymous");
127 return;
128 }
129
130 GNUNET_MESSENGER_disconnect (handle);
131
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}
139
140/**
141 * Main function for testcase.
142 *
143 * @param cls Closure
144 * @param cfg Configuration
145 * @param peer Peer for testing
146 */
147static void
148run (void *cls,
149 const struct GNUNET_CONFIGURATION_Handle *cfg,
150 struct GNUNET_TESTING_Peer *peer)
151{
152 die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
153
154 op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, "connect");
155 messenger = GNUNET_MESSENGER_connect (cfg, NULL, &on_identity, NULL, NULL, NULL);
156}
157
158/**
159 * The main function.
160 *
161 * @param argc number of arguments from the command line
162 * @param argv command line arguments
163 * @return 0 ok, 1 on error
164 */
165int
166main (int argc,
167 char **argv)
168{
169 if (0 != GNUNET_TESTING_peer_run ("test-messenger", "test_messenger_api.conf", &run, NULL))
170 return 1;
171
172 return status;
173}
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 8404195dc..000000000
--- a/src/messenger/test_messenger_async_client.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 0, 1 };
40 unsigned int stages [] = { 0x10, 0x20 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_async_client", &cfg);
48}
diff --git a/src/messenger/test_messenger_async_p2p.c b/src/messenger/test_messenger_async_p2p.c
deleted file mode 100644
index 25746f7ff..000000000
--- a/src/messenger/test_messenger_async_p2p.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 2, 1 };
40 unsigned int stages [] = { 0x30, 0x30 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_async_p2p", &cfg);
48}
diff --git a/src/messenger/test_messenger_growth.c b/src/messenger/test_messenger_growth.c
deleted file mode 100644
index c3f243cbf..000000000
--- a/src/messenger/test_messenger_growth.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
40 unsigned int stages [] = { 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
41
42 struct test_configuration cfg;
43 cfg.count = 8;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_growth", &cfg);
48}
diff --git a/src/messenger/test_messenger_ring.c b/src/messenger/test_messenger_ring.c
deleted file mode 100644
index 777d79eb8..000000000
--- a/src/messenger/test_messenger_ring.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 8, 1, 2, 3, 4, 5, 6, 7 };
40 unsigned int stages [] = { 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
41
42 struct test_configuration cfg;
43 cfg.count = 8;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_ring", &cfg);
48}
diff --git a/src/messenger/test_messenger_server.c b/src/messenger/test_messenger_server.c
deleted file mode 100644
index 61e96e879..000000000
--- a/src/messenger/test_messenger_server.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
40 unsigned int stages [] = { 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
41
42 struct test_configuration cfg;
43 cfg.count = 8;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_server", &cfg);
48}
diff --git a/src/messenger/test_messenger_sync_client.c b/src/messenger/test_messenger_sync_client.c
deleted file mode 100644
index 02d90a61d..000000000
--- a/src/messenger/test_messenger_sync_client.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 0, 1 };
40 unsigned int stages [] = { 0x01, 0x20 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_sync_client", &cfg);
48}
diff --git a/src/messenger/test_messenger_sync_p2p.c b/src/messenger/test_messenger_sync_p2p.c
deleted file mode 100644
index 0a900a39e..000000000
--- a/src/messenger/test_messenger_sync_p2p.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 2, 1 };
40 unsigned int stages [] = { 0x21, 0x21 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_sync_p2p", &cfg);
48}
diff --git a/src/messenger/test_messenger_worst_client.c b/src/messenger/test_messenger_worst_client.c
deleted file mode 100644
index a3d5aafec..000000000
--- a/src/messenger/test_messenger_worst_client.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 0, 1 };
40 unsigned int stages [] = { 0x10, 0x02 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_worst_client", &cfg);
48}
diff --git a/src/messenger/test_messenger_worst_p2p.c b/src/messenger/test_messenger_worst_p2p.c
deleted file mode 100644
index 89e54cfbd..000000000
--- a/src/messenger/test_messenger_worst_p2p.c
+++ /dev/null
@@ -1,48 +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,
37 char **argv)
38{
39 unsigned int doors [] = { 2, 1 };
40 unsigned int stages [] = { 0x12, 0x12 };
41
42 struct test_configuration cfg;
43 cfg.count = 2;
44 cfg.doors = doors;
45 cfg.stages = stages;
46
47 return GNUNET_run_messenger_setup ("test_messenger_worst_p2p", &cfg);
48}
diff --git a/src/messenger/testing_messenger_barrier.c b/src/messenger/testing_messenger_barrier.c
deleted file mode 100644
index a95ea9ef1..000000000
--- a/src/messenger/testing_messenger_barrier.c
+++ /dev/null
@@ -1,172 +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,
65 int status);
66
67static void
68cancel_barrier (void *cls)
69{
70 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR);
71}
72
73static void
74complete_barrier (void *cls)
75{
76 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK);
77}
78
79void
80GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier)
81{
82 if ((!barrier) || (barrier->task))
83 return;
84
85 barrier->task = GNUNET_SCHEDULER_add_now(cancel_barrier, barrier);
86}
87
88struct GNUNET_BarrierWaitHandle
89{
90 GNUNET_BarrierWaitStatusCallback cb;
91 void *cls;
92
93 struct GNUNET_BarrierWaitHandle *prev;
94 struct GNUNET_BarrierWaitHandle *next;
95
96 struct GNUNET_BarrierHandle *barrier;
97};
98
99static void
100exit_status (struct GNUNET_BarrierHandle *barrier,
101 int status)
102{
103 struct GNUNET_BarrierWaitHandle *waiting = barrier->head;
104 while (waiting)
105 {
106 struct GNUNET_BarrierWaitHandle *current = waiting;
107
108 if (current->cb)
109 current->cb(current->cls, current, status);
110
111 waiting = waiting->next;
112
113 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, current);
114 GNUNET_free(current);
115 }
116
117 if (barrier->cb)
118 barrier->cb(barrier->cls, barrier, status);
119
120 GNUNET_free(barrier);
121}
122
123struct GNUNET_BarrierWaitHandle*
124GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
125 GNUNET_BarrierWaitStatusCallback cb,
126 void *cb_cls)
127{
128 if ((!barrier) || (0 == barrier->requirement))
129 return NULL;
130
131 struct GNUNET_BarrierWaitHandle *waiting = GNUNET_new(struct GNUNET_BarrierWaitHandle);
132
133 if (!waiting)
134 return NULL;
135
136 waiting->cb = cb;
137 waiting->cls = cb_cls;
138 waiting->prev = NULL;
139 waiting->next = NULL;
140 waiting->barrier = barrier;
141
142 GNUNET_CONTAINER_DLL_insert_tail(barrier->head, barrier->tail, waiting);
143 barrier->requirement--;
144
145 if ((barrier->requirement == 0) && (!barrier->task))
146 barrier->task = GNUNET_SCHEDULER_add_now(complete_barrier, barrier);
147
148 return waiting;
149}
150
151void
152GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting)
153{
154 if (!waiting)
155 return;
156
157 struct GNUNET_BarrierHandle *barrier = waiting->barrier;
158
159 if (!barrier)
160 return;
161
162 if ((barrier->requirement == 0) && (barrier->task))
163 {
164 GNUNET_SCHEDULER_cancel(barrier->task);
165 barrier->task = NULL;
166 }
167
168 barrier->requirement++;
169 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, waiting);
170
171 GNUNET_free(waiting);
172}
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 3cde8c9bb..000000000
--- a/src/messenger/testing_messenger_setup.c
+++ /dev/null
@@ -1,547 +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,
208 struct GNUNET_BarrierWaitHandle *waiting,
209 int status)
210{
211 struct test_peer *peer = cls;
212
213 GNUNET_assert(peer != NULL);
214
215 if (peer->wait == waiting)
216 peer->wait = NULL;
217}
218
219static void
220barrier_wait_cb (void *cls,
221 struct GNUNET_BarrierWaitHandle *waiting,
222 int status)
223{
224 struct test_peer *peer = cls;
225
226 GNUNET_assert(peer != NULL);
227
228 if (peer->wait == waiting)
229 peer->wait = NULL;
230
231 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x02))
232 {
233 unsigned int door = peer->props->cfg->doors[peer->num - 1];
234
235 if (door == 0)
236 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
237 else
238 door = door - 1;
239
240 struct GNUNET_HashCode hash;
241 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
242
243 struct GNUNET_MESSENGER_Room *room;
244 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
245
246 if (peer->room)
247 GNUNET_assert(room == peer->room);
248 else
249 GNUNET_assert(room != NULL);
250
251 peer->room = room;
252 }
253}
254
255/**
256 * Function called whenever a message is received or sent.
257 *
258 * @param cls Closure
259 * @param room Room
260 * @param sender Sender
261 * @param message Message
262 * @param hash Hash of message
263 * @param flags Flags of message
264 */
265static void
266on_message (void *cls,
267 struct GNUNET_MESSENGER_Room *room,
268 const struct GNUNET_MESSENGER_Contact *sender,
269 const struct GNUNET_MESSENGER_Message *message,
270 const struct GNUNET_HashCode *hash,
271 enum GNUNET_MESSENGER_MessageFlags flags)
272{
273 struct test_peer *peer = cls;
274
275 GNUNET_assert(peer != NULL);
276
277 fprintf (stderr, "Peer: %s; [%s] Message: %s (%s)\n",
278 GNUNET_i2s(&(peer->peer_id)),
279 GNUNET_sh2s(&(message->header.sender_id)),
280 GNUNET_MESSENGER_name_of_kind(message->header.kind),
281 GNUNET_h2s(hash));
282
283 if (GNUNET_MESSENGER_KIND_PEER == message->header.kind)
284 peer->peer_messages++;
285
286 if (peer->props->num_hosts == peer->peer_messages)
287 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier2_wait_cb, peer);
288 else if (peer->props->num_hosts < peer->peer_messages)
289 {
290 if (peer->wait)
291 GNUNET_cancel_wait_barrier(peer->wait);
292
293 peer->wait = NULL;
294
295 if (peer->op_task)
296 GNUNET_SCHEDULER_cancel(peer->op_task);
297
298 peer->message = "peer";
299 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
300 }
301}
302
303static void
304second_stage (void *cls)
305{
306 struct test_peer *peer = cls;
307
308 GNUNET_assert(peer != NULL);
309
310 peer->op_task = NULL;
311
312 struct GNUNET_HashCode hash;
313 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
314
315 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x10))
316 {
317 struct GNUNET_MESSENGER_Room *room;
318 room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
319
320 if (peer->room)
321 GNUNET_assert(room == peer->room);
322 else
323 GNUNET_assert(room != NULL);
324
325 peer->room = room;
326 }
327
328 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x20))
329 {
330 unsigned int door = peer->props->cfg->doors[peer->num - 1];
331
332 if (door == 0)
333 door = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, peer->props->cfg->count);
334 else
335 door = door - 1;
336
337 struct GNUNET_MESSENGER_Room *room;
338 room = GNUNET_MESSENGER_enter_room(peer->handle, &(peer->props->peers[door].peer_id), &hash);
339
340 if (peer->room)
341 GNUNET_assert(room == peer->room);
342 else
343 GNUNET_assert(room != NULL);
344
345 peer->room = room;
346 }
347}
348
349static void
350on_peer (void *cb_cls,
351 struct GNUNET_TESTBED_Operation *op,
352 const struct GNUNET_TESTBED_PeerInformation *pinfo,
353 const char *emsg)
354{
355 struct test_peer *peer = cb_cls;
356
357 GNUNET_assert(peer != NULL);
358
359 if (emsg)
360 {
361 peer->message = GNUNET_strdup(emsg);
362 peer->op_task = GNUNET_SCHEDULER_add_now (&end_error_cb, peer);
363 return;
364 }
365
366 if (!pinfo)
367 {
368 peer->message = "info";
369 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
370 return;
371 }
372
373 if (pinfo->pit != GNUNET_TESTBED_PIT_CONFIGURATION)
374 {
375 peer->message = "config";
376 peer->op_task = GNUNET_SCHEDULER_add_now (&end_operation_cb, peer);
377 return;
378 }
379
380 peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, NULL, &on_message, peer);
381
382 GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_get_peer_identity(
383 pinfo->result.cfg, &(peer->peer_id)
384 ));
385
386 if (0 != (peer->props->cfg->stages[peer->num - 1] & 0x01))
387 {
388 struct GNUNET_HashCode hash;
389 GNUNET_CRYPTO_hash (TEST_ROOM, sizeof(TEST_ROOM), &hash);
390
391 peer->room = GNUNET_MESSENGER_open_room (peer->handle, &hash);
392
393 GNUNET_assert(peer->room != NULL);
394 }
395 else
396 peer->room = NULL;
397
398 peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier_wait_cb, peer);
399}
400
401/**
402 * Main function for a peer of the testcase.
403 *
404 * @param cls Closure
405 * @param event Information about the event
406 */
407static void
408run (void *cls,
409 const struct GNUNET_TESTBED_EventInformation *event)
410{
411 struct test_properties *properties = cls;
412
413 GNUNET_assert(properties != NULL);
414
415 if (GNUNET_TESTBED_ET_PEER_START != event->type)
416 {
417 fprintf (stderr, "Testcase failed (operation: 'start').\n");
418
419 GNUNET_SCHEDULER_shutdown ();
420 return;
421 }
422
423 struct test_peer *peer = &(properties->peers[properties->num_peer++]);
424
425 peer->props = properties;
426 peer->num = properties->num_peer;
427
428 peer->peer = event->details.peer_start.peer;
429 peer->op = GNUNET_TESTBED_peer_get_information (peer->peer, GNUNET_TESTBED_PIT_CONFIGURATION, on_peer, peer);
430}
431
432static void
433barrier2_cb (void *cls,
434 struct GNUNET_BarrierHandle *barrier,
435 int status)
436{
437 struct test_properties *properties = cls;
438
439 GNUNET_assert(properties != NULL);
440
441 if (properties->barrier == barrier)
442 properties->barrier = NULL;
443
444 if (GNUNET_SYSERR == status)
445 {
446 fprintf (stderr, "Testcase failed (operation: 'barrier2').\n");
447
448 GNUNET_SCHEDULER_shutdown ();
449 return;
450 }
451 else if (GNUNET_OK == status)
452 {
453 if (properties->die_task)
454 GNUNET_SCHEDULER_cancel(properties->die_task);
455
456 properties->die_task = GNUNET_SCHEDULER_add_delayed (
457 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count),
458 &end_cb, properties
459 );
460 }
461}
462
463static void
464barrier_cb (void *cls,
465 struct GNUNET_BarrierHandle *barrier,
466 int status)
467{
468 struct test_properties *properties = cls;
469
470 GNUNET_assert(properties != NULL);
471
472 if (properties->barrier == barrier)
473 properties->barrier = NULL;
474 else if (!properties->barrier)
475 return;
476
477 if (properties->num_peer != properties->cfg->count)
478 {
479 fprintf (stderr, "Testcase failed (operation: 'process').\n");
480
481 GNUNET_SCHEDULER_shutdown ();
482 return;
483 }
484
485 if (GNUNET_SYSERR == status)
486 {
487 fprintf (stderr, "Testcase failed (operation: 'barrier').\n");
488
489 GNUNET_SCHEDULER_shutdown ();
490 return;
491 }
492 else if (GNUNET_OK == status)
493 {
494 properties->barrier = GNUNET_init_barrier (properties->num_peer, &barrier2_cb, properties);
495
496 for (unsigned int i = 0; i < properties->num_peer; i++)
497 properties->peers[i].op_task = GNUNET_SCHEDULER_add_now (&second_stage, &(properties->peers[i]));
498 }
499}
500
501static void
502init (void *cls,
503 struct GNUNET_TESTBED_RunHandle *h,
504 unsigned int num_peers,
505 struct GNUNET_TESTBED_Peer **peers,
506 unsigned int links_succeeded,
507 unsigned int links_failed)
508{
509 struct test_properties *properties = cls;
510
511 GNUNET_assert(properties != NULL);
512
513 properties->end_task = GNUNET_SCHEDULER_add_shutdown(&shutdown_cb, properties);
514 properties->die_task = GNUNET_SCHEDULER_add_delayed (
515 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, properties->cfg->count * 5),
516 &end_badly_cb, properties
517 );
518}
519
520int
521GNUNET_run_messenger_setup (const char* test_name,
522 const struct test_configuration *cfg)
523{
524 struct test_properties properties;
525 memset(&properties, 0, sizeof(properties));
526
527 properties.cfg = cfg;
528 properties.peers = GNUNET_new_array(cfg->count, struct test_peer);
529
530 for (unsigned int i = 0; i < cfg->count; i++)
531 if (0 != (cfg->stages[i] & 0x11))
532 properties.num_hosts++;
533
534 properties.status = 1;
535 properties.barrier = GNUNET_init_barrier (cfg->count, &barrier_cb, &properties);
536
537 if (GNUNET_OK != GNUNET_TESTBED_test_run (test_name, "test_messenger_api.conf",
538 cfg->count,
539 (1LL << GNUNET_TESTBED_ET_PEER_START),
540 &run, &properties,
541 &init, &properties))
542 return 1;
543
544 GNUNET_free(properties.peers);
545
546 return properties.status;
547}
diff --git a/src/messenger/testing_messenger_setup.h b/src/messenger/testing_messenger_setup.h
deleted file mode 100644
index e5ae0c151..000000000
--- a/src/messenger/testing_messenger_setup.h
+++ /dev/null
@@ -1,40 +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,
38 const struct test_configuration *cfg);
39
40#endif /* GNUNET_TESTING_MESSENGER_SETUP_H_ */