aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/gnunet-service-messenger_member_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_member_store.c')
-rw-r--r--src/service/messenger/gnunet-service-messenger_member_store.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/service/messenger/gnunet-service-messenger_member_store.c b/src/service/messenger/gnunet-service-messenger_member_store.c
new file mode 100644
index 000000000..e7876b382
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_member_store.c
@@ -0,0 +1,301 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2023 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
43
44static int
45iterate_destroy_members (void *cls,
46 const struct GNUNET_ShortHashCode *key,
47 void *value)
48{
49 struct GNUNET_MESSENGER_Member *member = value;
50 destroy_member (member);
51 return GNUNET_YES;
52}
53
54
55void
56clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
57{
58 GNUNET_assert ((store) && (store->members));
59
60 GNUNET_CONTAINER_multishortmap_iterate (store->members,
61 iterate_destroy_members, NULL);
62 GNUNET_CONTAINER_multishortmap_destroy (store->members);
63}
64
65
66struct GNUNET_MESSENGER_ContactStore*
67get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
68{
69 GNUNET_assert ((store) && (store->room));
70
71 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
72
73 return get_service_contact_store (room->service);
74}
75
76
77const struct GNUNET_HashCode*
78get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
79{
80 GNUNET_assert (store);
81
82 return get_srv_room_key ((const struct
83 GNUNET_MESSENGER_SrvRoom*) store->room);
84}
85
86
87static int
88callback_scan_for_members (void *cls,
89 const char *filename)
90{
91 struct GNUNET_MESSENGER_MemberStore *store = cls;
92
93 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
94 {
95 char *directory;
96
97 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
98
99 load_member (store, directory);
100
101 GNUNET_free (directory);
102 }
103
104 return GNUNET_OK;
105}
106
107
108static int
109iterate_load_next_member_sessions (void *cls,
110 const struct GNUNET_ShortHashCode *id,
111 void *value)
112{
113 const char *sync_dir = cls;
114
115 struct GNUNET_MESSENGER_Member *member = value;
116
117 if (! member)
118 return GNUNET_YES;
119
120 char *member_dir;
121 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s (id),
122 DIR_SEPARATOR);
123
124 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
125 load_member_next_sessions (member, member_dir);
126
127 GNUNET_free (member_dir);
128 return GNUNET_YES;
129}
130
131
132static int
133iterate_sync_member_contacts (void *cls,
134 const struct GNUNET_ShortHashCode *id,
135 void *value)
136{
137 struct GNUNET_MESSENGER_Member *member = value;
138
139 if (! member)
140 return GNUNET_YES;
141
142 sync_member_contacts (member);
143 return GNUNET_YES;
144}
145
146
147void
148load_member_store (struct GNUNET_MESSENGER_MemberStore *store,
149 const char *directory)
150{
151 GNUNET_assert ((store) && (directory));
152
153 char *scan_dir;
154 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
155
156 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
157 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
158
159 GNUNET_CONTAINER_multishortmap_iterate (store->members,
160 iterate_load_next_member_sessions,
161 scan_dir);
162 GNUNET_CONTAINER_multishortmap_iterate (store->members,
163 iterate_sync_member_contacts, NULL);
164
165 GNUNET_free (scan_dir);
166}
167
168
169static int
170iterate_save_members (void *cls,
171 const struct GNUNET_ShortHashCode *id,
172 void *value)
173{
174 const char *save_dir = cls;
175
176 struct GNUNET_MESSENGER_Member *member = value;
177
178 if (! member)
179 return GNUNET_YES;
180
181 char *member_dir;
182 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s (id),
183 DIR_SEPARATOR);
184
185 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
186 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
187 save_member (member, member_dir);
188
189 GNUNET_free (member_dir);
190 return GNUNET_YES;
191}
192
193
194void
195save_member_store (struct GNUNET_MESSENGER_MemberStore *store,
196 const char *directory)
197{
198 GNUNET_assert ((store) && (directory));
199
200 char *save_dir;
201 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
202
203 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
204 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
205 GNUNET_CONTAINER_multishortmap_iterate (store->members,
206 iterate_save_members, save_dir);
207
208 GNUNET_free (save_dir);
209}
210
211
212struct GNUNET_MESSENGER_Member*
213get_store_member (const struct GNUNET_MESSENGER_MemberStore *store,
214 const struct GNUNET_ShortHashCode *id)
215{
216 GNUNET_assert ((store) && (store->members) && (id));
217
218 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
219}
220
221
222struct GNUNET_MESSENGER_Member*
223get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
224 const struct GNUNET_MESSENGER_Message *message)
225{
226 GNUNET_assert ((store) && (message));
227
228 if (GNUNET_YES == is_peer_message (message))
229 return NULL;
230
231 if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
232 return add_store_member (store, &(message->header.sender_id));
233 else
234 return get_store_member (store, &(message->header.sender_id));
235}
236
237
238struct GNUNET_MESSENGER_Member*
239add_store_member (struct GNUNET_MESSENGER_MemberStore *store,
240 const struct GNUNET_ShortHashCode *id)
241{
242 GNUNET_assert ((store) && (store->members));
243
244 struct GNUNET_MESSENGER_Member *member = id? get_store_member (store, id) :
245 NULL;
246
247 if (member)
248 return member;
249
250 member = create_member (store, id);
251
252 if (! member)
253 return NULL;
254
255 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members,
256 get_member_id (member),
257 member,
258 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
259 {
260 destroy_member (member);
261 return NULL;
262 }
263
264 return member;
265}
266
267
268struct GNUNET_MESSENGER_ClosureIterateMembers
269{
270 GNUNET_MESSENGER_MemberIteratorCallback it;
271 void *cls;
272};
273
274static int
275iterate_store_members_it (void *cls,
276 const struct GNUNET_ShortHashCode *key,
277 void *value)
278{
279 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
280 struct GNUNET_MESSENGER_Member *member = value;
281
282 return iterate_member_sessions (member, iterate->it, iterate->cls);
283}
284
285
286int
287iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store,
288 GNUNET_MESSENGER_MemberIteratorCallback it,
289 void *cls)
290{
291 GNUNET_assert ((store) && (store->members) && (it));
292
293 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
294
295 iterate.it = it;
296 iterate.cls = cls;
297
298 return GNUNET_CONTAINER_multishortmap_iterate (store->members,
299 iterate_store_members_it,
300 &iterate);
301}