aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_member_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_member_store.c')
-rw-r--r--src/messenger/gnunet-service-messenger_member_store.c250
1 files changed, 250 insertions, 0 deletions
diff --git a/src/messenger/gnunet-service-messenger_member_store.c b/src/messenger/gnunet-service-messenger_member_store.c
new file mode 100644
index 000000000..2925965d4
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_member_store.c
@@ -0,0 +1,250 @@
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.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_member_store.h"
27
28#include "gnunet-service-messenger_member.h"
29#include "gnunet-service-messenger_service.h"
30#include "gnunet-service-messenger_room.h"
31
32void
33init_member_store (struct GNUNET_MESSENGER_MemberStore *store, struct GNUNET_MESSENGER_SrvRoom *room)
34{
35 GNUNET_assert ((store) && (room));
36
37 store->room = room;
38 store->members = GNUNET_CONTAINER_multishortmap_create(8, GNUNET_NO);
39}
40
41static int
42iterate_destroy_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
43{
44 struct GNUNET_MESSENGER_Member *member = value;
45 destroy_member(member);
46 return GNUNET_YES;
47}
48
49void
50clear_member_store (struct GNUNET_MESSENGER_MemberStore *store)
51{
52 GNUNET_assert ((store) && (store->members));
53
54 GNUNET_CONTAINER_multishortmap_iterate (store->members, iterate_destroy_members, NULL);
55 GNUNET_CONTAINER_multishortmap_destroy (store->members);
56}
57
58
59struct GNUNET_MESSENGER_ContactStore*
60get_member_contact_store (struct GNUNET_MESSENGER_MemberStore *store)
61{
62 GNUNET_assert ((store) && (store->room));
63
64 struct GNUNET_MESSENGER_SrvRoom *room = store->room;
65
66 return get_service_contact_store(room->service);
67}
68
69const struct GNUNET_HashCode*
70get_member_store_key (const struct GNUNET_MESSENGER_MemberStore *store)
71{
72 GNUNET_assert (store);
73
74 return get_room_key((const struct GNUNET_MESSENGER_SrvRoom*) store->room);
75}
76
77static int
78callback_scan_for_members (void *cls, const char *filename)
79{
80 struct GNUNET_MESSENGER_MemberStore *store = cls;
81
82 if (GNUNET_YES == GNUNET_DISK_directory_test (filename, GNUNET_YES))
83 {
84 char *directory;
85
86 GNUNET_asprintf (&directory, "%s%c", filename, DIR_SEPARATOR);
87
88 load_member(store, directory);
89
90 GNUNET_free(directory);
91 }
92
93 return GNUNET_OK;
94}
95
96static int
97iterate_load_next_member_sessions (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
98{
99 const char *sync_dir = cls;
100
101 struct GNUNET_MESSENGER_Member *member = value;
102
103 if (!member)
104 return GNUNET_YES;
105
106 char *member_dir;
107 GNUNET_asprintf (&member_dir, "%s%s%c", sync_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
108
109 if (GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_YES))
110 load_member_next_sessions (member, member_dir);
111
112 GNUNET_free(member_dir);
113 return GNUNET_YES;
114}
115
116static int
117iterate_sync_member_contacts (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
118{
119 struct GNUNET_MESSENGER_Member *member = value;
120
121 if (!member)
122 return GNUNET_YES;
123
124 sync_member_contacts (member);
125 return GNUNET_YES;
126}
127
128void
129load_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
130{
131 GNUNET_assert ((store) && (directory));
132
133 char *scan_dir;
134 GNUNET_asprintf (&scan_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
135
136 if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
137 GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_members, store);
138
139 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_load_next_member_sessions, scan_dir);
140 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_sync_member_contacts, NULL);
141
142 GNUNET_free(scan_dir);
143}
144
145static int
146iterate_save_members (void *cls, const struct GNUNET_ShortHashCode *id, void *value)
147{
148 const char *save_dir = cls;
149
150 struct GNUNET_MESSENGER_Member *member = value;
151
152 if (!member)
153 return GNUNET_YES;
154
155 char *member_dir;
156 GNUNET_asprintf (&member_dir, "%s%s%c", save_dir, GNUNET_sh2s(id), DIR_SEPARATOR);
157
158 if ((GNUNET_YES == GNUNET_DISK_directory_test (member_dir, GNUNET_NO)) ||
159 (GNUNET_OK == GNUNET_DISK_directory_create (member_dir)))
160 save_member(member, member_dir);
161
162 GNUNET_free(member_dir);
163 return GNUNET_YES;
164}
165
166void
167save_member_store (struct GNUNET_MESSENGER_MemberStore *store, const char *directory)
168{
169 GNUNET_assert ((store) && (directory));
170
171 char* save_dir;
172 GNUNET_asprintf (&save_dir, "%s%s%c", directory, "members", DIR_SEPARATOR);
173
174 if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
175 (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
176 GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_save_members, save_dir);
177
178 GNUNET_free(save_dir);
179}
180
181struct GNUNET_MESSENGER_Member*
182get_store_member (const struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
183{
184 GNUNET_assert ((store) && (store->members) && (id));
185
186 return GNUNET_CONTAINER_multishortmap_get (store->members, id);
187}
188
189struct GNUNET_MESSENGER_Member*
190get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_MESSENGER_Message *message)
191{
192 if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
193 (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
194 return add_store_member(store, &(message->header.sender_id));
195 else
196 return get_store_member(store, &(message->header.sender_id));
197}
198
199struct GNUNET_MESSENGER_Member*
200add_store_member (struct GNUNET_MESSENGER_MemberStore *store, const struct GNUNET_ShortHashCode *id)
201{
202 GNUNET_assert ((store) && (store->members));
203
204 struct GNUNET_MESSENGER_Member *member = id? get_store_member(store, id) : NULL;
205
206 if (member)
207 return member;
208
209 member = create_member(store, id);
210
211 if (!member)
212 return NULL;
213
214 if (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put (store->members, get_member_id(member), member,
215 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
216 {
217 destroy_member(member);
218 return NULL;
219 }
220
221 return member;
222}
223
224struct GNUNET_MESSENGER_ClosureIterateMembers {
225 GNUNET_MESSENGER_MemberIteratorCallback it;
226 void *cls;
227};
228
229static int
230iterate_store_members_it (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
231{
232 struct GNUNET_MESSENGER_ClosureIterateMembers *iterate = cls;
233 struct GNUNET_MESSENGER_Member *member = value;
234
235 return iterate_member_sessions(member, iterate->it, iterate->cls);
236}
237
238int
239iterate_store_members (struct GNUNET_MESSENGER_MemberStore *store, GNUNET_MESSENGER_MemberIteratorCallback it,
240 void* cls)
241{
242 GNUNET_assert ((store) && (store->members) && (it));
243
244 struct GNUNET_MESSENGER_ClosureIterateMembers iterate;
245
246 iterate.it = it;
247 iterate.cls = cls;
248
249 return GNUNET_CONTAINER_multishortmap_iterate(store->members, iterate_store_members_it, &iterate);
250}