aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/messenger_api_room.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/messenger_api_room.c')
-rw-r--r--src/messenger/messenger_api_room.c341
1 files changed, 0 insertions, 341 deletions
diff --git a/src/messenger/messenger_api_room.c b/src/messenger/messenger_api_room.c
deleted file mode 100644
index 0d9237a2e..000000000
--- a/src/messenger/messenger_api_room.c
+++ /dev/null
@@ -1,341 +0,0 @@
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_room.c
23 * @brief messenger api: client implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_room.h"
27
28#include "messenger_api_handle.h"
29
30struct GNUNET_MESSENGER_Room*
31create_room (struct GNUNET_MESSENGER_Handle *handle, const struct GNUNET_HashCode *key)
32{
33 GNUNET_assert((handle) && (key));
34
35 struct GNUNET_MESSENGER_Room *room = GNUNET_new(struct GNUNET_MESSENGER_Room);
36
37 room->handle = handle;
38 GNUNET_memcpy(&(room->key), key, sizeof(*key));
39
40 room->opened = GNUNET_NO;
41 room->contact_id = NULL;
42
43 init_list_tunnels (&(room->entries));
44
45 room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
46 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
47
48 return room;
49}
50
51static int
52iterate_destroy_message (void *cls, const struct GNUNET_HashCode *key, void *value)
53{
54 struct GNUNET_MESSENGER_RoomMessageEntry *entry = value;
55
56 destroy_message (entry->message);
57 GNUNET_free(entry);
58
59 return GNUNET_YES;
60}
61
62void
63destroy_room (struct GNUNET_MESSENGER_Room *room)
64{
65 GNUNET_assert(room);
66
67 clear_list_tunnels (&(room->entries));
68
69 if (room->messages)
70 {
71 GNUNET_CONTAINER_multihashmap_iterate (room->messages, iterate_destroy_message, NULL);
72
73 GNUNET_CONTAINER_multihashmap_destroy (room->messages);
74 }
75
76 if (room->members)
77 GNUNET_CONTAINER_multishortmap_destroy (room->members);
78
79 if (room->contact_id)
80 GNUNET_free(room->contact_id);
81
82 GNUNET_free(room);
83}
84
85const struct GNUNET_MESSENGER_Message*
86get_room_message (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
87{
88 GNUNET_assert((room) && (hash));
89
90 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
91 room->messages, hash
92 );
93
94 return (entry? entry->message : NULL);
95}
96
97struct GNUNET_MESSENGER_Contact*
98get_room_sender (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
99{
100 GNUNET_assert((room) && (hash));
101
102 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
103 room->messages, hash
104 );
105
106 return (entry? entry->sender : NULL);
107}
108
109static struct GNUNET_MESSENGER_Contact*
110handle_join_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
111 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
112{
113 if (!sender)
114 {
115 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
116 struct GNUNET_HashCode context;
117
118 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
119
120 sender = get_store_contact(store, &context, &(message->body.join.key));
121 }
122
123 if ((GNUNET_YES != GNUNET_CONTAINER_multishortmap_contains_value(room->members, &(message->header.sender_id), sender)) &&
124 (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put(room->members, &(message->header.sender_id), sender,
125 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
126 increase_contact_rc(sender);
127
128 return sender;
129}
130
131static void
132handle_leave_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
133 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
134{
135 if ((!sender) ||
136 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)))
137 return;
138
139 struct GNUNET_HashCode context;
140 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
141
142 if (GNUNET_YES == decrease_contact_rc(sender))
143 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room with you anymore!\n");
144}
145
146static void
147handle_name_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
148 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
149{
150 if (!sender)
151 return;
152
153 set_contact_name (sender, message->body.name.name);
154}
155
156static void
157handle_key_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
158 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
159{
160 if (!sender)
161 return;
162
163 struct GNUNET_HashCode context;
164 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
165
166 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
167
168 update_store_contact(store, sender, &context, &context, &(message->body.key.key));
169}
170
171static void
172handle_id_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
173 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
174{
175 if ((!sender) ||
176 (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, &(message->header.sender_id), sender)) ||
177 (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, &(message->body.id.id), sender,
178 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
179 return;
180
181 struct GNUNET_HashCode context, next_context;
182 get_context_from_member(&(room->key), &(message->header.sender_id), &context);
183 get_context_from_member(&(room->key), &(message->body.id.id), &next_context);
184
185 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store(room->handle);
186
187 update_store_contact(store, sender, &context, &next_context, get_contact_key(sender));
188}
189
190static void
191handle_miss_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
192 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
193{
194 if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), room->contact_id)))
195 {
196 struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels (&(room->entries), &(message->body.miss.peer), NULL);
197
198 if (match)
199 remove_from_list_tunnels (&(room->entries), match);
200 }
201}
202
203static void
204handle_delete_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
205 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
206{
207 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (
208 room->messages, &(message->body.deletion.hash)
209 );
210
211 if ((entry) && ((entry->sender == sender) || (get_handle_contact (room->handle, &(room->key)) == sender)) &&
212 (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->messages, &(message->body.deletion.hash), entry)))
213 {
214 destroy_message (entry->message);
215 GNUNET_free(entry);
216 }
217}
218
219struct GNUNET_MESSENGER_Contact*
220handle_room_message (struct GNUNET_MESSENGER_Room *room, struct GNUNET_MESSENGER_Contact *sender,
221 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
222{
223 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, hash))
224 return sender;
225
226 switch (message->header.kind)
227 {
228 case GNUNET_MESSENGER_KIND_JOIN:
229 sender = handle_join_message (room, sender, message, hash);
230 break;
231 case GNUNET_MESSENGER_KIND_LEAVE:
232 handle_leave_message (room, sender, message, hash);
233 break;
234 case GNUNET_MESSENGER_KIND_NAME:
235 handle_name_message (room, sender, message, hash);
236 break;
237 case GNUNET_MESSENGER_KIND_KEY:
238 handle_key_message (room, sender, message, hash);
239 break;
240 case GNUNET_MESSENGER_KIND_ID:
241 handle_id_message (room, sender, message, hash);
242 break;
243 case GNUNET_MESSENGER_KIND_MISS:
244 handle_miss_message (room, sender, message, hash);
245 break;
246 case GNUNET_MESSENGER_KIND_DELETE:
247 handle_delete_message (room, sender, message, hash);
248 break;
249 default:
250 break;
251 }
252
253 struct GNUNET_MESSENGER_RoomMessageEntry *entry = GNUNET_new(struct GNUNET_MESSENGER_RoomMessageEntry);
254
255 if (!entry)
256 return sender;
257
258 entry->sender = sender;
259 entry->message = copy_message (message);
260
261 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (room->messages, hash, entry,
262 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
263 {
264 destroy_message (entry->message);
265 GNUNET_free(entry);
266 }
267
268 return sender;
269}
270
271struct GNUNET_MESSENGER_MemberCall
272{
273 struct GNUNET_MESSENGER_Room *room;
274 GNUNET_MESSENGER_MemberCallback callback;
275 void *cls;
276};
277
278static int
279iterate_local_members (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
280{
281 struct GNUNET_MESSENGER_MemberCall *call = cls;
282 struct GNUNET_MESSENGER_Contact *contact = value;
283
284 return call->callback(call->cls, call->room, contact);
285}
286
287int
288iterate_room_members (struct GNUNET_MESSENGER_Room *room, GNUNET_MESSENGER_MemberCallback callback,
289 void* cls)
290{
291 GNUNET_assert(room);
292
293 if (!callback)
294 return GNUNET_CONTAINER_multishortmap_iterate(room->members, NULL, NULL);
295
296 struct GNUNET_MESSENGER_MemberCall call;
297
298 call.room = room;
299 call.callback = callback;
300 call.cls = cls;
301
302 GNUNET_assert(callback);
303
304 return GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_local_members, &call);
305}
306
307struct GNUNET_MESSENGER_MemberFind
308{
309 const struct GNUNET_MESSENGER_Contact *contact;
310 int result;
311};
312
313static int
314iterate_find_member (void* cls, const struct GNUNET_ShortHashCode *key, void *value)
315{
316 struct GNUNET_MESSENGER_MemberFind *find = cls;
317 struct GNUNET_MESSENGER_Contact *contact = value;
318
319 if (contact == find->contact)
320 {
321 find->result = GNUNET_YES;
322 return GNUNET_NO;
323 }
324
325 return GNUNET_YES;
326}
327
328int
329find_room_member (const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_MESSENGER_Contact *contact)
330{
331 GNUNET_assert(room);
332
333 struct GNUNET_MESSENGER_MemberFind find;
334
335 find.contact = contact;
336 find.result = GNUNET_NO;
337
338 GNUNET_CONTAINER_multishortmap_iterate(room->members, iterate_find_member, &find);
339
340 return find.result;
341}