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.c269
1 files changed, 269 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..fc28babc4
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_member_store.c
@@ -0,0 +1,269 @@
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}