aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_ego_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_ego_store.c')
-rw-r--r--src/messenger/gnunet-service-messenger_ego_store.c295
1 files changed, 295 insertions, 0 deletions
diff --git a/src/messenger/gnunet-service-messenger_ego_store.c b/src/messenger/gnunet-service-messenger_ego_store.c
new file mode 100644
index 000000000..3b069fcf5
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_ego_store.c
@@ -0,0 +1,295 @@
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_ego_store.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_ego_store.h"
27
28#include "gnunet-service-messenger_handle.h"
29
30static void
31callback_update_ego (void *cls, struct GNUNET_IDENTITY_Ego *ego, void **ctx, const char *identifier)
32{
33 if ((!ego) || (!identifier))
34 return;
35
36 struct GNUNET_MESSENGER_EgoStore *store = cls;
37
38 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "New ego in use: '%s'\n", identifier);
39
40 update_store_ego (store, identifier, GNUNET_IDENTITY_ego_get_private_key (ego));
41}
42
43void
44init_ego_store(struct GNUNET_MESSENGER_EgoStore *store, const struct GNUNET_CONFIGURATION_Handle *config)
45{
46 GNUNET_assert ((store) && (config));
47
48 store->cfg = config;
49 store->identity = GNUNET_IDENTITY_connect (config, &callback_update_ego, store);
50 store->egos = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
51
52 store->lu_start = NULL;
53 store->lu_end = NULL;
54
55 store->op_start = NULL;
56 store->op_end = NULL;
57}
58
59
60static int
61iterate_destroy_egos (void *cls, const struct GNUNET_HashCode *key, void *value)
62{
63 struct GNUNET_MESSENGER_Ego *ego = value;
64 GNUNET_free(ego);
65 return GNUNET_YES;
66}
67
68void
69clear_ego_store(struct GNUNET_MESSENGER_EgoStore *store)
70{
71 GNUNET_assert (store);
72
73 struct GNUNET_MESSENGER_EgoOperation *op;
74
75 while (store->op_start)
76 {
77 op = store->op_start;
78
79 GNUNET_IDENTITY_cancel (op->operation);
80 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, op);
81
82 if (op->identifier)
83 GNUNET_free (op->identifier);
84
85 GNUNET_free (op);
86 }
87
88 struct GNUNET_MESSENGER_EgoLookup *lu;
89
90 while (store->lu_start)
91 {
92 lu = store->lu_start;
93
94 GNUNET_IDENTITY_ego_lookup_cancel(lu->lookup);
95 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, lu);
96
97 if (lu->identifier)
98 GNUNET_free(lu->identifier);
99
100 GNUNET_free (lu);
101 }
102
103 GNUNET_CONTAINER_multihashmap_iterate (store->egos, iterate_destroy_egos, NULL);
104 GNUNET_CONTAINER_multihashmap_destroy (store->egos);
105
106 if (store->identity)
107 {
108 GNUNET_IDENTITY_disconnect (store->identity);
109
110 store->identity = NULL;
111 }
112}
113
114static void
115callback_ego_create (void *cls, const struct GNUNET_IDENTITY_PrivateKey *key, const char *emsg)
116{
117 struct GNUNET_MESSENGER_EgoOperation *element = cls;
118 struct GNUNET_MESSENGER_EgoStore *store = element->store;
119
120 GNUNET_assert(element->identifier);
121
122 if (emsg)
123 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
124
125 if (key)
126 {
127 struct GNUNET_MESSENGER_SrvHandle *handle = element->handle;
128
129 struct GNUNET_MESSENGER_Ego *msg_ego = update_store_ego (store, element->identifier, key);
130
131 set_handle_ego (handle, msg_ego);
132 }
133 else
134 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Creating ego failed!\n");
135
136 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
137 GNUNET_free (element->identifier);
138 GNUNET_free (element);
139}
140
141void
142create_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
143 void *handle)
144{
145 GNUNET_assert ((store) && (identifier));
146
147 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
148
149 element->store = store;
150 element->handle = handle;
151
152 element->identifier = GNUNET_strdup (identifier);
153
154 element->operation = GNUNET_IDENTITY_create (store->identity, identifier, NULL,
155 GNUNET_IDENTITY_TYPE_ECDSA, callback_ego_create, element);
156
157 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
158}
159
160static void
161callback_ego_lookup (void *cls, struct GNUNET_IDENTITY_Ego *ego)
162{
163 struct GNUNET_MESSENGER_EgoLookup *element = cls;
164 struct GNUNET_MESSENGER_EgoStore *store = element->store;
165
166 GNUNET_assert(element->identifier);
167
168 struct GNUNET_MESSENGER_Ego *msg_ego;
169
170 if (ego)
171 msg_ego = update_store_ego (
172 store, element->identifier, GNUNET_IDENTITY_ego_get_private_key(ego)
173 );
174 else
175 msg_ego = NULL;
176
177 if (element->cb)
178 element->cb(element->cls, element->identifier, msg_ego);
179
180 GNUNET_CONTAINER_DLL_remove (store->lu_start, store->lu_end, element);
181 GNUNET_free (element->identifier);
182 GNUNET_free (element);
183}
184
185void
186lookup_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
187 GNUNET_MESSENGER_EgoLookupCallback lookup, void *cls)
188{
189 GNUNET_assert (store);
190
191 if (!identifier)
192 {
193 lookup(cls, identifier, NULL);
194 return;
195 }
196
197 struct GNUNET_HashCode hash;
198 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
199
200 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
201
202 if (ego)
203 lookup(cls, identifier, ego);
204 else
205 {
206 struct GNUNET_MESSENGER_EgoLookup *element = GNUNET_new (struct GNUNET_MESSENGER_EgoLookup);
207
208 element->store = store;
209
210 element->cb = lookup;
211 element->cls = cls;
212
213 element->identifier = GNUNET_strdup (identifier);
214
215 element->lookup = GNUNET_IDENTITY_ego_lookup(store->cfg, identifier, callback_ego_lookup, element);
216
217 GNUNET_CONTAINER_DLL_insert (store->lu_start, store->lu_end, element);
218 }
219}
220
221struct GNUNET_MESSENGER_Ego*
222update_store_ego(struct GNUNET_MESSENGER_EgoStore *store, const char *identifier,
223 const struct GNUNET_IDENTITY_PrivateKey *key)
224{
225 GNUNET_assert ((store) && (identifier) && (key));
226
227 struct GNUNET_HashCode hash;
228 GNUNET_CRYPTO_hash (identifier, strlen (identifier), &hash);
229
230 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
231
232 if (!ego)
233 {
234 ego = GNUNET_new(struct GNUNET_MESSENGER_Ego);
235 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
236 }
237
238 GNUNET_memcpy(&(ego->priv), key, sizeof(*key));
239
240 if (GNUNET_OK != GNUNET_IDENTITY_key_get_public (key, &(ego->pub)))
241 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Updating invalid ego key failed!\n");
242
243 return ego;
244}
245
246static void
247callback_ego_rename (void *cls, const char *emsg)
248{
249 struct GNUNET_MESSENGER_EgoOperation *element = cls;
250 struct GNUNET_MESSENGER_EgoStore *store = element->store;
251
252 GNUNET_assert(element->identifier);
253
254 if (emsg)
255 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%s\n", emsg);
256
257 struct GNUNET_HashCode hash;
258 GNUNET_CRYPTO_hash (element->identifier, strlen (element->identifier), &hash);
259
260 struct GNUNET_MESSENGER_Ego *ego = GNUNET_CONTAINER_multihashmap_get (store->egos, &hash);
261
262 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->egos, &hash, ego))
263 {
264 GNUNET_CRYPTO_hash ((char*) element->handle, strlen ((char*) element->handle), &hash);
265
266 GNUNET_CONTAINER_multihashmap_put (store->egos, &hash, ego,
267 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
268 }
269 else
270 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Renaming ego failed!\n");
271
272 GNUNET_free (element->handle);
273
274 GNUNET_CONTAINER_DLL_remove (store->op_start, store->op_end, element);
275 GNUNET_free (element->identifier);
276 GNUNET_free (element);
277}
278
279void
280rename_store_ego (struct GNUNET_MESSENGER_EgoStore *store, const char *old_identifier,
281 const char *new_identifier)
282{
283 GNUNET_assert ((store) && (old_identifier) && (new_identifier));
284
285 struct GNUNET_MESSENGER_EgoOperation *element = GNUNET_new (struct GNUNET_MESSENGER_EgoOperation);
286
287 element->store = store;
288 element->handle = GNUNET_strdup (new_identifier);
289
290 element->identifier = GNUNET_strdup (old_identifier);
291
292 element->operation = GNUNET_IDENTITY_rename (store->identity, old_identifier, new_identifier, callback_ego_rename, element);
293
294 GNUNET_CONTAINER_DLL_insert (store->op_start, store->op_end, element);
295}