GNUnet debian-0.24.3-23-g589b01d60
messenger_api_epoch.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2024--2025 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 */
26#include "messenger_api_epoch.h"
27
28#include "gnunet_common.h"
30#include "gnunet_util_lib.h"
31#include "messenger_api.h"
36#include "messenger_api_room.h"
37#include <stdint.h>
38
39static const struct GNUNET_MESSENGER_Contact**
41 const struct GNUNET_HashCode *epoch,
42 uint32_t *members_count)
43{
44 const struct GNUNET_MESSENGER_Message *message;
45 const struct GNUNET_MESSENGER_Contact **members;
46 uint32_t allocation_count;
47 uint32_t count;
48
49 GNUNET_assert ((room) && (epoch) && (members_count));
50
51 message = get_room_message (room, epoch);
52
53 if (! message)
54 return NULL;
55
56 switch (message->header.kind)
57 {
59 {
60 struct GNUNET_MESSENGER_Epoch *previous;
61 const struct GNUNET_MESSENGER_Contact *contact;
62
63 contact = get_room_sender (room, epoch);
64
65 if (! contact)
66 return NULL;
67
68 if (GNUNET_is_zero (&(message->body.join.epoch)))
69 {
70 allocation_count = 1;
71 count = 0;
72
73 members = GNUNET_malloc (
74 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
75
76 if (! members)
77 return NULL;
78
79 members[count++] = contact;
80
81 *members_count = count;
82 return members;
83 }
84
85 previous = get_room_epoch (
86 room, &(message->body.join.epoch), GNUNET_NO);
87
88 if ((previous) && (previous->members))
89 {
90 allocation_count = previous->members_count + 1;
91
92 for (count = 0; count < previous->members_count; count++)
93 {
94 if (previous->members[count] == contact)
95 {
96 allocation_count = previous->members_count;
97 break;
98 }
99 }
100
101 members = GNUNET_malloc (
102 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
103
104 if (! members)
105 return NULL;
106
107 for (count = 0; count < previous->members_count; count++)
108 members[count] = previous->members[count];
109
110 if (count < allocation_count)
111 members[count++] = contact;
112
113 *members_count = count;
114 return members;
115 }
116
117 break;
118 }
120 {
121 struct GNUNET_MESSENGER_Epoch *previous;
122 const struct GNUNET_MESSENGER_Contact *contact;
123
124 previous = get_room_epoch (
125 room, &(message->body.leave.epoch), GNUNET_NO);
126 contact = get_room_sender (room, epoch);
127
128 if ((previous) && (previous->members) && (contact))
129 {
130 uint32_t index;
131
132 allocation_count = previous->members_count > 1?
133 previous->members_count - 1 : 1;
134 count = 0;
135
136 members = GNUNET_malloc (
137 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
138
139 if (! members)
140 return NULL;
141
142 for (index = 0; index < previous->members_count; index++)
143 if (previous->members[index] != contact)
144 members[count++] = previous->members[index];
145
146 *members_count = count;
147 return members;
148 }
149 }
151 {
152 struct GNUNET_MESSENGER_Epoch *prev0;
153 struct GNUNET_MESSENGER_Epoch *prev1;
154
155 prev0 = get_room_epoch (room, &(message->body.merge.epochs[0]),
156 GNUNET_NO);
157 prev1 = get_room_epoch (room, &(message->body.merge.epochs[1]),
158 GNUNET_NO);
159
160 if ((prev0) && (prev1) && (prev0->members) && (prev1->members))
161 {
163 uint32_t duplicates;
164 uint32_t index;
165
166 allocation_count = prev0->members_count + prev1->members_count;
167 duplicates = 0;
168
169 for (index = 0; index < prev0->members_count; index++)
170 {
171 for (count = 0; count < prev1->members_count; count++)
172 {
173 if (prev1->members[count] == prev0->members[index])
174 {
175 duplicates++;
176 break;
177 }
178 }
179 }
180
181 if (! allocation_count)
182 return NULL;
183
184 if (allocation_count > duplicates)
185 allocation_count -= duplicates;
186 else
187 allocation_count = 1;
188
190 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
191
192 if (! members)
193 return NULL;
194
195 count = 0;
196
197 for (index = 0; index < prev0->members_count; index++)
198 members[count++] = prev0->members[index];
199
200 for (index = 0; index < prev1->members_count; index++)
201 {
202 drop = GNUNET_NO;
203
204 for (duplicates = 0; duplicates < prev0->members_count; duplicates++
205 )
206 {
207 if (prev0->members[duplicates] == prev1->members[index])
208 {
209 drop = GNUNET_YES;
210 break;
211 }
212 }
213
214 if (GNUNET_YES == drop)
215 continue;
216
217 members[count++] = prev1->members[index];
218 }
219
220 *members_count = count;
221 return members;
222 }
223 else if ((prev0) && (! prev1) && (prev0->members))
224 {
225 uint32_t index;
226
227 allocation_count = prev0->members_count;
228
230 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
231
232 if (! members)
233 return NULL;
234
235 count = 0;
236
237 for (index = 0; index < prev0->members_count; index++)
238 members[count++] = prev0->members[index];
239
240 *members_count = count;
241 return members;
242 }
243 else if ((! prev0) && (prev1) && (prev1->members))
244 {
245 uint32_t index;
246
247 allocation_count = prev1->members_count;
248
250 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
251
252 if (! members)
253 return NULL;
254
255 count = 0;
256
257 for (index = 0; index < prev1->members_count; index++)
258 members[count++] = prev1->members[index];
259
260 *members_count = count;
261 return members;
262 }
263 }
264 default:
265 break;
266 }
267
268 return NULL;
269}
270
271
272static void
274 struct GNUNET_MESSENGER_Epoch *follow)
275{
276 struct GNUNET_MESSENGER_Epoch **follows;
277 uint32_t count;
278 uint32_t i;
279
280 GNUNET_assert ((epoch) && (follow));
281
282 if (epoch == follow)
283 return;
284
285 for (i = 0; i < epoch->following_count; i++)
286 {
287 if (epoch->following[i] == follow)
288 return;
289 }
290
291 count = epoch->following_count + 1;
292 follows = GNUNET_malloc (sizeof (struct GNUNET_MESSENGER_Epoch*) * count);
293
294 if (! follows)
295 return;
296
297 for (i = 0; i < epoch->following_count; i++)
298 follows[i] = epoch->following[i];
299
300 follows[epoch->following_count] = follow;
301
302 if (epoch->following)
303 GNUNET_free (epoch->following);
304
305 epoch->following_count = count;
306 epoch->following = follows;
307}
308
309
310static void
312{
313 const struct GNUNET_MESSENGER_Message *message;
314 struct GNUNET_MESSENGER_Epoch *previous;
315
316 GNUNET_assert (epoch);
317
318 message = get_room_message (epoch->room, &(epoch->hash));
319
320 if (! message)
321 return;
322
323 switch (message->header.kind)
324 {
326 {
327 previous = get_room_epoch (epoch->room,
328 &(message->body.join.epoch),
329 GNUNET_NO);
330
331 if (previous)
332 add_following_epoch (previous, epoch);
333 break;
334 }
336 {
337 previous = get_room_epoch (epoch->room,
338 &(message->body.leave.epoch),
339 GNUNET_NO);
340
341 if (previous)
342 add_following_epoch (previous, epoch);
343 break;
344 }
346 {
347 previous = get_room_epoch (epoch->room,
348 &(message->body.merge.epochs[0]),
349 GNUNET_NO);
350
351 if (previous)
352 add_following_epoch (previous, epoch);
353
354 previous = get_room_epoch (epoch->room,
355 &(message->body.merge.epochs[1]),
356 GNUNET_NO);
357
358 if (previous)
359 add_following_epoch (previous, epoch);
360 break;
361 }
362 default:
363 return;
364 }
365}
366
367
370 const struct GNUNET_HashCode *hash)
371{
372 struct GNUNET_MESSENGER_Epoch *epoch;
373
374 GNUNET_assert ((room) && (hash));
375
376 if (GNUNET_is_zero (hash))
377 return NULL;
378
379 epoch = GNUNET_new (struct GNUNET_MESSENGER_Epoch);
380
381 if (! epoch)
382 return NULL;
383
385
386 GNUNET_memcpy (&(epoch->hash), hash, sizeof (epoch->hash));
389
390 epoch->room = room;
391 epoch->private_key = NULL;
392
394 8, GNUNET_NO);
395
397 1, GNUNET_NO);
398
400 1, GNUNET_NO);
401
403 1, GNUNET_NO);
404
405 epoch->members_count = 0;
406 epoch->members = NULL;
407
408 epoch->main_announcement = NULL;
409 epoch->main_group = NULL;
410
411 memset (&(epoch->proposal_hash), 0, sizeof (epoch->proposal_hash));
412 epoch->proposal_timeout = NULL;
413
414 epoch->following_count = 0;
415 epoch->following = NULL;
416
417 reset_epoch_size (epoch);
418
419 return epoch;
420}
421
422
425 const struct GNUNET_HashCode *epoch,
426 const struct GNUNET_MESSENGER_Contact *contact);
427
428static const struct GNUNET_MESSENGER_Contact**
430 const struct GNUNET_HashCode *epoch,
431 uint32_t *members_count)
432{
434 const struct GNUNET_MESSENGER_Contact **members;
435 uint32_t allocation_count;
436 uint32_t count;
437
438 GNUNET_assert ((room) && (epoch) && (members_count));
439
440 members = get_members_of_epoch (room, epoch, members_count);
441
442 if (members)
443 return members;
444
445 allocation_count = GNUNET_CONTAINER_multishortmap_size (room->members);
446 count = 0;
447
449
450 if (it)
451 {
452 struct GNUNET_ShortHashCode member_id;
453 const struct GNUNET_MESSENGER_Contact *member;
454
455 members = GNUNET_malloc (
456 allocation_count * sizeof (const struct GNUNET_MESSENGER_Contact*));
457
458 if (! members)
459 goto skip_iterator;
460
462 member_id,
463 (const
464 void**)
465 &member))
466 {
467 if (GNUNET_YES == is_epoch_member_in_room (room, epoch, member))
468 members[count++] = member;
469 }
470
471skip_iterator:
473 }
474
475 GNUNET_assert (allocation_count >= count);
476
477 *members_count = count;
478 return members;
479}
480
481
484 const struct GNUNET_ShortHashCode *key
485 ,
486 void *value)
487{
488 struct GNUNET_MESSENGER_Epoch *epoch;
489 struct GNUNET_MESSENGER_EpochGroup *group;
490
491 GNUNET_assert ((cls) && (value));
492
493 epoch = cls;
494 group = value;
495
496 if ((GNUNET_YES != group->valid) ||
497 (! get_epoch_group_key (group)) ||
500 return GNUNET_YES;
501
503 return GNUNET_YES;
504}
505
506
509 const struct GNUNET_HashCode *hash)
510{
511 const struct GNUNET_MESSENGER_Contact **members;
512 struct GNUNET_MESSENGER_Epoch *epoch;
513 uint32_t members_count;
514
515 GNUNET_assert ((room) && (hash));
516
518
519 if (! members)
520 return NULL;
521
522 epoch = create_epoch (room, hash);
523
524 if (! epoch)
525 {
526 if (members)
528
529 return NULL;
530 }
531
533 epoch->members = members;
534
535 {
536 const struct GNUNET_MESSENGER_EpochGroup *previous;
537
538 previous = get_epoch_previous_group (epoch, NULL);
539
540 if ((! previous) || (GNUNET_YES != previous->valid) ||
541 (! get_epoch_group_key (previous)) ||
543 return epoch;
544
547 epoch);
548
551
552 if (epoch->main_group)
554 }
555
556 return epoch;
557}
558
559
562 const struct GNUNET_ShortHashCode *key,
563 void *value)
564{
565 struct GNUNET_MESSENGER_EpochGroup *group;
566
568
569 group = value;
570
571 destroy_epoch_group (group);
572 return GNUNET_YES;
573}
574
575
578 const struct GNUNET_ShortHashCode *key,
579 void *value)
580{
581 struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
582
584
585 announcement = value;
586
587 destroy_epoch_announcement (announcement);
588 return GNUNET_YES;
589}
590
591
592void
594{
596
598 {
600 epoch->proposal_timeout = NULL;
601 }
602
603 memset (&(epoch->proposal_hash), 0, sizeof (epoch->proposal_hash));
604
605 epoch->main_group = NULL;
606 epoch->main_announcement = NULL;
607
608 if (epoch->nonces)
610
611 if (epoch->groups)
612 {
615 NULL);
616
618 }
619
620 if (epoch->announcements)
621 {
624 NULL);
625
627 }
628
629 if (epoch->waiting)
631
632 if (epoch->following)
634
635 if (epoch->members)
637
638 if (epoch->private_key)
640
642}
643
644
645uint32_t
647{
649
650 return epoch->members_count;
651}
652
653
656 const struct GNUNET_HashCode *key,
657 GNUNET_UNUSED void *value)
658{
659 struct GNUNET_MESSENGER_Epoch *epoch;
660
661 GNUNET_assert ((cls) && (key));
662
663 epoch = cls;
664
665 update_room_message (epoch->room, key);
666 return GNUNET_YES;
667}
668
669
670void
672{
673 const struct GNUNET_MESSENGER_Contact **members;
674 uint32_t members_count;
675 uint32_t i;
676
677 GNUNET_assert (epoch);
678
680
681 members = get_members_of_epoch (
682 epoch->room, &(epoch->hash), &members_count);
683
684 if (! members)
685 return;
686
687 if (epoch->members)
688 GNUNET_free (epoch->members);
689
690 epoch->members_count = members_count;
691 epoch->members = members;
692
696
697 for (i = 0; i < epoch->following_count; i++)
698 reset_epoch_size (epoch->following[i]);
699}
700
701
704 const struct GNUNET_HashCode *hash)
705{
706 GNUNET_assert ((epoch) && (hash));
707
708 if (epoch->members)
709 return GNUNET_NO;
710
712 epoch->waiting, hash))
713 return GNUNET_YES;
714
716 epoch->waiting, hash, NULL,
718 return GNUNET_SYSERR;
719 else
720 return GNUNET_YES;
721}
722
723
726 const struct GNUNET_TIME_Relative timeout)
727{
728 GNUNET_assert (epoch);
729
730 if (epoch->private_key)
731 return epoch->private_key;
732
734
735 if (! epoch->private_key)
736 return NULL;
737
739
742
743 return epoch->private_key;
744}
745
746
747const struct GNUNET_TIME_Relative
749{
750 GNUNET_assert (epoch);
751
752 if (! epoch->private_key)
754
755 return GNUNET_TIME_absolute_get_remaining (epoch->private_key_expiration);
756}
757
758
762 announcement,
763 const struct
765{
766 uint32_t count;
767 uint32_t max;
768
769 if (! other)
770 return GNUNET_NO;
771 if (! announcement)
772 return GNUNET_YES;
773
776
777 if (count > max)
778 return GNUNET_YES;
779 else if (count < max)
780 return GNUNET_NO;
781
782 if (0 < GNUNET_memcmp (&(other->identifier), &(announcement->identifier)))
783 return GNUNET_YES;
784 else
785 return GNUNET_NO;
786}
787
788
791 const struct GNUNET_ShortHashCode *key,
792 void *value)
793{
795 struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
796
797 GNUNET_assert ((cls) && (key) && (value));
798
799 result = cls;
800 announcement = value;
801
803 *result = announcement;
804
805 return GNUNET_YES;
806}
807
808
811 const struct
813 void *value)
814{
815 struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
816
817 GNUNET_assert ((cls) && (key) && (value));
818
819 announcement = value;
820
821 if ((GNUNET_YES != announcement->valid) ||
822 (! get_epoch_announcement_key (announcement)))
823 return GNUNET_YES;
824
826}
827
828
834{
835 struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
837
839
840 announcement = NULL;
841
842 if (GNUNET_YES == valid)
844 else
846
847 if (identifier)
848 {
850 &(identifier->hash),
851 iterator,
852 &announcement);
853
854 if ((announcement) || (GNUNET_SYSERR == valid))
855 return announcement;
856
858
859 if (! announcement)
860 return NULL;
861
863 &(identifier->hash),
864 announcement,
866 {
867 destroy_epoch_announcement (announcement);
868 return NULL;
869 }
870
871 if ((GNUNET_YES == valid) && (GNUNET_YES != announcement->valid))
872 return NULL;
873 }
874 else
876 iterator,
877 &announcement);
878
879 return announcement;
880}
881
882
885 const struct GNUNET_MESSENGER_EpochGroup *other)
886{
887 uint32_t count;
888 uint32_t max;
889
890 if (! other)
891 return GNUNET_NO;
892 if (! group)
893 return GNUNET_YES;
894
895 count = get_epoch_group_members_count (other);
897
898 if (count > max)
899 return GNUNET_YES;
900 else if (count < max)
901 return GNUNET_NO;
902
903 if (0 < GNUNET_memcmp (&(other->identifier), &(group->identifier)))
904 return GNUNET_YES;
905 else
906 return GNUNET_NO;
907}
908
909
912 const struct GNUNET_ShortHashCode *key,
913 void *value)
914{
916 struct GNUNET_MESSENGER_EpochGroup *group;
917
918 GNUNET_assert ((cls) && (key) && (value));
919
920 result = cls;
921 group = value;
922
924 *result = group;
925
926 return GNUNET_YES;
927}
928
929
932 const struct GNUNET_ShortHashCode *key,
933 void *value)
934{
935 struct GNUNET_MESSENGER_EpochGroup *group;
936
937 GNUNET_assert ((cls) && (key) && (value));
938
939 group = value;
940
941 if ((GNUNET_YES != group->valid) ||
942 (! get_epoch_group_key (group)))
943 return GNUNET_YES;
944
946}
947
948
953{
954 struct GNUNET_MESSENGER_EpochGroup *group;
956
958
959 group = NULL;
960
961 if (GNUNET_YES == valid)
963 else
965
966 if (identifier)
967 {
969 &(identifier->hash),
970 iterator,
971 &group);
972
973 if ((group) || (GNUNET_SYSERR == valid))
974 return group;
975
978 valid);
979
980 if (! group)
981 return NULL;
982
984 &(identifier->hash),
985 group,
987 {
988 destroy_epoch_group (group);
989 return NULL;
990 }
991 }
992 else
994 iterator,
995 &group);
996
997 return group;
998}
999
1000
1003 const struct GNUNET_MESSENGER_Epoch *other)
1004{
1005 const struct GNUNET_MESSENGER_Message *message;
1006
1007 GNUNET_assert ((epoch) && (other));
1008
1009 if (epoch->room != other->room)
1010 return GNUNET_NO;
1011
1012 message = get_room_message (other->room, &(other->hash));
1013
1014 if (! message)
1015 return GNUNET_SYSERR;
1016
1017 switch (message->header.kind)
1018 {
1020 return 0 == GNUNET_CRYPTO_hash_cmp (&(epoch->hash), &(message->body.join.
1021 epoch))?
1024 return 0 == GNUNET_CRYPTO_hash_cmp (&(epoch->hash), &(message->body.leave.
1025 epoch))?
1028 if (0 == GNUNET_CRYPTO_hash_cmp (&(epoch->hash), &(message->body.merge.
1029 epochs[0])))
1030 return GNUNET_YES;
1031
1032 if (0 == GNUNET_CRYPTO_hash_cmp (&(epoch->hash), &(message->body.merge.
1033 epochs[1])))
1034 return GNUNET_YES;
1035
1036 return GNUNET_NO;
1037 default:
1038 return GNUNET_SYSERR;
1039 }
1040}
1041
1042
1046 identifier)
1047{
1048 const struct GNUNET_MESSENGER_Message *message;
1049 struct GNUNET_MESSENGER_Epoch *previous;
1050 const struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
1051
1053
1054 message = get_room_message (epoch->room, &(epoch->hash));
1055
1056 if ((! message) || (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind))
1057 return NULL;
1058
1059 previous = get_room_message_epoch (epoch->room,
1060 &(message->header.previous));
1061
1062 if (epoch == previous)
1063 return NULL;
1064
1065 if (previous)
1066 announcement = get_epoch_announcement (previous, identifier,
1068 else
1069 announcement = NULL;
1070
1071 if ((! announcement) ||
1072 (announcement->epoch == epoch) ||
1073 (0 == GNUNET_CRYPTO_hash_cmp (&(announcement->epoch->hash),
1074 &(epoch->hash))))
1075 return NULL;
1076
1077 return announcement;
1078}
1079
1080
1081const struct GNUNET_MESSENGER_EpochGroup*
1084 identifier)
1085{
1086 const struct GNUNET_MESSENGER_Message *message;
1087 struct GNUNET_MESSENGER_Epoch *previous;
1088 const struct GNUNET_MESSENGER_EpochGroup *group;
1089
1091
1092 message = get_room_message (epoch->room, &(epoch->hash));
1093
1094 if (! message)
1095 return NULL;
1096
1097 previous = get_room_message_epoch (epoch->room, &(message->header.previous));
1098
1099 if (epoch == previous)
1100 return NULL;
1101
1102 if (previous)
1103 group = get_epoch_group (previous,
1104 identifier,
1105 identifier?
1107 else
1108 group = NULL;
1109
1110 if (GNUNET_MESSENGER_KIND_MERGE == message->header.kind)
1111 {
1112 struct GNUNET_MESSENGER_Epoch *other;
1113 const struct GNUNET_MESSENGER_EpochGroup *other_group;
1114
1115 other = get_room_message_epoch (
1116 epoch->room,
1117 &(message->body.merge.previous));
1118
1119 if (previous == other)
1120 goto skip_merge;
1121
1122 if (other)
1123 other_group = get_epoch_group (other, identifier, GNUNET_SYSERR);
1124 else
1125 other_group = NULL;
1126
1127 if (GNUNET_YES == is_other_epoch_group_better (group, other_group))
1128 group = other_group;
1129 }
1130
1131skip_merge:
1132 if ((group) && ((group->epoch == epoch) ||
1133 (0 == GNUNET_CRYPTO_hash_cmp (&(group->epoch->hash),
1134 &(epoch->hash)))))
1135 return NULL;
1136
1137 return group;
1138}
1139
1140
1141static int
1142compare_member_public_keys (const char *key_string,
1143 const struct GNUNET_CRYPTO_PublicKey *key)
1144{
1145 char *str;
1146 int result;
1147
1148 GNUNET_assert ((key_string) && (key));
1149
1151 if (! str)
1152 return 0;
1153
1154 result = strcmp (key_string, str);
1155
1156 GNUNET_free (str);
1157 return result;
1158}
1159
1160
1161uint32_t
1163 const struct GNUNET_MESSENGER_Contact *contact)
1164{
1165 const struct GNUNET_CRYPTO_PublicKey *key;
1166 char *key_string;
1167 uint32_t position;
1168 uint32_t i;
1169 int result;
1170
1171 GNUNET_assert ((epoch) && (contact));
1172
1173 key = get_contact_key (contact);
1175
1176 if (! key_string)
1177 return epoch->members_count;
1178
1179 position = 0;
1180
1181 for (i = 0; i < epoch->members_count; i++)
1182 {
1184 key_string, get_contact_key (epoch->members[i]));
1185
1186 if ((0 < result) ||
1187 ((0 == result) && (contact->id < epoch->members[i]->id)))
1188 position++;
1189 }
1190
1191 GNUNET_free (key_string);
1192 return position;
1193}
1194
1195
1196static enum GNUNET_GenericReturnValue
1198 const struct GNUNET_HashCode *epoch,
1199 const struct GNUNET_MESSENGER_Contact *contact)
1200{
1202
1203 GNUNET_assert ((room) && (epoch) && (contact));
1204
1206
1207 if (! entry)
1208 return GNUNET_SYSERR;
1209
1210 if (contact == entry->sender)
1211 return GNUNET_YES;
1212
1213 if (! entry->sender)
1214 return GNUNET_NO;
1215
1216 return GNUNET_NO;
1217}
1218
1219
1220static enum GNUNET_GenericReturnValue
1222 const struct GNUNET_HashCode *epoch,
1223 const struct GNUNET_MESSENGER_Contact *contact,
1225{
1226 const struct GNUNET_MESSENGER_Message *message;
1227 const struct GNUNET_HashCode *previous;
1228
1229 GNUNET_assert ((room) && (epoch) && (contact) && (map));
1230
1232 return GNUNET_NO;
1233
1234 message = get_room_message (room, epoch);
1235
1236 if (! message)
1237 return GNUNET_NO;
1238
1241
1242 switch (message->header.kind)
1243 {
1245 if (GNUNET_YES == is_epoch_sender_in_room (room, epoch, contact))
1246 return GNUNET_YES;
1247
1248 previous = &(message->body.join.epoch);
1249 break;
1251 if (GNUNET_YES == is_epoch_sender_in_room (room, epoch, contact))
1252 return GNUNET_NO;
1253
1254 previous = &(message->body.leave.epoch);
1255 break;
1257 previous = &(message->body.merge.epochs[0]);
1258
1259 if ((previous) &&
1260 (GNUNET_YES == is_epoch_member_in_room_graph (room, previous, contact,
1261 map)))
1262 return GNUNET_YES;
1263
1264 previous = &(message->body.merge.epochs[1]);
1265 break;
1266 default:
1267 previous = NULL;
1268 break;
1269 }
1270
1271 if (! previous)
1272 return GNUNET_NO;
1273
1274 return is_epoch_member_in_room_graph (room, previous, contact, map);
1275}
1276
1277
1278static enum GNUNET_GenericReturnValue
1280 const struct GNUNET_HashCode *epoch,
1281 const struct GNUNET_MESSENGER_Contact *contact)
1282{
1285
1286 GNUNET_assert ((room) && (epoch) && (contact));
1287
1288 if (GNUNET_is_zero (epoch))
1289 return GNUNET_NO;
1290
1292
1293 if (! map)
1294 return GNUNET_NO;
1295
1296 result = is_epoch_member_in_room_graph (room, epoch, contact, map);
1297
1299 return result;
1300}
1301
1302
1305 const struct GNUNET_MESSENGER_Contact *contact)
1306{
1307 uint32_t i;
1308
1309 GNUNET_assert ((epoch) && (contact));
1310
1311 for (i = 0; i < epoch->members_count; i++)
1312 if (contact == epoch->members[i])
1313 return GNUNET_YES;
1314
1315 return is_epoch_member_in_room (epoch->room, &(epoch->hash), contact);
1316}
1317
1318
1319double
1321 const struct GNUNET_MESSENGER_Contact *contact,
1323 membership)
1324{
1325 uint32_t members_count;
1326 uint32_t announced;
1327 uint32_t position;
1328
1329 GNUNET_assert ((epoch) && (contact));
1330
1331 members_count = get_epoch_size (epoch);
1332 announced = membership?
1333 get_epoch_membership_count (membership) : 0;
1334
1335 if (members_count <= announced)
1336 return 0.0;
1337
1338 position = get_epoch_member_position (epoch, contact);
1339
1340 if (position > announced)
1341 position -= announced;
1342 else
1343 position = 0;
1344
1345 return (0.0 + position) / (members_count - announced);
1346}
1347
1348
1349void
1351 struct GNUNET_MESSENGER_Message *message)
1352{
1353 GNUNET_assert ((epoch) && (message));
1354
1356 &(epoch->hash),
1357 message,
1358 NULL,
1359 GNUNET_YES);
1360}
1361
1362
1363void
1366 announcement)
1367{
1368 GNUNET_assert ((epoch) && (announcement));
1369
1370 if (! get_epoch_announcement_key (announcement))
1371 return;
1372
1373 if (GNUNET_YES != announcement->valid)
1374 return;
1375
1376 if ((! epoch->main_announcement) ||
1378 epoch->main_announcement, announcement)))
1379 epoch->main_announcement = announcement;
1380}
1381
1382
1383static void
1386{
1387 GNUNET_assert (epoch);
1388
1391 timeout);
1392}
1393
1394
1395static enum GNUNET_GenericReturnValue
1397{
1399
1400 GNUNET_assert (epoch);
1401
1403 epoch->proposal_expiration);
1404
1406 return GNUNET_NO;
1407 else
1408 return GNUNET_YES;
1409}
1410
1411
1412void
1414 struct GNUNET_MESSENGER_EpochGroup *group)
1415{
1416 GNUNET_assert ((epoch) && (group));
1417
1418 if (! get_epoch_group_key (group))
1419 return;
1420
1421 if (GNUNET_YES != group->valid)
1422 return;
1423
1424 if (GNUNET_YES != is_epoch_group_completed (group))
1425 return;
1426
1427 if (GNUNET_YES == is_epoch_group_proposal (group))
1428 {
1429 if (epoch->proposal_timeout)
1431
1432 epoch->proposal_timeout = NULL;
1433
1434 memset (&(epoch->proposal_hash), 0, sizeof (epoch->proposal_hash));
1436 }
1437
1438 if ((! epoch->main_group) ||
1440 group)))
1441 epoch->main_group = group;
1442}
1443
1444
1445static void
1447{
1448 struct GNUNET_MESSENGER_Epoch *epoch;
1449
1450 GNUNET_assert (cls);
1451
1452 epoch = cls;
1453 epoch->proposal_timeout = NULL;
1454
1456}
1457
1458
1459static enum GNUNET_GenericReturnValue
1461 const struct GNUNET_MESSENGER_EpochGroup *
1462 subgroup)
1463{
1466 const struct GNUNET_MESSENGER_EpochGroup *group;
1467
1468 GNUNET_assert ((epoch) && (subgroup));
1469
1471
1472 if (! iter)
1473 return GNUNET_NO;
1474
1475 result = GNUNET_NO;
1476
1478 (const
1479 void**) &
1480 group))
1481 {
1482 if (group == subgroup)
1483 continue;
1484
1485 if (get_epoch_group_level (subgroup) >= get_epoch_group_level (group))
1486 continue;
1487
1488 if (GNUNET_YES == is_epoch_group_subgroup_of (subgroup, group))
1489 {
1491 break;
1492 }
1493 }
1494
1496 return result;
1497}
1498
1499
1502 const struct GNUNET_MESSENGER_Contact *contact)
1503{
1507 const struct GNUNET_MESSENGER_EpochGroup *group;
1508
1509 GNUNET_assert ((epoch) && (contact));
1510
1512
1513 if (! iter)
1514 return GNUNET_NO;
1515
1516 result = GNUNET_NO;
1517
1519 (const
1520 void**) &
1521 group))
1522 {
1523 if (GNUNET_YES == is_epoch_group_member (group, contact))
1524 {
1526 break;
1527 }
1528 }
1529
1531 return result;
1532}
1533
1534
1535void
1537 const struct GNUNET_TIME_Relative timeout)
1538{
1539 uint32_t level;
1540 struct GNUNET_MESSENGER_EpochGroup *group;
1541 struct GNUNET_HashCode initiator;
1542 struct GNUNET_HashCode partner;
1543
1544 GNUNET_assert (epoch);
1545
1546 if (GNUNET_YES != epoch->room->handle->group_keys)
1547 return;
1548
1549 if ((epoch->proposal_timeout) ||
1550 (GNUNET_YES == is_epoch_proposing (epoch)))
1551 return;
1552
1553 if (epoch->main_group)
1554 {
1556
1558 return;
1559
1560 if (GNUNET_OK != get_epoch_group_member_hash (epoch->main_group, &(initiator
1561 ),
1562 GNUNET_NO))
1563 return;
1564
1565 level = get_epoch_group_level (epoch->main_group);
1567
1568 if (! iter)
1569 return;
1570
1571 group = NULL;
1572
1574 NULL,
1575 (const
1576 void**)
1577 &group))
1578 {
1579 if ((epoch->main_group != group) &&
1580 (level == get_epoch_group_level (group)) &&
1581 (GNUNET_YES == is_epoch_group_completed (group)) &&
1582 (GNUNET_YES != is_epoch_subgroup_of_any_group (epoch, group)))
1583 break;
1584
1585 group = NULL;
1586 }
1587
1589
1590 if (! group)
1591 return;
1592
1593 if (GNUNET_OK != get_epoch_group_member_hash (group, &partner, GNUNET_YES))
1594 return;
1595 }
1596 else if (epoch->main_announcement)
1597 {
1599 struct GNUNET_HashCode hash;
1600 const struct GNUNET_MESSENGER_Contact *contact;
1601
1603 )
1604 return;
1605
1607 main_announcement, &(
1608 initiator), GNUNET_NO
1609 ))
1610 return;
1611
1612 level = 0;
1614 main_announcement->
1615 membership->members);
1616
1617 if (! iter)
1618 return;
1619
1620 contact = NULL;
1621
1623 hash,
1624 (const
1625 void**) &
1626 contact))
1627 {
1628 if ((0 != GNUNET_CRYPTO_hash_cmp (&initiator, &hash)) &&
1629 (GNUNET_NO == is_epoch_member_in_any_group (epoch, contact)))
1630 break;
1631
1632 contact = NULL;
1633 }
1634
1636
1637 if (! contact)
1638 return;
1639
1640 GNUNET_memcpy (&partner, &hash, sizeof (partner));
1641 }
1642 else
1643 return;
1644
1645 level++;
1646 if (level >= 0x80)
1647 return;
1648
1649 group = create_epoch_group (epoch, NULL, level, GNUNET_YES);
1650
1651 if (! group)
1652 return;
1653
1655 &(group->identifier.hash)
1656 ,
1657 group,
1659 {
1660 destroy_epoch_group (group);
1661 return;
1662 }
1663
1664 if (GNUNET_OK != send_epoch_group (group, &initiator, &partner, timeout))
1665 {
1667 hash), group);
1668 destroy_epoch_group (group);
1669 return;
1670 }
1671
1673}
1674
1675
1676void
1678 const struct GNUNET_HashCode *hash)
1679{
1680 const struct GNUNET_MESSENGER_Message *group_message;
1682
1683 GNUNET_assert ((epoch) && (hash));
1684
1685 if (epoch->proposal_timeout)
1686 return;
1687
1688 group_message = get_room_message (epoch->room, hash);
1689
1690 if (! group_message)
1691 return;
1692
1693 if (GNUNET_MESSENGER_KIND_GROUP != group_message->header.kind)
1694 return;
1695
1696 if (! group_message->body.group.identifier.code.group_bit)
1697 return;
1698
1699 timeout = get_message_timeout (group_message);
1700
1702 return;
1703
1704 GNUNET_memcpy (&(epoch->proposal_hash), hash, sizeof (epoch->proposal_hash));
1706
1708 timeout,
1711 epoch);
1712}
1713
1714
1715const struct GNUNET_MESSENGER_EpochGroup*
1717{
1718 const struct GNUNET_MESSENGER_Message *group_message;
1719
1720 GNUNET_assert (epoch);
1721
1722 group_message = get_room_message (epoch->room, &(epoch->proposal_hash));
1723
1724 if (! group_message)
1725 return NULL;
1726
1727 if (GNUNET_MESSENGER_KIND_GROUP != group_message->header.kind)
1728 return NULL;
1729
1730 if (! group_message->body.group.identifier.code.group_bit)
1731 return NULL;
1732
1733 return get_epoch_group (epoch, &(group_message->body.group.identifier),
1734 GNUNET_NO);
1735}
1736
1737
1738void
1740{
1741 const struct GNUNET_MESSENGER_EpochGroup *proposal_group;
1742
1744
1746 {
1748 epoch->proposal_timeout = NULL;
1749 }
1750
1751 proposal_group = get_epoch_proposal_group (epoch);
1752
1753 memset (&(epoch->proposal_hash), 0, sizeof (epoch->proposal_hash));
1754
1755 if (! proposal_group)
1756 return;
1757
1758 if (GNUNET_YES != is_epoch_group_completed (proposal_group))
1760 &(proposal_group->identifier.hash),
1761 proposal_group);
1762}
1763
1764
1765static enum GNUNET_GenericReturnValue
1767 const struct GNUNET_ShortHashCode *key,
1768 void *value)
1769{
1770 const struct GNUNET_MESSENGER_Contact **contact;
1771 struct GNUNET_MESSENGER_EpochAnnouncement *announcement;
1772
1773 GNUNET_assert ((cls) && (value));
1774
1775 contact = cls;
1776 announcement = value;
1777
1778 invalidate_epoch_announcement (announcement, *contact);
1779 return GNUNET_YES;
1780}
1781
1782
1783static enum GNUNET_GenericReturnValue
1785 const struct GNUNET_ShortHashCode *key,
1786 void *value)
1787{
1788 const struct GNUNET_MESSENGER_Contact **contact;
1789 struct GNUNET_MESSENGER_EpochGroup *group;
1790
1791 GNUNET_assert ((cls) && (value));
1792
1793 contact = cls;
1794 group = value;
1795
1796 invalidate_epoch_group (group, *contact);
1797 return GNUNET_YES;
1798}
1799
1800
1801void
1803 const struct GNUNET_MESSENGER_Contact *
1804 contact)
1805{
1806 GNUNET_assert ((epoch) && (contact));
1807
1810 &contact);
1811
1814 &contact);
1815}
static struct GNUNET_TIME_Relative timeout
User defined timestamp for completing operations.
Definition: gnunet-arm.c:118
struct GNUNET_HashCode key
The key used in the DHT.
static char * value
Value of the record to add/remove.
static int result
Global testing status.
static unsigned int epochs
-e option.
enum GNUNET_GenericReturnValue update_room_message(struct GNUNET_MESSENGER_SrvRoom *room, struct GNUNET_MESSENGER_Message *message, const struct GNUNET_HashCode *hash)
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
void GNUNET_CRYPTO_ecdhe_key_create(struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
Create a new private key.
Definition: crypto_ecc.c:454
int GNUNET_CRYPTO_hash_cmp(const struct GNUNET_HashCode *h1, const struct GNUNET_HashCode *h2)
Compare function for HashCodes, producing a total ordering of all hashcodes.
Definition: crypto_hash.c:218
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_contains(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Check if the map contains any value under the given key (including values that are NULL).
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
enum GNUNET_GenericReturnValue(* GNUNET_CONTAINER_ShortmapIterator)(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
Iterator over hash map entries.
void * GNUNET_CONTAINER_multihashmap_get(const struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Given a key find a value in the map matching the key.
void GNUNET_CONTAINER_multishortmap_iterator_destroy(struct GNUNET_CONTAINER_MultiShortmapIterator *iter)
Destroy a multishortmap iterator.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_iterator_next(struct GNUNET_CONTAINER_MultiHashMapIterator *iter, struct GNUNET_HashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator's position.
struct GNUNET_CONTAINER_MultiShortmap * GNUNET_CONTAINER_multishortmap_create(unsigned int len, int do_not_copy_keys)
Create a multi peer map (hash map for public keys of peers).
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_put(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_put(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, void *value, enum GNUNET_CONTAINER_MultiHashMapOption opt)
Store a key-value pair in the map.
struct GNUNET_CONTAINER_MultiShortmapIterator * GNUNET_CONTAINER_multishortmap_iterator_create(const struct GNUNET_CONTAINER_MultiShortmap *map)
Create an iterator for a multihashmap.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multishortmap_iterator_next(struct GNUNET_CONTAINER_MultiShortmapIterator *iter, struct GNUNET_ShortHashCode *key, const void **value)
Retrieve the next element from the hash map at the iterator's position.
int GNUNET_CONTAINER_multishortmap_iterate(struct GNUNET_CONTAINER_MultiShortmap *map, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Iterate over all entries in the map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
void GNUNET_CONTAINER_multishortmap_destroy(struct GNUNET_CONTAINER_MultiShortmap *map)
Destroy a hash map.
int GNUNET_CONTAINER_multishortmap_get_multiple(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, GNUNET_CONTAINER_ShortmapIterator it, void *it_cls)
Iterate over all entries in the map that match a particular key.
unsigned int GNUNET_CONTAINER_multihashmap_clear(struct GNUNET_CONTAINER_MultiHashMap *map)
Remove all entries from the map.
void GNUNET_CONTAINER_multihashmap_iterator_destroy(struct GNUNET_CONTAINER_MultiHashMapIterator *iter)
Destroy a multihashmap iterator.
unsigned int GNUNET_CONTAINER_multishortmap_size(const struct GNUNET_CONTAINER_MultiShortmap *map)
Get the number of key-value pairs in the map.
int GNUNET_CONTAINER_multishortmap_remove(struct GNUNET_CONTAINER_MultiShortmap *map, const struct GNUNET_ShortHashCode *key, const void *value)
Remove the given key-value pair from the map.
struct GNUNET_CONTAINER_MultiHashMapIterator * GNUNET_CONTAINER_multihashmap_iterator_create(const struct GNUNET_CONTAINER_MultiHashMap *map)
Create an iterator for a multihashmap.
@ GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST
, ' bother checking if a value already exists (faster than GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE...
#define GNUNET_is_zero(a)
Check that memory in a is all zeros.
char * GNUNET_CRYPTO_public_key_to_string(const struct GNUNET_CRYPTO_PublicKey *key)
Creates a (Base32) string representation of the public key.
Definition: crypto_pkey.c:379
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#define GNUNET_UNUSED
gcc-ism to document unused arguments
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_SCHEDULER_PRIORITY_HIGH
Run with high priority (important requests).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
@ GNUNET_MESSENGER_KIND_LEAVE
The leave kind.
@ GNUNET_MESSENGER_KIND_JOIN
The join kind.
@ GNUNET_MESSENGER_KIND_MERGE
The merge kind.
@ GNUNET_MESSENGER_KIND_GROUP
The group kind.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1207
struct GNUNET_TIME_Relative GNUNET_TIME_relative_get_zero_(void)
Return relative time of 0ms.
Definition: time.c:133
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get_zero_(void)
Return absolute time of 0ms.
Definition: time.c:142
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:406
bool GNUNET_TIME_relative_is_zero(struct GNUNET_TIME_Relative rel)
Test if rel is zero.
Definition: time.c:664
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_add(struct GNUNET_TIME_Absolute start, struct GNUNET_TIME_Relative duration)
Add a given relative duration to the given start time.
Definition: time.c:452
void enqueue_message_to_room(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, struct GNUNET_MESSENGER_Message *message, struct GNUNET_MESSENGER_Message *transcript, enum GNUNET_GenericReturnValue sync)
Enqueus a message and its optional transcript for sending it to a given room and epoch.
void require_message_from_room(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Requires a specific message in a given room which can be identified by its hash.
const struct GNUNET_CRYPTO_PublicKey * get_contact_key(const struct GNUNET_MESSENGER_Contact *contact)
Returns the public key of a given contact.
uint32_t get_epoch_member_position(const struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Contact *contact)
Returns the index position of a specific contact inside a given epoch in relation to its list of memb...
void invalidate_epoch_keys_by_member(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Contact *contact)
Invalidates all announced epoch and group keys by a specific contact inside a given epoch.
const struct GNUNET_TIME_Relative get_epoch_private_key_timeout(const struct GNUNET_MESSENGER_Epoch *epoch)
Returns the current relative timeout for the private key (ECDHE) of a given epoch that limits the usa...
static int compare_member_public_keys(const char *key_string, const struct GNUNET_CRYPTO_PublicKey *key)
static const struct GNUNET_MESSENGER_Contact ** get_members_of_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, uint32_t *members_count)
static const struct GNUNET_MESSENGER_Contact ** get_members_of_new_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, uint32_t *members_count)
uint32_t get_epoch_size(const struct GNUNET_MESSENGER_Epoch *epoch)
Returns the amount of members by a given epoch or zero as long as it's not fully initialized yet.
struct GNUNET_MESSENGER_Epoch * create_new_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Creates and allocates a new epoch in a given room which can be identified by a specific hash.
void cancel_epoch_proposal_group(struct GNUNET_MESSENGER_Epoch *epoch)
Cancels the current proposal of a new group from a given epoch.
static enum GNUNET_GenericReturnValue is_epoch_member_in_room_graph(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, const struct GNUNET_MESSENGER_Contact *contact, struct GNUNET_CONTAINER_MultiHashMap *map)
static enum GNUNET_GenericReturnValue is_other_epoch_group_better(const struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_MESSENGER_EpochGroup *other)
struct GNUNET_MESSENGER_Epoch * create_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Creates and allocates an epoch in a given room which can be identified by a specific hash.
static enum GNUNET_GenericReturnValue it_find_valid_group_with_most_members(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
struct GNUNET_MESSENGER_EpochGroup * get_epoch_group(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier, enum GNUNET_GenericReturnValue valid)
Returns the epoch group of a given epoch using a specific unique identifier or NULL.
static enum GNUNET_GenericReturnValue iterate_destroy_announcement(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_group(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
const struct GNUNET_MESSENGER_EpochAnnouncement * get_epoch_previous_announcement(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier)
Returns the epoch announcement of a previous epoch from a given epoch using a specific announcement i...
void update_epoch_announcement(struct GNUNET_MESSENGER_Epoch *epoch, struct GNUNET_MESSENGER_EpochAnnouncement *announcement)
Updates the main announcement of a given epoch, looking into replacing the current main announcement ...
static enum GNUNET_GenericReturnValue it_find_valid_announcement_with_most_members(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
enum GNUNET_GenericReturnValue delay_epoch_message_for_its_members(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_HashCode *hash)
Adds a message with a given hash to a list that can be delayed in processing for the members of a spe...
static void set_epoch_proposing(struct GNUNET_MESSENGER_Epoch *epoch, struct GNUNET_TIME_Relative timeout)
const struct GNUNET_MESSENGER_EpochGroup * get_epoch_previous_group(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier)
Returns the epoch group of a previous epoch from a given epoch using a specific group identifier.
static enum GNUNET_GenericReturnValue it_handle_epoch_message_delayed(void *cls, const struct GNUNET_HashCode *key, void *value)
enum GNUNET_GenericReturnValue is_epoch_member(const struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Contact *contact)
Returns whether a specific contact is member of a given epoch.
void set_epoch_proposal_group(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_HashCode *hash)
Sets the current group of proposal for a given epoch to the group specified by a message identified b...
const struct GNUNET_CRYPTO_EcdhePrivateKey * get_epoch_private_key(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_TIME_Relative timeout)
Returns the asymmetric private key (ECDHE) from a handle for a given epoch that can be used for HPKE ...
void destroy_epoch(struct GNUNET_MESSENGER_Epoch *epoch)
Destroys an epoch and frees its memory fully from the client API.
static enum GNUNET_GenericReturnValue is_epoch_subgroup_of_any_group(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_EpochGroup *subgroup)
struct GNUNET_MESSENGER_EpochAnnouncement * get_epoch_announcement(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier, enum GNUNET_GenericReturnValue valid)
Returns the epoch announcement of a given epoch using a specific unique identifier or NULL.
void reset_epoch_size(struct GNUNET_MESSENGER_Epoch *epoch)
Resets the amount of members by a given epoch to recalculate the exact amount.
static enum GNUNET_GenericReturnValue is_other_epoch_announcement_better(const struct GNUNET_MESSENGER_EpochAnnouncement *announcement, const struct GNUNET_MESSENGER_EpochAnnouncement *other)
static enum GNUNET_GenericReturnValue is_epoch_member_in_room(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, const struct GNUNET_MESSENGER_Contact *contact)
static enum GNUNET_GenericReturnValue iterate_epoch_announcement_invalidation(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
static void on_epoch_proposal_timeout(void *cls)
static void add_following_epoch(struct GNUNET_MESSENGER_Epoch *epoch, struct GNUNET_MESSENGER_Epoch *follow)
void propose_epoch_group(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_TIME_Relative timeout)
Tries to propose a new group inside a given epoch that will automatically be formed by using the clie...
static enum GNUNET_GenericReturnValue it_find_group_with_most_members(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
double get_epoch_position_factor(const struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Contact *contact, const struct GNUNET_MESSENGER_EpochMembership *membership)
Returns a relative member positon of a specific contact inside a given epoch in relation to its list ...
void send_epoch_message(const struct GNUNET_MESSENGER_Epoch *epoch, struct GNUNET_MESSENGER_Message *message)
Sends a created and allocated message in a room of a given epoch enforcing the message gets interpret...
enum GNUNET_GenericReturnValue is_epoch_member_in_any_group(struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Contact *contact)
const struct GNUNET_MESSENGER_EpochGroup * get_epoch_proposal_group(struct GNUNET_MESSENGER_Epoch *epoch)
Returns the current group of proposal for a given epoch.
static void setup_following_epochs_of_previous(struct GNUNET_MESSENGER_Epoch *epoch)
static enum GNUNET_GenericReturnValue it_find_announcement_with_most_members(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
void update_epoch_group(struct GNUNET_MESSENGER_Epoch *epoch, struct GNUNET_MESSENGER_EpochGroup *group)
Updates the main group of a given epoch, looking into replacing the current main group with a specifi...
static enum GNUNET_GenericReturnValue is_epoch_sender_in_room(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *epoch, const struct GNUNET_MESSENGER_Contact *contact)
static enum GNUNET_GenericReturnValue is_epoch_proposing(const struct GNUNET_MESSENGER_Epoch *epoch)
static enum GNUNET_GenericReturnValue iterate_epoch_group_invalidation(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
static enum GNUNET_GenericReturnValue it_move_epoch_groups_from_previous_epoch(void *cls, const struct GNUNET_ShortHashCode *key, void *value)
enum GNUNET_GenericReturnValue is_epoch_previous_of_other(const struct GNUNET_MESSENGER_Epoch *epoch, const struct GNUNET_MESSENGER_Epoch *other)
Returns whether a given epoch is the epoch before some other epoch.
enum GNUNET_GenericReturnValue get_epoch_announcement_member_hash(const struct GNUNET_MESSENGER_EpochAnnouncement *announcement, struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue other)
Provides an announcement hash of a member from a given epoch announcement.
struct GNUNET_MESSENGER_EpochAnnouncement * create_epoch_announcement(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier, enum GNUNET_GenericReturnValue valid)
Creates and allocates a new epoch announcement for a given epoch using a specific announcement identi...
const struct GNUNET_CRYPTO_SymmetricSessionKey * get_epoch_announcement_key(const struct GNUNET_MESSENGER_EpochAnnouncement *announcement)
Returns the secret key of a given epoch announcement or NULL.
void destroy_epoch_announcement(struct GNUNET_MESSENGER_EpochAnnouncement *announcement)
Destroys a given epoch announcement and frees its resources.
void invalidate_epoch_announcement(struct GNUNET_MESSENGER_EpochAnnouncement *announcement, const struct GNUNET_MESSENGER_Contact *contact)
Invalidates a given epoch announcement by a specific contact.
enum GNUNET_GenericReturnValue is_epoch_announcement_announced(const struct GNUNET_MESSENGER_EpochAnnouncement *announcement)
Returns whether the client has announced being part of a given epoch announcement owning its secret k...
uint32_t get_epoch_announcement_members_count(const struct GNUNET_MESSENGER_EpochAnnouncement *announcement)
Returns the current amount of members of a given epoch announcement.
enum GNUNET_GenericReturnValue send_epoch_group_announcement(struct GNUNET_MESSENGER_EpochGroup *group)
Tries to send an announcement message by the client for a given epoch group using its secret key.
enum GNUNET_GenericReturnValue is_epoch_group_announced(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns whether the client has announced being part of a given epoch group owning its secret key.
enum GNUNET_GenericReturnValue is_epoch_group_compatible(const struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_MESSENGER_Epoch *epoch)
Returns whether a given epoch group is compatible with a specific epoch with its members.
enum GNUNET_GenericReturnValue is_epoch_group_proposal(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns whether a given epoch group is the current proposal of the client.
void invalidate_epoch_group(struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_MESSENGER_Contact *contact)
Invalidates a given epoch group by a specific contact.
uint32_t get_epoch_group_members_count(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns the current amount of members of a given epoch group.
enum GNUNET_GenericReturnValue is_epoch_group_subgroup_of(const struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_MESSENGER_EpochGroup *other)
Returns whether a given epoch group is subgroup of a specific other group.
enum GNUNET_GenericReturnValue send_epoch_group(struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_HashCode *initiator_event, const struct GNUNET_HashCode *partner_event, struct GNUNET_TIME_Relative timeout)
Tries to send a group message by the client for a given epoch group to propose it forming a group out...
struct GNUNET_MESSENGER_EpochGroup * create_epoch_group(struct GNUNET_MESSENGER_Epoch *epoch, const union GNUNET_MESSENGER_EpochIdentifier *identifier, uint32_t level, enum GNUNET_GenericReturnValue valid)
Creates and allocates a new epoch group for a given epoch using a specific group identifier or NULL a...
void destroy_epoch_group(struct GNUNET_MESSENGER_EpochGroup *group)
Destroys a given epoch group and frees its resources.
enum GNUNET_GenericReturnValue is_epoch_group_member(const struct GNUNET_MESSENGER_EpochGroup *group, const struct GNUNET_MESSENGER_Contact *contact)
Returns whether a specific contact is confirmed member of a given epoch group.
enum GNUNET_GenericReturnValue is_epoch_group_completed(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns whether a given epoch group is complete in terms of confirmed announcements from its members.
uint32_t get_epoch_group_level(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns the group level of a given epoch group.
const struct GNUNET_CRYPTO_SymmetricSessionKey * get_epoch_group_key(const struct GNUNET_MESSENGER_EpochGroup *group)
Returns the secret key of a given epoch group or NULL.
enum GNUNET_GenericReturnValue get_epoch_group_member_hash(const struct GNUNET_MESSENGER_EpochGroup *group, struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue other)
Provides an announcement hash of a member from a given epoch group.
uint32_t get_epoch_membership_count(const struct GNUNET_MESSENGER_EpochMembership *membership)
Returns the current amount of individual members inside a given epoch membership.
struct GNUNET_TIME_Relative get_message_timeout(const struct GNUNET_MESSENGER_Message *message)
Return the relative timeout of the content from a given message that controls when a delayed handling...
#define max(x, y)
struct GNUNET_MESSENGER_Epoch * get_room_message_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Returns the epoch of a local message with a given hash in a room.
struct GNUNET_MESSENGER_Contact * get_room_sender(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Returns a messages sender locally stored from a map for a given hash in a room.
const struct GNUNET_MESSENGER_Message * get_room_message(const struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash)
Returns a message locally stored from a map for a given hash in a room.
struct GNUNET_MESSENGER_Epoch * get_room_epoch(struct GNUNET_MESSENGER_Room *room, const struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue recent)
Returns the epoch in a given room from a specific epoch hash that represents the exact message the ep...
static struct GNUNET_CONTAINER_MultiPeerMap * map
Peermap of PeerIdentities to "struct PeerEntry" (for fast lookup).
Definition: peer.c:63
Internal representation of the hash map.
Private ECC key encoded for transmission.
An identity key as per LSD0001.
A 512-bit hashcode.
union GNUNET_MESSENGER_EpochIdentifier identifier
enum GNUNET_GenericReturnValue valid
struct GNUNET_MESSENGER_Epoch * epoch
union GNUNET_MESSENGER_EpochIdentifier identifier
struct GNUNET_MESSENGER_Room * room
struct GNUNET_CONTAINER_MultiHashMap * waiting
struct GNUNET_CONTAINER_MultiShortmap * announcements
struct GNUNET_MESSENGER_Epoch ** following
struct GNUNET_MESSENGER_EpochGroup * main_group
struct GNUNET_SCHEDULER_Task * proposal_timeout
struct GNUNET_CONTAINER_MultiShortmap * nonces
struct GNUNET_TIME_Absolute private_key_expiration
struct GNUNET_MESSENGER_EpochAnnouncement * main_announcement
struct GNUNET_CRYPTO_EcdhePrivateKey * private_key
struct GNUNET_CONTAINER_MultiShortmap * groups
const struct GNUNET_MESSENGER_Contact ** members
struct GNUNET_TIME_Absolute proposal_expiration
struct GNUNET_HashCode proposal_hash
struct GNUNET_HashCode hash
enum GNUNET_GenericReturnValue group_keys
struct GNUNET_MESSENGER_MessageGroup group
struct GNUNET_MESSENGER_MessageMerge merge
struct GNUNET_MESSENGER_MessageLeave leave
struct GNUNET_MESSENGER_MessageJoin join
union GNUNET_MESSENGER_EpochIdentifier identifier
The identifier of the group in an epoch.
struct GNUNET_HashCode previous
The hash of the previous message from the senders perspective.
enum GNUNET_MESSENGER_MessageKind kind
The kind of the message.
struct GNUNET_HashCode epoch
The previous epoch the message was sent from.
struct GNUNET_HashCode epoch
The previous epoch the message was sent from.
struct GNUNET_HashCode previous
The hash of a second previous message.
struct GNUNET_HashCode epochs[2]
The previous epochs the message was sent from.
struct GNUNET_MESSENGER_MessageHeader header
Header.
struct GNUNET_MESSENGER_MessageBody body
Body.
struct GNUNET_MESSENGER_Contact * sender
struct GNUNET_MESSENGER_Handle * handle
struct GNUNET_CONTAINER_MultiShortmap * members
struct GNUNET_CONTAINER_MultiHashMap * messages
A 256-bit hashcode.
Time for relative time used by GNUnet, in microseconds.
An epoch identifier unifies an epoch identifier code and its 256bit hash representation.
struct GNUNET_MESSENGER_EpochIdentifierCode code