aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_member.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_member.c')
-rw-r--r--src/messenger/gnunet-service-messenger_member.c386
1 files changed, 0 insertions, 386 deletions
diff --git a/src/messenger/gnunet-service-messenger_member.c b/src/messenger/gnunet-service-messenger_member.c
deleted file mode 100644
index b0a735dbe..000000000
--- a/src/messenger/gnunet-service-messenger_member.c
+++ /dev/null
@@ -1,386 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2021 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @author Tobias Frisch
22 * @file src/messenger/gnunet-service-messenger_member.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member.h"
27
28#include "gnunet-service-messenger_member_session.h"
29
30struct GNUNET_MESSENGER_Member*
31create_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
32{
33 GNUNET_assert (store);
34
35 struct GNUNET_MESSENGER_Member *member = GNUNET_new(struct GNUNET_MESSENGER_Member);
36
37 member->store = store;
38
39 if (id)
40 GNUNET_memcpy(&(member->id), id, sizeof(member->id));
41 else if (GNUNET_YES != generate_free_member_id(&(member->id), store->members))
42 {
43 GNUNET_free (member);
44 return NULL;
45 }
46
47 member->sessions = GNUNET_CONTAINER_multihashmap_create(2, GNUNET_NO);
48
49 return member;
50}
51
52static int
53iterate_destroy_session (void *cls, const struct GNUNET_HashCode *key, void *value)
54{
55 struct GNUNET_MESSENGER_MemberSession *session = value;
56 destroy_member_session(session);
57 return GNUNET_YES;
58}
59
60void
61destroy_member (struct GNUNET_MESSENGER_Member *member)
62{
63 GNUNET_assert((member) && (member->sessions));
64
65 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_destroy_session, NULL);
66 GNUNET_CONTAINER_multihashmap_destroy (member->sessions);
67
68 GNUNET_free (member);
69}
70
71const struct GNUNET_ShortHashCode*
72get_member_id (const struct GNUNET_MESSENGER_Member *member)
73{
74 GNUNET_assert (member);
75
76 return &(member->id);
77}
78
79static int
80callback_scan_for_sessions (void *cls, const char *filename)
81{
82 struct GNUNET_MESSENGER_Member *member = cls;
83
84 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
85 {
86 char *directory;
87
88 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
89
90 load_member_session(member, directory);
91 GNUNET_free (directory);
92 }
93
94 return GNUNET_OK;
95}
96
97void
98load_member (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
99{
100 GNUNET_assert ((store) && (directory));
101
102 char *config_file;
103 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
104
105 struct GNUNET_MESSENGER_Member *member = NULL;
106
107 if (GNUNET_YES != GNUNET_DISK_file_test (config_file))
108 goto free_config;
109
110 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
111
112 if (GNUNET_OK == GNUNET_CONFIGURATION_parse (cfg, config_file))
113 {
114 struct GNUNET_ShortHashCode id;
115
116 if (GNUNET_OK != GNUNET_CONFIGURATION_get_data (cfg, "member", "id", &id, sizeof(id)))
117 goto destroy_config;
118
119 member = add_store_member(store, &id);
120 }
121
122destroy_config:
123
124 GNUNET_CONFIGURATION_destroy (cfg);
125
126free_config:
127 GNUNET_free(config_file);
128
129 if (!member)
130 return;
131
132 char *scan_dir;
133 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
134
135 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
136 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_sessions, member);
137
138 GNUNET_free(scan_dir);
139}
140
141static int
142iterate_load_next_session (void *cls, const struct GNUNET_HashCode *key, void *value)
143{
144 const char* sessions_directory = cls;
145
146 char* load_dir;
147 GNUNET_asprintf (&load_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
148
149 struct GNUNET_MESSENGER_MemberSession *session = value;
150
151 if (GNUNET_YES == GNUNET_DISK_directory_test (load_dir, GNUNET_YES))
152 load_member_session_next (session, load_dir);
153
154 GNUNET_free (load_dir);
155 return GNUNET_YES;
156}
157
158void
159load_member_next_sessions (const struct GNUNET_MESSENGER_Member *member, const char *directory)
160{
161 GNUNET_assert ((member) && (directory));
162
163 char* load_dir;
164 GNUNET_asprintf (&load_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
165
166 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_load_next_session, load_dir);
167
168 GNUNET_free(load_dir);
169}
170
171static int
172iterate_save_session (void *cls, const struct GNUNET_HashCode *key, void *value)
173{
174 const char* sessions_directory = cls;
175
176 char* save_dir;
177 GNUNET_asprintf (&save_dir, "%s%s%c", sessions_directory, GNUNET_h2s(key), DIR_SEPARATOR);
178
179 struct GNUNET_MESSENGER_MemberSession *session = value;
180
181 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
182 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
183 save_member_session (session, save_dir);
184
185 GNUNET_free (save_dir);
186 return GNUNET_YES;
187}
188
189void
190save_member (struct GNUNET_MESSENGER_Member *member, const char *directory)
191{
192 GNUNET_assert ((member) && (directory));
193
194 char *config_file;
195 GNUNET_asprintf (&config_file, "%s%s", directory, "member.cfg");
196
197 struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
198
199 char *id_data = GNUNET_STRINGS_data_to_string_alloc (&(member->id), sizeof(member->id));
200
201 if (id_data)
202 {
203 GNUNET_CONFIGURATION_set_value_string (cfg, "member", "id", id_data);
204
205 GNUNET_free(id_data);
206 }
207
208 GNUNET_CONFIGURATION_write (cfg, config_file);
209 GNUNET_CONFIGURATION_destroy (cfg);
210
211 GNUNET_free(config_file);
212
213 char* save_dir;
214 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "sessions", DIR_SEPARATOR);
215
216 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
217 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
218 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_save_session, save_dir);
219
220 GNUNET_free(save_dir);
221}
222
223static void
224sync_session_contact_from_next (struct GNUNET_MESSENGER_MemberSession *session, struct GNUNET_MESSENGER_MemberSession *next)
225{
226 GNUNET_assert((session) && (next));
227
228 if (session == next)
229 return;
230
231 if (next->next)
232 sync_session_contact_from_next (session, next->next);
233 else
234 session->contact = next->contact;
235}
236
237static int
238iterate_sync_session_contact (void *cls, const struct GNUNET_HashCode *key, void *value)
239{
240 struct GNUNET_MESSENGER_MemberSession *session = value;
241
242 if (session->next)
243 sync_session_contact_from_next (session, session->next);
244
245 return GNUNET_YES;
246}
247
248void
249sync_member_contacts (struct GNUNET_MESSENGER_Member *member)
250{
251 GNUNET_assert ((member) && (member->sessions));
252
253 GNUNET_CONTAINER_multihashmap_iterate (member->sessions, iterate_sync_session_contact, NULL);
254}
255
256struct GNUNET_MESSENGER_MemberSession*
257get_member_session (const struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
258{
259 GNUNET_assert ((member) && (public_key));
260
261 struct GNUNET_HashCode hash;
262 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
263
264 return GNUNET_CONTAINER_multihashmap_get(member->sessions, &hash);
265}
266
267struct GNUNET_MESSENGER_ClosureSearchSession {
268 const struct GNUNET_MESSENGER_Message *message;
269 const struct GNUNET_HashCode *hash;
270
271 struct GNUNET_MESSENGER_MemberSession *match;
272};
273
274static int
275iterate_search_session (void *cls, const struct GNUNET_HashCode *key, void *value)
276{
277 struct GNUNET_MESSENGER_ClosureSearchSession* search = cls;
278 struct GNUNET_MESSENGER_MemberSession *session = value;
279
280 if (GNUNET_OK != verify_member_session_as_sender(session, search->message, search->hash))
281 return GNUNET_YES;
282
283 search->match = session;
284 return GNUNET_NO;
285}
286
287static struct GNUNET_MESSENGER_MemberSession*
288try_member_session (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_IDENTITY_PublicKey *public_key)
289{
290 struct GNUNET_MESSENGER_MemberSession* session = get_member_session(member, public_key);
291
292 if (session)
293 return session;
294
295 session = create_member_session(member, public_key);
296
297 if (session)
298 add_member_session(member, session);
299
300 return session;
301}
302
303struct GNUNET_MESSENGER_MemberSession*
304get_member_session_of (struct GNUNET_MESSENGER_Member *member, const struct GNUNET_MESSENGER_Message *message,
305 const struct GNUNET_HashCode *hash)
306{
307 GNUNET_assert ((member) && (message) && (hash) &&
308 (0 == GNUNET_memcmp(&(member->id), &(message->header.sender_id))));
309
310 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
311 return try_member_session(member, &(message->body.info.host_key));
312 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
313 return try_member_session(member, &(message->body.join.key));
314
315 struct GNUNET_MESSENGER_ClosureSearchSession search;
316
317 search.message = message;
318 search.hash = hash;
319
320 search.match = NULL;
321 GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_search_session, &search);
322
323 return search.match;
324}
325
326void
327add_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
328{
329 if (!session)
330 return;
331
332 GNUNET_assert((member) && (session->member == member));
333
334 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
335
336 struct GNUNET_HashCode hash;
337 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
338
339 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(
340 member->sessions, &hash, session,
341 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
342 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Adding a member session failed: %s\n",
343 GNUNET_h2s(&hash));
344}
345
346void
347remove_member_session (struct GNUNET_MESSENGER_Member *member, struct GNUNET_MESSENGER_MemberSession *session)
348{
349 GNUNET_assert ((member) && (session) && (session->member == member));
350
351 const struct GNUNET_IDENTITY_PublicKey *public_key = get_member_session_public_key(session);
352
353 struct GNUNET_HashCode hash;
354 GNUNET_CRYPTO_hash(public_key, sizeof(*public_key), &hash);
355
356 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(member->sessions, &hash, session))
357 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Removing a member session failed: %s\n",
358 GNUNET_h2s(&hash));
359}
360
361struct GNUNET_MESSENGER_ClosureIterateSessions {
362 GNUNET_MESSENGER_MemberIteratorCallback it;
363 void *cls;
364};
365
366static int
367iterate_member_sessions_it (void *cls, const struct GNUNET_HashCode *key, void *value)
368{
369 struct GNUNET_MESSENGER_ClosureIterateSessions *iterate = cls;
370 struct GNUNET_MESSENGER_MemberSession *session = value;
371
372 return iterate->it (iterate->cls, get_member_session_public_key(session), session);
373}
374
375int
376iterate_member_sessions (struct GNUNET_MESSENGER_Member *member, GNUNET_MESSENGER_MemberIteratorCallback it, void *cls)
377{
378 GNUNET_assert ((member) && (member->sessions) && (it));
379
380 struct GNUNET_MESSENGER_ClosureIterateSessions iterate;
381
382 iterate.it = it;
383 iterate.cls = cls;
384
385 return GNUNET_CONTAINER_multihashmap_iterate(member->sessions, iterate_member_sessions_it, &iterate);
386}