aboutsummaryrefslogtreecommitdiff
path: root/src/service/messenger/gnunet-service-messenger_service.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/service/messenger/gnunet-service-messenger_service.c')
-rw-r--r--src/service/messenger/gnunet-service-messenger_service.c354
1 files changed, 354 insertions, 0 deletions
diff --git a/src/service/messenger/gnunet-service-messenger_service.c b/src/service/messenger/gnunet-service-messenger_service.c
new file mode 100644
index 000000000..b72bbd201
--- /dev/null
+++ b/src/service/messenger/gnunet-service-messenger_service.c
@@ -0,0 +1,354 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--2023 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_service.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "gnunet-service-messenger_service.h"
28#include "gnunet-service-messenger.h"
29#include "messenger_api_message_kind.h"
30
31static void
32callback_shutdown_service (void *cls)
33{
34 struct GNUNET_MESSENGER_Service *service = cls;
35
36 if (service)
37 {
38 service->shutdown = NULL;
39
40 destroy_service (service);
41 }
42}
43
44
45struct GNUNET_MESSENGER_Service*
46create_service (const struct GNUNET_CONFIGURATION_Handle *config,
47 struct GNUNET_SERVICE_Handle *service_handle)
48{
49 GNUNET_assert ((config) && (service_handle));
50
51 struct GNUNET_MESSENGER_Service *service = GNUNET_new (struct
52 GNUNET_MESSENGER_Service);
53
54 service->config = config;
55 service->service = service_handle;
56
57 service->shutdown = GNUNET_SCHEDULER_add_shutdown (&callback_shutdown_service,
58 service);
59
60 service->peer = NULL;
61 service->dir = NULL;
62
63 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config,
64 GNUNET_MESSENGER_SERVICE_NAME,
65 "MESSENGER_DIR",
66 &(service->dir)))
67 {
68 if (service->dir)
69 GNUNET_free (service->dir);
70
71 service->dir = NULL;
72 }
73 else
74 {
75 if ((GNUNET_YES != GNUNET_DISK_directory_test (service->dir, GNUNET_YES)) &&
76 (GNUNET_OK
77 !=
78 GNUNET_DISK_directory_create (service->dir)))
79 {
80 GNUNET_free (service->dir);
81
82 service->dir = NULL;
83 }
84 }
85
86 service->cadet = GNUNET_CADET_connect (service->config);
87
88 init_list_handles (&(service->handles));
89
90 service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
91
92 init_contact_store (get_service_contact_store (service));
93
94 return service;
95}
96
97
98static int
99iterate_destroy_rooms (void *cls,
100 const struct GNUNET_HashCode *key,
101 void *value)
102{
103 struct GNUNET_MESSENGER_SrvRoom *room = value;
104 destroy_srv_room (room, GNUNET_NO);
105 return GNUNET_YES;
106}
107
108
109void
110destroy_service (struct GNUNET_MESSENGER_Service *service)
111{
112 GNUNET_assert (service);
113
114 if (service->shutdown)
115 {
116 GNUNET_SCHEDULER_cancel (service->shutdown);
117
118 service->shutdown = NULL;
119 }
120
121 clear_list_handles (&(service->handles));
122
123 GNUNET_CONTAINER_multihashmap_iterate (service->rooms, iterate_destroy_rooms,
124 NULL);
125 GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
126
127 clear_contact_store (get_service_contact_store (service));
128
129 if (service->cadet)
130 {
131 GNUNET_CADET_disconnect (service->cadet);
132
133 service->cadet = NULL;
134 }
135
136 if (service->dir)
137 {
138 GNUNET_free (service->dir);
139
140 service->dir = NULL;
141 }
142
143 if (service->peer)
144 {
145 GNUNET_free (service->peer);
146
147 service->peer = NULL;
148 }
149
150 GNUNET_SERVICE_shutdown (service->service);
151
152 GNUNET_free (service);
153}
154
155
156struct GNUNET_MESSENGER_ContactStore*
157get_service_contact_store (struct GNUNET_MESSENGER_Service *service)
158{
159 GNUNET_assert (service);
160
161 return &(service->contact_store);
162}
163
164
165struct GNUNET_MESSENGER_SrvHandle*
166add_service_handle (struct GNUNET_MESSENGER_Service *service,
167 struct GNUNET_MQ_Handle *mq)
168{
169 GNUNET_assert ((service) && (mq));
170
171 struct GNUNET_MESSENGER_SrvHandle *handle = create_srv_handle (service, mq);
172
173 if (handle)
174 {
175 add_list_handle (&(service->handles), handle);
176 }
177
178 return handle;
179}
180
181
182void
183remove_service_handle (struct GNUNET_MESSENGER_Service *service,
184 struct GNUNET_MESSENGER_SrvHandle *handle)
185{
186 GNUNET_assert ((service) && (handle));
187
188 if (! handle)
189 return;
190
191 if (GNUNET_YES == remove_list_handle (&(service->handles), handle))
192 destroy_srv_handle (handle);
193}
194
195
196int
197get_service_peer_identity (struct GNUNET_MESSENGER_Service *service,
198 struct GNUNET_PeerIdentity *peer)
199{
200 GNUNET_assert ((service) && (peer));
201
202 if (service->peer)
203 {
204 GNUNET_memcpy (peer, service->peer, sizeof(struct GNUNET_PeerIdentity));
205 return GNUNET_OK;
206 }
207
208 int result = GNUNET_CRYPTO_get_peer_identity (service->config, peer);
209
210 if (GNUNET_OK != result)
211 return result;
212
213 if (! service->peer)
214 service->peer = GNUNET_new (struct GNUNET_PeerIdentity);
215
216 GNUNET_memcpy (service->peer, peer, sizeof(struct GNUNET_PeerIdentity));
217 return result;
218}
219
220
221struct GNUNET_MESSENGER_SrvRoom*
222get_service_room (const struct GNUNET_MESSENGER_Service *service,
223 const struct GNUNET_HashCode *key)
224{
225 GNUNET_assert ((service) && (key));
226
227 return GNUNET_CONTAINER_multihashmap_get (service->rooms, key);
228}
229
230
231int
232open_service_room (struct GNUNET_MESSENGER_Service *service,
233 struct GNUNET_MESSENGER_SrvHandle *handle,
234 const struct GNUNET_HashCode *key)
235{
236 GNUNET_assert ((service) && (handle) && (key));
237
238 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
239
240 if (room)
241 return open_srv_room (room, handle);
242
243 room = create_srv_room (handle, key);
244
245 if ((GNUNET_YES == open_srv_room (room, handle)) &&
246 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
247 key, room,
248 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
249 return GNUNET_YES;
250
251 destroy_srv_room (room, GNUNET_YES);
252 return GNUNET_NO;
253}
254
255
256int
257entry_service_room (struct GNUNET_MESSENGER_Service *service,
258 struct GNUNET_MESSENGER_SrvHandle *handle,
259 const struct GNUNET_PeerIdentity *door,
260 const struct GNUNET_HashCode *key)
261{
262 GNUNET_assert ((service) && (handle) && (door) && (key));
263
264 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
265
266 if (room)
267 {
268 if (GNUNET_YES == enter_srv_room_at (room, handle, door))
269 return GNUNET_YES;
270 else
271 return GNUNET_NO;
272 }
273
274 room = create_srv_room (handle, key);
275
276 if ((GNUNET_YES == enter_srv_room_at (room, handle, door)) &&
277 (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (service->rooms,
278 key, room,
279 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
280 {
281 return GNUNET_YES;
282 }
283 else
284 {
285 destroy_srv_room (room, GNUNET_YES);
286 return GNUNET_NO;
287 }
288
289}
290
291
292int
293close_service_room (struct GNUNET_MESSENGER_Service *service,
294 struct GNUNET_MESSENGER_SrvHandle *handle,
295 const struct GNUNET_HashCode *key)
296{
297 GNUNET_assert ((service) && (handle) && (key));
298
299 struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (service, key);
300
301 if (! room)
302 return GNUNET_NO;
303
304 const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle,
305 key);
306
307 GNUNET_assert (id);
308
309 if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (handle->member_ids,
310 key, id))
311 return GNUNET_NO;
312
313 struct GNUNET_MESSENGER_SrvHandle *member_handle = (struct
314 GNUNET_MESSENGER_SrvHandle
315 *)
316 find_list_handle_by_member (
317 &(service->handles), key);
318
319 if (! member_handle)
320 {
321 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_remove (service->rooms, key,
322 room))
323 {
324 destroy_srv_room (room, GNUNET_YES);
325 return GNUNET_YES;
326 }
327 else
328 return GNUNET_NO;
329 }
330
331 if (room->host == handle)
332 room->host = member_handle;
333
334 return GNUNET_YES;
335}
336
337
338void
339handle_service_message (struct GNUNET_MESSENGER_Service *service,
340 struct GNUNET_MESSENGER_SrvRoom *room,
341 const struct GNUNET_MESSENGER_SenderSession *session,
342 const struct GNUNET_MESSENGER_Message *message,
343 const struct GNUNET_HashCode *hash)
344{
345 GNUNET_assert ((service) && (room) && (session) && (message) && (hash));
346
347 struct GNUNET_MESSENGER_ListHandle *element = service->handles.head;
348
349 while (element)
350 {
351 notify_srv_handle_message (element->handle, room, session, message, hash);
352 element = element->next;
353 }
354}