aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_member.c
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2020-11-01 22:57:28 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2021-03-06 01:30:37 +0100
commit2925310d67483aca6e055e1ce0593c6463cd6c72 (patch)
tree2cc8aacafc25563cdccde2eee9a90f9ca257d405 /src/messenger/gnunet-service-messenger_member.c
parent82b864a64679b0a735201724907cdf2b7e4e16c3 (diff)
downloadgnunet-2925310d67483aca6e055e1ce0593c6463cd6c72.tar.gz
gnunet-2925310d67483aca6e055e1ce0593c6463cd6c72.zip
-added core functionality of the messenger service
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> formatting messenger code Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -completed core functionality of messenger service Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -code cleanup and reuse Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> +added structure to memberships of rooms Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented member permission checks and deletion of messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -moved solving requests out of updating last messages (also forward before update) Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -reduced complexity of permisson check and changed load/save of rooms Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added save/load for accessed keys and basement peers of a room Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented save/load for members with their history and session Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -abstracted management of egos and contacts Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fix warning Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -abstracted management of members Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed and adjusted test case Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -separated handling of direct and anonymous contacts Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -messenger added member-sessions which fix multiple edge cases, also additional cleanup Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -updated docs and fixed memory leak Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -changed info messages and added protocol version exchange Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adjusted client api to use contacts from sessions Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added more logging and fixed wrong session usage Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adjusted comm0 test case and removed adding members from checking messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed test-case for peer exchange Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -getting multiple peers connected in test-case with cadet Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed wrong assert and added tunnel version check -simplified handling and forwarding Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed merging last messages and cycling info messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -automated adding sessions and members Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -corrected use of identity keys and signatures Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adding local joining on entering external room Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed test-case comm0 Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added more test-cases with generic setup Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed multiple simultaneous channels blocking each other Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -making test-cases more precise Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added check of members in test-cases, reduced merge messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -unified delayed operations: requests, deletions and merges Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -finished handling of operations Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed member session historystorage, added request permission check and padding for transmission Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -improved padding and removed automatic recursive requests Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented filter for sending messages and added private messages to API level Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -wrong setups fixed with proper ego lookups Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed problem with anonymous ego and changed to discrete-level padding Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added links to replace deleted messages, added local deletion and fixed anonymous id changing Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added session completion and removal through completion process Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src/messenger/gnunet-service-messenger_member.c')
-rw-r--r--src/messenger/gnunet-service-messenger_member.c379
1 files changed, 379 insertions, 0 deletions
diff --git a/src/messenger/gnunet-service-messenger_member.c b/src/messenger/gnunet-service-messenger_member.c
new file mode 100644
index 000000000..6e39cec13
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member.c
@@ -0,0 +1,379 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member.h"
27
28#include "gnunet-service-messenger_member_session.h"
29
30struct GNUNET_MESSENGER_Member*
31create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
32{
33 GNUNET_assert (store);
34
35 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
36
37 member->store = store;
38
39 if (id)
40 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
41 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
42 {
43 GNUNET_free (member);
44 return NULL;
45 }
46
47 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
48
49 return member;
50}
51
52static int
53iterate_destroy_session (void *cls, const struct GNUNET_HashCode *key, void *value)
54{
55 struct GNUNET_MESSENGER_MemberSession *session = value;
56 destroy_member_session(session);
57 return GNUNET_YES;
58}
59
60void
61destroy_member (struct GNUNET_MESSENGER_Member *member)
62{
63 GNUNET_assert((member) && (member->sessions));
64
65 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
67
68 GNUNET_free (member);
69}
70
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member)
73{
74 GNUNET_assert (member);
75
76 return &(member->id);
77}
78
79static int
80callback_scan_for_sessions (void *cls, const char *filename)
81{
82 struct GNUNET_MESSENGER_Member *member = cls;
83
84 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
85 {
86 char *directory;
87
88 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
89
90 load_member_session(member, directory);
91 }
92
93 return GNUNET_OK;
94}
95
96void
97load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
98{
99 GNUNET_assert ((store) && (directory));
100
101 char *config_file;
102 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
103
104 struct GNUNET_MESSENGER_Member *member = NULL;
105
106 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
107 goto free_config;
108
109 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
110
111 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
112 {
113 struct GNUNET_ShortHashCode id;
114
115 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
116 goto destroy_config;
117
118 member = add_store_member(store, &id);
119 }
120
121destroy_config:
122
123 GNUNET_CONFIGURATION_destroy (cfg);
124
125free_config:
126 GNUNET_free(config_file);
127
128 if (!member)
129 return;
130
131 char *scan_dir;
132 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
133
134 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
135 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
136
137 GNUNET_free(scan_dir);
138}
139
140static int
141iterate_load_next_session (void *cls, const struct GNUNET_HashCode *key, void *value)
142{
143 const char* sessions_directory = cls;
144
145 char* load_dir;
146 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
147
148 struct GNUNET_MESSENGER_MemberSession *session = value;
149
150 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
151 load_member_session_next (session, load_dir);
152
153 GNUNET_free (load_dir);
154 return GNUNET_YES;
155}
156
157void
158load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory)
159{
160 GNUNET_assert ((member) && (directory));
161
162 char* load_dir;
163 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
164
165 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
166
167 GNUNET_free(load_dir);
168}
169
170static int
171iterate_save_session (void *cls, const struct GNUNET_HashCode *key, void *value)
172{
173 const char* sessions_directory = cls;
174
175 char* save_dir;
176 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
177
178 struct GNUNET_MESSENGER_MemberSession *session = value;
179
180 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
181 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
182 save_member_session (session, save_dir);
183
184 GNUNET_free (save_dir);
185 return GNUNET_YES;
186}
187
188void
189save_member (struct GNUNET_MESSENGER_Member *member, const char *directory)
190{
191 GNUNET_assert ((member) && (directory));
192
193 char *config_file;
194 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
195
196 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
197
198 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
199
200 if (id_data)
201 {
202 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
203
204 GNUNET_free(id_data);
205 }
206
207 GNUNET_CONFIGURATION_write (cfg, config_file);
208 GNUNET_CONFIGURATION_destroy (cfg);
209
210 GNUNET_free(config_file);
211
212 char* save_dir;
213 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
214
215 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
216 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
217 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
218
219 GNUNET_free(save_dir);
220}
221
222static void
223sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
224{
225 GNUNET_assert((session) && (next));
226
227 if (session == next)
228 return;
229
230 if (next->next)
231 sync_session_contact_from_next (session, next->next);
232 else
233 session->contact = next->contact;
234}
235
236static int
237iterate_sync_session_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
238{
239 struct GNUNET_MESSENGER_MemberSession *session = value;
240
241 if (session->next)
242 sync_session_contact_from_next (session, session->next);
243
244 return GNUNET_YES;
245}
246
247void
248sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
249{
250 GNUNET_assert ((member) && (member->sessions));
251
252 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
253}
254
255struct GNUNET_MESSENGER_MemberSession*
256get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
257{
258 GNUNET_assert ((member) && (public_key));
259
260 struct GNUNET_HashCode hash;
261 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
262
263 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
264}
265
266struct GNUNET_MESSENGER_ClosureSearchSession {
267 const struct GNUNET_MESSENGER_Message *message;
268 const struct GNUNET_HashCode *hash;
269
270 struct GNUNET_MESSENGER_MemberSession *match;
271};
272
273static int
274iterate_search_session (void *cls, const struct GNUNET_HashCode *key, void *value)
275{
276 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
277 struct GNUNET_MESSENGER_MemberSession *session = value;
278
279 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
280 return GNUNET_YES;
281
282 search->match = session;
283 return GNUNET_NO;
284}
285
286static struct GNUNET_MESSENGER_MemberSession*
287try_member_session (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
288{
289 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
290
291 if (session)
292 return session;
293
294 session = create_member_session(member, public_key);
295
296 if (session)
297 add_member_session(member, session);
298
299 return session;
300}
301
302struct GNUNET_MESSENGER_MemberSession*
303get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
304 const struct GNUNET_HashCode *hash)
305{
306 GNUNET_assert ((member) && (message) && (hash) &&
307 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
308
309 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
310 return try_member_session(member, &(message->body.info.host_key));
311 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
312 return try_member_session(member, &(message->body.join.key));
313
314 struct GNUNET_MESSENGER_ClosureSearchSession search;
315
316 search.message = message;
317 search.hash = hash;
318
319 search.match = NULL;
320 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
321
322 return search.match;
323}
324
325void
326add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
327{
328 if (!session)
329 return;
330
331 GNUNET_assert((member) && (session->member == member));
332
333 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
334
335 struct GNUNET_HashCode hash;
336 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
337
338 GNUNET_CONTAINER_multihashmap_put(member->sessions, &hash, session, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
339}
340
341void
342remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
343{
344 GNUNET_assert ((member) && (session) && (session->member == member));
345
346 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
347
348 struct GNUNET_HashCode hash;
349 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
350
351 GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session);
352}
353
354struct GNUNET_MESSENGER_ClosureIterateSessions {
355 GNUNET_MESSENGER_MemberIteratorCallback it;
356 void *cls;
357};
358
359static int
360iterate_member_sessions_it (void *cls, const struct GNUNET_HashCode *key, void *value)
361{
362 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
363 struct GNUNET_MESSENGER_MemberSession *session = value;
364
365 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
366}
367
368int
369iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
370{
371 GNUNET_assert ((member) && (member->sessions) && (it));
372
373 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
374
375 iterate.it = it;
376 iterate.cls = cls;
377
378 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
379}