aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/messenger_api_message_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/messenger_api_message_control.c')
-rw-r--r--src/service/messenger/messenger_api_message_control.c251
1 files changed, 251 insertions, 0 deletions
diff --git a/src/service/messenger/messenger_api_message_control.c b/src/service/messenger/messenger_api_message_control.c
new file mode 100644
index 000000000..e8d0333dc
--- /dev/null
+++ b/src/service/messenger/messenger_api_message_control.c
@@ -0,0 +1,251 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2024 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_message_control.c
23 * @brief messenger api: client and service implementation of GNUnet MESSENGER service
24 */
25
26#include "messenger_api_message_control.h"
27
28#include "gnunet_common.h"
29#include "gnunet_messenger_service.h"
30#include "gnunet_scheduler_lib.h"
31#include "messenger_api_contact.h"
32#include "messenger_api_contact_store.h"
33#include "messenger_api_handle.h"
34#include "messenger_api_message.h"
35#include "messenger_api_room.h"
36
37struct GNUNET_MESSENGER_MessageControl*
38create_message_control (struct GNUNET_MESSENGER_Room *room)
39{
40 GNUNET_assert (room);
41
42 struct GNUNET_MESSENGER_MessageControl *control;
43
44 control = GNUNET_new (struct GNUNET_MESSENGER_MessageControl);
45 control->room = room;
46
47 control->peer_messages = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
48 control->member_messages = GNUNET_CONTAINER_multishortmap_create (8,
49 GNUNET_NO);
50
51 control->head = NULL;
52 control->tail = NULL;
53
54 return control;
55}
56
57
58void
59destroy_message_control (struct GNUNET_MESSENGER_MessageControl *control)
60{
61 GNUNET_assert (control);
62
63 struct GNUNET_MESSENGER_MessageControlQueue *queue;
64 while (control->head)
65 {
66 queue = control->head;
67
68 if (queue->task)
69 GNUNET_SCHEDULER_cancel (queue->task);
70
71 destroy_message (queue->message);
72
73 GNUNET_CONTAINER_DLL_remove (control->head, control->tail, queue);
74 GNUNET_free (queue);
75 }
76
77 GNUNET_CONTAINER_multishortmap_destroy (control->peer_messages);
78 GNUNET_CONTAINER_multishortmap_destroy (control->member_messages);
79
80 GNUNET_free (control);
81}
82
83
84static void
85enqueue_message_control (struct GNUNET_MESSENGER_MessageControl *control,
86 const struct GNUNET_HashCode *sender,
87 const struct GNUNET_HashCode *context,
88 const struct GNUNET_HashCode *hash,
89 const struct GNUNET_MESSENGER_Message *message,
90 enum GNUNET_MESSENGER_MessageFlags flags)
91{
92 GNUNET_assert ((control) && (sender) && (context) && (hash) && (message));
93
94 struct GNUNET_CONTAINER_MultiShortmap *map;
95 if (GNUNET_YES == is_peer_message (message))
96 map = control->peer_messages;
97 else
98 map = control->member_messages;
99
100 struct GNUNET_MESSENGER_MessageControlQueue *queue;
101
102 queue = GNUNET_new (struct GNUNET_MESSENGER_MessageControlQueue);
103 queue->control = control;
104
105 GNUNET_memcpy (&(queue->sender), sender, sizeof (queue->sender));
106 GNUNET_memcpy (&(queue->context), context, sizeof (queue->context));
107 GNUNET_memcpy (&(queue->hash), hash, sizeof (queue->hash));
108
109 queue->message = copy_message (message);
110 queue->flags = flags;
111 queue->task = NULL;
112
113 GNUNET_CONTAINER_DLL_insert (control->head, control->tail, queue);
114
115 GNUNET_CONTAINER_multishortmap_put (map,
116 &(message->header.sender_id),
117 queue,
118 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
119}
120
121
122static void
123handle_message_control (struct GNUNET_MESSENGER_MessageControl *control,
124 struct GNUNET_MESSENGER_Contact *contact,
125 const struct GNUNET_HashCode *hash,
126 const struct GNUNET_MESSENGER_Message *message,
127 enum GNUNET_MESSENGER_MessageFlags flags)
128{
129 GNUNET_assert ((control) && (hash) && (message));
130
131 handle_room_message (control->room, contact, message, hash, flags);
132
133 if (flags & GNUNET_MESSENGER_FLAG_RECENT)
134 update_room_last_message (control->room, hash);
135
136 callback_room_message (control->room, hash);
137}
138
139
140static void
141task_message_control (void *cls)
142{
143 GNUNET_assert (cls);
144
145 struct GNUNET_MESSENGER_MessageControlQueue *queue = cls;
146 struct GNUNET_MESSENGER_MessageControl *control = queue->control;
147
148 queue->task = NULL;
149
150 struct GNUNET_MESSENGER_Handle *handle = get_room_handle (control->room);
151 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
152 handle);
153
154 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw (
155 store, &(queue->context), &(queue->sender));
156
157 struct GNUNET_CONTAINER_MultiShortmap *map;
158 if (GNUNET_YES == is_peer_message (queue->message))
159 map = control->peer_messages;
160 else
161 map = control->member_messages;
162
163 GNUNET_CONTAINER_multishortmap_remove (map,
164 &(queue->message->header.sender_id),
165 queue);
166
167 GNUNET_CONTAINER_DLL_remove (control->head, control->tail, queue);
168
169 handle_message_control (control,
170 contact,
171 &(queue->hash),
172 queue->message,
173 queue->flags);
174
175 destroy_message (queue->message);
176
177 GNUNET_free (queue);
178}
179
180
181static enum GNUNET_GenericReturnValue
182iterate_message_control (void *cls,
183 const struct GNUNET_ShortHashCode *key,
184 void *value)
185{
186 GNUNET_assert ((key) && (value));
187
188 struct GNUNET_MESSENGER_MessageControlQueue *queue = value;
189
190 if (queue->task)
191 return GNUNET_YES;
192
193 queue->task = GNUNET_SCHEDULER_add_now (task_message_control, queue);
194 return GNUNET_YES;
195}
196
197
198void
199process_message_control (struct GNUNET_MESSENGER_MessageControl *control,
200 const struct GNUNET_HashCode *sender,
201 const struct GNUNET_HashCode *context,
202 const struct GNUNET_HashCode *hash,
203 const struct GNUNET_MESSENGER_Message *message,
204 enum GNUNET_MESSENGER_MessageFlags flags)
205{
206 GNUNET_assert ((control) && (sender) && (context) && (hash) && (message));
207
208 struct GNUNET_MESSENGER_Handle *handle = get_room_handle (control->room);
209 struct GNUNET_MESSENGER_ContactStore *store = get_handle_contact_store (
210 handle);
211
212 struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw (
213 store, context, sender);
214
215 if ((! contact) &&
216 (GNUNET_MESSENGER_KIND_JOIN != message->header.kind) &&
217 (GNUNET_MESSENGER_KIND_PEER != message->header.kind))
218 enqueue_message_control (control, sender, context, hash, message, flags);
219 else
220 handle_message_control (control, contact, hash, message, flags);
221
222 struct GNUNET_CONTAINER_MultiShortmap *map = NULL;
223 const struct GNUNET_ShortHashCode *id = &(message->header.sender_id);
224
225 if (GNUNET_YES == is_peer_message (message))
226 map = control->peer_messages;
227
228 switch (message->header.kind)
229 {
230 case GNUNET_MESSENGER_KIND_JOIN:
231 map = control->member_messages;
232 break;
233 case GNUNET_MESSENGER_KIND_PEER:
234 map = control->peer_messages;
235 break;
236 case GNUNET_MESSENGER_KIND_ID:
237 map = control->member_messages;
238 id = &(message->body.id.id);
239 break;
240 default:
241 break;
242 }
243
244 if (! map)
245 return;
246
247 GNUNET_CONTAINER_multishortmap_get_multiple (map,
248 id,
249 iterate_message_control,
250 NULL);
251}