diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-08-11 14:41:03 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-08-11 14:41:03 +0000 |
commit | 7fe8782a2beffafb0fa3fadae43d4498335f4472 (patch) | |
tree | 1d5982382d50b31e3434f74df1c61fae9d8bb573 /src | |
parent | 7226997d96e7c2724d912553d1c7e613ee4cdd04 (diff) | |
download | gnunet-7fe8782a2beffafb0fa3fadae43d4498335f4472.tar.gz gnunet-7fe8782a2beffafb0fa3fadae43d4498335f4472.zip |
- flat namestore plugin (experimental)
Diffstat (limited to 'src')
-rw-r--r-- | src/namestore/Makefile.am | 27 | ||||
-rw-r--r-- | src/namestore/plugin_namestore_flat.c | 673 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore.c | 4 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore_flat.conf | 2 |
4 files changed, 704 insertions, 2 deletions
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am index 2f8c81425..221e88a91 100644 --- a/src/namestore/Makefile.am +++ b/src/namestore/Makefile.am | |||
@@ -20,6 +20,13 @@ if USE_COVERAGE | |||
20 | XLIBS = -lgcov | 20 | XLIBS = -lgcov |
21 | endif | 21 | endif |
22 | 22 | ||
23 | if HAVE_EXPERIMENTAL | ||
24 | FLAT_PLUGIN = libgnunet_plugin_namestore_flat.la | ||
25 | if HAVE_TESTING | ||
26 | FLAT_TESTS = test_plugin_namestore_flat | ||
27 | endif | ||
28 | endif | ||
29 | |||
23 | if HAVE_SQLITE | 30 | if HAVE_SQLITE |
24 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la | 31 | SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la |
25 | if HAVE_TESTING | 32 | if HAVE_TESTING |
@@ -60,6 +67,7 @@ if HAVE_SQLITE | |||
60 | check_PROGRAMS = \ | 67 | check_PROGRAMS = \ |
61 | $(SQLITE_TESTS) \ | 68 | $(SQLITE_TESTS) \ |
62 | $(POSTGRES_TESTS) \ | 69 | $(POSTGRES_TESTS) \ |
70 | $(FLAT_TESTS) \ | ||
63 | $(TESTING_TESTS) | 71 | $(TESTING_TESTS) |
64 | endif | 72 | endif |
65 | 73 | ||
@@ -150,8 +158,20 @@ gnunet_service_namestore_LDADD = \ | |||
150 | plugin_LTLIBRARIES = \ | 158 | plugin_LTLIBRARIES = \ |
151 | $(SQLITE_PLUGIN) \ | 159 | $(SQLITE_PLUGIN) \ |
152 | $(POSTGRES_PLUGIN) \ | 160 | $(POSTGRES_PLUGIN) \ |
161 | $(FLAT_PLUGIN) \ | ||
153 | $(REST_PLUGIN) | 162 | $(REST_PLUGIN) |
154 | 163 | ||
164 | libgnunet_plugin_namestore_flat_la_SOURCES = \ | ||
165 | plugin_namestore_flat.c | ||
166 | libgnunet_plugin_namestore_flat_la_LIBADD = \ | ||
167 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | ||
168 | $(top_builddir)/src/statistics/libgnunetstatistics.la \ | ||
169 | $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ | ||
170 | $(LTLIBINTL) | ||
171 | libgnunet_plugin_namestore_flat_la_LDFLAGS = \ | ||
172 | $(GN_PLUGIN_LDFLAGS) | ||
173 | |||
174 | |||
155 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ | 175 | libgnunet_plugin_namestore_sqlite_la_SOURCES = \ |
156 | plugin_namestore_sqlite.c | 176 | plugin_namestore_sqlite.c |
157 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ | 177 | libgnunet_plugin_namestore_sqlite_la_LIBADD = \ |
@@ -307,6 +327,12 @@ test_namestore_api_zone_iteration_stop_LDADD = \ | |||
307 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ | 327 | $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \ |
308 | libgnunetnamestore.la | 328 | libgnunetnamestore.la |
309 | 329 | ||
330 | test_plugin_namestore_flat_SOURCES = \ | ||
331 | test_plugin_namestore.c | ||
332 | test_plugin_namestore_flat_LDADD = \ | ||
333 | $(top_builddir)/src/testing/libgnunettesting.la \ | ||
334 | $(top_builddir)/src/util/libgnunetutil.la | ||
335 | |||
310 | test_plugin_namestore_sqlite_SOURCES = \ | 336 | test_plugin_namestore_sqlite_SOURCES = \ |
311 | test_plugin_namestore.c | 337 | test_plugin_namestore.c |
312 | test_plugin_namestore_sqlite_LDADD = \ | 338 | test_plugin_namestore_sqlite_LDADD = \ |
@@ -328,6 +354,7 @@ EXTRA_DIST = \ | |||
328 | test_namestore_api.conf \ | 354 | test_namestore_api.conf \ |
329 | test_plugin_namestore_sqlite.conf \ | 355 | test_plugin_namestore_sqlite.conf \ |
330 | test_plugin_namestore_postgres.conf \ | 356 | test_plugin_namestore_postgres.conf \ |
357 | test_plugin_namestore_flat.conf \ | ||
331 | test_hostkey \ | 358 | test_hostkey \ |
332 | zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey \ | 359 | zonefiles/S5I9DSGQVAB5FVV16T3B3CC5H1B2JGL3Q412JBKURME8EKU0600G.zkey \ |
333 | zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey \ | 360 | zonefiles/AQ835GVL939H4O8QJQ7GBLPTQC0QAAO91BN7QK01BA63MDSK6I4G.zkey \ |
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c new file mode 100644 index 000000000..b2fd70d92 --- /dev/null +++ b/src/namestore/plugin_namestore_flat.c | |||
@@ -0,0 +1,673 @@ | |||
1 | /* | ||
2 | * This file is part of GNUnet | ||
3 | * Copyright (C) 2009-2015 Christian Grothoff (and other contributing authors) | ||
4 | * | ||
5 | * GNUnet is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published | ||
7 | * by the Free Software Foundation; either version 3, or (at your | ||
8 | * 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 | * General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with GNUnet; see the file COPYING. If not, write to the | ||
17 | * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
18 | * Boston, MA 02110-1301, USA. | ||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file namestore/plugin_namestore_flat.c | ||
23 | * @brief file-based namestore backend | ||
24 | * @author Martin Schanzenbach | ||
25 | */ | ||
26 | |||
27 | #include "platform.h" | ||
28 | #include "gnunet_namestore_plugin.h" | ||
29 | #include "gnunet_namestore_service.h" | ||
30 | #include "gnunet_gnsrecord_lib.h" | ||
31 | #include "namestore.h" | ||
32 | |||
33 | /** | ||
34 | * Context for all functions in this plugin. | ||
35 | */ | ||
36 | struct Plugin | ||
37 | { | ||
38 | |||
39 | const struct GNUNET_CONFIGURATION_Handle *cfg; | ||
40 | |||
41 | /** | ||
42 | * Database filename. | ||
43 | */ | ||
44 | char *fn; | ||
45 | |||
46 | /** | ||
47 | * HashMap | ||
48 | */ | ||
49 | struct GNUNET_CONTAINER_MultiHashMap *hm; | ||
50 | |||
51 | /** | ||
52 | * Offset | ||
53 | */ | ||
54 | uint32_t offset; | ||
55 | |||
56 | /** | ||
57 | * Target Offset | ||
58 | */ | ||
59 | uint32_t target_offset; | ||
60 | |||
61 | /** | ||
62 | * Iterator closure | ||
63 | */ | ||
64 | void *iter_cls; | ||
65 | |||
66 | /** | ||
67 | * Iterator | ||
68 | */ | ||
69 | GNUNET_NAMESTORE_RecordIterator iter; | ||
70 | |||
71 | /** | ||
72 | * Zone to iterate | ||
73 | */ | ||
74 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *iter_zone; | ||
75 | |||
76 | /** | ||
77 | * PKEY to look for in zone to name | ||
78 | */ | ||
79 | struct GNUNET_CRYPTO_EcdsaPublicKey *iter_pkey; | ||
80 | |||
81 | /** | ||
82 | * Iteration result found | ||
83 | */ | ||
84 | int iter_result_found; | ||
85 | |||
86 | }; | ||
87 | |||
88 | struct FlatFileEntry | ||
89 | { | ||
90 | /** | ||
91 | * Entry zone | ||
92 | */ | ||
93 | struct GNUNET_CRYPTO_EcdsaPrivateKey *private_key; | ||
94 | |||
95 | /** | ||
96 | * Entry zone pkey | ||
97 | */ | ||
98 | struct GNUNET_CRYPTO_EcdsaPublicKey *pkey; | ||
99 | |||
100 | /** | ||
101 | * Record cound | ||
102 | */ | ||
103 | uint32_t record_count; | ||
104 | |||
105 | /** | ||
106 | * Rvalue | ||
107 | */ | ||
108 | uint64_t rvalue; | ||
109 | |||
110 | /** | ||
111 | * Record data | ||
112 | */ | ||
113 | struct GNUNET_GNSRECORD_Data *record_data; | ||
114 | |||
115 | /** | ||
116 | * Label | ||
117 | */ | ||
118 | char *label; | ||
119 | |||
120 | |||
121 | }; | ||
122 | |||
123 | |||
124 | /** | ||
125 | * Initialize the database connections and associated | ||
126 | * data structures (create tables and indices | ||
127 | * as needed as well). | ||
128 | * | ||
129 | * @param plugin the plugin context (state for this module) | ||
130 | * @return #GNUNET_OK on success | ||
131 | */ | ||
132 | static int | ||
133 | database_setup (struct Plugin *plugin) | ||
134 | { | ||
135 | char *afsdir; | ||
136 | char *key_str; | ||
137 | char *record_data; | ||
138 | char *zone_private_key; | ||
139 | char *pkey; | ||
140 | char *record_data_b64; | ||
141 | char *buffer; | ||
142 | char *line; | ||
143 | char *label; | ||
144 | char *rvalue; | ||
145 | char *record_count; | ||
146 | size_t record_data_size; | ||
147 | size_t size; | ||
148 | struct GNUNET_HashCode hkey; | ||
149 | struct GNUNET_DISK_FileHandle *fh; | ||
150 | struct FlatFileEntry *entry; | ||
151 | |||
152 | if (GNUNET_OK != | ||
153 | GNUNET_CONFIGURATION_get_value_filename (plugin->cfg, | ||
154 | "namestore-flat", | ||
155 | "FILENAME", &afsdir)) | ||
156 | { | ||
157 | GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, | ||
158 | "namestore-flat", "FILENAME"); | ||
159 | return GNUNET_SYSERR; | ||
160 | } | ||
161 | if (GNUNET_OK != GNUNET_DISK_file_test (afsdir)) | ||
162 | { | ||
163 | if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir)) | ||
164 | { | ||
165 | GNUNET_break (0); | ||
166 | GNUNET_free (afsdir); | ||
167 | return GNUNET_SYSERR; | ||
168 | } | ||
169 | } | ||
170 | /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */ | ||
171 | plugin->fn = afsdir; | ||
172 | |||
173 | /* Load data from file into hashmap */ | ||
174 | plugin->hm = GNUNET_CONTAINER_multihashmap_create (10, | ||
175 | GNUNET_NO); | ||
176 | fh = GNUNET_DISK_file_open (afsdir, | ||
177 | GNUNET_DISK_OPEN_CREATE, | ||
178 | GNUNET_DISK_PERM_USER_WRITE | | ||
179 | GNUNET_DISK_PERM_USER_READ); | ||
180 | if (NULL == fh) | ||
181 | { | ||
182 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
183 | _("Unable to initialize file: %s.\n"), | ||
184 | afsdir); | ||
185 | return GNUNET_SYSERR; | ||
186 | } | ||
187 | |||
188 | if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir, | ||
189 | &size, | ||
190 | GNUNET_YES, | ||
191 | GNUNET_YES)) | ||
192 | { | ||
193 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
194 | _("Unable to get filesize: %s.\n"), | ||
195 | afsdir); | ||
196 | return GNUNET_SYSERR; | ||
197 | } | ||
198 | |||
199 | buffer = GNUNET_malloc (size); | ||
200 | |||
201 | if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh, | ||
202 | buffer, | ||
203 | size)) | ||
204 | { | ||
205 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
206 | _("Unable to read file: %s.\n"), | ||
207 | afsdir); | ||
208 | return GNUNET_SYSERR; | ||
209 | } | ||
210 | |||
211 | GNUNET_DISK_file_close (fh); | ||
212 | |||
213 | line = strtok ("\n", buffer); | ||
214 | while (line != NULL) { | ||
215 | zone_private_key = strtok (",", line); | ||
216 | pkey = strtok (NULL, line); | ||
217 | rvalue = strtok (NULL, line); | ||
218 | record_count = strtok (NULL, line); | ||
219 | record_data_b64 = strtok (NULL, line); | ||
220 | label = strtok (NULL, line); | ||
221 | line = strtok ("\n", buffer); | ||
222 | entry = GNUNET_malloc (sizeof (struct FlatFileEntry)); | ||
223 | GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey, | ||
224 | strlen (pkey), | ||
225 | entry->pkey); | ||
226 | sscanf (rvalue, "%lu", &entry->rvalue); | ||
227 | sscanf (record_count, "%u", &entry->record_count); | ||
228 | entry->label = GNUNET_strdup (label); | ||
229 | record_data_size = GNUNET_STRINGS_base64_decode (record_data_b64, | ||
230 | strlen (record_data_b64), | ||
231 | &record_data); | ||
232 | entry->record_data = | ||
233 | GNUNET_malloc (sizeof (struct GNUNET_GNSRECORD_Data) * entry->record_count); | ||
234 | GNUNET_GNSRECORD_records_deserialize (record_data_size, | ||
235 | record_data, | ||
236 | entry->record_count, | ||
237 | entry->record_data); | ||
238 | GNUNET_free (record_data); | ||
239 | GNUNET_STRINGS_base64_decode (zone_private_key, | ||
240 | strlen (zone_private_key), | ||
241 | (char**)&entry->private_key); | ||
242 | key_str = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
243 | memcpy (key_str, label, strlen (label)); | ||
244 | memcpy (key_str+strlen(label), | ||
245 | entry->private_key, | ||
246 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
247 | GNUNET_CRYPTO_hash (key_str, | ||
248 | strlen (key_str), | ||
249 | &hkey); | ||
250 | GNUNET_free (key_str); | ||
251 | if (GNUNET_OK != | ||
252 | GNUNET_CONTAINER_multihashmap_put (plugin->hm, | ||
253 | &hkey, | ||
254 | entry, | ||
255 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY)) | ||
256 | { | ||
257 | GNUNET_free (entry); | ||
258 | GNUNET_break (0); | ||
259 | } | ||
260 | } | ||
261 | GNUNET_free (buffer); | ||
262 | return GNUNET_OK; | ||
263 | } | ||
264 | |||
265 | |||
266 | /** | ||
267 | * Store values in hashmap in file and free data | ||
268 | * | ||
269 | * @param plugin the plugin context | ||
270 | */ | ||
271 | static int | ||
272 | store_and_free_entries (void *cls, | ||
273 | const struct GNUNET_HashCode *key, | ||
274 | void *value) | ||
275 | { | ||
276 | struct GNUNET_DISK_FileHandle *fh = cls; | ||
277 | struct FlatFileEntry *entry = value; | ||
278 | char *line; | ||
279 | char *zone_private_key; | ||
280 | char *pkey; | ||
281 | char *rvalue; | ||
282 | char *record_count; | ||
283 | char *record_data_buf; | ||
284 | char *record_data_b64; | ||
285 | size_t record_data_len; | ||
286 | |||
287 | GNUNET_STRINGS_base64_encode ((char*)entry->private_key, | ||
288 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey), | ||
289 | &zone_private_key); | ||
290 | pkey = GNUNET_CRYPTO_ecdsa_public_key_to_string (entry->pkey); | ||
291 | GNUNET_asprintf (&rvalue, "%hhu", entry->rvalue); | ||
292 | GNUNET_asprintf (&record_count, "%u", entry->record_count); | ||
293 | |||
294 | record_data_len = GNUNET_GNSRECORD_records_get_size (entry->record_count, | ||
295 | entry->record_data); | ||
296 | |||
297 | record_data_buf = GNUNET_malloc (record_data_len); | ||
298 | GNUNET_GNSRECORD_records_serialize (entry->record_count, | ||
299 | entry->record_data, | ||
300 | record_data_len, | ||
301 | record_data_buf); | ||
302 | |||
303 | GNUNET_STRINGS_base64_encode (record_data_buf, | ||
304 | strlen (record_data_buf), | ||
305 | &record_data_b64); | ||
306 | |||
307 | GNUNET_asprintf (&line, | ||
308 | "%s.%s.%s.%s.%s.%s\n", | ||
309 | zone_private_key, | ||
310 | pkey, | ||
311 | rvalue, | ||
312 | record_count, | ||
313 | record_data_b64, | ||
314 | entry->label); | ||
315 | |||
316 | GNUNET_free (rvalue); | ||
317 | GNUNET_free (record_count); | ||
318 | GNUNET_free (record_data_buf); | ||
319 | GNUNET_free (record_data_b64); | ||
320 | |||
321 | GNUNET_DISK_file_write (fh, | ||
322 | line, | ||
323 | strlen (line)); | ||
324 | |||
325 | GNUNET_free (entry->private_key); | ||
326 | GNUNET_free (entry->pkey); | ||
327 | GNUNET_free (entry->label); | ||
328 | GNUNET_free (entry->record_data); | ||
329 | GNUNET_free (entry); | ||
330 | return GNUNET_YES; | ||
331 | } | ||
332 | |||
333 | /** | ||
334 | * Shutdown database connection and associate data | ||
335 | * structures. | ||
336 | * @param plugin the plugin context (state for this module) | ||
337 | */ | ||
338 | static void | ||
339 | database_shutdown (struct Plugin *plugin) | ||
340 | { | ||
341 | struct GNUNET_DISK_FileHandle *fh; | ||
342 | fh = GNUNET_DISK_file_open (plugin->fn, | ||
343 | GNUNET_DISK_OPEN_CREATE | | ||
344 | GNUNET_DISK_OPEN_TRUNCATE, | ||
345 | GNUNET_DISK_PERM_USER_WRITE | | ||
346 | GNUNET_DISK_PERM_USER_READ); | ||
347 | if (NULL == fh) | ||
348 | { | ||
349 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
350 | _("Unable to initialize file: %s.\n"), | ||
351 | plugin->fn); | ||
352 | return; | ||
353 | } | ||
354 | |||
355 | GNUNET_CONTAINER_multihashmap_iterate (plugin->hm, | ||
356 | &store_and_free_entries, | ||
357 | fh); | ||
358 | GNUNET_CONTAINER_multihashmap_destroy (plugin->hm); | ||
359 | GNUNET_DISK_file_close (fh); | ||
360 | } | ||
361 | |||
362 | |||
363 | /** | ||
364 | * Store a record in the datastore. Removes any existing record in the | ||
365 | * same zone with the same name. | ||
366 | * | ||
367 | * @param cls closure (internal context for the plugin) | ||
368 | * @param zone_key private key of the zone | ||
369 | * @param label name that is being mapped (at most 255 characters long) | ||
370 | * @param rd_count number of entries in @a rd array | ||
371 | * @param rd array of records with data to store | ||
372 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
373 | */ | ||
374 | static int | ||
375 | namestore_store_records (void *cls, | ||
376 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone_key, | ||
377 | const char *label, | ||
378 | unsigned int rd_count, | ||
379 | const struct GNUNET_GNSRECORD_Data *rd) | ||
380 | { | ||
381 | struct Plugin *plugin = cls; | ||
382 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | ||
383 | uint64_t rvalue; | ||
384 | size_t data_size; | ||
385 | unsigned int i; | ||
386 | char *key_str; | ||
387 | struct GNUNET_HashCode hkey; | ||
388 | struct FlatFileEntry *entry; | ||
389 | |||
390 | memset (&pkey, 0, sizeof (pkey)); | ||
391 | for (i=0;i<rd_count;i++) | ||
392 | if (GNUNET_GNSRECORD_TYPE_PKEY == rd[i].record_type) | ||
393 | { | ||
394 | GNUNET_break (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey) == rd[i].data_size); | ||
395 | memcpy (&pkey, | ||
396 | rd[i].data, | ||
397 | rd[i].data_size); | ||
398 | break; | ||
399 | } | ||
400 | rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK, UINT64_MAX); | ||
401 | data_size = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | ||
402 | if (data_size > 64 * 65536) | ||
403 | { | ||
404 | GNUNET_break (0); | ||
405 | return GNUNET_SYSERR; | ||
406 | } | ||
407 | char data[data_size]; | ||
408 | |||
409 | if (data_size != GNUNET_GNSRECORD_records_serialize (rd_count, rd, | ||
410 | data_size, data)) | ||
411 | { | ||
412 | GNUNET_break (0); | ||
413 | return GNUNET_SYSERR; | ||
414 | } | ||
415 | |||
416 | key_str = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
417 | memcpy (key_str, label, strlen (label)); | ||
418 | memcpy (key_str+strlen(label), | ||
419 | zone_key, | ||
420 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
421 | GNUNET_CRYPTO_hash (key_str, | ||
422 | strlen (key_str), | ||
423 | &hkey); | ||
424 | |||
425 | GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, &hkey); | ||
426 | |||
427 | if (0 != rd_count) | ||
428 | { | ||
429 | entry = GNUNET_malloc (sizeof (struct FlatFileEntry)); | ||
430 | entry->private_key = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
431 | memcpy (&entry->private_key, | ||
432 | zone_key, | ||
433 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
434 | entry->pkey = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
435 | memcpy (entry->pkey, | ||
436 | &pkey, | ||
437 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
438 | entry->rvalue = rvalue; | ||
439 | entry->record_count = rd_count; | ||
440 | entry->record_data = GNUNET_malloc (data_size); | ||
441 | memcpy (&entry->record_data, data, data_size); | ||
442 | return GNUNET_CONTAINER_multihashmap_put (plugin->hm, | ||
443 | &hkey, | ||
444 | entry, | ||
445 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY); | ||
446 | } | ||
447 | return GNUNET_NO; | ||
448 | } | ||
449 | |||
450 | |||
451 | /** | ||
452 | * Lookup records in the datastore for which we are the authority. | ||
453 | * | ||
454 | * @param cls closure (internal context for the plugin) | ||
455 | * @param zone private key of the zone | ||
456 | * @param label name of the record in the zone | ||
457 | * @param iter function to call with the result | ||
458 | * @param iter_cls closure for @a iter | ||
459 | * @return #GNUNET_OK on success, else #GNUNET_SYSERR | ||
460 | */ | ||
461 | static int | ||
462 | namestore_lookup_records (void *cls, | ||
463 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
464 | const char *label, | ||
465 | GNUNET_NAMESTORE_RecordIterator iter, | ||
466 | void *iter_cls) | ||
467 | { | ||
468 | struct Plugin *plugin = cls; | ||
469 | struct FlatFileEntry *entry; | ||
470 | struct GNUNET_HashCode hkey; | ||
471 | char *key_str; | ||
472 | |||
473 | if (NULL == zone) | ||
474 | { | ||
475 | return GNUNET_SYSERR; | ||
476 | } | ||
477 | key_str = GNUNET_malloc (strlen (label) + sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
478 | memcpy (key_str, label, strlen (label)); | ||
479 | memcpy (key_str+strlen(label), | ||
480 | zone, | ||
481 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)); | ||
482 | GNUNET_CRYPTO_hash (key_str, | ||
483 | strlen (key_str), | ||
484 | &hkey); | ||
485 | GNUNET_free (key_str); | ||
486 | |||
487 | entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm, &hkey); | ||
488 | |||
489 | if (NULL == entry) | ||
490 | return GNUNET_NO; | ||
491 | if (NULL != iter) | ||
492 | iter (iter_cls, entry->private_key, entry->label, entry->record_count, entry->record_data); | ||
493 | return GNUNET_YES; | ||
494 | } | ||
495 | |||
496 | |||
497 | static int | ||
498 | iterate_zones (void *cls, | ||
499 | const struct GNUNET_HashCode *key, | ||
500 | void *value) | ||
501 | { | ||
502 | struct Plugin *plugin = cls; | ||
503 | struct FlatFileEntry *entry = value; | ||
504 | |||
505 | |||
506 | if ((plugin->target_offset > plugin->offset) || | ||
507 | (0 != memcmp (entry->private_key, | ||
508 | plugin->iter_zone, | ||
509 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey)))) { | ||
510 | plugin->offset++; | ||
511 | return GNUNET_YES; | ||
512 | } | ||
513 | |||
514 | plugin->iter (plugin->iter_cls, | ||
515 | entry->private_key, | ||
516 | entry->label, | ||
517 | entry->record_count, | ||
518 | entry->record_data); | ||
519 | plugin->iter_result_found = GNUNET_YES; | ||
520 | return GNUNET_NO; | ||
521 | } | ||
522 | |||
523 | /** | ||
524 | * Iterate over the results for a particular key and zone in the | ||
525 | * datastore. Will return at most one result to the iterator. | ||
526 | * | ||
527 | * @param cls closure (internal context for the plugin) | ||
528 | * @param zone hash of public key of the zone, NULL to iterate over all zones | ||
529 | * @param offset offset in the list of all matching records | ||
530 | * @param iter function to call with the result | ||
531 | * @param iter_cls closure for @a iter | ||
532 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
533 | */ | ||
534 | static int | ||
535 | namestore_iterate_records (void *cls, | ||
536 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
537 | uint64_t offset, | ||
538 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | ||
539 | { | ||
540 | struct Plugin *plugin = cls; | ||
541 | plugin->target_offset = offset; | ||
542 | plugin->offset = 0; | ||
543 | plugin->iter = iter; | ||
544 | plugin->iter_cls = cls; | ||
545 | plugin->iter_zone = zone; | ||
546 | plugin->iter_result_found = GNUNET_NO; | ||
547 | GNUNET_CONTAINER_multihashmap_iterate (plugin->hm, | ||
548 | &iterate_zones, | ||
549 | plugin); | ||
550 | return plugin->iter_result_found; | ||
551 | } | ||
552 | |||
553 | static int | ||
554 | zone_to_name (void *cls, | ||
555 | const struct GNUNET_HashCode *key, | ||
556 | void *value) | ||
557 | { | ||
558 | struct Plugin *plugin = cls; | ||
559 | struct FlatFileEntry *entry = value; | ||
560 | int i; | ||
561 | |||
562 | if (0 != memcmp (entry->private_key, | ||
563 | plugin->iter_zone, | ||
564 | sizeof (struct GNUNET_CRYPTO_EcdsaPrivateKey))) | ||
565 | return GNUNET_YES; | ||
566 | |||
567 | for (i = 0; i < entry->record_count; i++) { | ||
568 | if (GNUNET_GNSRECORD_TYPE_PKEY != entry->record_data[i].record_type) | ||
569 | continue; | ||
570 | if (0 == memcmp (plugin->iter_pkey, | ||
571 | entry->record_data[i].data, | ||
572 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey))) | ||
573 | { | ||
574 | plugin->iter (plugin->iter_cls, | ||
575 | entry->private_key, | ||
576 | entry->label, | ||
577 | entry->record_count, | ||
578 | entry->record_data); | ||
579 | plugin->iter_result_found = GNUNET_YES; | ||
580 | |||
581 | } | ||
582 | } | ||
583 | |||
584 | return GNUNET_YES; | ||
585 | } | ||
586 | |||
587 | /** | ||
588 | * Look for an existing PKEY delegation record for a given public key. | ||
589 | * Returns at most one result to the iterator. | ||
590 | * | ||
591 | * @param cls closure (internal context for the plugin) | ||
592 | * @param zone private key of the zone to look up in, never NULL | ||
593 | * @param value_zone public key of the target zone (value), never NULL | ||
594 | * @param iter function to call with the result | ||
595 | * @param iter_cls closure for @a iter | ||
596 | * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error | ||
597 | */ | ||
598 | static int | ||
599 | namestore_zone_to_name (void *cls, | ||
600 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone, | ||
601 | const struct GNUNET_CRYPTO_EcdsaPublicKey *value_zone, | ||
602 | GNUNET_NAMESTORE_RecordIterator iter, void *iter_cls) | ||
603 | { | ||
604 | struct Plugin *plugin = cls; | ||
605 | |||
606 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
607 | "Performing reverse lookup for `%s'\n", | ||
608 | GNUNET_GNSRECORD_z2s (value_zone)); | ||
609 | |||
610 | GNUNET_CONTAINER_multihashmap_iterate (plugin->hm, | ||
611 | &zone_to_name, | ||
612 | plugin); | ||
613 | |||
614 | |||
615 | return plugin->iter_result_found; | ||
616 | } | ||
617 | |||
618 | |||
619 | /** | ||
620 | * Entry point for the plugin. | ||
621 | * | ||
622 | * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*" | ||
623 | * @return NULL on error, otherwise the plugin context | ||
624 | */ | ||
625 | void * | ||
626 | libgnunet_plugin_namestore_flat_init (void *cls) | ||
627 | { | ||
628 | static struct Plugin plugin; | ||
629 | const struct GNUNET_CONFIGURATION_Handle *cfg = cls; | ||
630 | struct GNUNET_NAMESTORE_PluginFunctions *api; | ||
631 | |||
632 | if (NULL != plugin.cfg) | ||
633 | return NULL; /* can only initialize once! */ | ||
634 | memset (&plugin, 0, sizeof (struct Plugin)); | ||
635 | plugin.cfg = cfg; | ||
636 | if (GNUNET_OK != database_setup (&plugin)) | ||
637 | { | ||
638 | database_shutdown (&plugin); | ||
639 | return NULL; | ||
640 | } | ||
641 | api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions); | ||
642 | api->cls = &plugin; | ||
643 | api->store_records = &namestore_store_records; | ||
644 | api->iterate_records = &namestore_iterate_records; | ||
645 | api->zone_to_name = &namestore_zone_to_name; | ||
646 | api->lookup_records = &namestore_lookup_records; | ||
647 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
648 | _("flat file database running\n")); | ||
649 | return api; | ||
650 | } | ||
651 | |||
652 | |||
653 | /** | ||
654 | * Exit point from the plugin. | ||
655 | * | ||
656 | * @param cls the plugin context (as returned by "init") | ||
657 | * @return always NULL | ||
658 | */ | ||
659 | void * | ||
660 | libgnunet_plugin_namestore_flat_done (void *cls) | ||
661 | { | ||
662 | struct GNUNET_NAMESTORE_PluginFunctions *api = cls; | ||
663 | struct Plugin *plugin = api->cls; | ||
664 | |||
665 | database_shutdown (plugin); | ||
666 | plugin->cfg = NULL; | ||
667 | GNUNET_free (api); | ||
668 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
669 | "flat file plugin is finished\n"); | ||
670 | return NULL; | ||
671 | } | ||
672 | |||
673 | /* end of plugin_namestore_flat.c */ | ||
diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c index 4c98bdaa1..9c358abe8 100644 --- a/src/namestore/test_plugin_namestore.c +++ b/src/namestore/test_plugin_namestore.c | |||
@@ -182,7 +182,7 @@ main (int argc, char *argv[]) | |||
182 | GNUNET_GETOPT_OPTION_END | 182 | GNUNET_GETOPT_OPTION_END |
183 | }; | 183 | }; |
184 | 184 | ||
185 | GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); | 185 | //GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); |
186 | GNUNET_log_setup ("test-plugin-namestore", | 186 | GNUNET_log_setup ("test-plugin-namestore", |
187 | "WARNING", | 187 | "WARNING", |
188 | NULL); | 188 | NULL); |
@@ -193,7 +193,7 @@ main (int argc, char *argv[]) | |||
193 | "test-plugin-namestore", "nohelp", options, &run, NULL); | 193 | "test-plugin-namestore", "nohelp", options, &run, NULL); |
194 | if (ok != 0) | 194 | if (ok != 0) |
195 | FPRINTF (stderr, "Missed some testcases: %d\n", ok); | 195 | FPRINTF (stderr, "Missed some testcases: %d\n", ok); |
196 | GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); | 196 | //GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namestore-sqlite"); |
197 | return ok; | 197 | return ok; |
198 | } | 198 | } |
199 | 199 | ||
diff --git a/src/namestore/test_plugin_namestore_flat.conf b/src/namestore/test_plugin_namestore_flat.conf new file mode 100644 index 000000000..2909d76e1 --- /dev/null +++ b/src/namestore/test_plugin_namestore_flat.conf | |||
@@ -0,0 +1,2 @@ | |||
1 | [namestore-flat] | ||
2 | FILENAME = /tmp/gnunet-test-plugin-namestore-sqlite/flatdb | ||