GNUnet debian-0.24.3-26-g2202bbd4d
gnunet-service-messenger_message_store.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2020--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 */
27
29
30#include "gnunet_common.h"
31#include "gnunet_network_lib.h"
33#include "gnunet_util_lib.h"
35
36#include <stdint.h>
37#include <string.h>
38
39void
41 const char *directory)
42{
43 GNUNET_assert (store);
44
45 store->directory = directory? GNUNET_strdup (directory) : NULL;
46
47 store->storage_messages = NULL;
48 store->writing_task = NULL;
49
55
57 store->write_links = GNUNET_NO;
58}
59
60
63 const struct GNUNET_HashCode *key,
64 void *value)
65{
67
69
70 entry = value;
71
72 GNUNET_free (entry);
73 return GNUNET_YES;
74}
75
76
79 const struct GNUNET_HashCode *key,
80 void *value)
81{
82 struct GNUNET_MESSENGER_Message *message;
83
85
86 message = value;
87
88 destroy_message (message);
89 return GNUNET_YES;
90}
91
92
95 const struct GNUNET_HashCode *key,
96 void *value)
97{
98 struct GNUNET_HashCode *hash;
99
101
102 hash = value;
103
104 GNUNET_free (hash);
105 return GNUNET_YES;
106}
107
108
109void
111{
112 GNUNET_assert (store);
113
114 if (store->storage_messages)
115 {
117 store->storage_messages = NULL;
118 }
119
120 if (store->writing_task)
121 {
123 store->writing_task = NULL;
124 }
125
131 NULL);
135 NULL);
136
142
143 if (store->directory)
144 {
145 GNUNET_free (store->directory);
146 store->directory = NULL;
147 }
148}
149
150
151void
153 const char *directory)
154{
155 GNUNET_assert ((store) && (directory));
156
157 if (store->directory)
158 {
159 if (0 == strcmp (store->directory, directory))
160 return;
161
163 {
165 "Moving message store failed because directory exists already! (%s)\n",
166 directory);
167 return;
168 }
169
170 if (0 != rename (store->directory, directory))
171 {
173 "Moving message store failed! (%s -> %s)\n",
174 store->directory, directory);
175 return;
176 }
177
178 GNUNET_free (store->directory);
179 }
180
181 store->directory = GNUNET_strdup (directory);
182}
183
184
186{
189};
190
191static int
193 void *attribute,
194 size_t attribute_len,
195 uint64_t *size)
196{
197 ssize_t result;
198
199 result = GNUNET_DISK_file_read (file, attribute, attribute_len);
200 if (GNUNET_SYSERR != result)
201 *size -= result;
202
203 return attribute_len != result;
204}
205
206
207#define load_message_store_attribute_failed(file, attribute, size) \
208 load_message_store_attribute (file, &(attribute), sizeof(attribute), \
209 &(size))
210
211#define save_message_store_attribute_failed(file, attribute) \
212 sizeof(attribute) != GNUNET_DISK_file_write (file, &(attribute), \
213 sizeof(attribute))
214
215static void
217 const char *filename)
218{
219 enum GNUNET_DISK_AccessPermissions permission;
220 struct GNUNET_DISK_FileHandle *entries;
222 struct GNUNET_MESSENGER_MessageEntry *entry;
223 uint64_t entry_size, size;
224
227 return;
228
229 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
230 storage.entry.length);
231
232 if (size < entry_size)
233 return;
234
235 permission = (GNUNET_DISK_PERM_USER_READ);
237 permission);
238
239 if (! entries)
240 return;
241
242 memset (&storage, 0, sizeof(storage));
243 entry = NULL;
244
245 while (size >= entry_size)
246 {
247 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
249 size)) ||
251 size)))
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
254 break;
255 }
256
258
259 if (! entry)
260 break;
261
262 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
263
265 store->entries, &(storage.hash))) ||
267 store->entries, &(storage.hash), entry,
269 {
271 "Loading message entry twice: %s\n",
272 GNUNET_h2s (&(storage.hash)));
274 break;
275 }
276
278 "Loading message entry with hash: %s\n",
279 GNUNET_h2s (&(storage.hash)));
280
281 entry = NULL;
282 }
283
284 if (entry)
285 GNUNET_free (entry);
286
287 GNUNET_DISK_file_close (entries);
288}
289
290
292{
295};
296
297static void
299 const char *filename)
300{
301 enum GNUNET_DISK_AccessPermissions permission;
304 struct GNUNET_MESSENGER_MessageLink *link;
305 uint64_t link_size, size;
306
309 return;
310
311 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
312 storage.link.first);
313
314 if (size < link_size)
315 return;
316
317 permission = (GNUNET_DISK_PERM_USER_READ);
318
320 permission);
321
322 if (! links)
323 return;
324
325 memset (&storage, 0, sizeof(storage));
326 link = NULL;
327
328 while (size >= link_size)
329 {
332 storage.link.multiple, size)) ||
334 ||
335 ((GNUNET_YES == storage.link.multiple) &&
337 )))
338 break;
339
341
342 if (! link)
343 break;
344
345 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
346
348 store->links, &(storage.hash))) ||
350 store->links, &(storage.hash), link,
352 break;
353
354 link = NULL;
355 }
356
357 if (link)
358 GNUNET_free (link);
359
361}
362
363
364static void
366 const char *filename)
367{
368 enum GNUNET_DISK_AccessPermissions permission;
370 struct GNUNET_HashCode storage[2];
371 struct GNUNET_HashCode *epoch;
372 uint64_t epoch_size, size;
373
376 return;
377
378 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
379
380 if (size < epoch_size)
381 return;
382
383 permission = (GNUNET_DISK_PERM_USER_READ);
384
386 permission);
387
388 if (! epochs)
389 return;
390
391 epoch = NULL;
392
393 while (size >= epoch_size)
394 {
395 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
397 break;
398
399 epoch = GNUNET_new (struct GNUNET_HashCode);
400
401 if (! epoch)
402 break;
403
404 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
405
407 store->epochs, &(storage[0]))) ||
409 store->epochs, &(storage[0]), epoch,
411 break;
412
413 epoch = NULL;
414 }
415
416 if (epoch)
417 GNUNET_free (epoch);
418
420}
421
422
423void
425{
426 enum GNUNET_DISK_AccessPermissions permission;
427 char *filename;
428
429 GNUNET_assert (store);
430
431 if (! store->directory)
432 return;
433
435
436 if (store->storage_messages)
438
440 "%s%s", store->directory, "messages.store");
441
445 permission);
446 else
447 store->storage_messages = NULL;
448
450
451 if (! store->storage_messages)
452 return;
453
455 "%s%s", store->directory, "entries.store");
456
459
461
463 "%s%s", store->directory, "links.store");
464
467
469 "%s%s", store->directory, "epochs.store");
470
473
475}
476
477
479{
481
483};
484
485
488 const struct GNUNET_HashCode *key,
489 void *value)
490{
492 struct GNUNET_HashCode *epoch;
493
494 GNUNET_assert ((cls) && (key) && (value));
495
496 save = cls;
497 epoch = value;
498
499 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
500 (save_message_store_attribute_failed (save->storage, (*epoch))))
501 return GNUNET_NO;
502
503 return GNUNET_YES;
504}
505
506
509 const struct GNUNET_HashCode *key,
510 void *value)
511{
513 struct GNUNET_MESSENGER_MessageLink *link;
514
515 GNUNET_assert ((cls) && (key) && (value));
516
517 save = cls;
518 link = value;
519
520 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
523 return GNUNET_NO;
524
525 if ((GNUNET_YES == link->multiple) &&
527 return GNUNET_NO;
528
529 return GNUNET_YES;
530}
531
532
535 const struct GNUNET_HashCode *key,
536 void *value)
537{
539 struct GNUNET_MESSENGER_MessageEntry *entry;
540
541 GNUNET_assert ((cls) && (key) && (value));
542
543 save = cls;
544 entry = value;
545
546 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
547 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
549 return GNUNET_NO;
550
551 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
552 GNUNET_h2s (key));
553
554 return GNUNET_YES;
555}
556
557
560 const struct GNUNET_HashCode *key,
561 void *value)
562{
565 struct GNUNET_MESSENGER_Message *message;
566
567 GNUNET_assert ((cls) && (key) && (value));
568
569 save = cls;
570
572 save->store->entries, key))
573 {
575 "Skipping storage of message: %s\n", GNUNET_h2s (key));
576 return GNUNET_YES;
577 }
578
579 message = value;
580
581 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
582
583 storage.entry.length = get_message_size (message, GNUNET_YES);
585 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
586
587 if ((GNUNET_SYSERR == storage.entry.offset) ||
588 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
590 storage.entry.offset)) ||
592 storage.entry.length)))
593 {
595 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
596 return GNUNET_NO;
597 }
598
599 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
600 GNUNET_h2s (&(storage.hash)));
601
602 {
603 char *buffer;
604 buffer = GNUNET_malloc (storage.entry.length);
605
606 if (! buffer)
607 return GNUNET_NO;
608
609 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
610
611 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
612 storage.entry.length);
613
614 GNUNET_free (buffer);
615 }
616
617 {
618 struct GNUNET_MESSENGER_MessageEntry *entry;
620
621 if (! entry)
622 return GNUNET_NO;
623
624 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
625
627 save->store->entries, &(storage.hash), entry,
629 {
631 "Message entry might get stored twice: %s\n",
632 GNUNET_h2s (&(storage.hash)));
633 GNUNET_free (entry);
634 return GNUNET_NO;
635 }
636 }
637
638 return GNUNET_YES;
639}
640
641
642void
644{
646 enum GNUNET_DISK_AccessPermissions permission;
647 char *filename;
648
650
651 if (! store->directory)
652 return;
653
655
657 "%s%s", store->directory, "epochs.store");
658
659 save.store = store;
661 | GNUNET_DISK_OPEN_CREATE, permission);
662
664
665 if (! save.storage)
666 {
668 "No access to local storage of message epochs!\n");
669 goto save_links;
670 }
671
672 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
674 goto close_epochs;
675
677 &save);
678
679close_epochs:
681
682save_links:
684 goto save_entries;
685
687 "%s%s", store->directory, "links.store");
688
689 save.store = store;
691 | GNUNET_DISK_OPEN_CREATE, permission);
692
694
695 if (! save.storage)
696 {
698 "No access to local storage of message links!\n");
699 goto save_entries;
700 }
701
702 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
704 goto close_links;
705
707 &save);
709
710close_links:
712
713save_entries:
715 "%s%s", store->directory, "entries.store");
716
717 save.store = store;
719 | GNUNET_DISK_OPEN_CREATE, permission);
720
722
723 if (! save.storage)
724 {
726 "No access to local storage of message entries!\n");
727 return;
728 }
729
731 {
732 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
734 goto close_entries;
735
737 &save);
739 }
740 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
742 goto close_entries;
743
746
748 "%s%s", store->directory, "messages.store");
749
753 permission);
754
756
758 {
761
763 GNUNET_DISK_file_sync (save.storage);
764 }
765
766close_entries:
768 save.storage = NULL;
769}
770
771
774 const struct GNUNET_HashCode *hash)
775{
776 GNUNET_assert ((store) && (hash));
777
779 hash))
780 return GNUNET_YES;
781
783 hash))
784 return GNUNET_YES;
785
787}
788
789
790const struct GNUNET_MESSENGER_Message*
792 const struct GNUNET_HashCode *hash)
793{
794 struct GNUNET_MESSENGER_Message *message;
795 const struct GNUNET_MESSENGER_MessageEntry *entry;
796 enum GNUNET_GenericReturnValue decoding;
797 struct GNUNET_HashCode check;
798 char *buffer;
799
800 GNUNET_assert ((store) && (hash));
801
802 if (GNUNET_is_zero (hash))
803 return NULL;
804
805 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
806
807 if (message)
808 return message;
809
810 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
811
812 if (message)
813 return message;
814
815 if (! store->storage_messages)
816 {
818 "Local storage of messages is unavailable: %s\n",
819 GNUNET_h2s (hash));
820 return NULL;
821 }
822
823 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
824
825 if (! entry)
826 {
828 "No entry in storage for message found: %s\n",
829 GNUNET_h2s (hash));
830 return NULL;
831 }
832
833 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
834 entry->offset,
836 {
838 "Offset for message in local storage invalid: %s\n",
839 GNUNET_h2s (hash));
840 return NULL;
841 }
842
843 buffer = GNUNET_malloc (entry->length);
844
845 if (! buffer)
846 {
848 "Allocation for message data buffer failed: %s\n",
849 GNUNET_h2s (hash));
850 return NULL;
851 }
852
853 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
854 entry->length) ||
856 GNUNET_YES)))
857 {
859 "Reading message from local storage failed: %s\n",
860 GNUNET_h2s (hash));
861 goto free_buffer;
862 }
863
865 decoding = decode_message (message, entry->length, buffer,
866 GNUNET_YES, NULL);
867
868 hash_message (message, entry->length, buffer, &check);
869
870 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
871 {
873 "Decoding message failed or checksum mismatched: %s\n",
874 GNUNET_h2s (hash));
875
877 hash, entry))
879 "Corrupted entry could not be removed from store: %s\n",
880 GNUNET_h2s (hash));
881
883 goto free_message;
884 }
885
887 store->messages, hash, message,
889 goto free_buffer;
890
891free_message:
892 destroy_message (message);
893 message = NULL;
894
895free_buffer:
896 GNUNET_free (buffer);
897 return message;
898}
899
900
903 const struct GNUNET_HashCode *hash,
904 enum GNUNET_GenericReturnValue deleted_only)
905{
906 const struct GNUNET_MESSENGER_Message *message;
907
908 if (GNUNET_is_zero (hash))
909 return NULL;
910
911 if (GNUNET_YES == deleted_only)
912 goto get_link;
913
914 message = get_store_message (store, hash);
915
916 if (message)
917 {
918 static struct GNUNET_MESSENGER_MessageLink link;
919
920 GNUNET_memcpy (&(link.first), &(message->header.previous),
921 sizeof(link.first));
922
925
926 if (GNUNET_YES == link.multiple)
927 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
928 sizeof(link.second));
929 else
930 GNUNET_memcpy (&(link.second), &(message->header.previous),
931 sizeof(link.second));
932
933 return &link;
934 }
935
936get_link:
937 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
938}
939
940
941const struct GNUNET_HashCode*
943 const struct GNUNET_HashCode *hash)
944{
945 struct GNUNET_HashCode *epoch;
946
947 GNUNET_assert ((store) && (hash));
948
949 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
950
951 if (! epoch)
952 return hash;
953
954 return epoch;
955}
956
957
958static void
960 const struct GNUNET_HashCode *hash,
961 const struct GNUNET_MESSENGER_Message *message)
962{
963 struct GNUNET_MESSENGER_MessageLink *link;
964
965 GNUNET_assert ((store) && (hash) && (message));
966
967 if (GNUNET_is_zero (hash))
968 return;
969
971
972 GNUNET_memcpy (&(link->first), &(message->header.previous),
973 sizeof(link->first));
974
977
978 if (GNUNET_YES == link->multiple)
979 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
980 sizeof(link->second));
981 else
982 GNUNET_memcpy (&(link->second), &(message->header.previous),
983 sizeof(link->second));
984
986 store->links, hash, link,
988 GNUNET_free (link);
989 else
990 store->write_links = GNUNET_YES;
991}
992
993
994static void
996 const struct GNUNET_HashCode *hash,
997 const struct GNUNET_HashCode *epoch)
998{
999 struct GNUNET_HashCode *copy;
1000
1001 GNUNET_assert ((store) && (hash) && (epoch));
1002
1003 if (GNUNET_is_zero (hash))
1004 return;
1005
1007 store->epochs, hash))
1008 return;
1009
1010 copy = GNUNET_new (struct GNUNET_HashCode);
1011
1012 if (! copy)
1013 return;
1014
1015 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1016
1018 store->epochs, hash, copy,
1020 GNUNET_free (copy);
1021}
1022
1023
1024static void
1026{
1027 struct GNUNET_MESSENGER_MessageStore *store;
1028
1029 GNUNET_assert (cls);
1030
1031 store = cls;
1032 store->writing_task = NULL;
1033
1034 save_message_store (store);
1035}
1036
1037
1040 const struct GNUNET_HashCode *hash,
1041 struct GNUNET_MESSENGER_Message *message)
1042{
1043 struct GNUNET_HashCode *epoch;
1046
1047 GNUNET_assert ((store) && (hash) && (message));
1048
1049 if (GNUNET_is_zero (hash))
1050 return GNUNET_SYSERR;
1051
1052 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1053
1054 if (epoch)
1055 goto reverse_epoch;
1056
1057 epoch = GNUNET_new (struct GNUNET_HashCode);
1058
1059 if (! epoch)
1060 goto skip_epoch;
1061
1062 switch (message->header.kind)
1063 {
1066 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1067 break;
1069 {
1070 const struct GNUNET_HashCode *epoch0;
1071 const struct GNUNET_HashCode *epoch1;
1072
1073 epoch0 = &(message->body.merge.epochs[0]);
1074 epoch1 = &(message->body.merge.epochs[1]);
1075
1076 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1077 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1078 else
1079 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1080
1081 break;
1082 }
1083 default:
1085 epoch,
1086 get_store_message_epoch (store, &(message->header.previous)),
1087 sizeof (struct GNUNET_HashCode));
1088 break;
1089 }
1090
1092 store->epochs, hash, epoch,
1094 {
1095 GNUNET_free (epoch);
1096 goto skip_epoch;
1097 }
1098
1099reverse_epoch:
1100 switch (message->header.kind)
1101 {
1104 store,
1105 &(message->header.previous),
1106 &(message->body.join.epoch));
1107 break;
1110 store,
1111 &(message->header.previous),
1112 &(message->body.leave.epoch));
1113 break;
1116 store,
1117 &(message->header.previous),
1118 &(message->body.merge.epochs[0]));
1120 store,
1121 &(message->body.merge.previous),
1122 &(message->body.merge.epochs[1]));
1123 break;
1124 default:
1126 store,
1127 &(message->header.previous),
1128 epoch);
1129 break;
1130 }
1131
1132skip_epoch:
1133 map = store->messages;
1134
1135 if (get_message_discourse (message))
1136 map = store->discourses;
1137
1139 {
1141 "Message has already been stored! (%s)\n",
1142 GNUNET_h2s (hash));
1143 return GNUNET_SYSERR;
1144 }
1145
1147 map, hash, message,
1149
1150 if ((GNUNET_OK != result) || (map == store->discourses))
1151 return result;
1152
1153 if (! store->writing_task)
1157 store);
1158
1159 return result;
1160}
1161
1162
1165 const struct GNUNET_HashCode *hash)
1166{
1167 const struct GNUNET_MESSENGER_MessageEntry *entry;
1168 const struct GNUNET_MESSENGER_Message *message;
1169
1170 GNUNET_assert ((store) && (hash));
1171
1172 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1173
1174 if (! entry)
1175 goto clear_memory;
1176
1177 message = get_store_message (store, hash);
1178
1179 if (message)
1180 {
1181 if (GNUNET_YES == is_epoch_message (message))
1182 {
1184 "Deletion of message is not allowed! (%s)\n",
1185 GNUNET_h2s (hash));
1186 return GNUNET_SYSERR;
1187 }
1188
1189 add_link (store, hash, message);
1190 }
1191
1192 if (! store->storage_messages)
1193 goto clear_entry;
1194
1195 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1196 entry->offset,
1198 return GNUNET_SYSERR;
1199
1200 {
1202 char *clear_buffer;
1203
1204 clear_buffer = GNUNET_malloc (entry->length);
1205
1206 if (! clear_buffer)
1207 return GNUNET_SYSERR;
1208
1209 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1210
1211 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1212 clear_buffer, entry->length))
1213 ||
1216 else
1217 result = GNUNET_OK;
1218
1219 GNUNET_free (clear_buffer);
1220
1221 if (GNUNET_OK != result)
1222 return result;
1223 }
1224
1225clear_entry:
1227 entry))
1228 store->rewrite_entries = GNUNET_YES;
1229
1230clear_memory:
1232 return GNUNET_OK;
1233}
1234
1235
1237{
1241};
1242
1243static enum GNUNET_GenericReturnValue
1245 const struct GNUNET_HashCode *key,
1246 void *value)
1247{
1249 struct GNUNET_MESSENGER_Message *message;
1250 const struct GNUNET_ShortHashCode *discourse;
1251
1252 GNUNET_assert ((cls) && (key) && (value));
1253
1254 cleanup = cls;
1255 message = value;
1256
1257 discourse = get_message_discourse (message);
1258
1259 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1260 return GNUNET_YES;
1261
1262 {
1265
1266 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1267 return GNUNET_YES;
1268 }
1269
1271 destroy_message (message);
1272
1273 return GNUNET_YES;
1274}
1275
1276
1277void
1279 store,
1280 const struct GNUNET_ShortHashCode *
1281 discourse,
1282 const struct GNUNET_TIME_Absolute
1283 timestamp)
1284{
1287
1288 GNUNET_assert ((store) && (discourse));
1289
1291
1292 cleanup.list = &list;
1293 cleanup.timestamp = timestamp;
1294
1295 GNUNET_memcpy (&(cleanup.discourse), discourse,
1296 sizeof (struct GNUNET_ShortHashCode));
1297
1300 &cleanup);
1301
1302 {
1303 struct GNUNET_MESSENGER_ListMessage *element;
1304 for (element = list.head; element; element = element->next)
1306 store->discourses,
1307 &(element->hash));
1308 }
1309
1311}
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:68
static uint64_t timestamp(void)
Get current timestamp.
struct GNUNET_HashCode key
The key used in the DHT.
static void cleanup(void *cls)
Disconnect and shutdown.
Definition: gnunet-did.c:131
static char * filename
static char * value
Value of the record to add/remove.
static int result
Global testing status.
static unsigned int epochs
-e option.
void clear_list_messages(struct GNUNET_MESSENGER_ListMessages *messages)
Clears the list of message hashes.
void init_list_messages(struct GNUNET_MESSENGER_ListMessages *messages)
Initializes list of message hashes as empty list.
void add_to_list_messages(struct GNUNET_MESSENGER_ListMessages *messages, const struct GNUNET_HashCode *hash)
Adds a specific hash from a message to the end of the list.
static enum GNUNET_GenericReturnValue iterate_save_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_hashs(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_entries(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_destroy_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
void save_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Saves messages from a message store into its directory.
enum GNUNET_GenericReturnValue contains_store_message(const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Checks if a message matching a given hash is stored in a message store.
static void task_save_messages(void *cls)
const struct GNUNET_HashCode * get_store_message_epoch(const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Returns the epoch hash of a message from a message store matching a given hash.
static enum GNUNET_GenericReturnValue iterate_flag_for_cleanup_discourse_message(void *cls, const struct GNUNET_HashCode *key, void *value)
enum GNUNET_GenericReturnValue put_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, struct GNUNET_MESSENGER_Message *message)
Stores a message into the message store.
static void load_message_store_entries(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
void clear_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Clears a message store, wipes its content and deallocates its memory.
enum GNUNET_GenericReturnValue delete_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Deletes a message in the message store.
static enum GNUNET_GenericReturnValue iterate_save_links(void *cls, const struct GNUNET_HashCode *key, void *value)
static int load_message_store_attribute(const struct GNUNET_DISK_FileHandle *file, void *attribute, size_t attribute_len, uint64_t *size)
void cleanup_store_discourse_messages_before(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_ShortHashCode *discourse, const struct GNUNET_TIME_Absolute timestamp)
Cleans up and deletes all discourse messages existing in the message store memory before a certain ti...
#define save_message_store_attribute_failed(file, attribute)
static void load_message_store_links(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
void load_message_store(struct GNUNET_MESSENGER_MessageStore *store)
Loads messages from its directory into a message store.
void init_message_store(struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
Initializes a message store as fully empty using a specific directory.
const struct GNUNET_MESSENGER_MessageLink * get_store_message_link(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, enum GNUNET_GenericReturnValue deleted_only)
Returns the message link from a message store matching a given hash.
#define load_message_store_attribute_failed(file, attribute, size)
static enum GNUNET_GenericReturnValue iterate_save_messages(void *cls, const struct GNUNET_HashCode *key, void *value)
static enum GNUNET_GenericReturnValue iterate_save_epochs(void *cls, const struct GNUNET_HashCode *key, void *value)
static void load_message_store_epochs(struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
const struct GNUNET_MESSENGER_Message * get_store_message(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
Returns the message from a message store matching a given hash.
static void add_link(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_MESSENGER_Message *message)
static void put_store_message_epoch(struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, const struct GNUNET_HashCode *epoch)
void move_message_store(struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
Moves all storage from a message store from its current directory to a given directory.
static void save()
Write persistent statistics to disk.
static struct GNUNET_CONTAINER_MultiPeerMap * links
Map from PIDs to struct VirtualLink entries describing links CORE knows to exist.
commonly used definitions; globals in this file are exempt from the rule that the module name ("commo...
Basic low-level networking interface.
API to schedule computations using continuation passing style.
void GNUNET_CRYPTO_zero_keys(void *buffer, size_t length)
Zero out buffer, securely against compiler optimizations.
struct GNUNET_DISK_FileHandle * GNUNET_DISK_file_open(const char *fn, enum GNUNET_DISK_OpenFlags flags, enum GNUNET_DISK_AccessPermissions perm)
Open a file.
Definition: disk.c:1258
enum GNUNET_GenericReturnValue GNUNET_DISK_file_test(const char *fil)
Check that fil corresponds to a filename (of a file that exists and that is not a directory).
Definition: disk.c:533
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:710
off_t GNUNET_DISK_file_seek(const struct GNUNET_DISK_FileHandle *h, off_t offset, enum GNUNET_DISK_Seek whence)
Move the read/write pointer in a file.
Definition: disk.c:219
enum GNUNET_GenericReturnValue GNUNET_DISK_file_size(const char *filename, uint64_t *size, int include_symbolic_links, int single_file_mode)
Get the size of the file (or directory) of the given file (in bytes).
Definition: disk.c:235
GNUNET_DISK_AccessPermissions
File access permissions, UNIX-style.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_sync(const struct GNUNET_DISK_FileHandle *h)
Write file changes to disk.
Definition: disk.c:1451
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition: disk.c:454
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1332
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:673
@ GNUNET_DISK_OPEN_READ
Open the file for reading.
@ GNUNET_DISK_OPEN_WRITE
Open the file for writing.
@ GNUNET_DISK_OPEN_CREATE
Create file if it doesn't exist.
@ GNUNET_DISK_OPEN_READWRITE
Open the file for both reading and writing.
@ GNUNET_DISK_PERM_USER_READ
Owner can read.
@ GNUNET_DISK_PERM_USER_WRITE
Owner can write.
@ GNUNET_DISK_SEEK_SET
Seek an absolute position (from the start of the file).
@ GNUNET_DISK_SEEK_END
Seek an absolute position from the end of the file.
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_remove_all(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key)
Remove all entries for the given key from the map.
int GNUNET_CONTAINER_multihashmap_iterate(struct GNUNET_CONTAINER_MultiHashMap *map, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map.
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.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_remove(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, const void *value)
Remove the given key-value pair from 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.
void GNUNET_CONTAINER_multihashmap_destroy(struct GNUNET_CONTAINER_MultiHashMap *map)
Destroy a hash map.
struct GNUNET_CONTAINER_MultiHashMap * GNUNET_CONTAINER_multihashmap_create(unsigned int len, int do_not_copy_keys)
Create a multi hash map.
@ 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.
#define GNUNET_log(kind,...)
#define GNUNET_memcmp(a, b)
Compare memory in a and b, where both must be of the same pointer type.
#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_BACKGROUND
Run as background job (higher than idle, lower than default).
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash value to a string (for printing debug messages).
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_DEBUG
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#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_UNKNOWN
The unknown kind.
@ GNUNET_MESSENGER_KIND_JOIN
The join kind.
@ GNUNET_MESSENGER_KIND_MERGE
The merge 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_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1231
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:741
#define GNUNET_TIME_absolute_cmp(t1, op, t2)
Compare two absolute times.
void encode_message(const struct GNUNET_MESSENGER_Message *message, uint16_t length, char *buffer, enum GNUNET_GenericReturnValue include_header)
Encodes a given message into a buffer of a maximal length in bytes.
const struct GNUNET_ShortHashCode * get_message_discourse(const struct GNUNET_MESSENGER_Message *message)
Returns the discourse hash of a message depending on its kind.
enum GNUNET_GenericReturnValue is_epoch_message(const struct GNUNET_MESSENGER_Message *message)
Returns whether a certain kind of message from storage contains some specific details that might be r...
void hash_message(const struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, struct GNUNET_HashCode *hash)
Calculates a hash of a given buffer with a length in bytes from a message.
struct GNUNET_MESSENGER_Message * create_message(enum GNUNET_MESSENGER_MessageKind kind)
Creates and allocates a new message with a specific kind.
void destroy_message(struct GNUNET_MESSENGER_Message *message)
Destroys a message and frees its memory fully.
uint16_t get_message_kind_size(enum GNUNET_MESSENGER_MessageKind kind, enum GNUNET_GenericReturnValue include_header)
Returns the minimal size in bytes to encode a message of a specific kind.
uint16_t get_message_size(const struct GNUNET_MESSENGER_Message *message, enum GNUNET_GenericReturnValue include_header)
Returns the exact size in bytes to encode a given message.
enum GNUNET_GenericReturnValue decode_message(struct GNUNET_MESSENGER_Message *message, uint16_t length, const char *buffer, enum GNUNET_GenericReturnValue include_header, uint16_t *padding)
Decodes a message from a given buffer of a maximal length in bytes.
static struct GNUNET_CONTAINER_MultiPeerMap * map
Peermap of PeerIdentities to "struct PeerEntry" (for fast lookup).
Definition: peer.c:63
static unsigned int size
Size of the "table".
Definition: peer.c:68
Internal representation of the hash map.
Handle used to access files (and pipes).
A 512-bit hashcode.
struct GNUNET_MESSENGER_ListMessage * next
struct GNUNET_MESSENGER_MessageMerge merge
struct GNUNET_MESSENGER_MessageLeave leave
struct GNUNET_MESSENGER_MessageJoin join
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_TIME_AbsoluteNBO timestamp
The timestamp 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_CONTAINER_MultiHashMap * links
struct GNUNET_DISK_FileHandle * storage_messages
struct GNUNET_CONTAINER_MultiHashMap * messages
struct GNUNET_CONTAINER_MultiHashMap * entries
struct GNUNET_CONTAINER_MultiHashMap * epochs
struct GNUNET_CONTAINER_MultiHashMap * discourses
struct GNUNET_MESSENGER_MessageHeader header
Header.
struct GNUNET_MESSENGER_MessageBody body
Body.
A 256-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.