aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/messenger_api_contact_store.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/messenger_api_contact_store.c')
-rw-r--r--src/messenger/messenger_api_contact_store.c182
1 files changed, 182 insertions, 0 deletions
diff --git a/src/messenger/messenger_api_contact_store.c b/src/messenger/messenger_api_contact_store.c
new file mode 100644
index 000000000..5238b2c58
--- /dev/null
+++ b/src/messenger/messenger_api_contact_store.c
@@ -0,0 +1,182 @@
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/messenger_api_contact_store.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_contact_store.h"
27
28#include "messenger_api_contact.h"
29#include "messenger_api_util.h"
30
31void
32init_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
33{
34 GNUNET_assert (store);
35
36 store->anonymous = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
37 store->contacts = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38}
39
40static int
41iterate_destroy_contacts (void *cls, const struct GNUNET_HashCode *key, void *value)
42{
43 struct GNUNET_MESSENGER_Contact *contact = value;
44 destroy_contact (contact);
45 return GNUNET_YES;
46}
47
48void
49clear_contact_store (struct GNUNET_MESSENGER_ContactStore *store)
50{
51 GNUNET_assert ((store) && (store->contacts));
52
53 GNUNET_CONTAINER_multihashmap_iterate (store->anonymous, iterate_destroy_contacts, NULL);
54 GNUNET_CONTAINER_multihashmap_iterate (store->contacts, iterate_destroy_contacts, NULL);
55
56 GNUNET_CONTAINER_multihashmap_destroy (store->anonymous);
57 GNUNET_CONTAINER_multihashmap_destroy (store->contacts);
58}
59
60static struct GNUNET_CONTAINER_MultiHashMap*
61select_store_contact_map (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
62 struct GNUNET_HashCode *hash)
63{
64 const struct GNUNET_IDENTITY_PublicKey *anonymous = get_anonymous_public_key ();
65
66 struct GNUNET_HashCode anonHash;
67 GNUNET_CRYPTO_hash (anonymous, sizeof(*anonymous), &anonHash);
68
69 if ((context) && (0 == GNUNET_CRYPTO_hash_cmp(hash, &anonHash)))
70 {
71 GNUNET_memcpy(hash, context, sizeof(*context));
72 return store->anonymous;
73 }
74 else
75 return store->contacts;
76}
77
78struct GNUNET_MESSENGER_Contact*
79get_store_contact_raw (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
80 const struct GNUNET_HashCode *key_hash)
81{
82 GNUNET_assert ((store) && (store->contacts) && (context) && (key_hash));
83
84 struct GNUNET_HashCode hash;
85 GNUNET_memcpy(&hash, key_hash, sizeof(*key_hash));
86
87 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
88 store, context, &hash
89 );
90
91 return GNUNET_CONTAINER_multihashmap_get (map, &hash);
92}
93
94struct GNUNET_MESSENGER_Contact*
95get_store_contact (struct GNUNET_MESSENGER_ContactStore *store, const struct GNUNET_HashCode *context,
96 const struct GNUNET_IDENTITY_PublicKey *pubkey)
97{
98 GNUNET_assert ((store) && (store->contacts) && (context) && (pubkey));
99
100 struct GNUNET_HashCode hash;
101 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
102
103 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
104 store, context, &hash
105 );
106
107 struct GNUNET_MESSENGER_Contact *contact = GNUNET_CONTAINER_multihashmap_get (map, &hash);
108
109 if (contact)
110 {
111 if (0 != GNUNET_memcmp(pubkey, get_contact_key(contact)))
112 {
113 char* str = GNUNET_IDENTITY_public_key_to_string (get_contact_key(contact));
114 GNUNET_log (GNUNET_ERROR_TYPE_INVALID, "Contact in store uses wrong key: %s\n", str);
115 GNUNET_free (str);
116 return NULL;
117 }
118
119 return contact;
120 }
121
122 contact = create_contact (pubkey);
123
124 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
126 return contact;
127
128 destroy_contact (contact);
129 return NULL;
130}
131
132void
133update_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
134 const struct GNUNET_HashCode *context, const struct GNUNET_HashCode *next_context,
135 const struct GNUNET_IDENTITY_PublicKey *pubkey)
136{
137 GNUNET_assert ((store) && (store->contacts) && (contact) && (pubkey));
138
139 const struct GNUNET_IDENTITY_PublicKey* oldkey = get_contact_key (contact);
140
141 struct GNUNET_HashCode hash;
142 GNUNET_CRYPTO_hash (oldkey, sizeof(*oldkey), &hash);
143
144 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
145 store, context, &hash
146 );
147
148 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
149 {
150 GNUNET_memcpy(&(contact->public_key), pubkey, sizeof(*pubkey));
151
152 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
153
154 map = select_store_contact_map (
155 store, next_context, &hash
156 );
157
158 GNUNET_CONTAINER_multihashmap_put (map, &hash, contact,
159 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
160 }
161}
162
163void
164remove_store_contact (struct GNUNET_MESSENGER_ContactStore *store, struct GNUNET_MESSENGER_Contact* contact,
165 const struct GNUNET_HashCode *context)
166{
167 GNUNET_assert ((store) && (store->contacts) && (contact));
168
169 const struct GNUNET_IDENTITY_PublicKey* pubkey = get_contact_key(contact);
170
171 struct GNUNET_HashCode hash;
172 GNUNET_CRYPTO_hash (pubkey, sizeof(*pubkey), &hash);
173
174 struct GNUNET_CONTAINER_MultiHashMap *map = select_store_contact_map (
175 store, context, &hash
176 );
177
178 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (map, &hash, contact))
179 return;
180
181 destroy_contact (contact);
182}