GNUnet 0.29.1-6-gb66d952d5
 
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
506 discourses,
507 key))
508 return GNUNET_YES;
509
510 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
511 (save_message_store_attribute_failed (save->storage, (*epoch))))
512 return GNUNET_NO;
513
514 return GNUNET_YES;
515}
516
517
520 const struct GNUNET_HashCode *key,
521 void *value)
522{
524 struct GNUNET_MESSENGER_MessageLink *link;
525
526 GNUNET_assert ((cls) && (key) && (value));
527
528 save = cls;
529 link = value;
530
531 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
534 return GNUNET_NO;
535
536 if ((GNUNET_YES == link->multiple) &&
538 return GNUNET_NO;
539
540 return GNUNET_YES;
541}
542
543
546 const struct GNUNET_HashCode *key,
547 void *value)
548{
550 struct GNUNET_MESSENGER_MessageEntry *entry;
551
552 GNUNET_assert ((cls) && (key) && (value));
553
554 save = cls;
555 entry = value;
556
557 if ((save_message_store_attribute_failed (save->storage, (*key))) ||
558 (save_message_store_attribute_failed (save->storage, entry->offset)) ||
560 return GNUNET_NO;
561
562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message entry with hash: %s\n",
563 GNUNET_h2s (key));
564
565 return GNUNET_YES;
566}
567
568
571 const struct GNUNET_HashCode *key,
572 void *value)
573{
576 struct GNUNET_MESSENGER_Message *message;
577
578 GNUNET_assert ((cls) && (key) && (value));
579
580 save = cls;
581
583 save->store->entries, key))
584 {
586 "Skipping storage of message: %s\n", GNUNET_h2s (key));
587 return GNUNET_YES;
588 }
589
590 message = value;
591
592 GNUNET_memcpy (&(storage.hash), key, sizeof(storage.hash));
593
594 storage.entry.length = get_message_size (message, GNUNET_YES);
596 save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
597
598 if ((GNUNET_SYSERR == storage.entry.offset) ||
599 (save_message_store_attribute_failed (save->storage, storage.hash)) ||
601 storage.entry.offset)) ||
603 storage.entry.length)))
604 {
606 "Storing entry of message failed: %s\n", GNUNET_h2s (key));
607 return GNUNET_NO;
608 }
609
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
611 GNUNET_h2s (&(storage.hash)));
612
613 {
614 char *buffer;
615 buffer = GNUNET_malloc (storage.entry.length);
616
617 if (! buffer)
618 return GNUNET_NO;
619
620 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
621
622 GNUNET_DISK_file_write (save->store->storage_messages, buffer,
623 storage.entry.length);
624
625 GNUNET_free (buffer);
626 }
627
628 {
629 struct GNUNET_MESSENGER_MessageEntry *entry;
631
632 if (! entry)
633 return GNUNET_NO;
634
635 GNUNET_memcpy (entry, &(storage.entry), sizeof(*entry));
636
638 save->store->entries, &(storage.hash), entry,
640 {
642 "Message entry might get stored twice: %s\n",
643 GNUNET_h2s (&(storage.hash)));
644 GNUNET_free (entry);
645 return GNUNET_NO;
646 }
647 }
648
649 return GNUNET_YES;
650}
651
652
653void
655{
657 enum GNUNET_DISK_AccessPermissions permission;
658 char *filename;
659
661
662 if (store->writing_task)
663 {
665 store->writing_task = NULL;
666 }
667
668 if (! store->directory)
669 return;
670
672
674 "%s%s", store->directory, "epochs.store");
675
676 save.store = store;
678 | GNUNET_DISK_OPEN_CREATE, permission);
679
681
682 if (! save.storage)
683 {
685 "No access to local storage of message epochs!\n");
686 goto save_links;
687 }
688
689 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
691 goto close_epochs;
692
694 &save);
695
696close_epochs:
698
699save_links:
701 goto save_entries;
702
704 "%s%s", store->directory, "links.store");
705
706 save.store = store;
708 | GNUNET_DISK_OPEN_CREATE, permission);
709
711
712 if (! save.storage)
713 {
715 "No access to local storage of message links!\n");
716 goto save_entries;
717 }
718
719 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
721 goto close_links;
722
724 &save);
726
727close_links:
729
730save_entries:
732 "%s%s", store->directory, "entries.store");
733
734 save.store = store;
736 | GNUNET_DISK_OPEN_CREATE, permission);
737
739
740 if (! save.storage)
741 {
743 "No access to local storage of message entries!\n");
744 return;
745 }
746
748 {
749 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
751 goto close_entries;
752
754 &save);
756 }
757 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0,
759 goto close_entries;
760
763
765 "%s%s", store->directory, "messages.store");
766
770 permission);
771
773
775 {
778
780 GNUNET_DISK_file_sync (save.storage);
781 }
782
783close_entries:
785 save.storage = NULL;
786}
787
788
791 const struct GNUNET_HashCode *hash)
792{
793 GNUNET_assert ((store) && (hash));
794
796 hash))
797 return GNUNET_YES;
798
800 hash))
801 return GNUNET_YES;
802
804}
805
806
807const struct GNUNET_MESSENGER_Message*
809 const struct GNUNET_HashCode *hash)
810{
811 struct GNUNET_MESSENGER_Message *message;
812 const struct GNUNET_MESSENGER_MessageEntry *entry;
813 enum GNUNET_GenericReturnValue decoding;
814 struct GNUNET_HashCode check;
815 char *buffer;
816
817 GNUNET_assert ((store) && (hash));
818
819 if (GNUNET_is_zero (hash))
820 return NULL;
821
822 message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
823
824 if (message)
825 return message;
826
827 message = GNUNET_CONTAINER_multihashmap_get (store->discourses, hash);
828
829 if (message)
830 return message;
831
832 if (! store->storage_messages)
833 {
835 "Local storage of messages is unavailable: %s\n",
836 GNUNET_h2s (hash));
837 return NULL;
838 }
839
840 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
841
842 if (! entry)
843 {
845 "No entry in storage for message found: %s\n",
846 GNUNET_h2s (hash));
847 return NULL;
848 }
849
850 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
851 entry->offset,
853 {
855 "Offset for message in local storage invalid: %s\n",
856 GNUNET_h2s (hash));
857 return NULL;
858 }
859
860 buffer = GNUNET_malloc (entry->length);
861
862 if (! buffer)
863 {
865 "Allocation for message data buffer failed: %s\n",
866 GNUNET_h2s (hash));
867 return NULL;
868 }
869
870 if ((GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) !=
871 entry->length) ||
873 GNUNET_YES)))
874 {
876 "Reading message from local storage failed: %s\n",
877 GNUNET_h2s (hash));
878 goto free_buffer;
879 }
880
882 decoding = decode_message (message, entry->length, buffer,
883 GNUNET_YES, NULL);
884
885 hash_message (message, entry->length, buffer, &check);
886
887 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
888 {
890 "Decoding message failed or checksum mismatched: %s\n",
891 GNUNET_h2s (hash));
892
894 hash, entry))
896 "Corrupted entry could not be removed from store: %s\n",
897 GNUNET_h2s (hash));
898
900 goto free_message;
901 }
902
904 store->messages, hash, message,
906 goto free_buffer;
907
908free_message:
909 destroy_message (message);
910 message = NULL;
911
912free_buffer:
913 GNUNET_free (buffer);
914 return message;
915}
916
917
920 const struct GNUNET_HashCode *hash,
921 enum GNUNET_GenericReturnValue deleted_only)
922{
923 const struct GNUNET_MESSENGER_Message *message;
924
925 if (GNUNET_is_zero (hash))
926 return NULL;
927
928 if (GNUNET_YES == deleted_only)
929 goto get_link;
930
931 message = get_store_message (store, hash);
932
933 if (message)
934 {
935 static struct GNUNET_MESSENGER_MessageLink link;
936
937 GNUNET_memcpy (&(link.first), &(message->header.previous),
938 sizeof(link.first));
939
942
943 if (GNUNET_YES == link.multiple)
944 GNUNET_memcpy (&(link.second), &(message->body.merge.previous),
945 sizeof(link.second));
946 else
947 GNUNET_memcpy (&(link.second), &(message->header.previous),
948 sizeof(link.second));
949
950 return &link;
951 }
952
953get_link:
954 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
955}
956
957
958const struct GNUNET_HashCode*
960 const struct GNUNET_HashCode *hash)
961{
962 struct GNUNET_HashCode *epoch;
963
964 GNUNET_assert ((store) && (hash));
965
966 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
967
968 if (! epoch)
969 return hash;
970
971 return epoch;
972}
973
974
975static void
977 const struct GNUNET_HashCode *hash,
978 const struct GNUNET_MESSENGER_Message *message)
979{
980 struct GNUNET_MESSENGER_MessageLink *link;
981
982 GNUNET_assert ((store) && (hash) && (message));
983
984 if (GNUNET_is_zero (hash))
985 return;
986
988
989 GNUNET_memcpy (&(link->first), &(message->header.previous),
990 sizeof(link->first));
991
994
995 if (GNUNET_YES == link->multiple)
996 GNUNET_memcpy (&(link->second), &(message->body.merge.previous),
997 sizeof(link->second));
998 else
999 GNUNET_memcpy (&(link->second), &(message->header.previous),
1000 sizeof(link->second));
1001
1003 store->links, hash, link,
1005 GNUNET_free (link);
1006 else
1007 store->write_links = GNUNET_YES;
1008}
1009
1010
1011static void
1013 const struct GNUNET_HashCode *hash,
1014 const struct GNUNET_HashCode *epoch)
1015{
1016 struct GNUNET_HashCode *copy;
1017
1018 GNUNET_assert ((store) && (hash) && (epoch));
1019
1020 if (GNUNET_is_zero (hash))
1021 return;
1022
1024 store->epochs, hash))
1025 return;
1026
1027 copy = GNUNET_new (struct GNUNET_HashCode);
1028
1029 if (! copy)
1030 return;
1031
1032 GNUNET_memcpy (copy, epoch, sizeof (struct GNUNET_HashCode));
1033
1035 store->epochs, hash, copy,
1037 GNUNET_free (copy);
1038}
1039
1040
1041static void
1043{
1044 struct GNUNET_MESSENGER_MessageStore *store;
1045
1046 GNUNET_assert (cls);
1047
1048 store = cls;
1049 store->writing_task = NULL;
1050
1051 save_message_store (store);
1052}
1053
1054
1057 const struct GNUNET_HashCode *hash,
1058 struct GNUNET_MESSENGER_Message *message)
1059{
1060 struct GNUNET_HashCode *epoch;
1063
1064 GNUNET_assert ((store) && (hash) && (message));
1065
1066 if (GNUNET_is_zero (hash))
1067 return GNUNET_SYSERR;
1068
1069 epoch = GNUNET_CONTAINER_multihashmap_get (store->epochs, hash);
1070
1071 if (epoch)
1072 goto reverse_epoch;
1073
1074 epoch = GNUNET_new (struct GNUNET_HashCode);
1075
1076 if (! epoch)
1077 goto skip_epoch;
1078
1079 switch (message->header.kind)
1080 {
1083 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1084 break;
1086 {
1087 const struct GNUNET_HashCode *epoch0;
1088 const struct GNUNET_HashCode *epoch1;
1089
1090 epoch0 = &(message->body.merge.epochs[0]);
1091 epoch1 = &(message->body.merge.epochs[1]);
1092
1093 if (0 == GNUNET_CRYPTO_hash_cmp (epoch0, epoch1))
1094 GNUNET_memcpy (epoch, epoch0, sizeof (struct GNUNET_HashCode));
1095 else
1096 GNUNET_memcpy (epoch, hash, sizeof (struct GNUNET_HashCode));
1097
1098 break;
1099 }
1100 default:
1102 epoch,
1103 get_store_message_epoch (store, &(message->header.previous)),
1104 sizeof (struct GNUNET_HashCode));
1105 break;
1106 }
1107
1109 store->epochs, hash, epoch,
1111 {
1112 GNUNET_free (epoch);
1113 goto skip_epoch;
1114 }
1115
1116reverse_epoch:
1117 switch (message->header.kind)
1118 {
1121 store,
1122 &(message->header.previous),
1123 &(message->body.join.epoch));
1124 break;
1127 store,
1128 &(message->header.previous),
1129 &(message->body.leave.epoch));
1130 break;
1133 store,
1134 &(message->header.previous),
1135 &(message->body.merge.epochs[0]));
1137 store,
1138 &(message->body.merge.previous),
1139 &(message->body.merge.epochs[1]));
1140 break;
1141 default:
1143 store,
1144 &(message->header.previous),
1145 epoch);
1146 break;
1147 }
1148
1149skip_epoch:
1150 map = store->messages;
1151
1152 if (get_message_discourse (message))
1153 map = store->discourses;
1154
1156 {
1158 "Message has already been stored! (%s)\n",
1159 GNUNET_h2s (hash));
1160 return GNUNET_SYSERR;
1161 }
1162
1164 map, hash, message,
1166
1167 if ((GNUNET_OK != result) || (map == store->discourses))
1168 return result;
1169
1170 if (! store->writing_task)
1174 store);
1175
1176 return result;
1177}
1178
1179
1182 const struct GNUNET_HashCode *hash)
1183{
1184 const struct GNUNET_MESSENGER_MessageEntry *entry;
1185 const struct GNUNET_MESSENGER_Message *message;
1186
1187 GNUNET_assert ((store) && (hash));
1188
1189 entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
1190
1191 if (! entry)
1192 goto clear_memory;
1193
1194 message = get_store_message (store, hash);
1195
1196 if (message)
1197 {
1198 if (GNUNET_YES == is_epoch_message (message))
1199 {
1201 "Deletion of message is not allowed! (%s)\n",
1202 GNUNET_h2s (hash));
1203 return GNUNET_SYSERR;
1204 }
1205
1206 add_link (store, hash, message);
1207 }
1208
1209 if (! store->storage_messages)
1210 goto clear_entry;
1211
1212 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages,
1213 entry->offset,
1215 return GNUNET_SYSERR;
1216
1217 {
1219 char *clear_buffer;
1220
1221 clear_buffer = GNUNET_malloc (entry->length);
1222
1223 if (! clear_buffer)
1224 return GNUNET_SYSERR;
1225
1226 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
1227
1228 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages,
1229 clear_buffer, entry->length))
1230 ||
1233 else
1234 result = GNUNET_OK;
1235
1236 GNUNET_free (clear_buffer);
1237
1238 if (GNUNET_OK != result)
1239 return result;
1240 }
1241
1242clear_entry:
1244 entry))
1245 store->rewrite_entries = GNUNET_YES;
1246
1247clear_memory:
1251 return GNUNET_OK;
1252}
1253
1254
1261
1262static enum GNUNET_GenericReturnValue
1264 const struct GNUNET_HashCode *key,
1265 void *value)
1266{
1268 struct GNUNET_MESSENGER_Message *message;
1269 const struct GNUNET_ShortHashCode *discourse;
1270
1271 GNUNET_assert ((cls) && (key) && (value));
1272
1273 cleanup = cls;
1274 message = value;
1275
1276 discourse = get_message_discourse (message);
1277
1278 if ((! discourse) || (0 != GNUNET_memcmp (discourse, &(cleanup->discourse))))
1279 return GNUNET_YES;
1280
1281 {
1284
1285 if (GNUNET_TIME_absolute_cmp (timestamp, >=, cleanup->timestamp))
1286 return GNUNET_YES;
1287 }
1288
1290 destroy_message (message);
1291
1292 return GNUNET_YES;
1293}
1294
1295
1296void
1298 store,
1299 const struct GNUNET_ShortHashCode *
1300 discourse,
1301 const struct GNUNET_TIME_Absolute
1302 timestamp)
1303{
1306
1307 GNUNET_assert ((store) && (discourse));
1308
1310
1311 cleanup.list = &list;
1312 cleanup.timestamp = timestamp;
1313
1314 GNUNET_memcpy (&(cleanup.discourse), discourse,
1315 sizeof (struct GNUNET_ShortHashCode));
1316
1319 &cleanup);
1320
1321 {
1322 struct GNUNET_MESSENGER_ListMessage *element;
1323 for (element = list.head; element; element = element->next)
1325 &(element->hash)))
1327 store->epochs, &(element->hash));
1328 }
1329
1331}
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.