GNUnet 0.28.0-dev.3-20-gf1136b0b8
 
Loading...
Searching...
No Matches
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--2026 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 store->entries = NULL;
144 store->messages = NULL;
145 store->links = NULL;
146 store->discourses = NULL;
147 store->epochs = NULL;
148
149 if (store->directory)
150 {
151 GNUNET_free (store->directory);
152 store->directory = NULL;
153 }
154}
155
156
157void
159 const char *directory)
160{
161 GNUNET_assert ((store) && (directory));
162
163 if (store->directory)
164 {
165 if (0 == strcmp (store->directory, directory))
166 return;
167
169 {
171 "Moving message store failed because directory exists already! (%s)\n",
172 directory);
173 return;
174 }
175
176 if (0 != rename (store->directory, directory))
177 {
179 "Moving message store failed! (%s -> %s)\n",
180 store->directory, directory);
181 return;
182 }
183
184 GNUNET_free (store->directory);
185 }
186
187 store->directory = GNUNET_strdup (directory);
188}
189
190
196
197static int
199 void *attribute,
200 size_t attribute_len,
201 uint64_t *size)
202{
203 ssize_t result;
204
205 result = GNUNET_DISK_file_read (file, attribute, attribute_len);
206 if (GNUNET_SYSERR != result)
207 *size -= result;
208
209 return attribute_len != result;
210}
211
212
213#define load_message_store_attribute_failed(file, attribute, size) \
214 load_message_store_attribute (file, &(attribute), sizeof(attribute), \
215 &(size))
216
217#define save_message_store_attribute_failed(file, attribute) \
218 sizeof(attribute) != GNUNET_DISK_file_write (file, &(attribute), \
219 sizeof(attribute))
220
221static void
223 const char *filename)
224{
225 enum GNUNET_DISK_AccessPermissions permission;
226 struct GNUNET_DISK_FileHandle *entries;
228 struct GNUNET_MESSENGER_MessageEntry *entry;
229 uint64_t entry_size, size;
230
233 return;
234
235 entry_size = sizeof(storage.hash) + sizeof(storage.entry.offset) + sizeof(
236 storage.entry.length);
237
238 if (size < entry_size)
239 return;
240
241 permission = (GNUNET_DISK_PERM_USER_READ);
243 permission);
244
245 if (! entries)
246 return;
247
248 memset (&storage, 0, sizeof(storage));
249 entry = NULL;
250
251 while (size >= entry_size)
252 {
253 if ((load_message_store_attribute_failed (entries, storage.hash, size)) ||
255 size)) ||
257 size)))
258 {
259 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Loading message entry failed!\n");
260 break;
261 }
262
264
265 if (! entry)
266 break;
267
268 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
269
271 store->entries, &(storage.hash))) ||
273 store->entries, &(storage.hash), entry,
275 {
277 "Loading message entry twice: %s\n",
278 GNUNET_h2s (&(storage.hash)));
280 break;
281 }
282
284 "Loading message entry with hash: %s\n",
285 GNUNET_h2s (&(storage.hash)));
286
287 entry = NULL;
288 }
289
290 if (entry)
291 GNUNET_free (entry);
292
293 GNUNET_DISK_file_close (entries);
294}
295
296
302
303static void
305 const char *filename)
306{
307 enum GNUNET_DISK_AccessPermissions permission;
310 struct GNUNET_MESSENGER_MessageLink *link;
311 uint64_t link_size, size;
312
315 return;
316
317 link_size = sizeof(storage.hash) + sizeof(storage.link.multiple) + sizeof(
318 storage.link.first);
319
320 if (size < link_size)
321 return;
322
323 permission = (GNUNET_DISK_PERM_USER_READ);
324
326 permission);
327
328 if (! links)
329 return;
330
331 memset (&storage, 0, sizeof(storage));
332 link = NULL;
333
334 while (size >= link_size)
335 {
338 storage.link.multiple, size)) ||
340 ||
341 ((GNUNET_YES == storage.link.multiple) &&
343 )))
344 break;
345
347
348 if (! link)
349 break;
350
351 GNUNET_memcpy (link, &(storage.link), sizeof(*link));
352
354 store->links, &(storage.hash))) ||
356 store->links, &(storage.hash), link,
358 break;
359
360 link = NULL;
361 }
362
363 if (link)
364 GNUNET_free (link);
365
367}
368
369
370static void
372 const char *filename)
373{
374 enum GNUNET_DISK_AccessPermissions permission;
376 struct GNUNET_HashCode storage[2];
377 struct GNUNET_HashCode *epoch;
378 uint64_t epoch_size, size;
379
382 return;
383
384 epoch_size = sizeof(storage[0]) + sizeof(storage[1]);
385
386 if (size < epoch_size)
387 return;
388
389 permission = (GNUNET_DISK_PERM_USER_READ);
390
392 permission);
393
394 if (! epochs)
395 return;
396
397 epoch = NULL;
398
399 while (size >= epoch_size)
400 {
401 if ((load_message_store_attribute_failed (epochs, storage[0], size)) ||
403 break;
404
405 epoch = GNUNET_new (struct GNUNET_HashCode);
406
407 if (! epoch)
408 break;
409
410 GNUNET_memcpy (epoch, &(storage[1]), sizeof(*epoch));
411
413 store->epochs, &(storage[0]))) ||
415 store->epochs, &(storage[0]), epoch,
417 break;
418
419 epoch = NULL;
420 }
421
422 if (epoch)
423 GNUNET_free (epoch);
424
426}
427
428
429void
431{
432 enum GNUNET_DISK_AccessPermissions permission;
433 char *filename;
434
435 GNUNET_assert (store);
436
437 if (! store->directory)
438 return;
439
441
442 if (store->storage_messages)
444
446 "%s%s", store->directory, "messages.store");
447
451 permission);
452 else
453 store->storage_messages = NULL;
454
456
457 if (! store->storage_messages)
458 return;
459
461 "%s%s", store->directory, "entries.store");
462
465
468 "%s%s", store->directory, "links.store");
469
472
475 "%s%s", store->directory, "epochs.store");
476
479
481}
482
483
490
491
494 const struct GNUNET_HashCode *key,
495 void *value)
496{
498 struct GNUNET_HashCode *epoch;
499
500 GNUNET_assert ((cls) && (key) && (value));
501
502 save = cls;
503 epoch = value;
504
505 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
506 (save_message_store_attribute_failed (save->storage, (*epoch))))
507 return GNUNET_NO;
508
509 return GNUNET_YES;
510}
511
512
515 const struct GNUNET_HashCode *key,
516 void *value)
517{
519 struct GNUNET_MESSENGER_MessageLink *link;
520
521 GNUNET_assert ((cls) && (key) && (value));
522
523 save = cls;
524 link = value;
525
526 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
529 return GNUNET_NO;
530
531 if ((GNUNET_YES == link->multiple) &&
533 return GNUNET_NO;
534
535 return GNUNET_YES;
536}
537
538
541 const struct GNUNET_HashCode *key,
542 void *value)
543{
545 struct GNUNET_MESSENGER_MessageEntry *entry;
546
547 GNUNET_assert ((cls) && (key) && (value));
548
549 save = cls;
550 entry = value;
551
552 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
553 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
555 return GNUNET_NO;
556
557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
558 GNUNET_h2s (key));
559
560 return GNUNET_YES;
561}
562
563
566 const struct GNUNET_HashCode *key,
567 void *value)
568{
571 struct GNUNET_MESSENGER_Message *message;
572
573 GNUNET_assert ((cls) && (key) && (value));
574
575 save = cls;
576
578 save->store->entries, key))
579 {
581 "Skipping storage of message: %s\n", GNUNET_h2s (key));
582 return GNUNET_YES;
583 }
584
585 message = value;
586
587 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
588
589 storage.entry.length = get_message_size (message, GNUNET_YES);
591 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
592
593 if ((GNUNET_SYSERR == storage.entry.offset) ||
594 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
596 storage.entry.offset)) ||
598 storage.entry.length)))
599 {
601 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
602 return GNUNET_NO;
603 }
604
605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
606 GNUNET_h2s (&(storage.hash)));
607
608 {
609 char *buffer;
610 buffer = GNUNET_malloc (storage.entry.length);
611
612 if (! buffer)
613 return GNUNET_NO;
614
615 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
616
617 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
618 storage.entry.length);
619
620 GNUNET_free (buffer);
621 }
622
623 {
624 struct GNUNET_MESSENGER_MessageEntry *entry;
626
627 if (! entry)
628 return GNUNET_NO;
629
630 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
631
633 save->store->entries, &(storage.hash), entry,
635 {
637 "Message entry might get stored twice: %s\n",
638 GNUNET_h2s (&(storage.hash)));
639 GNUNET_free (entry);
640 return GNUNET_NO;
641 }
642 }
643
644 return GNUNET_YES;
645}
646
647
648void
650{
652 enum GNUNET_DISK_AccessPermissions permission;
653 char *filename;
654
656
657 if (! store->directory)
658 return;
659
661
663 "%s%s", store->directory, "epochs.store");
664
665 save.store = store;
667 | GNUNET_DISK_OPEN_CREATE, permission);
668
670
671 if (! save.storage)
672 {
674 "No access to local storage of message epochs!\n");
675 goto save_links;
676 }
677
678 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
680 goto close_epochs;
681
683 &save);
684
685close_epochs:
687
688save_links:
690 goto save_entries;
691
693 "%s%s", store->directory, "links.store");
694
695 save.store = store;
697 | GNUNET_DISK_OPEN_CREATE, permission);
698
700
701 if (! save.storage)
702 {
704 "No access to local storage of message links!\n");
705 goto save_entries;
706 }
707
708 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
710 goto close_links;
711
713 &save);
715
716close_links:
718
719save_entries:
721 "%s%s", store->directory, "entries.store");
722
723 save.store = store;
725 | GNUNET_DISK_OPEN_CREATE, permission);
726
728
729 if (! save.storage)
730 {
732 "No access to local storage of message entries!\n");
733 return;
734 }
735
737 {
738 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
740 goto close_entries;
741
743 &save);
745 }
746 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
748 goto close_entries;
749
752
754 "%s%s", store->directory, "messages.store");
755
759 permission);
760
762
764 {
767
769 GNUNET_DISK_file_sync (save.storage);
770 }
771
772close_entries:
774 save.storage = NULL;
775}
776
777
780 const struct GNUNET_HashCode *hash)
781{
782 GNUNET_assert ((store) && (hash));
783
785 hash))
786 return GNUNET_YES;
787
789 hash))
790 return GNUNET_YES;
791
793}
794
795
796const struct GNUNET_MESSENGER_Message*
798 const struct GNUNET_HashCode *hash)
799{
800 struct GNUNET_MESSENGER_Message *message;
801 const struct GNUNET_MESSENGER_MessageEntry *entry;
802 enum GNUNET_GenericReturnValue decoding;
803 struct GNUNET_HashCode check;
804 char *buffer;
805
806 GNUNET_assert ((store) && (hash));
807
808 if (GNUNET_is_zero (hash))
809 return NULL;
810
811 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
812
813 if (message)
814 return message;
815
816 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
817
818 if (message)
819 return message;
820
821 if (! store->storage_messages)
822 {
824 "Local storage of messages is unavailable: %s\n",
825 GNUNET_h2s (hash));
826 return NULL;
827 }
828
829 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
830
831 if (! entry)
832 {
834 "No entry in storage for message found: %s\n",
835 GNUNET_h2s (hash));
836 return NULL;
837 }
838
839 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
840 entry->offset,
842 {
844 "Offset for message in local storage invalid: %s\n",
845 GNUNET_h2s (hash));
846 return NULL;
847 }
848
849 buffer = GNUNET_malloc (entry->length);
850
851 if (! buffer)
852 {
854 "Allocation for message data buffer failed: %s\n",
855 GNUNET_h2s (hash));
856 return NULL;
857 }
858
859 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
860 entry->length) ||
862 GNUNET_YES)))
863 {
865 "Reading message from local storage failed: %s\n",
866 GNUNET_h2s (hash));
867 goto free_buffer;
868 }
869
871 decoding = decode_message (message, entry->length, buffer,
872 GNUNET_YES, NULL);
873
874 hash_message (message, entry->length, buffer, &check);
875
876 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
877 {
879 "Decoding message failed or checksum mismatched: %s\n",
880 GNUNET_h2s (hash));
881
883 hash, entry))
885 "Corrupted entry could not be removed from store: %s\n",
886 GNUNET_h2s (hash));
887
889 goto free_message;
890 }
891
893 store->messages, hash, message,
895 goto free_buffer;
896
897free_message:
898 destroy_message (message);
899 message = NULL;
900
901free_buffer:
902 GNUNET_free (buffer);
903 return message;
904}
905
906
909 const struct GNUNET_HashCode *hash,
910 enum GNUNET_GenericReturnValue deleted_only)
911{
912 const struct GNUNET_MESSENGER_Message *message;
913
914 if (GNUNET_is_zero (hash))
915 return NULL;
916
917 if (GNUNET_YES == deleted_only)
918 goto get_link;
919
920 message = get_store_message (store, hash);
921
922 if (message)
923 {
924 static struct GNUNET_MESSENGER_MessageLink link;
925
926 GNUNET_memcpy (&(link.first), &(message->header.previous),
927 sizeof(link.first));
928
931
932 if (GNUNET_YES == link.multiple)
933 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
934 sizeof(link.second));
935 else
936 GNUNET_memcpy (&(link.second), &(message->header.previous),
937 sizeof(link.second));
938
939 return &link;
940 }
941
942get_link:
943 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
944}
945
946
947const struct GNUNET_HashCode*
949 const struct GNUNET_HashCode *hash)
950{
951 struct GNUNET_HashCode *epoch;
952
953 GNUNET_assert ((store) && (hash));
954
955 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
956
957 if (! epoch)
958 return hash;
959
960 return epoch;
961}
962
963
964static void
966 const struct GNUNET_HashCode *hash,
967 const struct GNUNET_MESSENGER_Message *message)
968{
969 struct GNUNET_MESSENGER_MessageLink *link;
970
971 GNUNET_assert ((store) && (hash) && (message));
972
973 if (GNUNET_is_zero (hash))
974 return;
975
977
978 GNUNET_memcpy (&(link->first), &(message->header.previous),
979 sizeof(link->first));
980
983
984 if (GNUNET_YES == link->multiple)
985 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
986 sizeof(link->second));
987 else
988 GNUNET_memcpy (&(link->second), &(message->header.previous),
989 sizeof(link->second));
990
992 store->links, hash, link,
994 GNUNET_free (link);
995 else
996 store->write_links = GNUNET_YES;
997}
998
999
1000static void
1002 const struct GNUNET_HashCode *hash,
1003 const struct GNUNET_HashCode *epoch)
1004{
1005 struct GNUNET_HashCode *copy;
1006
1007 GNUNET_assert ((store) && (hash) && (epoch));
1008
1009 if (GNUNET_is_zero (hash))
1010 return;
1011
1013 store->epochs, hash))
1014 return;
1015
1016 copy = GNUNET_new (struct GNUNET_HashCode);
1017
1018 if (! copy)
1019 return;
1020
1021 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1022
1024 store->epochs, hash, copy,
1026 GNUNET_free (copy);
1027}
1028
1029
1030static void
1032{
1033 struct GNUNET_MESSENGER_MessageStore *store;
1034
1035 GNUNET_assert (cls);
1036
1037 store = cls;
1038 store->writing_task = NULL;
1039
1040 save_message_store (store);
1041}
1042
1043
1046 const struct GNUNET_HashCode *hash,
1047 struct GNUNET_MESSENGER_Message *message)
1048{
1049 struct GNUNET_HashCode *epoch;
1052
1053 GNUNET_assert ((store) && (hash) && (message));
1054
1055 if (GNUNET_is_zero (hash))
1056 return GNUNET_SYSERR;
1057
1058 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1059
1060 if (epoch)
1061 goto reverse_epoch;
1062
1063 epoch = GNUNET_new (struct GNUNET_HashCode);
1064
1065 if (! epoch)
1066 goto skip_epoch;
1067
1068 switch (message->header.kind)
1069 {
1072 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1073 break;
1075 {
1076 const struct GNUNET_HashCode *epoch0;
1077 const struct GNUNET_HashCode *epoch1;
1078
1079 epoch0 = &(message->body.merge.epochs[0]);
1080 epoch1 = &(message->body.merge.epochs[1]);
1081
1082 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1083 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1084 else
1085 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1086
1087 break;
1088 }
1089 default:
1091 epoch,
1092 get_store_message_epoch (store, &(message->header.previous)),
1093 sizeof (struct GNUNET_HashCode));
1094 break;
1095 }
1096
1098 store->epochs, hash, epoch,
1100 {
1101 GNUNET_free (epoch);
1102 goto skip_epoch;
1103 }
1104
1105reverse_epoch:
1106 switch (message->header.kind)
1107 {
1110 store,
1111 &(message->header.previous),
1112 &(message->body.join.epoch));
1113 break;
1116 store,
1117 &(message->header.previous),
1118 &(message->body.leave.epoch));
1119 break;
1122 store,
1123 &(message->header.previous),
1124 &(message->body.merge.epochs[0]));
1126 store,
1127 &(message->body.merge.previous),
1128 &(message->body.merge.epochs[1]));
1129 break;
1130 default:
1132 store,
1133 &(message->header.previous),
1134 epoch);
1135 break;
1136 }
1137
1138skip_epoch:
1139 map = store->messages;
1140
1141 if (get_message_discourse (message))
1142 map = store->discourses;
1143
1145 {
1147 "Message has already been stored! (%s)\n",
1148 GNUNET_h2s (hash));
1149 return GNUNET_SYSERR;
1150 }
1151
1153 map, hash, message,
1155
1156 if ((GNUNET_OK != result) || (map == store->discourses))
1157 return result;
1158
1159 if (! store->writing_task)
1163 store);
1164
1165 return result;
1166}
1167
1168
1171 const struct GNUNET_HashCode *hash)
1172{
1173 const struct GNUNET_MESSENGER_MessageEntry *entry;
1174 const struct GNUNET_MESSENGER_Message *message;
1175
1176 GNUNET_assert ((store) && (hash));
1177
1178 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1179
1180 if (! entry)
1181 goto clear_memory;
1182
1183 message = get_store_message (store, hash);
1184
1185 if (message)
1186 {
1187 if (GNUNET_YES == is_epoch_message (message))
1188 {
1190 "Deletion of message is not allowed! (%s)\n",
1191 GNUNET_h2s (hash));
1192 return GNUNET_SYSERR;
1193 }
1194
1195 add_link (store, hash, message);
1196 }
1197
1198 if (! store->storage_messages)
1199 goto clear_entry;
1200
1201 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1202 entry->offset,
1204 return GNUNET_SYSERR;
1205
1206 {
1208 char *clear_buffer;
1209
1210 clear_buffer = GNUNET_malloc (entry->length);
1211
1212 if (! clear_buffer)
1213 return GNUNET_SYSERR;
1214
1215 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1216
1217 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1218 clear_buffer, entry->length))
1219 ||
1222 else
1223 result = GNUNET_OK;
1224
1225 GNUNET_free (clear_buffer);
1226
1227 if (GNUNET_OK != result)
1228 return result;
1229 }
1230
1231clear_entry:
1233 entry))
1234 store->rewrite_entries = GNUNET_YES;
1235
1236clear_memory:
1240 return GNUNET_OK;
1241}
1242
1243
1250
1251static enum GNUNET_GenericReturnValue
1253 const struct GNUNET_HashCode *key,
1254 void *value)
1255{
1257 struct GNUNET_MESSENGER_Message *message;
1258 const struct GNUNET_ShortHashCode *discourse;
1259
1260 GNUNET_assert ((cls) && (key) && (value));
1261
1262 cleanup = cls;
1263 message = value;
1264
1265 discourse = get_message_discourse (message);
1266
1267 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1268 return GNUNET_YES;
1269
1270 {
1273
1274 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1275 return GNUNET_YES;
1276 }
1277
1279 destroy_message (message);
1280
1281 return GNUNET_YES;
1282}
1283
1284
1285void
1287 store,
1288 const struct GNUNET_ShortHashCode *
1289 discourse,
1290 const struct GNUNET_TIME_Absolute
1291 timestamp)
1292{
1295
1296 GNUNET_assert ((store) && (discourse));
1297
1299
1300 cleanup.list = &list;
1301 cleanup.timestamp = timestamp;
1302
1303 GNUNET_memcpy (&(cleanup.discourse), discourse,
1304 sizeof (struct GNUNET_ShortHashCode));
1305
1308 &cleanup);
1309
1310 {
1311 struct GNUNET_MESSENGER_ListMessage *element;
1312 for (element = list.head; element; element = element->next)
1314 store->discourses,
1315 &(element->hash));
1316 }
1317
1319}
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 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 cleanup()
Cleanup task.
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:1308
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:557
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:745
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:1507
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_test(const char *fil, int is_readable)
Test if fil is a directory and listable.
Definition disk.c:466
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition disk.c:1386
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:704
@ 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.
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.
enum GNUNET_GenericReturnValue GNUNET_CONTAINER_multihashmap_get_multiple(struct GNUNET_CONTAINER_MultiHashMap *map, const struct GNUNET_HashCode *key, GNUNET_CONTAINER_MultiHashMapIteratorCallback it, void *it_cls)
Iterate over all entries in the map that match a particular key.
@ 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_BULK
@ 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:986
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:1237
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition time.c:737
#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 maximum 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 maximum 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_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.