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