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.c1390
1 files changed, 0 insertions, 1390 deletions
diff --git a/src/messenger/gnunet-service-messenger_room.c b/src/messenger/gnunet-service-messenger_room.c
deleted file mode 100644
index 12d21b814..000000000
--- a/src/messenger/gnunet-service-messenger_room.c
+++ /dev/null
@@ -1,1390 +0,0 @@
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_room.c
23 * @brief GNUnet MESSENGER service
24 */
25
26#include "platform.h"
27#include "gnunet-service-messenger_room.h"
28
29#include "gnunet-service-messenger_member.h"
30#include "gnunet-service-messenger_sender_session.h"
31
32#include "gnunet-service-messenger_message_kind.h"
33#include "gnunet-service-messenger_message_handle.h"
34#include "gnunet-service-messenger_message_send.h"
35
36#include "gnunet-service-messenger_operation.h"
37
38#include "gnunet-service-messenger.h"
39#include "gnunet-service-messenger_service.h"
40#include "gnunet-service-messenger_tunnel.h"
41
42#include "messenger_api_message.h"
43#include "messenger_api_util.h"
44
45static void
46idle_request_room_messages (void *cls);
47
48struct GNUNET_MESSENGER_SrvRoom*
49create_srv_room (struct GNUNET_MESSENGER_SrvHandle *handle,
50 const struct GNUNET_HashCode *key)
51{
52 GNUNET_assert ((handle) && (key));
53
54 struct GNUNET_MESSENGER_SrvRoom *room = GNUNET_new (struct
55 GNUNET_MESSENGER_SrvRoom);
56
57 room->service = handle->service;
58 room->host = handle;
59 room->port = NULL;
60
61 GNUNET_memcpy (&(room->key), key, sizeof(struct GNUNET_HashCode));
62
63 room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
64
65 init_peer_store (get_srv_room_peer_store (room));
66 init_member_store (get_srv_room_member_store (room), room);
67 init_message_store (get_srv_room_message_store (room));
68 init_operation_store (get_srv_room_operation_store (room), room);
69
70 init_list_tunnels (&(room->basement));
71 init_message_state (&(room->state));
72
73 room->peer_message = NULL;
74
75 init_list_messages (&(room->handling));
76 room->idle = NULL;
77
78 if (room->service->dir)
79 load_srv_room (room);
80
81 room->idle = GNUNET_SCHEDULER_add_with_priority (
82 GNUNET_SCHEDULER_PRIORITY_IDLE, idle_request_room_messages, room);
83
84 return room;
85}
86
87
88static int
89iterate_destroy_tunnels (void *cls,
90 const struct GNUNET_PeerIdentity *key,
91 void *value)
92{
93 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
94 destroy_tunnel (tunnel);
95 return GNUNET_YES;
96}
97
98
99static void
100handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room);
101
102void
103destroy_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
104 int deletion)
105{
106 GNUNET_assert (room);
107
108 if (room->idle)
109 {
110 GNUNET_SCHEDULER_cancel (room->idle);
111 room->idle = NULL;
112 }
113
114 if (room->port)
115 GNUNET_CADET_close_port (room->port);
116
117 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels, iterate_destroy_tunnels,
118 NULL);
119 handle_room_messages (room);
120
121 if (! (room->service->dir))
122 goto skip_saving;
123
124 if (GNUNET_YES == deletion)
125 remove_srv_room (room);
126 else
127 save_srv_room (room);
128
129skip_saving:
130 clear_peer_store (get_srv_room_peer_store (room));
131 clear_member_store (get_srv_room_member_store (room));
132 clear_message_store (get_srv_room_message_store (room));
133 clear_operation_store (get_srv_room_operation_store (room));
134
135 GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
136 clear_list_tunnels (&(room->basement));
137 clear_message_state (&(room->state));
138
139 if (room->peer_message)
140 GNUNET_free (room->peer_message);
141
142 GNUNET_free (room);
143}
144
145
146struct GNUNET_MESSENGER_PeerStore*
147get_srv_room_peer_store (struct GNUNET_MESSENGER_SrvRoom *room)
148{
149 GNUNET_assert (room);
150
151 return &(room->peer_store);
152}
153
154
155struct GNUNET_MESSENGER_MemberStore*
156get_srv_room_member_store (struct GNUNET_MESSENGER_SrvRoom *room)
157{
158 GNUNET_assert (room);
159
160 return &(room->member_store);
161}
162
163
164struct GNUNET_MESSENGER_MessageStore*
165get_srv_room_message_store (struct GNUNET_MESSENGER_SrvRoom *room)
166{
167 GNUNET_assert (room);
168
169 return &(room->message_store);
170}
171
172
173struct GNUNET_MESSENGER_OperationStore*
174get_srv_room_operation_store (struct GNUNET_MESSENGER_SrvRoom *room)
175{
176 GNUNET_assert (room);
177
178 return &(room->operation_store);
179}
180
181
182static int
183send_room_info (struct GNUNET_MESSENGER_SrvRoom *room,
184 struct GNUNET_MESSENGER_SrvHandle *handle,
185 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
186{
187 if ((! handle) || (! is_tunnel_connected (tunnel)))
188 return GNUNET_NO;
189
190 return send_tunnel_message (tunnel, handle, create_message_info (
191 room->service));
192}
193
194
195static void*
196callback_room_connect (void *cls,
197 struct GNUNET_CADET_Channel *channel,
198 const struct GNUNET_PeerIdentity *source)
199{
200 struct GNUNET_MESSENGER_SrvRoom *room = cls;
201
202 struct GNUNET_MESSENGER_SrvTunnel *tunnel = create_tunnel (room, source);
203
204 if ((tunnel) &&
205 (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, source,
206 tunnel,
207 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)))
208 {
209 destroy_tunnel (tunnel);
210 tunnel = NULL;
211 }
212
213 if (! tunnel)
214 {
215 delayed_disconnect_channel (channel);
216 return NULL;
217 }
218
219 bind_tunnel (tunnel, channel);
220
221 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
222 "New tunnel in room (%s) established to peer: %s\n",
223 GNUNET_h2s (get_srv_room_key (room)), GNUNET_i2s (source));
224
225 if (GNUNET_YES == send_room_info (room, room->host, tunnel))
226 return tunnel;
227
228 disconnect_tunnel (tunnel);
229
230 if (GNUNET_YES == GNUNET_CONTAINER_multipeermap_remove (room->tunnels, source,
231 tunnel))
232 destroy_tunnel (tunnel);
233
234 return NULL;
235}
236
237
238static int
239join_room (struct GNUNET_MESSENGER_SrvRoom *room,
240 struct GNUNET_MESSENGER_SrvHandle *handle,
241 struct GNUNET_MESSENGER_Member *member)
242{
243 GNUNET_assert ((room) && (handle) && (member));
244
245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Joining room: %s (%s)\n", GNUNET_h2s (
246 get_srv_room_key (room)),
247 GNUNET_sh2s (get_member_id (member)));
248
249 const struct GNUNET_ShortHashCode *member_id = get_member_id (member);
250
251 if (GNUNET_OK != change_srv_handle_member_id (handle, get_srv_room_key (room),
252 member_id))
253 return GNUNET_NO;
254
255 notify_srv_handle_member_id (handle, room, member_id, GNUNET_YES);
256 return GNUNET_YES;
257}
258
259
260static int
261join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room,
262 struct GNUNET_MESSENGER_SrvHandle *handle)
263{
264 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (
265 handle, get_srv_room_key (room));
266
267 struct GNUNET_MESSENGER_MemberStore *member_store =
268 get_srv_room_member_store (room);
269 struct GNUNET_MESSENGER_Member *member = add_store_member (member_store,
270 member_id);
271
272 if (GNUNET_NO == join_room (room, handle, member))
273 return GNUNET_NO;
274
275 return GNUNET_YES;
276}
277
278
279extern int
280check_tunnel_message (void *cls,
281 const struct GNUNET_MessageHeader *header);
282
283extern void
284handle_tunnel_message (void *cls,
285 const struct GNUNET_MessageHeader *header);
286
287extern void
288callback_tunnel_disconnect (void *cls,
289 const struct GNUNET_CADET_Channel *channel);
290
291int
292open_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
293 struct GNUNET_MESSENGER_SrvHandle *handle)
294{
295 GNUNET_assert ((room) && (handle));
296
297 if (room->port)
298 return join_room_locally (room, handle);
299
300 struct GNUNET_CADET_Handle *cadet = get_srv_room_cadet (room);
301 const struct GNUNET_HashCode *key = get_srv_room_key (room);
302
303 struct GNUNET_MQ_MessageHandler handlers[] = { GNUNET_MQ_hd_var_size (
304 tunnel_message,
305 GNUNET_MESSAGE_TYPE_CADET_CLI,
306 struct
307 GNUNET_MessageHeader, NULL),
308 GNUNET_MQ_handler_end () };
309
310 struct GNUNET_HashCode port;
311 convert_messenger_key_to_port (key, &port);
312 room->port = GNUNET_CADET_open_port (cadet, &port, callback_room_connect,
313 room, NULL, callback_tunnel_disconnect,
314 handlers);
315
316 if (room->port)
317 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Port of room (%s) was opened!\n",
318 GNUNET_h2s (get_srv_room_key (room)));
319 else
320 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
321 "Port of room (%s) could not be opened!\n",
322 GNUNET_h2s (get_srv_room_key (room)));
323
324 const struct GNUNET_ShortHashCode *member_id = get_srv_handle_member_id (
325 handle, get_srv_room_key (room));
326
327 struct GNUNET_MESSENGER_MemberStore *member_store =
328 get_srv_room_member_store (room);
329 struct GNUNET_MESSENGER_Member *member = add_store_member (member_store,
330 member_id);
331
332 if ((GNUNET_NO == join_room (room, handle, member)) && (room->port))
333 {
334 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
335 "You could not join the room, therefore it keeps closed!\n");
336
337 GNUNET_CADET_close_port (room->port);
338 room->port = NULL;
339
340 return GNUNET_NO;
341 }
342
343 if (! room->port)
344 return GNUNET_NO;
345
346 return send_srv_room_message (room, handle, create_message_peer (
347 room->service));
348}
349
350
351int
352enter_srv_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
353 struct GNUNET_MESSENGER_SrvHandle *handle,
354 const struct GNUNET_PeerIdentity *door)
355{
356 GNUNET_assert ((room) && (handle) && (door));
357
358 struct GNUNET_PeerIdentity peer;
359
360 if ((GNUNET_OK == get_service_peer_identity (room->service, &peer)) &&
361 (0 == GNUNET_memcmp (&peer, door)))
362 return join_room_locally (room, handle);
363
364 struct GNUNET_MESSENGER_SrvTunnel *tunnel =
365 GNUNET_CONTAINER_multipeermap_get (room->tunnels, door);
366
367 if (! tunnel)
368 {
369 tunnel = create_tunnel (room, door);
370
371 if (GNUNET_OK != GNUNET_CONTAINER_multipeermap_put (room->tunnels, door,
372 tunnel,
373 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE))
374 {
375 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
376 "You could not connect to that door!\n");
377 destroy_tunnel (tunnel);
378 return GNUNET_NO;
379 }
380 }
381
382 if (GNUNET_SYSERR == connect_tunnel (tunnel))
383 {
384 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
385 "Connection failure during entrance!\n");
386 GNUNET_CONTAINER_multipeermap_remove (room->tunnels, door, tunnel);
387 destroy_tunnel (tunnel);
388 return GNUNET_NO;
389 }
390
391 return join_room_locally (room, handle);
392}
393
394
395static void
396sign_srv_room_message_by_peer (const void *cls,
397 struct GNUNET_MESSENGER_Message *message,
398 uint16_t length,
399 char *buffer,
400 const struct GNUNET_HashCode *hash)
401{
402 const struct GNUNET_MESSENGER_SrvHandle *handle = cls;
403
404 GNUNET_assert ((handle) && (handle->service));
405
406 sign_message_by_peer (message, length, buffer, hash, handle->service->config);
407}
408
409
410struct GNUNET_MQ_Envelope*
411pack_srv_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
412 const struct GNUNET_MESSENGER_SrvHandle *handle,
413 struct GNUNET_MESSENGER_Message *message,
414 struct GNUNET_HashCode *hash,
415 int mode)
416{
417 GNUNET_assert ((room) && (handle) && (message) && (hash));
418
419 if (GNUNET_YES != is_peer_message (message))
420 return pack_message (message, hash, NULL, mode, NULL);
421
422 message->header.timestamp = GNUNET_TIME_absolute_hton (
423 GNUNET_TIME_absolute_get ());
424
425 struct GNUNET_PeerIdentity peer;
426 if (GNUNET_OK != get_service_peer_identity (handle->service, &peer))
427 return NULL;
428
429 convert_peer_identity_to_id (&peer, &(message->header.sender_id));
430 get_message_state_chain_hash (&(room->state), &(message->header.previous));
431
432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
433 "Packing message with peer signature: %s\n",
434 GNUNET_sh2s (&(message->header.sender_id)));
435
436 message->header.signature.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA);
437 return pack_message (message, hash, sign_srv_room_message_by_peer, mode,
438 handle);
439}
440
441
442struct GNUNET_MESSENGER_ClosureSendRoom
443{
444 struct GNUNET_MESSENGER_SrvRoom *room;
445 struct GNUNET_MESSENGER_SrvHandle *handle;
446 struct GNUNET_MESSENGER_SrvTunnel *exclude;
447 struct GNUNET_MESSENGER_Message *message;
448 struct GNUNET_HashCode *hash;
449 int packed;
450};
451
452static int
453iterate_send_room_message (void *cls,
454 const struct GNUNET_PeerIdentity *key,
455 void *value)
456{
457 struct GNUNET_MESSENGER_SrvTunnel *tunnel = value;
458
459 if ((! is_tunnel_connected (tunnel)) ||
460 (get_tunnel_messenger_version (tunnel) < GNUNET_MESSENGER_VERSION))
461 return GNUNET_YES;
462
463 struct GNUNET_MESSENGER_ClosureSendRoom *closure = cls;
464
465 if (tunnel == closure->exclude)
466 return GNUNET_YES;
467
468 struct GNUNET_MQ_Envelope *env = NULL;
469
470 if (closure->packed == GNUNET_NO)
471 {
472 env = pack_srv_room_message (closure->room, closure->handle,
473 closure->message, closure->hash,
474 GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
475
476 if (env)
477 closure->packed = GNUNET_YES;
478 }
479 else
480 env = pack_message (closure->message, NULL, NULL,
481 GNUNET_MESSENGER_PACK_MODE_ENVELOPE, NULL);
482
483 if (env)
484 send_tunnel_envelope (tunnel, env, closure->hash);
485
486 return GNUNET_YES;
487}
488
489
490int
491update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
492 struct GNUNET_MESSENGER_Message *message,
493 const struct GNUNET_HashCode *hash);
494
495void
496callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
497 const struct GNUNET_MESSENGER_Message *message,
498 const struct GNUNET_HashCode *hash);
499
500int
501send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
502 struct GNUNET_MESSENGER_SrvHandle *handle,
503 struct GNUNET_MESSENGER_Message *message)
504{
505 GNUNET_assert ((room) && (handle));
506
507 if (! message)
508 return GNUNET_NO;
509
510 if (GNUNET_YES == is_message_session_bound (message))
511 merge_srv_room_last_messages (room, handle);
512
513
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
515 "Sending message from handle in room: %s (%s)\n",
516 GNUNET_h2s (&(room->key)),
517 GNUNET_MESSENGER_name_of_kind (message->header.kind));
518
519 struct GNUNET_HashCode hash;
520 struct GNUNET_MESSENGER_ClosureSendRoom closure;
521
522 closure.room = room;
523 closure.handle = handle;
524 closure.exclude = NULL;
525 closure.message = message;
526 closure.hash = &hash;
527 closure.packed = GNUNET_NO;
528
529 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels,
530 iterate_send_room_message, &closure);
531
532 if (GNUNET_NO == closure.packed)
533 pack_srv_room_message (room, handle, message, &hash,
534 GNUNET_MESSENGER_PACK_MODE_UNKNOWN);
535
536 const int new_message = update_room_message (room, message, &hash);
537
538 if (GNUNET_YES != new_message)
539 return GNUNET_SYSERR;
540
541 switch (message->header.kind)
542 {
543 case GNUNET_MESSENGER_KIND_JOIN:
544 send_message_join (room, handle, message, &hash);
545 break;
546 case GNUNET_MESSENGER_KIND_KEY:
547 send_message_key (room, handle, message, &hash);
548 break;
549 case GNUNET_MESSENGER_KIND_PEER:
550 send_message_peer (room, handle, message, &hash);
551 break;
552 case GNUNET_MESSENGER_KIND_ID:
553 send_message_id (room, handle, message, &hash);
554 break;
555 case GNUNET_MESSENGER_KIND_REQUEST:
556 send_message_request (room, handle, message, &hash);
557 break;
558 default:
559 break;
560 }
561
562 callback_room_handle_message (room, message, &hash);
563 return GNUNET_YES;
564}
565
566
567void
568forward_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
569 struct GNUNET_MESSENGER_SrvTunnel *tunnel,
570 struct GNUNET_MESSENGER_Message *message,
571 const struct GNUNET_HashCode *hash)
572{
573 GNUNET_assert ((room) && (tunnel));
574
575 if (! message)
576 return;
577
578 struct GNUNET_MESSENGER_ClosureSendRoom closure;
579 struct GNUNET_HashCode message_hash;
580
581 GNUNET_memcpy (&message_hash, hash, sizeof(struct GNUNET_HashCode));
582
583 closure.room = room;
584 closure.handle = NULL;
585 closure.exclude = tunnel;
586 closure.message = message;
587 closure.hash = &message_hash;
588 closure.packed = GNUNET_YES;
589
590 GNUNET_CONTAINER_multipeermap_iterate (room->tunnels,
591 iterate_send_room_message, &closure);
592}
593
594
595void
596check_srv_room_peer_status (struct GNUNET_MESSENGER_SrvRoom *room,
597 struct GNUNET_MESSENGER_SrvTunnel *tunnel)
598{
599 if (! room->peer_message)
600 return;
601
602 struct GNUNET_MESSENGER_MessageStore *message_store =
603 get_srv_room_message_store (room);
604
605 const struct GNUNET_MESSENGER_Message *message = get_store_message (
606 message_store, room->peer_message);
607
608 if (! message)
609 {
610 GNUNET_free (room->peer_message);
611 room->peer_message = NULL;
612 return;
613 }
614
615 if (tunnel)
616 forward_tunnel_message (tunnel, message, room->peer_message);
617}
618
619
620void
621merge_srv_room_last_messages (struct GNUNET_MESSENGER_SrvRoom *room,
622 struct GNUNET_MESSENGER_SrvHandle *handle)
623{
624 GNUNET_assert (room);
625
626 if (! handle)
627 return;
628
629 const struct GNUNET_HashCode *hash;
630
631merge_next:
632 hash = get_message_state_merge_hash (&(room->state));
633
634 if (! hash)
635 return;
636
637 send_srv_room_message (room, handle, create_message_merge (hash));
638 goto merge_next;
639}
640
641
642void
643callback_room_deletion (struct GNUNET_MESSENGER_SrvRoom *room,
644 const struct GNUNET_HashCode *hash)
645{
646 if (GNUNET_OK != delete_store_message (get_srv_room_message_store (room),
647 hash))
648 {
649 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Deletion of message failed! (%s)\n",
650 GNUNET_h2s (hash));
651 return;
652 }
653}
654
655
656void
657callback_room_merge (struct GNUNET_MESSENGER_SrvRoom *room,
658 const struct GNUNET_HashCode *hash)
659{
660 if (! room->host)
661 return;
662
663 send_srv_room_message (room, room->host, create_message_merge (hash));
664}
665
666
667int
668delete_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
669 struct GNUNET_MESSENGER_MemberSession *session,
670 const struct GNUNET_HashCode *hash,
671 const struct GNUNET_TIME_Relative delay)
672{
673 GNUNET_assert ((room) && (session) && (hash));
674
675 const struct GNUNET_TIME_Relative forever =
676 GNUNET_TIME_relative_get_forever_ ();
677
678 if (0 == GNUNET_memcmp (&forever, &delay))
679 {
680 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
681 "Deletion is delayed forever: operation is impossible!\n");
682 return GNUNET_SYSERR;
683 }
684
685 struct GNUNET_MESSENGER_MessageStore *message_store =
686 get_srv_room_message_store (room);
687
688 const struct GNUNET_MESSENGER_Message *message = get_store_message (
689 message_store, hash);
690
691 if (! message)
692 return GNUNET_YES;
693
694 if (GNUNET_YES != check_member_session_history (session, hash, GNUNET_YES))
695 {
696 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
697 "Unpermitted request for deletion by member (%s) of message (%s)!\n",
698 GNUNET_sh2s (get_member_session_id (session)), GNUNET_h2s (
699 hash));
700
701 return GNUNET_NO;
702 }
703
704 struct GNUNET_MESSENGER_OperationStore *operation_store =
705 get_srv_room_operation_store (room);
706
707 if (GNUNET_OK != use_store_operation (operation_store, hash,
708 GNUNET_MESSENGER_OP_DELETE, delay))
709 {
710 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
711 "Deletion has failed: operation denied!\n");
712 return GNUNET_SYSERR;
713 }
714
715 return GNUNET_YES;
716}
717
718
719struct GNUNET_CADET_Handle*
720get_srv_room_cadet (struct GNUNET_MESSENGER_SrvRoom *room)
721{
722 GNUNET_assert (room);
723
724 return room->service->cadet;
725}
726
727
728const struct GNUNET_HashCode*
729get_srv_room_key (const struct GNUNET_MESSENGER_SrvRoom *room)
730{
731 GNUNET_assert (room);
732
733 return &(room->key);
734}
735
736
737const struct GNUNET_MESSENGER_SrvTunnel*
738get_srv_room_tunnel (const struct GNUNET_MESSENGER_SrvRoom *room,
739 const struct GNUNET_PeerIdentity *peer)
740{
741 GNUNET_assert ((room) && (peer));
742
743 return GNUNET_CONTAINER_multipeermap_get (room->tunnels, peer);
744}
745
746
747static int
748request_room_message_step (struct GNUNET_MESSENGER_SrvRoom *room,
749 const struct GNUNET_HashCode *hash,
750 const struct GNUNET_MESSENGER_MemberSession *session,
751 GNUNET_MESSENGER_MessageRequestCallback callback,
752 void *cls)
753{
754 struct GNUNET_MESSENGER_MessageStore *message_store =
755 get_srv_room_message_store (room);
756
757 const struct GNUNET_MESSENGER_MessageLink *link = get_store_message_link (
758 message_store, hash, GNUNET_YES
759 );
760
761 if (! link)
762 goto forward;
763
764 int result = request_room_message_step (room, &(link->first), session,
765 callback, cls);
766
767 if ((GNUNET_YES == link->multiple) &&
768 (GNUNET_YES == request_room_message_step (room, &(link->second), session,
769 callback, cls)))
770 return GNUNET_YES;
771 else
772 return result;
773
774forward:
775 if (GNUNET_YES != check_member_session_history (session, hash, GNUNET_NO))
776 return GNUNET_YES;
777
778 const struct GNUNET_MESSENGER_Message *message = get_store_message (
779 message_store, hash);
780
781 if (! message)
782 return GNUNET_NO;
783
784 if (callback)
785 callback (cls, room, message, hash);
786
787 return GNUNET_YES;
788}
789
790
791int
792request_srv_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
793 const struct GNUNET_HashCode *hash,
794 const struct GNUNET_MESSENGER_MemberSession *session,
795 GNUNET_MESSENGER_MessageRequestCallback callback,
796 void *cls)
797{
798 GNUNET_assert ((room) && (hash));
799
800 int result = request_room_message_step (room, hash, session, callback, cls);
801
802 if ((GNUNET_NO == result) && (callback))
803 callback (cls, room, NULL, hash);
804
805 return result;
806}
807
808
809void
810callback_room_disconnect (struct GNUNET_MESSENGER_SrvRoom *room,
811 void *cls)
812{
813 struct GNUNET_MESSENGER_SrvTunnel *tunnel = cls;
814
815 if (! room->host)
816 return;
817
818 struct GNUNET_PeerIdentity identity;
819 get_tunnel_peer_identity (tunnel, &identity);
820
821 if ((GNUNET_YES != GNUNET_CONTAINER_multipeermap_remove (room->tunnels,
822 &identity,
823 tunnel)) ||
824 (GNUNET_YES == GNUNET_CONTAINER_multipeermap_contains (room->tunnels,
825 &identity)))
826 return;
827
828 if (GNUNET_YES == contains_list_tunnels (&(room->basement), &identity))
829 send_srv_room_message (room, room->host, create_message_miss (&identity));
830}
831
832
833int
834callback_verify_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
835 void *cls,
836 struct GNUNET_MESSENGER_Message *message,
837 struct GNUNET_HashCode *hash)
838{
839 if (GNUNET_MESSENGER_KIND_UNKNOWN == message->header.kind)
840 {
841 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
842 "Message error: Kind is unknown! (%d)\n", message->header.kind);
843 return GNUNET_SYSERR;
844 }
845
846 struct GNUNET_MESSENGER_MessageStore *message_store =
847 get_srv_room_message_store (room);
848
849 const struct GNUNET_MESSENGER_Message *previous = get_store_message (
850 message_store, &(message->header.previous));
851
852 if (! previous)
853 goto skip_time_comparison;
854
855 struct GNUNET_TIME_Absolute timestamp = GNUNET_TIME_absolute_ntoh (
856 message->header.timestamp);
857 struct GNUNET_TIME_Absolute last = GNUNET_TIME_absolute_ntoh (
858 previous->header.timestamp);
859
860 if (GNUNET_TIME_relative_get_zero_ ().rel_value_us !=
861 GNUNET_TIME_absolute_get_difference (timestamp, last).rel_value_us)
862 {
863 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
864 "Message warning: Timestamp does not check out!\n");
865 }
866
867skip_time_comparison:
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message of kind: %s!\n",
869 GNUNET_MESSENGER_name_of_kind (message->header.kind));
870
871 return GNUNET_OK;
872}
873
874
875static void
876idle_request_room_messages (void *cls)
877{
878 struct GNUNET_MESSENGER_SrvRoom *room = cls;
879
880 room->idle = NULL;
881
882 struct GNUNET_MESSENGER_OperationStore *operation_store =
883 get_srv_room_operation_store (room);
884 const struct GNUNET_HashCode *hash = get_message_state_merge_hash (
885 &(room->state));
886
887 if ((hash) &&
888 (GNUNET_MESSENGER_OP_UNKNOWN == get_store_operation_type (operation_store,
889 hash)))
890 use_store_operation (
891 operation_store,
892 hash,
893 GNUNET_MESSENGER_OP_MERGE,
894 GNUNET_MESSENGER_MERGE_DELAY
895 );
896
897 room->idle = GNUNET_SCHEDULER_add_delayed_with_priority (
898 GNUNET_MESSENGER_IDLE_DELAY,
899 GNUNET_SCHEDULER_PRIORITY_IDLE,
900 idle_request_room_messages,
901 cls
902 );
903}
904
905
906void
907solve_srv_room_member_collisions (struct GNUNET_MESSENGER_SrvRoom *room,
908 const struct
909 GNUNET_IDENTITY_PublicKey *public_key,
910 const struct GNUNET_ShortHashCode *member_id,
911 struct GNUNET_TIME_Absolute timestamp)
912{
913 GNUNET_assert ((room) && (public_key) && (member_id));
914
915 struct GNUNET_MESSENGER_MemberStore *member_store =
916 get_srv_room_member_store (room);
917 struct GNUNET_MESSENGER_Member *member = get_store_member (member_store,
918 member_id);
919
920 if ((! member) || (1 >= GNUNET_CONTAINER_multihashmap_size (
921 member->sessions)))
922 return;
923
924 struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
925 struct GNUNET_MESSENGER_ListHandle *element;
926
927 const struct GNUNET_IDENTITY_PublicKey *pubkey;
928
929 for (element = handles->head; element; element = element->next)
930 {
931 if (0 != GNUNET_memcmp (member_id, get_srv_handle_member_id (
932 element->handle, get_srv_room_key (room))))
933 continue;
934
935 pubkey = get_srv_handle_key (element->handle);
936
937 if (0 == GNUNET_memcmp (public_key, pubkey))
938 continue;
939
940 struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member,
941 pubkey);
942
943 if (! session)
944 continue;
945
946 struct GNUNET_TIME_Absolute start = get_member_session_start (session);
947
948 if (GNUNET_TIME_relative_get_zero_ ().rel_value_us !=
949 GNUNET_TIME_absolute_get_difference (start, timestamp).rel_value_us)
950 continue;
951
952 struct GNUNET_ShortHashCode random_id;
953 generate_free_member_id (&random_id, member_store->members);
954
955 notify_srv_handle_member_id (element->handle, room, &random_id, GNUNET_NO);
956 }
957}
958
959
960void
961rebuild_srv_room_basement_structure (struct GNUNET_MESSENGER_SrvRoom *room)
962{
963 GNUNET_assert (room);
964
965 struct GNUNET_PeerIdentity peer;
966 size_t src;
967
968 if ((GNUNET_OK != get_service_peer_identity (room->service, &peer)) ||
969 (! find_list_tunnels (&(room->basement), &peer, &src)))
970 return;
971
972 size_t count = count_of_tunnels (&(room->basement));
973
974 struct GNUNET_MESSENGER_ListTunnel *element = room->basement.head;
975 struct GNUNET_MESSENGER_SrvTunnel *tunnel;
976
977 size_t dst = 0;
978
979 while (element)
980 {
981 GNUNET_PEER_resolve (element->peer, &peer);
982
983 tunnel = GNUNET_CONTAINER_multipeermap_get (room->tunnels, &peer);
984
985 if (! tunnel)
986 {
987 element = remove_from_list_tunnels (&(room->basement), element);
988 continue;
989 }
990
991 if (GNUNET_YES == required_connection_between (count, src, dst))
992 {
993 if (GNUNET_SYSERR == connect_tunnel (tunnel))
994 {
995 element = remove_from_list_tunnels (&(room->basement), element);
996 continue;
997 }
998 }
999 else
1000 disconnect_tunnel (tunnel);
1001
1002 element = element->next;
1003 dst++;
1004 }
1005}
1006
1007
1008static void
1009handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
1010{
1011 struct GNUNET_MESSENGER_MessageStore *message_store =
1012 get_srv_room_message_store (room);
1013 struct GNUNET_MESSENGER_MemberStore *member_store =
1014 get_srv_room_member_store (room);
1015 struct GNUNET_MESSENGER_PeerStore *peer_store = get_srv_room_peer_store (
1016 room);
1017
1018 while (room->handling.head)
1019 {
1020 struct GNUNET_MESSENGER_ListMessage *element = room->handling.head;
1021
1022 const struct GNUNET_MESSENGER_Message *message = get_store_message (
1023 message_store, &(element->hash));
1024
1025 if (! message)
1026 goto finish_handling;
1027
1028 struct GNUNET_MESSENGER_SenderSession session;
1029
1030 if (GNUNET_YES == is_peer_message (message))
1031 {
1032 session.peer = get_store_peer_of (peer_store, message, &(element->hash));
1033
1034 if (! session.peer)
1035 goto finish_handling;
1036 }
1037 else
1038 {
1039 struct GNUNET_MESSENGER_Member *member = get_store_member_of (
1040 member_store, message);
1041
1042 if (! member)
1043 goto finish_handling;
1044
1045 session.member = get_member_session_of (member, message,
1046 &(element->hash));
1047
1048 if (! session.member)
1049 goto finish_handling;
1050 }
1051
1052 handle_service_message (room->service, room, &session, message,
1053 &(element->hash));
1054
1055finish_handling:
1056 GNUNET_CONTAINER_DLL_remove (room->handling.head, room->handling.tail,
1057 element);
1058 GNUNET_free (element);
1059 }
1060}
1061
1062
1063int
1064update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
1065 struct GNUNET_MESSENGER_Message *message,
1066 const struct GNUNET_HashCode *hash)
1067{
1068 GNUNET_assert ((room) && (message) && (hash));
1069
1070 struct GNUNET_MESSENGER_OperationStore *operation_store =
1071 get_srv_room_operation_store (room);
1072
1073 const int requested = (GNUNET_MESSENGER_OP_REQUEST ==
1074 get_store_operation_type (operation_store, hash)?
1075 GNUNET_YES : GNUNET_NO
1076 );
1077
1078 if (GNUNET_YES == requested)
1079 cancel_store_operation (operation_store, hash);
1080
1081 struct GNUNET_MESSENGER_MessageStore *message_store =
1082 get_srv_room_message_store (room);
1083
1084 const struct GNUNET_MESSENGER_Message *old_message = get_store_message (
1085 message_store, hash);
1086
1087 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handle a message in room (%s).\n",
1088 GNUNET_h2s (get_srv_room_key (room)));
1089
1090 if ((old_message) || (GNUNET_OK != put_store_message (message_store, hash,
1091 message)))
1092 {
1093 if (old_message != message)
1094 destroy_message (message);
1095
1096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Duplicate message got dropped!\n");
1097 return GNUNET_NO;
1098 }
1099
1100 update_message_state (&(room->state), requested, message, hash);
1101
1102 if ((GNUNET_YES == requested) ||
1103 (GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
1104 (GNUNET_MESSENGER_KIND_REQUEST == message->header.kind))
1105 return GNUNET_YES;
1106
1107 if ((GNUNET_MESSENGER_KIND_MERGE == message->header.kind) &&
1108 (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type (operation_store,
1109 &(message->body.
1110 merge.previous))))
1111 cancel_store_operation (operation_store, &(message->body.merge.previous));
1112
1113 if (GNUNET_MESSENGER_OP_MERGE == get_store_operation_type (operation_store,
1114 &(message->header.
1115 previous)))
1116 cancel_store_operation (operation_store, &(message->header.previous));
1117
1118 return GNUNET_YES;
1119}
1120
1121
1122struct GNUNET_MESSENGER_MemberSessionCompletion
1123{
1124 struct GNUNET_MESSENGER_MemberSessionCompletion *prev;
1125 struct GNUNET_MESSENGER_MemberSessionCompletion *next;
1126
1127 struct GNUNET_MESSENGER_MemberSession *session;
1128};
1129
1130struct GNUNET_MESSENGER_MemberUpdate
1131{
1132 const struct GNUNET_MESSENGER_Message *message;
1133 const struct GNUNET_HashCode *hash;
1134
1135 struct GNUNET_MESSENGER_MemberSessionCompletion *head;
1136 struct GNUNET_MESSENGER_MemberSessionCompletion *tail;
1137};
1138
1139static int
1140iterate_update_member_sessions (void *cls,
1141 const struct
1142 GNUNET_IDENTITY_PublicKey *public_key,
1143 struct GNUNET_MESSENGER_MemberSession *session)
1144{
1145 struct GNUNET_MESSENGER_MemberUpdate *update = cls;
1146
1147 update_member_session_history (session, update->message, update->hash);
1148
1149 if (GNUNET_YES == is_member_session_completed (session))
1150 {
1151 struct GNUNET_MESSENGER_MemberSessionCompletion *element = GNUNET_new (
1152 struct GNUNET_MESSENGER_MemberSessionCompletion
1153 );
1154
1155 element->session = session;
1156
1157 GNUNET_CONTAINER_DLL_insert_tail (update->head, update->tail, element);
1158 }
1159
1160 return GNUNET_YES;
1161}
1162
1163
1164static void
1165remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1166 struct GNUNET_MESSENGER_MemberSession *session);
1167
1168void
1169callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
1170 const struct GNUNET_MESSENGER_Message *message,
1171 const struct GNUNET_HashCode *hash)
1172{
1173 GNUNET_assert ((room) && (message) && (hash));
1174
1175 struct GNUNET_MESSENGER_PeerStore *peer_store = get_srv_room_peer_store (
1176 room);
1177 struct GNUNET_MESSENGER_MemberStore *member_store =
1178 get_srv_room_member_store (room);
1179
1180 struct GNUNET_MESSENGER_SenderSession session;
1181
1182 if (GNUNET_YES == is_peer_message (message))
1183 {
1184 session.peer = get_store_peer_of (peer_store, message, hash);
1185
1186 if (! session.peer)
1187 {
1188 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1189 "Message handling dropped: Peer is missing!\n");
1190 return;
1191 }
1192 }
1193 else
1194 {
1195 struct GNUNET_MESSENGER_Member *member = get_store_member_of (member_store,
1196 message);
1197
1198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n",
1199 GNUNET_h2s (hash));
1200
1201 if (! member)
1202 {
1203 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1204 "Message handling dropped: Member is missing!\n");
1205 return;
1206 }
1207
1208 session.member = get_member_session_of (member, message, hash);
1209
1210 if (! session.member)
1211 {
1212 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1213 "Message handling dropped: Session is missing!\n");
1214 return;
1215 }
1216 }
1217
1218 struct GNUNET_MESSENGER_MemberUpdate update;
1219 update.message = message;
1220 update.hash = hash;
1221
1222 update.head = NULL;
1223 update.tail = NULL;
1224
1225 iterate_store_members (member_store, iterate_update_member_sessions, &update);
1226
1227 while (update.head)
1228 {
1229 struct GNUNET_MESSENGER_MemberSessionCompletion *element = update.head;
1230
1231 remove_room_member_session (room, element->session);
1232
1233 GNUNET_CONTAINER_DLL_remove (update.head, update.tail, element);
1234 GNUNET_free (element);
1235 }
1236
1237 const int start_handle = room->handling.head ? GNUNET_NO : GNUNET_YES;
1238
1239 add_to_list_messages (&(room->handling), hash);
1240
1241 switch (message->header.kind)
1242 {
1243 case GNUNET_MESSENGER_KIND_JOIN:
1244 handle_message_join (room, &session, message, hash);
1245 break;
1246 case GNUNET_MESSENGER_KIND_LEAVE:
1247 handle_message_leave (room, &session, message, hash);
1248 break;
1249 case GNUNET_MESSENGER_KIND_NAME:
1250 handle_message_name (room, &session, message, hash);
1251 break;
1252 case GNUNET_MESSENGER_KIND_KEY:
1253 handle_message_key (room, &session, message, hash);
1254 break;
1255 case GNUNET_MESSENGER_KIND_PEER:
1256 handle_message_peer (room, &session, message, hash);
1257 break;
1258 case GNUNET_MESSENGER_KIND_ID:
1259 handle_message_id (room, &session, message, hash);
1260 break;
1261 case GNUNET_MESSENGER_KIND_MISS:
1262 handle_message_miss (room, &session, message, hash);
1263 break;
1264 case GNUNET_MESSENGER_KIND_DELETE:
1265 handle_message_delete (room, &session, message, hash);
1266 break;
1267 default:
1268 break;
1269 }
1270
1271 if (GNUNET_YES == start_handle)
1272 handle_room_messages (room);
1273}
1274
1275
1276static void
1277get_room_data_subdir (struct GNUNET_MESSENGER_SrvRoom *room,
1278 char **dir)
1279{
1280 GNUNET_assert ((room) && (dir));
1281
1282 GNUNET_asprintf (dir, "%s%s%c%s%c", room->service->dir, "rooms",
1283 DIR_SEPARATOR, GNUNET_h2s (get_srv_room_key (room)),
1284 DIR_SEPARATOR);
1285}
1286
1287
1288void
1289load_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1290{
1291 GNUNET_assert (room);
1292
1293 char *room_dir;
1294 get_room_data_subdir (room, &room_dir);
1295
1296 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1297 {
1298 load_member_store (get_srv_room_member_store (room), room_dir);
1299 load_message_store (get_srv_room_message_store (room), room_dir);
1300 load_operation_store (get_srv_room_operation_store (room), room_dir);
1301
1302 char *basement_file;
1303 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1304
1305 load_list_tunnels (&(room->basement), basement_file);
1306 GNUNET_free (basement_file);
1307
1308 load_message_state (&(room->state), room_dir);
1309 }
1310
1311 GNUNET_free (room_dir);
1312}
1313
1314
1315void
1316save_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1317{
1318 GNUNET_assert (room);
1319
1320 char *room_dir;
1321 get_room_data_subdir (room, &room_dir);
1322
1323 if ((GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_NO)) ||
1324 (GNUNET_OK == GNUNET_DISK_directory_create (room_dir)))
1325 {
1326 save_member_store (get_srv_room_member_store (room), room_dir);
1327 save_message_store (get_srv_room_message_store (room), room_dir);
1328 save_operation_store (get_srv_room_operation_store (room), room_dir);
1329
1330 char *basement_file;
1331 GNUNET_asprintf (&basement_file, "%s%s", room_dir, "basement.list");
1332
1333 save_list_tunnels (&(room->basement), basement_file);
1334 GNUNET_free (basement_file);
1335
1336 save_message_state (&(room->state), room_dir);
1337 }
1338
1339 GNUNET_free (room_dir);
1340}
1341
1342
1343void
1344remove_srv_room (struct GNUNET_MESSENGER_SrvRoom *room)
1345{
1346 GNUNET_assert (room);
1347
1348 char *room_dir;
1349 get_room_data_subdir (room, &room_dir);
1350
1351 if (GNUNET_YES == GNUNET_DISK_directory_test (room_dir, GNUNET_YES))
1352 GNUNET_DISK_directory_remove (room_dir);
1353
1354 GNUNET_free (room_dir);
1355}
1356
1357
1358static void
1359remove_room_member_session (struct GNUNET_MESSENGER_SrvRoom *room,
1360 struct GNUNET_MESSENGER_MemberSession *session)
1361{
1362 GNUNET_assert ((room) && (session));
1363
1364 remove_member_session (session->member, session);
1365
1366 const struct GNUNET_IDENTITY_PublicKey *public_key =
1367 get_member_session_public_key (session);
1368
1369 struct GNUNET_HashCode hash;
1370 GNUNET_CRYPTO_hash (public_key, sizeof(*public_key), &hash);
1371
1372 char *room_dir;
1373 get_room_data_subdir (room, &room_dir);
1374
1375 char *session_dir;
1376 GNUNET_asprintf (
1377 &session_dir, "%s%s%c%s%c%s%c%s%c", room_dir,
1378 "members", DIR_SEPARATOR,
1379 GNUNET_sh2s (get_member_session_id (session)), DIR_SEPARATOR,
1380 "sessions", DIR_SEPARATOR,
1381 GNUNET_h2s (&hash), DIR_SEPARATOR
1382 );
1383
1384 GNUNET_free (room_dir);
1385
1386 GNUNET_DISK_directory_remove (session_dir);
1387 GNUNET_free (session_dir);
1388
1389 destroy_member_session (session);
1390}