plugin_namestore_flat.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. * This file is part of GNUnet
  3. * Copyright (C) 2009-2015, 2018, 2019 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. SPDX-License-Identifier: AGPL3.0-or-later
  18. */
  19. /**
  20. * @file namestore/plugin_namestore_flat.c
  21. * @brief file-based namestore backend
  22. * @author Martin Schanzenbach
  23. * @author Christian Grothoff
  24. */
  25. #include "platform.h"
  26. #include "gnunet_namestore_plugin.h"
  27. #include "gnunet_namestore_service.h"
  28. #include "gnunet_gnsrecord_lib.h"
  29. #include "namestore.h"
  30. /**
  31. * Context for all functions in this plugin.
  32. */
  33. struct Plugin
  34. {
  35. const struct GNUNET_CONFIGURATION_Handle *cfg;
  36. /**
  37. * Database filename.
  38. */
  39. char *fn;
  40. /**
  41. * HashMap
  42. */
  43. struct GNUNET_CONTAINER_MultiHashMap *hm;
  44. };
  45. struct FlatFileEntry
  46. {
  47. /**
  48. * Entry zone
  49. */
  50. struct GNUNET_IDENTITY_PrivateKey private_key;
  51. /**
  52. * Record cound
  53. */
  54. uint32_t record_count;
  55. /**
  56. * Rvalue
  57. */
  58. uint64_t rvalue;
  59. /**
  60. * Record data
  61. */
  62. struct GNUNET_GNSRECORD_Data *record_data;
  63. /**
  64. * Label
  65. */
  66. char *label;
  67. };
  68. /**
  69. * Hash contactenation of @a pkey and @a label into @a h
  70. *
  71. * @param pkey a key
  72. * @param label a label
  73. * @param h[out] initialized hash
  74. */
  75. static void
  76. hash_pkey_and_label (const struct GNUNET_IDENTITY_PrivateKey *pkey,
  77. const char *label,
  78. struct GNUNET_HashCode *h)
  79. {
  80. char *key;
  81. size_t label_len;
  82. size_t key_len;
  83. label_len = strlen (label);
  84. key_len = label_len + sizeof(struct GNUNET_IDENTITY_PrivateKey);
  85. key = GNUNET_malloc (key_len);
  86. GNUNET_memcpy (key,
  87. label,
  88. label_len);
  89. GNUNET_memcpy (key + label_len,
  90. pkey,
  91. sizeof(struct GNUNET_IDENTITY_PrivateKey));
  92. GNUNET_CRYPTO_hash (key,
  93. key_len,
  94. h);
  95. GNUNET_free (key);
  96. }
  97. /**
  98. * Initialize the database connections and associated
  99. * data structures (create tables and indices
  100. * as needed as well).
  101. *
  102. * @param plugin the plugin context (state for this module)
  103. * @return #GNUNET_OK on success
  104. */
  105. static int
  106. database_setup (struct Plugin *plugin)
  107. {
  108. char *flatdbfile;
  109. char *record_data;
  110. char *zone_private_key;
  111. char *record_data_b64;
  112. char *buffer;
  113. char *line;
  114. char *label;
  115. char *rvalue;
  116. char *record_count;
  117. size_t record_data_size;
  118. uint64_t size;
  119. struct GNUNET_HashCode hkey;
  120. struct GNUNET_DISK_FileHandle *fh;
  121. struct FlatFileEntry *entry;
  122. struct GNUNET_DISK_MapHandle *mh;
  123. if (GNUNET_OK !=
  124. GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
  125. "namestore-flat",
  126. "FILENAME",
  127. &flatdbfile))
  128. {
  129. GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
  130. "namestore-flat",
  131. "FILENAME");
  132. return GNUNET_SYSERR;
  133. }
  134. if (GNUNET_OK !=
  135. GNUNET_DISK_file_test (flatdbfile))
  136. {
  137. if (GNUNET_OK !=
  138. GNUNET_DISK_directory_create_for_file (flatdbfile))
  139. {
  140. GNUNET_break (0);
  141. GNUNET_free (flatdbfile);
  142. return GNUNET_SYSERR;
  143. }
  144. }
  145. /* flatdbfile should be UTF-8-encoded. If it isn't, it's a bug */
  146. plugin->fn = flatdbfile;
  147. /* Load data from file into hashmap */
  148. plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
  149. GNUNET_NO);
  150. fh = GNUNET_DISK_file_open (flatdbfile,
  151. GNUNET_DISK_OPEN_CREATE
  152. | GNUNET_DISK_OPEN_READWRITE,
  153. GNUNET_DISK_PERM_USER_WRITE
  154. | GNUNET_DISK_PERM_USER_READ);
  155. if (NULL == fh)
  156. {
  157. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  158. _ ("Unable to initialize file: %s.\n"),
  159. flatdbfile);
  160. return GNUNET_SYSERR;
  161. }
  162. if (GNUNET_SYSERR ==
  163. GNUNET_DISK_file_size (flatdbfile,
  164. &size,
  165. GNUNET_YES,
  166. GNUNET_YES))
  167. {
  168. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  169. _ ("Unable to get filesize: %s.\n"),
  170. flatdbfile);
  171. GNUNET_DISK_file_close (fh);
  172. return GNUNET_SYSERR;
  173. }
  174. if (size > SIZE_MAX)
  175. {
  176. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  177. _ ("File too big to map: %llu bytes.\n"),
  178. (unsigned long long) size);
  179. GNUNET_DISK_file_close (fh);
  180. return GNUNET_SYSERR;
  181. }
  182. if (0 == size)
  183. {
  184. GNUNET_DISK_file_close (fh);
  185. return GNUNET_OK;
  186. }
  187. buffer = GNUNET_DISK_file_map (fh,
  188. &mh,
  189. GNUNET_DISK_MAP_TYPE_READ,
  190. size);
  191. if (NULL == buffer)
  192. {
  193. GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
  194. "mmap");
  195. GNUNET_DISK_file_close (fh);
  196. return GNUNET_SYSERR;
  197. }
  198. if ('\0' != buffer[size - 1])
  199. {
  200. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  201. _ ("Namestore database file `%s' malformed\n"),
  202. flatdbfile);
  203. GNUNET_DISK_file_unmap (mh);
  204. GNUNET_DISK_file_close (fh);
  205. return GNUNET_SYSERR;
  206. }
  207. line = strtok (buffer, "\n");
  208. while (NULL != line)
  209. {
  210. zone_private_key = strtok (line, ",");
  211. if (NULL == zone_private_key)
  212. break;
  213. rvalue = strtok (NULL, ",");
  214. if (NULL == rvalue)
  215. break;
  216. record_count = strtok (NULL, ",");
  217. if (NULL == record_count)
  218. break;
  219. record_data_b64 = strtok (NULL, ",");
  220. if (NULL == record_data_b64)
  221. break;
  222. label = strtok (NULL, ",");
  223. if (NULL == label)
  224. break;
  225. line = strtok (NULL, "\n");
  226. entry = GNUNET_new (struct FlatFileEntry);
  227. {
  228. unsigned long long ll;
  229. if (1 != sscanf (rvalue,
  230. "%llu",
  231. &ll))
  232. {
  233. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  234. "Error parsing entry\n");
  235. GNUNET_free (entry);
  236. break;
  237. }
  238. entry->rvalue = (uint64_t) ll;
  239. }
  240. {
  241. unsigned int ui;
  242. if (1 != sscanf (record_count,
  243. "%u",
  244. &ui))
  245. {
  246. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  247. "Error parsing entry\n");
  248. GNUNET_free (entry);
  249. break;
  250. }
  251. entry->record_count = (uint32_t) ui;
  252. }
  253. entry->label = GNUNET_strdup (label);
  254. record_data_size
  255. = GNUNET_STRINGS_base64_decode (record_data_b64,
  256. strlen (record_data_b64),
  257. (void **) &record_data);
  258. entry->record_data =
  259. GNUNET_new_array (entry->record_count,
  260. struct GNUNET_GNSRECORD_Data);
  261. if (GNUNET_OK !=
  262. GNUNET_GNSRECORD_records_deserialize (record_data_size,
  263. record_data,
  264. entry->record_count,
  265. entry->record_data))
  266. {
  267. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  268. "Unable to deserialize record %s\n",
  269. label);
  270. GNUNET_free (entry->label);
  271. GNUNET_free (entry);
  272. GNUNET_free (record_data);
  273. break;
  274. }
  275. GNUNET_free (record_data);
  276. {
  277. struct GNUNET_IDENTITY_PrivateKey *private_key;
  278. GNUNET_STRINGS_base64_decode (zone_private_key,
  279. strlen (zone_private_key),
  280. (void **) &private_key);
  281. entry->private_key = *private_key;
  282. GNUNET_free (private_key);
  283. }
  284. hash_pkey_and_label (&entry->private_key,
  285. label,
  286. &hkey);
  287. if (GNUNET_OK !=
  288. GNUNET_CONTAINER_multihashmap_put (plugin->hm,
  289. &hkey,
  290. entry,
  291. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  292. {
  293. GNUNET_free (entry);
  294. GNUNET_break (0);
  295. }
  296. }
  297. GNUNET_DISK_file_unmap (mh);
  298. GNUNET_DISK_file_close (fh);
  299. return GNUNET_OK;
  300. }
  301. /**
  302. * Store values in hashmap in file and free data
  303. *
  304. * @param plugin the plugin context
  305. * @param key key in the map
  306. * @param value a `struct FlatFileEntry`
  307. */
  308. static int
  309. store_and_free_entries (void *cls,
  310. const struct GNUNET_HashCode *key,
  311. void *value)
  312. {
  313. struct GNUNET_DISK_FileHandle *fh = cls;
  314. struct FlatFileEntry *entry = value;
  315. char *line;
  316. char *zone_private_key;
  317. char *record_data_b64;
  318. ssize_t data_size;
  319. (void) key;
  320. GNUNET_STRINGS_base64_encode (&entry->private_key,
  321. sizeof(struct GNUNET_IDENTITY_PrivateKey),
  322. &zone_private_key);
  323. data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
  324. entry->record_data);
  325. if (data_size < 0)
  326. {
  327. GNUNET_break (0);
  328. GNUNET_free (zone_private_key);
  329. return GNUNET_SYSERR;
  330. }
  331. if (data_size >= UINT16_MAX)
  332. {
  333. GNUNET_break (0);
  334. GNUNET_free (zone_private_key);
  335. return GNUNET_SYSERR;
  336. }
  337. {
  338. char data[data_size];
  339. ssize_t ret;
  340. ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
  341. entry->record_data,
  342. data_size,
  343. data);
  344. if ((ret < 0) ||
  345. (data_size != ret))
  346. {
  347. GNUNET_break (0);
  348. GNUNET_free (zone_private_key);
  349. return GNUNET_SYSERR;
  350. }
  351. GNUNET_STRINGS_base64_encode (data,
  352. data_size,
  353. &record_data_b64);
  354. }
  355. GNUNET_asprintf (&line,
  356. "%s,%llu,%u,%s,%s\n",
  357. zone_private_key,
  358. (unsigned long long) entry->rvalue,
  359. (unsigned int) entry->record_count,
  360. record_data_b64,
  361. entry->label);
  362. GNUNET_free (record_data_b64);
  363. GNUNET_free (zone_private_key);
  364. GNUNET_DISK_file_write (fh,
  365. line,
  366. strlen (line));
  367. GNUNET_free (line);
  368. GNUNET_free (entry->label);
  369. GNUNET_free (entry->record_data);
  370. GNUNET_free (entry);
  371. return GNUNET_YES;
  372. }
  373. /**
  374. * Shutdown database connection and associate data
  375. * structures.
  376. * @param plugin the plugin context (state for this module)
  377. */
  378. static void
  379. database_shutdown (struct Plugin *plugin)
  380. {
  381. struct GNUNET_DISK_FileHandle *fh;
  382. fh = GNUNET_DISK_file_open (plugin->fn,
  383. GNUNET_DISK_OPEN_CREATE
  384. | GNUNET_DISK_OPEN_TRUNCATE
  385. | GNUNET_DISK_OPEN_READWRITE,
  386. GNUNET_DISK_PERM_USER_WRITE
  387. | GNUNET_DISK_PERM_USER_READ);
  388. if (NULL == fh)
  389. {
  390. GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
  391. _ ("Unable to initialize file: %s.\n"),
  392. plugin->fn);
  393. return;
  394. }
  395. GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
  396. &store_and_free_entries,
  397. fh);
  398. GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
  399. /* append 0-terminator */
  400. GNUNET_DISK_file_write (fh,
  401. "",
  402. 1);
  403. GNUNET_DISK_file_close (fh);
  404. }
  405. /**
  406. * Store a record in the datastore. Removes any existing record in the
  407. * same zone with the same name.
  408. *
  409. * @param cls closure (internal context for the plugin)
  410. * @param zone_key private key of the zone
  411. * @param label name that is being mapped (at most 255 characters long)
  412. * @param rd_count number of entries in @a rd array
  413. * @param rd array of records with data to store
  414. * @return #GNUNET_OK on success, else #GNUNET_SYSERR
  415. */
  416. static int
  417. namestore_flat_store_records (void *cls,
  418. const struct
  419. GNUNET_IDENTITY_PrivateKey *zone_key,
  420. const char *label,
  421. unsigned int rd_count,
  422. const struct GNUNET_GNSRECORD_Data *rd)
  423. {
  424. struct Plugin *plugin = cls;
  425. uint64_t rvalue;
  426. struct GNUNET_HashCode hkey;
  427. struct FlatFileEntry *entry;
  428. rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
  429. UINT64_MAX);
  430. hash_pkey_and_label (zone_key,
  431. label,
  432. &hkey);
  433. GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
  434. &hkey);
  435. if (0 == rd_count)
  436. {
  437. GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
  438. "sqlite",
  439. "Record deleted\n");
  440. return GNUNET_OK;
  441. }
  442. entry = GNUNET_new (struct FlatFileEntry);
  443. GNUNET_asprintf (&entry->label,
  444. label,
  445. strlen (label));
  446. GNUNET_memcpy (&entry->private_key,
  447. zone_key,
  448. sizeof(struct GNUNET_IDENTITY_PrivateKey));
  449. entry->rvalue = rvalue;
  450. entry->record_count = rd_count;
  451. entry->record_data = GNUNET_new_array (rd_count,
  452. struct GNUNET_GNSRECORD_Data);
  453. for (unsigned int i = 0; i < rd_count; i++)
  454. {
  455. entry->record_data[i].expiration_time = rd[i].expiration_time;
  456. entry->record_data[i].record_type = rd[i].record_type;
  457. entry->record_data[i].flags = rd[i].flags;
  458. entry->record_data[i].data_size = rd[i].data_size;
  459. entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
  460. GNUNET_memcpy ((char *) entry->record_data[i].data,
  461. rd[i].data,
  462. rd[i].data_size);
  463. }
  464. return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
  465. &hkey,
  466. entry,
  467. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
  468. }
  469. /**
  470. * Lookup records in the datastore for which we are the authority.
  471. *
  472. * @param cls closure (internal context for the plugin)
  473. * @param zone private key of the zone
  474. * @param label name of the record in the zone
  475. * @param iter function to call with the result
  476. * @param iter_cls closure for @a iter
  477. * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
  478. */
  479. static int
  480. namestore_flat_lookup_records (void *cls,
  481. const struct GNUNET_IDENTITY_PrivateKey *zone,
  482. const char *label,
  483. GNUNET_NAMESTORE_RecordIterator iter,
  484. void *iter_cls)
  485. {
  486. struct Plugin *plugin = cls;
  487. struct FlatFileEntry *entry;
  488. struct GNUNET_HashCode hkey;
  489. if (NULL == zone)
  490. {
  491. GNUNET_break (0);
  492. return GNUNET_SYSERR;
  493. }
  494. hash_pkey_and_label (zone,
  495. label,
  496. &hkey);
  497. entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
  498. &hkey);
  499. if (NULL == entry)
  500. return GNUNET_NO;
  501. if (NULL != iter)
  502. iter (iter_cls,
  503. 1, /* zero is illegal */
  504. &entry->private_key,
  505. entry->label,
  506. entry->record_count,
  507. entry->record_data);
  508. return GNUNET_YES;
  509. }
  510. /**
  511. * Closure for #iterate_zones.
  512. */
  513. struct IterateContext
  514. {
  515. /**
  516. * How many more records should we skip before returning results?
  517. */
  518. uint64_t offset;
  519. /**
  520. * How many more records should we return?
  521. */
  522. uint64_t limit;
  523. /**
  524. * What is the position of the current entry, counting
  525. * starts from 1.
  526. */
  527. uint64_t pos;
  528. /**
  529. * Target zone.
  530. */
  531. const struct GNUNET_IDENTITY_PrivateKey *zone;
  532. /**
  533. * Function to call on each record.
  534. */
  535. GNUNET_NAMESTORE_RecordIterator iter;
  536. /**
  537. * Closure for @e iter.
  538. */
  539. void *iter_cls;
  540. };
  541. /**
  542. * Helper function for #namestore_flat_iterate_records().
  543. *
  544. * @param cls a `struct IterateContext`
  545. * @param key unused
  546. * @param value a `struct FlatFileEntry`
  547. * @return #GNUNET_YES to continue the iteration
  548. */
  549. static int
  550. iterate_zones (void *cls,
  551. const struct GNUNET_HashCode *key,
  552. void *value)
  553. {
  554. struct IterateContext *ic = cls;
  555. struct FlatFileEntry *entry = value;
  556. (void) key;
  557. if (0 == ic->limit)
  558. return GNUNET_NO;
  559. if ((NULL != ic->zone) &&
  560. (0 != GNUNET_memcmp (&entry->private_key,
  561. ic->zone)))
  562. return GNUNET_YES;
  563. ic->pos++;
  564. if (ic->offset > 0)
  565. {
  566. ic->offset--;
  567. return GNUNET_YES;
  568. }
  569. ic->iter (ic->iter_cls,
  570. ic->pos,
  571. (NULL == ic->zone)
  572. ? &entry->private_key
  573. : ic->zone,
  574. entry->label,
  575. entry->record_count,
  576. entry->record_data);
  577. ic->limit--;
  578. if (0 == ic->limit)
  579. return GNUNET_NO;
  580. return GNUNET_YES;
  581. }
  582. /**
  583. * Iterate over the results for a particular key and zone in the
  584. * datastore. Will return at most one result to the iterator.
  585. *
  586. * @param cls closure (internal context for the plugin)
  587. * @param zone hash of public key of the zone, NULL to iterate over all zones
  588. * @param serial serial number to exclude in the list of all matching records
  589. * @param limit maximum number of results to return to @a iter
  590. * @param iter function to call with the result
  591. * @param iter_cls closure for @a iter
  592. * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
  593. */
  594. static int
  595. namestore_flat_iterate_records (void *cls,
  596. const struct
  597. GNUNET_IDENTITY_PrivateKey *zone,
  598. uint64_t serial,
  599. uint64_t limit,
  600. GNUNET_NAMESTORE_RecordIterator iter,
  601. void *iter_cls)
  602. {
  603. struct Plugin *plugin = cls;
  604. struct IterateContext ic;
  605. ic.offset = serial;
  606. ic.pos = 0;
  607. ic.limit = limit;
  608. ic.iter = iter;
  609. ic.iter_cls = iter_cls;
  610. ic.zone = zone;
  611. GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
  612. &iterate_zones,
  613. &ic);
  614. return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
  615. }
  616. /**
  617. * Closure for #zone_to_name.
  618. */
  619. struct ZoneToNameContext
  620. {
  621. const struct GNUNET_IDENTITY_PrivateKey *zone;
  622. const struct GNUNET_IDENTITY_PublicKey *value_zone;
  623. GNUNET_NAMESTORE_RecordIterator iter;
  624. void *iter_cls;
  625. int result_found;
  626. };
  627. static int
  628. zone_to_name (void *cls,
  629. const struct GNUNET_HashCode *key,
  630. void *value)
  631. {
  632. struct ZoneToNameContext *ztn = cls;
  633. struct FlatFileEntry *entry = value;
  634. (void) key;
  635. if (0 != GNUNET_memcmp (&entry->private_key,
  636. ztn->zone))
  637. return GNUNET_YES;
  638. for (unsigned int i = 0; i < entry->record_count; i++)
  639. {
  640. if (GNUNET_NO ==
  641. GNUNET_GNSRECORD_is_zonekey_type (entry->record_data[i].record_type))
  642. continue;
  643. if (ztn->value_zone->type != entry->record_data[i].record_type)
  644. continue;
  645. if (0 == memcmp (ztn->value_zone,
  646. entry->record_data[i].data,
  647. entry->record_data[i].data_size))
  648. {
  649. ztn->iter (ztn->iter_cls,
  650. i + 1, /* zero is illegal! */
  651. &entry->private_key,
  652. entry->label,
  653. entry->record_count,
  654. entry->record_data);
  655. ztn->result_found = GNUNET_YES;
  656. }
  657. }
  658. return GNUNET_YES;
  659. }
  660. /**
  661. * Look for an existing PKEY delegation record for a given public key.
  662. * Returns at most one result to the iterator.
  663. *
  664. * @param cls closure (internal context for the plugin)
  665. * @param zone private key of the zone to look up in, never NULL
  666. * @param value_zone public key of the target zone (value), never NULL
  667. * @param iter function to call with the result
  668. * @param iter_cls closure for @a iter
  669. * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
  670. */
  671. static int
  672. namestore_flat_zone_to_name (void *cls,
  673. const struct GNUNET_IDENTITY_PrivateKey *zone,
  674. const struct
  675. GNUNET_IDENTITY_PublicKey *value_zone,
  676. GNUNET_NAMESTORE_RecordIterator iter,
  677. void *iter_cls)
  678. {
  679. struct Plugin *plugin = cls;
  680. struct ZoneToNameContext ztn = {
  681. .iter = iter,
  682. .iter_cls = iter_cls,
  683. .zone = zone,
  684. .value_zone = value_zone,
  685. .result_found = GNUNET_NO
  686. };
  687. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  688. "Performing reverse lookup for `%s'\n",
  689. GNUNET_GNSRECORD_z2s (value_zone));
  690. GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
  691. &zone_to_name,
  692. &ztn);
  693. return ztn.result_found;
  694. }
  695. /**
  696. * Entry point for the plugin.
  697. *
  698. * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
  699. * @return NULL on error, otherwise the plugin context
  700. */
  701. void *
  702. libgnunet_plugin_namestore_flat_init (void *cls)
  703. {
  704. static struct Plugin plugin;
  705. const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
  706. struct GNUNET_NAMESTORE_PluginFunctions *api;
  707. if (NULL != plugin.cfg)
  708. return NULL; /* can only initialize once! */
  709. memset (&plugin,
  710. 0,
  711. sizeof(struct Plugin));
  712. plugin.cfg = cfg;
  713. if (GNUNET_OK != database_setup (&plugin))
  714. {
  715. database_shutdown (&plugin);
  716. return NULL;
  717. }
  718. api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
  719. api->cls = &plugin;
  720. api->store_records = &namestore_flat_store_records;
  721. api->iterate_records = &namestore_flat_iterate_records;
  722. api->zone_to_name = &namestore_flat_zone_to_name;
  723. api->lookup_records = &namestore_flat_lookup_records;
  724. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  725. _ ("Flat file database running\n"));
  726. return api;
  727. }
  728. /**
  729. * Exit point from the plugin.
  730. *
  731. * @param cls the plugin context (as returned by "init")
  732. * @return always NULL
  733. */
  734. void *
  735. libgnunet_plugin_namestore_flat_done (void *cls)
  736. {
  737. struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
  738. struct Plugin *plugin = api->cls;
  739. database_shutdown (plugin);
  740. plugin->cfg = NULL;
  741. GNUNET_free (api);
  742. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  743. "Flat file plugin is finished\n");
  744. return NULL;
  745. }
  746. /* end of plugin_namestore_flat.c */