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.c476
-rw-r--r--src/messenger/gnunet-service-messenger.h133
-rw-r--r--src/messenger/gnunet-service-messenger_basement.c65
-rw-r--r--src/messenger/gnunet-service-messenger_basement.h70
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c482
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.h206
-rw-r--r--src/messenger/gnunet-service-messenger_handle.c712
-rw-r--r--src/messenger/gnunet-service-messenger_handle.h249
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.c105
-rw-r--r--src/messenger/gnunet-service-messenger_list_handles.h100
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.c156
-rw-r--r--src/messenger/gnunet-service-messenger_list_messages.h112
-rw-r--r--src/messenger/gnunet-service-messenger_member.c416
-rw-r--r--src/messenger/gnunet-service-messenger_member.h180
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.c766
-rw-r--r--src/messenger/gnunet-service-messenger_member_session.h291
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c269
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.h157
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.c154
-rw-r--r--src/messenger/gnunet-service-messenger_message_handle.h158
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.c242
-rw-r--r--src/messenger/gnunet-service-messenger_message_kind.h173
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.c186
-rw-r--r--src/messenger/gnunet-service-messenger_message_recv.h87
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.c77
-rw-r--r--src/messenger/gnunet-service-messenger_message_send.h97
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.c114
-rw-r--r--src/messenger/gnunet-service-messenger_message_state.h67
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.c581
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.h168
-rw-r--r--src/messenger/gnunet-service-messenger_operation.c221
-rw-r--r--src/messenger/gnunet-service-messenger_operation.h130
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.c237
-rw-r--r--src/messenger/gnunet-service-messenger_operation_store.h130
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1274
-rw-r--r--src/messenger/gnunet-service-messenger_room.h378
-rw-r--r--src/messenger/gnunet-service-messenger_service.c320
-rw-r--r--src/messenger/gnunet-service-messenger_service.h210
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.c403
-rw-r--r--src/messenger/gnunet-service-messenger_tunnel.h193
-rw-r--r--src/messenger/messenger.conf.in14
-rw-r--r--src/messenger/messenger_api.c801
-rw-r--r--src/messenger/messenger_api_contact.c111
-rw-r--r--src/messenger/messenger_api_contact.h116
-rw-r--r--src/messenger/messenger_api_contact_store.c194
-rw-r--r--src/messenger/messenger_api_contact_store.h126
-rw-r--r--src/messenger/messenger_api_ego.h38
-rw-r--r--src/messenger/messenger_api_handle.c208
-rw-r--r--src/messenger/messenger_api_handle.h178
-rw-r--r--src/messenger/messenger_api_list_tunnels.c193
-rw-r--r--src/messenger/messenger_api_list_tunnels.h136
-rw-r--r--src/messenger/messenger_api_message.c947
-rw-r--r--src/messenger/messenger_api_message.h250
-rw-r--r--src/messenger/messenger_api_room.c369
-rw-r--r--src/messenger/messenger_api_room.h146
-rw-r--r--src/messenger/messenger_api_util.c103
-rw-r--r--src/messenger/messenger_api_util.h78
-rw-r--r--src/messenger/plugin_gnsrecord_messenger.c298
-rw-r--r--src/messenger/test_messenger.c181
-rw-r--r--src/messenger/test_messenger_adapt.c49
-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.c49
-rw-r--r--src/messenger/test_messenger_async_p2p.c49
-rw-r--r--src/messenger/test_messenger_growth.c49
-rw-r--r--src/messenger/test_messenger_ring.c49
-rw-r--r--src/messenger/test_messenger_server.c49
-rw-r--r--src/messenger/test_messenger_sync_client.c49
-rw-r--r--src/messenger/test_messenger_sync_p2p.c49
-rw-r--r--src/messenger/test_messenger_worst_client.c49
-rw-r--r--src/messenger/test_messenger_worst_p2p.c49
-rw-r--r--src/messenger/testing_messenger_barrier.c173
-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, 17216 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 9444fa12d..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 "platform.h"
27#include <stdio.h>
28
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 f0bb853d7..000000000
--- a/src/messenger/gnunet-service-messenger.c
+++ /dev/null
@@ -1,476 +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 "platform.h"
27#include "gnunet-service-messenger.h"
28
29#include "gnunet-service-messenger_handle.h"
30#include "gnunet-service-messenger_message_kind.h"
31#include "gnunet-service-messenger_service.h"
32#include "messenger_api_message.h"
33
34struct GNUNET_MESSENGER_Client
35{
36 struct GNUNET_SERVICE_Client *client;
37 struct GNUNET_MESSENGER_SrvHandle *handle;
38};
39
40struct GNUNET_MESSENGER_Service *messenger;
41
42static int
43check_create (void *cls,
44 const struct GNUNET_MESSENGER_CreateMessage *msg)
45{
46 GNUNET_MQ_check_zero_termination (msg);
47 return GNUNET_OK;
48}
49
50static void
51handle_create (void *cls,
52 const struct GNUNET_MESSENGER_CreateMessage *msg)
53{
54 struct GNUNET_MESSENGER_Client *msg_client = cls;
55
56 const char *name = ((const char*) msg) + sizeof(*msg);
57
58 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
59
60 setup_srv_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
61
62 GNUNET_SERVICE_client_continue (msg_client->client);
63}
64
65static void
66handle_update (void *cls,
67 const struct GNUNET_MESSENGER_UpdateMessage *msg)
68{
69 struct GNUNET_MESSENGER_Client *msg_client = cls;
70
71 update_srv_handle (msg_client->handle);
72
73 GNUNET_SERVICE_client_continue (msg_client->client);
74}
75
76static void
77handle_destroy (void *cls,
78 const struct GNUNET_MESSENGER_DestroyMessage *msg)
79{
80 struct GNUNET_MESSENGER_Client *msg_client = cls;
81
82 GNUNET_SERVICE_client_drop (msg_client->client);
83}
84
85static int
86check_set_name (void *cls,
87 const struct GNUNET_MESSENGER_NameMessage *msg)
88{
89 GNUNET_MQ_check_zero_termination (msg);
90 return GNUNET_OK;
91}
92
93static void
94handle_set_name (void *cls,
95 const struct GNUNET_MESSENGER_NameMessage *msg)
96{
97 struct GNUNET_MESSENGER_Client *msg_client = cls;
98
99 const char *name = ((const char*) msg) + sizeof(*msg);
100
101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
102
103 set_srv_handle_name (msg_client->handle, name);
104
105 GNUNET_SERVICE_client_continue (msg_client->client);
106}
107
108static void
109handle_room_open (void *cls,
110 const struct GNUNET_MESSENGER_RoomMessage *msg)
111{
112 struct GNUNET_MESSENGER_Client *msg_client = cls;
113
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (
115 &(msg->key)));
116
117 if (GNUNET_YES == open_srv_handle_room (msg_client->handle, &(msg->key)))
118 {
119 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (
120 msg_client->handle, &(msg->key));
121
122 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening room with member id: %s\n",
123 GNUNET_sh2s (member_id));
124
125 struct GNUNET_MESSENGER_RoomMessage *response;
126 struct GNUNET_MQ_Envelope *env;
127
128 env = GNUNET_MQ_msg (response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
129 GNUNET_memcpy (&(response->key), &(msg->key), sizeof(msg->key));
130 GNUNET_MQ_send (msg_client->handle->mq, env);
131 }
132 else
133 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Opening room failed: %s\n",
134 GNUNET_h2s (&(msg->key)));
135
136 GNUNET_SERVICE_client_continue (msg_client->client);
137}
138
139static void
140handle_room_entry (void *cls,
141 const struct GNUNET_MESSENGER_RoomMessage *msg)
142{
143 struct GNUNET_MESSENGER_Client *msg_client = cls;
144
145 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (
146 &(msg->key)), GNUNET_i2s (&(msg->door)));
147
148 if (GNUNET_YES == entry_srv_handle_room (msg_client->handle, &(msg->door),
149 &(msg->key)))
150 {
151 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (
152 msg_client->handle, &(msg->key));
153
154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entering room with member id: %s\n",
155 GNUNET_sh2s (member_id));
156
157 struct GNUNET_MESSENGER_RoomMessage *response;
158 struct GNUNET_MQ_Envelope *env;
159
160 env = GNUNET_MQ_msg (response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
161 GNUNET_memcpy (&(response->door), &(msg->door), sizeof(msg->door));
162 GNUNET_memcpy (&(response->key), &(msg->key), sizeof(msg->key));
163 GNUNET_MQ_send (msg_client->handle->mq, env);
164 }
165 else
166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Entrance into room failed: %s, %s\n",
167 GNUNET_h2s (&(msg->key)),
168 GNUNET_i2s (&(msg->door)));
169
170 GNUNET_SERVICE_client_continue (msg_client->client);
171}
172
173static void
174handle_room_close (void *cls,
175 const struct GNUNET_MESSENGER_RoomMessage *msg)
176{
177 struct GNUNET_MESSENGER_Client *msg_client = cls;
178
179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closing room: %s\n", GNUNET_h2s (
180 &(msg->key)));
181
182 if (GNUNET_YES == close_srv_handle_room (msg_client->handle, &(msg->key)))
183 {
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closing room succeeded: %s\n",
185 GNUNET_h2s (&(msg->key)));
186
187 struct GNUNET_MESSENGER_RoomMessage *response;
188 struct GNUNET_MQ_Envelope *env;
189
190 env = GNUNET_MQ_msg (response, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
191 GNUNET_memcpy (&(response->key), &(msg->key), sizeof(msg->key));
192 GNUNET_MQ_send (msg_client->handle->mq, env);
193 }
194 else
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Closing room failed: %s\n",
196 GNUNET_h2s (&(msg->key)));
197
198 GNUNET_SERVICE_client_continue (msg_client->client);
199}
200
201static int
202check_send_message (void *cls,
203 const struct GNUNET_MESSENGER_SendMessage *msg)
204{
205 const uint16_t full_length = ntohs (msg->header.size);
206
207 if (full_length < sizeof(*msg))
208 return GNUNET_NO;
209
210 const enum GNUNET_MESSENGER_MessageFlags flags = (
211 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
212 );
213
214 const uint16_t length = full_length - sizeof(*msg);
215 const char *buffer = ((const char*) msg) + sizeof(*msg);
216 struct GNUNET_IDENTITY_PublicKey public_key;
217
218
219 size_t key_length = 0;
220
221 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE))
222 if (GNUNET_SYSERR ==
223 GNUNET_IDENTITY_read_public_key_from_buffer (buffer, length,
224 &public_key,
225 &key_length))
226 return GNUNET_NO;
227
228 const uint16_t msg_length = length - key_length;
229 const char *msg_buffer = buffer + key_length;
230
231 struct GNUNET_MESSENGER_Message message;
232
233 if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_NO))
234 return GNUNET_NO;
235
236 if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, GNUNET_NO,
237 NULL))
238 return GNUNET_NO;
239
240 const int allowed = filter_message_sending (&message);
241
242 cleanup_message (&message);
243 return GNUNET_YES == allowed? GNUNET_OK : GNUNET_NO;
244}
245
246static void
247handle_send_message (void *cls,
248 const struct GNUNET_MESSENGER_SendMessage *msg)
249{
250 struct GNUNET_MESSENGER_Client *msg_client = cls;
251
252 const enum GNUNET_MESSENGER_MessageFlags flags = (
253 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
254 );
255
256 const struct GNUNET_HashCode *key = &(msg->key);
257 const char *buffer = ((const char*) msg) + sizeof(*msg);
258
259 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
260 size_t key_length = 0;
261
262 struct GNUNET_IDENTITY_PublicKey public_key;
263
264 if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
265 {
266 GNUNET_assert (GNUNET_SYSERR !=
267 GNUNET_IDENTITY_read_public_key_from_buffer (buffer,
268 length,
269 &public_key,
270 &key_length));
271 }
272 const uint16_t msg_length = length - key_length;
273 const char*msg_buffer = buffer + key_length;
274
275 struct GNUNET_MESSENGER_Message message;
276 decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
277
278 if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
279 (GNUNET_YES != encrypt_message (&message, &public_key)))
280 {
281 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
282 "Encrypting message failed: Message got dropped!\n");
283
284 goto end_handling;
285 }
286
287 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
288 GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (
289 key));
290
291 if (GNUNET_YES != send_srv_handle_message (msg_client->handle, key, &message))
292 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
293 GNUNET_MESSENGER_name_of_kind (message.header.kind),
294 GNUNET_h2s (key));
295
296 end_handling:
297 cleanup_message (&message);
298
299 GNUNET_SERVICE_client_continue (msg_client->client);
300}
301
302static void
303callback_found_message (void *cls,
304 struct GNUNET_MESSENGER_SrvRoom *room,
305 const struct GNUNET_MESSENGER_Message *message,
306 const struct GNUNET_HashCode *hash)
307{
308 struct GNUNET_MESSENGER_Client *msg_client = cls;
309
310 if (! message)
311 {
312 send_srv_room_message (room, msg_client->handle, create_message_request (
313 hash));
314 return;
315 }
316
317 struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store (room);
318
319 struct GNUNET_MESSENGER_Member *member = get_store_member_of (store, message);
320
321 if (! member)
322 {
323 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n",
324 GNUNET_h2s (hash));
325 return;
326 }
327
328 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of (
329 member, message, hash);
330
331 if (session)
332 notify_srv_handle_message (msg_client->handle, room, session, message,
333 hash);
334}
335
336static void
337handle_get_message (void *cls,
338 const struct GNUNET_MESSENGER_GetMessage *msg)
339{
340 struct GNUNET_MESSENGER_Client *msg_client = cls;
341
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Requesting message from room: %s\n",
343 GNUNET_h2s (&(msg->key)));
344
345 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (messenger,
346 &(msg->key));
347
348 if (! room)
349 {
350 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Room not found: %s\n", GNUNET_h2s (
351 &(msg->key)));
352 goto end_handling;
353 }
354
355 struct GNUNET_MESSENGER_MemberStore *member_store =
356 get_srv_room_member_store (room);
357
358 struct GNUNET_MESSENGER_Member *member = get_store_member (member_store,
359 get_srv_handle_member_id (
360 msg_client->
361 handle,
362 &(msg->key)
363 ));
364
365 if (! member)
366 {
367 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
368 "Member not valid to request a message!\n");
369 goto end_handling;
370 }
371
372 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member,
373 &(
374 get_srv_handle_ego (
375 msg_client
376 ->
377 handle)
378 ->pub));
379
380 if (! session)
381 {
382 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
383 "Session not valid to request a message!\n");
384 goto end_handling;
385 }
386
387 request_srv_room_message (room, &(msg->hash), session, callback_found_message,
388 msg_client);
389
390 end_handling:
391 GNUNET_SERVICE_client_continue (msg_client->client);
392}
393
394static void*
395callback_client_connect (void *cls,
396 struct GNUNET_SERVICE_Client *client,
397 struct GNUNET_MQ_Handle *mq)
398{
399 struct GNUNET_MESSENGER_Client *msg_client = GNUNET_new (struct
400 GNUNET_MESSENGER_Client);
401
402 msg_client->client = client;
403 msg_client->handle = add_service_handle (messenger, mq);
404
405 return msg_client;
406}
407
408static void
409callback_client_disconnect (void *cls,
410 struct GNUNET_SERVICE_Client *client,
411 void *internal_cls)
412{
413 struct GNUNET_MESSENGER_Client *msg_client = internal_cls;
414
415 remove_service_handle (messenger, msg_client->handle);
416
417 GNUNET_free (msg_client);
418}
419
420/**
421 * Setup MESSENGER internals.
422 *
423 * @param[in/out] cls closure
424 * @param[in] config configuration to use
425 * @param[in/out] service the initialized service
426 */
427static void
428run (void *cls,
429 const struct GNUNET_CONFIGURATION_Handle *config,
430 struct GNUNET_SERVICE_Handle *service)
431{
432 messenger = create_service (config, service);
433
434 if (! messenger)
435 GNUNET_SCHEDULER_shutdown ();
436}
437
438/**
439 * Define "main" method using service macro.
440 */
441GNUNET_SERVICE_MAIN (
442 GNUNET_MESSENGER_SERVICE_NAME,
443 GNUNET_SERVICE_OPTION_NONE,
444 &run,
445 &callback_client_connect,
446 &callback_client_disconnect,
447 NULL,
448 GNUNET_MQ_hd_var_size (create,
449 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, struct
450 GNUNET_MESSENGER_CreateMessage, NULL),
451 GNUNET_MQ_hd_fixed_size (update,
452 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE,
453 struct
454 GNUNET_MESSENGER_UpdateMessage, NULL),
455 GNUNET_MQ_hd_fixed_size (destroy,
456 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY,
457 struct
458 GNUNET_MESSENGER_DestroyMessage, NULL),
459 GNUNET_MQ_hd_var_size (set_name,
460 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME,
461 struct
462 GNUNET_MESSENGER_NameMessage, NULL),
463 GNUNET_MQ_hd_fixed_size (room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
464 struct GNUNET_MESSENGER_RoomMessage, NULL),
465 GNUNET_MQ_hd_fixed_size (room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
466 struct GNUNET_MESSENGER_RoomMessage, NULL),
467 GNUNET_MQ_hd_fixed_size (room_close, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
468 struct GNUNET_MESSENGER_RoomMessage, NULL),
469 GNUNET_MQ_hd_var_size (send_message,
470 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE, struct
471 GNUNET_MESSENGER_SendMessage, NULL),
472 GNUNET_MQ_hd_fixed_size (get_message,
473 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE,
474 struct
475 GNUNET_MESSENGER_GetMessage, NULL),
476 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 1db5c651c..000000000
--- a/src/messenger/gnunet-service-messenger.h
+++ /dev/null
@@ -1,133 +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_identity_service.h"
32#include "gnunet_protocols.h"
33#include "gnunet_util_lib.h"
34
35/**
36 * Message to create a handle for a client
37 */
38struct GNUNET_MESSENGER_CreateMessage
39{
40 struct GNUNET_MessageHeader header;
41};
42
43/**
44 * Message to update the handle (its EGO key) for a client
45 */
46struct GNUNET_MESSENGER_UpdateMessage
47{
48 struct GNUNET_MessageHeader header;
49};
50
51/**
52 * Message to destroy the handle for a client
53 */
54struct GNUNET_MESSENGER_DestroyMessage
55{
56 struct GNUNET_MessageHeader header;
57};
58
59/**
60 * Message to receive the current name of a handle
61 */
62struct GNUNET_MESSENGER_NameMessage
63{
64 struct GNUNET_MessageHeader header;
65};
66
67/**
68 * Message to receive the current public key of a handle
69 */
70struct GNUNET_MESSENGER_KeyMessage
71{
72 struct GNUNET_MessageHeader header;
73};
74
75/**
76 * General message to confirm interaction with a room
77 */
78struct GNUNET_MESSENGER_RoomMessage
79{
80 struct GNUNET_MessageHeader header;
81
82 struct GNUNET_PeerIdentity door;
83 struct GNUNET_HashCode key;
84};
85
86/**
87 * Message to receive the current member id of a handle in room
88 */
89struct GNUNET_MESSENGER_MemberMessage
90{
91 struct GNUNET_MessageHeader header;
92
93 struct GNUNET_HashCode key;
94 struct GNUNET_ShortHashCode id;
95};
96
97/**
98 * Message to send something into a room
99 */
100struct GNUNET_MESSENGER_SendMessage
101{
102 struct GNUNET_MessageHeader header;
103
104 struct GNUNET_HashCode key;
105 uint32_t flags;
106};
107
108/**
109 * Message to request something from a room
110 */
111struct GNUNET_MESSENGER_GetMessage
112{
113 struct GNUNET_MessageHeader header;
114
115 struct GNUNET_HashCode key;
116 struct GNUNET_HashCode hash;
117};
118
119/**
120 * Message to receive something from a room
121 */
122struct GNUNET_MESSENGER_RecvMessage
123{
124 struct GNUNET_MessageHeader header;
125
126 struct GNUNET_HashCode key;
127 struct GNUNET_HashCode sender;
128 struct GNUNET_HashCode context;
129 struct GNUNET_HashCode hash;
130 uint32_t flags;
131};
132
133#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 ae0dcaa62..000000000
--- a/src/messenger/gnunet-service-messenger_basement.c
+++ /dev/null
@@ -1,65 +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 "platform.h"
27#include "gnunet-service-messenger_basement.h"
28
29size_t
30count_of_tunnels (const struct GNUNET_MESSENGER_ListTunnels *tunnels)
31{
32 GNUNET_assert(tunnels);
33
34 const struct GNUNET_MESSENGER_ListTunnel *element;
35 size_t count = 0;
36
37 for (element = tunnels->head; element; element = element->next)
38 count++;
39
40 return count;
41}
42
43int
44should_connect_tunnel_to (size_t count,
45 size_t src,
46 size_t dst)
47{
48 if ((src + 1) % count == dst % count)
49 return GNUNET_YES;
50
51 return GNUNET_NO;
52}
53
54int
55required_connection_between (size_t count,
56 size_t src,
57 size_t dst)
58{
59 if (GNUNET_YES == should_connect_tunnel_to (count, src, dst))
60 return GNUNET_YES;
61 if (GNUNET_YES == should_connect_tunnel_to (count, dst, src))
62 return GNUNET_YES;
63
64 return GNUNET_NO;
65}
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 3eb313b08..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.c
+++ /dev/null
@@ -1,482 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_ego_store.h"
28
29#include "gnunet-service-messenger_handle.h"
30
31static void
32callback_update_ego (void *cls,
33 struct GNUNET_IDENTITY_Ego *ego,
34 void **ctx,
35 const char *identifier)
36{
37 if ((!ctx) || (!identifier))
38 return;
39
40 struct GNUNET_MESSENGER_EgoStore *store = cls;
41
42 if (ego)
43 {
44 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
45 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
46 }
47 else
48 {
49 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Ego got deleted: '%s'\n", identifier);
50 delete_store_ego (store, identifier);
51 }
52}
53
54void
55init_ego_store(struct GNUNET_MESSENGER_EgoStore *store,
56 const struct GNUNET_CONFIGURATION_Handle *config)
57{
58 GNUNET_assert ((store) && (config));
59
60 store->cfg = config;
61 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
62 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
63 store->handles = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
64
65 store->lu_start = NULL;
66 store->lu_end = NULL;
67
68 store->op_start = NULL;
69 store->op_end = NULL;
70}
71
72static int
73iterate_destroy_egos (void *cls,
74 const struct GNUNET_HashCode *key,
75 void *value)
76{
77 struct GNUNET_MESSENGER_Ego *ego = value;
78 GNUNET_free(ego);
79 return GNUNET_YES;
80}
81
82void
83clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
84{
85 GNUNET_assert (store);
86
87 struct GNUNET_MESSENGER_EgoOperation *op;
88
89 while (store->op_start)
90 {
91 op = store->op_start;
92
93 GNUNET_IDENTITY_cancel (op->operation);
94 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
95
96 if (op->identifier)
97 GNUNET_free (op->identifier);
98
99 GNUNET_free (op);
100 }
101
102 struct GNUNET_MESSENGER_EgoLookup *lu;
103
104 while (store->lu_start)
105 {
106 lu = store->lu_start;
107
108 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
109 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
110
111 if (lu->identifier)
112 GNUNET_free(lu->identifier);
113
114 GNUNET_free (lu);
115 }
116
117 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
118 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
119
120 GNUNET_CONTAINER_multihashmap_destroy (store->handles);
121
122 if (store->identity)
123 {
124 GNUNET_IDENTITY_disconnect (store->identity);
125
126 store->identity = NULL;
127 }
128}
129
130static int
131iterate_create_ego (void *cls,
132 const struct GNUNET_HashCode *key,
133 void *value)
134{
135 struct GNUNET_MESSENGER_SrvHandle *handle = value;
136 set_srv_handle_ego (handle, (struct GNUNET_MESSENGER_Ego*) cls);
137 return GNUNET_YES;
138}
139
140static void
141callback_ego_create (void *cls,
142 const struct GNUNET_IDENTITY_PrivateKey *key,
143 enum GNUNET_ErrorCode ec)
144{
145 struct GNUNET_MESSENGER_EgoOperation *element = cls;
146 struct GNUNET_MESSENGER_EgoStore *store = element->store;
147
148 GNUNET_assert (element->identifier);
149
150 /**
151 * FIXME: This is dangerous, please handle errors
152 */
153 if (GNUNET_EC_NONE != ec)
154 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
155 GNUNET_ErrorCode_get_hint (ec));
156
157 if (key)
158 {
159 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
160
161 struct GNUNET_HashCode hash;
162 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
163
164 GNUNET_CONTAINER_multihashmap_get_multiple (store->handles, &hash, iterate_create_ego, msg_ego);
165 }
166 else
167 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
168
169 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
170 GNUNET_free (element->identifier);
171 GNUNET_free (element);
172}
173
174void
175create_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
176 const char *identifier)
177{
178 GNUNET_assert ((store) && (identifier));
179
180 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store create ego: %s\n", identifier);
181
182 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
183
184 element->store = store;
185 element->cls = NULL;
186
187 element->identifier = GNUNET_strdup (identifier);
188
189 element->operation = GNUNET_IDENTITY_create (
190 store->identity,
191 identifier,
192 NULL,
193 GNUNET_IDENTITY_TYPE_ECDSA,
194 callback_ego_create,
195 element
196 );
197
198 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
199}
200
201void
202bind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
203 const char *identifier,
204 void *handle)
205{
206 GNUNET_assert ((store) && (identifier) && (handle));
207
208 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store bind ego: %s\n", identifier);
209
210 struct GNUNET_HashCode hash;
211 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
212
213 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains_value(store->handles, &hash, handle))
214 return;
215
216 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->handles, &hash, handle,
217 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
218 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Putting handle binding to ego store failed!\n");
219}
220
221void
222unbind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
223 const char *identifier,
224 void *handle)
225{
226 GNUNET_assert ((store) && (identifier) && (handle));
227
228 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store unbind ego: %s\n", identifier);
229
230 struct GNUNET_HashCode hash;
231 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
232
233 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_contains_value(store->handles, &hash, handle))
234 return;
235
236 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(store->handles, &hash, handle))
237 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Removing handle binding from ego store failed!\n");
238}
239
240static void
241callback_ego_lookup (void *cls,
242 struct GNUNET_IDENTITY_Ego *ego)
243{
244 struct GNUNET_MESSENGER_EgoLookup *element = cls;
245 struct GNUNET_MESSENGER_EgoStore *store = element->store;
246
247 GNUNET_assert (element->identifier);
248
249 struct GNUNET_MESSENGER_Ego *msg_ego = NULL;
250
251 if (ego)
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "New ego looked up: '%s'\n", element->identifier);
254 msg_ego = update_store_ego (
255 store,
256 element->identifier,
257 GNUNET_IDENTITY_ego_get_private_key(ego)
258 );
259 }
260 else
261 {
262 struct GNUNET_HashCode hash;
263 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
264
265 if (GNUNET_CONTAINER_multihashmap_get (store->egos, &hash))
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Looked up ego got deleted: '%s'\n", element->identifier);
268 delete_store_ego(store, element->identifier);
269 }
270 }
271
272 if (element->cb)
273 element->cb(element->cls, element->identifier, msg_ego);
274
275 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
276 GNUNET_free (element->identifier);
277 GNUNET_free (element);
278}
279
280void
281lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store,
282 const char *identifier,
283 GNUNET_MESSENGER_EgoLookupCallback lookup,
284 void *cls)
285{
286 GNUNET_assert (store);
287
288 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store lookup ego: %s\n", identifier);
289
290 if (!identifier)
291 {
292 lookup(cls, identifier, NULL);
293 return;
294 }
295
296 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
297
298 element->store = store;
299
300 element->cb = lookup;
301 element->cls = cls;
302
303 element->identifier = GNUNET_strdup (identifier);
304
305 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
306
307 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
308}
309
310struct GNUNET_MESSENGER_Ego*
311update_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
312 const char *identifier,
313 const struct GNUNET_IDENTITY_PrivateKey *key)
314{
315 GNUNET_assert ((store) && (identifier) && (key));
316
317 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store update ego: %s\n", identifier);
318
319 struct GNUNET_HashCode hash;
320 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
321
322 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
323
324 if (!ego)
325 {
326 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
327 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
328 }
329
330 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
331
332 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
333 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
334
335 return ego;
336}
337
338void
339delete_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
340 const char *identifier)
341{
342 GNUNET_assert ((store) && (identifier));
343
344 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store delete ego: %s\n", identifier);
345
346 struct GNUNET_HashCode hash;
347 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
348
349 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
350
351 if (ego)
352 {
353 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Ego is not stored!\n");
354 return;
355 }
356
357 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
358 {
359 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Removing ego from store failed!\n");
360 return;
361 }
362
363 GNUNET_free(ego);
364}
365
366static void
367callback_ego_rename (void *cls,
368 enum GNUNET_ErrorCode ec)
369{
370 struct GNUNET_MESSENGER_EgoOperation *element = cls;
371 struct GNUNET_MESSENGER_EgoStore *store = element->store;
372
373 GNUNET_assert (element->identifier);
374
375 /**
376 * FIXME: Dangerous, handle error
377 */
378 if (GNUNET_EC_NONE != ec)
379 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
380 GNUNET_ErrorCode_get_hint (ec));
381
382 struct GNUNET_HashCode hash;
383 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
384
385 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
386
387 if (!ego)
388 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Ego is not stored!\n");
389
390 char *identifier = (char*) element->cls;
391
392 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
393 {
394 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
395
396 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
397 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
398 }
399 else
400 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
401
402 GNUNET_free (identifier);
403
404 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
405 GNUNET_free (element->identifier);
406 GNUNET_free (element);
407}
408
409void
410rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
411 const char *old_identifier,
412 const char *new_identifier)
413{
414 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
415
416 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store rename ego: %s -> %s\n", old_identifier, new_identifier);
417
418 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
419
420 element->store = store;
421 element->cls = GNUNET_strdup (new_identifier);
422
423 element->identifier = GNUNET_strdup (old_identifier);
424
425 element->operation = GNUNET_IDENTITY_rename (
426 store->identity,
427 old_identifier,
428 new_identifier,
429 callback_ego_rename,
430 element
431 );
432
433 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
434}
435
436static void
437callback_ego_delete (void *cls,
438 enum GNUNET_ErrorCode ec)
439{
440 struct GNUNET_MESSENGER_EgoOperation *element = cls;
441 struct GNUNET_MESSENGER_EgoStore *store = element->store;
442
443 GNUNET_assert (element->identifier);
444
445 /**
446 * FIXME: Dangerous, handle error
447 */
448 if (GNUNET_EC_NONE != ec)
449 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%s\n",
450 GNUNET_ErrorCode_get_hint (ec));
451
452 create_store_ego (store, element->identifier);
453
454 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
455 GNUNET_free (element->identifier);
456 GNUNET_free (element);
457}
458
459void
460renew_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
461 const char *identifier)
462{
463 GNUNET_assert ((store) && (identifier));
464
465 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Store renew ego: %s\n", identifier);
466
467 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
468
469 element->store = store;
470 element->cls = NULL;
471
472 element->identifier = GNUNET_strdup (identifier);
473
474 element->operation = GNUNET_IDENTITY_delete(
475 store->identity,
476 identifier,
477 callback_ego_delete,
478 element
479 );
480
481 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
482}
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 a5f8a69d8..000000000
--- a/src/messenger/gnunet-service-messenger_ego_store.h
+++ /dev/null
@@ -1,206 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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_util_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
66 void *cls;
67
68 char *identifier;
69};
70
71struct GNUNET_MESSENGER_EgoStore
72{
73 const struct GNUNET_CONFIGURATION_Handle *cfg;
74
75 struct GNUNET_IDENTITY_Handle *identity;
76 struct GNUNET_CONTAINER_MultiHashMap *egos;
77 struct GNUNET_CONTAINER_MultiHashMap *handles;
78
79 struct GNUNET_MESSENGER_EgoLookup *lu_start;
80 struct GNUNET_MESSENGER_EgoLookup *lu_end;
81
82 struct GNUNET_MESSENGER_EgoOperation *op_start;
83 struct GNUNET_MESSENGER_EgoOperation *op_end;
84};
85
86/**
87 * Initializes an EGO-store as fully empty.
88 *
89 * @param[out] store EGO-store
90 * @param[in] config Configuration handle
91 */
92void
93init_ego_store (struct GNUNET_MESSENGER_EgoStore *store,
94 const struct GNUNET_CONFIGURATION_Handle *config);
95
96/**
97 * Clears an EGO-store, wipes its content and deallocates its memory.
98 *
99 * @param[in,out] store EGO-store
100 */
101void
102clear_ego_store (struct GNUNET_MESSENGER_EgoStore *store);
103
104/**
105 * Creates a new EGO which will be registered to a <i>store</i> under
106 * a specific <i>identifier</i>.
107 *
108 * @param[in,out] store EGO-store
109 * @param[in] identifier Identifier string
110 */
111void
112create_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
113 const char *identifier);
114
115/**
116 * Binds an EGO which was registered to a <i>store</i> under
117 * a specific <i>identifier</i> to a given <i>handle</i>
118 *
119 * @param[in,out] store EGO-store
120 * @param[in] identifier Identifier string
121 * @param[in,out] handle Handle
122 */
123void
124bind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
125 const char *identifier,
126 void *handle);
127
128/**
129 * Binds an EGO which was registered to a <i>store</i> under
130 * a specific <i>identifier</i> to a given <i>handle</i>
131 *
132 * @param[in,out] store EGO-store
133 * @param[in] identifier Identifier string
134 * @param[in,out] handle Handle
135 */
136void
137unbind_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
138 const char *identifier,
139 void *handle);
140
141/**
142 * Lookups an EGO which was registered to a <i>store</i> under
143 * a specific <i>identifier</i>.
144 *
145 * @param[in,out] store EGO-store
146 * @param[in] identifier Identifier string
147 * @param[in] lookup Lookup callback (non-NULL)
148 * @param[in] cls Closure
149 */
150void
151lookup_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
152 const char *identifier,
153 GNUNET_MESSENGER_EgoLookupCallback lookup,
154 void *cls);
155
156/**
157 * Updates the registration of an EGO to a <i>store</i> under
158 * a specific <i>identifier</i> with a new <i>key</i>.
159 *
160 * @param[in,out] store EGO-store
161 * @param[in] identifier Identifier string
162 * @param[in] key Private EGO key
163 * @return Updated EGO
164 */
165struct GNUNET_MESSENGER_Ego*
166update_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
167 const char *identifier,
168 const struct GNUNET_IDENTITY_PrivateKey *key);
169
170/**
171 * Deletes the registration of an EGO in a <i>store</i> under
172 * a specific <i>identifier</i>.
173 *
174 * @param[in,out] store EGO-store
175 * @param[in] identifier Identifier string
176 */
177void
178delete_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
179 const char *identifier);
180
181/**
182 * Updates the location of a registered EGO in a <i>store</i> to
183 * a different one under a specific <i>new_identifier</i> replacing
184 * its old one.
185 *
186 * @param[in,out] store EGO-store
187 * @param[in] old_identifier Old identifier string
188 * @param[in] new_identifier New identifier string
189 */
190void
191rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
192 const char *old_identifier,
193 const char *new_identifier);
194
195/**
196 * Replaces the registered EGO in a <i>store</i> under a specific
197 * <i>identifier</i> with a newly created one.
198 *
199 * @param[in,out] store EGO-store
200 * @param[in] identifier Identifier string
201 */
202void
203renew_store_ego (struct GNUNET_MESSENGER_EgoStore *store,
204 const char *identifier);
205
206#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 17692761d..000000000
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ /dev/null
@@ -1,712 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_handle.h"
28
29#include "gnunet-service-messenger.h"
30#include "gnunet-service-messenger_message_kind.h"
31
32#include "messenger_api_util.h"
33
34struct GNUNET_MESSENGER_SrvHandle*
35create_srv_handle (struct GNUNET_MESSENGER_Service *service,
36 struct GNUNET_MQ_Handle *mq)
37{
38 GNUNET_assert((service) && (mq));
39
40 struct GNUNET_MESSENGER_SrvHandle *handle = GNUNET_new(struct GNUNET_MESSENGER_SrvHandle);
41
42 handle->service = service;
43 handle->mq = mq;
44
45 handle->name = NULL;
46 handle->ego = NULL;
47
48 handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
49
50 return handle;
51}
52
53int
54iterate_free_member_ids (void *cls,
55 const struct GNUNET_HashCode *key,
56 void *value)
57{
58 GNUNET_free(value);
59
60 return GNUNET_YES;
61}
62
63void
64destroy_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
65{
66 GNUNET_assert(handle);
67
68 if (handle->service->dir)
69 save_srv_handle_configuration (handle);
70
71 if (handle->name)
72 {
73 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
74
75 unbind_store_ego(store, handle->name, handle);
76
77 GNUNET_free(handle->name);
78 }
79
80 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_free_member_ids, NULL);
81 GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
82
83 GNUNET_free(handle);
84}
85
86void
87get_srv_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
88 const char *name,
89 char **dir)
90{
91 GNUNET_assert((handle) && (dir));
92
93 if (name)
94 GNUNET_asprintf (dir, "%s%s%c%s%c", handle->service->dir, "identities",
95 DIR_SEPARATOR, name, DIR_SEPARATOR);
96 else
97 GNUNET_asprintf (dir, "%s%s%c", handle->service->dir, "anonymous",
98 DIR_SEPARATOR);
99}
100
101static int
102create_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
103 const struct GNUNET_HashCode *key)
104{
105 GNUNET_assert((handle) && (key));
106
107 struct GNUNET_ShortHashCode *random_id = GNUNET_new(struct GNUNET_ShortHashCode);
108
109 if (!random_id)
110 return GNUNET_NO;
111
112 generate_free_member_id (random_id, NULL);
113
114 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, random_id,
115 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
116 {
117 GNUNET_free(random_id);
118 return GNUNET_NO;
119 }
120
121 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Created a new member id (%s) for room: %s\n", GNUNET_sh2s (random_id),
122 GNUNET_h2s (key));
123
124 return GNUNET_YES;
125}
126
127const struct GNUNET_ShortHashCode*
128get_srv_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
129 const struct GNUNET_HashCode *key)
130{
131 GNUNET_assert((handle) && (key));
132
133 return GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
134}
135
136int
137change_srv_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
138 const struct GNUNET_HashCode *key,
139 const struct GNUNET_ShortHashCode *unique_id)
140{
141 GNUNET_assert((handle) && (key) && (unique_id));
142
143 struct GNUNET_ShortHashCode *member_id = GNUNET_CONTAINER_multihashmap_get (handle->member_ids, key);
144
145 if (!member_id)
146 {
147 member_id = GNUNET_new(struct GNUNET_ShortHashCode);
148 GNUNET_memcpy(member_id, unique_id, sizeof(*member_id));
149
150 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->member_ids, key, member_id,
151 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
152 {
153 GNUNET_free(member_id);
154 return GNUNET_SYSERR;
155 }
156 }
157
158 if (0 == GNUNET_memcmp(unique_id, member_id))
159 goto send_message_to_client;
160
161 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room (%s).\n", GNUNET_sh2s (member_id),
162 GNUNET_h2s (key));
163
164 GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
165
166 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", GNUNET_sh2s (unique_id));
167
168 struct GNUNET_MESSENGER_MemberMessage *msg;
169 struct GNUNET_MQ_Envelope *env;
170
171send_message_to_client:
172
173 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
174
175 GNUNET_memcpy(&(msg->key), key, sizeof(*key));
176 GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
177
178 GNUNET_MQ_send (handle->mq, env);
179 return GNUNET_OK;
180}
181
182static void
183change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
184 const char *name)
185{
186 GNUNET_assert(handle);
187
188 if (handle->name)
189 GNUNET_free(handle->name);
190
191 handle->name = name ? GNUNET_strdup(name) : NULL;
192
193 const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
194
195 struct GNUNET_MESSENGER_NameMessage *msg;
196 struct GNUNET_MQ_Envelope *env;
197
198 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
199
200 char *extra = ((char*) msg) + sizeof(*msg);
201
202 if (name_len)
203 GNUNET_memcpy(extra, handle->name, name_len);
204
205 extra[name_len] = '\0';
206
207 GNUNET_MQ_send (handle->mq, env);
208}
209
210static void
211change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
212 const struct GNUNET_MESSENGER_Ego *ego)
213{
214 GNUNET_assert(handle);
215
216 handle->ego = ego;
217
218 ego = get_srv_handle_ego (handle);
219
220 const uint16_t length = GNUNET_IDENTITY_public_key_get_length(&(ego->pub));
221
222 struct GNUNET_MESSENGER_KeyMessage *msg;
223 struct GNUNET_MQ_Envelope *env;
224
225 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
226
227 char *extra = ((char*) msg) + sizeof(*msg);
228
229 if (GNUNET_IDENTITY_write_public_key_to_buffer(&(ego->pub), extra, length) < 0)
230 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
231
232 GNUNET_MQ_send (handle->mq, env);
233}
234
235struct GNUNET_MESSENGER_MessageHandle
236{
237 struct GNUNET_MESSENGER_SrvHandle *handle;
238 struct GNUNET_MESSENGER_Message *message;
239};
240
241static int
242iterate_send_message (void *cls,
243 const struct GNUNET_HashCode *key,
244 void *value)
245{
246 struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
247
248 send_srv_handle_message (msg_handle->handle, key, msg_handle->message);
249
250 return GNUNET_YES;
251}
252
253void
254set_srv_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
255 const struct GNUNET_MESSENGER_Ego *ego)
256{
257 GNUNET_assert((handle) && (ego));
258
259 struct GNUNET_MESSENGER_MessageHandle msg_handle;
260
261 msg_handle.handle = handle;
262 msg_handle.message = create_message_key (&(ego->priv));
263
264 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
265
266 destroy_message (msg_handle.message);
267
268 change_handle_ego (handle, ego);
269}
270
271const struct GNUNET_MESSENGER_Ego*
272get_srv_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
273{
274 GNUNET_assert(handle);
275
276 static struct GNUNET_MESSENGER_Ego anonymous;
277 static int read_keys = 0;
278
279 if (handle->ego)
280 return handle->ego;
281
282 if (!read_keys)
283 {
284 struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
285 GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key (ego), sizeof(anonymous.priv));
286 GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
287 read_keys = 1;
288 }
289
290 return &anonymous;
291}
292
293static void
294callback_setup_handle_name (void *cls,
295 const char *name,
296 const struct GNUNET_MESSENGER_Ego *ego)
297{
298 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
299
300 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
301
302 change_handle_name (handle, name);
303 change_handle_ego (handle, ego);
304
305 if (handle->service->dir)
306 load_srv_handle_configuration (handle);
307}
308
309void
310setup_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
311 const char *name)
312{
313 GNUNET_assert(handle);
314
315 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
316
317 lookup_store_ego (store, name, callback_setup_handle_name, handle);
318}
319
320static void
321callback_update_handle (void *cls,
322 const char *name,
323 const struct GNUNET_MESSENGER_Ego *ego)
324{
325 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
326
327 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
328
329 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
330
331 bind_store_ego(store, handle->name, handle);
332
333 if (!ego)
334 create_store_ego (store, handle->name);
335 else
336 renew_store_ego (store, handle->name);
337}
338
339void
340update_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
341{
342 GNUNET_assert (handle);
343
344 if (!handle->name)
345 {
346 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is required!\n");
347 return;
348 }
349
350 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
351
352 lookup_store_ego (store, handle->name, callback_update_handle, handle);
353}
354
355static void
356callback_set_handle_name (void *cls,
357 const char *name,
358 const struct GNUNET_MESSENGER_Ego *ego)
359{
360 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
361
362 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
363
364 if (ego)
365 {
366 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is occupied! (%s)\n", name);
367 return;
368 }
369
370 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
371
372 char *old_dir;
373 get_srv_handle_data_subdir (handle, handle->name, &old_dir);
374
375 char *new_dir;
376 get_srv_handle_data_subdir (handle, name, &new_dir);
377
378 if ((GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO)) &&
379 (GNUNET_OK != GNUNET_DISK_directory_remove(new_dir)))
380 goto free_dirs;
381
382 if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
383 {
384 GNUNET_DISK_directory_create_for_file (new_dir);
385
386 if (0 != rename (old_dir, new_dir))
387 goto free_dirs;
388 }
389
390 if (handle->ego)
391 rename_store_ego(store, handle->name, name);
392
393 struct GNUNET_MESSENGER_MessageHandle msg_handle;
394 msg_handle.handle = handle;
395 msg_handle.message = create_message_name (name);
396
397 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_send_message, &msg_handle);
398 destroy_message (msg_handle.message);
399 change_handle_name (handle, name);
400
401free_dirs:
402 GNUNET_free(old_dir);
403 GNUNET_free(new_dir);
404}
405
406void
407set_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
408 const char *name)
409{
410 GNUNET_assert(handle);
411
412 if (!name)
413 {
414 if (handle->ego)
415 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is required!\n");
416 else
417 change_handle_name (handle, name);
418
419 return;
420 }
421
422 struct GNUNET_MESSENGER_EgoStore *store = get_service_ego_store(handle->service);
423
424 lookup_store_ego (store, name, callback_set_handle_name, handle);
425}
426
427int
428open_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
429 const struct GNUNET_HashCode *key)
430{
431 GNUNET_assert((handle) && (key));
432
433 if ((!get_srv_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
434 return GNUNET_NO;
435
436 return open_service_room (handle->service, handle, key);
437}
438
439int
440entry_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
441 const struct GNUNET_PeerIdentity *door,
442 const struct GNUNET_HashCode *key)
443{
444 GNUNET_assert((handle) && (door) && (key));
445
446 if ((!get_srv_handle_member_id (handle, key)) && (GNUNET_YES != create_handle_member_id (handle, key)))
447 return GNUNET_NO;
448
449 return entry_service_room (handle->service, handle, door, key);
450}
451
452int
453close_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
454 const struct GNUNET_HashCode *key)
455{
456 GNUNET_assert((handle) && (key));
457
458 if (!get_srv_handle_member_id (handle, key))
459 return GNUNET_NO;
460
461 return close_service_room (handle->service, handle, key);
462}
463
464int
465send_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
466 const struct GNUNET_HashCode *key,
467 const struct GNUNET_MESSENGER_Message *message)
468{
469 GNUNET_assert((handle) && (key) && (message));
470
471 const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle, key);
472
473 if (!id)
474 {
475 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "It is required to be a member of a room to send messages!\n");
476 return GNUNET_NO;
477 }
478
479 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, key);
480
481 if (!room)
482 {
483 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "The room (%s) is unknown!\n", GNUNET_h2s (key));
484 return GNUNET_NO;
485 }
486
487 struct GNUNET_MESSENGER_Message *msg = copy_message(message);
488
489 GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
490
491 return send_srv_room_message (room, handle, msg);
492}
493
494static const struct GNUNET_HashCode*
495get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession *session)
496{
497 if (session->next)
498 return get_next_member_session_contect (session->next);
499 else
500 return get_member_session_context(session);
501}
502
503static const struct GNUNET_MESSENGER_MemberSession*
504get_handle_member_session (struct GNUNET_MESSENGER_SrvHandle *handle,
505 struct GNUNET_MESSENGER_SrvRoom *room,
506 const struct GNUNET_HashCode *key)
507{
508 GNUNET_assert((handle) && (room) && (key) && (handle->service));
509
510 const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id(handle, key);
511
512 if (!id)
513 return NULL;
514
515 struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store(room);
516 struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
517
518 const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(handle);
519
520 if (!ego)
521 return NULL;
522
523 return get_member_session(member, &(ego->pub));
524}
525
526void
527notify_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
528 struct GNUNET_MESSENGER_SrvRoom *room,
529 const struct GNUNET_MESSENGER_MemberSession *session,
530 const struct GNUNET_MESSENGER_Message *message,
531 const struct GNUNET_HashCode *hash)
532{
533 GNUNET_assert((handle) && (room) && (session) && (message) && (hash));
534
535 const struct GNUNET_HashCode *key = get_srv_room_key(room);
536
537 if ((!handle->mq) || (!get_srv_handle_member_id (handle, key)))
538 {
539 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notifying client about message requires membership!\n");
540 return;
541 }
542
543 const struct GNUNET_IDENTITY_PublicKey *pubkey = get_contact_key(session->contact);
544
545 struct GNUNET_HashCode sender;
546 GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
547
548 const struct GNUNET_HashCode *context = get_next_member_session_contect (session);
549
550 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", GNUNET_h2s (hash));
551
552 struct GNUNET_MESSENGER_Message *private_message = NULL;
553
554 if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
555 {
556 private_message = copy_message(message);
557
558 if (GNUNET_YES != decrypt_message(private_message, &(get_srv_handle_ego(handle)->priv)))
559 {
560 destroy_message(private_message);
561 private_message = NULL;
562 }
563 else
564 message = private_message;
565 }
566
567 struct GNUNET_MESSENGER_RecvMessage *msg;
568 struct GNUNET_MQ_Envelope *env;
569
570 uint16_t length = get_message_size (message, GNUNET_YES);
571
572 env = GNUNET_MQ_msg_extra(msg, length, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE);
573
574 GNUNET_memcpy(&(msg->key), key, sizeof(msg->key));
575 GNUNET_memcpy(&(msg->sender), &sender, sizeof(msg->sender));
576 GNUNET_memcpy(&(msg->context), context, sizeof(msg->context));
577 GNUNET_memcpy(&(msg->hash), hash, sizeof(msg->hash));
578
579 msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
580
581 if (get_handle_member_session(handle, room, key) == session)
582 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
583
584 if (private_message)
585 msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
586
587 char *buffer = ((char*) msg) + sizeof(*msg);
588 encode_message (message, length, buffer, GNUNET_YES);
589
590 if (private_message)
591 destroy_message(private_message);
592
593 GNUNET_MQ_send (handle->mq, env);
594}
595
596static int
597callback_scan_for_rooms (void *cls,
598 const char *filename)
599{
600 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
601
602 if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, ".cfg")))
603 return GNUNET_OK;
604
605 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load room configuration of handle: %s\n", filename);
606
607 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
608
609 if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, filename)))
610 {
611 struct GNUNET_HashCode key;
612 struct GNUNET_ShortHashCode member_id;
613
614 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, sizeof(key))) &&
615 (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", &member_id, sizeof(member_id))))
616 change_srv_handle_member_id (handle, &key, &member_id);
617 }
618
619 GNUNET_CONFIGURATION_destroy (cfg);
620 return GNUNET_OK;
621}
622
623void
624load_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
625{
626 GNUNET_assert(handle);
627
628 char *id_dir;
629 get_srv_handle_data_subdir (handle, handle->name, &id_dir);
630
631 if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
632 {
633 char *scan_dir;
634 GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
635
636 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
637 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
638
639 GNUNET_free(scan_dir);
640 }
641
642 GNUNET_free(id_dir);
643}
644
645static int
646iterate_save_rooms (void *cls,
647 const struct GNUNET_HashCode *key,
648 void *value)
649{
650 struct GNUNET_MESSENGER_SrvHandle *handle = cls;
651 struct GNUNET_ShortHashCode *member_id = value;
652
653 char *id_dir;
654 get_srv_handle_data_subdir (handle, handle->name, &id_dir);
655
656 char *filename;
657 GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (key));
658 GNUNET_free(id_dir);
659
660 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save room configuration of handle: %s\n", filename);
661
662 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
663
664 char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
665
666 if (key_data)
667 {
668 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
669
670 GNUNET_free(key_data);
671 }
672
673 char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, sizeof(*member_id));
674
675 if (member_id_data)
676 {
677 GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", member_id_data);
678
679 GNUNET_free(member_id_data);
680 }
681
682 GNUNET_CONFIGURATION_write (cfg, filename);
683 GNUNET_CONFIGURATION_destroy (cfg);
684
685 GNUNET_free(filename);
686
687 return GNUNET_YES;
688}
689
690void
691save_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
692{
693 GNUNET_assert(handle);
694
695 char *id_dir;
696 get_srv_handle_data_subdir (handle, handle->name, &id_dir);
697
698 if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || (GNUNET_OK
699 == GNUNET_DISK_directory_create (id_dir)))
700 {
701 char *save_dir;
702 GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
703
704 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
705 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
706 GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, iterate_save_rooms, handle);
707
708 GNUNET_free(save_dir);
709 }
710
711 GNUNET_free(id_dir);
712}
diff --git a/src/messenger/gnunet-service-messenger_handle.h b/src/messenger/gnunet-service-messenger_handle.h
deleted file mode 100644
index edcd2ccd0..000000000
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ /dev/null
@@ -1,249 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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_util_lib.h"
32#include "gnunet_identity_service.h"
33
34#include "gnunet-service-messenger_service.h"
35#include "gnunet-service-messenger_member_session.h"
36
37#include "messenger_api_ego.h"
38#include "messenger_api_message.h"
39
40struct GNUNET_MESSENGER_SrvHandle
41{
42 struct GNUNET_MESSENGER_Service *service;
43 struct GNUNET_MQ_Handle *mq;
44
45 char *name;
46
47 const struct GNUNET_MESSENGER_Ego *ego;
48
49 struct GNUNET_CONTAINER_MultiHashMap *member_ids;
50};
51
52/**
53 * Creates and allocates a new handle related to a <i>service</i> and using a given <i>mq</i> (message queue).
54 *
55 * @param[in,out] service MESSENGER Service
56 * @param[in,out] mq Message queue
57 * @return New handle
58 */
59struct GNUNET_MESSENGER_SrvHandle*
60create_srv_handle (struct GNUNET_MESSENGER_Service *service,
61 struct GNUNET_MQ_Handle *mq);
62
63/**
64 * Destroys a handle and frees its memory fully.
65 *
66 * @param[in,out] handle Handle
67 */
68void
69destroy_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
70
71/**
72 * Writes the path of the directory for a given <i>handle</i> using a specific <i>name</i> to the parameter
73 * <i>dir</i>. This directory will be used to store data regarding the handle and its messages.
74 *
75 * @param[in] handle Handle
76 * @param[in] name Potential name of the handle
77 * @param[out] dir Path to store data
78 */
79void
80get_srv_handle_data_subdir (const struct GNUNET_MESSENGER_SrvHandle *handle,
81 const char *name,
82 char **dir);
83
84/**
85 * Returns the member id of a given <i>handle</i> in a specific <i>room</i>.
86 *
87 * If the handle is not a member of the specific <i>room</i>, NULL gets returned.
88 *
89 * @param[in] handle Handle
90 * @param[in] key Key of a room
91 * @return Member id or NULL
92 */
93const struct GNUNET_ShortHashCode*
94get_srv_handle_member_id (const struct GNUNET_MESSENGER_SrvHandle *handle,
95 const struct GNUNET_HashCode *key);
96
97/**
98 * Changes the member id of a given <i>handle</i> in a specific <i>room</i> to match a <i>unique_id</i>
99 * and returns GNUNET_OK on success.
100 *
101 * The client connected to the <i>handle</i> will be informed afterwards automatically.
102 *
103 * @param[in,out] handle Handle
104 * @param[in] key Key of a room
105 * @param[in] unique_id Unique member id
106 * @return GNUNET_OK on success, otherwise GNUNET_SYSERR
107 */
108int
109change_srv_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
110 const struct GNUNET_HashCode *key,
111 const struct GNUNET_ShortHashCode *unique_id);
112
113/**
114 * Sets the EGO used by a given <i>handle</i>.
115 *
116 * @param[in,out] handle Handle
117 * @param[in] ego EGO key pair
118 */
119void
120set_srv_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
121 const struct GNUNET_MESSENGER_Ego *ego);
122
123/**
124 * Returns the EGO used by a given <i>handle</i>.
125 *
126 * @param[in] handle Handle
127 * @return EGO key pair
128 */
129const struct GNUNET_MESSENGER_Ego*
130get_srv_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
131
132/**
133 * Tries to set the name and EGO key of a <i>handle</i> initially by looking up a specific <i>name</i>.
134 *
135 * @param[in,out] handle Handle
136 * @param[in] name Name (optionally: valid EGO name)
137 */
138void
139setup_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
140 const char *name);
141
142/**
143 * Tries to change the key pair of an EGO of a <i>handle</i> under the same name and informs all rooms
144 * about the change automatically.
145 *
146 * @param[in,out] handle Handle
147 */
148void
149update_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
150
151/**
152 * Tries to rename the handle which implies renaming the EGO its using and moving all related data into
153 * the directory fitting to the changed <i>name</i>.
154 *
155 * The client connected to the <i>handle</i> will be informed afterwards automatically.
156 *
157 * @param[in,out] handle Handle
158 * @param[in] name New name
159 */
160void
161set_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
162 const char *name);
163
164/**
165 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and opens the
166 * room from the handles service.
167 *
168 * @param[in,out] handle Handle
169 * @param[in] key Key of a room
170 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
171 */
172int
173open_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
174 const struct GNUNET_HashCode *key);
175
176/**
177 * Makes a given <i>handle</i> a member of the room using a specific <i>key</i> and enters the room
178 * through a tunnel to a peer identified by a given <i>door</i> (peer identity).
179 *
180 * @param[in,out] handle Handle
181 * @param[in] door Peer identity
182 * @param[in] key Key of a room
183 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
184 */
185int
186entry_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
187 const struct GNUNET_PeerIdentity *door,
188 const struct GNUNET_HashCode *key);
189
190/**
191 * Removes the membership of the room using a specific <i>key</i> and closes it if no other handle
192 * from this service is still a member of it.
193 *
194 * @param[in,out] handle Handle
195 * @param[in] key Key of a room
196 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
197 */
198int
199close_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle *handle,
200 const struct GNUNET_HashCode *key);
201
202/**
203 * Sends a <i>message</i> from a given <i>handle</i> to the room using a specific <i>key</i>.
204 *
205 * @param[in,out] handle Handle
206 * @param[in] key Key of a room
207 * @param[in] message Message
208 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
209 */
210int
211send_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
212 const struct GNUNET_HashCode *key,
213 const struct GNUNET_MESSENGER_Message *message);
214
215/**
216 * Notifies the handle that a new message was received or sent.
217 *
218 * @param[in,out] handle Handle
219 * @param[in] room Room of the message
220 * @param[in] session Member session
221 * @param[in] message Message
222 * @param[in] hash Hash of message
223 */
224void
225notify_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
226 struct GNUNET_MESSENGER_SrvRoom *room,
227 const struct GNUNET_MESSENGER_MemberSession *session,
228 const struct GNUNET_MESSENGER_Message *message,
229 const struct GNUNET_HashCode *hash);
230
231/**
232 * Loads member ids and other potential configuration from a given <i>handle</i> which
233 * depends on the given name the <i>handle</i> uses.
234 *
235 * @param[out] handle Handle
236 */
237void
238load_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
239
240/**
241 * Saves member ids and other potential configuration from a given <i>handle</i> which
242 * depends on the given name the <i>handle</i> uses.
243 *
244 * @param[in] handle Handle
245 */
246void
247save_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
248
249#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 0703c2de6..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.c
+++ /dev/null
@@ -1,105 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_list_handles.h"
28
29#include "gnunet-service-messenger_handle.h"
30
31void
32init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
33{
34 GNUNET_assert(handles);
35
36 handles->head = NULL;
37 handles->tail = NULL;
38}
39
40void
41clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles)
42{
43 GNUNET_assert(handles);
44
45 while (handles->head)
46 {
47 struct GNUNET_MESSENGER_ListHandle *element = handles->head;
48
49 GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element);
50 destroy_srv_handle (element->handle);
51 GNUNET_free(element);
52 }
53
54 handles->head = NULL;
55 handles->tail = NULL;
56}
57
58void
59add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
60 struct GNUNET_MESSENGER_SrvHandle *handle)
61{
62 GNUNET_assert((handles) && (handle));
63
64 struct GNUNET_MESSENGER_ListHandle *element = GNUNET_new(struct GNUNET_MESSENGER_ListHandle);
65
66 element->handle = handle;
67
68 GNUNET_CONTAINER_DLL_insert_tail(handles->head, handles->tail, element);
69}
70
71int
72remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
73 struct GNUNET_MESSENGER_SrvHandle *handle)
74{
75 GNUNET_assert((handles) && (handle));
76
77 struct GNUNET_MESSENGER_ListHandle *element;
78
79 for (element = handles->head; element; element = element->next)
80 if (element->handle == handle)
81 break;
82
83 if (!element)
84 return GNUNET_NO;
85
86 GNUNET_CONTAINER_DLL_remove(handles->head, handles->tail, element);
87 GNUNET_free(element);
88
89 return GNUNET_YES;
90}
91
92struct GNUNET_MESSENGER_SrvHandle*
93find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles,
94 const struct GNUNET_HashCode *key)
95{
96 GNUNET_assert((handles) && (key));
97
98 struct GNUNET_MESSENGER_ListHandle *element;
99
100 for (element = handles->head; element; element = element->next)
101 if (get_srv_handle_member_id ((struct GNUNET_MESSENGER_SrvHandle*) element->handle, key))
102 return element->handle;
103
104 return NULL;
105}
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 8c066519e..000000000
--- a/src/messenger/gnunet-service-messenger_list_handles.h
+++ /dev/null
@@ -1,100 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/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_util_lib.h"
31
32struct GNUNET_MESSENGER_SrvHandle;
33
34struct GNUNET_MESSENGER_ListHandle
35{
36 struct GNUNET_MESSENGER_ListHandle *prev;
37 struct GNUNET_MESSENGER_ListHandle *next;
38
39 struct GNUNET_MESSENGER_SrvHandle *handle;
40};
41
42struct GNUNET_MESSENGER_ListHandles
43{
44 struct GNUNET_MESSENGER_ListHandle *head;
45 struct GNUNET_MESSENGER_ListHandle *tail;
46};
47
48/**
49 * Initializes list of <i>handles</i> as empty list.
50 *
51 * @param[out] handles List of handles
52 */
53void
54init_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
55
56/**
57 * Destroys remaining <i>handles</i> and clears the list.
58 *
59 * @param[in,out] handles List of handles
60 */
61void
62clear_list_handles (struct GNUNET_MESSENGER_ListHandles *handles);
63
64/**
65 * Adds a specific <i>handle</i> to the end of the list.
66 *
67 * @param[in,out] handles List of handles
68 * @param[in,out] handle Handle
69 */
70void
71add_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
72 struct GNUNET_MESSENGER_SrvHandle *handle);
73
74/**
75 * Removes the first entry matching with a specific <i>handle</i> from the list of
76 * <i>handles</i> and returns #GNUNET_YES on success or #GNUNET_NO on failure.
77 *
78 * @param[in,out] handles List of handles
79 * @param[in,out] handle Handle
80 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
81 */
82int
83remove_list_handle (struct GNUNET_MESSENGER_ListHandles *handles,
84 struct GNUNET_MESSENGER_SrvHandle *handle);
85
86/**
87 * Searches linearly through the list of <i>handles</i> for members of a specific room
88 * which is identified by a given <i>key</i>.
89 *
90 * If no handle is found which is a current member, NULL gets returned.
91 *
92 * @param[in] handles List of handles
93 * @param[in] key Common key of a room
94 * @return First handle which is a current member
95 */
96struct GNUNET_MESSENGER_SrvHandle*
97find_list_handle_by_member (const struct GNUNET_MESSENGER_ListHandles *handles,
98 const struct GNUNET_HashCode *key);
99
100#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 5bab52806..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.c
+++ /dev/null
@@ -1,156 +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 "platform.h"
27#include "gnunet-service-messenger_list_messages.h"
28
29void
30init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
31{
32 GNUNET_assert(messages);
33
34 messages->head = NULL;
35 messages->tail = NULL;
36}
37
38void
39clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages)
40{
41 GNUNET_assert(messages);
42
43 while (messages->head)
44 {
45 struct GNUNET_MESSENGER_ListMessage *element = messages->head;
46
47 GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element);
48 GNUNET_free(element);
49 }
50
51 messages->head = NULL;
52 messages->tail = NULL;
53}
54
55void
56add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
57 const struct GNUNET_HashCode *hash)
58{
59 GNUNET_assert((messages) && (hash));
60
61 struct GNUNET_MESSENGER_ListMessage *element = GNUNET_new(struct GNUNET_MESSENGER_ListMessage);
62
63 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
64
65 GNUNET_CONTAINER_DLL_insert_tail(messages->head, messages->tail, element);
66}
67
68void
69copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
70 const struct GNUNET_MESSENGER_ListMessages *origin)
71{
72 GNUNET_assert((messages) && (origin));
73
74 struct GNUNET_MESSENGER_ListMessage *element;
75
76 for (element = origin->head; element; element = element->next)
77 add_to_list_messages (messages, &(element->hash));
78}
79
80void
81remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
82 const struct GNUNET_HashCode *hash)
83{
84 GNUNET_assert((messages) && (hash));
85
86 struct GNUNET_MESSENGER_ListMessage *element;
87
88 for (element = messages->head; element; element = element->next)
89 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), hash))
90 {
91 GNUNET_CONTAINER_DLL_remove(messages->head, messages->tail, element);
92 GNUNET_free(element);
93 break;
94 }
95}
96
97void
98load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
99 const char *path)
100{
101 GNUNET_assert((messages) && (path));
102
103 if (GNUNET_YES != GNUNET_DISK_file_test (path))
104 return;
105
106 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
107
108 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
109 path, GNUNET_DISK_OPEN_READ, permission
110 );
111
112 if (!handle)
113 return;
114
115 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
116
117 struct GNUNET_HashCode hash;
118 ssize_t len;
119
120 do {
121 len = GNUNET_DISK_file_read(handle, &hash, sizeof(hash));
122
123 if (len != sizeof(hash))
124 break;
125
126 add_to_list_messages(messages, &hash);
127 } while (len == sizeof(hash));
128
129 GNUNET_DISK_file_close(handle);
130}
131
132void
133save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages,
134 const char *path)
135{
136 GNUNET_assert((messages) && (path));
137
138 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
139
140 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
141 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
142 );
143
144 if (!handle)
145 return;
146
147 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
148
149 struct GNUNET_MESSENGER_ListMessage *element;
150
151 for (element = messages->head; element; element = element->next)
152 GNUNET_DISK_file_write(handle, &(element->hash), sizeof(element->hash));
153
154 GNUNET_DISK_file_sync(handle);
155 GNUNET_DISK_file_close(handle);
156}
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 5839f63ca..000000000
--- a/src/messenger/gnunet-service-messenger_list_messages.h
+++ /dev/null
@@ -1,112 +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_util_lib.h"
31
32struct GNUNET_MESSENGER_ListMessage
33{
34 struct GNUNET_MESSENGER_ListMessage *prev;
35 struct GNUNET_MESSENGER_ListMessage *next;
36
37 struct GNUNET_HashCode hash;
38};
39
40struct GNUNET_MESSENGER_ListMessages
41{
42 struct GNUNET_MESSENGER_ListMessage *head;
43 struct GNUNET_MESSENGER_ListMessage *tail;
44};
45
46/**
47 * Initializes list of message hashes as empty list.
48 *
49 * @param[out] messages List of hashes
50 */
51void
52init_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
53
54/**
55 * Clears the list of message hashes.
56 *
57 * @param[in,out] messages List of hashes
58 */
59void
60clear_list_messages (struct GNUNET_MESSENGER_ListMessages *messages);
61
62/**
63 * Adds a specific <i>hash</i> from a message to the end of the list.
64 *
65 * @param[in,out] messages List of hashes
66 * @param[in] hash Hash of message
67 */
68void
69add_to_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
70 const struct GNUNET_HashCode *hash);
71
72/**
73 * Copies all message hashes from an <i>origin</i> to another list.
74 *
75 * @param[in,out] messages Destination list of hashes
76 * @param[in] origin Source list of hashes
77 */
78void
79copy_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
80 const struct GNUNET_MESSENGER_ListMessages *origin);
81
82/**
83 * Removes the first entry with a matching <i>hash</i> from the list.
84 *
85 * @param[in,out] messages List of hashes
86 * @param[in] hash Hash of message
87 */
88void
89remove_from_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
90 const struct GNUNET_HashCode *hash);
91
92/**
93 * Loads the list of message hashes from a file under a given <i>path</i>.
94 *
95 * @param[out] messages List of hashes
96 * @param[in] path Path of file
97 */
98void
99load_list_messages (struct GNUNET_MESSENGER_ListMessages *messages,
100 const char *path);
101
102/**
103 * Saves the list of message hashes to a file under a given <i>path</i>.
104 *
105 * @param[in] messages List of hashes
106 * @param[in] path Path of file
107 */
108void
109save_list_messages (const struct GNUNET_MESSENGER_ListMessages *messages,
110 const char *path);
111
112#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 444148831..000000000
--- a/src/messenger/gnunet-service-messenger_member.c
+++ /dev/null
@@ -1,416 +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 "platform.h"
27#include "gnunet-service-messenger_member.h"
28
29#include "gnunet-service-messenger_member_session.h"
30
31struct GNUNET_MESSENGER_Member*
32create_member (struct GNUNET_MESSENGER_MemberStore *store,
33 const struct GNUNET_ShortHashCode *id)
34{
35 GNUNET_assert (store);
36
37 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
38
39 member->store = store;
40
41 if (id)
42 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
43 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
44 {
45 GNUNET_free (member);
46 return NULL;
47 }
48
49 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
50
51 return member;
52}
53
54static int
55iterate_destroy_session (void *cls,
56 const struct GNUNET_HashCode *key,
57 void *value)
58{
59 struct GNUNET_MESSENGER_MemberSession *session = value;
60 destroy_member_session(session);
61 return GNUNET_YES;
62}
63
64void
65destroy_member (struct GNUNET_MESSENGER_Member *member)
66{
67 GNUNET_assert((member) && (member->sessions));
68
69 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
70 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
71
72 GNUNET_free (member);
73}
74
75const struct GNUNET_ShortHashCode*
76get_member_id (const struct GNUNET_MESSENGER_Member *member)
77{
78 GNUNET_assert (member);
79
80 return &(member->id);
81}
82
83static int
84callback_scan_for_sessions (void *cls,
85 const char *filename)
86{
87 struct GNUNET_MESSENGER_Member *member = cls;
88
89 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
90 {
91 char *directory;
92
93 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
94
95 load_member_session(member, directory);
96 GNUNET_free (directory);
97 }
98
99 return GNUNET_OK;
100}
101
102void
103load_member (struct GNUNET_MESSENGER_MemberStore *store,
104 const char *directory)
105{
106 GNUNET_assert ((store) && (directory));
107
108 char *config_file;
109 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
110
111 struct GNUNET_MESSENGER_Member *member = NULL;
112
113 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
114 goto free_config;
115
116 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load member configuration: %s\n", config_file);
117
118 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
119
120 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
121 {
122 struct GNUNET_ShortHashCode id;
123
124 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
125 goto destroy_config;
126
127 member = add_store_member(store, &id);
128 }
129
130destroy_config:
131
132 GNUNET_CONFIGURATION_destroy (cfg);
133
134free_config:
135 GNUNET_free(config_file);
136
137 if (!member)
138 return;
139
140 char *scan_dir;
141 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
142
143 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
144 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
145
146 GNUNET_free(scan_dir);
147}
148
149static int
150iterate_load_next_session (void *cls,
151 const struct GNUNET_HashCode *key,
152 void *value)
153{
154 const char* sessions_directory = cls;
155
156 char* load_dir;
157 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
158
159 struct GNUNET_MESSENGER_MemberSession *session = value;
160
161 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
162 load_member_session_next (session, load_dir);
163
164 GNUNET_free (load_dir);
165 return GNUNET_YES;
166}
167
168void
169load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member,
170 const char *directory)
171{
172 GNUNET_assert ((member) && (directory));
173
174 char* load_dir;
175 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
176
177 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
178
179 GNUNET_free(load_dir);
180}
181
182static int
183iterate_save_session (void *cls,
184 const struct GNUNET_HashCode *key,
185 void *value)
186{
187 const char* sessions_directory = cls;
188
189 char* save_dir;
190 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
191
192 struct GNUNET_MESSENGER_MemberSession *session = value;
193
194 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
195 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
196 save_member_session (session, save_dir);
197
198 GNUNET_free (save_dir);
199 return GNUNET_YES;
200}
201
202void
203save_member (struct GNUNET_MESSENGER_Member *member,
204 const char *directory)
205{
206 GNUNET_assert ((member) && (directory));
207
208 char *config_file;
209 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
210
211 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save member configuration: %s\n", config_file);
212
213 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
214
215 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
216
217 if (id_data)
218 {
219 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
220
221 GNUNET_free(id_data);
222 }
223
224 GNUNET_CONFIGURATION_write (cfg, config_file);
225 GNUNET_CONFIGURATION_destroy (cfg);
226
227 GNUNET_free(config_file);
228
229 char* save_dir;
230 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
231
232 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
233 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
234 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
235
236 GNUNET_free(save_dir);
237}
238
239static void
240sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session,
241 struct GNUNET_MESSENGER_MemberSession *next)
242{
243 GNUNET_assert((session) && (next));
244
245 if (session == next)
246 return;
247
248 if (next->next)
249 sync_session_contact_from_next (session, next->next);
250 else
251 session->contact = next->contact;
252}
253
254static int
255iterate_sync_session_contact (void *cls,
256 const struct GNUNET_HashCode *key,
257 void *value)
258{
259 struct GNUNET_MESSENGER_MemberSession *session = value;
260
261 if (session->next)
262 sync_session_contact_from_next (session, session->next);
263
264 return GNUNET_YES;
265}
266
267void
268sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
269{
270 GNUNET_assert ((member) && (member->sessions));
271
272 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
273}
274
275struct GNUNET_MESSENGER_MemberSession*
276get_member_session (const struct GNUNET_MESSENGER_Member *member,
277 const struct GNUNET_IDENTITY_PublicKey *public_key)
278{
279 GNUNET_assert ((member) && (public_key));
280
281 struct GNUNET_HashCode hash;
282 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
283
284 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
285}
286
287struct GNUNET_MESSENGER_ClosureSearchSession {
288 const struct GNUNET_MESSENGER_Message *message;
289 const struct GNUNET_HashCode *hash;
290
291 struct GNUNET_MESSENGER_MemberSession *match;
292};
293
294static int
295iterate_search_session (void *cls,
296 const struct GNUNET_HashCode *key,
297 void *value)
298{
299 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
300 struct GNUNET_MESSENGER_MemberSession *session = value;
301
302 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
303 return GNUNET_YES;
304
305 search->match = session;
306 return GNUNET_NO;
307}
308
309static struct GNUNET_MESSENGER_MemberSession*
310try_member_session (struct GNUNET_MESSENGER_Member *member,
311 const struct GNUNET_IDENTITY_PublicKey *public_key)
312{
313 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
314
315 if (session)
316 return session;
317
318 session = create_member_session(member, public_key);
319
320 if (session)
321 add_member_session(member, session);
322
323 return session;
324}
325
326struct GNUNET_MESSENGER_MemberSession*
327get_member_session_of (struct GNUNET_MESSENGER_Member *member,
328 const struct GNUNET_MESSENGER_Message *message,
329 const struct GNUNET_HashCode *hash)
330{
331 GNUNET_assert ((member) && (message) && (hash) &&
332 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
333
334 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
335 return try_member_session(member, &(message->body.info.host_key));
336 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
337 return try_member_session(member, &(message->body.join.key));
338
339 struct GNUNET_MESSENGER_ClosureSearchSession search;
340
341 search.message = message;
342 search.hash = hash;
343
344 search.match = NULL;
345 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
346
347 return search.match;
348}
349
350void
351add_member_session (struct GNUNET_MESSENGER_Member *member,
352 struct GNUNET_MESSENGER_MemberSession *session)
353{
354 if (!session)
355 return;
356
357 GNUNET_assert((member) && (session->member == member));
358
359 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
360
361 struct GNUNET_HashCode hash;
362 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
363
364 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
365 member->sessions, &hash, session,
366 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
367 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
368 GNUNET_h2s(&hash));
369}
370
371void
372remove_member_session (struct GNUNET_MESSENGER_Member *member,
373 struct GNUNET_MESSENGER_MemberSession *session)
374{
375 GNUNET_assert ((member) && (session) && (session->member == member));
376
377 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
378
379 struct GNUNET_HashCode hash;
380 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
381
382 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
383 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
384 GNUNET_h2s(&hash));
385}
386
387struct GNUNET_MESSENGER_ClosureIterateSessions {
388 GNUNET_MESSENGER_MemberIteratorCallback it;
389 void *cls;
390};
391
392static int
393iterate_member_sessions_it (void *cls,
394 const struct GNUNET_HashCode *key,
395 void *value)
396{
397 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
398 struct GNUNET_MESSENGER_MemberSession *session = value;
399
400 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
401}
402
403int
404iterate_member_sessions (struct GNUNET_MESSENGER_Member *member,
405 GNUNET_MESSENGER_MemberIteratorCallback it,
406 void *cls)
407{
408 GNUNET_assert ((member) && (member->sessions) && (it));
409
410 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
411
412 iterate.it = it;
413 iterate.cls = cls;
414
415 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
416}
diff --git a/src/messenger/gnunet-service-messenger_member.h b/src/messenger/gnunet-service-messenger_member.h
deleted file mode 100644
index 0c5870fd3..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 519ac6f05..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ /dev/null
@@ -1,766 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021--2022 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 "platform.h"
27#include "gnunet-service-messenger_member_session.h"
28
29#include "gnunet-service-messenger_room.h"
30#include "gnunet-service-messenger_message_store.h"
31
32#include "messenger_api_contact_store.h"
33
34struct GNUNET_MESSENGER_MemberSession*
35create_member_session (struct GNUNET_MESSENGER_Member *member,
36 const struct GNUNET_IDENTITY_PublicKey *pubkey)
37{
38 if ((!member) || (!pubkey) || (!(member->store)))
39 return NULL;
40
41 struct GNUNET_MESSENGER_MemberSession *session = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
42 session->member = member;
43
44 GNUNET_memcpy(&(session->public_key), pubkey, sizeof(session->public_key));
45
46 get_context_from_member (
47 get_member_session_key (session),
48 get_member_session_id (session),
49 &(session->context)
50 );
51
52 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
53
54 session->contact = get_store_contact(
55 store,
56 get_member_session_context (session),
57 get_member_session_public_key (session)
58 );
59
60 if (!(session->contact))
61 {
62 GNUNET_free(session);
63 return NULL;
64 }
65
66 increase_contact_rc (session->contact);
67
68 session->history = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
69
70 init_list_messages(&(session->messages));
71
72 session->prev = NULL;
73 session->next = NULL;
74
75 session->start = GNUNET_TIME_absolute_get();
76
77 session->closed = GNUNET_NO;
78 session->completed = GNUNET_NO;
79
80 return session;
81}
82
83static void
84check_member_session_completion (struct GNUNET_MESSENGER_MemberSession *session)
85{
86 GNUNET_assert (session);
87
88 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Check session history (%s) for completion.\n",
89 GNUNET_sh2s(get_member_session_id(session)));
90
91 if (!session->messages.tail)
92 {
93 session->completed = GNUNET_YES;
94 goto completion;
95 }
96
97 const struct GNUNET_HashCode* start = &(session->messages.head->hash);
98 const struct GNUNET_HashCode* end = &(session->messages.tail->hash);
99
100 struct GNUNET_MESSENGER_ListMessages level;
101 init_list_messages(&level);
102
103 add_to_list_messages(&level, end);
104
105 struct GNUNET_MESSENGER_MessageStore *store = get_srv_room_message_store(session->member->store->room);
106
107 struct GNUNET_MESSENGER_ListMessages list;
108 init_list_messages(&list);
109
110 while (level.head)
111 {
112 struct GNUNET_MESSENGER_ListMessage *element;
113
114 for (element = level.head; element; element = element->next)
115 {
116 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
117 store, &(element->hash), GNUNET_NO
118 );
119
120 if (!link)
121 continue;
122
123 add_to_list_messages(&list, &(link->first));
124
125 if (GNUNET_YES == link->multiple)
126 add_to_list_messages(&list, &(link->second));
127 }
128
129 clear_list_messages(&level);
130
131 for (element = list.head; element; element = element->next)
132 if (GNUNET_YES == check_member_session_history(session, &(element->hash), GNUNET_YES))
133 break;
134
135 if (element)
136 if (0 != GNUNET_CRYPTO_hash_cmp(&(element->hash), start))
137 add_to_list_messages(&level, &(element->hash));
138 else
139 session->completed = GNUNET_YES;
140 else
141 copy_list_messages(&level, &list);
142
143 clear_list_messages(&list);
144 }
145
146completion:
147 if (GNUNET_YES == is_member_session_completed(session))
148 {
149 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Completed session history (%s)\n",
150 GNUNET_sh2s(get_member_session_id(session)));
151
152 GNUNET_CONTAINER_multihashmap_clear (session->history);
153
154 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
155
156 if ((session->contact) && (GNUNET_YES == decrease_contact_rc (session->contact)))
157 remove_store_contact (
158 store,
159 session->contact,
160 get_member_session_context(session)
161 );
162
163 session->contact = NULL;
164 }
165}
166
167static int
168iterate_copy_history (void *cls,
169 const struct GNUNET_HashCode *key,
170 void *value)
171{
172 struct GNUNET_MESSENGER_MemberSession *next = cls;
173
174 GNUNET_CONTAINER_multihashmap_put(next->history, key, (value? next : NULL),
175 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
176
177 return GNUNET_YES;
178}
179
180struct GNUNET_MESSENGER_MemberSession*
181switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
182 const struct GNUNET_MESSENGER_Message *message,
183 const struct GNUNET_HashCode *hash)
184{
185 if ((!session) || (!message) || (!hash))
186 return NULL;
187
188 GNUNET_assert((GNUNET_MESSENGER_KIND_ID == message->header.kind) ||
189 (GNUNET_MESSENGER_KIND_KEY == message->header.kind));
190
191 struct GNUNET_MESSENGER_MemberSession *next = GNUNET_new(struct GNUNET_MESSENGER_MemberSession);
192
193 if (GNUNET_MESSENGER_KIND_ID == message->header.kind)
194 next->member = add_store_member(session->member->store, &(message->body.id.id));
195 else
196 next->member = session->member;
197
198 if (GNUNET_MESSENGER_KIND_KEY == message->header.kind)
199 GNUNET_memcpy(&(next->public_key), &(message->body.key.key), sizeof(next->public_key));
200 else
201 GNUNET_memcpy(&(next->public_key), get_member_session_public_key(session), sizeof(next->public_key));
202
203 get_context_from_member (
204 get_member_session_key (next),
205 get_member_session_id (next),
206 &(next->context)
207 );
208
209 update_store_contact(
210 get_member_contact_store(next->member->store),
211 get_member_session_contact(session),
212 get_member_session_context(session),
213 get_member_session_context(next),
214 get_member_session_public_key(next)
215 );
216
217 next->contact = get_member_session_contact(session);
218
219 if (!(next->contact))
220 {
221 GNUNET_free(next);
222 return NULL;
223 }
224
225 increase_contact_rc (next->contact);
226
227 next->history = GNUNET_CONTAINER_multihashmap_create(
228 GNUNET_CONTAINER_multihashmap_size(session->history), GNUNET_NO
229 );
230
231 GNUNET_CONTAINER_multihashmap_iterate(session->history, iterate_copy_history, next);
232
233 init_list_messages(&(next->messages));
234 copy_list_messages(&(next->messages), &(session->messages));
235
236 session->next = next;
237 next->prev = session;
238 next->next = NULL;
239
240 next->start = GNUNET_TIME_absolute_get();
241
242 session->closed = GNUNET_YES;
243 next->closed = GNUNET_NO;
244 next->completed = GNUNET_NO;
245
246 check_member_session_completion (session);
247
248 return next;
249}
250
251void
252destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session)
253{
254 GNUNET_assert (session);
255
256 GNUNET_CONTAINER_multihashmap_destroy (session->history);
257
258 clear_list_messages (&(session->messages));
259
260 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact (session);
261
262 if ((contact) && (GNUNET_YES == decrease_contact_rc (contact)))
263 remove_store_contact (
264 get_member_contact_store(session->member->store),
265 contact,
266 get_member_session_context(session)
267 );
268
269 GNUNET_free(session);
270}
271
272int
273reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
274 const struct GNUNET_HashCode *hash)
275{
276 GNUNET_assert ((session) && (hash));
277
278 struct GNUNET_MESSENGER_ContactStore *store = get_member_contact_store(session->member->store);
279 struct GNUNET_MESSENGER_Contact *contact = get_store_contact(
280 store,
281 get_member_session_context (session),
282 get_member_session_public_key (session)
283 );
284
285 if (!contact)
286 return GNUNET_SYSERR;
287
288 if (contact == session->contact)
289 goto clear_messages;
290
291 session->contact = contact;
292 increase_contact_rc (session->contact);
293
294clear_messages:
295 clear_list_messages(&(session->messages));
296 add_to_list_messages(&(session->messages), hash);
297
298 session->next = NULL;
299 session->closed = GNUNET_NO;
300 session->completed = GNUNET_NO;
301
302 return GNUNET_OK;
303}
304
305void
306close_member_session (struct GNUNET_MESSENGER_MemberSession* session)
307{
308 GNUNET_assert (session);
309
310 session->closed = GNUNET_YES;
311 check_member_session_completion (session);
312}
313
314int
315is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session)
316{
317 GNUNET_assert(session);
318
319 return session->closed;
320}
321
322int
323is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session)
324{
325 GNUNET_assert(session);
326
327 return session->completed;
328}
329
330struct GNUNET_TIME_Absolute
331get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session)
332{
333 GNUNET_assert(session);
334
335 if (session->prev)
336 return get_member_session_start(session->prev);
337
338 return session->start;
339}
340
341const struct GNUNET_HashCode*
342get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session)
343{
344 GNUNET_assert((session) && (session->member));
345
346 return get_member_store_key(session->member->store);
347}
348
349const struct GNUNET_ShortHashCode*
350get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session)
351{
352 GNUNET_assert(session);
353
354 return get_member_id(session->member);
355}
356
357const struct GNUNET_IDENTITY_PublicKey*
358get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session)
359{
360 GNUNET_assert(session);
361
362 return &(session->public_key);
363}
364
365const struct GNUNET_HashCode*
366get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session)
367{
368 GNUNET_assert(session);
369
370 return &(session->context);
371}
372
373struct GNUNET_MESSENGER_Contact*
374get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session)
375{
376 GNUNET_assert (session);
377
378 return session->contact;
379}
380
381int verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
382 const struct GNUNET_MESSENGER_Message *message,
383 const struct GNUNET_HashCode *hash)
384{
385 GNUNET_assert((session) && (message) && (hash));
386
387 if (GNUNET_YES == is_member_session_completed(session))
388 return GNUNET_SYSERR;
389
390 if (0 != GNUNET_memcmp(get_member_session_id(session), &(message->header.sender_id)))
391 return GNUNET_SYSERR;
392
393 return verify_message(message, hash, get_member_session_public_key(session));
394}
395
396int
397check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
398 const struct GNUNET_HashCode *hash, int ownership)
399{
400 GNUNET_assert((session) && (hash));
401
402 if (GNUNET_YES == ownership)
403 return (NULL != GNUNET_CONTAINER_multihashmap_get(session->history, hash)? GNUNET_YES : GNUNET_NO);
404 else
405 return GNUNET_CONTAINER_multihashmap_contains(session->history, hash);
406}
407
408static void
409update_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
410 const struct GNUNET_HashCode *hash, int ownership)
411{
412 GNUNET_assert ((session) && (hash));
413
414 if ((GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(session->history, hash, (GNUNET_YES == ownership? session : NULL),
415 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) && (session->next))
416 update_member_chain_history (session->next, hash, ownership);
417}
418
419void
420update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
421 const struct GNUNET_MESSENGER_Message *message,
422 const struct GNUNET_HashCode *hash)
423{
424 GNUNET_assert((session) && (message) && (hash));
425
426 if (GNUNET_YES == is_member_session_completed(session))
427 return;
428
429 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Updating sessions history (%s) += (%s)\n",
430 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
431
432 if (GNUNET_OK == verify_member_session_as_sender (session, message, hash))
433 {
434 if (GNUNET_YES == is_message_session_bound (message))
435 add_to_list_messages(&(session->messages), hash);
436
437 update_member_chain_history (session, hash, GNUNET_YES);
438 }
439 else
440 update_member_chain_history (session, hash, GNUNET_NO);
441
442 if (GNUNET_YES == session->closed)
443 check_member_session_completion(session);
444}
445
446static void
447clear_member_chain_history (struct GNUNET_MESSENGER_MemberSession *session,
448 const struct GNUNET_HashCode *hash)
449{
450 GNUNET_assert ((session) && (hash));
451
452 if ((0 < GNUNET_CONTAINER_multihashmap_remove_all(session->history, hash)) && (session->next))
453 clear_member_session_history(session->next, hash);
454}
455
456void
457clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
458 const struct GNUNET_HashCode *hash)
459{
460 GNUNET_assert((session) && (hash));
461
462 clear_member_chain_history (session, hash);
463}
464
465struct GNUNET_MESSENGER_MemberSessionHistoryEntry
466{
467 struct GNUNET_HashCode hash;
468 unsigned char ownership;
469};
470
471static void
472load_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
473 const char *path)
474{
475 GNUNET_assert((session) && (path));
476
477 if (GNUNET_YES != GNUNET_DISK_file_test (path))
478 return;
479
480 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
481
482 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
483 path, GNUNET_DISK_OPEN_READ, permission
484 );
485
486 if (!handle)
487 return;
488
489 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
490
491 struct GNUNET_MESSENGER_MemberSessionHistoryEntry entry;
492 ssize_t len;
493
494 int status;
495
496 do {
497 len = GNUNET_DISK_file_read(handle, &(entry.hash), sizeof(entry.hash));
498
499 if (len != sizeof(entry.hash))
500 break;
501
502 len = GNUNET_DISK_file_read(handle, &(entry.ownership), sizeof(entry.ownership));
503
504 if (len != sizeof(entry.ownership))
505 break;
506
507 status = GNUNET_CONTAINER_multihashmap_put(session->history, &(entry.hash), (entry.ownership? session : NULL),
508 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
509 } while (status == GNUNET_OK);
510
511 GNUNET_DISK_file_close(handle);
512}
513
514void
515load_member_session (struct GNUNET_MESSENGER_Member *member,
516 const char *directory)
517{
518 GNUNET_assert ((member) && (directory));
519
520 char *config_file;
521 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
522
523 struct GNUNET_MESSENGER_MemberSession *session = NULL;
524
525 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
526 goto free_config;
527
528 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load session configuration of member: %s\n", config_file);
529
530 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
531
532 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
533 {
534 char *key_data;
535
536 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "key", &key_data))
537 goto destroy_config;
538
539 struct GNUNET_IDENTITY_PublicKey key;
540
541 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &key);
542
543 GNUNET_free(key_data);
544
545 if (GNUNET_OK != key_return)
546 goto destroy_config;
547
548 session = create_member_session(member, &key);
549
550 unsigned long long numeric_value;
551
552 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "start", &numeric_value))
553 session->start.abs_value_us = numeric_value;
554
555 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "closed", &numeric_value))
556 session->closed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
557
558 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number(cfg, "session", "completed", &numeric_value))
559 session->completed = (GNUNET_YES == numeric_value? GNUNET_YES : GNUNET_NO);
560 }
561
562destroy_config:
563 GNUNET_CONFIGURATION_destroy (cfg);
564
565free_config:
566 GNUNET_free(config_file);
567
568 if (!session)
569 return;
570
571 char *history_file;
572 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
573
574 load_member_session_history (session, history_file);
575 GNUNET_free(history_file);
576
577 char *messages_file;
578 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
579
580 load_list_messages(&(session->messages), messages_file);
581 GNUNET_free(messages_file);
582
583 add_member_session(member, session);
584}
585
586static struct GNUNET_MESSENGER_MemberSession*
587get_cycle_safe_next_session (struct GNUNET_MESSENGER_MemberSession *session,
588 struct GNUNET_MESSENGER_MemberSession *next)
589{
590 if (!next)
591 return NULL;
592
593 struct GNUNET_MESSENGER_MemberSession *check = next;
594
595 do {
596 if (check == session)
597 return NULL;
598
599 check = check->next;
600 } while (check);
601
602 return next;
603}
604
605void
606load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session,
607 const char *directory)
608{
609 GNUNET_assert ((session) && (directory));
610
611 char *config_file;
612 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
613
614 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
615 goto free_config;
616
617 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load next session configuration of member: %s\n", config_file);
618
619 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
620
621 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
622 {
623 char *key_data;
624
625 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg, "session", "next_key", &key_data))
626 goto destroy_config;
627
628 struct GNUNET_IDENTITY_PublicKey next_key;
629
630 enum GNUNET_GenericReturnValue key_return = GNUNET_IDENTITY_public_key_from_string(key_data, &next_key);
631
632 GNUNET_free(key_data);
633
634 if (GNUNET_OK != key_return)
635 goto destroy_config;
636
637 struct GNUNET_ShortHashCode next_id;
638
639 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "session", "next_id", &next_id, sizeof(next_id)))
640 goto destroy_config;
641
642 struct GNUNET_MESSENGER_Member *member = get_store_member(session->member->store, &next_id);
643
644 session->next = get_cycle_safe_next_session(
645 session, member? get_member_session (member, &next_key) : NULL
646 );
647
648 if (session->next)
649 session->next->prev = session;
650 }
651
652destroy_config:
653 GNUNET_CONFIGURATION_destroy (cfg);
654
655free_config:
656 GNUNET_free(config_file);
657}
658
659static int
660iterate_save_member_session_history_hentries (void *cls,
661 const struct GNUNET_HashCode *key,
662 void *value)
663{
664 struct GNUNET_DISK_FileHandle *handle = cls;
665 unsigned char ownership = value? GNUNET_YES : GNUNET_NO;
666
667 GNUNET_DISK_file_write(handle, key, sizeof(*key));
668 GNUNET_DISK_file_write(handle, &ownership, sizeof(ownership));
669
670 return GNUNET_YES;
671}
672
673static void
674save_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
675 const char *path)
676{
677 GNUNET_assert((session) && (path));
678
679 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
680
681 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
682 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
683 );
684
685 if (!handle)
686 return;
687
688 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
689
690 GNUNET_CONTAINER_multihashmap_iterate(
691 session->history,
692 iterate_save_member_session_history_hentries,
693 handle
694 );
695
696 GNUNET_DISK_file_sync(handle);
697 GNUNET_DISK_file_close(handle);
698}
699
700void
701save_member_session (struct GNUNET_MESSENGER_MemberSession *session,
702 const char *directory)
703{
704 GNUNET_assert ((session) && (directory));
705
706 char *config_file;
707 GNUNET_asprintf (&config_file, "%s%s", directory, "session.cfg");
708
709 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save session configuration of member: %s\n", config_file);
710
711 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
712
713 char *key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session));
714
715 if (key_data)
716 {
717 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "key", key_data);
718
719 GNUNET_free(key_data);
720 }
721
722 if (session->next)
723 {
724 const struct GNUNET_ShortHashCode *next_id = get_member_session_id(session->next);
725
726 char *next_id_data = GNUNET_STRINGS_data_to_string_alloc (next_id, sizeof(*next_id));
727
728 if (next_id_data)
729 {
730 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_id", next_id_data);
731
732 GNUNET_free(next_id_data);
733 }
734
735 key_data = GNUNET_IDENTITY_public_key_to_string(get_member_session_public_key(session->next));
736
737 if (key_data)
738 {
739 GNUNET_CONFIGURATION_set_value_string (cfg, "session", "next_key", key_data);
740
741 GNUNET_free(key_data);
742 }
743 }
744
745 GNUNET_CONFIGURATION_set_value_number(cfg, "session", "start", session->start.abs_value_us);
746
747 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "closed", session->closed);
748 GNUNET_CONFIGURATION_set_value_number (cfg, "session", "completed", session->completed);
749
750 GNUNET_CONFIGURATION_write (cfg, config_file);
751 GNUNET_CONFIGURATION_destroy (cfg);
752
753 GNUNET_free(config_file);
754
755 char *history_file;
756 GNUNET_asprintf (&history_file, "%s%s", directory, "history.map");
757
758 save_member_session_history (session, history_file);
759 GNUNET_free(history_file);
760
761 char *messages_file;
762 GNUNET_asprintf (&messages_file, "%s%s", directory, "messages.list");
763
764 save_list_messages(&(session->messages), messages_file);
765 GNUNET_free(messages_file);
766}
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 9b4065d05..000000000
--- a/src/messenger/gnunet-service-messenger_member_session.h
+++ /dev/null
@@ -1,291 +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_util_lib.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_time_lib.h"
33
34#include "gnunet-service-messenger_member.h"
35
36#include "messenger_api_contact.h"
37
38struct GNUNET_MESSENGER_MemberSession {
39 struct GNUNET_MESSENGER_Member *member;
40
41 struct GNUNET_IDENTITY_PublicKey public_key;
42 struct GNUNET_HashCode context;
43
44 struct GNUNET_MESSENGER_Contact *contact;
45
46 struct GNUNET_CONTAINER_MultiHashMap *history;
47 struct GNUNET_MESSENGER_ListMessages messages;
48
49 struct GNUNET_MESSENGER_MemberSession* prev;
50 struct GNUNET_MESSENGER_MemberSession* next;
51
52 struct GNUNET_TIME_Absolute start;
53
54 int closed;
55 int completed;
56};
57
58/**
59 * Creates and allocates a new member session of a <i>member</i> with a given
60 * public key.
61 *
62 * If the creation fails, NULL gets returned.
63 *
64 * @param[in,out] member Member
65 * @param[in] pubkey Public key of EGO
66 * @return New member session
67 */
68struct GNUNET_MESSENGER_MemberSession*
69create_member_session (struct GNUNET_MESSENGER_Member *member,
70 const struct GNUNET_IDENTITY_PublicKey *pubkey);
71
72/**
73 * Creates and allocates a new member session closing and replacing a given
74 * other <i>session</i> of the same member. The new session could have significant
75 * changes to the members public key or its member id depending on the used
76 * <i>message</i> to switch session. The new session will be linked to the old
77 * one.
78 *
79 * @param[in,out] session Old member session
80 * @param[in] message Message
81 * @param[in] hash Hash of message
82 * @return New member session
83 */
84struct GNUNET_MESSENGER_MemberSession*
85switch_member_session (struct GNUNET_MESSENGER_MemberSession *session,
86 const struct GNUNET_MESSENGER_Message *message,
87 const struct GNUNET_HashCode *hash);
88
89/**
90 * Destroys a member session and frees its memory fully.
91 *
92 * @param[in,out] session Member session
93 */
94void
95destroy_member_session(struct GNUNET_MESSENGER_MemberSession* session);
96
97/**
98 * Resets a given member <i>session</i> which re-opens a member
99 * session for new usage. Every connection to other sessions will be
100 * be dropped. The member sessions messages will be cleared but old
101 * history from uncompleted sessions however can be reused!
102 *
103 * @param[in,out] session Member session
104 * @param[in] hash Hash of initial message (JOIN message!)
105 * @return #GNUNET_OK on success, #GNUNET_SYSERR otherwise
106 */
107int
108reset_member_session (struct GNUNET_MESSENGER_MemberSession* session,
109 const struct GNUNET_HashCode *hash);
110
111/**
112 * Closes a given member <i>session</i> which opens the request
113 * for completion of the given member session.
114 *
115 * Closing a session may complete a session and can't be used without
116 * a reset! ( @see #reset_member_session() )
117 *
118 * @param[in,out] session Member session
119 */
120void
121close_member_session (struct GNUNET_MESSENGER_MemberSession* session);
122
123/**
124 * Returns if the given member <i>session</i> has been closed.
125 *
126 * @param[in] session Member session
127 * @return #GNUNET_YES or #GNUNET_NO
128 */
129int
130is_member_session_closed (const struct GNUNET_MESSENGER_MemberSession* session);
131
132/**
133 * Returns if the given member <i>session</i> has been completed.
134 *
135 * A completed member session can't verify any message as its own and
136 * it won't add any message to its history.
137 *
138 * @param[in] session Member session
139 * @return #GNUNET_YES or #GNUNET_NO
140 */
141int
142is_member_session_completed (const struct GNUNET_MESSENGER_MemberSession* session);
143
144/**
145 * Returns the timestamp of the member <i>session</i>'s start.
146 *
147 * @param[in] session Member session
148 * @return Absolute timestamp
149 */
150struct GNUNET_TIME_Absolute
151get_member_session_start (const struct GNUNET_MESSENGER_MemberSession* session);
152
153/**
154 * Returns the key of the room a given member <i>session</i> belongs to.
155 *
156 * @param[in] session Member session
157 * @return Key of room
158 */
159const struct GNUNET_HashCode*
160get_member_session_key (const struct GNUNET_MESSENGER_MemberSession* session);
161
162/**
163 * Returns the member id of a given member <i>session</i>.
164 *
165 * @param[in] session Member session
166 * @return Member id
167 */
168const struct GNUNET_ShortHashCode*
169get_member_session_id (const struct GNUNET_MESSENGER_MemberSession* session);
170
171/**
172 * Returns the public key from an EGO of a given member <i>session</i>.
173 *
174 * @param[in] session Member session
175 * @return Public key of EGO
176 */
177const struct GNUNET_IDENTITY_PublicKey*
178get_member_session_public_key (const struct GNUNET_MESSENGER_MemberSession* session);
179
180/**
181 * Returns the member context of a given member <i>session</i>.
182 *
183 * @param[in] session Member session
184 * @return Member context as hash
185 */
186const struct GNUNET_HashCode*
187get_member_session_context (const struct GNUNET_MESSENGER_MemberSession* session);
188
189/**
190 * Returns the contact which is connected to a given member <i>session</i>.
191 *
192 * @param[in] session Member session
193 * @return Contact
194 */
195struct GNUNET_MESSENGER_Contact*
196get_member_session_contact (struct GNUNET_MESSENGER_MemberSession* session);
197
198/**
199 * Verifies a given member <i>session</i> as sender of a selected <i>message</i> and
200 * its <i>hash</i>. The function returns #GNUNET_OK if the message session is verified
201 * as sender, otherwise #GNUNET_SYSERR.
202 *
203 * @see #is_member_session_completed() for verification.
204 *
205 * @param[in] session Member session
206 * @param[in] message Message
207 * @param[in] hash Hash of message
208 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
209 */
210int
211verify_member_session_as_sender (const struct GNUNET_MESSENGER_MemberSession *session,
212 const struct GNUNET_MESSENGER_Message *message,
213 const struct GNUNET_HashCode *hash);
214
215/**
216 * Checks the history of a <i>session</i> for a specific message which is identified
217 * by its <i>hash</i> and if the <i>ownership</i> flag is set, if the message is
218 * owned by the sessions contact.
219 *
220 * @param[in] session Member session
221 * @param[in] hash Hash of message
222 * @param[in] ownership Ownership flag
223 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
224 */
225int
226check_member_session_history (const struct GNUNET_MESSENGER_MemberSession *session,
227 const struct GNUNET_HashCode *hash,
228 int ownership);
229
230/**
231 * Adds a given <i>message</i> to the history of a <i>session</i> using the messages
232 * <i>hash</i>. The ownership will be set automatically.
233 *
234 * @see #is_member_session_completed() for updating a history.
235 *
236 * @param[in,out] session Member session
237 * @param[in] message Message
238 * @param[in] hash Hash of message
239 */
240void
241update_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
242 const struct GNUNET_MESSENGER_Message *message,
243 const struct GNUNET_HashCode *hash);
244
245/**
246 * Removes a message from the history of a <i>session</i> using the messages
247 * <i>hash</i>.
248 *
249 * @param[in,out] session Member session
250 * @param[in] hash Hash of message
251 */
252void
253clear_member_session_history (struct GNUNET_MESSENGER_MemberSession *session,
254 const struct GNUNET_HashCode *hash);
255
256/**
257 * Loads data from a <i>directory</i> into a new allocated and created member
258 * session of a <i>member</i> if the required information can be read from the
259 * content of the given directory.
260 *
261 * @param[out] member Member
262 * @param[in] directory Path to a directory
263 */
264void
265load_member_session (struct GNUNET_MESSENGER_Member *member,
266 const char *directory);
267
268/**
269 * Loads the connection from one <i>session</i> to another through the
270 * next attribute. Necessary information will be loaded from a configuration
271 * file inside of a given <i>directory</i>.
272 *
273 * @param[in,out] session Member session
274 * @param[in] directory Path to a directory
275 */
276void
277load_member_session_next (struct GNUNET_MESSENGER_MemberSession *session,
278 const char *directory);
279
280/**
281 * Saves data from a member <i>session</i> into a <i>directory</i> which can be
282 * load to restore the member session completely.
283 *
284 * @param[in] session Member session
285 * @param[in] directory Path to a directory
286 */
287void
288save_member_session (struct GNUNET_MESSENGER_MemberSession *session,
289 const char *directory);
290
291#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 fc28babc4..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.c
+++ /dev/null
@@ -1,269 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_member_store.h"
28
29#include "gnunet-service-messenger_member.h"
30#include "gnunet-service-messenger_service.h"
31#include "gnunet-service-messenger_room.h"
32
33void
34init_member_store (struct GNUNET_MESSENGER_MemberStore *store,
35 struct GNUNET_MESSENGER_SrvRoom *room)
36{
37 GNUNET_assert ((store) && (room));
38
39 store->room = room;
40 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
41}
42
43static int
44iterate_destroy_members (void *cls,
45 const struct GNUNET_ShortHashCode *key,
46 void *value)
47{
48 struct GNUNET_MESSENGER_Member *member = value;
49 destroy_member(member);
50 return GNUNET_YES;
51}
52
53void
54clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
55{
56 GNUNET_assert ((store) && (store->members));
57
58 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
59 GNUNET_CONTAINER_multishortmap_destroy (store->members);
60}
61
62
63struct GNUNET_MESSENGER_ContactStore*
64get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
65{
66 GNUNET_assert ((store) && (store->room));
67
68 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
69
70 return get_service_contact_store(room->service);
71}
72
73const struct GNUNET_HashCode*
74get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
75{
76 GNUNET_assert (store);
77
78 return get_srv_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
79}
80
81static int
82callback_scan_for_members (void *cls,
83 const char *filename)
84{
85 struct GNUNET_MESSENGER_MemberStore *store = cls;
86
87 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
88 {
89 char *directory;
90
91 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
92
93 load_member(store, directory);
94
95 GNUNET_free(directory);
96 }
97
98 return GNUNET_OK;
99}
100
101static int
102iterate_load_next_member_sessions (void *cls,
103 const struct GNUNET_ShortHashCode *id,
104 void *value)
105{
106 const char *sync_dir = cls;
107
108 struct GNUNET_MESSENGER_Member *member = value;
109
110 if (!member)
111 return GNUNET_YES;
112
113 char *member_dir;
114 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
115
116 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
117 load_member_next_sessions (member, member_dir);
118
119 GNUNET_free(member_dir);
120 return GNUNET_YES;
121}
122
123static int
124iterate_sync_member_contacts (void *cls,
125 const struct GNUNET_ShortHashCode *id,
126 void *value)
127{
128 struct GNUNET_MESSENGER_Member *member = value;
129
130 if (!member)
131 return GNUNET_YES;
132
133 sync_member_contacts (member);
134 return GNUNET_YES;
135}
136
137void
138load_member_store (struct GNUNET_MESSENGER_MemberStore *store,
139 const char *directory)
140{
141 GNUNET_assert ((store) && (directory));
142
143 char *scan_dir;
144 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
145
146 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
147 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
148
149 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
150 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
151
152 GNUNET_free(scan_dir);
153}
154
155static int
156iterate_save_members (void *cls,
157 const struct GNUNET_ShortHashCode *id,
158 void *value)
159{
160 const char *save_dir = cls;
161
162 struct GNUNET_MESSENGER_Member *member = value;
163
164 if (!member)
165 return GNUNET_YES;
166
167 char *member_dir;
168 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
169
170 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
171 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
172 save_member(member, member_dir);
173
174 GNUNET_free(member_dir);
175 return GNUNET_YES;
176}
177
178void
179save_member_store (struct GNUNET_MESSENGER_MemberStore *store,
180 const char *directory)
181{
182 GNUNET_assert ((store) && (directory));
183
184 char* save_dir;
185 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
186
187 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
188 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
189 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
190
191 GNUNET_free(save_dir);
192}
193
194struct GNUNET_MESSENGER_Member*
195get_store_member (const struct GNUNET_MESSENGER_MemberStore *store,
196 const struct GNUNET_ShortHashCode *id)
197{
198 GNUNET_assert ((store) && (store->members) && (id));
199
200 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
201}
202
203struct GNUNET_MESSENGER_Member*
204get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
205 const struct GNUNET_MESSENGER_Message *message)
206{
207 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
208 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
209 return add_store_member(store, &(message->header.sender_id));
210 else
211 return get_store_member(store, &(message->header.sender_id));
212}
213
214struct GNUNET_MESSENGER_Member*
215add_store_member (struct GNUNET_MESSENGER_MemberStore *store,
216 const struct GNUNET_ShortHashCode *id)
217{
218 GNUNET_assert ((store) && (store->members));
219
220 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
221
222 if (member)
223 return member;
224
225 member = create_member(store, id);
226
227 if (!member)
228 return NULL;
229
230 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
231 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
232 {
233 destroy_member(member);
234 return NULL;
235 }
236
237 return member;
238}
239
240struct GNUNET_MESSENGER_ClosureIterateMembers {
241 GNUNET_MESSENGER_MemberIteratorCallback it;
242 void *cls;
243};
244
245static int
246iterate_store_members_it (void *cls,
247 const struct GNUNET_ShortHashCode *key,
248 void *value)
249{
250 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
251 struct GNUNET_MESSENGER_Member *member = value;
252
253 return iterate_member_sessions(member, iterate->it, iterate->cls);
254}
255
256int
257iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store,
258 GNUNET_MESSENGER_MemberIteratorCallback it,
259 void* cls)
260{
261 GNUNET_assert ((store) && (store->members) && (it));
262
263 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
264
265 iterate.it = it;
266 iterate.cls = cls;
267
268 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
269}
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 05b00f39a..000000000
--- a/src/messenger/gnunet-service-messenger_member_store.h
+++ /dev/null
@@ -1,157 +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_util_lib.h"
31#include "gnunet_identity_service.h"
32#include "messenger_api_message.h"
33
34struct GNUNET_MESSENGER_SrvRoom;
35
36struct GNUNET_MESSENGER_Member;
37struct GNUNET_MESSENGER_MemberSession;
38
39struct GNUNET_MESSENGER_MemberStore
40{
41 struct GNUNET_MESSENGER_SrvRoom *room;
42
43 struct GNUNET_CONTAINER_MultiShortmap *members;
44};
45
46typedef int (*GNUNET_MESSENGER_MemberIteratorCallback) (
47 void *cls,
48 const struct GNUNET_IDENTITY_PublicKey *public_key,
49 struct GNUNET_MESSENGER_MemberSession *session);
50
51/**
52 * Initializes a member <i>store</i> as fully empty connected to a <i>room</i>.
53 *
54 * @param[out] store Member store
55 * @param room Room
56 */
57void
58init_member_store (struct GNUNET_MESSENGER_MemberStore *store,
59 struct GNUNET_MESSENGER_SrvRoom *room);
60
61/**
62 * Clears a member <i>store</i>, wipes its content and deallocates its memory.
63 *
64 * @param[in,out] store Member store
65 */
66void
67clear_member_store (struct GNUNET_MESSENGER_MemberStore *store);
68
69/**
70 * Returns the used contact store of a given member <i>store</i>.
71 *
72 * @param[in,out] store Member store
73 * @return Contact store
74 */
75struct GNUNET_MESSENGER_ContactStore*
76get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store);
77
78/**
79 * Returns the shared secret you need to access a room of the <i>store</i>.
80 *
81 * @param[in] store Member store
82 * @return Shared secret
83 */
84const struct GNUNET_HashCode*
85get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store);
86
87/**
88 * Loads members from a directory into a member <i>store</i>.
89 *
90 * @param[out] store Member store
91 * @param[in] directory Path to a directory
92 */
93void
94load_member_store (struct GNUNET_MESSENGER_MemberStore *store,
95 const char *directory);
96
97/**
98 * Saves members from a member <i>store</i> into a directory.
99 *
100 * @param[in] store Member store
101 * @param[in] directory Path to a directory
102 */
103void
104save_member_store (struct GNUNET_MESSENGER_MemberStore *store,
105 const char *directory);
106
107/**
108 * Returns the member in a <i>store</i> identified by a given <i>id</i>. If the <i>store</i>
109 * does not contain a member with the given <i>id</i>, NULL gets returned.
110 *
111 * @param[in] store Member store
112 * @param[in] id Member id
113 * @return Member or NULL
114 */
115struct GNUNET_MESSENGER_Member*
116get_store_member (const struct GNUNET_MESSENGER_MemberStore *store,
117 const struct GNUNET_ShortHashCode *id);
118
119/**
120 * Returns the member of a <i>store</i> using a sender id of a given <i>message</i>.
121 * If the member does not provide a matching session, NULL gets returned.
122 *
123 * @param[in,out] store Member store
124 * @param[in] message Message
125 * @return Member or NULL
126 */
127struct GNUNET_MESSENGER_Member*
128get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
129 const struct GNUNET_MESSENGER_Message *message);
130
131/**
132 * Adds a member to a <i>store</i> under a specific <i>id</i> and returns it on success.
133 *
134 * @param[in,out] store Member store
135 * @param[in] id Member id
136 * @return Member or NULL
137 */
138struct GNUNET_MESSENGER_Member*
139add_store_member (struct GNUNET_MESSENGER_MemberStore *store,
140 const struct GNUNET_ShortHashCode *id);
141
142/**
143 * Iterate through all member sessions currently connected to the members of the given
144 * member <i>store</i> and call the provided iterator callback with a selected closure.
145 * The function will return the amount of members it iterated through.
146 *
147 * @param[in,out] store Member store
148 * @param[in] it Iterator callback
149 * @param[in,out] cls Closure
150 * @return Amount of members iterated through
151 */
152int
153iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store,
154 GNUNET_MESSENGER_MemberIteratorCallback it,
155 void* cls);
156
157#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 06b987657..000000000
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ /dev/null
@@ -1,154 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_message_handle.h"
28
29static void
30handle_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
31 const struct GNUNET_MESSENGER_Message *message,
32 const struct GNUNET_HashCode *hash)
33{
34 struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, message, hash);
35
36 if (next != session)
37 add_member_session(next->member, next);
38}
39
40void
41handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
42 struct GNUNET_MESSENGER_MemberSession *session,
43 const struct GNUNET_MESSENGER_Message *message,
44 const struct GNUNET_HashCode *hash)
45{
46 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
47 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_srv_room_key(room)));
48
49 if (GNUNET_OK != reset_member_session(session, hash))
50 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
51
52 solve_srv_room_member_collisions (
53 room,
54 &(message->body.join.key),
55 &(message->header.sender_id),
56 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
57 );
58}
59
60void
61handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
62 struct GNUNET_MESSENGER_MemberSession *session,
63 const struct GNUNET_MESSENGER_Message *message,
64 const struct GNUNET_HashCode *hash)
65{
66 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
67 GNUNET_sh2s (&(message->header.sender_id)), GNUNET_h2s(get_srv_room_key(room)));
68
69 close_member_session(session);
70}
71
72void
73handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
74 struct GNUNET_MESSENGER_MemberSession *session,
75 const struct GNUNET_MESSENGER_Message *message,
76 const struct GNUNET_HashCode *hash)
77{
78 struct GNUNET_MESSENGER_Contact *contact = get_member_session_contact(session);
79
80 if (!contact)
81 return;
82
83 set_contact_name (contact, message->body.name.name);
84}
85
86void
87handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
88 struct GNUNET_MESSENGER_MemberSession *session,
89 const struct GNUNET_MESSENGER_Message *message,
90 const struct GNUNET_HashCode *hash)
91{
92 handle_session_switch (session, message, hash);
93}
94
95void
96handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
97 struct GNUNET_MESSENGER_MemberSession *session,
98 const struct GNUNET_MESSENGER_Message *message,
99 const struct GNUNET_HashCode *hash)
100{
101 if (GNUNET_NO == contains_list_tunnels (&(room->basement), &(message->body.peer.peer)))
102 add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
103
104 if (room->peer_message)
105 rebuild_srv_room_basement_structure (room);
106}
107
108void
109handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
110 struct GNUNET_MESSENGER_MemberSession *session,
111 const struct GNUNET_MESSENGER_Message *message,
112 const struct GNUNET_HashCode *hash)
113{
114 handle_session_switch (session, message, hash);
115
116 solve_srv_room_member_collisions (
117 room,
118 get_member_session_public_key(session),
119 &(message->body.id.id),
120 GNUNET_TIME_absolute_ntoh(message->header.timestamp)
121 );
122}
123
124void
125handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
126 struct GNUNET_MESSENGER_MemberSession *session,
127 const struct GNUNET_MESSENGER_Message *message,
128 const struct GNUNET_HashCode *hash)
129{
130 struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels (&(room->basement), &(message->body.peer.peer), NULL);
131
132 if (!element)
133 return;
134
135 remove_from_list_tunnels (&(room->basement), element);
136
137 if (room->peer_message)
138 rebuild_srv_room_basement_structure (room);
139}
140
141void
142handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room,
143 struct GNUNET_MESSENGER_MemberSession *session,
144 const struct GNUNET_MESSENGER_Message *message,
145 const struct GNUNET_HashCode *hash)
146{
147 struct GNUNET_TIME_Relative delay = GNUNET_TIME_relative_ntoh (message->body.deletion.delay);
148 struct GNUNET_TIME_Absolute action = GNUNET_TIME_absolute_ntoh (message->header.timestamp);
149
150 action = GNUNET_TIME_absolute_add (action, delay);
151 delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), action);
152
153 delete_srv_room_message (room, session, &(message->body.deletion.hash), delay);
154}
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 0a97cd840..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_util_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 828e84d4f..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ /dev/null
@@ -1,242 +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 "platform.h"
27#include "gnunet-service-messenger_message_kind.h"
28
29#include "messenger_api_util.h"
30
31struct GNUNET_MESSENGER_Message*
32create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
33{
34 if (!ego)
35 return NULL;
36
37 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INFO);
38
39 if (!message)
40 return NULL;
41
42 GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
43
44 message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
45
46 return message;
47}
48
49struct GNUNET_MESSENGER_Message*
50create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
51{
52 if (!ego)
53 return NULL;
54
55 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_JOIN);
56
57 if (!message)
58 return NULL;
59
60 GNUNET_memcpy(&(message->body.join.key), &(ego->pub), sizeof(ego->pub));
61
62 return message;
63}
64
65struct GNUNET_MESSENGER_Message*
66create_message_leave ()
67{
68 return create_message (GNUNET_MESSENGER_KIND_LEAVE);
69}
70
71struct GNUNET_MESSENGER_Message*
72create_message_name (const char *name)
73{
74 if (!name)
75 return NULL;
76
77 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_NAME);
78
79 if (!message)
80 return NULL;
81
82 message->body.name.name = GNUNET_strdup(name);
83 return message;
84}
85
86struct GNUNET_MESSENGER_Message*
87create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
88{
89 if (!key)
90 return NULL;
91
92 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_KEY);
93
94 if (!message)
95 return NULL;
96
97 GNUNET_IDENTITY_key_get_public (key, &(message->body.key.key));
98 return message;
99}
100
101struct GNUNET_MESSENGER_Message*
102create_message_peer (const struct GNUNET_MESSENGER_Service *service)
103{
104 if (!service)
105 return NULL;
106
107 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_PEER);
108
109 if (!message)
110 return NULL;
111
112 if (GNUNET_OK == get_service_peer_identity (service, &(message->body.peer.peer)))
113 return message;
114 else
115 {
116 destroy_message (message);
117 return NULL;
118 }
119}
120
121struct GNUNET_MESSENGER_Message*
122create_message_id (const struct GNUNET_ShortHashCode *unique_id)
123{
124 if (!unique_id)
125 return NULL;
126
127 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_ID);
128
129 if (!message)
130 return NULL;
131
132 GNUNET_memcpy(&(message->body.id.id), unique_id, sizeof(struct GNUNET_ShortHashCode));
133
134 return message;
135}
136
137struct GNUNET_MESSENGER_Message*
138create_message_miss (const struct GNUNET_PeerIdentity *peer)
139{
140 if (!peer)
141 return NULL;
142
143 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MISS);
144
145 if (!message)
146 {
147 return NULL;
148 }
149
150 GNUNET_memcpy(&(message->body.miss.peer), peer, sizeof(struct GNUNET_PeerIdentity));
151
152 return message;
153}
154
155struct GNUNET_MESSENGER_Message*
156create_message_merge (const struct GNUNET_HashCode *previous)
157{
158 if (!previous)
159 return NULL;
160
161 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_MERGE);
162
163 if (!message)
164 return NULL;
165
166 GNUNET_memcpy(&(message->body.merge.previous), previous, sizeof(struct GNUNET_HashCode));
167
168 return message;
169}
170
171struct GNUNET_MESSENGER_Message*
172create_message_request (const struct GNUNET_HashCode *hash)
173{
174 if (!hash)
175 return NULL;
176
177 struct GNUNET_HashCode zero;
178 memset (&zero, 0, sizeof(zero));
179
180 if (0 == GNUNET_CRYPTO_hash_cmp (hash, &zero))
181 return NULL;
182
183 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_REQUEST);
184
185 if (!message)
186 return NULL;
187
188 GNUNET_memcpy(&(message->body.request.hash), hash, sizeof(struct GNUNET_HashCode));
189
190 return message;
191}
192
193struct GNUNET_MESSENGER_Message*
194create_message_invite (const struct GNUNET_PeerIdentity *door,
195 const struct GNUNET_HashCode *key)
196{
197 if ((!door) || (!key))
198 return NULL;
199
200 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_INVITE);
201
202 if (!message)
203 return NULL;
204
205 GNUNET_memcpy(&(message->body.invite.door), door, sizeof(struct GNUNET_PeerIdentity));
206 GNUNET_memcpy(&(message->body.invite.key), key, sizeof(struct GNUNET_HashCode));
207
208 return message;
209}
210
211struct GNUNET_MESSENGER_Message*
212create_message_text (const char *text)
213{
214 if (!text)
215 return NULL;
216
217 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_TEXT);
218
219 if (!message)
220 return NULL;
221
222 message->body.text.text = GNUNET_strdup(text);
223 return message;
224}
225
226struct GNUNET_MESSENGER_Message*
227create_message_delete (const struct GNUNET_HashCode *hash,
228 const struct GNUNET_TIME_Relative delay)
229{
230 if (!hash)
231 return NULL;
232
233 struct GNUNET_MESSENGER_Message *message = create_message (GNUNET_MESSENGER_KIND_DELETE);
234
235 if (!message)
236 return NULL;
237
238 GNUNET_memcpy(&(message->body.deletion.hash), hash, sizeof(struct GNUNET_HashCode));
239 message->body.deletion.delay = GNUNET_TIME_relative_hton (delay);
240
241 return message;
242}
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 102a70e33..000000000
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ /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 * @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_util_lib.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_time_lib.h"
33
34#include "messenger_api_message.h"
35#include "gnunet-service-messenger_service.h"
36#include "messenger_api_ego.h"
37
38/**
39 * Creates and allocates a new info message containing the hosts EGO public key and a newly generated unique member id.
40 * (all values are stored as copy)
41 *
42 * @param[in] ego EGO of the host
43 * @param[in] members Map of all assigned member ids
44 * @return New message
45 */
46struct GNUNET_MESSENGER_Message*
47create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
48
49/**
50 * Creates and allocates a new join message containing the clients EGO public key.
51 * (all values are stored as copy)
52 *
53 * @param[in] ego EGO of the client
54 * @return New message
55 */
56struct GNUNET_MESSENGER_Message*
57create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
58
59/**
60 * Creates and allocates a new leave message.
61 *
62 * @return New message
63 */
64struct GNUNET_MESSENGER_Message*
65create_message_leave ();
66
67/**
68 * Creates and allocates a new name message containing the <i>name</i> to change to.
69 * (all values are stored as copy)
70 *
71 * @param[in] name New name
72 * @return New message
73 */
74struct GNUNET_MESSENGER_Message*
75create_message_name (const char *name);
76
77/**
78 * Creates and allocates a new key message containing the public <i>key</i> to change to derived
79 * from its private counterpart. (all values are stored as copy)
80 *
81 * @param[in] key Private key of EGO
82 * @return New message
83 */
84struct GNUNET_MESSENGER_Message*
85create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
86
87/**
88 * Creates and allocates a new peer message containing a services peer identity.
89 * (all values are stored as copy)
90 *
91 * @param[in] service Service
92 * @return New message
93 */
94struct GNUNET_MESSENGER_Message*
95create_message_peer (const struct GNUNET_MESSENGER_Service *service);
96
97/**
98 * Creates and allocates a new id message containing the unique member id to change to.
99 * (all values are stored as copy)
100 *
101 * @param[in] unique_id Unique member id
102 * @return New message
103 */
104struct GNUNET_MESSENGER_Message*
105create_message_id (const struct GNUNET_ShortHashCode *unique_id);
106
107/**
108 * Creates and allocates a new miss message containing the missing <i>peer</i> identity.
109 * (all values are stored as copy)
110 *
111 * @param[in] peer Missing peer identity
112 * @return New message
113 */
114struct GNUNET_MESSENGER_Message*
115create_message_miss (const struct GNUNET_PeerIdentity *peer);
116
117/**
118 * Creates and allocates a new merge message containing the hash of a second <i>previous</i> message
119 * besides the regular previous message mentioned in a messages header.
120 * (all values are stored as copy)
121 *
122 * @param[in] previous Hash of message
123 * @return New message
124 */
125struct GNUNET_MESSENGER_Message*
126create_message_merge (const struct GNUNET_HashCode *previous);
127
128/**
129 * Creates and allocates a new request message containing the <i>hash</i> of a missing message.
130 * (all values are stored as copy)
131 *
132 * @param[in] hash Hash of message
133 * @return New message
134 */
135struct GNUNET_MESSENGER_Message*
136create_message_request (const struct GNUNET_HashCode *hash);
137
138/**
139 * Creates and allocates a new invite message containing the peer identity of an entrance peer
140 * to a room using a given <i>key</i> as shared secret for communication.
141 * (all values are stored as copy)
142 *
143 * @param[in] door Peer identity
144 * @param[in] key Shared secret of a room
145 * @return New message
146 */
147struct GNUNET_MESSENGER_Message*
148create_message_invite (const struct GNUNET_PeerIdentity *door,
149 const struct GNUNET_HashCode *key);
150
151/**
152 * Creates and allocates a new <i>text</i> message containing a string representing text.
153 * (all values are stored as copy)
154 *
155 * @param[in] text Text
156 * @return New message
157 */
158struct GNUNET_MESSENGER_Message*
159create_message_text (const char *text);
160
161/**
162 * Creates and allocates a new delete message containing the <i>hash</i> of a message to delete after a specific <i>delay</i>.
163 * (all values are stored as copy)
164 *
165 * @param[in] hash Hash of message
166 * @param[in] delay Delay of deletion
167 * @return New message
168 */
169struct GNUNET_MESSENGER_Message*
170create_message_delete (const struct GNUNET_HashCode *hash,
171 const struct GNUNET_TIME_Relative delay);
172
173#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 94202fdca..000000000
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ /dev/null
@@ -1,186 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_message_recv.h"
28
29#include "gnunet-service-messenger_operation.h"
30
31static void
32forward_about_members (struct GNUNET_MESSENGER_SrvRoom *room,
33 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
34 struct GNUNET_MESSENGER_MemberSession *session,
35 struct GNUNET_CONTAINER_MultiHashMap *map)
36{
37 if (session->prev)
38 forward_about_members (room, tunnel, session->prev, map);
39
40 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
41 struct GNUNET_MESSENGER_ListMessage *element;
42
43 for (element = session->messages.head; element; element = element->next)
44 {
45 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
46 continue;
47
48 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
49 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
50 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Forwarding of session message could be duplicated!\n");
51
52 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
53
54 if (message)
55 forward_tunnel_message(tunnel, message, &(element->hash));
56 }
57}
58
59static int
60iterate_forward_members (void *cls,
61 const struct GNUNET_IDENTITY_PublicKey *public_key,
62 struct GNUNET_MESSENGER_MemberSession *session)
63{
64 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
65
66 if (GNUNET_YES == is_member_session_completed(session))
67 return GNUNET_YES;
68
69 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
70
71 forward_about_members (tunnel->room, tunnel, session, map);
72
73 GNUNET_CONTAINER_multihashmap_destroy(map);
74 return GNUNET_YES;
75}
76
77int
78recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room,
79 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
80 const struct GNUNET_MESSENGER_Message *message,
81 const struct GNUNET_HashCode *hash)
82{
83 const uint32_t version = get_tunnel_messenger_version(tunnel);
84
85 if (GNUNET_OK != update_tunnel_messenger_version(tunnel, message->body.info.messenger_version))
86 {
87 disconnect_tunnel(tunnel);
88 return GNUNET_NO;
89 }
90
91 if (version == get_tunnel_messenger_version(tunnel))
92 return GNUNET_NO;
93
94 if (room->host)
95 {
96 const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(room->host);
97
98 send_tunnel_message (tunnel, room->host, create_message_info(ego));
99 }
100
101 struct GNUNET_PeerIdentity peer;
102 get_tunnel_peer_identity(tunnel, &peer);
103
104 if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
105 {
106 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
107
108 iterate_store_members(member_store, iterate_forward_members, tunnel);
109 }
110
111 check_srv_room_peer_status(room, tunnel);
112
113 return GNUNET_NO;
114}
115
116int
117recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
118 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
119 const struct GNUNET_MESSENGER_Message *message,
120 const struct GNUNET_HashCode *hash)
121{
122 struct GNUNET_PeerIdentity peer;
123 GNUNET_PEER_resolve (tunnel->peer, &peer);
124
125 if (0 == GNUNET_memcmp(&peer, &(message->body.peer.peer)))
126 {
127 if (!tunnel->peer_message)
128 tunnel->peer_message = GNUNET_new(struct GNUNET_HashCode);
129
130 GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
131 }
132
133 return GNUNET_YES;
134}
135
136static void
137callback_found_message (void *cls,
138 struct GNUNET_MESSENGER_SrvRoom *room,
139 const struct GNUNET_MESSENGER_Message *message,
140 const struct GNUNET_HashCode *hash)
141{
142 struct GNUNET_MESSENGER_SrvTunnel *tunnel = tunnel;
143
144 if (!message)
145 {
146 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(room);
147
148 use_store_operation(
149 operation_store,
150 hash,
151 GNUNET_MESSENGER_OP_REQUEST,
152 GNUNET_MESSENGER_REQUEST_DELAY
153 );
154 }
155 else
156 forward_tunnel_message (tunnel, message, hash);
157}
158
159/*
160 * Function returns GNUNET_NO to drop forwarding the request.
161 * It will only be forwarded if it can't be answered!
162 */
163int
164recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
165 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
166 const struct GNUNET_MESSENGER_Message *message,
167 const struct GNUNET_HashCode *hash)
168{
169 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
170 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
171
172 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Request for message (%s)\n", GNUNET_h2s (hash));
173
174 if (!member)
175 return GNUNET_NO;
176
177 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
178
179 if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO)))
180 return GNUNET_NO;
181
182 if (GNUNET_NO == request_srv_room_message(room, &(message->body.request.hash), session, callback_found_message, tunnel))
183 return GNUNET_YES;
184
185 return GNUNET_NO;
186}
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 8e5b02504..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_util_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 09039758b..000000000
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ /dev/null
@@ -1,77 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_message_send.h"
28
29#include "gnunet-service-messenger_member.h"
30#include "gnunet-service-messenger_member_session.h"
31#include "gnunet-service-messenger_operation.h"
32
33void
34send_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
35 struct GNUNET_MESSENGER_SrvHandle *handle,
36 const struct GNUNET_MESSENGER_Message *message,
37 const struct GNUNET_HashCode *hash)
38{
39 check_srv_room_peer_status(room, NULL);
40}
41
42void
43send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
44 struct GNUNET_MESSENGER_SrvHandle *handle,
45 const struct GNUNET_MESSENGER_Message *message,
46 const struct GNUNET_HashCode *hash)
47{
48 if (!room->peer_message)
49 room->peer_message = GNUNET_new(struct GNUNET_HashCode);
50
51 GNUNET_memcpy(room->peer_message, hash, sizeof(struct GNUNET_HashCode));
52}
53
54void
55send_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
56 struct GNUNET_MESSENGER_SrvHandle *handle,
57 const struct GNUNET_MESSENGER_Message *message,
58 const struct GNUNET_HashCode *hash)
59{
60 change_srv_handle_member_id (handle, get_srv_room_key(room), &(message->body.id.id));
61}
62
63void
64send_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
65 struct GNUNET_MESSENGER_SrvHandle *handle,
66 const struct GNUNET_MESSENGER_Message *message,
67 const struct GNUNET_HashCode *hash)
68{
69 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(room);
70
71 use_store_operation(
72 operation_store,
73 &(message->body.request.hash),
74 GNUNET_MESSENGER_OP_REQUEST,
75 GNUNET_MESSENGER_REQUEST_DELAY
76 );
77}
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 4f4c6cfc2..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_util_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 b2328588e..000000000
--- a/src/messenger/gnunet-service-messenger_message_state.c
+++ /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_message_state.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "gnunet-service-messenger_message_state.h"
28
29void
30init_message_state (struct GNUNET_MESSENGER_MessageState *state)
31{
32 GNUNET_assert(state);
33
34 init_list_messages (&(state->last_messages));
35}
36
37void
38clear_message_state (struct GNUNET_MESSENGER_MessageState *state)
39{
40 GNUNET_assert(state);
41
42 clear_list_messages (&(state->last_messages));
43}
44
45void
46get_message_state_chain_hash (const struct GNUNET_MESSENGER_MessageState *state,
47 struct GNUNET_HashCode *hash)
48{
49 GNUNET_assert((state) && (hash));
50
51 if (state->last_messages.head)
52 GNUNET_memcpy(hash, &(state->last_messages.head->hash), sizeof(*hash));
53 else
54 memset (hash, 0, sizeof(*hash));
55}
56
57const struct GNUNET_HashCode*
58get_message_state_merge_hash (const struct GNUNET_MESSENGER_MessageState *state)
59{
60 GNUNET_assert(state);
61
62 if (state->last_messages.head == state->last_messages.tail)
63 return NULL;
64
65 return &(state->last_messages.tail->hash);
66}
67
68void
69update_message_state (struct GNUNET_MESSENGER_MessageState *state,
70 int requested,
71 const struct GNUNET_MESSENGER_Message *message,
72 const struct GNUNET_HashCode *hash)
73{
74 GNUNET_assert((state) && (message) && (hash));
75
76 if ((GNUNET_YES == requested) ||
77 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
78 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
79 return;
80
81 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
82 remove_from_list_messages(&(state->last_messages), &(message->body.merge.previous));
83 remove_from_list_messages(&(state->last_messages), &(message->header.previous));
84
85 add_to_list_messages (&(state->last_messages), hash);
86}
87
88void
89load_message_state (struct GNUNET_MESSENGER_MessageState *state,
90 const char *path)
91{
92 GNUNET_assert((state) && (path));
93
94 char *last_messages_file;
95 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
96
97 load_list_messages(&(state->last_messages), last_messages_file);
98 GNUNET_free(last_messages_file);
99}
100
101void
102save_message_state (const struct GNUNET_MESSENGER_MessageState *state,
103 const char *path)
104{
105 GNUNET_assert((state) && (path));
106
107 char *last_messages_file;
108 GNUNET_asprintf (&last_messages_file, "%s%s", path, "last_messages.list");
109
110 save_list_messages(&(state->last_messages), last_messages_file);
111 GNUNET_free(last_messages_file);
112}
113
114
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 10e6a2c46..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_util_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 1f77de9ca..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ /dev/null
@@ -1,581 +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 "platform.h"
27#include "gnunet-service-messenger_message_store.h"
28#include "messenger_api_message.h"
29
30void
31init_message_store (struct GNUNET_MESSENGER_MessageStore *store)
32{
33 GNUNET_assert(store);
34
35 store->storage_messages = NULL;
36
37 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39 store->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
40
41 store->rewrite_entries = GNUNET_NO;
42 store->write_links = GNUNET_NO;
43}
44
45static int
46iterate_destroy_entries (void *cls,
47 const struct GNUNET_HashCode *key,
48 void *value)
49{
50 struct GNUNET_MESSENGER_MessageEntry *entry = value;
51
52 GNUNET_free(entry);
53
54 return GNUNET_YES;
55}
56
57static int
58iterate_destroy_messages (void *cls,
59 const struct GNUNET_HashCode *key,
60 void *value)
61{
62 struct GNUNET_MESSENGER_Message *message = value;
63
64 destroy_message (message);
65
66 return GNUNET_YES;
67}
68
69static int
70iterate_destroy_links (void *cls,
71 const struct GNUNET_HashCode *key,
72 void *value)
73{
74 struct GNUNET_HashCode *previous = value;
75
76 GNUNET_free(previous);
77
78 return GNUNET_YES;
79}
80
81void
82clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
83{
84 GNUNET_assert(store);
85
86 if (store->storage_messages)
87 {
88 GNUNET_DISK_file_close (store->storage_messages);
89
90 store->storage_messages = NULL;
91 }
92
93 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
94 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
95 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
96
97 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
98 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
99 GNUNET_CONTAINER_multihashmap_destroy (store->links);
100}
101
102struct GNUNET_MESSENGER_MessageEntryStorage
103{
104 struct GNUNET_HashCode hash;
105 struct GNUNET_MESSENGER_MessageEntry entry;
106};
107
108#define load_message_store_attribute_failed(file, attribute) \
109 sizeof(attribute) != GNUNET_DISK_file_read(file, &(attribute), sizeof(attribute))
110
111#define save_message_store_attribute_failed(file, attribute) \
112 sizeof(attribute) != GNUNET_DISK_file_write(file, &(attribute), sizeof(attribute))
113
114static void
115load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store,
116 const char *filename)
117{
118 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
119
120 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
121
122 if (!entries)
123 return;
124
125 struct GNUNET_MESSENGER_MessageEntryStorage storage;
126 struct GNUNET_MESSENGER_MessageEntry *entry;
127
128 memset(&storage, 0, sizeof(storage));
129
130 do
131 {
132 entry = NULL;
133
134 if ((load_message_store_attribute_failed(entries, storage.hash)) ||
135 (load_message_store_attribute_failed(entries, storage.entry.offset)) ||
136 (load_message_store_attribute_failed(entries, storage.entry.length)))
137 break;
138
139 entry = GNUNET_new(struct GNUNET_MESSENGER_MessageEntry);
140
141 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
142
143 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
144 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
145 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
146 {
147 store->rewrite_entries = GNUNET_YES;
148 break;
149 }
150 }
151 while (entry);
152
153 if (entry)
154 GNUNET_free(entry);
155
156 GNUNET_DISK_file_close (entries);
157}
158
159struct GNUNET_MESSENGER_MessageLinkStorage
160{
161 struct GNUNET_HashCode hash;
162 struct GNUNET_MESSENGER_MessageLink link;
163};
164
165static void
166load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store,
167 const char *filename)
168{
169 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
170
171 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
172
173 if (!entries)
174 return;
175
176 struct GNUNET_MESSENGER_MessageLinkStorage storage;
177 struct GNUNET_MESSENGER_MessageLink *link;
178
179 memset(&storage, 0, sizeof(storage));
180
181 do
182 {
183 link = NULL;
184
185 if ((load_message_store_attribute_failed(entries, storage.hash)) ||
186 (load_message_store_attribute_failed(entries, storage.link.multiple)) ||
187 (load_message_store_attribute_failed(entries, storage.link.first)) ||
188 ((GNUNET_YES == storage.link.multiple) &&
189 (load_message_store_attribute_failed(entries, storage.link.second))))
190 break;
191
192 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
193
194 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
195
196 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
197 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
198 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
199 break;
200 }
201 while (link);
202
203 if (link)
204 GNUNET_free(link);
205
206 GNUNET_DISK_file_close (entries);
207}
208
209void
210load_message_store (struct GNUNET_MESSENGER_MessageStore *store,
211 const char *directory)
212{
213 GNUNET_assert((store) && (directory));
214
215 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
216
217 if (store->storage_messages)
218 GNUNET_DISK_file_close (store->storage_messages);
219
220 char *filename;
221 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
222
223 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
224 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
225 else
226 store->storage_messages = NULL;
227
228 GNUNET_free(filename);
229
230 if (!store->storage_messages)
231 return;
232
233 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
234
235 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
236 load_message_store_entries(store, filename);
237
238 GNUNET_free(filename);
239
240 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
241
242 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
243 load_message_store_links(store, filename);
244
245 GNUNET_free(filename);
246}
247
248struct GNUNET_MESSENGER_ClosureMessageSave
249{
250 struct GNUNET_MESSENGER_MessageStore *store;
251
252 struct GNUNET_DISK_FileHandle *storage;
253};
254
255static int
256iterate_save_entries (void *cls,
257 const struct GNUNET_HashCode *key,
258 void *value)
259{
260 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
261 struct GNUNET_MESSENGER_MessageEntry *entry = value;
262
263 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
264 GNUNET_DISK_file_write (save->storage, &(entry->offset), sizeof(entry->offset));
265 GNUNET_DISK_file_write (save->storage, &(entry->length), sizeof(entry->length));
266
267 return GNUNET_YES;
268}
269
270static int
271iterate_save_messages (void *cls,
272 const struct GNUNET_HashCode *key,
273 void *value)
274{
275 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
276
277 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
278 return GNUNET_YES;
279
280 struct GNUNET_MESSENGER_Message *message = value;
281 struct GNUNET_MESSENGER_MessageEntryStorage storage;
282
283 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
284
285 storage.entry.length = get_message_size (message, GNUNET_YES);
286 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
287
288 if ((GNUNET_SYSERR == storage.entry.offset) ||
289 (save_message_store_attribute_failed(save->storage, storage.hash)) ||
290 (save_message_store_attribute_failed(save->storage, storage.entry.offset)) ||
291 (save_message_store_attribute_failed(save->storage, storage.entry.length)))
292 return GNUNET_YES;
293
294 char *buffer = GNUNET_malloc(storage.entry.length);
295
296 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
297
298 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
299
300 GNUNET_free(buffer);
301 return GNUNET_YES;
302}
303
304static int
305iterate_save_links (void *cls,
306 const struct GNUNET_HashCode *key,
307 void *value)
308{
309 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
310 struct GNUNET_MESSENGER_MessageLink *link = value;
311
312 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
313 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
314 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
315
316 if (GNUNET_YES == link->multiple)
317 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
318
319 return GNUNET_YES;
320}
321
322void
323save_message_store (struct GNUNET_MESSENGER_MessageStore *store,
324 const char *directory)
325{
326 GNUNET_assert((store) && (directory));
327
328 struct GNUNET_MESSENGER_ClosureMessageSave save;
329
330 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
331
332 char *filename;
333
334 if (GNUNET_YES != store->write_links)
335 goto save_entries;
336
337 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
338
339 save.store = store;
340 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
341
342 GNUNET_free(filename);
343
344 if (!save.storage)
345 goto save_entries;
346
347 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
348 goto close_links;
349
350 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
351 store->write_links = GNUNET_NO;
352
353close_links:
354 GNUNET_DISK_file_close (save.storage);
355
356save_entries:
357 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
358
359 save.store = store;
360 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
361
362 GNUNET_free(filename);
363
364 if (!save.storage)
365 return;
366
367 if (GNUNET_YES == store->rewrite_entries)
368 {
369 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
370 goto close_entries;
371
372 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
373 store->rewrite_entries = GNUNET_NO;
374 }
375 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
376 goto close_entries;
377
378 if (store->storage_messages)
379 GNUNET_DISK_file_close (store->storage_messages);
380
381 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
382
383 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE | GNUNET_DISK_OPEN_CREATE,
384 permission);
385
386 GNUNET_free(filename);
387
388 if (store->storage_messages)
389 {
390 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
391
392 GNUNET_DISK_file_sync (store->storage_messages);
393 GNUNET_DISK_file_sync (save.storage);
394 }
395
396close_entries:
397 GNUNET_DISK_file_close (save.storage);
398}
399
400int
401contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store,
402 const struct GNUNET_HashCode *hash)
403{
404 GNUNET_assert((store) && (hash));
405
406 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
407 return GNUNET_YES;
408
409 return GNUNET_CONTAINER_multihashmap_contains (store->entries, hash);
410}
411
412const struct GNUNET_MESSENGER_Message*
413get_store_message (struct GNUNET_MESSENGER_MessageStore *store,
414 const struct GNUNET_HashCode *hash)
415{
416 GNUNET_assert((store) && (hash));
417
418 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
419
420 if (message)
421 return message;
422
423 if (!store->storage_messages)
424 return NULL;
425
426 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
427
428 if (!entry)
429 return NULL;
430
431 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
432 return message;
433
434 char *buffer = GNUNET_malloc(entry->length);
435
436 if (!buffer)
437 return NULL;
438
439 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) ||
440 (entry->length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES)))
441 goto free_buffer;
442
443 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
444
445 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
446
447 struct GNUNET_HashCode check;
448 hash_message (message, entry->length, buffer, &check);
449
450 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
451 {
452 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
453 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Corrupted entry could not be removed from store: %s\n",
454 GNUNET_h2s(hash));
455
456 store->rewrite_entries = GNUNET_YES;
457
458 goto free_message;
459 }
460
461 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
462 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
463 goto free_buffer;
464
465free_message: destroy_message (message);
466 message = NULL;
467
468free_buffer:
469 GNUNET_free(buffer);
470
471 return message;
472}
473
474const struct GNUNET_MESSENGER_MessageLink*
475get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store,
476 const struct GNUNET_HashCode *hash,
477 int deleted_only)
478{
479 if (deleted_only)
480 goto get_link;
481
482 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
483
484 if (!message)
485 goto get_link;
486
487 static struct GNUNET_MESSENGER_MessageLink link;
488
489 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
490
491 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
492
493 if (GNUNET_YES == link.multiple)
494 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
495 else
496 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
497
498 return &link;
499
500get_link:
501 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
502}
503
504int
505put_store_message (struct GNUNET_MESSENGER_MessageStore *store,
506 const struct GNUNET_HashCode *hash,
507 struct GNUNET_MESSENGER_Message *message)
508{
509 GNUNET_assert((store) && (hash) && (message));
510
511 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
512 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
513}
514
515static void
516add_link (struct GNUNET_MESSENGER_MessageStore *store,
517 const struct GNUNET_HashCode *hash,
518 const struct GNUNET_MESSENGER_Message *message)
519{
520 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
521
522 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
523
524 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
525
526 if (GNUNET_YES == link->multiple)
527 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
528 else
529 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
530
531 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
532 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
533 GNUNET_free(link);
534}
535
536int
537delete_store_message (struct GNUNET_MESSENGER_MessageStore *store,
538 const struct GNUNET_HashCode *hash)
539{
540 GNUNET_assert((store) && (hash));
541
542 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
543
544 if (!entry)
545 goto clear_memory;
546
547 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
548
549 if (message)
550 add_link (store, hash, message);
551
552 if (!store->storage_messages)
553 goto clear_entry;
554
555 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
556 return GNUNET_SYSERR;
557
558 char *clear_buffer = GNUNET_malloc(entry->length);
559
560 if (!clear_buffer)
561 return GNUNET_SYSERR;
562
563 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
564
565 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
566 != GNUNET_DISK_file_sync (store->storage_messages)))
567 {
568 GNUNET_free(clear_buffer);
569 return GNUNET_SYSERR;
570 }
571
572 GNUNET_free(clear_buffer);
573
574clear_entry:
575 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
576 store->rewrite_entries = GNUNET_YES;
577
578clear_memory:
579 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
580 return GNUNET_OK;
581}
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 262d10555..000000000
--- a/src/messenger/gnunet-service-messenger_message_store.h
+++ /dev/null
@@ -1,168 +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_util_lib.h"
31
32struct GNUNET_MESSENGER_MessageEntry
33{
34 off_t offset;
35 uint16_t length;
36};
37
38struct GNUNET_MESSENGER_Message;
39
40struct GNUNET_MESSENGER_MessageLink
41{
42 uint8_t multiple;
43
44 struct GNUNET_HashCode first;
45 struct GNUNET_HashCode second;
46};
47
48struct GNUNET_MESSENGER_MessageStore
49{
50 struct GNUNET_DISK_FileHandle *storage_messages;
51
52 struct GNUNET_CONTAINER_MultiHashMap *entries;
53 struct GNUNET_CONTAINER_MultiHashMap *messages;
54 struct GNUNET_CONTAINER_MultiHashMap *links;
55
56 int rewrite_entries;
57 int write_links;
58};
59
60/**
61 * Initializes a message <i>store</i> as fully empty.
62 *
63 * @param[out] store Message store
64 */
65void
66init_message_store (struct GNUNET_MESSENGER_MessageStore *store);
67
68/**
69 * Clears a message <i>store</i>, wipes its content and deallocates its memory.
70 *
71 * @param[in,out] store Message store
72 */
73void
74clear_message_store (struct GNUNET_MESSENGER_MessageStore *store);
75
76/**
77 * Loads messages from a <i>directory</i> into a message <i>store</i>.
78 *
79 * @param[out] store Message store
80 * @param[in] directory Path to a directory
81 */
82void
83load_message_store (struct GNUNET_MESSENGER_MessageStore *store,
84 const char *directory);
85
86/**
87 * Saves messages from a message <i>store</i> into a <i>directory</i>.
88 *
89 * @param[in] store Message store
90 * @param[in] directory Path to a directory
91 */
92void
93save_message_store (struct GNUNET_MESSENGER_MessageStore *store,
94 const char *directory);
95
96/**
97 * Checks if a message matching a given <i>hash</i> is stored in a message <i>store</i>.
98 * The function returns #GNUNET_YES if a match is found, #GNUNET_NO otherwise.
99 *
100 * The message has not to be loaded from disk into memory for this check!
101 *
102 * @param[in] store Message store
103 * @param[in] hash Hash of message
104 * @return #GNUNET_YES on match, otherwise #GNUNET_NO
105 */
106int
107contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store,
108 const struct GNUNET_HashCode *hash);
109
110/**
111 * Returns the message from a message <i>store</i> matching a given <i>hash</i>. If no matching
112 * message is found, NULL gets returned.
113 *
114 * This function requires the message to be loaded into memory!
115 * @see contains_store_message()
116 *
117 * @param[in,out] store Message store
118 * @param[in] hash Hash of message
119 * @return Message or NULL
120 */
121const struct GNUNET_MESSENGER_Message*
122get_store_message (struct GNUNET_MESSENGER_MessageStore *store,
123 const struct GNUNET_HashCode *hash);
124
125/**
126 * Returns the message link from a message <i>store</i> matching a given <i>hash</i>. If the
127 * flag is set to #GNUNET_YES, only links from deleted messages will be returned or NULL.
128 *
129 * Otherwise message links will also returned for messages found in the store under the given
130 * hash. The link which will be returned copies link information from the message for
131 * temporary usage.
132 *
133 * @param[in,out] store Message store
134 * @param[in] hash Hash of message
135 * @param[in] deleted_only Flag
136 * @return Message link or NULL
137 */
138const struct GNUNET_MESSENGER_MessageLink*
139get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store,
140 const struct GNUNET_HashCode *hash,
141 int deleted_only);
142
143/**
144 * Stores a message into the message store. The result indicates if the operation was successful.
145 *
146 * @param[in,out] store Message store
147 * @param[in] hash Hash of message
148 * @param[in,out] message Message
149 * @return #GNUNET_OK on success, otherwise #GNUNET_NO
150 */
151int
152put_store_message (struct GNUNET_MESSENGER_MessageStore *store,
153 const struct GNUNET_HashCode *hash,
154 struct GNUNET_MESSENGER_Message *message);
155
156/**
157 * Deletes a message in the message store. It will be removed from disk space and memory. The result
158 * indicates if the operation was successful.
159 *
160 * @param[in,out] store Message store
161 * @param[in] hash Hash of message
162 * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
163 */
164int
165delete_store_message (struct GNUNET_MESSENGER_MessageStore *store,
166 const struct GNUNET_HashCode *hash);
167
168#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 9c4201fdf..000000000
--- a/src/messenger/gnunet-service-messenger_operation.c
+++ /dev/null
@@ -1,221 +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 "platform.h"
27#include "gnunet-service-messenger_operation.h"
28
29#include "gnunet-service-messenger_operation_store.h"
30
31struct GNUNET_MESSENGER_Operation*
32create_operation (const struct GNUNET_HashCode *hash)
33{
34 GNUNET_assert(hash);
35
36 struct GNUNET_MESSENGER_Operation *op = GNUNET_new(struct GNUNET_MESSENGER_Operation);
37
38 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
39 GNUNET_memcpy(&(op->hash), hash, sizeof(*hash));
40 op->timestamp = GNUNET_TIME_absolute_get_zero_();
41 op->store = NULL;
42 op->task = NULL;
43
44 return op;
45}
46
47void
48destroy_operation (struct GNUNET_MESSENGER_Operation *op)
49{
50 GNUNET_assert(op);
51
52 if (op->task)
53 GNUNET_SCHEDULER_cancel(op->task);
54
55 GNUNET_free(op);
56}
57
58static void
59callback_operation (void *cls);
60
61struct GNUNET_MESSENGER_Operation*
62load_operation (struct GNUNET_MESSENGER_OperationStore *store,
63 const char *path)
64{
65 GNUNET_assert((store) && (path));
66
67 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load operation configuration: %s\n", path);
68
69 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
70 struct GNUNET_MESSENGER_Operation* op = NULL;
71
72 if (GNUNET_OK != GNUNET_CONFIGURATION_parse(cfg, path))
73 goto destroy_config;
74
75 struct GNUNET_HashCode hash;
76
77 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "hash", &hash, sizeof(hash)))
78 goto destroy_config;
79
80 op = create_operation(&hash);
81
82 unsigned long long type_number;
83 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg, "operation", "type", &type_number))
84 switch (type_number)
85 {
86 case GNUNET_MESSENGER_OP_REQUEST:
87 op->type = GNUNET_MESSENGER_OP_REQUEST;
88 break;
89 case GNUNET_MESSENGER_OP_DELETE:
90 op->type = GNUNET_MESSENGER_OP_DELETE;
91 break;
92 case GNUNET_MESSENGER_OP_MERGE:
93 op->type = GNUNET_MESSENGER_OP_MERGE;
94 break;
95 default:
96 break;
97 }
98
99 if ((GNUNET_MESSENGER_OP_UNKNOWN == op->type) ||
100 (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "operation", "timestamp", &(op->timestamp), sizeof(op->timestamp))))
101 {
102 destroy_operation(op);
103 op = NULL;
104 goto destroy_config;
105 }
106
107 const struct GNUNET_TIME_Relative delay = GNUNET_TIME_absolute_get_remaining(op->timestamp);
108
109 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
110 delay,
111 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
112 callback_operation,
113 op
114 );
115
116 op->store = store;
117
118destroy_config:
119 GNUNET_CONFIGURATION_destroy (cfg);
120
121 return op;
122}
123
124void
125save_operation (const struct GNUNET_MESSENGER_Operation *op,
126 const char *path)
127{
128 GNUNET_assert((path) && (op));
129
130 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save operation configuration: %s\n", path);
131
132 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
133
134 char *hash_data;
135 hash_data = GNUNET_STRINGS_data_to_string_alloc (&(op->hash), sizeof(op->hash));
136
137 if (hash_data)
138 {
139 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "hash", hash_data);
140
141 GNUNET_free(hash_data);
142 }
143
144 GNUNET_CONFIGURATION_set_value_number(cfg, "operation", "type", op->type);
145
146 char *timestamp_data;
147 timestamp_data = GNUNET_STRINGS_data_to_string_alloc (&(op->timestamp), sizeof(op->timestamp));
148
149 if (timestamp_data)
150 {
151 GNUNET_CONFIGURATION_set_value_string (cfg, "operation", "timestamp", timestamp_data);
152
153 GNUNET_free(timestamp_data);
154 }
155
156 GNUNET_CONFIGURATION_write (cfg, path);
157 GNUNET_CONFIGURATION_destroy (cfg);
158}
159
160extern void
161callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
162 enum GNUNET_MESSENGER_OperationType type,
163 const struct GNUNET_HashCode *hash);
164
165static void
166callback_operation (void *cls)
167{
168 struct GNUNET_MESSENGER_Operation *op = cls;
169
170 op->task = NULL;
171
172 callback_store_operation (op->store, op->type, &(op->hash));
173}
174
175int
176start_operation (struct GNUNET_MESSENGER_Operation *op,
177 enum GNUNET_MESSENGER_OperationType type,
178 struct GNUNET_MESSENGER_OperationStore *store,
179 struct GNUNET_TIME_Relative delay)
180{
181 GNUNET_assert((op) && (store));
182
183 if (op->task)
184 return GNUNET_SYSERR;
185
186 const struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_add(
187 GNUNET_TIME_absolute_get(),
188 delay
189 );
190
191 op->task = GNUNET_SCHEDULER_add_delayed_with_priority(
192 delay,
193 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
194 callback_operation,
195 op
196 );
197
198 op->type = type;
199 op->timestamp = timestamp;
200 op->store = store;
201
202 return GNUNET_OK;
203}
204
205int
206stop_operation (struct GNUNET_MESSENGER_Operation *op)
207{
208 GNUNET_assert(op);
209
210 if (!op->task)
211 return GNUNET_SYSERR;
212
213 GNUNET_SCHEDULER_cancel(op->task);
214 op->task = NULL;
215
216 op->type = GNUNET_MESSENGER_OP_UNKNOWN;
217 op->timestamp = GNUNET_TIME_absolute_get_zero_();
218 op->store = NULL;
219
220 return GNUNET_OK;
221}
diff --git a/src/messenger/gnunet-service-messenger_operation.h b/src/messenger/gnunet-service-messenger_operation.h
deleted file mode 100644
index b93282d24..000000000
--- a/src/messenger/gnunet-service-messenger_operation.h
+++ /dev/null
@@ -1,130 +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_util_lib.h"
32#include "gnunet_scheduler_lib.h"
33#include "gnunet_time_lib.h"
34
35enum GNUNET_MESSENGER_OperationType
36{
37 GNUNET_MESSENGER_OP_REQUEST = 1,
38 GNUNET_MESSENGER_OP_DELETE = 2,
39 GNUNET_MESSENGER_OP_MERGE = 3,
40
41 GNUNET_MESSENGER_OP_UNKNOWN = 0
42};
43
44struct GNUNET_MESSENGER_OperationStore;
45
46struct GNUNET_MESSENGER_Operation
47{
48 enum GNUNET_MESSENGER_OperationType type;
49
50 struct GNUNET_HashCode hash;
51 struct GNUNET_TIME_Absolute timestamp;
52
53 struct GNUNET_MESSENGER_OperationStore *store;
54 struct GNUNET_SCHEDULER_Task* task;
55};
56
57/**
58 * Creates and allocates a new operation under a given <i>hash</i>.
59 *
60 * @param[in] hash Hash of message
61 */
62struct GNUNET_MESSENGER_Operation*
63create_operation (const struct GNUNET_HashCode *hash);
64
65/**
66 * Destroys an operation and frees its memory fully.
67 *
68 * @param[in,out] op Operation
69 */
70void
71destroy_operation (struct GNUNET_MESSENGER_Operation *op);
72
73/**
74 * Loads data from a configuration file at a selected <i>path</i> into
75 * a new allocated and created operation for a specific operation
76 * <i>store</i> if the required information could be read successfully.
77 *
78 * The method will return the new operation and it will be started
79 * automatically to match its timestamp of execution.
80 *
81 * If the method fails to restore any valid operation from the file,
82 * NULL gets returned instead.
83 *
84 * @param[in,out] store Operation store
85 * @param[in] path Path of a configuration file
86 */
87struct GNUNET_MESSENGER_Operation*
88load_operation (struct GNUNET_MESSENGER_OperationStore *store,
89 const char *path);
90
91/**
92 * Saves data from an <i>operation</i> into a configuration file at a
93 * selected <i>path</i> which can be load to restore the operation
94 * completely and continue its process.
95 *
96 * @param[in] op Operation
97 * @param[in] path Path of a configuration file
98 */
99void
100save_operation (const struct GNUNET_MESSENGER_Operation *op,
101 const char *path);
102
103/**
104 * Starts an inactive operation with a given <i>delay</i> in a
105 * specific operation <i>store</i>. The method will replace the
106 * operations type to process it correctly. An operation can't be
107 * started twice, it has to be stopped or fully processed first.
108 *
109 * @param[in,out] op Operation
110 * @param[in] type Type of operation
111 * @param[in,out] store Operation store
112 * @param[in] delay Delay
113 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
114 */
115int
116start_operation (struct GNUNET_MESSENGER_Operation *op,
117 enum GNUNET_MESSENGER_OperationType type,
118 struct GNUNET_MESSENGER_OperationStore *store,
119 struct GNUNET_TIME_Relative delay);
120
121/**
122 * Stops an active operation and resets its type to be
123 * #GNUNET_MESSENGER_OP_UNKNOWN.
124 *
125 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
126 */
127int
128stop_operation (struct GNUNET_MESSENGER_Operation *op);
129
130#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 6a639d69e..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.c
+++ /dev/null
@@ -1,237 +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 "platform.h"
27#include "gnunet-service-messenger_operation_store.h"
28
29#include "gnunet-service-messenger_operation.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
34 struct GNUNET_MESSENGER_SrvRoom *room)
35{
36 GNUNET_assert((store) && (room));
37
38 store->room = room;
39 store->operations = GNUNET_CONTAINER_multihashmap_create(8, GNUNET_NO);
40}
41
42static int
43iterate_destroy_operations (void *cls,
44 const struct GNUNET_HashCode *key,
45 void *value)
46{
47 struct GNUNET_MESSENGER_Operation *op = value;
48
49 destroy_operation(op);
50
51 return GNUNET_YES;
52}
53
54void
55clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store)
56{
57 GNUNET_assert(store);
58
59 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_destroy_operations, NULL);
60 GNUNET_CONTAINER_multihashmap_destroy(store->operations);
61}
62
63static int
64callback_scan_for_operations (void *cls,
65 const char *filename)
66{
67 struct GNUNET_MESSENGER_OperationStore *store = cls;
68
69 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
70 return GNUNET_OK;
71
72 if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, ".cfg")))
73 return GNUNET_OK;
74
75 struct GNUNET_MESSENGER_Operation *op = load_operation(store, filename);
76
77 if ((op) && (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
78 store->operations,
79 &(op->hash), op,
80 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
81 {
82 destroy_operation(op);
83 }
84
85 return GNUNET_OK;
86}
87
88void
89load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
90 const char *directory)
91{
92 GNUNET_assert ((store) && (directory));
93
94 char* load_dir;
95 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
96
97 if (GNUNET_OK == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
98 GNUNET_DISK_directory_scan (load_dir, callback_scan_for_operations, store);
99
100 GNUNET_free(load_dir);
101}
102
103static int
104iterate_save_operations (void *cls,
105 const struct GNUNET_HashCode *key,
106 void *value)
107{
108 const char *save_dir = cls;
109
110 struct GNUNET_MESSENGER_Operation *op = value;
111
112 if (!op)
113 return GNUNET_YES;
114
115 char *op_dir;
116 GNUNET_asprintf (&op_dir, "%s%s.cfg", save_dir, GNUNET_h2s(key));
117 save_operation(op, op_dir);
118
119 GNUNET_free(op_dir);
120 return GNUNET_YES;
121}
122
123void
124save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
125 const char *directory)
126{
127 GNUNET_assert ((store) && (directory));
128
129 char* save_dir;
130 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "operations", DIR_SEPARATOR);
131
132 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
133 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
134 GNUNET_CONTAINER_multihashmap_iterate (store->operations, iterate_save_operations, save_dir);
135
136 GNUNET_free(save_dir);
137}
138
139enum GNUNET_MESSENGER_OperationType
140get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
141 const struct GNUNET_HashCode *hash)
142{
143 GNUNET_assert((store) && (hash));
144
145 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
146
147 if (!op)
148 return GNUNET_MESSENGER_OP_UNKNOWN;
149
150 return op->type;
151}
152
153int
154use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
155 const struct GNUNET_HashCode *hash,
156 enum GNUNET_MESSENGER_OperationType type,
157 struct GNUNET_TIME_Relative delay)
158{
159 GNUNET_assert((store) && (hash));
160
161 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
162
163 if (op)
164 goto use_op;
165
166 op = create_operation(hash);
167
168 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->operations, hash, op, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
169 {
170 destroy_operation(op);
171
172 return GNUNET_SYSERR;
173 }
174
175use_op:
176 if ((op->type != GNUNET_MESSENGER_OP_UNKNOWN) &&
177 (type == GNUNET_MESSENGER_OP_DELETE))
178 stop_operation (op);
179
180 return start_operation(op, type, store, delay);
181}
182
183void
184cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
185 const struct GNUNET_HashCode *hash)
186{
187 GNUNET_assert((store) && (hash));
188
189 struct GNUNET_MESSENGER_Operation *op = GNUNET_CONTAINER_multihashmap_get(store->operations, hash);
190
191 if (!op)
192 return;
193
194 stop_operation(op);
195
196 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(store->operations, hash, op))
197 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Canceled operation could not be removed: %s\n",
198 GNUNET_h2s(hash));
199
200 destroy_operation(op);
201}
202
203extern void
204callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
205 const struct GNUNET_HashCode *hash);
206
207extern void
208callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
209 const struct GNUNET_HashCode *hash);
210
211void
212callback_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
213 enum GNUNET_MESSENGER_OperationType type,
214 const struct GNUNET_HashCode *hash)
215{
216 GNUNET_assert((store) && (hash));
217
218 struct GNUNET_HashCode op_hash;
219 GNUNET_memcpy(&op_hash, hash, sizeof(op_hash));
220 cancel_store_operation (store, &op_hash);
221
222 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
223
224 switch (type)
225 {
226 case GNUNET_MESSENGER_OP_REQUEST:
227 break;
228 case GNUNET_MESSENGER_OP_DELETE:
229 callback_room_deletion (room, &op_hash);
230 break;
231 case GNUNET_MESSENGER_OP_MERGE:
232 callback_room_merge (room, &op_hash);
233 break;
234 default:
235 break;
236 }
237}
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 16531758c..000000000
--- a/src/messenger/gnunet-service-messenger_operation_store.h
+++ /dev/null
@@ -1,130 +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_util_lib.h"
31#include "gnunet_time_lib.h"
32
33struct GNUNET_MESSENGER_SrvRoom;
34
35struct GNUNET_MESSENGER_OperationStore
36{
37 struct GNUNET_MESSENGER_SrvRoom *room;
38
39 struct GNUNET_CONTAINER_MultiHashMap *operations;
40};
41
42/**
43 * Initializes an operation <i>store</i> as fully empty with a given <i>room</i>.
44 *
45 * @param[out] store Operation store
46 * @param[in,out] room Room
47 */
48void
49init_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
50 struct GNUNET_MESSENGER_SrvRoom *room);
51
52/**
53 * Clears an operation <i>store</i>, stops all operations and deallocates its memory.
54 *
55 * @param[in,out] store Operation store
56 */
57void
58clear_operation_store (struct GNUNET_MESSENGER_OperationStore *store);
59
60/**
61 * Loads operations from a <i>directory</i> into an operation <i>store</i>.
62 *
63 * @param[out] store Operation store
64 * @param[in] directory Path to a directory
65 */
66void
67load_operation_store (struct GNUNET_MESSENGER_OperationStore *store,
68 const char *directory);
69
70/**
71 * Saves operations from an operation <i>store</i> into a <i>directory</i>.
72 *
73 * @param[in] store Operation store
74 * @param[in] directory Path to a directory
75 */
76void
77save_operation_store (const struct GNUNET_MESSENGER_OperationStore *store,
78 const char *directory);
79
80/**
81 * Returns the type of the active operation under a given <i>hash</i> in
82 * a specific operation <i>store</i>. If there is no active operation under
83 * the given <i>hash</i>, #GNUNET_MESSENGER_OP_UNKNOWN gets returned instead.
84 *
85 * @param[in] store Operation store
86 * @param[in] hash Hash of message
87 * @return Type of operation or #GNUNET_MESSENGER_OP_UNKNOWN
88 */
89enum GNUNET_MESSENGER_OperationType
90get_store_operation_type (const struct GNUNET_MESSENGER_OperationStore *store,
91 const struct GNUNET_HashCode *hash);
92
93/**
94 * Tries to use an operation under a given <i>hash</i> in a specific
95 * operation <i>store</i>. The operation will use the selected <i>type</i>
96 * if successful. The operation will be delayed by a given <i>delay</i>.
97 *
98 * If the selected type is #GNUNET_MESSENGER_OP_DELETE any active operation
99 * under the given hash will be stopped and replaced.
100 *
101 * If the new operation could be started successfully the method returns
102 * #GNUNET_OK, otherwise #GNUNET_SYSERR.
103 *
104 * @param[in,out] store Operation store
105 * @param[in] hash Hash of message
106 * @param[in] type Operation type
107 * @param[in] delay Delay
108 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
109 */
110int
111use_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
112 const struct GNUNET_HashCode *hash,
113 enum GNUNET_MESSENGER_OperationType type,
114 struct GNUNET_TIME_Relative delay);
115
116/**
117 * Stops any active operation under a given <i>hash</i> in a specific
118 * operation <i>store</i>.
119 *
120 * Beware that calling this method will also implicitly free the memory
121 * of any active operation under the given hash!
122 *
123 * @param[in,out] store Operation store
124 * @param[in] hash Hash of message
125 */
126void
127cancel_store_operation (struct GNUNET_MESSENGER_OperationStore *store,
128 const struct GNUNET_HashCode *hash);
129
130#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 4b734cb40..000000000
--- a/src/messenger/gnunet-service-messenger_room.c
+++ /dev/null
@@ -1,1274 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_room.h"
28
29#include "gnunet-service-messenger_member.h"
30#include "gnunet-service-messenger_member_session.h"
31
32#include "gnunet-service-messenger_message_kind.h"
33#include "gnunet-service-messenger_message_handle.h"
34#include "gnunet-service-messenger_message_send.h"
35
36#include "gnunet-service-messenger_operation.h"
37
38#include "gnunet-service-messenger.h"
39#include "gnunet-service-messenger_service.h"
40#include "gnunet-service-messenger_tunnel.h"
41#include "messenger_api_util.h"
42
43static void
44idle_request_room_messages (void *cls);
45
46struct GNUNET_MESSENGER_SrvRoom*
47create_srv_room (struct GNUNET_MESSENGER_SrvHandle *handle,
48 const struct GNUNET_HashCode *key)
49{
50 GNUNET_assert((handle) && (key));
51
52 struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new(struct GNUNET_MESSENGER_SrvRoom);
53
54 room->service = handle->service;
55 room->host = handle;
56 room->port = NULL;
57
58 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
59
60 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
61
62 init_member_store(get_srv_room_member_store(room), room);
63 init_message_store (get_srv_room_message_store(room));
64 init_operation_store(get_srv_room_operation_store(room), room);
65
66 init_list_tunnels (&(room->basement));
67 init_message_state(&(room->state));
68
69 room->peer_message = NULL;
70
71 init_list_messages (&(room->handling));
72 room->idle = NULL;
73
74 if (room->service->dir)
75 load_srv_room (room);
76
77 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
78
79 return room;
80}
81
82static int
83iterate_destroy_tunnels (void *cls,
84 const struct GNUNET_PeerIdentity *key,
85 void *value)
86{
87 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
88 destroy_tunnel (tunnel);
89 return GNUNET_YES;
90}
91
92static void
93handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
94
95void
96destroy_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
97 int deletion)
98{
99 GNUNET_assert(room);
100
101 if (room->idle)
102 {
103 GNUNET_SCHEDULER_cancel (room->idle);
104 room->idle = NULL;
105 }
106
107 if (room->port)
108 GNUNET_CADET_close_port (room->port);
109
110 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels, NULL);
111 handle_room_messages (room);
112
113 if (!(room->service->dir))
114 goto skip_saving;
115
116 if (GNUNET_YES == deletion)
117 remove_srv_room (room);
118 else
119 save_srv_room (room);
120
121skip_saving:
122 clear_member_store (get_srv_room_member_store(room));
123 clear_message_store (get_srv_room_message_store(room));
124 clear_operation_store(get_srv_room_operation_store(room));
125
126 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
127 clear_list_tunnels (&(room->basement));
128 clear_message_state(&(room->state));
129
130 if (room->peer_message)
131 GNUNET_free(room->peer_message);
132
133 GNUNET_free(room);
134}
135
136struct GNUNET_MESSENGER_MemberStore*
137get_srv_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
138{
139 GNUNET_assert(room);
140
141 return &(room->member_store);
142}
143
144struct GNUNET_MESSENGER_MessageStore*
145get_srv_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
146{
147 GNUNET_assert(room);
148
149 return &(room->message_store);
150}
151
152struct GNUNET_MESSENGER_OperationStore*
153get_srv_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
154{
155 GNUNET_assert(room);
156
157 return &(room->operation_store);
158}
159
160static int
161send_room_info (struct GNUNET_MESSENGER_SrvRoom *room,
162 struct GNUNET_MESSENGER_SrvHandle *handle,
163 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
164{
165 if ((!handle) || (!is_tunnel_connected (tunnel)))
166 return GNUNET_NO;
167
168 return send_tunnel_message (tunnel, handle, create_message_info (get_srv_handle_ego (handle)));
169}
170
171static void*
172callback_room_connect (void *cls,
173 struct GNUNET_CADET_Channel *channel,
174 const struct GNUNET_PeerIdentity *source)
175{
176 struct GNUNET_MESSENGER_SrvRoom *room = cls;
177
178 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
179
180 if ((tunnel) &&
181 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
182 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
183 {
184 destroy_tunnel (tunnel);
185 tunnel = NULL;
186 }
187
188 if (!tunnel)
189 {
190 delayed_disconnect_channel (channel);
191 return NULL;
192 }
193
194 bind_tunnel(tunnel, channel);
195
196 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "New tunnel in room (%s) established to peer: %s\n",
197 GNUNET_h2s(get_srv_room_key(room)), GNUNET_i2s (source));
198
199 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
200 return tunnel;
201
202 disconnect_tunnel (tunnel);
203
204 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel))
205 destroy_tunnel (tunnel);
206
207 return NULL;
208}
209
210static int
211join_room (struct GNUNET_MESSENGER_SrvRoom *room,
212 struct GNUNET_MESSENGER_SrvHandle *handle,
213 struct GNUNET_MESSENGER_Member *member)
214{
215 GNUNET_assert((room) && (handle) && (member));
216
217 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (get_srv_room_key (room)),
218 GNUNET_sh2s (get_member_id(member)));
219
220 const struct GNUNET_ShortHashCode *member_id = get_member_id(member);
221
222 if (GNUNET_OK != change_srv_handle_member_id (handle, get_srv_room_key(room), member_id))
223 return GNUNET_NO;
224
225 struct GNUNET_MESSENGER_Message *message = create_message_join (get_srv_handle_ego (handle));
226
227 if (!message)
228 {
229 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be created!\n");
230
231 return GNUNET_NO;
232 }
233
234 GNUNET_memcpy(&(message->header.sender_id), member_id, sizeof(*member_id));
235 return send_srv_room_message (room, handle, message);
236}
237
238struct GNUNET_MESSENGER_MemberNotify
239{
240 struct GNUNET_MESSENGER_SrvRoom *room;
241 struct GNUNET_MESSENGER_SrvHandle *handle;
242 struct GNUNET_MESSENGER_MemberSession *session;
243};
244
245static void
246notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify,
247 struct GNUNET_MESSENGER_MemberSession *session,
248 struct GNUNET_CONTAINER_MultiHashMap *map,
249 int check_permission)
250{
251 if (session->prev)
252 notify_about_members (notify, session->prev, map, GNUNET_YES);
253
254 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(notify->room);
255 struct GNUNET_MESSENGER_ListMessage *element;
256
257 for (element = session->messages.head; element; element = element->next)
258 {
259 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, &(element->hash)))
260 continue;
261
262 if ((GNUNET_YES == check_permission) &&
263 (GNUNET_YES != check_member_session_history(notify->session, &(element->hash), GNUNET_NO)))
264 continue;
265
266 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), NULL,
267 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
268 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message could be duplicated!\n");
269
270 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, &(element->hash));
271
272 if (message)
273 notify_srv_handle_message (notify->handle, notify->room, session, message, &(element->hash));
274 }
275}
276
277static int
278iterate_notify_about_members (void *cls,
279 const struct GNUNET_IDENTITY_PublicKey *public_key,
280 struct GNUNET_MESSENGER_MemberSession *session)
281{
282 struct GNUNET_MESSENGER_MemberNotify *notify = cls;
283
284 if ((notify->session == session) || (GNUNET_YES == is_member_session_completed(session)))
285 return GNUNET_YES;
286
287 struct GNUNET_CONTAINER_MultiHashMap *map = GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
288
289 notify_about_members (notify, session, map, GNUNET_NO);
290
291 GNUNET_CONTAINER_multihashmap_destroy(map);
292 return GNUNET_YES;
293}
294
295static int
296join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room,
297 struct GNUNET_MESSENGER_SrvHandle *handle)
298{
299 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (handle, get_srv_room_key(room));
300
301 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
302 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
303
304 if (GNUNET_NO == join_room (room, handle, member))
305 return GNUNET_NO;
306
307 const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(handle);
308 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, &(ego->pub));
309
310 if (!session)
311 {
312 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join a room!\n");
313 return GNUNET_NO;
314 }
315
316 struct GNUNET_MESSENGER_MemberNotify notify;
317
318 notify.room = room;
319 notify.handle = handle;
320 notify.session = session;
321
322 iterate_store_members(get_srv_room_member_store(room), iterate_notify_about_members, &notify);
323
324 return GNUNET_YES;
325}
326
327extern int
328check_tunnel_message (void *cls,
329 const struct GNUNET_MessageHeader *header);
330
331extern void
332handle_tunnel_message (void *cls,
333 const struct GNUNET_MessageHeader *header);
334
335extern void
336callback_tunnel_disconnect (void *cls,
337 const struct GNUNET_CADET_Channel *channel);
338
339int
340open_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
341 struct GNUNET_MESSENGER_SrvHandle *handle)
342{
343 GNUNET_assert((room) && (handle));
344
345 if (room->port)
346 return join_room_locally (room, handle);
347
348 struct GNUNET_CADET_Handle *cadet = get_srv_room_cadet (room);
349 const struct GNUNET_HashCode *key = get_srv_room_key (room);
350
351 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
352 struct GNUNET_MessageHeader, NULL),
353 GNUNET_MQ_handler_end() };
354
355 struct GNUNET_HashCode port;
356 convert_messenger_key_to_port(key, &port);
357 room->port = GNUNET_CADET_open_port (cadet, &port, callback_room_connect, room, NULL, callback_tunnel_disconnect,
358 handlers);
359
360 if (room->port)
361 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
362 GNUNET_h2s(get_srv_room_key(room)));
363 else
364 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Port of room (%s) could not be opened!\n",
365 GNUNET_h2s(get_srv_room_key(room)));
366
367 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (handle, get_srv_room_key(room));
368
369 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
370 struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, member_id);
371
372 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
373 {
374 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
375
376 GNUNET_CADET_close_port (room->port);
377 room->port = NULL;
378
379 return GNUNET_NO;
380 }
381
382 struct GNUNET_MESSENGER_Message *peer_msg = create_message_peer (room->service);
383 GNUNET_memcpy(&(peer_msg->header.sender_id), member_id, sizeof(*member_id));
384 return (room->port ? send_srv_room_message (room, handle, peer_msg) : GNUNET_NO);
385}
386
387int
388enter_srv_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
389 struct GNUNET_MESSENGER_SrvHandle *handle,
390 const struct GNUNET_PeerIdentity *door)
391{
392 GNUNET_assert((room) && (handle) && (door));
393
394 struct GNUNET_PeerIdentity peer;
395
396 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
397 (0 == GNUNET_memcmp(&peer, door)))
398 return join_room_locally (room, handle);
399
400 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
401
402 if (!tunnel)
403 {
404 tunnel = create_tunnel (room, door);
405
406 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
407 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
408 {
409 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
410 destroy_tunnel (tunnel);
411 return GNUNET_NO;
412 }
413 }
414
415 if (GNUNET_SYSERR == connect_tunnel (tunnel))
416 {
417 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Connection failure during entrance!\n");
418 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
419 destroy_tunnel (tunnel);
420 return GNUNET_NO;
421 }
422
423 return join_room_locally (room, handle);
424}
425
426struct GNUNET_MQ_Envelope*
427pack_srv_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
428 const struct GNUNET_MESSENGER_SrvHandle *handle,
429 struct GNUNET_MESSENGER_Message *message,
430 struct GNUNET_HashCode *hash,
431 int mode)
432{
433 GNUNET_assert((room) && (handle) && (message) && (hash));
434
435 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
436
437 const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle, get_srv_room_key(room));
438
439 GNUNET_assert(id);
440
441 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
442 get_message_state_chain_hash (&(room->state), &(message->header.previous));
443
444 return pack_message (message, hash, get_srv_handle_ego (handle), mode);
445}
446
447struct GNUNET_MESSENGER_ClosureSendRoom
448{
449 struct GNUNET_MESSENGER_SrvRoom *room;
450 struct GNUNET_MESSENGER_SrvHandle *handle;
451 struct GNUNET_MESSENGER_SrvTunnel *exclude;
452 struct GNUNET_MESSENGER_Message *message;
453 struct GNUNET_HashCode *hash;
454 int packed;
455};
456
457static int
458iterate_send_room_message (void *cls,
459 const struct GNUNET_PeerIdentity *key,
460 void *value)
461{
462 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
463
464 if ((!is_tunnel_connected (tunnel)) ||
465 (get_tunnel_messenger_version(tunnel) < GNUNET_MESSENGER_VERSION))
466 return GNUNET_YES;
467
468 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
469
470 if (tunnel == closure->exclude)
471 return GNUNET_YES;
472
473 struct GNUNET_MQ_Envelope *env = NULL;
474
475 if (closure->packed == GNUNET_NO)
476 {
477 env = pack_srv_room_message (closure->room, closure->handle, closure->message, closure->hash,
478 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
479
480 if (env)
481 closure->packed = GNUNET_YES;
482 }
483 else
484 env = pack_message (closure->message, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
485
486 if (env)
487 send_tunnel_envelope (tunnel, env, closure->hash);
488
489 return GNUNET_YES;
490}
491
492int
493update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
494 struct GNUNET_MESSENGER_Message *message,
495 const struct GNUNET_HashCode *hash);
496
497void
498callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
499 struct GNUNET_MESSENGER_SrvHandle *handle,
500 const struct GNUNET_MESSENGER_Message *message,
501 const struct GNUNET_HashCode *hash);
502
503int
504send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
505 struct GNUNET_MESSENGER_SrvHandle *handle,
506 struct GNUNET_MESSENGER_Message *message)
507{
508 GNUNET_assert((room) && (handle));
509
510 if (!message)
511 return GNUNET_NO;
512
513 if (GNUNET_YES == is_message_session_bound(message))
514 merge_srv_room_last_messages(room, handle);
515
516 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member id: %s\n",
517 GNUNET_sh2s(get_srv_handle_member_id(handle, get_srv_room_key(room))));
518
519 struct GNUNET_HashCode hash;
520 struct GNUNET_MESSENGER_ClosureSendRoom closure;
521
522 closure.room = room;
523 closure.handle = handle;
524 closure.exclude = NULL;
525 closure.message = message;
526 closure.hash = &hash;
527 closure.packed = GNUNET_NO;
528
529 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
530
531 if (GNUNET_NO == closure.packed)
532 pack_srv_room_message (room, handle, message, &hash, GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
533
534 const int new_message = update_room_message (room, message, &hash);
535
536 if (GNUNET_YES != new_message)
537 return GNUNET_SYSERR;
538
539 switch (message->header.kind)
540 {
541 case GNUNET_MESSENGER_KIND_JOIN:
542 send_message_join (room, handle, message, &hash);
543 break;
544 case GNUNET_MESSENGER_KIND_PEER:
545 send_message_peer (room, handle, message, &hash);
546 break;
547 case GNUNET_MESSENGER_KIND_ID:
548 send_message_id (room, handle, message, &hash);
549 break;
550 case GNUNET_MESSENGER_KIND_REQUEST:
551 send_message_request (room, handle, message, &hash);
552 break;
553 default:
554 break;
555 }
556
557 callback_room_handle_message (room, handle, message, &hash);
558 return GNUNET_YES;
559}
560
561void
562forward_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
563 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
564 struct GNUNET_MESSENGER_Message *message,
565 const struct GNUNET_HashCode *hash)
566{
567 GNUNET_assert((room) && (tunnel));
568
569 if (!message)
570 return;
571
572 struct GNUNET_MESSENGER_ClosureSendRoom closure;
573 struct GNUNET_HashCode message_hash;
574
575 GNUNET_memcpy(&message_hash, hash, sizeof(struct GNUNET_HashCode));
576
577 closure.room = room;
578 closure.handle = NULL;
579 closure.exclude = tunnel;
580 closure.message = message;
581 closure.hash = &message_hash;
582 closure.packed = GNUNET_YES;
583
584 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
585}
586
587void
588check_srv_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room,
589 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
590{
591 if (!room->peer_message)
592 return;
593
594 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
595
596 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, room->peer_message);
597
598 if (!message)
599 {
600 GNUNET_free(room->peer_message);
601 room->peer_message = NULL;
602 return;
603 }
604
605 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
606 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
607
608 if (!member)
609 goto resend_peer_message;
610
611 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, room->peer_message);
612
613 if (GNUNET_YES == is_member_session_closed(session))
614 goto resend_peer_message;
615
616 if (tunnel)
617 forward_tunnel_message(tunnel, message, room->peer_message);
618
619 return;
620
621resend_peer_message:
622 if (room->host)
623 send_srv_room_message (room, room->host, create_message_peer (room->service));
624}
625
626void
627merge_srv_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room,
628 struct GNUNET_MESSENGER_SrvHandle *handle)
629{
630 GNUNET_assert(room);
631
632 if (!handle)
633 return;
634
635 const struct GNUNET_HashCode *hash;
636
637merge_next:
638 hash = get_message_state_merge_hash (&(room->state));
639
640 if (!hash)
641 return;
642
643 send_srv_room_message (room, handle, create_message_merge (hash));
644 goto merge_next;
645}
646
647void
648callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
649 const struct GNUNET_HashCode *hash)
650{
651 if (GNUNET_OK != delete_store_message (get_srv_room_message_store(room), hash))
652 {
653 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n", GNUNET_h2s(hash));
654 return;
655 }
656}
657
658void
659callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
660 const struct GNUNET_HashCode *hash)
661{
662 if (!room->host)
663 return;
664
665 send_srv_room_message (room, room->host, create_message_merge (hash));
666}
667
668int
669delete_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
670 struct GNUNET_MESSENGER_MemberSession *session,
671 const struct GNUNET_HashCode *hash,
672 const struct GNUNET_TIME_Relative delay)
673{
674 GNUNET_assert((room) && (session) && (hash));
675
676 const struct GNUNET_TIME_Relative forever = GNUNET_TIME_relative_get_forever_ ();
677
678 if (0 == GNUNET_memcmp(&forever, &delay))
679 {
680 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Deletion is delayed forever: operation is impossible!\n");
681 return GNUNET_SYSERR;
682 }
683
684 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
685
686 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
687
688 if (!message)
689 return GNUNET_YES;
690
691 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_YES))
692 {
693 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unpermitted request for deletion by member (%s) of message (%s)!\n",
694 GNUNET_sh2s(get_member_session_id(session)), GNUNET_h2s(hash));
695
696 return GNUNET_NO;
697 }
698
699 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(room);
700
701 if (GNUNET_OK != use_store_operation(operation_store, hash, GNUNET_MESSENGER_OP_DELETE, delay))
702 {
703 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Deletion has failed: operation denied!\n");
704 return GNUNET_SYSERR;
705 }
706
707 return GNUNET_YES;
708}
709
710struct GNUNET_CADET_Handle*
711get_srv_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
712{
713 GNUNET_assert(room);
714
715 return room->service->cadet;
716}
717
718const struct GNUNET_HashCode*
719get_srv_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
720{
721 GNUNET_assert(room);
722
723 return &(room->key);
724}
725
726const struct GNUNET_MESSENGER_SrvTunnel*
727get_srv_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room,
728 const struct GNUNET_PeerIdentity *peer)
729{
730 GNUNET_assert((room) && (peer));
731
732 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
733}
734
735static int
736request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room,
737 const struct GNUNET_HashCode *hash,
738 const struct GNUNET_MESSENGER_MemberSession *session,
739 GNUNET_MESSENGER_MessageRequestCallback callback,
740 void* cls)
741{
742 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
743
744 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link(
745 message_store, hash, GNUNET_YES
746 );
747
748 if (!link)
749 goto forward;
750
751 int result = request_room_message_step(room, &(link->first), session, callback, cls);
752
753 if ((GNUNET_YES == link->multiple) &&
754 (GNUNET_YES == request_room_message_step(room, &(link->second), session, callback, cls)))
755 return GNUNET_YES;
756 else
757 return result;
758
759forward:
760 if (GNUNET_YES != check_member_session_history(session, hash, GNUNET_NO))
761 return GNUNET_YES;
762
763 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
764
765 if (!message)
766 return GNUNET_NO;
767
768 if (callback)
769 callback (cls, room, message, hash);
770
771 return GNUNET_YES;
772}
773
774int
775request_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
776 const struct GNUNET_HashCode *hash,
777 const struct GNUNET_MESSENGER_MemberSession *session,
778 GNUNET_MESSENGER_MessageRequestCallback callback,
779 void* cls)
780{
781 GNUNET_assert((room) && (hash));
782
783 int result = request_room_message_step (room, hash, session, callback, cls);
784
785 if ((GNUNET_NO == result) && (callback))
786 callback (cls, room, NULL, hash);
787
788 return result;
789}
790
791void
792callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
793 void *cls)
794{
795 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
796
797 if (!room->host)
798 return;
799
800 struct GNUNET_PeerIdentity identity;
801 get_tunnel_peer_identity(tunnel, &identity);
802
803 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels, &identity, tunnel)) ||
804 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains(room->tunnels, &identity)))
805 return;
806
807 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
808 send_srv_room_message (room, room->host, create_message_miss (&identity));
809}
810
811int
812callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
813 void *cls,
814 struct GNUNET_MESSENGER_Message *message,
815 struct GNUNET_HashCode *hash)
816{
817 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
818 {
819 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Kind is unknown! (%d)\n", message->header.kind);
820 return GNUNET_SYSERR;
821 }
822
823 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
824
825 const struct GNUNET_MESSENGER_Message *previous = get_store_message(message_store, &(message->header.previous));
826
827 if (!previous)
828 goto skip_time_comparison;
829
830 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh(message->header.timestamp);
831 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh(previous->header.timestamp);
832
833 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(timestamp, last).rel_value_us)
834 {
835 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Message error: Timestamp does not check out!\n");
836 return GNUNET_SYSERR;
837 }
838
839skip_time_comparison:
840 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
841 GNUNET_MESSENGER_name_of_kind(message->header.kind));
842
843 return GNUNET_OK;
844}
845
846static void
847idle_request_room_messages (void *cls)
848{
849 struct GNUNET_MESSENGER_SrvRoom *room = cls;
850
851 room->idle = NULL;
852
853 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(room);
854 const struct GNUNET_HashCode *hash = get_message_state_merge_hash(&(room->state));
855
856 if ((hash) &&
857 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type(operation_store, hash)))
858 use_store_operation(
859 operation_store,
860 hash,
861 GNUNET_MESSENGER_OP_MERGE,
862 GNUNET_MESSENGER_MERGE_DELAY
863 );
864
865 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
866 GNUNET_MESSENGER_IDLE_DELAY,
867 GNUNET_SCHEDULER_PRIORITY_IDLE,
868 idle_request_room_messages,
869 cls
870 );
871}
872
873void
874solve_srv_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room,
875 const struct GNUNET_IDENTITY_PublicKey *public_key,
876 const struct GNUNET_ShortHashCode *member_id,
877 struct GNUNET_TIME_Absolute timestamp)
878{
879 GNUNET_assert ((room) && (public_key) && (member_id));
880
881 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
882 struct GNUNET_MESSENGER_Member *member = get_store_member(member_store, member_id);
883
884 if ((!member) || (1 >= GNUNET_CONTAINER_multihashmap_size(member->sessions)))
885 return;
886
887 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
888 struct GNUNET_MESSENGER_ListHandle* element;
889
890 for (element = handles->head; element; element = element->next)
891 {
892 if (0 != GNUNET_memcmp(member_id, get_srv_handle_member_id(element->handle, get_srv_room_key(room))))
893 continue;
894
895 if (0 == GNUNET_memcmp(public_key, &(get_srv_handle_ego(element->handle)->pub)))
896 continue;
897
898 struct GNUNET_MESSENGER_MemberSession *session = get_member_session(member, &(get_srv_handle_ego(element->handle)->pub));
899
900 if (!session)
901 continue;
902
903 struct GNUNET_TIME_Absolute start = get_member_session_start(session);
904
905 if (GNUNET_TIME_relative_get_zero_().rel_value_us != GNUNET_TIME_absolute_get_difference(start, timestamp).rel_value_us)
906 continue;
907
908 struct GNUNET_ShortHashCode random_id;
909 generate_free_member_id (&random_id, member_store->members);
910
911 send_srv_room_message(room, element->handle, create_message_id(&random_id));
912 }
913}
914
915void
916rebuild_srv_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
917{
918 GNUNET_assert(room);
919
920 struct GNUNET_PeerIdentity peer;
921 size_t src;
922
923 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
924 (!find_list_tunnels (&(room->basement), &peer, &src)))
925 return;
926
927 size_t count = count_of_tunnels (&(room->basement));
928
929 struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head;
930 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
931
932 size_t dst = 0;
933
934 while (element)
935 {
936 GNUNET_PEER_resolve (element->peer, &peer);
937
938 tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer);
939
940 if (!tunnel)
941 {
942 element = remove_from_list_tunnels (&(room->basement), element);
943 continue;
944 }
945
946 if (GNUNET_YES == required_connection_between (count, src, dst))
947 {
948 if (GNUNET_SYSERR == connect_tunnel (tunnel))
949 {
950 element = remove_from_list_tunnels (&(room->basement), element);
951 continue;
952 }
953 }
954 else
955 disconnect_tunnel (tunnel);
956
957 element = element->next;
958 dst++;
959 }
960}
961
962static void
963handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
964{
965 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
966 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
967
968 while (room->handling.head)
969 {
970 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
971
972 const struct GNUNET_MESSENGER_Message *message = get_store_message (message_store, &(element->hash));
973
974 if (!message)
975 goto finish_handling;
976
977 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
978
979 if (!member)
980 goto finish_handling;
981
982 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, &(element->hash));
983
984 if (session)
985 handle_service_message (room->service, room, session, message, &(element->hash));
986
987finish_handling:
988 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
989 GNUNET_free(element);
990 }
991}
992
993int
994update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
995 struct GNUNET_MESSENGER_Message *message,
996 const struct GNUNET_HashCode *hash)
997{
998 GNUNET_assert((room) && (message) && (hash));
999
1000 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(room);
1001
1002 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
1003 GNUNET_YES : GNUNET_NO
1004 );
1005
1006 if (GNUNET_YES == requested)
1007 cancel_store_operation(operation_store, hash);
1008
1009 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(room);
1010
1011 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (message_store, hash);
1012
1013 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n", GNUNET_h2s (get_srv_room_key(room)));
1014
1015 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash, message)))
1016 {
1017 if (old_message != message)
1018 destroy_message(message);
1019
1020 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
1021 return GNUNET_NO;
1022 }
1023
1024 update_message_state(&(room->state), requested, message, hash);
1025
1026 if ((GNUNET_YES == requested) ||
1027 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
1028 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
1029 return GNUNET_YES;
1030
1031 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
1032 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->body.merge.previous))))
1033 cancel_store_operation(operation_store, &(message->body.merge.previous));
1034
1035 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type(operation_store, &(message->header.previous)))
1036 cancel_store_operation(operation_store, &(message->header.previous));
1037
1038 return GNUNET_YES;
1039}
1040
1041struct GNUNET_MESSENGER_MemberSessionCompletion
1042{
1043 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
1044 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
1045
1046 struct GNUNET_MESSENGER_MemberSession *session;
1047};
1048
1049struct GNUNET_MESSENGER_MemberUpdate
1050{
1051 const struct GNUNET_MESSENGER_Message *message;
1052 const struct GNUNET_HashCode *hash;
1053
1054 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
1055 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
1056};
1057
1058static int
1059iterate_update_member_sessions (void *cls,
1060 const struct GNUNET_IDENTITY_PublicKey *public_key,
1061 struct GNUNET_MESSENGER_MemberSession *session)
1062{
1063 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
1064
1065 update_member_session_history(session, update->message, update->hash);
1066
1067 if (GNUNET_YES == is_member_session_completed(session))
1068 {
1069 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new(
1070 struct GNUNET_MESSENGER_MemberSessionCompletion
1071 );
1072
1073 element->session = session;
1074
1075 GNUNET_CONTAINER_DLL_insert_tail(update->head, update->tail, element);
1076 }
1077
1078 return GNUNET_YES;
1079}
1080
1081static void
1082remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1083 struct GNUNET_MESSENGER_MemberSession *session);
1084
1085void
1086callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
1087 struct GNUNET_MESSENGER_SrvHandle *handle,
1088 const struct GNUNET_MESSENGER_Message *message,
1089 const struct GNUNET_HashCode *hash)
1090{
1091 struct GNUNET_MESSENGER_MemberStore *member_store = get_srv_room_member_store(room);
1092 struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, message);
1093
1094 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", GNUNET_h2s (hash));
1095
1096 if (!member)
1097 {
1098 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is missing!\n");
1099 return;
1100 }
1101
1102 struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of(member, message, hash);
1103
1104 if (!session)
1105 {
1106 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session is missing!\n");
1107 return;
1108 }
1109
1110 struct GNUNET_MESSENGER_MemberUpdate update;
1111 update.message = message;
1112 update.hash = hash;
1113
1114 update.head = NULL;
1115 update.tail = NULL;
1116
1117 iterate_store_members(member_store, iterate_update_member_sessions, &update);
1118
1119 while (update.head)
1120 {
1121 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
1122
1123 remove_room_member_session (room, element->session);
1124
1125 GNUNET_CONTAINER_DLL_remove(update.head, update.tail, element);
1126 GNUNET_free (element);
1127 }
1128
1129 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
1130
1131 add_to_list_messages (&(room->handling), hash);
1132
1133 switch (message->header.kind)
1134 {
1135 case GNUNET_MESSENGER_KIND_JOIN:
1136 handle_message_join (room, session, message, hash);
1137 break;
1138 case GNUNET_MESSENGER_KIND_LEAVE:
1139 handle_message_leave (room, session, message, hash);
1140 break;
1141 case GNUNET_MESSENGER_KIND_NAME:
1142 handle_message_name (room, session, message, hash);
1143 break;
1144 case GNUNET_MESSENGER_KIND_KEY:
1145 handle_message_key (room, session, message, hash);
1146 break;
1147 case GNUNET_MESSENGER_KIND_PEER:
1148 handle_message_peer (room, session, message, hash);
1149 break;
1150 case GNUNET_MESSENGER_KIND_ID:
1151 handle_message_id (room, session, message, hash);
1152 break;
1153 case GNUNET_MESSENGER_KIND_MISS:
1154 handle_message_miss (room, session, message, hash);
1155 break;
1156 case GNUNET_MESSENGER_KIND_DELETE:
1157 handle_message_delete (room, session, message, hash);
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 if (GNUNET_YES == start_handle)
1164 handle_room_messages (room);
1165}
1166
1167static void
1168get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room,
1169 char **dir)
1170{
1171 GNUNET_assert((room) && (dir));
1172
1173 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms", DIR_SEPARATOR, GNUNET_h2s (get_srv_room_key(room)), DIR_SEPARATOR);
1174}
1175
1176void
1177load_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1178{
1179 GNUNET_assert(room);
1180
1181 char *room_dir;
1182 get_room_data_subdir (room, &room_dir);
1183
1184 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1185 {
1186 load_member_store (get_srv_room_member_store(room), room_dir);
1187 load_message_store (get_srv_room_message_store(room), room_dir);
1188 load_operation_store(get_srv_room_operation_store(room), room_dir);
1189
1190 char *basement_file;
1191 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1192
1193 load_list_tunnels(&(room->basement), basement_file);
1194 GNUNET_free(basement_file);
1195
1196 load_message_state(&(room->state), room_dir);
1197 }
1198
1199 GNUNET_free(room_dir);
1200}
1201
1202void
1203save_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1204{
1205 GNUNET_assert(room);
1206
1207 char *room_dir;
1208 get_room_data_subdir (room, &room_dir);
1209
1210 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1211 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1212 {
1213 save_member_store(get_srv_room_member_store(room), room_dir);
1214 save_message_store (get_srv_room_message_store(room), room_dir);
1215 save_operation_store(get_srv_room_operation_store(room), room_dir);
1216
1217 char *basement_file;
1218 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1219
1220 save_list_tunnels(&(room->basement), basement_file);
1221 GNUNET_free(basement_file);
1222
1223 save_message_state(&(room->state), room_dir);
1224 }
1225
1226 GNUNET_free(room_dir);
1227}
1228
1229void
1230remove_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1231{
1232 GNUNET_assert(room);
1233
1234 char *room_dir;
1235 get_room_data_subdir (room, &room_dir);
1236
1237 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1238 GNUNET_DISK_directory_remove(room_dir);
1239
1240 GNUNET_free(room_dir);
1241}
1242
1243static void
1244remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1245 struct GNUNET_MESSENGER_MemberSession *session)
1246{
1247 GNUNET_assert ((room) && (session));
1248
1249 remove_member_session (session->member, session);
1250
1251 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
1252
1253 struct GNUNET_HashCode hash;
1254 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
1255
1256 char *room_dir;
1257 get_room_data_subdir (room, &room_dir);
1258
1259 char* session_dir;
1260 GNUNET_asprintf (
1261 &session_dir, "%s%s%c%s%c%s%c%s%c", room_dir,
1262 "members", DIR_SEPARATOR,
1263 GNUNET_sh2s(get_member_session_id(session)), DIR_SEPARATOR,
1264 "sessions", DIR_SEPARATOR,
1265 GNUNET_h2s(&hash), DIR_SEPARATOR
1266 );
1267
1268 GNUNET_free (room_dir);
1269
1270 GNUNET_DISK_directory_remove(session_dir);
1271 GNUNET_free (session_dir);
1272
1273 destroy_member_session(session);
1274}
diff --git a/src/messenger/gnunet-service-messenger_room.h b/src/messenger/gnunet-service-messenger_room.h
deleted file mode 100644
index 2e9382595..000000000
--- a/src/messenger/gnunet-service-messenger_room.h
+++ /dev/null
@@ -1,378 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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_util_lib.h"
32#include "gnunet_identity_service.h"
33
34#include "gnunet_messenger_service.h"
35#include "gnunet-service-messenger_basement.h"
36#include "gnunet-service-messenger_handle.h"
37#include "gnunet-service-messenger_message_state.h"
38#include "gnunet-service-messenger_list_messages.h"
39
40#include "messenger_api_list_tunnels.h"
41
42#include "gnunet-service-messenger_member_store.h"
43#include "gnunet-service-messenger_message_store.h"
44#include "gnunet-service-messenger_operation_store.h"
45#include "messenger_api_ego.h"
46
47#define GNUNET_MESSENGER_IDLE_DELAY GNUNET_TIME_relative_multiply \
48 (GNUNET_TIME_relative_get_second_ (), 5)
49
50#define GNUNET_MESSENGER_REQUEST_DELAY GNUNET_TIME_relative_multiply \
51 (GNUNET_TIME_relative_get_minute_ (), 5)
52
53#define GNUNET_MESSENGER_MERGE_DELAY GNUNET_TIME_relative_multiply \
54 (GNUNET_TIME_relative_get_second_ (), 30)
55
56struct GNUNET_MESSENGER_SrvTunnel;
57struct GNUNET_MESSENGER_MemberSession;
58
59struct GNUNET_MESSENGER_SrvRoom
60{
61 struct GNUNET_MESSENGER_Service *service;
62 struct GNUNET_MESSENGER_SrvHandle *host;
63 struct GNUNET_CADET_Port *port;
64
65 struct GNUNET_HashCode key;
66
67 struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
68
69 struct GNUNET_MESSENGER_MemberStore member_store;
70 struct GNUNET_MESSENGER_MessageStore message_store;
71 struct GNUNET_MESSENGER_OperationStore operation_store;
72
73 struct GNUNET_MESSENGER_ListTunnels basement;
74 struct GNUNET_MESSENGER_MessageState state;
75
76 struct GNUNET_HashCode *peer_message;
77
78 struct GNUNET_MESSENGER_ListMessages handling;
79 struct GNUNET_SCHEDULER_Task *idle;
80};
81
82/**
83 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i>.
84 *
85 * @param[in,out] handle Handle
86 * @param[in] key Key of room
87 * @return New room
88 */
89struct GNUNET_MESSENGER_SrvRoom*
90create_srv_room (struct GNUNET_MESSENGER_SrvHandle *handle,
91 const struct GNUNET_HashCode *key);
92
93/**
94 * Destroys a room and frees its memory fully.
95 *
96 * The <i>deletion</i> flag should only be set to #GNUNET_YES if the
97 * room gets dropped by the service, otherwise #GNUNET_NO.
98 *
99 * @param[in,out] room Room
100 * @param[in] deletion Flag to indicate context of destruction
101 */
102void
103destroy_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
104 int deletion);
105
106/**
107 * Returns the used member store of a given <i>room</i>.
108 *
109 * @param[in,out] room Room
110 * @return Member store
111 */
112struct GNUNET_MESSENGER_MemberStore*
113get_srv_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room);
114
115/**
116 * Returns the used message store of a given <i>room</i>.
117 *
118 * @param[in,out] room Room
119 * @return Message store
120 */
121struct GNUNET_MESSENGER_MessageStore*
122get_srv_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room);
123
124/**
125 * Returns the used operation store of a given <i>room</i>.
126 *
127 * @param[in,out] room Room
128 * @return Operation store
129 */
130struct GNUNET_MESSENGER_OperationStore*
131get_srv_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room);
132
133/**
134 * Tries to open a <i>room</i> for a given <i>handle</i>. If the room has already been opened, the handle
135 * will locally join the room.
136 *
137 * Calling this method should result in joining a room and sending a peer message as well for this peer.
138 *
139 * If the function returns #GNUNET_YES the port for this room is guaranteed to be open for incoming connections.
140 *
141 * @param[in,out] room Room
142 * @param[in,out] handle Handle
143 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
144 */
145int
146open_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
147 struct GNUNET_MESSENGER_SrvHandle *handle);
148
149/**
150 * Connects a tunnel to a hosting peer of a <i>room</i> through a so called <i>door</i> which is represented by
151 * a peer identity of a hosting peer. During the connection the handle will join the room as a member, waiting for
152 * an info message from the selected host.
153 *
154 * @param[in,out] room Room
155 * @param[in,out] handle Handle
156 * @param[in] door Peer identity
157 * @return #GNUNET_YES on success, #GNUNET_NO on failure.
158 */
159int
160enter_srv_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
161 struct GNUNET_MESSENGER_SrvHandle *handle,
162 const struct GNUNET_PeerIdentity *door);
163
164/**
165 * Packs a <i>message</i> depending on the selected <i>mode</i> into a newly allocated envelope. It will set the
166 * timestamp of the message, the sender id and the previous messages hash automatically before packing. The message
167 * will be signed by the handles EGO.
168 *
169 * If the optional <i>hash</i> parameter is a valid pointer, its value will be overridden by the signed messages hash.
170 *
171 * If <i>mode</i> is set to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE, the function returns a valid envelope to send
172 * through a message queue, otherwise NULL.
173 *
174 * @param[in] room Room
175 * @param[in] handle Handle
176 * @param[in,out] message Message
177 * @param[out] hash Hash of message
178 * @param[in] mode Packing mode
179 * @return New envelope or NULL
180 */
181struct GNUNET_MQ_Envelope*
182pack_srv_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
183 const struct GNUNET_MESSENGER_SrvHandle *handle,
184 struct GNUNET_MESSENGER_Message *message,
185 struct GNUNET_HashCode *hash,
186 int mode);
187
188/**
189 * Sends a <i>message</i> from a given <i>handle</i> into a <i>room</i>. The <i>hash</i> parameter will be
190 * updated with the hash-value resulting from the sent message.
191 *
192 * The function handles packing the message automatically and will call linked message-events locally even if
193 * the message won't be sent to another peer.
194 *
195 * The function returns #GNUNET_YES on success, #GNUNET_NO if message is null and
196 * #GNUNET_SYSERR if the message was known already.
197 *
198 * @param[in,out] room Room
199 * @param[in,out] handle Handle
200 * @param[in,out] message Message
201 * @return #GNUNET_YES on success, #GNUNET_NO or #GNUNET_SYSERR otherwise.
202 */
203int
204send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
205 struct GNUNET_MESSENGER_SrvHandle *handle,
206 struct GNUNET_MESSENGER_Message *message);
207
208/**
209 * Forwards a <i>message</i> with a given <i>hash</i> to a specific <i>tunnel</i> inside of a <i>room</i>.
210 *
211 * @param[in,out] room Room
212 * @param[in,out] tunnel Tunnel
213 * @param[in,out] message Message
214 * @param[in] hash Hash of message
215 */
216void
217forward_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
218 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
219 struct GNUNET_MESSENGER_Message *message,
220 const struct GNUNET_HashCode *hash);
221
222/**
223 * Checks the current state of opening a given <i>room</i> from this peer and re-publishes it
224 * if necessary to a selected <i>tunnel</i> or to all connected tunnels if necessary or if the
225 * selected tunnel is NULL.
226 *
227 * @param[in,out] room Room
228 * @param[in,out] tunnel Tunnel
229 */
230void
231check_srv_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room,
232 struct GNUNET_MESSENGER_SrvTunnel *tunnel);
233
234/**
235 * Reduces all current forks inside of the message history of a <i>room</i> to one remaining last message
236 * by merging them down. All merge messages will be sent from a given <i>handle</i>.
237 *
238 * @param[in,out] room Room
239 * @param[in,out] handle Handle
240 */
241void
242merge_srv_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room,
243 struct GNUNET_MESSENGER_SrvHandle *handle);
244
245/**
246 * Deletes a message from the <i>room</i> with a given <i>hash</i> in a specific <i>delay</i> if
247 * the provided member by its session is permitted to do so.
248 *
249 * @param[in,out] room Room
250 * @param[in,out] session Member session
251 * @param[in] hash Hash of message
252 * @param[in] delay Delay of deletion
253 * @return #GNUNET_YES on success, #GNUNET_NO if permission gets denied, #GNUNET_SYSERR on operation failure
254 */
255int
256delete_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
257 struct GNUNET_MESSENGER_MemberSession *session,
258 const struct GNUNET_HashCode *hash,
259 const struct GNUNET_TIME_Relative delay);
260
261/**
262 * Returns the CADET handle from a rooms service.
263 *
264 * @param[in,out] room Room
265 * @return CADET handle
266 */
267struct GNUNET_CADET_Handle*
268get_srv_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room);
269
270/**
271 * Returns the shared secret you need to access a <i>room</i>.
272 *
273 * @param[in] room Room
274 * @return Shared secret
275 */
276const struct GNUNET_HashCode*
277get_srv_room_key (const struct GNUNET_MESSENGER_SrvRoom *room);
278
279/**
280 * Returns a tunnel inside of a <i>room</i> leading towards a given <i>peer</i> if such a tunnel exists,
281 * otherwise NULL.
282 *
283 * @param[in] room Room
284 * @param[in] peer Peer identity
285 * @return Tunnel or NULL
286 */
287const struct GNUNET_MESSENGER_SrvTunnel*
288get_srv_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room,
289 const struct GNUNET_PeerIdentity *peer);
290
291/**
292 * Method called whenever a <i>message</i> is found during a request in a <i>room</i>.
293 *
294 * @param[in,out] cls Closure from #request_room_message
295 * @param[in,out] room Room
296 * @param[in] message Message or NULL
297 * @param[in] hash Hash of message
298 */
299typedef void (GNUNET_MESSENGER_MessageRequestCallback) (
300 void *cls,
301 struct GNUNET_MESSENGER_SrvRoom *room,
302 const struct GNUNET_MESSENGER_Message *message,
303 const struct GNUNET_HashCode *hash
304);
305
306/**
307 * Requests a message from a <i>room</i> identified by a given <i>hash</i>. If the message is found,
308 * the selected <i>callback</i> will be called with it and the provided closure. If no matching message
309 * is found but it wasn't deleted the selected callback will be called with #NULL as message instead.
310 * In case of deletion the next available previous message will be used to call the callback.
311 *
312 * It is also possible that the given callback will not be called if the requesting session is not
313 * permitted!
314 *
315 * @param[in,out] room Room
316 * @param[in] hash Hash of message
317 * @param[in] callback Callback to process result
318 * @param[in] cls Closure for the <i>callback</i>
319 * @return #GNUNET_YES if the request could be processed, otherwise #GNUNET_NO
320 */
321int
322request_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
323 const struct GNUNET_HashCode *hash,
324 const struct GNUNET_MESSENGER_MemberSession *session,
325 GNUNET_MESSENGER_MessageRequestCallback callback,
326 void* cls);
327
328/**
329 * Checks for potential collisions with member ids and solves them changing active handles ids if they
330 * use an already used member id (comparing public key and timestamp).
331 *
332 * @param[in,out] room Room
333 * @param[in] public_key Public key of EGO
334 * @param[in] member_id Member ID
335 * @param[in] timestamp Timestamp
336 */
337void
338solve_srv_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room,
339 const struct GNUNET_IDENTITY_PublicKey *public_key,
340 const struct GNUNET_ShortHashCode *member_id,
341 struct GNUNET_TIME_Absolute timestamp);
342
343/**
344 * Rebuilds the decentralized structure for a <i>room</i> by ensuring all required connections are made
345 * depending on the amount of peers and this peers index in the list of them.
346 *
347 * @param[in,out] room Room
348 */
349void
350rebuild_srv_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room);
351
352/**
353 * Loads the local configuration for a given <i>room</i> of a service which contains the last messages hash
354 * and the ruleset for general access of new members.
355 *
356 * @param[out] room Room
357 */
358void
359load_srv_room (struct GNUNET_MESSENGER_SrvRoom *room);
360
361/**
362 * Saves the configuration for a given <i>room</i> of a service which contains the last messages hash
363 * and the ruleset for general access of new members locally.
364 *
365 * @param[in] room Room
366 */
367void
368save_srv_room (struct GNUNET_MESSENGER_SrvRoom *room);
369
370/**
371 * Removes the configuration for a given <i>room</i> of a service.
372 *
373 * @param[in] room Room
374 */
375void
376remove_srv_room (struct GNUNET_MESSENGER_SrvRoom *room);
377
378#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 8dfc258c1..000000000
--- a/src/messenger/gnunet-service-messenger_service.c
+++ /dev/null
@@ -1,320 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_service.h"
28#include "gnunet-service-messenger_message_kind.h"
29#include "gnunet-service-messenger.h"
30
31static void
32callback_shutdown_service (void *cls)
33{
34 struct GNUNET_MESSENGER_Service *service = cls;
35
36 if (service)
37 {
38 service->shutdown = NULL;
39
40 destroy_service (service);
41 }
42}
43
44struct GNUNET_MESSENGER_Service*
45create_service (const struct GNUNET_CONFIGURATION_Handle *config,
46 struct GNUNET_SERVICE_Handle *service_handle)
47{
48 GNUNET_assert((config) && (service_handle));
49
50 struct GNUNET_MESSENGER_Service *service = GNUNET_new(struct GNUNET_MESSENGER_Service);
51
52 service->config = config;
53 service->service = service_handle;
54
55 service->shutdown = GNUNET_SCHEDULER_add_shutdown (&callback_shutdown_service, service);
56
57 service->dir = NULL;
58
59 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config,
60 GNUNET_MESSENGER_SERVICE_NAME,
61 "MESSENGER_DIR", &(service->dir)))
62 {
63 if (service->dir)
64 GNUNET_free(service->dir);
65
66 service->dir = NULL;
67 }
68 else
69 {
70 if ((GNUNET_YES != GNUNET_DISK_directory_test (service->dir, GNUNET_YES)) && (GNUNET_OK
71 != GNUNET_DISK_directory_create (service->dir)))
72 {
73 GNUNET_free(service->dir);
74
75 service->dir = NULL;
76 }
77 }
78
79 service->cadet = GNUNET_CADET_connect (service->config);
80
81 init_ego_store(get_service_ego_store(service), service->config);
82
83 init_list_handles (&(service->handles));
84
85 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
86
87 init_contact_store(get_service_contact_store(service));
88
89 return service;
90}
91
92static int
93iterate_destroy_rooms (void *cls,
94 const struct GNUNET_HashCode *key,
95 void *value)
96{
97 struct GNUNET_MESSENGER_SrvRoom *room = value;
98 destroy_srv_room (room, GNUNET_NO);
99 return GNUNET_YES;
100}
101
102void
103destroy_service (struct GNUNET_MESSENGER_Service *service)
104{
105 GNUNET_assert(service);
106
107 if (service->shutdown)
108 {
109 GNUNET_SCHEDULER_cancel (service->shutdown);
110
111 service->shutdown = NULL;
112 }
113
114 clear_ego_store(get_service_ego_store(service));
115 clear_list_handles (&(service->handles));
116
117 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms, NULL);
118 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
119
120 clear_contact_store(get_service_contact_store(service));
121
122 if (service->cadet)
123 {
124 GNUNET_CADET_disconnect (service->cadet);
125
126 service->cadet = NULL;
127 }
128
129 if (service->dir)
130 {
131 GNUNET_free(service->dir);
132
133 service->dir = NULL;
134 }
135
136 GNUNET_SERVICE_shutdown (service->service);
137
138 GNUNET_free(service);
139}
140
141struct GNUNET_MESSENGER_EgoStore*
142get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
143{
144 GNUNET_assert(service);
145
146 return &(service->ego_store);
147}
148
149struct GNUNET_MESSENGER_ContactStore*
150get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
151{
152 GNUNET_assert(service);
153
154 return &(service->contact_store);
155}
156
157struct GNUNET_MESSENGER_SrvHandle*
158add_service_handle (struct GNUNET_MESSENGER_Service *service,
159 struct GNUNET_MQ_Handle *mq)
160{
161 GNUNET_assert((service) && (mq));
162
163 struct GNUNET_MESSENGER_SrvHandle *handle = create_srv_handle (service, mq);
164
165 if (handle)
166 {
167 add_list_handle (&(service->handles), handle);
168 }
169
170 return handle;
171}
172
173void
174remove_service_handle (struct GNUNET_MESSENGER_Service *service,
175 struct GNUNET_MESSENGER_SrvHandle *handle)
176{
177 GNUNET_assert((service) && (handle));
178
179 if (!handle)
180 return;
181
182 if (GNUNET_YES == remove_list_handle (&(service->handles), handle))
183 destroy_srv_handle (handle);
184}
185
186int
187get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
188 struct GNUNET_PeerIdentity *peer)
189{
190 GNUNET_assert((service) && (peer));
191
192 return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
193}
194
195struct GNUNET_MESSENGER_SrvRoom*
196get_service_room (const struct GNUNET_MESSENGER_Service *service,
197 const struct GNUNET_HashCode *key)
198{
199 GNUNET_assert((service) && (key));
200
201 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
202}
203
204int
205open_service_room (struct GNUNET_MESSENGER_Service *service,
206 struct GNUNET_MESSENGER_SrvHandle *handle,
207 const struct GNUNET_HashCode *key)
208{
209 GNUNET_assert((service) && (handle) && (key));
210
211 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
212
213 if (room)
214 return open_srv_room (room, handle);
215
216 room = create_srv_room (handle, key);
217
218 if ((GNUNET_YES == open_srv_room (room, handle)) &&
219 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
220 key, room,
221 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
222 return GNUNET_YES;
223
224 destroy_srv_room (room, GNUNET_YES);
225 return GNUNET_NO;
226}
227
228int
229entry_service_room (struct GNUNET_MESSENGER_Service *service,
230 struct GNUNET_MESSENGER_SrvHandle *handle,
231 const struct GNUNET_PeerIdentity *door,
232 const struct GNUNET_HashCode *key)
233{
234 GNUNET_assert((service) && (handle) && (door) && (key));
235
236 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
237
238 if (room)
239 {
240 if (GNUNET_YES == enter_srv_room_at (room, handle, door))
241 return GNUNET_YES;
242 else
243 return GNUNET_NO;
244 }
245
246 room = create_srv_room (handle, key);
247
248 if ((GNUNET_YES == enter_srv_room_at (room, handle, door)) &&
249 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
250 key, room,
251 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
252 {
253 return GNUNET_YES;
254 }
255 else
256 {
257 destroy_srv_room (room, GNUNET_YES);
258 return GNUNET_NO;
259 }
260
261}
262
263int
264close_service_room (struct GNUNET_MESSENGER_Service *service,
265 struct GNUNET_MESSENGER_SrvHandle *handle,
266 const struct GNUNET_HashCode *key)
267{
268 GNUNET_assert((service) && (handle) && (key));
269
270 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
271
272 if (!room)
273 return GNUNET_NO;
274
275 send_srv_room_message (room, handle, create_message_leave ());
276
277 const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle, key);
278
279 GNUNET_assert(id);
280
281 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (handle->member_ids, key, id))
282 return GNUNET_NO;
283
284 struct GNUNET_MESSENGER_SrvHandle *member_handle = (struct GNUNET_MESSENGER_SrvHandle*) find_list_handle_by_member (
285 &(service->handles), key);
286
287 if (!member_handle)
288 {
289 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key, room))
290 {
291 destroy_srv_room (room, GNUNET_YES);
292 return GNUNET_YES;
293 }
294 else
295 return GNUNET_NO;
296 }
297
298 if (room->host == handle)
299 room->host = member_handle;
300
301 return GNUNET_YES;
302}
303
304void
305handle_service_message (struct GNUNET_MESSENGER_Service *service,
306 struct GNUNET_MESSENGER_SrvRoom *room,
307 const struct GNUNET_MESSENGER_MemberSession *session,
308 const struct GNUNET_MESSENGER_Message *message,
309 const struct GNUNET_HashCode *hash)
310{
311 GNUNET_assert((service) && (room) && (session) && (message) && (hash));
312
313 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
314
315 while (element)
316 {
317 notify_srv_handle_message (element->handle, room, session, message, hash);
318 element = element->next;
319 }
320}
diff --git a/src/messenger/gnunet-service-messenger_service.h b/src/messenger/gnunet-service-messenger_service.h
deleted file mode 100644
index 36df81141..000000000
--- a/src/messenger/gnunet-service-messenger_service.h
+++ /dev/null
@@ -1,210 +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_util_lib.h"
32#include "gnunet_identity_service.h"
33
34#include "gnunet-service-messenger_ego_store.h"
35#include "gnunet-service-messenger_list_handles.h"
36
37#include "messenger_api_contact_store.h"
38#include "gnunet-service-messenger_room.h"
39
40#include "gnunet-service-messenger_member_session.h"
41
42struct GNUNET_MESSENGER_Service
43{
44 const struct GNUNET_CONFIGURATION_Handle *config;
45 struct GNUNET_SERVICE_Handle *service;
46
47 struct GNUNET_SCHEDULER_Task *shutdown;
48
49 char *dir;
50
51 struct GNUNET_CADET_Handle *cadet;
52
53 struct GNUNET_MESSENGER_EgoStore ego_store;
54 struct GNUNET_MESSENGER_ContactStore contact_store;
55
56 struct GNUNET_MESSENGER_ListHandles handles;
57
58 struct GNUNET_CONTAINER_MultiHashMap *rooms;
59};
60
61/**
62 * Creates and allocates a new service using a given <i>config</i> and a GNUnet service handle.
63 *
64 * @param[in] config Configuration
65 * @param[in,out] service_handle GNUnet service handle
66 * @return New service
67 */
68struct GNUNET_MESSENGER_Service*
69create_service (const struct GNUNET_CONFIGURATION_Handle *config,
70 struct GNUNET_SERVICE_Handle *service_handle);
71
72/**
73 * Destroys a <i>service</i> and frees its memory fully.
74 *
75 * @param[in,out] service Service
76 */
77void
78destroy_service (struct GNUNET_MESSENGER_Service *service);
79
80/**
81 * Returns the used EGO-store of a given <i>service</i>.
82 *
83 * @param[in,out] service Service
84 * @return EGO-store
85 */
86struct GNUNET_MESSENGER_EgoStore*
87get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
88
89/**
90 * Returns the used contact store of a given <i>service</i>.
91 *
92 * @param[in,out] service Service
93 * @return Contact store
94 */
95struct GNUNET_MESSENGER_ContactStore*
96get_service_contact_store (struct GNUNET_MESSENGER_Service *service);
97
98/**
99 * Creates and adds a new handle to a <i>service</i> using a given message queue.
100 *
101 * @param[in,out] service Service
102 * @param[in,out] mq Message queue
103 * @return New handle
104 */
105struct GNUNET_MESSENGER_SrvHandle*
106add_service_handle (struct GNUNET_MESSENGER_Service *service,
107 struct GNUNET_MQ_Handle *mq);
108
109/**
110 * Removes a <i>handle</i> from a <i>service</i> and destroys it.
111 *
112 * @param[in,out] service Service
113 * @param[in,out] handle Handle
114 */
115void
116remove_service_handle (struct GNUNET_MESSENGER_Service *service,
117 struct GNUNET_MESSENGER_SrvHandle *handle);
118
119/**
120 * Tries to write the peer identity of the peer running a <i>service</i> on to the <i>peer</i>
121 * parameter. The functions returns #GNUNET_OK on success, otherwise #GNUNET_SYSERR.
122 *
123 * @param[in] service Service
124 * @param[out] peer Peer identity
125 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
126 */
127int
128get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
129 struct GNUNET_PeerIdentity *peer);
130
131/**
132 * Returns the room identified by a given <i>key</i> for a <i>service</i>. If the service doesn't know any room
133 * using the given key, NULL gets returned.
134 *
135 * @param[in] service Service
136 * @param[in] key Key of room
137 * @return Room or NULL
138 */
139struct GNUNET_MESSENGER_SrvRoom*
140get_service_room (const struct GNUNET_MESSENGER_Service *service,
141 const struct GNUNET_HashCode *key);
142
143/**
144 * 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
145 * created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
146 *
147 * @param[in,out] service Service
148 * @param[in,out] handle Handle
149 * @param[in] key Key of room
150 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
151 */
152int
153open_service_room (struct GNUNET_MESSENGER_Service *service,
154 struct GNUNET_MESSENGER_SrvHandle *handle,
155 const struct GNUNET_HashCode *key);
156
157/**
158 * 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
159 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
160 *
161 * The room will be entered through the peer identitied by the peer identity provided as <i>door</i> parameter and
162 * a new connection will be made.
163 *
164 * @param[in,out] service Service
165 * @param[in,out] handle Handle
166 * @param[in] door Peer identity
167 * @param[in] key Key of room
168 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
169 */
170int
171entry_service_room (struct GNUNET_MESSENGER_Service *service,
172 struct GNUNET_MESSENGER_SrvHandle *handle,
173 const struct GNUNET_PeerIdentity *door,
174 const struct GNUNET_HashCode *key);
175
176/**
177 * 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
178 * be created if necessary. If the function is successful, it returns #GNUNET_YES, otherwise #GNUNET_NO.
179 *
180 * If the specific handle is currently the host of the room for this service, a new handle which is a member will
181 * take its place. Otherwise the room will be destroyed for this service.
182 *
183 * @param[in,out] service Service
184 * @param[in,out] handle Handle
185 * @param[in] key Key of room
186 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
187 */
188int
189close_service_room (struct GNUNET_MESSENGER_Service *service,
190 struct GNUNET_MESSENGER_SrvHandle *handle,
191 const struct GNUNET_HashCode *key);
192
193/**
194 * Sends a received or sent <i>message</i> with a given <i>hash</i> to each handle of a <i>service</i> which
195 * is currently member of a specific <i>room</i> for handling it in the client API.
196 *
197 * @param[in,out] service Service
198 * @param[in,out] room Room
199 * @param[in] session Member session
200 * @param[in] message Message
201 * @param[in] hash Hash of message
202 */
203void
204handle_service_message (struct GNUNET_MESSENGER_Service *service,
205 struct GNUNET_MESSENGER_SrvRoom *room,
206 const struct GNUNET_MESSENGER_MemberSession *session,
207 const struct GNUNET_MESSENGER_Message *message,
208 const struct GNUNET_HashCode *hash);
209
210#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 8ad7fff1c..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ /dev/null
@@ -1,403 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2022 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 "platform.h"
27#include "gnunet-service-messenger_tunnel.h"
28
29#include "gnunet-service-messenger_handle.h"
30#include "gnunet-service-messenger_message_recv.h"
31#include "gnunet-service-messenger_message_store.h"
32#include "gnunet-service-messenger_operation_store.h"
33#include "gnunet-service-messenger_operation.h"
34#include "messenger_api_util.h"
35
36struct GNUNET_MESSENGER_SrvTunnel*
37create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room,
38 const struct GNUNET_PeerIdentity *door)
39{
40 GNUNET_assert((room) && (door));
41
42 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_new(struct GNUNET_MESSENGER_SrvTunnel);
43
44 tunnel->room = room;
45 tunnel->channel = NULL;
46
47 tunnel->peer = GNUNET_PEER_intern (door);
48
49 tunnel->messenger_version = 0;
50
51 tunnel->peer_message = NULL;
52
53 init_message_state(&(tunnel->state));
54
55 return tunnel;
56}
57
58void
59destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
60{
61 GNUNET_assert(tunnel);
62
63 if (tunnel->channel)
64 GNUNET_CADET_channel_destroy (tunnel->channel);
65
66 GNUNET_PEER_change_rc (tunnel->peer, -1);
67
68 if (tunnel->peer_message)
69 GNUNET_free(tunnel->peer_message);
70
71 clear_message_state(&(tunnel->state));
72
73 GNUNET_free(tunnel);
74}
75
76void
77bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
78 struct GNUNET_CADET_Channel *channel)
79{
80 GNUNET_assert(tunnel);
81
82 if (tunnel->channel)
83 delayed_disconnect_channel (tunnel->channel);
84
85 tunnel->channel = channel;
86}
87
88extern void
89callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
90 void *cls);
91
92void
93callback_tunnel_disconnect (void *cls,
94 const struct GNUNET_CADET_Channel *channel)
95{
96 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
97
98 if (tunnel)
99 {
100 tunnel->channel = NULL;
101
102 callback_room_disconnect (tunnel->room, cls);
103 }
104}
105
106extern int
107callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
108 void *cls,
109 struct GNUNET_MESSENGER_Message *message,
110 struct GNUNET_HashCode *hash);
111
112int
113check_tunnel_message (void *cls,
114 const struct GNUNET_MessageHeader *header)
115{
116 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
117
118 if (!tunnel)
119 return GNUNET_SYSERR;
120
121 const uint16_t length = ntohs (header->size) - sizeof(*header);
122 const char *buffer = (const char*) &header[1];
123
124 struct GNUNET_MESSENGER_Message message;
125
126 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES))
127 {
128 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Message too short! (%d)\n", length);
129 return GNUNET_SYSERR;
130 }
131
132 uint16_t padding = 0;
133
134 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, &padding))
135 {
136 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Tunnel error: Decoding failed!\n");
137 return GNUNET_SYSERR;
138 }
139
140 struct GNUNET_HashCode hash;
141 hash_message (&message, length - padding, buffer, &hash);
142
143 return callback_verify_room_message (tunnel->room, cls, &message, &hash);
144}
145
146extern int
147update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
148 struct GNUNET_MESSENGER_Message *message,
149 const struct GNUNET_HashCode *hash);
150
151extern void
152callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
153 struct GNUNET_MESSENGER_SrvHandle *handle,
154 const struct GNUNET_MESSENGER_Message *message,
155 const struct GNUNET_HashCode *hash);
156
157static void
158update_tunnel_last_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
159 const struct GNUNET_HashCode *hash)
160{
161 struct GNUNET_MESSENGER_OperationStore *operation_store = get_srv_room_operation_store(tunnel->room);
162
163 const int requested = (GNUNET_MESSENGER_OP_REQUEST == get_store_operation_type(operation_store, hash)?
164 GNUNET_YES : GNUNET_NO
165 );
166
167 struct GNUNET_MESSENGER_MessageStore *message_store = get_srv_room_message_store(tunnel->room);
168
169 const struct GNUNET_MESSENGER_Message *message = get_store_message(message_store, hash);
170
171 if (message)
172 update_message_state(&(tunnel->state), requested, message, hash);
173}
174
175void
176handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header)
177{
178 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
179
180 if (!tunnel)
181 return;
182
183 const uint16_t length = ntohs (header->size) - sizeof(*header);
184 const char *buffer = (const char*) &header[1];
185
186 struct GNUNET_MESSENGER_Message message;
187 struct GNUNET_HashCode hash;
188
189 uint16_t padding = 0;
190
191 decode_message (&message, length, buffer, GNUNET_YES, &padding);
192 hash_message (&message, length - padding, buffer, &hash);
193
194 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Got message of kind: %s!\n",
195 GNUNET_MESSENGER_name_of_kind(message.header.kind));
196
197 const int new_message = update_room_message (
198 tunnel->room, copy_message (&message), &hash
199 );
200
201 if (GNUNET_YES != new_message)
202 goto receive_done;
203
204 update_tunnel_last_message (tunnel, &hash);
205
206 int forward_message = GNUNET_YES;
207
208 switch (message.header.kind)
209 {
210 case GNUNET_MESSENGER_KIND_INFO:
211 forward_message = recv_message_info (tunnel->room, tunnel, &message, &hash);
212 break;
213 case GNUNET_MESSENGER_KIND_PEER:
214 forward_message = recv_message_peer (tunnel->room, tunnel, &message, &hash);
215 break;
216 case GNUNET_MESSENGER_KIND_REQUEST:
217 forward_message = recv_message_request (tunnel->room, tunnel, &message, &hash);
218 break;
219 default:
220 break;
221 }
222
223 if (GNUNET_YES == forward_message)
224 {
225 forward_srv_room_message (tunnel->room, tunnel, &message, &hash);
226 callback_room_handle_message (tunnel->room, NULL, &message, &hash);
227 }
228
229receive_done:
230 cleanup_message(&message);
231
232 GNUNET_CADET_receive_done (tunnel->channel);
233}
234
235int
236connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
237{
238 GNUNET_assert(tunnel);
239
240 if (tunnel->channel)
241 return GNUNET_NO;
242
243 const struct GNUNET_PeerIdentity *door = GNUNET_PEER_resolve2 (tunnel->peer);
244
245 struct GNUNET_CADET_Handle *cadet = get_srv_room_cadet (tunnel->room);
246 const struct GNUNET_HashCode *key = get_srv_room_key (tunnel->room);
247
248 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
249 struct GNUNET_MessageHeader, NULL),
250 GNUNET_MQ_handler_end() };
251
252 struct GNUNET_HashCode port;
253 convert_messenger_key_to_port(key, &port);
254 tunnel->channel = GNUNET_CADET_channel_create (cadet, tunnel, door, &port, NULL, callback_tunnel_disconnect, handlers);
255
256 return GNUNET_YES;
257}
258
259void
260disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel)
261{
262 GNUNET_assert(tunnel);
263
264 if (tunnel->channel)
265 {
266 delayed_disconnect_channel (tunnel->channel);
267
268 tunnel->channel = NULL;
269 }
270}
271
272int
273is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
274{
275 GNUNET_assert(tunnel);
276
277 return (tunnel->channel ? GNUNET_YES : GNUNET_NO);
278}
279
280struct GNUNET_MESSENGER_MessageSent
281{
282 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
283 struct GNUNET_HashCode hash;
284};
285
286static void
287callback_tunnel_sent (void *cls)
288{
289 struct GNUNET_MESSENGER_MessageSent *sent = cls;
290
291 if (sent->tunnel)
292 update_tunnel_last_message (sent->tunnel, &(sent->hash));
293
294 GNUNET_free(sent);
295}
296
297void
298send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
299 struct GNUNET_MQ_Envelope *env,
300 const struct GNUNET_HashCode *hash)
301{
302 GNUNET_assert((tunnel) && (env) && (hash));
303
304 struct GNUNET_MQ_Handle *mq = GNUNET_CADET_get_mq (tunnel->channel);
305
306 struct GNUNET_MESSENGER_MessageSent *sent = GNUNET_new(struct GNUNET_MESSENGER_MessageSent);
307
308 GNUNET_memcpy(&(sent->hash), hash, sizeof(struct GNUNET_HashCode));
309
310 sent->tunnel = tunnel;
311
312 GNUNET_MQ_notify_sent (env, callback_tunnel_sent, sent);
313 GNUNET_MQ_send (mq, env);
314}
315
316int
317send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
318 void *handle,
319 struct GNUNET_MESSENGER_Message *message)
320{
321 GNUNET_assert((tunnel) && (handle));
322
323 if (!message)
324 return GNUNET_NO;
325
326 struct GNUNET_HashCode hash;
327 struct GNUNET_MQ_Envelope *env = pack_srv_room_message (
328 tunnel->room, (struct GNUNET_MESSENGER_SrvHandle*) handle,
329 message, &hash, GNUNET_MESSENGER_PACK_MODE_ENVELOPE
330 );
331
332 destroy_message(message);
333
334 if (!env)
335 return GNUNET_NO;
336
337 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Sending tunnel message: %s\n",
338 GNUNET_h2s(&hash));
339
340 send_tunnel_envelope (tunnel, env, &hash);
341 return GNUNET_YES;
342}
343
344void
345forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
346 const struct GNUNET_MESSENGER_Message *message,
347 const struct GNUNET_HashCode *hash)
348{
349 GNUNET_assert((tunnel) && (message) && (hash));
350
351 struct GNUNET_MESSENGER_Message *copy = copy_message(message);
352 struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
353
354 destroy_message(copy);
355
356 if (!env)
357 return;
358
359 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Forwarding tunnel message: %s\n",
360 GNUNET_h2s(hash));
361
362 send_tunnel_envelope (tunnel, env, hash);
363}
364
365const struct GNUNET_HashCode*
366get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
367{
368 GNUNET_assert(tunnel);
369
370 return tunnel->peer_message;
371}
372
373void
374get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel,
375 struct GNUNET_PeerIdentity *peer)
376{
377 GNUNET_assert(tunnel);
378
379 GNUNET_PEER_resolve(tunnel->peer, peer);
380}
381
382uint32_t
383get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel)
384{
385 GNUNET_assert(tunnel);
386
387 return tunnel->messenger_version;
388}
389
390int
391update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
392 uint32_t version)
393{
394 GNUNET_assert(tunnel);
395
396 if (version != GNUNET_MESSENGER_VERSION)
397 return GNUNET_SYSERR;
398
399 if (version > tunnel->messenger_version)
400 tunnel->messenger_version = version;
401
402 return GNUNET_OK;
403}
diff --git a/src/messenger/gnunet-service-messenger_tunnel.h b/src/messenger/gnunet-service-messenger_tunnel.h
deleted file mode 100644
index 2ffa2d04f..000000000
--- a/src/messenger/gnunet-service-messenger_tunnel.h
+++ /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/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_util_lib.h"
32
33#include "gnunet-service-messenger_room.h"
34#include "gnunet-service-messenger_message_state.h"
35
36struct GNUNET_MESSENGER_SrvTunnel
37{
38 struct GNUNET_MESSENGER_SrvRoom *room;
39 struct GNUNET_CADET_Channel *channel;
40
41 GNUNET_PEER_Id peer;
42
43 uint32_t messenger_version;
44
45 struct GNUNET_HashCode *peer_message;
46 struct GNUNET_MESSENGER_MessageState state;
47};
48
49/**
50 * Creates and allocates a tunnel of a <i>room</i> to a specific peer identity (called <i>door</i>).
51 *
52 * @param[in,out] room Room
53 * @param[in] door Peer identity
54 * @return New tunnel
55 */
56struct GNUNET_MESSENGER_SrvTunnel*
57create_tunnel (struct GNUNET_MESSENGER_SrvRoom *room,
58 const struct GNUNET_PeerIdentity *door);
59
60/**
61 * Destroys a <i>tunnel</i> and frees its memory fully.
62 *
63 * @param[in,out] tunnel
64 */
65void
66destroy_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
67
68/**
69 * Binds a CADET <i>channel</i> to a <i>tunnel</i> and replaces its channel
70 * the tunnel is currently bound to if necessary.
71 *
72 * @param[in,out] tunnel Tunnel
73 * @param[in,out] channel CADET channel
74 */
75void
76bind_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
77 struct GNUNET_CADET_Channel *channel);
78
79/**
80 * Tries to connect a <i>tunnel</i> by creating a new CADET channel and binding it.
81 * The function returns #GNUNET_YES on success, otherwise #GNUNET_NO.
82 *
83 * @param[in,out] tunnel Tunnel
84 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
85 */
86int
87connect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
88
89/**
90 * Disconnects and unbinds a channel from a <i>tunnel</i>. The actual disconnection
91 * will be asynchronous.
92 *
93 * @param[in,out] tunnel Tunnel
94 */
95void
96disconnect_tunnel (struct GNUNET_MESSENGER_SrvTunnel *tunnel);
97
98/**
99 * Returns the status of a currently bound channel of a <i>tunnel</i>.
100 *
101 * @param[in] tunnel Tunnel
102 * @return #GNUNET_YES or #GNUNET_NO
103 */
104int
105is_tunnel_connected (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
106
107/**
108 * Sends an envelope containing a <i>message</i> with a given <i>hash</i> through
109 * a <i>tunnel</i>.
110 *
111 * @param[in,out] tunnel Tunnel
112 * @param[in,out] env Envelope
113 * @param[in] hash Hash of message
114 */
115void
116send_tunnel_envelope (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
117 struct GNUNET_MQ_Envelope *env,
118 const struct GNUNET_HashCode *hash);
119
120/**
121 * Sends a <i>message</i> by packing it automatically into an envelope and passing it
122 * through the <i>tunnel</i>. The used <i>handle</i> will sign the message and
123 * the <i>hash</i> will be calculated and stored.
124 *
125 * @param[in,out] tunnel Tunnel
126 * @param[in,out] handle Handle
127 * @param[in,out] message Message
128 * @return #GNUNET_YES on success, GNUNET_NO otherwise
129 */
130int
131send_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
132 void *handle,
133 struct GNUNET_MESSENGER_Message *message);
134
135/**
136 * Forwards a given <i>message</i> with a known <i>hash</i> through a <i>tunnel</i>.
137 *
138 * @param[in,out] tunnel Tunnel
139 * @param[in] message Message
140 * @param[in] hash Hash of message
141 */
142void
143forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
144 const struct GNUNET_MESSENGER_Message *message,
145 const struct GNUNET_HashCode *hash);
146
147/**
148 * Returns the hash of the latest peer message published through a given <i>tunnel</i>
149 * and matching the tunnels peer identity. If no peer message has been linked to the tunnel
150 * yet, NULL gets returned.
151 *
152 * @param[in] tunnel Tunnel
153 * @return Hash of peer message or NULL
154 */
155const struct GNUNET_HashCode*
156get_tunnel_peer_message (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
157
158/**
159 * Writes the peer identity of the peer connected via <i>tunnel</i> to this peer into
160 * the <i>peer</i> parameter.
161 *
162 * @param[in] tunnel Tunnel
163 * @param[out] peer Peer identity
164 */
165void
166get_tunnel_peer_identity (const struct GNUNET_MESSENGER_SrvTunnel *tunnel,
167 struct GNUNET_PeerIdentity *peer);
168
169/**
170 * Returns the current messenger version the peer connected via a given <i>tunnel</i>
171 * has reported to be using if it was compatible during updating.
172 *
173 * @see update_tunnel_messenger_version
174 *
175 * @param[in] tunnel Tunnel
176 * @return Version of messenger
177 */
178uint32_t
179get_tunnel_messenger_version (const struct GNUNET_MESSENGER_SrvTunnel *tunnel);
180
181/**
182 * Updates the messenger version of the <i>tunnel</i> to a given <i>version</i> if
183 * it is compatible to the running peer of the service. Depending on success it
184 * returns #GNUNET_OK or #GNUNET_SYSERR on failure.
185 *
186 * @param[in,out] tunnel Tunnel
187 * @param[in] version Version of messenger
188 */
189int
190update_tunnel_messenger_version (struct GNUNET_MESSENGER_SrvTunnel *tunnel,
191 uint32_t version);
192
193#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 ef0544681..000000000
--- a/src/messenger/messenger.conf.in
+++ /dev/null
@@ -1,14 +0,0 @@
1[messenger]
2START_ON_DEMAND = @START_ON_DEMAND@
3RUN_PER_USER = YES
4@JAVAPORT@PORT = 2125
5HOSTNAME = localhost
6BINARY = gnunet-service-messenger
7ACCEPT_FROM = 127.0.0.1;
8ACCEPT_FROM6 = ::1;
9UNIXPATH = $GNUNET_USER_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 610c979c4..000000000
--- a/src/messenger/messenger_api.c
+++ /dev/null
@@ -1,801 +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 "platform.h"
27#include "gnunet_messenger_service.h"
28
29#include "gnunet-service-messenger.h"
30
31#include "messenger_api_handle.h"
32#include "messenger_api_message.h"
33#include "messenger_api_util.h"
34
35const char*
36GNUNET_MESSENGER_name_of_kind (enum GNUNET_MESSENGER_MessageKind kind)
37{
38 switch (kind)
39 {
40 case GNUNET_MESSENGER_KIND_INFO:
41 return "INFO";
42 case GNUNET_MESSENGER_KIND_JOIN:
43 return "JOIN";
44 case GNUNET_MESSENGER_KIND_LEAVE:
45 return "LEAVE";
46 case GNUNET_MESSENGER_KIND_NAME:
47 return "NAME";
48 case GNUNET_MESSENGER_KIND_KEY:
49 return "KEY";
50 case GNUNET_MESSENGER_KIND_PEER:
51 return "PEER";
52 case GNUNET_MESSENGER_KIND_ID:
53 return "ID";
54 case GNUNET_MESSENGER_KIND_MISS:
55 return "MISS";
56 case GNUNET_MESSENGER_KIND_MERGE:
57 return "MERGE";
58 case GNUNET_MESSENGER_KIND_REQUEST:
59 return "REQUEST";
60 case GNUNET_MESSENGER_KIND_INVITE:
61 return "INVITE";
62 case GNUNET_MESSENGER_KIND_TEXT:
63 return "TEXT";
64 case GNUNET_MESSENGER_KIND_FILE:
65 return "FILE";
66 case GNUNET_MESSENGER_KIND_PRIVATE:
67 return "PRIVATE";
68 case GNUNET_MESSENGER_KIND_DELETE:
69 return "DELETE";
70 default:
71 return "UNKNOWN";
72 }
73}
74
75static int
76check_get_name (void *cls,
77 const struct GNUNET_MESSENGER_NameMessage *msg)
78{
79 GNUNET_MQ_check_zero_termination(msg);
80 return GNUNET_OK;
81}
82
83static void
84handle_get_name (void *cls,
85 const struct GNUNET_MESSENGER_NameMessage *msg)
86{
87 struct GNUNET_MESSENGER_Handle *handle = cls;
88
89 const char *name = ((const char*) msg) + sizeof(*msg);
90
91 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
92
93 set_handle_name (handle, strlen (name) > 0 ? name : NULL);
94}
95
96static int
97check_get_key (void *cls,
98 const struct GNUNET_MESSENGER_KeyMessage *msg)
99{
100 const uint16_t full_length = ntohs (msg->header.size);
101
102 if (full_length < sizeof(*msg))
103 return GNUNET_NO;
104
105 const uint16_t length = full_length - sizeof(*msg);
106 const char *buffer = ((const char*) msg) + sizeof(*msg);
107
108 struct GNUNET_IDENTITY_PublicKey pubkey;
109 size_t read;
110 if (GNUNET_SYSERR ==
111 GNUNET_IDENTITY_read_public_key_from_buffer(buffer, length,
112 &pubkey, &read))
113 return GNUNET_NO;
114
115 return GNUNET_OK;
116}
117
118static void
119handle_get_key (void *cls,
120 const struct GNUNET_MESSENGER_KeyMessage *msg)
121{
122 struct GNUNET_MESSENGER_Handle *handle = cls;
123
124 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
125 const char *buffer = ((const char*) msg) + sizeof(*msg);
126
127 struct GNUNET_IDENTITY_PublicKey pubkey;
128 size_t read;
129 if (GNUNET_SYSERR ==
130 GNUNET_IDENTITY_read_public_key_from_buffer(buffer, length,
131 &pubkey, &read))
132 return;
133
134 char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
135 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
136 GNUNET_free(str);
137
138 set_handle_key (handle, &pubkey);
139
140 if (handle->identity_callback)
141 handle->identity_callback (handle->identity_cls, handle);
142}
143
144static void
145handle_member_id (void *cls,
146 const struct GNUNET_MESSENGER_MemberMessage *msg)
147{
148 struct GNUNET_MESSENGER_Handle *handle = cls;
149
150 const struct GNUNET_HashCode *key = &(msg->key);
151 const struct GNUNET_ShortHashCode *id = &(msg->id);
152
153 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", GNUNET_h2s (key));
154
155 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
156
157 if (room)
158 {
159 if (!room->contact_id)
160 room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
161
162 GNUNET_memcpy(room->contact_id, id, sizeof(*id));
163 }
164}
165
166static void
167handle_room_open (void *cls,
168 const struct GNUNET_MESSENGER_RoomMessage *msg)
169{
170 struct GNUNET_MESSENGER_Handle *handle = cls;
171
172 const struct GNUNET_HashCode *key = &(msg->key);
173
174 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
175
176 open_handle_room (handle, key);
177}
178
179static void
180handle_room_entry (void *cls,
181 const struct GNUNET_MESSENGER_RoomMessage *msg)
182{
183 struct GNUNET_MESSENGER_Handle *handle = cls;
184
185 const struct GNUNET_PeerIdentity *door = &(msg->door);
186 const struct GNUNET_HashCode *key = &(msg->key);
187
188 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
189
190 entry_handle_room_at (handle, door, key);
191}
192
193static void
194handle_room_close (void *cls,
195 const struct GNUNET_MESSENGER_RoomMessage *msg)
196{
197 struct GNUNET_MESSENGER_Handle *handle = cls;
198
199 const struct GNUNET_HashCode *key = &(msg->key);
200
201 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
202
203 close_handle_room (handle, key);
204}
205
206static int
207check_recv_message (void *cls,
208 const struct GNUNET_MESSENGER_RecvMessage *msg)
209{
210 const uint16_t full_length = ntohs (msg->header.size);
211
212 if (full_length < sizeof(*msg))
213 return GNUNET_NO;
214
215 const uint16_t length = full_length - sizeof(*msg);
216 const char *buffer = ((const char*) msg) + sizeof(*msg);
217
218 struct GNUNET_MESSENGER_Message message;
219
220 if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, GNUNET_YES))
221 return GNUNET_NO;
222
223 if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, NULL))
224 return GNUNET_NO;
225
226 cleanup_message(&message);
227 return GNUNET_OK;
228}
229
230static void
231handle_recv_message (void *cls,
232 const struct GNUNET_MESSENGER_RecvMessage *msg)
233{
234 struct GNUNET_MESSENGER_Handle *handle = cls;
235
236 const struct GNUNET_HashCode *key = &(msg->key);
237 const struct GNUNET_HashCode *sender = &(msg->sender);
238 const struct GNUNET_HashCode *context = &(msg->context);
239 const struct GNUNET_HashCode *hash = &(msg->hash);
240 const enum GNUNET_MESSENGER_MessageFlags flags = (
241 (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
242 );
243
244 const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
245 const char *buffer = ((const char*) msg) + sizeof(*msg);
246
247 struct GNUNET_MESSENGER_Message message;
248 decode_message (&message, length, buffer, GNUNET_YES, NULL);
249
250 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", GNUNET_MESSENGER_name_of_kind (message.header.kind));
251
252 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
253
254 if (room)
255 {
256 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(handle);
257
258 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: (%s : %s)\n",
259 GNUNET_h2s(sender), GNUNET_h2s_full(context));
260
261 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
262 store, context, sender
263 );
264
265 contact = handle_room_message (room, contact, &message, hash);
266
267 const struct GNUNET_MESSENGER_Message *stored_message = get_room_message(room, hash);
268
269 if (handle->msg_callback)
270 handle->msg_callback (handle->msg_cls, room, contact, stored_message, hash, flags);
271 }
272 else
273 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", GNUNET_h2s (key));
274
275 cleanup_message(&message);
276}
277
278static void
279reconnect (struct GNUNET_MESSENGER_Handle *handle);
280
281static void
282send_open_room (struct GNUNET_MESSENGER_Handle *handle,
283 struct GNUNET_MESSENGER_Room *room)
284{
285 struct GNUNET_MESSENGER_RoomMessage *msg;
286 struct GNUNET_MQ_Envelope *env;
287
288 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
289 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
290 GNUNET_MQ_send (handle->mq, env);
291}
292
293static void
294send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
295 struct GNUNET_MESSENGER_Room *room,
296 const struct GNUNET_PeerIdentity *door)
297{
298 struct GNUNET_MESSENGER_RoomMessage *msg;
299 struct GNUNET_MQ_Envelope *env;
300
301 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
302 GNUNET_memcpy(&(msg->door), door, sizeof(*door));
303 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
304 GNUNET_MQ_send (handle->mq, env);
305}
306
307static void
308send_close_room (struct GNUNET_MESSENGER_Handle *handle,
309 struct GNUNET_MESSENGER_Room *room)
310{
311 struct GNUNET_MESSENGER_RoomMessage *msg;
312 struct GNUNET_MQ_Envelope *env;
313
314 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
315 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
316 GNUNET_MQ_send (handle->mq, env);
317}
318
319static int
320iterate_reset_room (void *cls,
321 const struct GNUNET_HashCode *key,
322 void *value)
323{
324 struct GNUNET_MESSENGER_Handle *handle = cls;
325 struct GNUNET_MESSENGER_Room *room = value;
326
327 if (GNUNET_YES == room->opened)
328 send_open_room (handle, room);
329
330 struct GNUNET_MESSENGER_ListTunnel *entry = room->entries.head;
331
332 struct GNUNET_PeerIdentity door;
333
334 while (entry)
335 {
336 GNUNET_PEER_resolve (entry->peer, &door);
337
338 send_enter_room (handle, room, &door);
339
340 entry = entry->next;
341 }
342
343 return GNUNET_YES;
344}
345
346static void
347callback_reconnect (void *cls)
348{
349 struct GNUNET_MESSENGER_Handle *handle = cls;
350
351 handle->reconnect_task = NULL;
352 handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
353 ;
354
355 reconnect (handle);
356
357 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_reset_room, handle);
358}
359
360static int
361iterate_close_room (void *cls,
362 const struct GNUNET_HashCode *key,
363 void *value)
364{
365 struct GNUNET_MESSENGER_Handle *handle = cls;
366 struct GNUNET_MESSENGER_Room *room = value;
367
368 send_close_room (handle, room);
369
370 return GNUNET_YES;
371}
372
373static void
374callback_mq_error (void *cls,
375 enum GNUNET_MQ_Error error)
376{
377 struct GNUNET_MESSENGER_Handle *handle = cls;
378
379 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "MQ_Error: %u\n", error);
380
381 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_close_room, handle);
382
383 if (handle->mq)
384 {
385 GNUNET_MQ_destroy (handle->mq);
386 handle->mq = NULL;
387 }
388
389 handle->reconnect_task = GNUNET_SCHEDULER_add_delayed (handle->reconnect_time, &callback_reconnect, handle);
390}
391
392static void
393reconnect (struct GNUNET_MESSENGER_Handle *handle)
394{
395 const struct GNUNET_MQ_MessageHandler handlers[] =
396 {
397 GNUNET_MQ_hd_var_size(
398 get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
399 struct GNUNET_MESSENGER_NameMessage, handle
400 ),
401 GNUNET_MQ_hd_var_size(
402 get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
403 struct GNUNET_MESSENGER_KeyMessage, handle
404 ),
405 GNUNET_MQ_hd_fixed_size(
406 member_id,
407 GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
408 struct GNUNET_MESSENGER_MemberMessage, handle
409 ),
410 GNUNET_MQ_hd_fixed_size(
411 room_open,
412 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
413 struct GNUNET_MESSENGER_RoomMessage, handle
414 ),
415 GNUNET_MQ_hd_fixed_size(
416 room_entry,
417 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
418 struct GNUNET_MESSENGER_RoomMessage, handle
419 ),
420 GNUNET_MQ_hd_fixed_size(
421 room_close,
422 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
423 struct GNUNET_MESSENGER_RoomMessage, handle
424 ),
425 GNUNET_MQ_hd_var_size(
426 recv_message,
427 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
428 struct GNUNET_MESSENGER_RecvMessage, handle
429 ),
430 GNUNET_MQ_handler_end()
431 };
432
433 handle->mq = GNUNET_CLIENT_connect (handle->cfg, GNUNET_MESSENGER_SERVICE_NAME, handlers, &callback_mq_error, handle);
434}
435
436struct GNUNET_MESSENGER_Handle*
437GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
438 const char *name,
439 GNUNET_MESSENGER_IdentityCallback identity_callback,
440 void *identity_cls,
441 GNUNET_MESSENGER_MessageCallback msg_callback,
442 void *msg_cls)
443{
444 struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, identity_callback, identity_cls, msg_callback, msg_cls);
445
446 reconnect (handle);
447
448 if (handle->mq)
449 {
450 const uint16_t name_len = name ? strlen (name) : 0;
451
452 struct GNUNET_MESSENGER_CreateMessage *msg;
453 struct GNUNET_MQ_Envelope *env;
454
455 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
456
457 char *extra = ((char*) msg) + sizeof(*msg);
458
459 if (name_len)
460 GNUNET_memcpy(extra, name, name_len);
461
462 extra[name_len] = '\0';
463
464 GNUNET_MQ_send (handle->mq, env);
465 return handle;
466 }
467 else
468 {
469 destroy_handle (handle);
470 return NULL;
471 }
472}
473
474int
475GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
476{
477 if ((!handle) || (!get_handle_name (handle)))
478 return GNUNET_SYSERR;
479
480 struct GNUNET_MESSENGER_UpdateMessage *msg;
481 struct GNUNET_MQ_Envelope *env;
482
483 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
484 GNUNET_MQ_send (handle->mq, env);
485 return GNUNET_OK;
486}
487
488void
489GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
490{
491 if (!handle)
492 return;
493
494 struct GNUNET_MESSENGER_DestroyMessage *msg;
495 struct GNUNET_MQ_Envelope *env;
496
497 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY);
498 GNUNET_MQ_send (handle->mq, env);
499
500 destroy_handle (handle);
501}
502
503const char*
504GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
505{
506 if (!handle)
507 return NULL;
508
509 return get_handle_name (handle);
510}
511
512int
513GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
514 const char *name)
515{
516 if (!handle)
517 return GNUNET_SYSERR;
518
519 const uint16_t name_len = name ? strlen (name) : 0;
520
521 struct GNUNET_MESSENGER_NameMessage *msg;
522 struct GNUNET_MQ_Envelope *env;
523
524 env = GNUNET_MQ_msg_extra(msg, name_len + 1, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
525
526 char *extra = ((char*) msg) + sizeof(*msg);
527
528 if (name_len)
529 GNUNET_memcpy(extra, name, name_len);
530
531 extra[name_len] = '\0';
532
533 GNUNET_MQ_send (handle->mq, env);
534 return GNUNET_YES;
535}
536
537static const struct GNUNET_IDENTITY_PublicKey*
538get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
539{
540 if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
541 return NULL;
542
543 return public_key;
544}
545
546const struct GNUNET_IDENTITY_PublicKey*
547GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle)
548{
549 if (!handle)
550 return NULL;
551
552 return get_non_anonymous_key (get_handle_key (handle));
553}
554
555struct GNUNET_MESSENGER_Room*
556GNUNET_MESSENGER_open_room (struct GNUNET_MESSENGER_Handle *handle,
557 const struct GNUNET_HashCode *key)
558{
559 if ((!handle) || (!key))
560 return NULL;
561
562 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
563
564 if (!room)
565 {
566 room = create_room (handle, key);
567
568 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
569 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
570 {
571 destroy_room (room);
572 return NULL;
573 }
574 }
575
576 send_open_room (handle, room);
577 return room;
578}
579
580struct GNUNET_MESSENGER_Room*
581GNUNET_MESSENGER_enter_room (struct GNUNET_MESSENGER_Handle *handle,
582 const struct GNUNET_PeerIdentity *door,
583 const struct GNUNET_HashCode *key)
584{
585 if ((!handle) || (!door) || (!key))
586 return NULL;
587
588 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
589
590 if (!room)
591 {
592 room = create_room (handle, key);
593
594 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (handle->rooms, key, room,
595 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
596 {
597 destroy_room (room);
598 return NULL;
599 }
600 }
601
602 send_enter_room (handle, room, door);
603 return room;
604}
605
606void
607GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room *room)
608{
609 if (!room)
610 return;
611
612 send_close_room (room->handle, room);
613}
614
615struct GNUNET_MESSENGER_RoomFind
616{
617 const struct GNUNET_MESSENGER_Contact *contact;
618 GNUNET_MESSENGER_MemberCallback callback;
619 size_t counter;
620 void *cls;
621};
622
623static int
624iterate_find_room (void* cls,
625 const struct GNUNET_HashCode *key,
626 void *value)
627{
628 struct GNUNET_MESSENGER_RoomFind *find = cls;
629 struct GNUNET_MESSENGER_Room *room = value;
630
631 if ((find->counter > 0) && ((!find->contact) || (GNUNET_YES == find_room_member(room, find->contact))))
632 {
633 find->counter--;
634
635 if (!find->callback)
636 return GNUNET_YES;
637
638 return find->callback(find->cls, room, find->contact);
639 }
640 else
641 return GNUNET_NO;
642}
643
644int
645GNUNET_MESSENGER_find_rooms (const struct GNUNET_MESSENGER_Handle *handle,
646 const struct GNUNET_MESSENGER_Contact *contact,
647 GNUNET_MESSENGER_MemberCallback callback,
648 void *cls)
649{
650 if (!handle)
651 return GNUNET_SYSERR;
652
653 struct GNUNET_MESSENGER_RoomFind find;
654
655 find.contact = contact;
656 find.callback = callback;
657 find.counter = (contact? contact->rc : SIZE_MAX);
658 find.cls = cls;
659
660 return GNUNET_CONTAINER_multihashmap_iterate(handle->rooms, iterate_find_room, &find);
661}
662
663const struct GNUNET_HashCode*
664GNUNET_MESSENGER_room_get_key (const struct GNUNET_MESSENGER_Room *room)
665{
666 if (!room)
667 return NULL;
668
669 return &(room->key);
670}
671
672const struct GNUNET_MESSENGER_Contact*
673GNUNET_MESSENGER_get_sender (const struct GNUNET_MESSENGER_Room *room,
674 const struct GNUNET_HashCode *hash)
675{
676 if ((!room) || (!hash))
677 return NULL;
678
679 return get_room_sender(room, hash);
680}
681
682const char*
683GNUNET_MESSENGER_contact_get_name (const struct GNUNET_MESSENGER_Contact *contact)
684{
685 if (!contact)
686 return NULL;
687
688 return get_contact_name (contact);
689}
690
691const struct GNUNET_IDENTITY_PublicKey*
692GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact *contact)
693{
694 if (!contact)
695 return NULL;
696
697 return get_non_anonymous_key (get_contact_key (contact));
698}
699
700void
701GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
702 const struct GNUNET_MESSENGER_Message *message,
703 const struct GNUNET_MESSENGER_Contact *contact)
704{
705 if ((!room) || (!message))
706 return;
707
708 switch (filter_message_sending (message))
709 {
710 case GNUNET_SYSERR:
711 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: This kind of message is reserved for the service!\n");
712 return;
713 case GNUNET_NO:
714 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: This kind of message could cause issues!\n");
715 return;
716 default:
717 break;
718 }
719
720 ssize_t key_length = 0;
721
722 if (contact)
723 {
724 const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key (
725 get_contact_key(contact)
726 );
727
728 if (public_key)
729 key_length = GNUNET_IDENTITY_public_key_get_length(public_key);
730 else
731 key_length = -1;
732 }
733
734 if (key_length < 0)
735 {
736 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid key!\n");
737 return;
738 }
739
740 const uint16_t msg_length = get_message_size (message, GNUNET_NO);
741
742 struct GNUNET_MESSENGER_SendMessage *msg;
743 struct GNUNET_MQ_Envelope *env;
744
745 const uint16_t length = (uint16_t) key_length + msg_length;
746
747 env = GNUNET_MQ_msg_extra(
748 msg, length,
749 GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
750 );
751
752 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
753
754 msg->flags = (uint32_t) (
755 contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
756 );
757
758 char *buffer = ((char*) msg) + sizeof(*msg);
759 char *msg_buffer = buffer + key_length;
760
761 if (key_length > 0)
762 GNUNET_IDENTITY_write_public_key_to_buffer(get_contact_key(contact), buffer, key_length);
763
764 encode_message (message, msg_length, msg_buffer, GNUNET_NO);
765
766 GNUNET_MQ_send (room->handle->mq, env);
767}
768
769const struct GNUNET_MESSENGER_Message*
770GNUNET_MESSENGER_get_message (const struct GNUNET_MESSENGER_Room *room,
771 const struct GNUNET_HashCode *hash)
772{
773 if ((!room) || (!hash))
774 return NULL;
775
776 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, hash);
777
778 if (!message)
779 {
780 struct GNUNET_MESSENGER_GetMessage *msg;
781 struct GNUNET_MQ_Envelope *env;
782
783 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
784 GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
785 GNUNET_memcpy(&(msg->hash), hash, sizeof(*hash));
786 GNUNET_MQ_send (room->handle->mq, env);
787 }
788
789 return message;
790}
791
792int
793GNUNET_MESSENGER_iterate_members (struct GNUNET_MESSENGER_Room *room,
794 GNUNET_MESSENGER_MemberCallback callback,
795 void *cls)
796{
797 if (!room)
798 return GNUNET_SYSERR;
799
800 return iterate_room_members(room, callback, cls);
801}
diff --git a/src/messenger/messenger_api_contact.c b/src/messenger/messenger_api_contact.c
deleted file mode 100644
index a284c3b08..000000000
--- a/src/messenger/messenger_api_contact.c
+++ /dev/null
@@ -1,111 +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 "platform.h"
27#include "messenger_api_contact.h"
28
29struct GNUNET_MESSENGER_Contact*
30create_contact (const struct GNUNET_IDENTITY_PublicKey *key)
31{
32 GNUNET_assert(key);
33
34 struct GNUNET_MESSENGER_Contact *contact = GNUNET_new(struct GNUNET_MESSENGER_Contact);
35
36 contact->name = NULL;
37 contact->rc = 0;
38
39 GNUNET_memcpy(&(contact->public_key), key, sizeof(contact->public_key));
40
41 return contact;
42}
43
44void
45destroy_contact (struct GNUNET_MESSENGER_Contact *contact)
46{
47 GNUNET_assert(contact);
48
49 if (contact->name)
50 GNUNET_free(contact->name);
51
52 GNUNET_free(contact);
53}
54
55const char*
56get_contact_name (const struct GNUNET_MESSENGER_Contact *contact)
57{
58 GNUNET_assert(contact);
59
60 return contact->name;
61}
62
63void
64set_contact_name (struct GNUNET_MESSENGER_Contact *contact,
65 const char *name)
66{
67 GNUNET_assert(contact);
68
69 if (contact->name)
70 GNUNET_free(contact->name);
71
72 contact->name = name ? GNUNET_strdup(name) : NULL;
73}
74
75const struct GNUNET_IDENTITY_PublicKey*
76get_contact_key (const struct GNUNET_MESSENGER_Contact *contact)
77{
78 GNUNET_assert(contact);
79
80 return &(contact->public_key);
81}
82
83void
84increase_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
85{
86 GNUNET_assert(contact);
87
88 contact->rc++;
89}
90
91int
92decrease_contact_rc (struct GNUNET_MESSENGER_Contact *contact)
93{
94 GNUNET_assert(contact);
95
96 if (contact->rc > 0)
97 contact->rc--;
98
99 return contact->rc ? GNUNET_NO : GNUNET_YES;
100}
101
102void
103get_context_from_member (const struct GNUNET_HashCode *key,
104 const struct GNUNET_ShortHashCode *id,
105 struct GNUNET_HashCode *context)
106{
107 GNUNET_assert((key) && (id) && (context));
108
109 GNUNET_CRYPTO_hash (id, sizeof(*id), context);
110 GNUNET_CRYPTO_hash_xor (key, context, context);
111}
diff --git a/src/messenger/messenger_api_contact.h b/src/messenger/messenger_api_contact.h
deleted file mode 100644
index e2919bcc3..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_util_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] context 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 d42155e20..000000000
--- a/src/messenger/messenger_api_contact_store.c
+++ /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/messenger_api_contact_store.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "messenger_api_contact_store.h"
28
29#include "messenger_api_contact.h"
30#include "messenger_api_util.h"
31
32void
33init_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
34{
35 GNUNET_assert (store);
36
37 store->anonymous = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_contacts (void *cls,
43 const struct GNUNET_HashCode *key,
44 void *value)
45{
46 struct GNUNET_MESSENGER_Contact *contact = value;
47 destroy_contact (contact);
48 return GNUNET_YES;
49}
50
51void
52clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
53{
54 GNUNET_assert ((store) && (store->contacts));
55
56 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
57 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
58
59 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
60 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
61}
62
63static struct GNUNET_CONTAINER_MultiHashMap*
64select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store,
65 const struct GNUNET_HashCode *context,
66 struct GNUNET_HashCode *hash)
67{
68 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
69
70 struct GNUNET_HashCode anonHash;
71 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
72
73 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
74 {
75 GNUNET_memcpy(hash, context, sizeof(*context));
76 return store->anonymous;
77 }
78 else
79 return store->contacts;
80}
81
82struct GNUNET_MESSENGER_Contact*
83get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store,
84 const struct GNUNET_HashCode *context,
85 const struct GNUNET_HashCode *key_hash)
86{
87 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
88
89 struct GNUNET_HashCode hash;
90 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
91
92 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
93 store, context, &hash
94 );
95
96 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
97}
98
99struct GNUNET_MESSENGER_Contact*
100get_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
101 const struct GNUNET_HashCode *context,
102 const struct GNUNET_IDENTITY_PublicKey *pubkey)
103{
104 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
105
106 struct GNUNET_HashCode hash;
107 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
108
109 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
110 store, context, &hash
111 );
112
113 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
114
115 if (contact)
116 {
117 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
118 {
119 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
120 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
121 GNUNET_free (str);
122 return NULL;
123 }
124
125 return contact;
126 }
127
128 contact = create_contact (pubkey);
129
130 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
131 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
132 return contact;
133
134 destroy_contact (contact);
135 return NULL;
136}
137
138void
139update_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
140 struct GNUNET_MESSENGER_Contact* contact,
141 const struct GNUNET_HashCode *context,
142 const struct GNUNET_HashCode *next_context,
143 const struct GNUNET_IDENTITY_PublicKey *pubkey)
144{
145 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
146
147 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
148
149 struct GNUNET_HashCode hash;
150 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
151
152 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
153 store, context, &hash
154 );
155
156 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
157 {
158 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
159
160 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
161
162 map = select_store_contact_map (
163 store, next_context, &hash
164 );
165
166 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
167 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
168 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating a contact failed: %s\n",
169 GNUNET_h2s(&hash));
170 }
171}
172
173void
174remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
175 struct GNUNET_MESSENGER_Contact* contact,
176 const struct GNUNET_HashCode *context)
177{
178 GNUNET_assert ((store) && (store->contacts) && (contact));
179
180 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
181
182 struct GNUNET_HashCode hash;
183 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
184
185 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
186 store, context, &hash
187 );
188
189 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
190 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a contact failed: %s\n",
191 GNUNET_h2s(&hash));
192
193 destroy_contact (contact);
194}
diff --git a/src/messenger/messenger_api_contact_store.h b/src/messenger/messenger_api_contact_store.h
deleted file mode 100644
index c74a67740..000000000
--- a/src/messenger/messenger_api_contact_store.h
+++ /dev/null
@@ -1,126 +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_util_lib.h"
31#include "gnunet_identity_service.h"
32
33struct GNUNET_MESSENGER_Contact;
34
35struct GNUNET_MESSENGER_ContactStore
36{
37 struct GNUNET_CONTAINER_MultiHashMap *anonymous;
38 struct GNUNET_CONTAINER_MultiHashMap *contacts;
39};
40
41/**
42 * Initializes a contact store as fully empty.
43 *
44 * @param[out] store Contact store
45 */
46void
47init_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
48
49/**
50 * Clears a contact store, wipes its content and deallocates its memory.
51 *
52 * @param[in,out] store Contact store
53 */
54void
55clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store);
56
57/**
58 * Returns a contact using the hash of a specific public key. In case the anonymous
59 * key gets used by the requested contact, it will use its provided member
60 * <i>context</i> to select the matching contact from the <i>store</i>.
61 *
62 * In case there is no contact stored which uses the given key or context,
63 * NULL gets returned.
64 *
65 * @param[in,out] store Contact store
66 * @param[in] context Member context
67 * @param[in] key_hash Hash of public key
68 */
69struct GNUNET_MESSENGER_Contact*
70get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store,
71 const struct GNUNET_HashCode *context,
72 const struct GNUNET_HashCode *key_hash);
73
74/**
75 * Returns a contact using a specific public key. In case the anonymous
76 * key gets used by the requested contact, it will use its provided member
77 * <i>context</i> to select the matching contact from the <i>store</i>.
78 *
79 * In case there is no contact stored which uses the given key or context,
80 * a new contact will be created automatically.
81 *
82 * The function returns NULL if an error occurs during allocation
83 * or validation of the contacts key.
84 *
85 * @param[in,out] store Contact store
86 * @param[in] context Member context
87 * @param[in] pubkey Public key of EGO
88 */
89struct GNUNET_MESSENGER_Contact*
90get_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
91 const struct GNUNET_HashCode *context,
92 const struct GNUNET_IDENTITY_PublicKey *pubkey);
93
94/**
95 * Moves a <i>contact</i> from the <i>store</i> to another location
96 * matching a given public key and member <i>context</i>.
97 *
98 * This function allows changes of keys or changes of member contexts!
99 *
100 * @param[in,out] store Contact store
101 * @param[in,out] contact Contact
102 * @param[in] context Member context
103 * @param[in] next_context Member context
104 * @param[in] pubkey Public key of EGO
105 */
106void
107update_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
108 struct GNUNET_MESSENGER_Contact* contact,
109 const struct GNUNET_HashCode *context,
110 const struct GNUNET_HashCode *next_context,
111 const struct GNUNET_IDENTITY_PublicKey *pubkey);
112
113/**
114 * Removes a <i>contact</i> from the <i>store</i> which uses
115 * a given member <i>context</i>.
116 *
117 * @param[in,out] store Contact store
118 * @param[in,out] contact Contact
119 * @param[in] context Member context
120 */
121void
122remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store,
123 struct GNUNET_MESSENGER_Contact* contact,
124 const struct GNUNET_HashCode *context);
125
126#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 ec8d3dc7a..000000000
--- a/src/messenger/messenger_api_handle.c
+++ /dev/null
@@ -1,208 +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 "platform.h"
27#include "messenger_api_handle.h"
28
29#include "messenger_api_util.h"
30
31struct GNUNET_MESSENGER_Handle*
32create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg,
33 GNUNET_MESSENGER_IdentityCallback identity_callback,
34 void *identity_cls,
35 GNUNET_MESSENGER_MessageCallback msg_callback,
36 void *msg_cls)
37{
38 GNUNET_assert(cfg);
39
40 struct GNUNET_MESSENGER_Handle *handle = GNUNET_new(struct GNUNET_MESSENGER_Handle);
41
42 handle->cfg = cfg;
43 handle->mq = NULL;
44
45 handle->identity_callback = identity_callback;
46 handle->identity_cls = identity_cls;
47
48 handle->msg_callback = msg_callback;
49 handle->msg_cls = msg_cls;
50
51 handle->name = NULL;
52 handle->pubkey = NULL;
53
54 handle->reconnect_time = GNUNET_TIME_relative_get_zero_ ();
55 handle->reconnect_task = NULL;
56
57 handle->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
58
59 init_contact_store(get_handle_contact_store(handle));
60
61 return handle;
62}
63
64static int
65iterate_destroy_room (void *cls,
66 const struct GNUNET_HashCode *key,
67 void *value)
68{
69 struct GNUNET_MESSENGER_Room *room = value;
70
71 destroy_room (room);
72
73 return GNUNET_YES;
74}
75
76void
77destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
78{
79 GNUNET_assert(handle);
80
81 if (handle->reconnect_task)
82 GNUNET_SCHEDULER_cancel (handle->reconnect_task);
83
84 if (handle->mq)
85 GNUNET_MQ_destroy (handle->mq);
86
87 if (handle->name)
88 GNUNET_free(handle->name);
89
90 if (handle->pubkey)
91 GNUNET_free(handle->pubkey);
92
93 if (handle->rooms)
94 {
95 GNUNET_CONTAINER_multihashmap_iterate (handle->rooms, iterate_destroy_room, NULL);
96
97 GNUNET_CONTAINER_multihashmap_destroy (handle->rooms);
98 }
99
100 clear_contact_store(get_handle_contact_store(handle));
101
102 GNUNET_free(handle);
103}
104
105void
106set_handle_name (struct GNUNET_MESSENGER_Handle *handle,
107 const char *name)
108{
109 GNUNET_assert(handle);
110
111 if (handle->name)
112 GNUNET_free(handle->name);
113
114 handle->name = name ? GNUNET_strdup(name) : NULL;
115}
116
117const char*
118get_handle_name (const struct GNUNET_MESSENGER_Handle *handle)
119{
120 GNUNET_assert(handle);
121
122 return handle->name;
123}
124
125void
126set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
127 const struct GNUNET_IDENTITY_PublicKey *pubkey)
128{
129 GNUNET_assert(handle);
130
131 if (!handle->pubkey)
132 handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
133
134 GNUNET_memcpy(handle->pubkey, pubkey, sizeof(*pubkey));
135}
136
137const struct GNUNET_IDENTITY_PublicKey*
138get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
139{
140 GNUNET_assert(handle);
141
142 if (handle->pubkey)
143 return handle->pubkey;
144
145 return get_anonymous_public_key ();
146}
147
148struct GNUNET_MESSENGER_ContactStore*
149get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle)
150{
151 GNUNET_assert(handle);
152
153 return &(handle->contact_store);
154}
155
156struct GNUNET_MESSENGER_Contact*
157get_handle_contact (struct GNUNET_MESSENGER_Handle *handle,
158 const struct GNUNET_HashCode *key)
159{
160 GNUNET_assert((handle) && (key));
161
162 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
163
164 if ((!room) || (!(room->contact_id)))
165 return NULL;
166
167 struct GNUNET_HashCode context;
168 get_context_from_member (key, room->contact_id, &context);
169
170 return get_store_contact(get_handle_contact_store(handle), &context, get_handle_key(handle));
171}
172
173void
174open_handle_room (struct GNUNET_MESSENGER_Handle *handle,
175 const struct GNUNET_HashCode *key)
176{
177 GNUNET_assert((handle) && (key));
178
179 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
180
181 if (room)
182 room->opened = GNUNET_YES;
183}
184
185void
186entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle,
187 const struct GNUNET_PeerIdentity *door,
188 const struct GNUNET_HashCode *key)
189{
190 GNUNET_assert((handle) && (door) && (key));
191
192 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
193
194 if (room)
195 add_to_list_tunnels (&(room->entries), door);
196}
197
198void
199close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
200 const struct GNUNET_HashCode *key)
201{
202 GNUNET_assert((handle) && (key));
203
204 struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
205
206 if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (handle->rooms, key, room)))
207 destroy_room (room);
208}
diff --git a/src/messenger/messenger_api_handle.h b/src/messenger/messenger_api_handle.h
deleted file mode 100644
index d246855ff..000000000
--- a/src/messenger/messenger_api_handle.h
+++ /dev/null
@@ -1,178 +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_util_lib.h"
32#include "gnunet_identity_service.h"
33
34#include "gnunet_messenger_service.h"
35
36#include "messenger_api_contact_store.h"
37#include "messenger_api_room.h"
38
39struct GNUNET_MESSENGER_Handle
40{
41 const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43 struct GNUNET_MQ_Handle *mq;
44
45 GNUNET_MESSENGER_IdentityCallback identity_callback;
46 void *identity_cls;
47
48 GNUNET_MESSENGER_MessageCallback msg_callback;
49 void *msg_cls;
50
51 char *name;
52 struct GNUNET_IDENTITY_PublicKey *pubkey;
53
54 struct GNUNET_TIME_Relative reconnect_time;
55 struct GNUNET_SCHEDULER_Task *reconnect_task;
56
57 struct GNUNET_MESSENGER_ContactStore contact_store;
58
59 struct GNUNET_CONTAINER_MultiHashMap *rooms;
60};
61
62/**
63 * Creates and allocates a new handle using a given configuration and a custom message callback
64 * with a given closure for the client API.
65 *
66 * @param[in] cfg Configuration
67 * @param[in] msg_callback Message callback
68 * @param[in,out] msg_cls Closure
69 * @return New handle
70 */
71struct GNUNET_MESSENGER_Handle*
72create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg,
73 GNUNET_MESSENGER_IdentityCallback identity_callback,
74 void *identity_cls,
75 GNUNET_MESSENGER_MessageCallback msg_callback,
76 void *msg_cls);
77
78/**
79 * Destroys a <i>handle</i> and frees its memory fully from the client API.
80 *
81 * @param[in,out] handle Handle
82 */
83void
84destroy_handle (struct GNUNET_MESSENGER_Handle *handle);
85
86/**
87 * Sets the name of a <i>handle</i> to a specific <i>name</i>.
88 *
89 * @param[in,out] handle Handle
90 * @param[in] name New name
91 */
92void
93set_handle_name (struct GNUNET_MESSENGER_Handle *handle,
94 const char *name);
95
96/**
97 * Returns the current name of a given <i>handle</i> or NULL if no valid name was assigned yet.
98 *
99 * @param[in] handle Handle
100 * @return Name of the handle or NULL
101 */
102const char*
103get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
104
105/**
106 * Sets the public key of a given <i>handle</i> to a specific public key.
107 *
108 * @param[in,out] handle Handle
109 * @param[in] pubkey Public key
110 */
111void
112set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
113 const struct GNUNET_IDENTITY_PublicKey *pubkey);
114
115/**
116 * Returns the public key of a given <i>handle</i>.
117 *
118 * @param[in] handle Handle
119 * @return Public key of the handle
120 */
121const struct GNUNET_IDENTITY_PublicKey*
122get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
123
124/**
125 * Returns the used contact store of a given <i>handle</i>.
126 *
127 * @param[in,out] handle Handle
128 * @return Contact store
129 */
130struct GNUNET_MESSENGER_ContactStore*
131get_handle_contact_store (struct GNUNET_MESSENGER_Handle *handle);
132
133/**
134 * Returns the contact of a given <i>handle</i> in a room identified by a
135 * given <i>key</i>.
136 *
137 * @param[in,out] handle Handle
138 * @param[in] key Key of room
139 * @return Contact
140 */
141struct GNUNET_MESSENGER_Contact*
142get_handle_contact (struct GNUNET_MESSENGER_Handle *handle,
143 const struct GNUNET_HashCode *key);
144
145/**
146 * Marks a room known to a <i>handle</i> identified by a given <i>key</i> as open.
147 *
148 * @param[in,out] handle Handle
149 * @param[in] key Key of room
150 */
151void
152open_handle_room (struct GNUNET_MESSENGER_Handle *handle,
153 const struct GNUNET_HashCode *key);
154
155/**
156 * Adds a tunnel for a room known to a <i>handle</i> identified by a given <i>key</i> to a
157 * list of opened connections.
158 *
159 * @param[in,out] handle Handle
160 * @param[in] door Peer identity
161 * @param[in] key Key of room
162 */
163void
164entry_handle_room_at (struct GNUNET_MESSENGER_Handle *handle,
165 const struct GNUNET_PeerIdentity *door,
166 const struct GNUNET_HashCode *key);
167
168/**
169 * Destroys and so implicitly closes a room known to a <i>handle</i> identified by a given <i>key</i>.
170 *
171 * @param[in,out] handle Handle
172 * @param[in] key Key of room
173 */
174void
175close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
176 const struct GNUNET_HashCode *key);
177
178#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 a4126c286..000000000
--- a/src/messenger/messenger_api_list_tunnels.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_list_tunnels.c
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "messenger_api_list_tunnels.h"
28
29void
30init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels)
31{
32 GNUNET_assert(tunnels);
33
34 tunnels->head = NULL;
35 tunnels->tail = NULL;
36}
37
38void
39clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels)
40{
41 GNUNET_assert(tunnels);
42
43 struct GNUNET_MESSENGER_ListTunnel *element;
44
45 for (element = tunnels->head; element; element = tunnels->head)
46 {
47 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
48 GNUNET_PEER_change_rc (element->peer, -1);
49 GNUNET_free(element);
50 }
51
52 tunnels->head = NULL;
53 tunnels->tail = NULL;
54}
55
56static int
57compare_list_tunnels (void *cls,
58 struct GNUNET_MESSENGER_ListTunnel *element0,
59 struct GNUNET_MESSENGER_ListTunnel *element1)
60{
61 return ((int) element0->peer) - ((int) element1->peer);
62}
63
64void
65add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
66 const struct GNUNET_PeerIdentity *peer)
67{
68 GNUNET_assert((tunnels) && (peer));
69
70 struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct GNUNET_MESSENGER_ListTunnel);
71
72 element->peer = GNUNET_PEER_intern (peer);
73
74 GNUNET_CONTAINER_DLL_insert_sorted(struct GNUNET_MESSENGER_ListTunnel, compare_list_tunnels, NULL, tunnels->head,
75 tunnels->tail, element);
76}
77
78struct GNUNET_MESSENGER_ListTunnel*
79find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
80 const struct GNUNET_PeerIdentity *peer,
81 size_t *index)
82{
83 GNUNET_assert((tunnels) && (peer));
84
85 struct GNUNET_MESSENGER_ListTunnel *element;
86 struct GNUNET_PeerIdentity pid;
87
88 if (index)
89 *index = 0;
90
91 for (element = tunnels->head; element; element = element->next)
92 {
93 GNUNET_PEER_resolve (element->peer, &pid);
94
95 if (0 == GNUNET_memcmp(&pid, peer))
96 return element;
97
98 if (index)
99 (*index) = (*index) + 1;
100 }
101
102 return NULL;
103}
104
105int
106contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
107 const struct GNUNET_PeerIdentity *peer)
108{
109 GNUNET_assert((tunnels) && (peer));
110
111 return find_list_tunnels (tunnels, peer, NULL) != NULL ? GNUNET_YES : GNUNET_NO;
112}
113
114struct GNUNET_MESSENGER_ListTunnel*
115remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
116 struct GNUNET_MESSENGER_ListTunnel *element)
117{
118 GNUNET_assert((tunnels) && (element));
119
120 struct GNUNET_MESSENGER_ListTunnel *next = element->next;
121
122 GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
123 GNUNET_PEER_change_rc (element->peer, -1);
124 GNUNET_free(element);
125
126 return next;
127}
128
129void
130load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
131 const char *path)
132{
133 GNUNET_assert((tunnels) && (path));
134
135 if (GNUNET_YES != GNUNET_DISK_file_test (path))
136 return;
137
138 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
139
140 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
141 path, GNUNET_DISK_OPEN_READ, permission
142 );
143
144 if (!handle)
145 return;
146
147 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
148
149 struct GNUNET_PeerIdentity peer;
150 ssize_t len;
151
152 do {
153 len = GNUNET_DISK_file_read(handle, &peer, sizeof(peer));
154
155 if (len != sizeof(peer))
156 break;
157
158 add_to_list_tunnels(tunnels, &peer);
159 } while (len == sizeof(peer));
160
161 GNUNET_DISK_file_close(handle);
162}
163
164void
165save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
166 const char *path)
167{
168 GNUNET_assert((tunnels) && (path));
169
170 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
171
172 struct GNUNET_DISK_FileHandle *handle = GNUNET_DISK_file_open(
173 path, GNUNET_DISK_OPEN_CREATE | GNUNET_DISK_OPEN_WRITE, permission
174 );
175
176 if (!handle)
177 return;
178
179 GNUNET_DISK_file_seek(handle, 0, GNUNET_DISK_SEEK_SET);
180
181 struct GNUNET_MESSENGER_ListTunnel *element;
182 struct GNUNET_PeerIdentity pid;
183
184 for (element = tunnels->head; element; element = element->next)
185 {
186 GNUNET_PEER_resolve (element->peer, &pid);
187
188 GNUNET_DISK_file_write(handle, &pid, sizeof(pid));
189 }
190
191 GNUNET_DISK_file_sync(handle);
192 GNUNET_DISK_file_close(handle);
193}
diff --git a/src/messenger/messenger_api_list_tunnels.h b/src/messenger/messenger_api_list_tunnels.h
deleted file mode 100644
index d2ceeafc2..000000000
--- a/src/messenger/messenger_api_list_tunnels.h
+++ /dev/null
@@ -1,136 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/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_util_lib.h"
31
32struct GNUNET_MESSENGER_ListTunnel
33{
34 struct GNUNET_MESSENGER_ListTunnel *prev;
35 struct GNUNET_MESSENGER_ListTunnel *next;
36
37 GNUNET_PEER_Id peer;
38};
39
40struct GNUNET_MESSENGER_ListTunnels
41{
42 struct GNUNET_MESSENGER_ListTunnel *head;
43 struct GNUNET_MESSENGER_ListTunnel *tail;
44};
45
46/**
47 * Initializes list of tunnels peer identities as empty list.
48 *
49 * @param[out] tunnels List of peer identities
50 */
51void
52init_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
53
54/**
55 * Clears the list of tunnels peer identities.
56 *
57 * @param[in,out] tunnels List of peer identities
58 */
59void
60clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels);
61
62/**
63 * Adds a specific <i>peer</i> from a tunnel to the end of the list.
64 *
65 * @param[in,out] tunnels List of peer identities
66 * @param[in] peer Peer identity of tunnel
67 */
68void
69add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
70 const struct GNUNET_PeerIdentity *peer);
71
72/**
73 * Searches linearly through the list of tunnels peer identities for matching a
74 * specific <i>peer</i> identity and returns the matching element of the list.
75 *
76 * If no matching element is found, NULL gets returned.
77 *
78 * If <i>index</i> is not NULL, <i>index</i> will be overridden with the numeric index of
79 * the found element in the list. If no matching element is found, <i>index</i> will
80 * contain the total amount of elements in the list.
81 *
82 * @param[in,out] tunnels List of peer identities
83 * @param[in] peer Peer identity of tunnel
84 * @param[out] index Index of found element (optional)
85 * @return Element in the list with matching peer identity
86 */
87struct GNUNET_MESSENGER_ListTunnel*
88find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
89 const struct GNUNET_PeerIdentity *peer,
90 size_t *index);
91
92/**
93 * Tests linearly if the list of tunnels peer identities contains a specific
94 * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise #GNUNET_NO.
95 *
96 * @param[in,out] tunnels List of peer identities
97 * @param[in] peer Peer identity of tunnel
98 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
99 */
100int
101contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
102 const struct GNUNET_PeerIdentity *peer);
103
104/**
105 * Removes a specific <i>element</i> from the list of tunnels peer identities and returns
106 * the next element in the list.
107 *
108 * @param[in,out] tunnels List of peer identities
109 * @param[in,out] element Element of the list
110 * @return Next element in the list
111 */
112struct GNUNET_MESSENGER_ListTunnel*
113remove_from_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
114 struct GNUNET_MESSENGER_ListTunnel *element);
115
116/**
117 * Loads the list of tunnels peer identities from a file under a given <i>path</i>.
118 *
119 * @param[out] tunnels List of hashes
120 * @param[in] path Path of file
121 */
122void
123load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
124 const char *path);
125
126/**
127 * Saves the list of tunnels peer identities to a file under a given <i>path</i>.
128 *
129 * @param[in] tunnels List of hashes
130 * @param[in] path Path of file
131 */
132void
133save_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
134 const char *path);
135
136#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 ac63f16ca..000000000
--- a/src/messenger/messenger_api_message.c
+++ /dev/null
@@ -1,947 +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 "platform.h"
27#include "messenger_api_message.h"
28
29struct GNUNET_MESSENGER_MessageSignature
30{
31 struct GNUNET_CRYPTO_EccSignaturePurpose purpose;
32 struct GNUNET_HashCode hash;
33};
34
35struct GNUNET_MESSENGER_ShortMessage
36{
37 enum GNUNET_MESSENGER_MessageKind kind;
38 struct GNUNET_MESSENGER_MessageBody body;
39};
40
41struct GNUNET_MESSENGER_Message*
42create_message (enum GNUNET_MESSENGER_MessageKind kind)
43{
44 struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct GNUNET_MESSENGER_Message);
45
46 message->header.kind = kind;
47
48 switch (message->header.kind)
49 {
50 case GNUNET_MESSENGER_KIND_NAME:
51 message->body.name.name = NULL;
52 break;
53 case GNUNET_MESSENGER_KIND_TEXT:
54 message->body.text.text = NULL;
55 break;
56 case GNUNET_MESSENGER_KIND_FILE:
57 message->body.file.uri = NULL;
58 break;
59 case GNUNET_MESSENGER_KIND_PRIVATE:
60 message->body.privacy.length = 0;
61 message->body.privacy.data = NULL;
62 break;
63 default:
64 break;
65 }
66
67 return message;
68}
69
70struct GNUNET_MESSENGER_Message*
71copy_message (const struct GNUNET_MESSENGER_Message *message)
72{
73 GNUNET_assert(message);
74
75 struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct GNUNET_MESSENGER_Message);
76
77 GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
78
79 switch (message->header.kind)
80 {
81 case GNUNET_MESSENGER_KIND_NAME:
82 copy->body.name.name = GNUNET_strdup(message->body.name.name);
83 break;
84 case GNUNET_MESSENGER_KIND_TEXT:
85 copy->body.text.text = GNUNET_strdup(message->body.text.text);
86 break;
87 case GNUNET_MESSENGER_KIND_FILE:
88 copy->body.file.uri = GNUNET_strdup(message->body.file.uri);
89 break;
90 case GNUNET_MESSENGER_KIND_PRIVATE:
91 copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc(copy->body.privacy.length) : NULL;
92
93 if (copy->body.privacy.data)
94 {
95 GNUNET_memcpy(copy->body.privacy.data, message->body.privacy.data, copy->body.privacy.length);
96 }
97
98 break;
99 default:
100 break;
101 }
102
103 return copy;
104}
105
106static void
107destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind,
108 struct GNUNET_MESSENGER_MessageBody *body)
109{
110 switch (kind)
111 {
112 case GNUNET_MESSENGER_KIND_NAME:
113 GNUNET_free(body->name.name);
114 break;
115 case GNUNET_MESSENGER_KIND_TEXT:
116 GNUNET_free(body->text.text);
117 break;
118 case GNUNET_MESSENGER_KIND_FILE:
119 GNUNET_free(body->file.uri);
120 break;
121 case GNUNET_MESSENGER_KIND_PRIVATE:
122 GNUNET_free(body->privacy.data);
123 break;
124 default:
125 break;
126 }
127}
128
129void
130cleanup_message (struct GNUNET_MESSENGER_Message *message)
131{
132 GNUNET_assert(message);
133
134 destroy_message_body (message->header.kind, &(message->body));
135}
136
137void
138destroy_message (struct GNUNET_MESSENGER_Message *message)
139{
140 GNUNET_assert(message);
141
142 destroy_message_body (message->header.kind, &(message->body));
143
144 GNUNET_free(message);
145}
146
147int
148is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
149{
150 GNUNET_assert(message);
151
152 if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
153 (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
154 (GNUNET_MESSENGER_KIND_NAME == message->header.kind) ||
155 (GNUNET_MESSENGER_KIND_KEY == message->header.kind) ||
156 (GNUNET_MESSENGER_KIND_ID == message->header.kind))
157 return GNUNET_YES;
158 else
159 return GNUNET_NO;
160}
161
162static void
163fold_short_message (const struct GNUNET_MESSENGER_Message *message,
164 struct GNUNET_MESSENGER_ShortMessage *shortened)
165{
166 shortened->kind = message->header.kind;
167
168 GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
169}
170
171static void
172unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened,
173 struct GNUNET_MESSENGER_Message *message)
174{
175 destroy_message_body (message->header.kind, &(message->body));
176
177 message->header.kind = shortened->kind;
178
179 GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct GNUNET_MESSENGER_MessageBody));
180}
181
182#define member_size(type, member) sizeof(((type*) NULL)->member)
183
184static uint16_t
185get_message_body_kind_size (enum GNUNET_MESSENGER_MessageKind kind)
186{
187 uint16_t length = 0;
188
189 switch (kind)
190 {
191 case GNUNET_MESSENGER_KIND_INFO:
192 length += member_size(struct GNUNET_MESSENGER_Message, body.info.messenger_version);
193 break;
194 case GNUNET_MESSENGER_KIND_PEER:
195 length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
196 break;
197 case GNUNET_MESSENGER_KIND_ID:
198 length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
199 break;
200 case GNUNET_MESSENGER_KIND_MISS:
201 length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
202 break;
203 case GNUNET_MESSENGER_KIND_MERGE:
204 length += member_size(struct GNUNET_MESSENGER_Message, body.merge.previous);
205 break;
206 case GNUNET_MESSENGER_KIND_REQUEST:
207 length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
208 break;
209 case GNUNET_MESSENGER_KIND_INVITE:
210 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
211 length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
212 break;
213 case GNUNET_MESSENGER_KIND_TEXT:
214 break;
215 case GNUNET_MESSENGER_KIND_FILE:
216 length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
217 length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
218 length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
219 break;
220 case GNUNET_MESSENGER_KIND_PRIVATE:
221 length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
222 break;
223 case GNUNET_MESSENGER_KIND_DELETE:
224 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.hash);
225 length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.delay);
226 break;
227 default:
228 break;
229 }
230
231 return length;
232}
233
234typedef uint32_t kind_t;
235
236uint16_t
237get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
238 int include_header)
239{
240 uint16_t length = 0;
241
242 if (GNUNET_YES == include_header)
243 {
244 length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
245 length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
246 length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
247 }
248
249 length += sizeof(kind_t);
250
251 return length + get_message_body_kind_size (kind);
252}
253
254static uint16_t
255get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
256 const struct GNUNET_MESSENGER_MessageBody *body)
257{
258 uint16_t length = 0;
259
260 switch (kind)
261 {
262 case GNUNET_MESSENGER_KIND_INFO:
263 length += GNUNET_IDENTITY_public_key_get_length(&(body->info.host_key));
264 break;
265 case GNUNET_MESSENGER_KIND_JOIN:
266 length += GNUNET_IDENTITY_public_key_get_length(&(body->join.key));
267 break;
268 case GNUNET_MESSENGER_KIND_NAME:
269 length += (body->name.name ? strlen (body->name.name) : 0);
270 break;
271 case GNUNET_MESSENGER_KIND_KEY:
272 length += GNUNET_IDENTITY_public_key_get_length(&(body->key.key));
273 break;
274 case GNUNET_MESSENGER_KIND_TEXT:
275 length += strlen (body->text.text);
276 break;
277 case GNUNET_MESSENGER_KIND_FILE:
278 length += strlen (body->file.uri);
279 break;
280 case GNUNET_MESSENGER_KIND_PRIVATE:
281 length += body->privacy.length;
282 break;
283 default:
284 break;
285 }
286
287 return length;
288}
289
290uint16_t
291get_message_size (const struct GNUNET_MESSENGER_Message *message,
292 int include_header)
293{
294 GNUNET_assert(message);
295
296 uint16_t length = 0;
297
298 if (GNUNET_YES == include_header)
299 length += GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
300
301 length += get_message_kind_size (message->header.kind, include_header);
302 length += get_message_body_size (message->header.kind, &(message->body));
303
304 return length;
305}
306
307static uint16_t
308get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
309 int include_body)
310{
311 const uint16_t minimum_size = sizeof(struct GNUNET_HashCode) + sizeof(kind_t);
312
313 if (message)
314 return minimum_size + get_message_body_kind_size (message->kind)
315 + (include_body == GNUNET_YES? get_message_body_size (message->kind, &(message->body)) : 0);
316 else
317 return minimum_size;
318}
319
320static uint16_t
321calc_usual_padding ()
322{
323 uint16_t padding = 0;
324 uint16_t kind_size;
325
326 for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
327 kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, GNUNET_YES);
328
329 if (kind_size > padding)
330 padding = kind_size;
331 }
332
333 return padding + GNUNET_MESSENGER_PADDING_MIN;
334}
335
336#define max(x, y) (x > y? x : y)
337
338static uint16_t
339calc_padded_length (uint16_t length)
340{
341 static uint16_t usual_padding = 0;
342
343 if (!usual_padding)
344 usual_padding = calc_usual_padding();
345
346 const uint16_t padded_length = max(
347 length + GNUNET_MESSENGER_PADDING_MIN,
348 usual_padding
349 );
350
351 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
352 return GNUNET_MESSENGER_PADDING_LEVEL0;
353
354 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL1)
355 return GNUNET_MESSENGER_PADDING_LEVEL1;
356
357 if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL2)
358 return GNUNET_MESSENGER_PADDING_LEVEL2;
359
360 return GNUNET_MESSENGER_MAX_MESSAGE_SIZE;
361
362}
363
364#define min(x, y) (x < y? x : y)
365
366#define encode_step_ext(dst, offset, src, size) do { \
367 GNUNET_memcpy(dst + offset, src, size); \
368 offset += size; \
369} while (0)
370
371#define encode_step(dst, offset, src) do { \
372 encode_step_ext(dst, offset, src, sizeof(*src)); \
373} while (0)
374
375#define encode_step_key(dst, offset, src, length) do { \
376 ssize_t result = GNUNET_IDENTITY_write_public_key_to_buffer( \
377 src, dst + offset, length - offset \
378 ); \
379 if (result < 0) \
380 GNUNET_break (0); \
381 else \
382 offset += result; \
383} while (0)
384
385#define encode_step_signature(dst, offset, src, length) do { \
386 ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
387 src, dst + offset, length - offset \
388 ); \
389 if (result < 0) \
390 GNUNET_break (0); \
391 else \
392 offset += result; \
393} while (0)
394
395static void
396encode_message_body (enum GNUNET_MESSENGER_MessageKind kind,
397 const struct GNUNET_MESSENGER_MessageBody *body,
398 uint16_t length,
399 char *buffer,
400 uint16_t offset)
401{
402 uint32_t version;
403 switch (kind)
404 {
405 case GNUNET_MESSENGER_KIND_INFO:
406 version = GNUNET_htobe32(body->info.messenger_version);
407
408 encode_step_key(buffer, offset, &(body->info.host_key), length);
409 encode_step(buffer, offset, &version);
410 break;
411 case GNUNET_MESSENGER_KIND_JOIN:
412 encode_step_key(buffer, offset, &(body->join.key), length);
413 break;
414 case GNUNET_MESSENGER_KIND_NAME:
415 if (body->name.name)
416 encode_step_ext(buffer, offset, body->name.name, min(length - offset, strlen(body->name.name)));
417 break;
418 case GNUNET_MESSENGER_KIND_KEY:
419 encode_step_key(buffer, offset, &(body->key.key), length);
420 break;
421 case GNUNET_MESSENGER_KIND_PEER:
422 encode_step(buffer, offset, &(body->peer.peer));
423 break;
424 case GNUNET_MESSENGER_KIND_ID:
425 encode_step(buffer, offset, &(body->id.id));
426 break;
427 case GNUNET_MESSENGER_KIND_MISS:
428 encode_step(buffer, offset, &(body->miss.peer));
429 break;
430 case GNUNET_MESSENGER_KIND_MERGE:
431 encode_step(buffer, offset, &(body->merge.previous));
432 break;
433 case GNUNET_MESSENGER_KIND_REQUEST:
434 encode_step(buffer, offset, &(body->request.hash));
435 break;
436 case GNUNET_MESSENGER_KIND_INVITE:
437 encode_step(buffer, offset, &(body->invite.door));
438 encode_step(buffer, offset, &(body->invite.key));
439 break;
440 case GNUNET_MESSENGER_KIND_TEXT:
441 encode_step_ext(buffer, offset, body->text.text, min(length - offset, strlen(body->text.text)));
442 break;
443 case GNUNET_MESSENGER_KIND_FILE:
444 encode_step(buffer, offset, &(body->file.key));
445 encode_step(buffer, offset, &(body->file.hash));
446 encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
447 encode_step_ext(buffer, offset, body->file.uri, min(length - offset, strlen(body->file.uri)));
448 break;
449 case GNUNET_MESSENGER_KIND_PRIVATE:
450 encode_step(buffer, offset, &(body->privacy.key));
451 encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, body->privacy.length));
452 break;
453 case GNUNET_MESSENGER_KIND_DELETE:
454 encode_step(buffer, offset, &(body->deletion.hash));
455 encode_step(buffer, offset, &(body->deletion.delay));
456 break;
457 default:
458 break;
459 }
460
461 if (offset >= length)
462 return;
463
464 const uint16_t padding = length - offset;
465 const uint16_t used_padding = sizeof(padding) + sizeof(char);
466
467 GNUNET_assert(padding >= used_padding);
468
469 buffer[offset++] = '\0';
470
471 if (padding > used_padding)
472 GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, padding - used_padding);
473
474 GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
475}
476
477void
478encode_message (const struct GNUNET_MESSENGER_Message *message,
479 uint16_t length,
480 char *buffer,
481 int include_header)
482{
483 GNUNET_assert((message) && (buffer));
484
485 uint16_t offset = 0;
486
487 if (GNUNET_YES == include_header)
488 encode_step_signature(buffer, offset, &(message->header.signature), length);
489
490 const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
491
492 if (GNUNET_YES == include_header)
493 {
494 encode_step(buffer, offset, &(message->header.timestamp));
495 encode_step(buffer, offset, &(message->header.sender_id));
496 encode_step(buffer, offset, &(message->header.previous));
497 }
498
499 encode_step(buffer, offset, &kind);
500
501 encode_message_body (message->header.kind, &(message->body), length, buffer, offset);
502}
503
504static void
505encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
506 uint16_t length,
507 char *buffer)
508{
509 struct GNUNET_HashCode hash;
510 uint16_t offset = sizeof(hash);
511
512 const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
513
514 encode_step(buffer, offset, &kind);
515
516 encode_message_body (message->kind, &(message->body), length, buffer, offset);
517
518 GNUNET_CRYPTO_hash(
519 buffer + sizeof(hash),
520 length - sizeof(hash),
521 &hash
522 );
523
524 GNUNET_memcpy(buffer, &hash, sizeof(hash));
525}
526
527#define decode_step_ext(src, offset, dst, size) do { \
528 GNUNET_memcpy(dst, src + offset, size); \
529 offset += size; \
530} while (0)
531
532#define decode_step(src, offset, dst) do { \
533 decode_step_ext(src, offset, dst, sizeof(*dst)); \
534} while (0)
535
536#define decode_step_malloc(src, offset, dst, size, zero) do { \
537 dst = GNUNET_malloc(size + zero); \
538 if (zero) dst[size] = 0; \
539 decode_step_ext(src, offset, dst, size); \
540} while (0)
541
542#define decode_step_key(src, offset, dst, length) do { \
543 enum GNUNET_GenericReturnValue result; \
544 size_t read; \
545 result = GNUNET_IDENTITY_read_public_key_from_buffer( \
546 src + offset, length - offset, dst, &read \
547 ); \
548 if (GNUNET_SYSERR == result) \
549 GNUNET_break(0); \
550 else \
551 offset += read; \
552} while (0)
553
554static uint16_t
555decode_message_body (enum GNUNET_MESSENGER_MessageKind *kind,
556 struct GNUNET_MESSENGER_MessageBody *body,
557 uint16_t length,
558 const char *buffer,
559 uint16_t offset)
560{
561 uint16_t padding = 0;
562
563 GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
564
565 if (padding > length - offset)
566 padding = 0;
567
568 const uint16_t end_zero = length - padding;
569
570 if ((padding) && (buffer[end_zero] != '\0'))
571 padding = 0;
572
573 length -= padding;
574
575 uint32_t version;
576 switch (*kind)
577 {
578 case GNUNET_MESSENGER_KIND_INFO: {
579 decode_step_key(buffer, offset, &(body->info.host_key), length);
580 decode_step(buffer, offset, &version);
581
582 body->info.messenger_version = GNUNET_be32toh(version);
583 break;
584 } case GNUNET_MESSENGER_KIND_JOIN: {
585 decode_step_key(buffer, offset, &(body->join.key), length);
586 break;
587 } case GNUNET_MESSENGER_KIND_NAME:
588 if (length - offset > 0)
589 decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
590 else
591 body->name.name = NULL;
592 break;
593 case GNUNET_MESSENGER_KIND_KEY:
594 decode_step_key(buffer, offset, &(body->key.key), length);
595 break;
596 case GNUNET_MESSENGER_KIND_PEER:
597 decode_step(buffer, offset, &(body->peer.peer));
598 break;
599 case GNUNET_MESSENGER_KIND_ID:
600 decode_step(buffer, offset, &(body->id.id));
601 break;
602 case GNUNET_MESSENGER_KIND_MISS:
603 decode_step(buffer, offset, &(body->miss.peer));
604 break;
605 case GNUNET_MESSENGER_KIND_MERGE:
606 decode_step(buffer, offset, &(body->merge.previous));
607 break;
608 case GNUNET_MESSENGER_KIND_REQUEST:
609 decode_step(buffer, offset, &(body->request.hash));
610 break;
611 case GNUNET_MESSENGER_KIND_INVITE:
612 decode_step(buffer, offset, &(body->invite.door));
613 decode_step(buffer, offset, &(body->invite.key));
614 break;
615 case GNUNET_MESSENGER_KIND_TEXT:
616 decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
617 break;
618 case GNUNET_MESSENGER_KIND_FILE:
619 decode_step(buffer, offset, &(body->file.key));
620 decode_step(buffer, offset, &(body->file.hash));
621 decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
622 decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
623 break;
624 case GNUNET_MESSENGER_KIND_PRIVATE:
625 decode_step(buffer, offset, &(body->privacy.key));
626
627 body->privacy.length = (length - offset);
628 decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
629 break;
630 case GNUNET_MESSENGER_KIND_DELETE:
631 decode_step(buffer, offset, &(body->deletion.hash));
632 decode_step(buffer, offset, &(body->deletion.delay));
633 break;
634 default:
635 *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
636 break;
637 }
638
639 return padding;
640}
641
642int
643decode_message (struct GNUNET_MESSENGER_Message *message,
644 uint16_t length,
645 const char *buffer,
646 int include_header,
647 uint16_t *padding)
648{
649 GNUNET_assert(
650 (message) &&
651 (buffer) &&
652 (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
653 );
654
655 uint16_t offset = 0;
656
657 if (GNUNET_YES == include_header)
658 {
659 ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
660 &(message->header.signature), buffer, length - offset
661 );
662
663 if (result < 0)
664 return GNUNET_NO;
665 else
666 offset += result;
667 }
668
669 const uint16_t count = length - offset;
670
671 if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, include_header))
672 return GNUNET_NO;
673
674 kind_t kind;
675
676 if (GNUNET_YES == include_header)
677 {
678 decode_step(buffer, offset, &(message->header.timestamp));
679 decode_step(buffer, offset, &(message->header.sender_id));
680 decode_step(buffer, offset, &(message->header.previous));
681 }
682
683 decode_step(buffer, offset, &kind);
684
685 message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
686
687 if (count < get_message_kind_size (message->header.kind, include_header))
688 return GNUNET_NO;
689
690 const uint16_t result = decode_message_body (&(message->header.kind), &(message->body), length, buffer, offset);
691
692 if (padding)
693 *padding = result;
694
695 return GNUNET_YES;
696}
697
698static int
699decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
700 uint16_t length,
701 const char *buffer)
702{
703 struct GNUNET_HashCode expected, hash;
704 uint16_t offset = sizeof(hash);
705
706 if (length < get_short_message_size (NULL, GNUNET_NO))
707 return GNUNET_NO;
708
709 GNUNET_memcpy(&hash, buffer, sizeof(hash));
710
711 GNUNET_CRYPTO_hash(
712 buffer + sizeof(hash),
713 length - sizeof(hash),
714 &expected
715 );
716
717 if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
718 return GNUNET_NO;
719
720 kind_t kind;
721
722 decode_step(buffer, offset, &kind);
723
724 message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
725
726 if (length < get_short_message_size (message, GNUNET_NO))
727 return GNUNET_NO;
728
729 decode_message_body (&(message->kind), &(message->body), length, buffer, offset);
730
731 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
732 return GNUNET_NO;
733
734 return GNUNET_YES;
735}
736
737void
738hash_message (const struct GNUNET_MESSENGER_Message *message,
739 uint16_t length,
740 const char *buffer,
741 struct GNUNET_HashCode *hash)
742{
743 GNUNET_assert((message) && (buffer) && (hash));
744
745 const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
746 &(message->header.signature)
747 );
748
749 GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
750}
751
752void
753sign_message (struct GNUNET_MESSENGER_Message *message,
754 uint16_t length,
755 char *buffer,
756 const struct GNUNET_HashCode *hash,
757 const struct GNUNET_MESSENGER_Ego *ego)
758{
759 GNUNET_assert((message) && (buffer) && (hash) && (ego));
760
761 struct GNUNET_MESSENGER_MessageSignature signature;
762
763 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
764 signature.purpose.size = htonl (sizeof(signature));
765
766 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
767 GNUNET_IDENTITY_sign(&(ego->priv), &signature, &(message->header.signature));
768
769 uint16_t offset = 0;
770 encode_step_signature(buffer, offset, &(message->header.signature), length);
771}
772
773int
774verify_message (const struct GNUNET_MESSENGER_Message *message,
775 const struct GNUNET_HashCode *hash,
776 const struct GNUNET_IDENTITY_PublicKey *key)
777{
778 GNUNET_assert((message) && (hash) && (key));
779
780 if (ntohl (key->type) != ntohl (message->header.signature.type))
781 return GNUNET_SYSERR;
782
783 struct GNUNET_MESSENGER_MessageSignature signature;
784
785 signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
786 signature.purpose.size = htonl (sizeof(signature));
787
788 GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
789
790 return GNUNET_IDENTITY_signature_verify(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
791 &(message->header.signature), key);
792}
793
794int
795encrypt_message (struct GNUNET_MESSENGER_Message *message,
796 const struct GNUNET_IDENTITY_PublicKey *key)
797{
798 GNUNET_assert((message) && (key));
799
800 struct GNUNET_MESSENGER_ShortMessage shortened;
801
802 fold_short_message (message, &shortened);
803
804 const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
805 const uint16_t padded_length = calc_padded_length(length);
806
807 message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
808 message->body.privacy.data = GNUNET_malloc(padded_length);
809 message->body.privacy.length = padded_length;
810
811 encode_short_message (&shortened, padded_length, message->body.privacy.data);
812
813 if (padded_length == GNUNET_IDENTITY_encrypt (message->body.privacy.data, padded_length, key,
814 &(message->body.privacy.key),
815 message->body.privacy.data))
816 {
817 destroy_message_body (shortened.kind, &(shortened.body));
818 return GNUNET_YES;
819 }
820 else
821 {
822 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Encrypting message failed!\n");
823
824 unfold_short_message (&shortened, message);
825 return GNUNET_NO;
826 }
827}
828
829int
830decrypt_message (struct GNUNET_MESSENGER_Message *message,
831 const struct GNUNET_IDENTITY_PrivateKey *key)
832{
833 GNUNET_assert((message) && (key));
834
835 if (message->body.privacy.length != GNUNET_IDENTITY_decrypt (message->body.privacy.data, message->body.privacy.length,
836 key, &(message->body.privacy.key),
837 message->body.privacy.data))
838 {
839 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decrypting message failed!\n");
840
841 return GNUNET_NO;
842 }
843
844 struct GNUNET_MESSENGER_ShortMessage shortened;
845
846 if (GNUNET_YES != decode_short_message (&shortened, message->body.privacy.length, message->body.privacy.data))
847 {
848 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Decoding decrypted message failed!\n");
849
850 return GNUNET_NO;
851 }
852
853 unfold_short_message (&shortened, message);
854
855 return GNUNET_YES;
856}
857
858struct GNUNET_MQ_Envelope*
859pack_message (struct GNUNET_MESSENGER_Message *message,
860 struct GNUNET_HashCode *hash,
861 const struct GNUNET_MESSENGER_Ego *ego,
862 int mode)
863{
864 GNUNET_assert(message);
865
866 if (ego)
867 message->header.signature.type = ego->priv.type;
868
869 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message kind=%u and sender: %s\n",
870 message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
871
872 struct GNUNET_MessageHeader *header;
873
874 const uint16_t length = get_message_size (message, GNUNET_YES);
875 const uint16_t padded_length = calc_padded_length(length);
876
877 struct GNUNET_MQ_Envelope *env;
878 char *buffer;
879
880 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
881 {
882 env = GNUNET_MQ_msg_extra(header, padded_length, GNUNET_MESSAGE_TYPE_CADET_CLI);
883
884 buffer = (char*) &(header[1]);
885 }
886 else
887 {
888 env = NULL;
889
890 buffer = GNUNET_malloc(padded_length);
891 }
892
893 encode_message (message, padded_length, buffer, GNUNET_YES);
894
895 if (hash)
896 {
897 hash_message (message, length, buffer, hash);
898
899 if (ego)
900 sign_message (message, length, buffer, hash, ego);
901 }
902
903 if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
904 GNUNET_free(buffer);
905
906 return env;
907}
908
909int
910filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
911{
912 switch (message->header.kind)
913 {
914 case GNUNET_MESSENGER_KIND_INFO:
915 return GNUNET_SYSERR; // Reserved for connection handling only!
916 case GNUNET_MESSENGER_KIND_JOIN:
917 return GNUNET_NO; // Use #GNUNET_MESSENGER_enter_room(...) instead!
918 case GNUNET_MESSENGER_KIND_LEAVE:
919 return GNUNET_NO; // Use #GNUNET_MESSENGER_close_room(...) instead!
920 case GNUNET_MESSENGER_KIND_NAME:
921 return GNUNET_YES;
922 case GNUNET_MESSENGER_KIND_KEY:
923 return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
924 case GNUNET_MESSENGER_KIND_PEER:
925 return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
926 case GNUNET_MESSENGER_KIND_ID:
927 return GNUNET_SYSERR; // Reserved for member id handling only!
928 case GNUNET_MESSENGER_KIND_MISS:
929 return GNUNET_SYSERR; // Reserved for connection handling only!
930 case GNUNET_MESSENGER_KIND_MERGE:
931 return GNUNET_YES;
932 case GNUNET_MESSENGER_KIND_REQUEST:
933 return GNUNET_YES;
934 case GNUNET_MESSENGER_KIND_INVITE:
935 return GNUNET_YES;
936 case GNUNET_MESSENGER_KIND_TEXT:
937 return GNUNET_YES;
938 case GNUNET_MESSENGER_KIND_FILE:
939 return GNUNET_YES;
940 case GNUNET_MESSENGER_KIND_PRIVATE:
941 return GNUNET_NO; // Use #GNUNET_MESSENGER_send_message(...) with a contact instead!
942 case GNUNET_MESSENGER_KIND_DELETE:
943 return GNUNET_YES;
944 default:
945 return GNUNET_SYSERR;
946 }
947}
diff --git a/src/messenger/messenger_api_message.h b/src/messenger/messenger_api_message.h
deleted file mode 100644
index 688c72994..000000000
--- a/src/messenger/messenger_api_message.h
+++ /dev/null
@@ -1,250 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/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_util_lib.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_signatures.h"
33
34#include "gnunet_messenger_service.h"
35
36#include "messenger_api_ego.h"
37
38#define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - GNUNET_MIN_MESSAGE_SIZE)
39
40#define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
41#define GNUNET_MESSENGER_PADDING_LEVEL0 (512)
42#define GNUNET_MESSENGER_PADDING_LEVEL1 (4096)
43#define GNUNET_MESSENGER_PADDING_LEVEL2 (32768)
44
45/**
46 * Creates and allocates a new message with a specific <i>kind</i>.
47 *
48 * @param[in] kind Kind of message
49 * @return New message
50 */
51struct GNUNET_MESSENGER_Message*
52create_message (enum GNUNET_MESSENGER_MessageKind kind);
53
54/**
55 * Creates and allocates a copy of a given <i>message</i>.
56 *
57 * @param[in] message Message
58 * @return New message
59 */
60struct GNUNET_MESSENGER_Message*
61copy_message (const struct GNUNET_MESSENGER_Message *message);
62
63/**
64 * Frees the messages body memory.
65 *
66 * @param[in,out] message Message
67 */
68void
69cleanup_message (struct GNUNET_MESSENGER_Message *message);
70
71/**
72 * Destroys a message and frees its memory fully.
73 *
74 * @param[in,out] message Message
75 */
76void
77destroy_message (struct GNUNET_MESSENGER_Message *message);
78
79/**
80 * Returns if the message should be bound to a member session.
81 *
82 * @param[in] message Message
83 * @return #GNUNET_YES or #GNUNET_NO
84 */
85int
86is_message_session_bound (const struct GNUNET_MESSENGER_Message *message);
87
88/**
89 * Returns the minimal size in bytes to encode a message of a specific <i>kind</i>.
90 *
91 * @param[in] kind Kind of message
92 * @param[in] include_header Flag to include header
93 * @return Minimal size to encode
94 */
95uint16_t
96get_message_kind_size (enum GNUNET_MESSENGER_MessageKind kind,
97 int include_header);
98
99/**
100 * Returns the exact size in bytes to encode a given <i>message</i>.
101 *
102 * @param[in] message Message
103 * @param[in] include_header Flag to include header
104 * @return Size to encode
105 */
106uint16_t
107get_message_size (const struct GNUNET_MESSENGER_Message *message,
108 int include_header);
109
110/**
111 * Encodes a given <i>message</i> into a <i>buffer</i> of a maximal <i>length</i> in bytes.
112 *
113 * @param[in] message Message
114 * @param[in] length Maximal length to encode
115 * @param[out] buffer Buffer
116 * @param[in] include_header Flag to include header
117 */
118void
119encode_message (const struct GNUNET_MESSENGER_Message *message,
120 uint16_t length,
121 char *buffer,
122 int include_header);
123
124/**
125 * Decodes a <i>message</i> from a given <i>buffer</i> of a maximal <i>length</i> in bytes.
126 *
127 * If the buffer is too small for a message of its decoded kind the function fails with
128 * resulting #GNUNET_NO after decoding only the messages header.
129 *
130 * On success the function returns #GNUNET_YES.
131 *
132 * @param[out] message Message
133 * @param[in] length Maximal length to decode
134 * @param[in] buffer Buffer
135 * @param[in] include_header Flag to include header
136 * @param[out] padding Padding
137 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
138 */
139int
140decode_message (struct GNUNET_MESSENGER_Message *message,
141 uint16_t length,
142 const char *buffer,
143 int include_header,
144 uint16_t *padding);
145
146/**
147 * Calculates a <i>hash</i> of a given <i>buffer</i> with a <i>length</i> in bytes
148 * from a <i>message</i>.
149 *
150 * @param[in] message Message
151 * @param[in] length Length of buffer
152 * @param[in] buffer Buffer
153 * @param[out] hash Hash
154 */
155void
156hash_message (const struct GNUNET_MESSENGER_Message *message,
157 uint16_t length,
158 const char *buffer,
159 struct GNUNET_HashCode *hash);
160
161/**
162 * Signs the <i>hash</i> of a <i>message</i> with a given <i>ego</i> and writes the signature
163 * into the <i>buffer</i> as well.
164 *
165 * @param[in,out] message Message
166 * @param[in] length Length of buffer
167 * @param[out] buffer Buffer
168 * @param[in] hash Hash of message
169 * @param[in] ego EGO
170 */
171void
172sign_message (struct GNUNET_MESSENGER_Message *message,
173 uint16_t length,
174 char *buffer,
175 const struct GNUNET_HashCode *hash,
176 const struct GNUNET_MESSENGER_Ego *ego);
177
178/**
179 * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a specific
180 * public key. The function returns #GNUNET_OK if the signature was valid, otherwise
181 * #GNUNET_SYSERR.
182 *
183 * @param[in] message Message
184 * @param[in] hash Hash of message
185 * @param[in] key Public key of EGO
186 * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
187 */
188int
189verify_message (const struct GNUNET_MESSENGER_Message *message,
190 const struct GNUNET_HashCode *hash,
191 const struct GNUNET_IDENTITY_PublicKey *key);
192
193/**
194 * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its body
195 * and kind with the now private encrypted <i>message</i>. The function returns
196 * #GNUNET_YES if the operation succeeded, otherwise #GNUNET_NO.
197 *
198 * @param[in,out] message Message
199 * @param[in] key Public key of EGO
200 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
201 */
202int
203encrypt_message (struct GNUNET_MESSENGER_Message *message,
204 const struct GNUNET_IDENTITY_PublicKey *key);
205
206/**
207 * Decrypts a private <i>message</i> using a given private <i>key</i> and replaces its body
208 * and kind with the inner encrypted message. The function returns #GNUNET_YES if the
209 * operation succeeded, otherwise #GNUNET_NO.
210 *
211 * @param[in,out] message Message
212 * @param[in] key Private key of EGO
213 * @return #GNUNET_YES on success, otherwise #GNUNET_NO
214 */
215int
216decrypt_message (struct GNUNET_MESSENGER_Message *message,
217 const struct GNUNET_IDENTITY_PrivateKey *key);
218
219#define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1
220#define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0
221
222/**
223 * Encodes the <i>message</i> to pack it into a newly allocated envelope if <i>mode</i>
224 * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode the message
225 * will be hashed if <i>hash</i> is not NULL and it will be signed if the <i>ego</i> is
226 * not NULL.
227 *
228 * @param[out] message Message
229 * @param[out] hash Hash of message
230 * @param[in] ego EGO to sign
231 * @param[in] mode Mode of packing
232 * @return Envelope or NULL
233 */
234struct GNUNET_MQ_Envelope*
235pack_message (struct GNUNET_MESSENGER_Message *message,
236 struct GNUNET_HashCode *hash,
237 const struct GNUNET_MESSENGER_Ego *ego,
238 int mode);
239
240/**
241 * Returns if a specific kind of message should be sent by a client. The function returns
242 * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for specific kinds
243 * of messages which should not be sent manually at all.
244 *
245 * @param[in] message Message
246 */
247int
248filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
249
250#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 c3e8bc957..000000000
--- a/src/messenger/messenger_api_room.c
+++ /dev/null
@@ -1,369 +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 "platform.h"
27#include "messenger_api_room.h"
28
29#include "messenger_api_handle.h"
30
31struct GNUNET_MESSENGER_Room*
32create_room (struct GNUNET_MESSENGER_Handle *handle,
33 const struct GNUNET_HashCode *key)
34{
35 GNUNET_assert((handle) && (key));
36
37 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
38
39 room->handle = handle;
40 GNUNET_memcpy(&(room->key), key, sizeof(*key));
41
42 room->opened = GNUNET_NO;
43 room->contact_id = NULL;
44
45 init_list_tunnels (&(room->entries));
46
47 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
48 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
49
50 return room;
51}
52
53static int
54iterate_destroy_message (void *cls,
55 const struct GNUNET_HashCode *key,
56 void *value)
57{
58 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
59
60 destroy_message (entry->message);
61 GNUNET_free(entry);
62
63 return GNUNET_YES;
64}
65
66void
67destroy_room (struct GNUNET_MESSENGER_Room *room)
68{
69 GNUNET_assert(room);
70
71 clear_list_tunnels (&(room->entries));
72
73 if (room->messages)
74 {
75 GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL);
76
77 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
78 }
79
80 if (room->members)
81 GNUNET_CONTAINER_multishortmap_destroy (room->members);
82
83 if (room->contact_id)
84 GNUNET_free(room->contact_id);
85
86 GNUNET_free(room);
87}
88
89const struct GNUNET_MESSENGER_Message*
90get_room_message (const struct GNUNET_MESSENGER_Room *room,
91 const struct GNUNET_HashCode *hash)
92{
93 GNUNET_assert((room) && (hash));
94
95 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
96 room->messages, hash
97 );
98
99 return (entry? entry->message : NULL);
100}
101
102struct GNUNET_MESSENGER_Contact*
103get_room_sender (const struct GNUNET_MESSENGER_Room *room,
104 const struct GNUNET_HashCode *hash)
105{
106 GNUNET_assert((room) && (hash));
107
108 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
109 room->messages, hash
110 );
111
112 return (entry? entry->sender : NULL);
113}
114
115static struct GNUNET_MESSENGER_Contact*
116handle_join_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 if (!sender)
122 {
123 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
124 struct GNUNET_HashCode context;
125
126 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
127
128 sender = get_store_contact(store, &context, &(message->body.join.key));
129 }
130
131 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
132 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
133 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
134 increase_contact_rc(sender);
135
136 return sender;
137}
138
139static void
140handle_leave_message (struct GNUNET_MESSENGER_Room *room,
141 struct GNUNET_MESSENGER_Contact *sender,
142 const struct GNUNET_MESSENGER_Message *message,
143 const struct GNUNET_HashCode *hash)
144{
145 if ((!sender) ||
146 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
147 return;
148
149 struct GNUNET_HashCode context;
150 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
151
152 if (GNUNET_YES == decrease_contact_rc(sender))
153 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
154}
155
156static void
157handle_name_message (struct GNUNET_MESSENGER_Room *room,
158 struct GNUNET_MESSENGER_Contact *sender,
159 const struct GNUNET_MESSENGER_Message *message,
160 const struct GNUNET_HashCode *hash)
161{
162 if (!sender)
163 return;
164
165 set_contact_name (sender, message->body.name.name);
166}
167
168static void
169handle_key_message (struct GNUNET_MESSENGER_Room *room,
170 struct GNUNET_MESSENGER_Contact *sender,
171 const struct GNUNET_MESSENGER_Message *message,
172 const struct GNUNET_HashCode *hash)
173{
174 if (!sender)
175 return;
176
177 struct GNUNET_HashCode context;
178 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
179
180 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
181
182 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
183}
184
185static void
186handle_id_message (struct GNUNET_MESSENGER_Room *room,
187 struct GNUNET_MESSENGER_Contact *sender,
188 const struct GNUNET_MESSENGER_Message *message,
189 const struct GNUNET_HashCode *hash)
190{
191 if ((!sender) ||
192 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
193 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
194 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
195 return;
196
197 struct GNUNET_HashCode context, next_context;
198 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
199 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
200
201 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
202
203 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
204}
205
206static void
207handle_miss_message (struct GNUNET_MESSENGER_Room *room,
208 struct GNUNET_MESSENGER_Contact *sender,
209 const struct GNUNET_MESSENGER_Message *message,
210 const struct GNUNET_HashCode *hash)
211{
212 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
213 {
214 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
215
216 if (match)
217 remove_from_list_tunnels (&(room->entries), match);
218 }
219}
220
221static void
222handle_delete_message (struct GNUNET_MESSENGER_Room *room,
223 struct GNUNET_MESSENGER_Contact *sender,
224 const struct GNUNET_MESSENGER_Message *message,
225 const struct GNUNET_HashCode *hash)
226{
227 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
228 room->messages, &(message->body.deletion.hash)
229 );
230
231 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
232 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.deletion.hash), entry)))
233 {
234 destroy_message (entry->message);
235 GNUNET_free(entry);
236 }
237}
238
239struct GNUNET_MESSENGER_Contact*
240handle_room_message (struct GNUNET_MESSENGER_Room *room,
241 struct GNUNET_MESSENGER_Contact *sender,
242 const struct GNUNET_MESSENGER_Message *message,
243 const struct GNUNET_HashCode *hash)
244{
245 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
246 return sender;
247
248 switch (message->header.kind)
249 {
250 case GNUNET_MESSENGER_KIND_JOIN:
251 sender = handle_join_message (room, sender, message, hash);
252 break;
253 case GNUNET_MESSENGER_KIND_LEAVE:
254 handle_leave_message (room, sender, message, hash);
255 break;
256 case GNUNET_MESSENGER_KIND_NAME:
257 handle_name_message (room, sender, message, hash);
258 break;
259 case GNUNET_MESSENGER_KIND_KEY:
260 handle_key_message (room, sender, message, hash);
261 break;
262 case GNUNET_MESSENGER_KIND_ID:
263 handle_id_message (room, sender, message, hash);
264 break;
265 case GNUNET_MESSENGER_KIND_MISS:
266 handle_miss_message (room, sender, message, hash);
267 break;
268 case GNUNET_MESSENGER_KIND_DELETE:
269 handle_delete_message (room, sender, message, hash);
270 break;
271 default:
272 break;
273 }
274
275 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
276
277 if (!entry)
278 return sender;
279
280 entry->sender = sender;
281 entry->message = copy_message (message);
282
283 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
284 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
285 {
286 destroy_message (entry->message);
287 GNUNET_free(entry);
288 }
289
290 return sender;
291}
292
293struct GNUNET_MESSENGER_MemberCall
294{
295 struct GNUNET_MESSENGER_Room *room;
296 GNUNET_MESSENGER_MemberCallback callback;
297 void *cls;
298};
299
300static int
301iterate_local_members (void* cls,
302 const struct GNUNET_ShortHashCode *key,
303 void *value)
304{
305 struct GNUNET_MESSENGER_MemberCall *call = cls;
306 struct GNUNET_MESSENGER_Contact *contact = value;
307
308 return call->callback(call->cls, call->room, contact);
309}
310
311int
312iterate_room_members (struct GNUNET_MESSENGER_Room *room,
313 GNUNET_MESSENGER_MemberCallback callback,
314 void* cls)
315{
316 GNUNET_assert(room);
317
318 if (!callback)
319 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
320
321 struct GNUNET_MESSENGER_MemberCall call;
322
323 call.room = room;
324 call.callback = callback;
325 call.cls = cls;
326
327 GNUNET_assert(callback);
328
329 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
330}
331
332struct GNUNET_MESSENGER_MemberFind
333{
334 const struct GNUNET_MESSENGER_Contact *contact;
335 int result;
336};
337
338static int
339iterate_find_member (void* cls,
340 const struct GNUNET_ShortHashCode *key,
341 void *value)
342{
343 struct GNUNET_MESSENGER_MemberFind *find = cls;
344 struct GNUNET_MESSENGER_Contact *contact = value;
345
346 if (contact == find->contact)
347 {
348 find->result = GNUNET_YES;
349 return GNUNET_NO;
350 }
351
352 return GNUNET_YES;
353}
354
355int
356find_room_member (const struct GNUNET_MESSENGER_Room *room,
357 const struct GNUNET_MESSENGER_Contact *contact)
358{
359 GNUNET_assert(room);
360
361 struct GNUNET_MESSENGER_MemberFind find;
362
363 find.contact = contact;
364 find.result = GNUNET_NO;
365
366 GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_find_member, &find);
367
368 return find.result;
369}
diff --git a/src/messenger/messenger_api_room.h b/src/messenger/messenger_api_room.h
deleted file mode 100644
index d5ffc5c4b..000000000
--- a/src/messenger/messenger_api_room.h
+++ /dev/null
@@ -1,146 +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_util_lib.h"
31
32#include "gnunet_messenger_service.h"
33
34#include "messenger_api_list_tunnels.h"
35#include "messenger_api_contact.h"
36#include "messenger_api_message.h"
37
38struct GNUNET_MESSENGER_RoomMessageEntry {
39 struct GNUNET_MESSENGER_Contact* sender;
40 struct GNUNET_MESSENGER_Message* message;
41};
42
43struct GNUNET_MESSENGER_Room
44{
45 struct GNUNET_MESSENGER_Handle *handle;
46 struct GNUNET_HashCode key;
47
48 int opened;
49
50 struct GNUNET_ShortHashCode *contact_id;
51
52 struct GNUNET_MESSENGER_ListTunnels entries;
53
54 struct GNUNET_CONTAINER_MultiHashMap *messages;
55 struct GNUNET_CONTAINER_MultiShortmap *members;
56};
57
58/**
59 * Creates and allocates a new room for a <i>handle</i> with a given <i>key</i> for the client API.
60 *
61 * @param[in,out] handle Handle
62 * @param[in] key Key of room
63 * @return New room
64 */
65struct GNUNET_MESSENGER_Room*
66create_room (struct GNUNET_MESSENGER_Handle *handle,
67 const struct GNUNET_HashCode *key);
68
69/**
70 * Destroys a room and frees its memory fully from the client API.
71 *
72 * @param[in,out] room Room
73 */
74void
75destroy_room (struct GNUNET_MESSENGER_Room *room);
76
77/**
78 * Returns a message locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no matching
79 * message is found, NULL gets returned.
80 *
81 * @param[in] room Room
82 * @param[in] hash Hash of message
83 * @return Message or NULL
84 */
85const struct GNUNET_MESSENGER_Message*
86get_room_message (const struct GNUNET_MESSENGER_Room *room,
87 const struct GNUNET_HashCode *hash);
88
89/**
90 * Returns a messages sender locally stored from a map for a given <i>hash</i> in a <i>room</i>. If no
91 * matching message is found, NULL gets returned.
92 *
93 * @param[in] room Room
94 * @param[in] hash Hash of message
95 * @return Contact of sender or NULL
96 */
97struct GNUNET_MESSENGER_Contact*
98get_room_sender (const struct GNUNET_MESSENGER_Room *room,
99 const struct GNUNET_HashCode *hash);
100
101/**
102 * Handles a <i>message</i> with a given <i>hash</i> in a <i>room</i> for the client API to update
103 * members and its information. The function also stores the message in map locally for access afterwards.
104 *
105 * The contact of the message's sender could be updated or even created. It may not be freed or destroyed though!
106 * (The contact may still be in use for old messages...)
107 *
108 * @param[in,out] room Room
109 * @param[in,out] sender Contact of sender
110 * @param[in] message Message
111 * @param[in] hash Hash of message
112 * @return Contact of sender
113 */
114struct GNUNET_MESSENGER_Contact*
115handle_room_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/**
121 * Iterates through all members of a given <i>room</i> to forward each of them to a selected
122 * <i>callback</i> with a custom closure.
123 *
124 * @param[in,out] room Room
125 * @param[in] callback Function called for each member
126 * @param[in,out] cls Closure
127 * @return Amount of members iterated
128 */
129int
130iterate_room_members (struct GNUNET_MESSENGER_Room *room,
131 GNUNET_MESSENGER_MemberCallback callback,
132 void* cls);
133
134/**
135 * Checks through all members of a given <i>room</i> if a specific <i>contact</i> is found and
136 * returns a result depending on that.
137 *
138 * @param[in] room Room
139 * @param[in] contact
140 * @return #GNUNET_YES if found, otherwise #GNUNET_NO
141 */
142int
143find_room_member (const struct GNUNET_MESSENGER_Room *room,
144 const struct GNUNET_MESSENGER_Contact *contact);
145
146#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 f56e2e201..000000000
--- a/src/messenger/messenger_api_util.c
+++ /dev/null
@@ -1,103 +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 "platform.h"
27#include "messenger_api_util.h"
28
29static void
30callback_close_channel (void *cls)
31{
32 struct GNUNET_CADET_Channel *channel = cls;
33
34 if (channel)
35 GNUNET_CADET_channel_destroy (channel);
36}
37
38void
39delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel)
40{
41 GNUNET_assert(channel);
42
43 GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ (),
44 GNUNET_SCHEDULER_PRIORITY_URGENT,
45 callback_close_channel, channel);
46}
47
48int
49generate_free_member_id (struct GNUNET_ShortHashCode *id,
50 const struct GNUNET_CONTAINER_MultiShortmap *members)
51{
52 GNUNET_assert(id);
53
54 size_t counter = 1 + (members ? GNUNET_CONTAINER_multishortmap_size (members) : 0);
55
56 do
57 {
58 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_STRONG, id, sizeof(struct GNUNET_ShortHashCode));
59
60 if ((members) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_contains (members, id)))
61 counter--;
62 else
63 break;
64 }
65 while (counter > 0);
66
67 if (counter)
68 return GNUNET_YES;
69
70 return GNUNET_NO;
71}
72
73const struct GNUNET_IDENTITY_PublicKey*
74get_anonymous_public_key ()
75{
76 static struct GNUNET_IDENTITY_PublicKey public_key;
77 static struct GNUNET_IDENTITY_Ego* ego = NULL;
78
79 if (!ego)
80 {
81 ego = GNUNET_IDENTITY_ego_get_anonymous();
82 GNUNET_IDENTITY_ego_get_public_key(ego, &public_key);
83 }
84
85 return &public_key;
86}
87
88void
89convert_messenger_key_to_port(const struct GNUNET_HashCode *key,
90 struct GNUNET_HashCode *port)
91{
92 static uint32_t version_value = 0;
93 static struct GNUNET_HashCode version;
94
95 if (!version_value) {
96 version_value = (uint32_t) (GNUNET_MESSENGER_VERSION);
97 version_value = ((version_value >> 16) & 0xFFFF);
98 version_value = GNUNET_htole32(version_value);
99 GNUNET_CRYPTO_hash(&version_value, sizeof(version_value), &version);
100 }
101
102 GNUNET_CRYPTO_hash_sum(key, &version, port);
103}
diff --git a/src/messenger/messenger_api_util.h b/src/messenger/messenger_api_util.h
deleted file mode 100644
index 3d68505a8..000000000
--- a/src/messenger/messenger_api_util.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/messenger_api_util.h
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#ifndef GNUNET_SERVICE_MESSENGER_UTIL_H
27#define GNUNET_SERVICE_MESSENGER_UTIL_H
28
29#include "platform.h"
30#include "gnunet_cadet_service.h"
31#include "gnunet_util_lib.h"
32#include "gnunet_identity_service.h"
33#include "gnunet_messenger_service.h"
34
35/**
36 * Starts an urgent task to close a CADET channel asynchronously.
37 *
38 * @param[in,out] channel Channel
39 */
40void
41delayed_disconnect_channel (struct GNUNET_CADET_Channel *channel);
42
43/**
44 * Tries to generate an unused member id and store it into the <i>id</i> parameter.
45 * A map containing all currently used member ids is used to check against.
46 *
47 * @param[out] id New member id
48 * @param[in] members Map of member ids
49 * @return #GNUNET_YES on success, #GNUNET_NO on failure
50 */
51int
52generate_free_member_id (struct GNUNET_ShortHashCode *id,
53 const struct GNUNET_CONTAINER_MultiShortmap *members);
54
55/**
56 * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() without
57 * recalculating it every time.
58 *
59 * @return anonymous public key
60 */
61const struct GNUNET_IDENTITY_PublicKey*
62get_anonymous_public_key ();
63
64/**
65 * Converts a Messenger service key of a room to the specific port which
66 * gets used for the CADET channels.
67 *
68 * The port includes upper bits of the #GNUNET_MESSENGER_VERSION to
69 * reduce the chance of incompatible connections.
70 *
71 * @param[in] key Messenger service room key
72 * @param[out] port CADET service port
73 */
74void
75convert_messenger_key_to_port(const struct GNUNET_HashCode *key,
76 struct GNUNET_HashCode *port);
77
78#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 e09a0330d..000000000
--- a/src/messenger/plugin_gnsrecord_messenger.c
+++ /dev/null
@@ -1,298 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2021--2022 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", key, door);
67 GNUNET_free (key);
68 GNUNET_free (door);
69 return ret;
70 }
71 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS:
72 {
73 if (data_size != sizeof(struct GNUNET_MESSENGER_RoomDetailsRecord))
74 {
75 GNUNET_break_op (0);
76 return NULL;
77 }
78
79 const struct GNUNET_MESSENGER_RoomDetailsRecord *record = data;
80
81 char *name = GNUNET_strndup(record->name, 256);
82 char *flags = GNUNET_STRINGS_data_to_string_alloc (&(record->flags), sizeof(uint32_t));
83
84 char *ret;
85 GNUNET_asprintf (&ret, "%s-%s", flags, name);
86 GNUNET_free (flags);
87 GNUNET_free (name);
88 return ret;
89 }
90 default:
91 return NULL;
92 }
93}
94
95
96/**
97 * Convert human-readable version of a 'value' of a record to the binary
98 * representation.
99 *
100 * @param cls closure, unused
101 * @param type type of the record
102 * @param s human-readable string
103 * @param data set to value in binary encoding (will be allocated)
104 * @param data_size set to number of bytes in @a data
105 * @return #GNUNET_OK on success
106 */
107static int
108messenger_string_to_value (void *cls,
109 uint32_t type,
110 const char *s,
111 void **data,
112 size_t *data_size)
113{
114 (void) cls;
115 if (NULL == s)
116 {
117 GNUNET_break (0);
118 return GNUNET_SYSERR;
119 }
120
121 switch (type)
122 {
123 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY:
124 {
125 char key [103];
126 const char *dash;
127 struct GNUNET_PeerIdentity door;
128
129 if ((NULL == (dash = strchr (s, '-'))) ||
130 (1 != sscanf (s, "%103s-", key)) ||
131 (GNUNET_OK != GNUNET_CRYPTO_eddsa_public_key_from_string (dash + 1,
132 strlen (dash + 1),
133 &(door.public_key))))
134 {
135 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
136 _ ("Unable to parse MESSENGER_ROOM_ENTRY record `%s'\n"),
137 s);
138 return GNUNET_SYSERR;
139 }
140
141 struct GNUNET_MESSENGER_RoomEntryRecord *record = GNUNET_new (
142 struct GNUNET_MESSENGER_RoomEntryRecord
143 );
144
145 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (key,
146 strlen (key),
147 &(record->key),
148 sizeof(struct GNUNET_HashCode)))
149 {
150 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
151 _ ("Unable to parse MESSENGER_ROOM_ENTRY record `%s'\n"),
152 s);
153 GNUNET_free (record);
154 return GNUNET_SYSERR;
155 }
156
157 record->door = door;
158 *data = record;
159 *data_size = sizeof(struct GNUNET_MESSENGER_RoomEntryRecord);
160 return GNUNET_OK;
161 }
162 case GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS:
163 {
164 char flags [7];
165 const char *dash;
166
167 if ((NULL == (dash = strchr (s, '-'))) ||
168 (1 != sscanf (s, "%7s-", flags)) ||
169 (strlen (dash + 1) > 256))
170 {
171 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
172 _ ("Unable to parse MESSENGER_ROOM_DETAILS record `%s'\n"),
173 s);
174 return GNUNET_SYSERR;
175 }
176
177 struct GNUNET_MESSENGER_RoomDetailsRecord *record = GNUNET_new (
178 struct GNUNET_MESSENGER_RoomDetailsRecord
179 );
180
181 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (flags,
182 strlen (flags),
183 &(record->flags),
184 sizeof(uint32_t)))
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 _ ("Unable to parse MESSENGER_ROOM_DETAILS record `%s'\n"),
188 s);
189 GNUNET_free (record);
190 return GNUNET_SYSERR;
191 }
192
193 GNUNET_memcpy(record->name, dash + 1, strlen(dash + 1));
194
195 *data = record;
196 *data_size = sizeof(struct GNUNET_MESSENGER_RoomDetailsRecord);
197 return GNUNET_OK;
198 }
199 default:
200 return GNUNET_SYSERR;
201 }
202}
203
204
205/**
206 * Mapping of record type numbers to human-readable
207 * record type names.
208 */
209static struct
210{
211 const char *name;
212 uint32_t number;
213} name_map[] = {
214 { "MESSENGER_ROOM_ENTRY", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_ENTRY },
215 { "MESSENGER_ROOM_DETAILS", GNUNET_GNSRECORD_TYPE_MESSENGER_ROOM_DETAILS },
216 { NULL, UINT32_MAX }
217};
218
219
220/**
221 * Convert a type name (e.g. "AAAA") to the corresponding number.
222 *
223 * @param cls closure, unused
224 * @param gns_typename name to convert
225 * @return corresponding number, UINT32_MAX on error
226 */
227static uint32_t
228messenger_typename_to_number (void *cls,
229 const char *gns_typename)
230{
231 unsigned int i;
232
233 (void) cls;
234 i = 0;
235 while ((name_map[i].name != NULL) &&
236 (0 != strcasecmp (gns_typename, name_map[i].name)))
237 i++;
238 return name_map[i].number;
239}
240
241
242/**
243 * Convert a type number to the corresponding type string (e.g. 1 to "A")
244 *
245 * @param cls closure, unused
246 * @param type number of a type to convert
247 * @return corresponding typestring, NULL on error
248 */
249static const char *
250messenger_number_to_typename (void *cls,
251 uint32_t type)
252{
253 unsigned int i;
254
255 (void) cls;
256 i = 0;
257 while ((name_map[i].name != NULL) &&
258 (type != name_map[i].number))
259 i++;
260 return name_map[i].name;
261}
262
263
264/**
265 * Entry point for the plugin.
266 *
267 * @param cls NULL
268 * @return the exported block API
269 */
270void *
271libgnunet_plugin_gnsrecord_messenger_init (void *cls)
272{
273 struct GNUNET_GNSRECORD_PluginFunctions *api;
274
275 (void) cls;
276 api = GNUNET_new (struct GNUNET_GNSRECORD_PluginFunctions);
277 api->value_to_string = &messenger_value_to_string;
278 api->string_to_value = &messenger_string_to_value;
279 api->typename_to_number = &messenger_typename_to_number;
280 api->number_to_typename = &messenger_number_to_typename;
281 return api;
282}
283
284
285/**
286 * Exit point from the plugin.
287 *
288 * @param cls the return value from #libgnunet_plugin_block_test_init
289 * @return NULL
290 */
291void *
292libgnunet_plugin_gnsrecord_messenger_done (void *cls)
293{
294 struct GNUNET_GNSRECORD_PluginFunctions *api = cls;
295
296 GNUNET_free (api);
297 return NULL;
298}
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
deleted file mode 100644
index 8758ce562..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 "platform.h"
26#include <stdio.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 b19634152..000000000
--- a/src/messenger/test_messenger_adapt.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 5, 1, 2, 3, 6, 7, 8, 4 };
41 unsigned int stages [] = { 0x21, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x21 };
42
43 struct test_configuration cfg;
44 cfg.count = 8;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_adapt", &cfg);
49}
diff --git a/src/messenger/test_messenger_anonymous.c b/src/messenger/test_messenger_anonymous.c
deleted file mode 100644
index 13f2b6f0e..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 "platform.h"
26#include <stdio.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 580fc1ecb..000000000
--- a/src/messenger/test_messenger_async_client.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 0, 1 };
41 unsigned int stages [] = { 0x10, 0x20 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_async_client", &cfg);
49}
diff --git a/src/messenger/test_messenger_async_p2p.c b/src/messenger/test_messenger_async_p2p.c
deleted file mode 100644
index 762be9d49..000000000
--- a/src/messenger/test_messenger_async_p2p.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 2, 1 };
41 unsigned int stages [] = { 0x30, 0x30 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_async_p2p", &cfg);
49}
diff --git a/src/messenger/test_messenger_growth.c b/src/messenger/test_messenger_growth.c
deleted file mode 100644
index 4a73e559d..000000000
--- a/src/messenger/test_messenger_growth.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
41 unsigned int stages [] = { 0x01, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
42
43 struct test_configuration cfg;
44 cfg.count = 8;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_growth", &cfg);
49}
diff --git a/src/messenger/test_messenger_ring.c b/src/messenger/test_messenger_ring.c
deleted file mode 100644
index c6b17861e..000000000
--- a/src/messenger/test_messenger_ring.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 8, 1, 2, 3, 4, 5, 6, 7 };
41 unsigned int stages [] = { 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21 };
42
43 struct test_configuration cfg;
44 cfg.count = 8;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_ring", &cfg);
49}
diff --git a/src/messenger/test_messenger_server.c b/src/messenger/test_messenger_server.c
deleted file mode 100644
index fdd9a3684..000000000
--- a/src/messenger/test_messenger_server.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 0, 1, 1, 1, 1, 1, 1, 1 };
41 unsigned int stages [] = { 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
42
43 struct test_configuration cfg;
44 cfg.count = 8;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_server", &cfg);
49}
diff --git a/src/messenger/test_messenger_sync_client.c b/src/messenger/test_messenger_sync_client.c
deleted file mode 100644
index 74c9548bc..000000000
--- a/src/messenger/test_messenger_sync_client.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 0, 1 };
41 unsigned int stages [] = { 0x01, 0x20 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_sync_client", &cfg);
49}
diff --git a/src/messenger/test_messenger_sync_p2p.c b/src/messenger/test_messenger_sync_p2p.c
deleted file mode 100644
index 299d5ff68..000000000
--- a/src/messenger/test_messenger_sync_p2p.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 2, 1 };
41 unsigned int stages [] = { 0x21, 0x21 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_sync_p2p", &cfg);
49}
diff --git a/src/messenger/test_messenger_worst_client.c b/src/messenger/test_messenger_worst_client.c
deleted file mode 100644
index ab535b876..000000000
--- a/src/messenger/test_messenger_worst_client.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 0, 1 };
41 unsigned int stages [] = { 0x10, 0x02 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_worst_client", &cfg);
49}
diff --git a/src/messenger/test_messenger_worst_p2p.c b/src/messenger/test_messenger_worst_p2p.c
deleted file mode 100644
index 0af9489a4..000000000
--- a/src/messenger/test_messenger_worst_p2p.c
+++ /dev/null
@@ -1,49 +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 "platform.h"
27#include "testing_messenger_setup.h"
28
29/**
30 * The main function.
31 *
32 * @param argc number of arguments from the command line
33 * @param argv command line arguments
34 * @return 0 ok, 1 on error
35 */
36int
37main (int argc,
38 char **argv)
39{
40 unsigned int doors [] = { 2, 1 };
41 unsigned int stages [] = { 0x12, 0x12 };
42
43 struct test_configuration cfg;
44 cfg.count = 2;
45 cfg.doors = doors;
46 cfg.stages = stages;
47
48 return GNUNET_run_messenger_setup ("test_messenger_worst_p2p", &cfg);
49}
diff --git a/src/messenger/testing_messenger_barrier.c b/src/messenger/testing_messenger_barrier.c
deleted file mode 100644
index 60d1fc0fe..000000000
--- a/src/messenger/testing_messenger_barrier.c
+++ /dev/null
@@ -1,173 +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 "platform.h"
27#include "testing_messenger_barrier.h"
28
29struct GNUNET_BarrierHandle
30{
31 unsigned int requirement;
32 GNUNET_BarrierStatusCallback cb;
33 void *cls;
34
35 struct GNUNET_BarrierWaitHandle *head;
36 struct GNUNET_BarrierWaitHandle *tail;
37
38 struct GNUNET_SCHEDULER_Task* task;
39};
40
41struct GNUNET_BarrierHandle*
42GNUNET_init_barrier (unsigned int requirement,
43 GNUNET_BarrierStatusCallback cb,
44 void *cb_cls)
45{
46 if (0 == requirement)
47 return NULL;
48
49 struct GNUNET_BarrierHandle *barrier = GNUNET_new(struct GNUNET_BarrierHandle);
50
51 if (!barrier)
52 return NULL;
53
54 barrier->requirement = requirement;
55 barrier->cb = cb;
56 barrier->cls = cb_cls;
57 barrier->head = NULL;
58 barrier->tail = NULL;
59 barrier->task = NULL;
60
61 return barrier;
62}
63
64static void
65exit_status (struct GNUNET_BarrierHandle *barrier,
66 int status);
67
68static void
69cancel_barrier (void *cls)
70{
71 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_SYSERR);
72}
73
74static void
75complete_barrier (void *cls)
76{
77 exit_status ((struct GNUNET_BarrierHandle*) cls, GNUNET_OK);
78}
79
80void
81GNUNET_cancel_barrier (struct GNUNET_BarrierHandle *barrier)
82{
83 if ((!barrier) || (barrier->task))
84 return;
85
86 barrier->task = GNUNET_SCHEDULER_add_now(cancel_barrier, barrier);
87}
88
89struct GNUNET_BarrierWaitHandle
90{
91 GNUNET_BarrierWaitStatusCallback cb;
92 void *cls;
93
94 struct GNUNET_BarrierWaitHandle *prev;
95 struct GNUNET_BarrierWaitHandle *next;
96
97 struct GNUNET_BarrierHandle *barrier;
98};
99
100static void
101exit_status (struct GNUNET_BarrierHandle *barrier,
102 int status)
103{
104 struct GNUNET_BarrierWaitHandle *waiting = barrier->head;
105 while (waiting)
106 {
107 struct GNUNET_BarrierWaitHandle *current = waiting;
108
109 if (current->cb)
110 current->cb(current->cls, current, status);
111
112 waiting = waiting->next;
113
114 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, current);
115 GNUNET_free(current);
116 }
117
118 if (barrier->cb)
119 barrier->cb(barrier->cls, barrier, status);
120
121 GNUNET_free(barrier);
122}
123
124struct GNUNET_BarrierWaitHandle*
125GNUNET_wait_barrier (struct GNUNET_BarrierHandle *barrier,
126 GNUNET_BarrierWaitStatusCallback cb,
127 void *cb_cls)
128{
129 if ((!barrier) || (0 == barrier->requirement))
130 return NULL;
131
132 struct GNUNET_BarrierWaitHandle *waiting = GNUNET_new(struct GNUNET_BarrierWaitHandle);
133
134 if (!waiting)
135 return NULL;
136
137 waiting->cb = cb;
138 waiting->cls = cb_cls;
139 waiting->prev = NULL;
140 waiting->next = NULL;
141 waiting->barrier = barrier;
142
143 GNUNET_CONTAINER_DLL_insert_tail(barrier->head, barrier->tail, waiting);
144 barrier->requirement--;
145
146 if ((barrier->requirement == 0) && (!barrier->task))
147 barrier->task = GNUNET_SCHEDULER_add_now(complete_barrier, barrier);
148
149 return waiting;
150}
151
152void
153GNUNET_cancel_wait_barrier (struct GNUNET_BarrierWaitHandle *waiting)
154{
155 if (!waiting)
156 return;
157
158 struct GNUNET_BarrierHandle *barrier = waiting->barrier;
159
160 if (!barrier)
161 return;
162
163 if ((barrier->requirement == 0) && (barrier->task))
164 {
165 GNUNET_SCHEDULER_cancel(barrier->task);
166 barrier->task = NULL;
167 }
168
169 barrier->requirement++;
170 GNUNET_CONTAINER_DLL_remove(barrier->head, barrier->tail, waiting);
171
172 GNUNET_free(waiting);
173}
diff --git a/src/messenger/testing_messenger_barrier.h b/src/messenger/testing_messenger_barrier.h
deleted file mode 100644
index 5ea0fe137..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 cb_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 cb_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 65cf12e73..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 "platform.h"
27#include "testing_messenger_setup.h"
28
29#include <stdio.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_ */