aboutsummaryrefslogtreecommitdiff
path: root/src/messenger/gnunet-service-messenger_message_store.c
diff options
context:
space:
mode:
authorTheJackiMonster <thejackimonster@gmail.com>2020-11-01 22:57:28 +0100
committerTheJackiMonster <thejackimonster@gmail.com>2021-03-06 01:30:37 +0100
commit2925310d67483aca6e055e1ce0593c6463cd6c72 (patch)
tree2cc8aacafc25563cdccde2eee9a90f9ca257d405 /src/messenger/gnunet-service-messenger_message_store.c
parent82b864a64679b0a735201724907cdf2b7e4e16c3 (diff)
downloadgnunet-2925310d67483aca6e055e1ce0593c6463cd6c72.tar.gz
gnunet-2925310d67483aca6e055e1ce0593c6463cd6c72.zip
-added core functionality of the messenger service
Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> formatting messenger code Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -completed core functionality of messenger service Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -code cleanup and reuse Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> +added structure to memberships of rooms Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented member permission checks and deletion of messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -moved solving requests out of updating last messages (also forward before update) Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -reduced complexity of permisson check and changed load/save of rooms Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added save/load for accessed keys and basement peers of a room Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented save/load for members with their history and session Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -abstracted management of egos and contacts Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fix warning Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -abstracted management of members Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed and adjusted test case Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -separated handling of direct and anonymous contacts Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -messenger added member-sessions which fix multiple edge cases, also additional cleanup Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -updated docs and fixed memory leak Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -changed info messages and added protocol version exchange Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adjusted client api to use contacts from sessions Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added more logging and fixed wrong session usage Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adjusted comm0 test case and removed adding members from checking messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed test-case for peer exchange Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -getting multiple peers connected in test-case with cadet Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed wrong assert and added tunnel version check -simplified handling and forwarding Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed merging last messages and cycling info messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -automated adding sessions and members Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -corrected use of identity keys and signatures Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -adding local joining on entering external room Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed test-case comm0 Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added more test-cases with generic setup Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed multiple simultaneous channels blocking each other Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -making test-cases more precise Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added check of members in test-cases, reduced merge messages Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -unified delayed operations: requests, deletions and merges Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -finished handling of operations Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed member session historystorage, added request permission check and padding for transmission Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -improved padding and removed automatic recursive requests Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -implemented filter for sending messages and added private messages to API level Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -wrong setups fixed with proper ego lookups Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -fixed problem with anonymous ego and changed to discrete-level padding Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added links to replace deleted messages, added local deletion and fixed anonymous id changing Signed-off-by: TheJackiMonster <thejackimonster@gmail.com> -added session completion and removal through completion process Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
Diffstat (limited to 'src/messenger/gnunet-service-messenger_message_store.c')
-rw-r--r--src/messenger/gnunet-service-messenger_message_store.c360
1 files changed, 310 insertions, 50 deletions
diff --git a/src/messenger/gnunet-service-messenger_message_store.c b/src/messenger/gnunet-service-messenger_message_store.c
index 5933d6390..1f3d262ac 100644
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ b/src/messenger/gnunet-service-messenger_message_store.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 Copyright (C) 2020 GNUnet e.V. 3 Copyright (C) 2020--2021 GNUnet e.V.
4 4
5 GNUnet is free software: you can redistribute it and/or modify it 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 6 under the terms of the GNU Affero General Public License as published
@@ -29,10 +29,16 @@
29void 29void
30init_message_store (struct GNUNET_MESSENGER_MessageStore *store) 30init_message_store (struct GNUNET_MESSENGER_MessageStore *store)
31{ 31{
32 GNUNET_assert(store);
33
32 store->storage_messages = NULL; 34 store->storage_messages = NULL;
33 35
34 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 36 store->entries = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
35 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO); 37 store->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
38 store->links = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
39
40 store->rewrite_entries = GNUNET_NO;
41 store->write_links = GNUNET_NO;
36} 42}
37 43
38static int 44static int
@@ -55,9 +61,21 @@ iterate_destroy_messages (void *cls, const struct GNUNET_HashCode *key, void *va
55 return GNUNET_YES; 61 return GNUNET_YES;
56} 62}
57 63
64static int
65iterate_destroy_links (void *cls, const struct GNUNET_HashCode *key, void *value)
66{
67 struct GNUNET_HashCode *previous = value;
68
69 GNUNET_free(previous);
70
71 return GNUNET_YES;
72}
73
58void 74void
59clear_message_store (struct GNUNET_MESSENGER_MessageStore *store) 75clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
60{ 76{
77 GNUNET_assert(store);
78
61 if (store->storage_messages) 79 if (store->storage_messages)
62 { 80 {
63 GNUNET_DISK_file_close (store->storage_messages); 81 GNUNET_DISK_file_close (store->storage_messages);
@@ -67,9 +85,11 @@ clear_message_store (struct GNUNET_MESSENGER_MessageStore *store)
67 85
68 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL); 86 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_destroy_entries, NULL);
69 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL); 87 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_destroy_messages, NULL);
88 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_destroy_links, NULL);
70 89
71 GNUNET_CONTAINER_multihashmap_destroy (store->entries); 90 GNUNET_CONTAINER_multihashmap_destroy (store->entries);
72 GNUNET_CONTAINER_multihashmap_destroy (store->messages); 91 GNUNET_CONTAINER_multihashmap_destroy (store->messages);
92 GNUNET_CONTAINER_multihashmap_destroy (store->links);
73} 93}
74 94
75struct GNUNET_MESSENGER_MessageEntryStorage 95struct GNUNET_MESSENGER_MessageEntryStorage
@@ -78,36 +98,15 @@ struct GNUNET_MESSENGER_MessageEntryStorage
78 struct GNUNET_MESSENGER_MessageEntry entry; 98 struct GNUNET_MESSENGER_MessageEntry entry;
79}; 99};
80 100
81void 101static void
82load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 102load_message_store_entries (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
83{ 103{
84 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 104 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
85
86 if (store->storage_messages)
87 GNUNET_DISK_file_close (store->storage_messages);
88
89 char *filename;
90 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
91
92 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
93 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
94 else
95 store->storage_messages = NULL;
96
97 GNUNET_free(filename);
98
99 if (!store->storage_messages)
100 return;
101
102 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
103
104 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
105 goto free_filename;
106 105
107 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission); 106 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
108 107
109 if (!entries) 108 if (!entries)
110 goto free_filename; 109 return;
111 110
112 struct GNUNET_MESSENGER_MessageEntryStorage storage; 111 struct GNUNET_MESSENGER_MessageEntryStorage storage;
113 struct GNUNET_MESSENGER_MessageEntry *entry; 112 struct GNUNET_MESSENGER_MessageEntry *entry;
@@ -120,9 +119,13 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
120 { 119 {
121 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry)); 120 GNUNET_memcpy(entry, &(storage.entry), sizeof(*entry));
122 121
123 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry, 122 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->entries, &(storage.hash))) ||
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) 123 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->entries, &(storage.hash), entry,
124 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
125 {
126 store->rewrite_entries = GNUNET_YES;
125 GNUNET_free(entry); 127 GNUNET_free(entry);
128 }
126 } 129 }
127 else 130 else
128 { 131 {
@@ -134,22 +137,118 @@ load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
134 while (entry); 137 while (entry);
135 138
136 GNUNET_DISK_file_close (entries); 139 GNUNET_DISK_file_close (entries);
140}
141
142struct GNUNET_MESSENGER_MessageLinkStorage
143{
144 struct GNUNET_HashCode hash;
145 struct GNUNET_MESSENGER_MessageLink link;
146};
147
148static void
149load_message_store_links (struct GNUNET_MESSENGER_MessageStore *store, const char *filename)
150{
151 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ);
152
153 struct GNUNET_DISK_FileHandle *entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READ, permission);
154
155 if (!entries)
156 return;
157
158 struct GNUNET_MESSENGER_MessageLinkStorage storage;
159 struct GNUNET_MESSENGER_MessageLink *link = NULL;
160
161 do
162 {
163 if ((sizeof(storage.hash) != GNUNET_DISK_file_read (entries, &(storage.hash), sizeof(storage.hash))) ||
164 (sizeof(storage.link.multiple) != GNUNET_DISK_file_read (entries, &(storage.link.multiple), sizeof(storage.link.multiple))) ||
165 (sizeof(storage.link.first) != GNUNET_DISK_file_read (entries, &(storage.link.first), sizeof(storage.link.first))) ||
166 ((GNUNET_YES == storage.link.multiple) &&
167 (sizeof(storage.link.second) != GNUNET_DISK_file_read (entries, &(storage.link.second), sizeof(storage.link.second)))))
168 break;
169
170 link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
171
172 GNUNET_memcpy(link, &(storage.link), sizeof(*link));
173
174 if ((GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->links, &(storage.hash))) ||
175 (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (store->links, &(storage.hash), link,
176 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
177 break;
178 }
179 while (link);
180
181 if (link)
182 GNUNET_free(link);
183
184 GNUNET_DISK_file_close (entries);
185}
186
187void
188load_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
189{
190 GNUNET_assert((store) && (directory));
191
192 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
193
194 if (store->storage_messages)
195 GNUNET_DISK_file_close (store->storage_messages);
196
197 char *filename;
198 GNUNET_asprintf (&filename, "%s%s", directory, "messages.store");
199
200 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
201 store->storage_messages = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_READWRITE, permission);
202 else
203 store->storage_messages = NULL;
204
205 GNUNET_free(filename);
206
207 if (!store->storage_messages)
208 return;
209
210 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
211
212 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
213 load_message_store_entries(store, filename);
214
215 GNUNET_free(filename);
216
217 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
218
219 if (GNUNET_YES == GNUNET_DISK_file_test (filename))
220 load_message_store_links(store, filename);
137 221
138free_filename:
139 GNUNET_free(filename); 222 GNUNET_free(filename);
140} 223}
141 224
142struct GNUNET_MESSENGER_MessageSave 225struct GNUNET_MESSENGER_ClosureMessageSave
143{ 226{
144 struct GNUNET_MESSENGER_MessageStore *store; 227 struct GNUNET_MESSENGER_MessageStore *store;
145 228
146 struct GNUNET_DISK_FileHandle *storage_entries; 229 struct GNUNET_DISK_FileHandle *storage;
147}; 230};
148 231
149static int 232static int
233iterate_save_entries (void *cls, const struct GNUNET_HashCode *key, void *value)
234{
235 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
236 struct GNUNET_MESSENGER_MessageEntry *entry = value;
237
238 struct GNUNET_MESSENGER_MessageEntryStorage storage;
239
240 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
241 GNUNET_memcpy(&(storage.entry), entry, sizeof(*entry));
242
243 GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage));
244
245 return GNUNET_YES;
246}
247
248static int
150iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value) 249iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value)
151{ 250{
152 struct GNUNET_MESSENGER_MessageSave *save = cls; 251 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
153 252
154 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key)) 253 if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (save->store->entries, key))
155 return GNUNET_YES; 254 return GNUNET_YES;
@@ -159,16 +258,16 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
159 258
160 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash)); 259 GNUNET_memcpy(&(storage.hash), key, sizeof(storage.hash));
161 260
162 storage.entry.length = get_message_size (message); 261 storage.entry.length = get_message_size (message, GNUNET_YES);
163 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END); 262 storage.entry.offset = GNUNET_DISK_file_seek (save->store->storage_messages, 0, GNUNET_DISK_SEEK_END);
164 263
165 if ((GNUNET_SYSERR == storage.entry.offset) || 264 if ((GNUNET_SYSERR == storage.entry.offset) || (sizeof(storage)
166 (sizeof(storage) != GNUNET_DISK_file_write (save->storage_entries, &storage, sizeof(storage)))) 265 != GNUNET_DISK_file_write (save->storage, &storage, sizeof(storage))))
167 return GNUNET_YES; 266 return GNUNET_YES;
168 267
169 char *buffer = GNUNET_malloc(storage.entry.length); 268 char *buffer = GNUNET_malloc(storage.entry.length);
170 269
171 encode_message (message, storage.entry.length, buffer); 270 encode_message (message, storage.entry.length, buffer, GNUNET_YES);
172 271
173 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length); 272 GNUNET_DISK_file_write (save->store->storage_messages, buffer, storage.entry.length);
174 273
@@ -177,25 +276,74 @@ iterate_save_messages (void *cls, const struct GNUNET_HashCode *key, void *value
177 return GNUNET_YES; 276 return GNUNET_YES;
178} 277}
179 278
279static int
280iterate_save_links (void *cls, const struct GNUNET_HashCode *key, void *value)
281{
282 struct GNUNET_MESSENGER_ClosureMessageSave *save = cls;
283 struct GNUNET_MESSENGER_MessageLink *link = value;
284
285 GNUNET_DISK_file_write (save->storage, key, sizeof(*key));
286 GNUNET_DISK_file_write (save->storage, &(link->multiple), sizeof(link->multiple));
287 GNUNET_DISK_file_write (save->storage, &(link->first), sizeof(link->first));
288
289 if (GNUNET_YES == link->multiple)
290 GNUNET_DISK_file_write (save->storage, &(link->second), sizeof(link->second));
291
292 return GNUNET_YES;
293}
294
180void 295void
181save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory) 296save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *directory)
182{ 297{
183 struct GNUNET_MESSENGER_MessageSave save; 298 GNUNET_assert((store) && (directory));
299
300 struct GNUNET_MESSENGER_ClosureMessageSave save;
184 301
185 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE); 302 enum GNUNET_DISK_AccessPermissions permission = (GNUNET_DISK_PERM_USER_READ | GNUNET_DISK_PERM_USER_WRITE);
186 303
187 char *filename; 304 char *filename;
305
306 if (GNUNET_YES != store->write_links)
307 goto save_entries;
308
309 GNUNET_asprintf (&filename, "%s%s", directory, "links.store");
310
311 save.store = store;
312 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
313
314 if (!save.storage)
315 goto save_entries;
316
317 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
318 goto close_links;
319
320 GNUNET_CONTAINER_multihashmap_iterate (store->links, iterate_save_links, &save);
321 store->write_links = GNUNET_NO;
322
323close_links:
324 GNUNET_DISK_file_close (save.storage);
325
326save_entries:
327 GNUNET_free(filename);
188 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store"); 328 GNUNET_asprintf (&filename, "%s%s", directory, "entries.store");
189 329
190 save.store = store; 330 save.store = store;
191 save.storage_entries = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission); 331 save.storage = GNUNET_DISK_file_open (filename, GNUNET_DISK_OPEN_WRITE | GNUNET_DISK_OPEN_CREATE, permission);
192 332
193 GNUNET_free(filename); 333 GNUNET_free(filename);
194 334
195 if (!save.storage_entries) 335 if (!save.storage)
196 return; 336 return;
197 337
198 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage_entries, 0, GNUNET_DISK_SEEK_END)) 338 if (GNUNET_YES == store->rewrite_entries)
339 {
340 if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_SET))
341 goto close_entries;
342
343 GNUNET_CONTAINER_multihashmap_iterate (store->entries, iterate_save_entries, &save);
344 store->rewrite_entries = GNUNET_NO;
345 }
346 else if (GNUNET_SYSERR == GNUNET_DISK_file_seek (save.storage, 0, GNUNET_DISK_SEEK_END))
199 goto close_entries; 347 goto close_entries;
200 348
201 if (store->storage_messages) 349 if (store->storage_messages)
@@ -213,16 +361,18 @@ save_message_store (struct GNUNET_MESSENGER_MessageStore *store, const char *dir
213 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save); 361 GNUNET_CONTAINER_multihashmap_iterate (store->messages, iterate_save_messages, &save);
214 362
215 GNUNET_DISK_file_sync (store->storage_messages); 363 GNUNET_DISK_file_sync (store->storage_messages);
216 GNUNET_DISK_file_sync (save.storage_entries); 364 GNUNET_DISK_file_sync (save.storage);
217 } 365 }
218 366
219close_entries: 367close_entries:
220 GNUNET_DISK_file_close (save.storage_entries); 368 GNUNET_DISK_file_close (save.storage);
221} 369}
222 370
223int 371int
224contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 372contains_store_message (const struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
225{ 373{
374 GNUNET_assert((store) && (hash));
375
226 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash)) 376 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (store->messages, hash))
227 return GNUNET_YES; 377 return GNUNET_YES;
228 378
@@ -232,6 +382,8 @@ contains_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struc
232const struct GNUNET_MESSENGER_Message* 382const struct GNUNET_MESSENGER_Message*
233get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash) 383get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
234{ 384{
385 GNUNET_assert((store) && (hash));
386
235 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash); 387 struct GNUNET_MESSENGER_Message *message = GNUNET_CONTAINER_multihashmap_get (store->messages, hash);
236 388
237 if (message) 389 if (message)
@@ -250,33 +402,141 @@ get_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNU
250 402
251 char *buffer = GNUNET_malloc(entry->length); 403 char *buffer = GNUNET_malloc(entry->length);
252 404
405 if (!buffer)
406 return NULL;
407
253 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length) 408 if (GNUNET_DISK_file_read (store->storage_messages, buffer, entry->length) != entry->length)
254 goto free_buffer; 409 goto free_buffer;
255 410
256
257 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN); 411 message = create_message (GNUNET_MESSENGER_KIND_UNKNOWN);
258 412
259 if ((GNUNET_YES != decode_message (message, entry->length, buffer)) || (GNUNET_OK 413 const int decoding = decode_message (message, entry->length, buffer, GNUNET_YES, NULL);
260 != GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
261 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)))
262 {
263 destroy_message (message);
264 414
265 message = NULL; 415 struct GNUNET_HashCode check;
416 hash_message (message, entry->length, buffer, &check);
266 417
418 if ((GNUNET_YES != decoding) || (GNUNET_CRYPTO_hash_cmp (hash, &check) != 0))
419 {
267 GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry); 420 GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry);
421 store->rewrite_entries = GNUNET_YES;
422
423 goto free_message;
268 } 424 }
269 425
426 if (GNUNET_OK == GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
427 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
428 goto free_buffer;
429
430free_message: destroy_message (message);
431 message = NULL;
432
270free_buffer: 433free_buffer:
271 GNUNET_free(buffer); 434 GNUNET_free(buffer);
272 435
273 return message; 436 return message;
274} 437}
275 438
439const struct GNUNET_MESSENGER_MessageLink*
440get_store_message_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
441 int deleted_only)
442{
443 if (deleted_only)
444 goto get_link;
445
446 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
447
448 if (!message)
449 goto get_link;
450
451 static struct GNUNET_MESSENGER_MessageLink link;
452
453 GNUNET_memcpy(&(link.first), &(message->header.previous), sizeof(link.first));
454
455 link.multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
456
457 if (GNUNET_YES == link.multiple)
458 GNUNET_memcpy(&(link.second), &(message->body.merge.previous), sizeof(link.second));
459 else
460 GNUNET_memcpy(&(link.second), &(message->header.previous), sizeof(link.second));
461
462 return &link;
463
464get_link:
465 return GNUNET_CONTAINER_multihashmap_get (store->links, hash);
466}
467
276int 468int
277put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash, 469put_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
278 struct GNUNET_MESSENGER_Message *message) 470 struct GNUNET_MESSENGER_Message *message)
279{ 471{
472 GNUNET_assert((store) && (hash) && (message));
473
280 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message, 474 return GNUNET_CONTAINER_multihashmap_put (store->messages, hash, message,
281 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); 475 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
282} 476}
477
478static void
479add_link (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash,
480 const struct GNUNET_MESSENGER_Message *message)
481{
482 struct GNUNET_MESSENGER_MessageLink *link = GNUNET_new(struct GNUNET_MESSENGER_MessageLink);
483
484 GNUNET_memcpy(&(link->first), &(message->header.previous), sizeof(link->first));
485
486 link->multiple = GNUNET_MESSENGER_KIND_MERGE == message->header.kind? GNUNET_YES : GNUNET_NO;
487
488 if (GNUNET_YES == link->multiple)
489 GNUNET_memcpy(&(link->second), &(message->body.merge.previous), sizeof(link->second));
490 else
491 GNUNET_memcpy(&(link->second), &(message->header.previous), sizeof(link->second));
492
493 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(store->links, hash, link,
494 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
495 GNUNET_free(link);
496}
497
498int
499delete_store_message (struct GNUNET_MESSENGER_MessageStore *store, const struct GNUNET_HashCode *hash)
500{
501 GNUNET_assert((store) && (hash));
502
503 const struct GNUNET_MESSENGER_MessageEntry *entry = GNUNET_CONTAINER_multihashmap_get (store->entries, hash);
504
505 if (!entry)
506 goto clear_memory;
507
508 const struct GNUNET_MESSENGER_Message *message = get_store_message(store, hash);
509
510 if (message)
511 add_link (store, hash, message);
512
513 if (!store->storage_messages)
514 goto clear_entry;
515
516 if (entry->offset != GNUNET_DISK_file_seek (store->storage_messages, entry->offset, GNUNET_DISK_SEEK_SET))
517 return GNUNET_SYSERR;
518
519 char *clear_buffer = GNUNET_malloc(entry->length);
520
521 if (!clear_buffer)
522 return GNUNET_SYSERR;
523
524 GNUNET_CRYPTO_zero_keys (clear_buffer, entry->length);
525
526 if ((entry->length != GNUNET_DISK_file_write (store->storage_messages, clear_buffer, entry->length)) || (GNUNET_OK
527 != GNUNET_DISK_file_sync (store->storage_messages)))
528 {
529 GNUNET_free(clear_buffer);
530 return GNUNET_SYSERR;
531 }
532
533 GNUNET_free(clear_buffer);
534
535clear_entry:
536 if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove (store->entries, hash, entry))
537 store->rewrite_entries = GNUNET_YES;
538
539clear_memory:
540 GNUNET_CONTAINER_multihashmap_remove_all (store->messages, hash);
541 return GNUNET_OK;
542}