aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_room.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/messenger/gnunet-service-messenger_room.c')
-rw-r--r--src/messenger/gnunet-service-messenger_room.c1051
1 files changed, 0 insertions, 1051 deletions
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
deleted file mode 100644
index 7383e1d20..000000000
--- a/src/messenger/gnunet-service-messenger_room.c
+++ /dev/null
@@ -1,1051 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020 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_room.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "gnunet-service-messenger_room.h"
27
28#include "gnunet-service-messenger_message_kind.h"
29
30#include "gnunet-service-messenger_service.h"
31#include "gnunet-service-messenger_util.h"
32
33static void
34idle_request_room_messages (void *cls);
35
36struct GNUNET_MESSENGER_SrvRoom*
37create_room (struct GNUNET_MESSENGER_SrvHandle *handle, const struct GNUNET_HashCode *key)
38{
39 GNUNET_assert((handle) && (key));
40
41 struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new(struct GNUNET_MESSENGER_SrvRoom);
42
43 room->service = handle->service;
44 room->host = handle;
45 room->port = NULL;
46
47 GNUNET_memcpy(&(room->key), key, sizeof(struct GNUNET_HashCode));
48
49 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
50 room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
51 room->member_infos = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
52
53 init_message_store (&(room->store));
54 room->requested = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
55
56 init_list_tunnels (&(room->basement));
57 init_list_messages (&(room->last_messages));
58
59 room->peer_message = NULL;
60
61 init_list_messages (&(room->handling));
62 room->idle = NULL;
63
64 room->strict_access = GNUNET_NO;
65
66 if (room->service->dir)
67 load_service_room_and_messages (room->service, room);
68
69 room->idle = GNUNET_SCHEDULER_add_with_priority (GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
70
71 return room;
72}
73
74static int
75iterate_destroy_tunnels (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
76{
77 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
78 destroy_tunnel (tunnel);
79 return GNUNET_YES;
80}
81
82static int
83iterate_clear_members (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
84{
85 struct GNUNET_MESSENGER_SrvContact *contact = value;
86
87 if (GNUNET_YES == decrease_contact_rc (contact))
88 {
89 struct GNUNET_MESSENGER_SrvRoom *room = cls;
90
91 const struct GNUNET_HashCode *id = get_contact_id_from_key (contact);
92
93 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (room->service->contacts, id, contact))
94 destroy_contact (contact);
95 }
96
97 return GNUNET_YES;
98}
99
100static int
101iterate_destroy_member_infos (void *cls, const struct GNUNET_ShortHashCode *key, void *value)
102{
103 struct GNUNET_MESSENGER_MemberInfo *info = value;
104
105 clear_list_messages (&(info->session_messages));
106
107 GNUNET_free(info);
108 return GNUNET_YES;
109}
110
111void
112destroy_room (struct GNUNET_MESSENGER_SrvRoom *room)
113{
114 GNUNET_assert(room);
115
116 if (room->idle)
117 {
118 GNUNET_SCHEDULER_cancel (room->idle);
119
120 room->idle = NULL;
121 }
122
123 if (room->port)
124 GNUNET_CADET_close_port (room->port);
125
126 merge_room_last_messages (room, room->host);
127
128 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels,
129 NULL);
130
131 handle_room_messages (room);
132
133 if (room->service->dir)
134 save_service_room_and_messages (room->service, room);
135
136 GNUNET_CONTAINER_multishortmap_iterate (room->members, iterate_clear_members, room);
137 GNUNET_CONTAINER_multishortmap_iterate (room->member_infos, iterate_destroy_member_infos, NULL);
138
139 clear_message_store (&(room->store));
140
141 GNUNET_CONTAINER_multihashmap_destroy (room->requested);
142
143 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
144 GNUNET_CONTAINER_multishortmap_destroy (room->members);
145 GNUNET_CONTAINER_multishortmap_destroy (room->member_infos);
146
147 clear_list_tunnels (&(room->basement));
148 clear_list_messages (&(room->last_messages));
149
150 if (room->peer_message)
151 GNUNET_free(room->peer_message);
152
153 GNUNET_free(room);
154}
155
156struct GNUNET_MESSENGER_SrvContact*
157get_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id)
158{
159 GNUNET_assert((room) && (room->members));
160
161 return GNUNET_CONTAINER_multishortmap_get (room->members, id);
162}
163
164void
165add_room_contact (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id,
166 const struct GNUNET_IDENTITY_PublicKey *pubkey)
167{
168 struct GNUNET_MESSENGER_SrvContact *contact = get_service_contact_by_pubkey (room->service, pubkey);
169
170 if (GNUNET_OK == GNUNET_CONTAINER_multishortmap_put (room->members, id, contact,
171 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
172 increase_contact_rc (contact);
173}
174
175struct GNUNET_MESSENGER_MemberInfo*
176get_room_member_info (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *id)
177{
178 GNUNET_assert((room) && (room->member_infos));
179
180 return GNUNET_CONTAINER_multishortmap_get (room->member_infos, id);
181}
182
183struct GNUNET_ShortHashCode*
184generate_room_member_id (const struct GNUNET_MESSENGER_SrvRoom *room)
185{
186 struct GNUNET_ShortHashCode *unique_id = GNUNET_new(struct GNUNET_ShortHashCode);
187
188 GNUNET_assert(room);
189
190 if (GNUNET_YES == generate_free_member_id (unique_id, room->members))
191 return unique_id;
192 else
193 {
194 GNUNET_free(unique_id);
195 return NULL;
196 }
197}
198
199const struct GNUNET_ShortHashCode*
200get_room_host_id (const struct GNUNET_MESSENGER_SrvRoom *room)
201{
202 GNUNET_assert(room);
203
204 return get_handle_member_id (room->host, &(room->key));
205}
206
207void
208change_room_host_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *unique_id)
209{
210 GNUNET_assert(room);
211
212 change_handle_member_id (room->host, &(room->key), unique_id);
213}
214
215static int
216send_room_info (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
217 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
218{
219 if (!handle)
220 return GNUNET_NO;
221
222 merge_room_last_messages (room, handle);
223
224 if (!is_tunnel_connected (tunnel))
225 return GNUNET_NO;
226
227 struct GNUNET_MESSENGER_Message *message = create_message_info (get_handle_ego(handle), room->members);
228
229 if (!message)
230 return GNUNET_NO;
231
232 if ((tunnel->peer_message) && (tunnel->contact_id))
233 {
234 GNUNET_memcpy(&(message->body.info.unique_id), &(tunnel->contact_id), sizeof(struct GNUNET_ShortHashCode));
235 GNUNET_free(tunnel->contact_id);
236
237 tunnel->contact_id = NULL;
238 }
239
240 struct GNUNET_HashCode hash;
241
242 send_tunnel_message (tunnel, handle, message, &hash);
243 destroy_message (message);
244
245 if (tunnel->contact_id)
246 {
247 GNUNET_free(tunnel->contact_id);
248
249 tunnel->contact_id = NULL;
250 }
251
252 return GNUNET_YES;
253}
254
255static void*
256callback_room_connect (void *cls, struct GNUNET_CADET_Channel *channel, const struct GNUNET_PeerIdentity *source)
257{
258 struct GNUNET_MESSENGER_SrvRoom *room = cls;
259
260 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, source);
261
262 if (tunnel)
263 {
264 if (GNUNET_YES == bind_tunnel (tunnel, channel))
265 {
266 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
267 return tunnel;
268 else
269 {
270 disconnect_tunnel (tunnel);
271 return NULL;
272 }
273 }
274 else
275 {
276 delayed_disconnect_channel (channel);
277 return NULL;
278 }
279 }
280 else
281 {
282 tunnel = create_tunnel (room, source);
283
284 if ((GNUNET_YES == bind_tunnel (tunnel, channel)) && (GNUNET_OK
285 == GNUNET_CONTAINER_multipeermap_put (room->tunnels, source, tunnel,
286 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
287 {
288 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
289 return tunnel;
290 else
291 {
292 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source, tunnel);
293
294 disconnect_tunnel (tunnel);
295 destroy_tunnel (tunnel);
296 return NULL;
297 }
298 }
299 else
300 {
301 tunnel->channel = NULL;
302 destroy_tunnel (tunnel);
303
304 delayed_disconnect_channel (channel);
305 return NULL;
306 }
307 }
308}
309
310static int
311join_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
312 const struct GNUNET_ShortHashCode *member_id)
313{
314 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s(get_room_key(room)), GNUNET_sh2s(member_id));
315
316 struct GNUNET_MESSENGER_Message *message = create_message_join (get_handle_ego(handle));
317
318 if (!message)
319 {
320 GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be created!\n");
321
322 return GNUNET_NO;
323 }
324
325 struct GNUNET_HashCode hash;
326
327 send_room_message (room, handle, message, &hash);
328 destroy_message (message);
329
330 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_new(struct GNUNET_MESSENGER_MemberInfo);
331
332 info->access = GNUNET_MESSENGER_MEMBER_ALLOWED;
333 init_list_messages (&(info->session_messages));
334
335 if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_put (room->member_infos, member_id, info,
336 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
337 {
338 change_handle_member_id (handle, &(room->key), member_id);
339
340 add_to_list_messages (&(info->session_messages), &hash);
341 return GNUNET_YES;
342 }
343 else
344 {
345 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Your member information could not be registered!\n");
346
347 GNUNET_free(info);
348 return GNUNET_NO;
349 }
350}
351
352static int
353join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
354{
355 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key));
356
357 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id);
358
359 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)))
360 return GNUNET_NO;
361
362 return GNUNET_YES;
363}
364
365extern int
366check_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
367extern void
368handle_tunnel_message (void *cls, const struct GNUNET_MessageHeader *header);
369
370extern void
371callback_tunnel_disconnect (void *cls, const struct GNUNET_CADET_Channel *channel);
372
373int
374open_room (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
375{
376 if (room->port)
377 return join_room_locally (room, handle);
378
379 struct GNUNET_CADET_Handle *cadet = get_room_cadet (room);
380 struct GNUNET_HashCode *key = get_room_key (room);
381
382 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size(tunnel_message, GNUNET_MESSAGE_TYPE_CADET_CLI,
383 struct GNUNET_MessageHeader, NULL),
384 GNUNET_MQ_handler_end() };
385
386 room->port = GNUNET_CADET_open_port (cadet, key, callback_room_connect, room, NULL,
387 callback_tunnel_disconnect, handlers);
388
389 const struct GNUNET_ShortHashCode *member_id = get_handle_member_id (handle, &(room->key));
390
391 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, member_id);
392
393 if ((!info) && (GNUNET_NO == join_room (room, handle, member_id)) && (room->port))
394 {
395 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not join the room, therefore it keeps closed!\n");
396
397 GNUNET_CADET_close_port (room->port);
398 room->port = NULL;
399
400 return GNUNET_NO;
401 }
402
403 struct GNUNET_MESSENGER_Message *message = create_message_peer (room->service);
404
405 if (message)
406 {
407 struct GNUNET_HashCode hash;
408
409 send_room_message (room, handle, message, &hash);
410 destroy_message (message);
411 }
412
413 return (room->port ? GNUNET_YES : GNUNET_NO);
414}
415
416int
417entry_room_at (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
418 const struct GNUNET_PeerIdentity *door)
419{
420 if (room->peer_message)
421 {
422 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, handle, room->peer_message, GNUNET_NO);
423
424 if (0 == GNUNET_memcmp(&(msg->body.peer.peer), door))
425 return join_room_locally (room, handle);
426 }
427
428 struct GNUNET_MESSENGER_SrvTunnel *tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
429
430 if (tunnel)
431 {
432 switch (connect_tunnel (tunnel))
433 {
434 case GNUNET_YES:
435 return GNUNET_YES;
436 case GNUNET_NO:
437 return join_room_locally (room, handle);
438 default:
439 return GNUNET_NO;
440 }
441 }
442
443 tunnel = create_tunnel (room, door);
444
445 if ((GNUNET_YES == connect_tunnel (tunnel)) &&
446 (GNUNET_OK == GNUNET_CONTAINER_multipeermap_put (room->tunnels, door, tunnel,
447 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
448 return GNUNET_YES;
449 else
450 {
451 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "You could not connect to that door!\n");
452
453 destroy_tunnel (tunnel);
454 return GNUNET_NO;
455 }
456}
457
458struct GNUNET_MESSENGER_SrvTunnelFinder
459{
460 const struct GNUNET_ShortHashCode *needle;
461 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
462};
463
464static int
465iterate_find_tunnel (void *cls, const struct GNUNET_PeerIdentity *peer, void *value)
466{
467 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
468 struct GNUNET_MESSENGER_SrvTunnelFinder *finder = cls;
469
470 if ((tunnel->contact_id) && (0 == GNUNET_memcmp(tunnel->contact_id, finder->needle)))
471 {
472 finder->tunnel = tunnel;
473 return GNUNET_NO;
474 }
475
476 return GNUNET_YES;
477}
478
479struct GNUNET_MESSENGER_SrvTunnel*
480find_room_tunnel_to (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *contact_id)
481{
482 struct GNUNET_MESSENGER_SrvTunnelFinder finder;
483
484 finder.needle = contact_id;
485 finder.tunnel = NULL;
486
487 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_find_tunnel, &finder);
488
489 return finder.tunnel;
490}
491
492struct GNUNET_MQ_Envelope*
493pack_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
494 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash, int mode)
495{
496 message->header.timestamp = GNUNET_TIME_absolute_hton (GNUNET_TIME_absolute_get ());
497
498 const struct GNUNET_ShortHashCode *id = get_handle_member_id (handle, &(room->key));
499
500 GNUNET_assert(id);
501
502 GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct GNUNET_ShortHashCode));
503
504 if (room->last_messages.head)
505 GNUNET_memcpy(&(message->header.previous), &(room->last_messages.head->hash), sizeof(struct GNUNET_HashCode));
506 else
507 memset (&(message->header.previous), 0, sizeof(struct GNUNET_HashCode));
508
509 return pack_message (message, hash, get_handle_ego (handle), mode);
510}
511
512struct GNUNET_MESSENGER_ClosureSendRoom
513{
514 struct GNUNET_MESSENGER_SrvRoom *room;
515 struct GNUNET_MESSENGER_SrvHandle *handle;
516 struct GNUNET_MESSENGER_SrvTunnel *exclude;
517 struct GNUNET_MESSENGER_Message *message;
518 struct GNUNET_HashCode *hash;
519 int packed;
520};
521
522static int
523iterate_send_room_message (void *cls, const struct GNUNET_PeerIdentity *key, void *value)
524{
525 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
526
527 if ((!is_tunnel_connected (tunnel)) || (!tunnel->contact_id))
528 return GNUNET_YES;
529
530 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
531
532 if (tunnel == closure->exclude)
533 return GNUNET_YES;
534
535 struct GNUNET_MQ_Envelope *env = NULL;
536
537 if (closure->packed == GNUNET_NO)
538 {
539 env = pack_room_message (closure->room, closure->handle, closure->message, closure->hash,
540 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
541
542 if (env)
543 {
544 closure->message = copy_message (closure->message);
545 closure->packed = GNUNET_YES;
546 }
547 }
548 else
549 {
550 env = pack_message (closure->message, NULL, NULL,
551 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
552 }
553
554 if (env)
555 send_tunnel_envelope (tunnel, closure->handle, env, closure->message, closure->hash);
556
557 return GNUNET_YES;
558}
559
560void
561callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls,
562 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash);
563
564void
565send_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
566 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
567{
568 struct GNUNET_MESSENGER_ClosureSendRoom closure;
569
570 closure.room = room;
571 closure.handle = handle;
572 closure.exclude = NULL;
573 closure.message = message;
574 closure.hash = hash;
575 closure.packed = GNUNET_NO;
576
577 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
578
579 if ((GNUNET_NO == closure.packed) && (closure.message == message))
580 {
581 pack_room_message (room, handle, message, hash,
582 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
583
584 callback_room_sent (room, handle, NULL, copy_message (message), hash);
585 }
586}
587
588void
589send_room_message_ext (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
590 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash,
591 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
592{
593 struct GNUNET_MESSENGER_ClosureSendRoom closure;
594
595 closure.room = room;
596 closure.handle = handle;
597 closure.exclude = tunnel;
598 closure.message = message;
599 closure.hash = hash;
600 closure.packed = GNUNET_NO;
601
602 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
603
604 if ((GNUNET_NO == closure.packed) && (closure.message == message))
605 {
606 pack_room_message (room, handle, message, hash,
607 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
608
609 callback_room_sent (room, handle, NULL, copy_message (message), hash);
610 }
611}
612
613void
614forward_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvTunnel *tunnel,
615 const struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
616{
617 struct GNUNET_MESSENGER_ClosureSendRoom closure;
618 struct GNUNET_HashCode message_hash;
619
620 GNUNET_memcpy(&message_hash, hash, sizeof(struct GNUNET_HashCode));
621
622 closure.room = room;
623 closure.handle = NULL;
624 closure.exclude = tunnel;
625 closure.message = copy_message (message);
626 closure.hash = &message_hash;
627 closure.packed = GNUNET_YES;
628
629 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_send_room_message, &closure);
630}
631
632void
633merge_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle)
634{
635 if (!handle)
636 return;
637
638 if (!room->last_messages.head)
639 return;
640
641 while (room->last_messages.head != room->last_messages.tail)
642 {
643 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.tail;
644
645 struct GNUNET_MESSENGER_Message *message = create_message_merge (&(element->hash));
646
647 if (message)
648 {
649 struct GNUNET_HashCode hash;
650
651 send_room_message (room, handle, message, &hash);
652 destroy_message (message);
653 }
654
655 if (element->prev)
656 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, element);
657 }
658}
659
660struct GNUNET_CADET_Handle*
661get_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
662{
663 return room->service->cadet;
664}
665
666struct GNUNET_HashCode*
667get_room_key (struct GNUNET_MESSENGER_SrvRoom *room)
668{
669 return &(room->key);
670}
671
672const struct GNUNET_MESSENGER_SrvTunnel*
673get_room_tunnel (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_PeerIdentity *peer)
674{
675 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
676}
677
678const struct GNUNET_MESSENGER_Message*
679get_room_message (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle,
680 const struct GNUNET_HashCode *hash, int request)
681{
682 const struct GNUNET_MESSENGER_Message *message = get_store_message (&(room->store), hash);
683
684 if ((message) || (!handle) || (GNUNET_YES != request)
685 || (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->requested, hash)))
686 return message;
687
688 struct GNUNET_MESSENGER_Message *request_msg = create_message_request (hash);
689
690 if (request_msg)
691 {
692 if (GNUNET_CONTAINER_multihashmap_put (room->requested, hash, NULL, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST) == GNUNET_OK)
693 {
694 struct GNUNET_HashCode request_hash;
695
696 send_room_message (room, handle, request_msg, &request_hash);
697 }
698
699 destroy_message (request_msg);
700 }
701
702 return message;
703}
704
705void
706callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room, void *cls)
707{
708 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
709
710 if (!room->host)
711 return;
712
713 struct GNUNET_PeerIdentity identity;
714
715 GNUNET_PEER_resolve (tunnel->peer, &identity);
716
717 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
718 {
719 struct GNUNET_MESSENGER_Message *message = create_message_miss (&identity);
720
721 if (message)
722 {
723 struct GNUNET_HashCode hash;
724
725 send_room_message (room, room->host, message, &hash);
726 destroy_message (message);
727 }
728 }
729}
730
731int
732callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room, void *cls,
733 struct GNUNET_MESSENGER_Message *message, struct GNUNET_HashCode *hash)
734{
735 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
736 return GNUNET_SYSERR;
737
738 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members,
739 &(message->header.sender_id));
740
741 if (!contact)
742 {
743 if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
744 contact = get_service_contact_by_pubkey (room->service, &(message->body.info.host_key));
745 else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
746 contact = get_service_contact_by_pubkey (room->service, &(message->body.join.key));
747 }
748
749 if ((!contact) || (GNUNET_SYSERR == verify_message (message, hash, get_contact_key (contact))))
750 return GNUNET_SYSERR;
751
752 if (GNUNET_YES == room->strict_access)
753 {
754 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos,
755 &(message->header.sender_id));
756
757 if ((info) && (GNUNET_MESSENGER_MEMBER_BLOCKED == info->access))
758 return GNUNET_SYSERR;
759 }
760
761 if (GNUNET_YES == contains_store_message (&(room->store), hash))
762 return GNUNET_NO;
763
764 return GNUNET_YES;
765}
766
767static void
768search_room_for_message (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_HashCode *hash)
769{
770 const struct GNUNET_MESSENGER_Message *message = get_room_message (room, room->host, hash, GNUNET_YES);
771
772 if (!message)
773 return;
774
775 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
776 search_room_for_message (room, &(message->body.merge.previous));
777
778 search_room_for_message (room, &(message->header.previous));
779}
780
781static void
782idle_request_room_messages (void *cls)
783{
784 struct GNUNET_MESSENGER_SrvRoom *room = cls;
785
786 room->idle = NULL;
787
788 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head;
789
790 while (element)
791 {
792 search_room_for_message (room, &(element->hash));
793
794 element = element->next;
795 }
796
797 merge_room_last_messages (room, room->host);
798
799 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_second_ (),
800 GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages,
801 cls);
802}
803
804void
805update_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_MESSENGER_Message *message,
806 const struct GNUNET_HashCode *hash)
807{
808 struct GNUNET_MESSENGER_ListMessage *element = room->last_messages.head;
809 struct GNUNET_MESSENGER_ListMessage *merging = NULL;
810
811 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
812 {
813 merging = room->last_messages.head;
814
815 while (merging)
816 {
817 if (0 == GNUNET_CRYPTO_hash_cmp (&(merging->hash), &(message->body.merge.previous)))
818 break;
819
820 merging = merging->next;
821 }
822
823 if (merging)
824 element = merging->next;
825 }
826
827 while (element)
828 {
829 if (0 == GNUNET_CRYPTO_hash_cmp (&(element->hash), &(message->header.previous)))
830 break;
831
832 element = element->next;
833 }
834
835 if ((merging) && (!element))
836 {
837 element = merging;
838 merging = NULL;
839 }
840
841 if (element)
842 {
843 GNUNET_memcpy(&(element->hash), hash, sizeof(struct GNUNET_HashCode));
844
845 if (merging)
846 GNUNET_CONTAINER_DLL_remove(room->last_messages.head, room->last_messages.tail, merging);
847 }
848 else
849 add_to_list_messages (&(room->last_messages), hash);
850
851 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (room->requested, hash))
852 GNUNET_CONTAINER_multihashmap_remove_all (room->requested, hash);
853}
854
855void
856switch_room_member_id (struct GNUNET_MESSENGER_SrvRoom *room, const struct GNUNET_ShortHashCode *old_id,
857 const struct GNUNET_ShortHashCode *new_id, const struct GNUNET_HashCode *hash)
858{
859 struct GNUNET_MESSENGER_SrvContact *contact = GNUNET_CONTAINER_multishortmap_get (room->members, old_id);
860
861 if ((contact) && (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (room->members, old_id, contact)))
862 GNUNET_CONTAINER_multishortmap_put (room->members, new_id, contact,
863 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
864
865 struct GNUNET_MESSENGER_MemberInfo *info = GNUNET_CONTAINER_multishortmap_get (room->member_infos, old_id);
866
867 if ((!info) || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove (room->member_infos, old_id, contact))
868 || (GNUNET_YES != GNUNET_CONTAINER_multishortmap_put (room->member_infos, new_id, contact,
869 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
870 return;
871
872 if (hash)
873 add_to_list_messages (&(info->session_messages), hash);
874}
875
876void
877rebuild_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
878{
879 struct GNUNET_PeerIdentity peer;
880 size_t src;
881
882 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) || (!find_list_tunnels (&(room->basement), &peer,
883 &src)))
884 return;
885
886 size_t count = count_of_tunnels (&(room->basement));
887
888 struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head;
889 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
890
891 size_t dst = 0;
892
893 while (element)
894 {
895 GNUNET_PEER_resolve (element->peer, &peer);
896
897 tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer);
898
899 if (!tunnel)
900 {
901 element = remove_from_list_tunnels (&(room->basement), element);
902 continue;
903 }
904
905 if (GNUNET_YES == required_connection_between (count, src, dst))
906 {
907 if (GNUNET_SYSERR == connect_tunnel (tunnel))
908 {
909 element = remove_from_list_tunnels (&(room->basement), element);
910 continue;
911 }
912 }
913 else
914 disconnect_tunnel (tunnel);
915
916 element = element->next;
917 dst++;
918 }
919}
920
921void
922handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
923{
924 while (room->handling.head)
925 {
926 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
927
928 const struct GNUNET_MESSENGER_Message *msg = get_room_message (room, room->host, &(element->hash), GNUNET_NO);
929
930 if (msg)
931 handle_service_message (room->service, room, msg, &(element->hash));
932
933 GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, element);
934 GNUNET_free(element);
935 }
936}
937
938#include "gnunet-service-messenger_message_recv.h"
939
940void
941callback_room_recv (struct GNUNET_MESSENGER_SrvRoom *room, void *cls, struct GNUNET_MESSENGER_Message *message,
942 const struct GNUNET_HashCode *hash)
943{
944 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
945
946 if (GNUNET_OK != put_store_message (&(room->store), hash, message))
947 return;
948
949 update_room_last_messages (room, message, hash);
950
951 if (GNUNET_MESSENGER_KIND_INFO != message->header.kind)
952 forward_room_message (room, tunnel, message, hash);
953
954 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
955
956 add_to_list_messages (&(room->handling), hash);
957
958 switch (message->header.kind)
959 {
960 case GNUNET_MESSENGER_KIND_INFO:
961 recv_message_info (room, tunnel, message, hash);
962 break;
963 case GNUNET_MESSENGER_KIND_JOIN:
964 recv_message_join (room, tunnel, message, hash);
965 break;
966 case GNUNET_MESSENGER_KIND_LEAVE:
967 recv_message_leave (room, tunnel, message, hash);
968 break;
969 case GNUNET_MESSENGER_KIND_NAME:
970 recv_message_name (room, tunnel, message, hash);
971 break;
972 case GNUNET_MESSENGER_KIND_KEY:
973 recv_message_key (room, tunnel, message, hash);
974 break;
975 case GNUNET_MESSENGER_KIND_PEER:
976 recv_message_peer (room, tunnel, message, hash);
977 break;
978 case GNUNET_MESSENGER_KIND_ID:
979 recv_message_id (room, tunnel, message, hash);
980 break;
981 case GNUNET_MESSENGER_KIND_MISS:
982 recv_message_miss (room, tunnel, message, hash);
983 break;
984 case GNUNET_MESSENGER_KIND_REQUEST:
985 recv_message_request (room, tunnel, message, hash);
986 break;
987 default:
988 break;
989 }
990
991 if (GNUNET_YES == start_handle)
992 handle_room_messages (room);
993}
994
995#include "gnunet-service-messenger_message_send.h"
996
997void
998callback_room_sent (struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_SrvHandle *handle, void *cls,
999 struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
1000{
1001 const struct GNUNET_MESSENGER_Message *old_message = get_room_message (room, handle, hash, GNUNET_NO);
1002
1003 if ((old_message) || (GNUNET_OK != put_store_message (&(room->store), hash, message)))
1004 {
1005 if (old_message != message)
1006 GNUNET_free(message);
1007 }
1008 else
1009 {
1010 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls; // may be NULL
1011
1012 update_room_last_messages (room, message, hash);
1013
1014 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
1015
1016 add_to_list_messages (&(room->handling), hash);
1017
1018 switch (message->header.kind)
1019 {
1020 case GNUNET_MESSENGER_KIND_INFO:
1021 send_message_info (room, handle, tunnel, message, hash);
1022 break;
1023 case GNUNET_MESSENGER_KIND_JOIN:
1024 send_message_join (room, handle, tunnel, message, hash);
1025 break;
1026 case GNUNET_MESSENGER_KIND_LEAVE:
1027 send_message_leave (room, handle, tunnel, message, hash);
1028 break;
1029 case GNUNET_MESSENGER_KIND_NAME:
1030 send_message_name (room, handle, tunnel, message, hash);
1031 break;
1032 case GNUNET_MESSENGER_KIND_KEY:
1033 send_message_key (room, handle, tunnel, message, hash);
1034 break;
1035 case GNUNET_MESSENGER_KIND_PEER:
1036 send_message_peer (room, handle, tunnel, message, hash);
1037 break;
1038 case GNUNET_MESSENGER_KIND_ID:
1039 send_message_id (room, handle, tunnel, message, hash);
1040 break;
1041 case GNUNET_MESSENGER_KIND_MISS:
1042 send_message_miss (room, handle, tunnel, message, hash);
1043 break;
1044 default:
1045 break;
1046 }
1047
1048 if (GNUNET_YES == start_handle)
1049 handle_room_messages (room);
1050 }
1051}