aboutsummaryrefslogtreecommitdiff
path: root/src/namecache
diff options
context:
space:
mode:
Diffstat (limited to 'src/namecache')
-rw-r--r--src/namecache/.gitignore7
-rw-r--r--src/namecache/Makefile.am179
-rw-r--r--src/namecache/gnunet-namecache.c246
-rw-r--r--src/namecache/gnunet-service-namecache.c391
-rw-r--r--src/namecache/namecache.conf.in30
-rw-r--r--src/namecache/namecache.h151
-rw-r--r--src/namecache/namecache_api.c567
-rw-r--r--src/namecache/plugin_namecache_flat.c430
-rw-r--r--src/namecache/plugin_namecache_postgres.c347
-rw-r--r--src/namecache/plugin_namecache_sqlite.c590
-rw-r--r--src/namecache/test_namecache_api.conf13
-rw-r--r--src/namecache/test_namecache_api_cache_block.c242
-rw-r--r--src/namecache/test_plugin_namecache.c132
-rw-r--r--src/namecache/test_plugin_namecache_flat.conf2
-rw-r--r--src/namecache/test_plugin_namecache_postgres.conf3
-rw-r--r--src/namecache/test_plugin_namecache_sqlite.conf2
16 files changed, 0 insertions, 3332 deletions
diff --git a/src/namecache/.gitignore b/src/namecache/.gitignore
deleted file mode 100644
index 2abc07dfb..000000000
--- a/src/namecache/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
1gnunet-service-namecache
2gnunet-namecache
3test_namecache_api_cache_block
4test_plugin_namecache_postgres
5test_plugin_namecache_sqlite
6zonefiles
7test_plugin_namecache_flat
diff --git a/src/namecache/Makefile.am b/src/namecache/Makefile.am
deleted file mode 100644
index 8ffa85ddb..000000000
--- a/src/namecache/Makefile.am
+++ /dev/null
@@ -1,179 +0,0 @@
1# This Makefile.am is in the public domain
2AM_CPPFLAGS = -I$(top_srcdir)/src/include $(POSTGRESQL_CPPFLAGS)
3
4plugindir = $(libdir)/gnunet
5
6pkgcfgdir= $(pkgdatadir)/config.d/
7
8libexecdir= $(pkglibdir)/libexec/
9
10pkgcfg_DATA = \
11 namecache.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIBS = -lgcov
16endif
17
18if HAVE_EXPERIMENTAL
19FLAT_PLUGIN = libgnunet_plugin_namecache_flat.la
20if HAVE_TESTING
21FLAT_TESTS = test_plugin_namecache_flat
22endif
23endif
24
25if HAVE_SQLITE
26SQLITE_PLUGIN = libgnunet_plugin_namecache_sqlite.la
27if HAVE_TESTING
28SQLITE_TESTS = test_plugin_namecache_sqlite
29endif
30endif
31
32if HAVE_POSTGRESQL
33POSTGRES_PLUGIN = libgnunet_plugin_namecache_postgres.la
34if HAVE_TESTING
35POSTGRES_TESTS = test_plugin_namecache_postgres
36endif
37endif
38
39# testcases do not even build yet; thus: experimental!
40if HAVE_TESTING
41TESTING_TESTS = \
42 test_namecache_api_cache_block
43endif
44
45if HAVE_SQLITE
46check_PROGRAMS = \
47 $(SQLITE_TESTS) \
48 $(POSTGRES_TESTS) \
49 $(FLAT_TESTS) \
50 $(TESTING_TESTS)
51endif
52
53if ENABLE_TEST_RUN
54AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
55TESTS = \
56 $(check_PROGRAMS)
57endif
58
59lib_LTLIBRARIES = \
60 libgnunetnamecache.la
61
62
63libgnunetnamecache_la_SOURCES = \
64 namecache_api.c \
65 namecache.h
66libgnunetnamecache_la_LIBADD = \
67 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
68 $(top_builddir)/src/identity/libgnunetidentity.la \
69 $(top_builddir)/src/util/libgnunetutil.la \
70 $(GN_LIBINTL)
71libgnunetnamecache_la_LDFLAGS = \
72 $(GN_LIB_LDFLAGS) \
73 -version-info 0:0:0
74
75
76libexec_PROGRAMS = \
77 gnunet-service-namecache
78
79bin_PROGRAMS = \
80 gnunet-namecache
81
82gnunet_namecache_SOURCES = \
83 gnunet-namecache.c
84gnunet_namecache_LDADD = \
85 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
86 $(top_builddir)/src/identity/libgnunetidentity.la \
87 $(top_builddir)/src/util/libgnunetutil.la \
88 libgnunetnamecache.la \
89 $(GN_LIBINTL)
90
91gnunet_service_namecache_SOURCES = \
92 gnunet-service-namecache.c
93
94gnunet_service_namecache_LDADD = \
95 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
96 $(top_builddir)/src/identity/libgnunetidentity.la \
97 $(top_builddir)/src/statistics/libgnunetstatistics.la \
98 $(top_builddir)/src/util/libgnunetutil.la \
99 libgnunetnamecache.la \
100 $(GN_LIBINTL)
101
102
103plugin_LTLIBRARIES = \
104 $(SQLITE_PLUGIN) \
105 $(FLAT_PLUGIN) \
106 $(POSTGRES_PLUGIN)
107
108libgnunet_plugin_namecache_flat_la_SOURCES = \
109 plugin_namecache_flat.c
110libgnunet_plugin_namecache_flat_la_LIBADD = \
111 libgnunetnamecache.la \
112 $(top_builddir)/src/statistics/libgnunetstatistics.la \
113 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
114 $(top_builddir)/src/identity/libgnunetidentity.la \
115 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
116 $(LTLIBINTL)
117libgnunet_plugin_namecache_flat_la_LDFLAGS = \
118 $(GN_PLUGIN_LDFLAGS)
119
120libgnunet_plugin_namecache_sqlite_la_SOURCES = \
121 plugin_namecache_sqlite.c
122libgnunet_plugin_namecache_sqlite_la_LIBADD = \
123 libgnunetnamecache.la \
124 $(top_builddir)/src/sq/libgnunetsq.la \
125 $(top_builddir)/src/statistics/libgnunetstatistics.la \
126 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
127 $(top_builddir)/src/identity/libgnunetidentity.la \
128 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
129 $(LTLIBINTL)
130libgnunet_plugin_namecache_sqlite_la_LDFLAGS = \
131 $(GN_PLUGIN_LDFLAGS)
132
133
134libgnunet_plugin_namecache_postgres_la_SOURCES = \
135 plugin_namecache_postgres.c
136libgnunet_plugin_namecache_postgres_la_LIBADD = \
137 libgnunetnamecache.la \
138 $(top_builddir)/src/pq/libgnunetpq.la \
139 $(top_builddir)/src/statistics/libgnunetstatistics.la \
140 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
141 $(top_builddir)/src/identity/libgnunetidentity.la \
142 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \
143 $(LTLIBINTL)
144libgnunet_plugin_namecache_postgres_la_LDFLAGS = \
145 $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
146
147test_namecache_api_cache_block_SOURCES = \
148 test_namecache_api_cache_block.c
149test_namecache_api_cache_block_LDADD = \
150 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
151 $(top_builddir)/src/identity/libgnunetidentity.la \
152 libgnunetnamecache.la \
153 $(top_builddir)/src/testing/libgnunettesting.la \
154 $(top_builddir)/src/util/libgnunetutil.la
155
156
157test_plugin_namecache_flat_SOURCES = \
158 test_plugin_namecache.c
159test_plugin_namecache_flat_LDADD = \
160 $(top_builddir)/src/testing/libgnunettesting.la \
161 $(top_builddir)/src/util/libgnunetutil.la
162
163test_plugin_namecache_sqlite_SOURCES = \
164 test_plugin_namecache.c
165test_plugin_namecache_sqlite_LDADD = \
166 $(top_builddir)/src/testing/libgnunettesting.la \
167 $(top_builddir)/src/util/libgnunetutil.la
168
169test_plugin_namecache_postgres_SOURCES = \
170 test_plugin_namecache.c
171test_plugin_namecache_postgres_LDADD = \
172 $(top_builddir)/src/testing/libgnunettesting.la \
173 $(top_builddir)/src/util/libgnunetutil.la
174
175EXTRA_DIST = \
176 test_namecache_api.conf \
177 test_plugin_namecache_sqlite.conf \
178 test_plugin_namecache_postgres.conf \
179 test_plugin_namecache_flat.conf
diff --git a/src/namecache/gnunet-namecache.c b/src/namecache/gnunet-namecache.c
deleted file mode 100644
index 19f2a5766..000000000
--- a/src/namecache/gnunet-namecache.c
+++ /dev/null
@@ -1,246 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013 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 */
20/**
21 * @file gnunet-namecache.c
22 * @brief command line tool to inspect the name cache
23 * @author Christian Grothoff
24 *
25 * TODO:
26 * - test
27 */
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_dnsparser_lib.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_gnsrecord_lib.h"
33#include "gnunet_namecache_service.h"
34
35
36/**
37 * Handle to the namecache.
38 */
39static struct GNUNET_NAMECACHE_Handle *ns;
40
41/**
42 * Queue entry for the 'query' operation.
43 */
44static struct GNUNET_NAMECACHE_QueueEntry *qe;
45
46/**
47 * Name (label) of the records to list.
48 */
49static char *name;
50
51/**
52 * Public key of the zone to look in.
53 */
54static struct GNUNET_IDENTITY_PublicKey pubkey;
55
56/**
57 * Public key of the zone to look in, in ASCII.
58 */
59static char *pkey;
60
61/**
62 * Global return value
63 */
64static int ret;
65
66
67/**
68 * Task run on shutdown. Cleans up everything.
69 *
70 * @param cls unused
71 */
72static void
73do_shutdown (void *cls)
74{
75 if (NULL != qe)
76 {
77 GNUNET_NAMECACHE_cancel (qe);
78 qe = NULL;
79 }
80 if (NULL != ns)
81 {
82 GNUNET_NAMECACHE_disconnect (ns);
83 ns = NULL;
84 }
85}
86
87
88/**
89 * Process a record that was stored in the namecache in a block.
90 *
91 * @param cls closure, NULL
92 * @param rd_len number of entries in @a rd array
93 * @param rd array of records with data to store
94 */
95static void
96display_records_from_block (void *cls,
97 unsigned int rd_len,
98 const struct GNUNET_GNSRECORD_Data *rd)
99{
100 const char *typestring;
101 char *s;
102 unsigned int i;
103
104 if (0 == rd_len)
105 {
106 fprintf (stdout, _ ("No records found for `%s'"), name);
107 return;
108 }
109 fprintf (stdout, "%s:\n", name);
110 for (i = 0; i < rd_len; i++)
111 {
112 typestring = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
113 s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
114 rd[i].data,
115 rd[i].data_size);
116 if (NULL == s)
117 {
118 fprintf (stdout,
119 _ ("\tCorrupt or unsupported record of type %u\n"),
120 (unsigned int) rd[i].record_type);
121 continue;
122 }
123 fprintf (stdout, "\t%s: %s\n", typestring, s);
124 GNUNET_free (s);
125 }
126 fprintf (stdout, "%s", "\n");
127}
128
129
130/**
131 * Display block obtained from listing (by name).
132 *
133 * @param cls NULL
134 * @param block NULL if not found
135 */
136static void
137handle_block (void *cls, const struct GNUNET_GNSRECORD_Block *block)
138{
139 qe = NULL;
140 if (NULL == block)
141 {
142 fprintf (stderr, "No matching block found\n");
143 }
144 else if (GNUNET_OK !=
145 GNUNET_GNSRECORD_block_decrypt (block,
146 &pubkey,
147 name,
148 &display_records_from_block,
149 NULL))
150 {
151 fprintf (stderr, "Failed to decrypt block!\n");
152 }
153 GNUNET_SCHEDULER_shutdown ();
154}
155
156
157/**
158 * Main function that will be run.
159 *
160 * @param cls closure
161 * @param args remaining command-line arguments
162 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
163 * @param cfg configuration
164 */
165static void
166run (void *cls,
167 char *const *args,
168 const char *cfgfile,
169 const struct GNUNET_CONFIGURATION_Handle *cfg)
170{
171 struct GNUNET_HashCode dhash;
172
173 if (NULL == pkey)
174 {
175 fprintf (stderr, _ ("You must specify which zone should be accessed\n"));
176 return;
177 }
178
179 if (GNUNET_OK !=
180 GNUNET_IDENTITY_public_key_from_string (pkey, &pubkey))
181 {
182 fprintf (stderr, _ ("Invalid public key for zone `%s'\n"), pkey);
183 GNUNET_SCHEDULER_shutdown ();
184 return;
185 }
186 if (NULL == name)
187 {
188 fprintf (stderr, _ ("You must specify a name\n"));
189 return;
190 }
191
192 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
193 ns = GNUNET_NAMECACHE_connect (cfg);
194 GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &dhash);
195 qe = GNUNET_NAMECACHE_lookup_block (ns, &dhash, &handle_block, NULL);
196}
197
198
199/**
200 * The main function for gnunet-namecache.
201 *
202 * @param argc number of arguments from the command line
203 * @param argv command line arguments
204 * @return 0 ok, 1 on error
205 */
206int
207main (int argc, char *const *argv)
208{
209 struct GNUNET_GETOPT_CommandLineOption options[] =
210 { GNUNET_GETOPT_option_string ('n',
211 "name",
212 "NAME",
213 gettext_noop (
214 "name of the record to add/delete/display"),
215 &name),
216
217 GNUNET_GETOPT_option_string (
218 'z',
219 "zone",
220 "PKEY",
221 gettext_noop ("specifies the public key of the zone to look in"),
222 &pkey),
223
224 GNUNET_GETOPT_OPTION_END };
225
226 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
227 return 2;
228
229 GNUNET_log_setup ("gnunet-namecache", "WARNING", NULL);
230 if (GNUNET_OK != GNUNET_PROGRAM_run (argc,
231 argv,
232 "gnunet-namecache",
233 _ ("GNUnet zone manipulation tool"),
234 options,
235 &run,
236 NULL))
237 {
238 GNUNET_free_nz ((void *) argv);
239 return 1;
240 }
241 GNUNET_free_nz ((void *) argv);
242 return ret;
243}
244
245
246/* end of gnunet-namecache.c */
diff --git a/src/namecache/gnunet-service-namecache.c b/src/namecache/gnunet-service-namecache.c
deleted file mode 100644
index 07bf30de9..000000000
--- a/src/namecache/gnunet-service-namecache.c
+++ /dev/null
@@ -1,391 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013 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 */
20
21/**
22 * @file namecache/gnunet-service-namecache.c
23 * @brief namecache for the GNUnet naming system
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_dnsparser_lib.h"
30#include "gnunet_statistics_service.h"
31#include "gnunet_namecache_service.h"
32#include "gnunet_namecache_plugin.h"
33#include "gnunet_signatures.h"
34#include "namecache.h"
35
36#define LOG_STRERROR_FILE(kind, syscall, \
37 filename) GNUNET_log_from_strerror_file (kind, "util", \
38 syscall, \
39 filename)
40
41
42/**
43 * A namecache client
44 */
45struct NamecacheClient
46{
47 /**
48 * The client
49 */
50 struct GNUNET_SERVICE_Client *client;
51
52 /**
53 * The message queue to talk to @e client.
54 */
55 struct GNUNET_MQ_Handle *mq;
56};
57
58
59/**
60 * Configuration handle.
61 */
62static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
63
64/**
65 * Handle to the statistics service
66 */
67static struct GNUNET_STATISTICS_Handle *statistics;
68
69/**
70 * Database handle
71 */
72static struct GNUNET_NAMECACHE_PluginFunctions *GSN_database;
73
74/**
75 * Name of the database plugin
76 */
77static char *db_lib_name;
78
79
80/**
81 * Task run during shutdown.
82 *
83 * @param cls unused
84 */
85static void
86cleanup_task (void *cls)
87{
88 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
89 "Stopping namecache service\n");
90 GNUNET_break (NULL ==
91 GNUNET_PLUGIN_unload (db_lib_name,
92 GSN_database));
93 GNUNET_free (db_lib_name);
94 db_lib_name = NULL;
95 if (NULL != statistics)
96 {
97 GNUNET_STATISTICS_destroy (statistics,
98 GNUNET_NO);
99 statistics = NULL;
100 }
101}
102
103
104/**
105 * Called whenever a client is disconnected.
106 * Frees our resources associated with that client.
107 *
108 * @param cls closure
109 * @param client identification of the client
110 * @param app_ctx the `struct NamecacheClient` for this @a client
111 */
112static void
113client_disconnect_cb (void *cls,
114 struct GNUNET_SERVICE_Client *client,
115 void *app_ctx)
116{
117 struct NamecacheClient *nc = app_ctx;
118
119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
120 "Client %p disconnected\n",
121 client);
122 GNUNET_free (nc);
123}
124
125
126/**
127 * Add a client to our list of active clients.
128 *
129 * @param cls NULL
130 * @param client client to add
131 * @param mq queue to talk to @a client
132 * @return internal namecache client structure for this client
133 */
134static void *
135client_connect_cb (void *cls,
136 struct GNUNET_SERVICE_Client *client,
137 struct GNUNET_MQ_Handle *mq)
138{
139 struct NamecacheClient *nc;
140
141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
142 "Client %p connected\n",
143 client);
144 nc = GNUNET_new (struct NamecacheClient);
145 nc->client = client;
146 nc->mq = mq;
147 return nc;
148}
149
150
151/**
152 * Context for name lookups passed from #handle_lookup_block to
153 * #handle_lookup_block_it as closure
154 */
155struct LookupBlockContext
156{
157 /**
158 * The client to send the response to
159 */
160 struct NamecacheClient *nc;
161
162 /**
163 * Operation id for the name lookup
164 */
165 uint32_t request_id;
166
167 /**
168 * Lookup status
169 */
170 int status;
171};
172
173
174/**
175 * A #GNUNET_NAMECACHE_BlockCallback for name lookups in #handle_lookup_block
176 *
177 * @param cls a `struct LookupNameContext *` with information about the request
178 * @param block the block
179 */
180static void
181handle_lookup_block_it (void *cls,
182 const struct GNUNET_GNSRECORD_Block *block)
183{
184 struct LookupBlockContext *lnc = cls;
185 struct GNUNET_MQ_Envelope *env;
186 struct LookupBlockResponseMessage *r;
187 size_t bsize;
188
189 bsize = GNUNET_GNSRECORD_block_get_size (block);
190 env = GNUNET_MQ_msg_extra (r,
191 bsize,
192 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE);
193 r->gns_header.r_id = htonl (lnc->request_id);
194 GNUNET_memcpy (&r[1],
195 block,
196 bsize);
197 GNUNET_STATISTICS_update (statistics,
198 "blocks found in cache",
199 1,
200 GNUNET_NO);
201 r->expire = GNUNET_TIME_absolute_hton (
202 GNUNET_GNSRECORD_block_get_expiration (block));
203 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
204 "Sending NAMECACHE_LOOKUP_BLOCK_RESPONSE message\n");
205 GNUNET_MQ_send (lnc->nc->mq,
206 env);
207}
208
209
210/**
211 * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK message
212 *
213 * @param cls a `struct NamecacheClient *`
214 * @param the inbound message
215 */
216static void
217handle_lookup_block (void *cls,
218 const struct LookupBlockMessage *ln_msg)
219{
220 struct NamecacheClient *nc = cls;
221 struct GNUNET_MQ_Envelope *env;
222 struct LookupBlockContext lnc;
223 struct LookupBlockResponseMessage *zir_end;
224 int ret;
225
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "Received NAMECACHE_LOOKUP_BLOCK message\n");
228 GNUNET_STATISTICS_update (statistics,
229 "blocks looked up",
230 1,
231 GNUNET_NO);
232 lnc.request_id = ntohl (ln_msg->gns_header.r_id);
233 lnc.nc = nc;
234 lnc.status = GNUNET_OK;
235 if (GNUNET_SYSERR ==
236 (ret = GSN_database->lookup_block (GSN_database->cls,
237 &ln_msg->query,
238 &handle_lookup_block_it,
239 &lnc)))
240 {
241 /* internal error (in database plugin); might be best to just hang up on
242 plugin rather than to signal that there are 'no' results, which
243 might also be false... */
244 GNUNET_break (0);
245 GNUNET_SERVICE_client_drop (nc->client);
246 return;
247 }
248 if ((0 == ret) || (GNUNET_SYSERR == lnc.status))
249 {
250 /* no records match at all, generate empty response */
251 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
252 "Sending empty NAMECACHE_LOOKUP_BLOCK_RESPONSE message\n");
253 env = GNUNET_MQ_msg (zir_end,
254 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE);
255 zir_end->gns_header.r_id = ln_msg->gns_header.r_id;
256 GNUNET_MQ_send (nc->mq,
257 env);
258 }
259 GNUNET_SERVICE_client_continue (nc->client);
260}
261
262
263/**
264 * Check a #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message
265 *
266 * @param cls our `struct NamecacheClient`
267 * @param rp_msg message to process
268 * @return #GNUNET_OK (always fine)
269 */
270static int
271check_block_cache (void *cls,
272 const struct BlockCacheMessage *rp_msg)
273{
274 return GNUNET_OK;
275}
276
277
278/**
279 * Handles a #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE message
280 *
281 * @param cls our `struct NamecacheClient`
282 * @param rp_msg message to process
283 */
284static void
285handle_block_cache (void *cls,
286 const struct BlockCacheMessage *rp_msg)
287{
288 struct NamecacheClient *nc = cls;
289 struct GNUNET_MQ_Envelope *env;
290 struct BlockCacheResponseMessage *rpr_msg;
291 struct GNUNET_GNSRECORD_Block *block;
292 size_t esize;
293 int res;
294
295 GNUNET_STATISTICS_update (statistics,
296 "blocks cached",
297 1,
298 GNUNET_NO);
299 esize = ntohs (rp_msg->gns_header.header.size) - sizeof(struct
300 BlockCacheMessage);
301 block = GNUNET_malloc (esize);
302 memcpy (block, &rp_msg[1], esize);
303 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
304 "Received NAMECACHE_BLOCK_CACHE message with type %u\n",
305 htonl (block->type));
306 res = GSN_database->cache_block (GSN_database->cls,
307 block);
308 GNUNET_free (block);
309 env = GNUNET_MQ_msg (rpr_msg,
310 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE);
311 rpr_msg->gns_header.r_id = rp_msg->gns_header.r_id;
312 rpr_msg->op_result = htonl (res);
313 GNUNET_MQ_send (nc->mq,
314 env);
315 GNUNET_SERVICE_client_continue (nc->client);
316}
317
318
319/**
320 * Process namecache requests.
321 *
322 * @param cls closure
323 * @param cfg configuration to use
324 * @param service the initialized service
325 */
326static void
327run (void *cls,
328 const struct GNUNET_CONFIGURATION_Handle *cfg,
329 struct GNUNET_SERVICE_Handle *service)
330{
331 char *database;
332
333 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
334 "Starting namecache service\n");
335 GSN_cfg = cfg;
336
337 /* Loading database plugin */
338 if (GNUNET_OK !=
339 GNUNET_CONFIGURATION_get_value_string (cfg,
340 "namecache",
341 "database",
342 &database))
343 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
344 "No database backend configured\n");
345
346 GNUNET_asprintf (&db_lib_name,
347 "libgnunet_plugin_namecache_%s",
348 database);
349 GSN_database = GNUNET_PLUGIN_load (db_lib_name,
350 (void *) GSN_cfg);
351 GNUNET_free (database);
352 if (NULL == GSN_database)
353 {
354 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
355 "Could not load database backend `%s'\n",
356 db_lib_name);
357 GNUNET_SCHEDULER_add_now (&cleanup_task,
358 NULL);
359 return;
360 }
361 statistics = GNUNET_STATISTICS_create ("namecache",
362 cfg);
363
364 /* Configuring server handles */
365 GNUNET_SCHEDULER_add_shutdown (&cleanup_task,
366 NULL);
367}
368
369
370/**
371 * Define "main" method using service macro.
372 */
373GNUNET_SERVICE_MAIN
374 ("namecache",
375 GNUNET_SERVICE_OPTION_NONE,
376 &run,
377 &client_connect_cb,
378 &client_disconnect_cb,
379 NULL,
380 GNUNET_MQ_hd_fixed_size (lookup_block,
381 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK,
382 struct LookupBlockMessage,
383 NULL),
384 GNUNET_MQ_hd_var_size (block_cache,
385 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE,
386 struct BlockCacheMessage,
387 NULL),
388 GNUNET_MQ_handler_end ());
389
390
391/* end of gnunet-service-namecache.c */
diff --git a/src/namecache/namecache.conf.in b/src/namecache/namecache.conf.in
deleted file mode 100644
index cf1340846..000000000
--- a/src/namecache/namecache.conf.in
+++ /dev/null
@@ -1,30 +0,0 @@
1[namecache]
2START_ON_DEMAND = @START_ON_DEMAND@
3RUN_PER_USER = NO
4UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-namecache.sock
5UNIX_MATCH_UID = NO
6UNIX_MATCH_GID = YES
7@UNIXONLY@ PORT = 2113
8HOSTNAME = localhost
9BINARY = gnunet-service-namecache
10ACCEPT_FROM = 127.0.0.1;
11ACCEPT_FROM6 = ::1;
12DATABASE = sqlite
13
14# Disables use of caching by GNS. Useful for systems that
15# publish very large zones and are CPU bound, if they do not
16# also do a large number of lookups.
17DISABLE = NO
18
19[namecache-sqlite]
20FILENAME = $GNUNET_DATA_HOME/namecache/sqlite.db
21
22[namecache-flat]
23FILENAME = $GNUNET_DATA_HOME/namecache/flat.db
24
25[namecache-postgres]
26CONFIG = postgres:///gnunet
27TEMPORARY_TABLE = NO
28
29
30
diff --git a/src/namecache/namecache.h b/src/namecache/namecache.h
deleted file mode 100644
index 4c809b4d1..000000000
--- a/src/namecache/namecache.h
+++ /dev/null
@@ -1,151 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2011-2013 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 */
20
21/**
22 * @file namecache/namecache.h
23 * @brief common internal definitions for namecache service
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef NAMECACHE_H
28#define NAMECACHE_H
29
30/**
31 * Maximum length of any name, including 0-termination.
32 */
33#define MAX_NAME_LEN 256
34
35GNUNET_NETWORK_STRUCT_BEGIN
36
37/**
38 * Generic namecache message with op id
39 */
40struct GNUNET_NAMECACHE_Header
41{
42 /**
43 * header.type will be GNUNET_MESSAGE_TYPE_NAMECACHE_*
44 * header.size will be message size
45 */
46 struct GNUNET_MessageHeader header;
47
48 /**
49 * Request ID in NBO
50 */
51 uint32_t r_id GNUNET_PACKED;
52};
53
54
55/**
56 * Lookup a block in the namecache
57 */
58struct LookupBlockMessage
59{
60 /**
61 * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK
62 */
63 struct GNUNET_NAMECACHE_Header gns_header;
64
65 /**
66 * The query.
67 */
68 struct GNUNET_HashCode query GNUNET_PACKED;
69};
70
71
72/**
73 * Lookup response
74 */
75struct LookupBlockResponseMessage
76{
77 /**
78 * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE
79 */
80 struct GNUNET_NAMECACHE_Header gns_header;
81
82 /**
83 * Expiration time
84 */
85 struct GNUNET_TIME_AbsoluteNBO expire;
86
87 /**
88 * Signature.
89 */
90 struct GNUNET_CRYPTO_EcdsaSignature signature;
91
92 /**
93 * Derived public key.
94 */
95 struct GNUNET_IDENTITY_PublicKey derived_key;
96
97 /* followed by encrypted block data */
98};
99
100
101/**
102 * Cache a record in the namecache.
103 */
104struct BlockCacheMessage
105{
106 /**
107 * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE
108 */
109 struct GNUNET_NAMECACHE_Header gns_header;
110
111 /**
112 * Expiration time
113 */
114 struct GNUNET_TIME_AbsoluteNBO expire;
115
116 /**
117 * Signature.
118 */
119 struct GNUNET_CRYPTO_EcdsaSignature signature;
120
121 /**
122 * Derived public key.
123 */
124 struct GNUNET_IDENTITY_PublicKey derived_key;
125
126 /* followed by encrypted block data */
127};
128
129
130/**
131 * Response to a request to cache a block.
132 */
133struct BlockCacheResponseMessage
134{
135 /**
136 * Type will be #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE
137 */
138 struct GNUNET_NAMECACHE_Header gns_header;
139
140 /**
141 * #GNUNET_OK on success, #GNUNET_SYSERR error
142 */
143 int32_t op_result GNUNET_PACKED;
144};
145
146
147GNUNET_NETWORK_STRUCT_END
148
149
150/* end of namecache.h */
151#endif
diff --git a/src/namecache/namecache_api.c b/src/namecache/namecache_api.c
deleted file mode 100644
index 70c848037..000000000
--- a/src/namecache/namecache_api.c
+++ /dev/null
@@ -1,567 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2010-2013, 2016 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 */
20
21/**
22 * @file namecache/namecache_api.c
23 * @brief API to access the NAMECACHE service
24 * @author Martin Schanzenbach
25 * @author Matthias Wachs
26 * @author Christian Grothoff
27 */
28
29#include "platform.h"
30#include "gnunet_util_lib.h"
31#include "gnunet_crypto_lib.h"
32#include "gnunet_constants.h"
33#include "gnunet_dnsparser_lib.h"
34#include "gnunet_gnsrecord_lib.h"
35#include "gnunet_signatures.h"
36#include "gnunet_namecache_service.h"
37#include "namecache.h"
38
39
40#define LOG(kind, ...) GNUNET_log_from (kind, "namecache-api", __VA_ARGS__)
41
42
43/**
44 * An QueueEntry used to store information for a pending
45 * NAMECACHE record operation
46 */
47struct GNUNET_NAMECACHE_QueueEntry
48{
49 /**
50 * Kept in a DLL.
51 */
52 struct GNUNET_NAMECACHE_QueueEntry *next;
53
54 /**
55 * Kept in a DLL.
56 */
57 struct GNUNET_NAMECACHE_QueueEntry *prev;
58
59 /**
60 * Main handle to access the namecache.
61 */
62 struct GNUNET_NAMECACHE_Handle *nsh;
63
64 /**
65 * Continuation to call
66 */
67 GNUNET_NAMECACHE_ContinuationWithStatus cont;
68
69 /**
70 * Closure for @e cont.
71 */
72 void *cont_cls;
73
74 /**
75 * Function to call with the blocks we get back; or NULL.
76 */
77 GNUNET_NAMECACHE_BlockProcessor block_proc;
78
79 /**
80 * Closure for @e block_proc.
81 */
82 void *block_proc_cls;
83
84 /**
85 * The operation id this zone iteration operation has
86 */
87 uint32_t op_id;
88};
89
90
91/**
92 * Connection to the NAMECACHE service.
93 */
94struct GNUNET_NAMECACHE_Handle
95{
96 /**
97 * Configuration to use.
98 */
99 const struct GNUNET_CONFIGURATION_Handle *cfg;
100
101 /**
102 * Message queue to service.
103 */
104 struct GNUNET_MQ_Handle *mq;
105
106 /**
107 * Currently pending transmission request (or NULL).
108 */
109 struct GNUNET_CLIENT_TransmitHandle *th;
110
111 /**
112 * Head of pending namecache queue entries
113 */
114 struct GNUNET_NAMECACHE_QueueEntry *op_head;
115
116 /**
117 * Tail of pending namecache queue entries
118 */
119 struct GNUNET_NAMECACHE_QueueEntry *op_tail;
120
121 /**
122 * Reconnect task
123 */
124 struct GNUNET_SCHEDULER_Task *reconnect_task;
125
126 /**
127 * Delay introduced before we reconnect.
128 */
129 struct GNUNET_TIME_Relative reconnect_delay;
130
131 /**
132 * Should we reconnect to service due to some serious error?
133 */
134 int reconnect;
135
136 /**
137 * The last operation id used for a NAMECACHE operation
138 */
139 uint32_t last_op_id_used;
140};
141
142
143/**
144 * Disconnect from service and then reconnect.
145 *
146 * @param h our handle
147 */
148static void
149force_reconnect (struct GNUNET_NAMECACHE_Handle *h);
150
151
152/**
153 * Find queue entry for the given @a rid.
154 *
155 * @param h handle to search
156 * @param rid request ID to look for
157 * @return NULL if not found, otherwise the queue entry (removed from the queue)
158 */
159static struct GNUNET_NAMECACHE_QueueEntry *
160find_qe (struct GNUNET_NAMECACHE_Handle *h,
161 uint32_t rid)
162{
163 struct GNUNET_NAMECACHE_QueueEntry *qe;
164
165 for (qe = h->op_head; qe != NULL; qe = qe->next)
166 {
167 if (qe->op_id == rid)
168 {
169 GNUNET_CONTAINER_DLL_remove (h->op_head,
170 h->op_tail,
171 qe);
172 return qe;
173 }
174 }
175 return NULL;
176}
177
178
179/**
180 * Handle an incoming message of type
181 * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
182 *
183 * @param cls the `struct GNUNET_NAMECACHE_Handle`
184 * @param msg the message we received
185 */
186static int
187check_lookup_block_response (void *cls,
188 const struct LookupBlockResponseMessage *msg)
189{
190 /* any length will do, format validation is in handler */
191 return GNUNET_OK;
192}
193
194
195/**
196 * Handle an incoming message of type
197 * #GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE.
198 *
199 * @param cls the `struct GNUNET_NAMECACHE_Handle`
200 * @param msg the message we received
201 */
202static void
203handle_lookup_block_response (void *cls,
204 const struct LookupBlockResponseMessage *msg)
205{
206 struct GNUNET_NAMECACHE_Handle *h = cls;
207 size_t size;
208 struct GNUNET_NAMECACHE_QueueEntry *qe;
209
210 LOG (GNUNET_ERROR_TYPE_DEBUG,
211 "Received LOOKUP_BLOCK_RESPONSE\n");
212 qe = find_qe (h,
213 ntohl (msg->gns_header.r_id));
214 if (NULL == qe)
215 return;
216 if (0 == GNUNET_TIME_absolute_ntoh (msg->expire).abs_value_us)
217 {
218 /* no match found */
219 if (NULL != qe->block_proc)
220 qe->block_proc (qe->block_proc_cls,
221 NULL);
222 GNUNET_free (qe);
223 return;
224 }
225 size = ntohs (msg->gns_header.header.size)
226 - sizeof(struct LookupBlockResponseMessage);
227 {
228 char buf[size] GNUNET_ALIGN;
229 struct GNUNET_GNSRECORD_Block *block;
230
231 memset (buf, 0, size);
232 block = (struct GNUNET_GNSRECORD_Block *) buf;
233 GNUNET_memcpy (block,
234 &msg[1],
235 size);
236 if (GNUNET_OK !=
237 GNUNET_GNSRECORD_block_verify (block))
238 {
239 GNUNET_break (0);
240 if (NULL != qe->block_proc)
241 qe->block_proc (qe->block_proc_cls,
242 NULL);
243 force_reconnect (h);
244 }
245 else
246 {
247 if (NULL != qe->block_proc)
248 qe->block_proc (qe->block_proc_cls,
249 block);
250 }
251 }
252 GNUNET_free (qe);
253}
254
255
256/**
257 * Handle an incoming message of type
258 * #GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE
259 *
260 * @param cls the `struct GNUNET_NAMECACHE_Handle`
261 * @param msg the message we received
262 * @param size the message size
263 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error and we did NOT notify the client
264 */
265static void
266handle_block_cache_response (void *cls,
267 const struct BlockCacheResponseMessage *msg)
268{
269 struct GNUNET_NAMECACHE_Handle *h = cls;
270 struct GNUNET_NAMECACHE_QueueEntry *qe;
271 int res;
272
273 LOG (GNUNET_ERROR_TYPE_DEBUG,
274 "Received BLOCK_CACHE_RESPONSE\n");
275 qe = find_qe (h,
276 ntohl (msg->gns_header.r_id));
277 if (NULL == qe)
278 return;
279 res = ntohl (msg->op_result);
280 /* TODO: add actual error message from namecache to response... */
281 if (NULL != qe->cont)
282 qe->cont (qe->cont_cls,
283 res,
284 (GNUNET_OK == res)
285 ? NULL
286 : _ ("Namecache failed to cache block"));
287 GNUNET_free (qe);
288}
289
290
291/**
292 * Generic error handler, called with the appropriate error code and
293 * the same closure specified at the creation of the message queue.
294 * Not every message queue implementation supports an error handler.
295 *
296 * @param cls closure with the `struct GNUNET_NAMECACHE_Handle *`
297 * @param error error code
298 */
299static void
300mq_error_handler (void *cls,
301 enum GNUNET_MQ_Error error)
302{
303 struct GNUNET_NAMECACHE_Handle *h = cls;
304
305 force_reconnect (h);
306}
307
308
309/**
310 * Reconnect to namecache service.
311 *
312 * @param h the handle to the NAMECACHE service
313 */
314static void
315reconnect (struct GNUNET_NAMECACHE_Handle *h)
316{
317 struct GNUNET_MQ_MessageHandler handlers[] = {
318 GNUNET_MQ_hd_var_size (lookup_block_response,
319 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK_RESPONSE,
320 struct LookupBlockResponseMessage,
321 h),
322 GNUNET_MQ_hd_fixed_size (block_cache_response,
323 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE_RESPONSE,
324 struct BlockCacheResponseMessage,
325 h),
326 GNUNET_MQ_handler_end ()
327 };
328
329 GNUNET_assert (NULL == h->mq);
330 h->mq = GNUNET_CLIENT_connect (h->cfg,
331 "namecache",
332 handlers,
333 &mq_error_handler,
334 h);
335}
336
337
338/**
339 * Re-establish the connection to the service.
340 *
341 * @param cls handle to use to re-connect.
342 */
343static void
344reconnect_task (void *cls)
345{
346 struct GNUNET_NAMECACHE_Handle *h = cls;
347
348 h->reconnect_task = NULL;
349 reconnect (h);
350}
351
352
353/**
354 * Disconnect from service and then reconnect.
355 *
356 * @param h our handle
357 */
358static void
359force_reconnect (struct GNUNET_NAMECACHE_Handle *h)
360{
361 struct GNUNET_NAMECACHE_QueueEntry *qe;
362
363 h->reconnect = GNUNET_NO;
364 GNUNET_MQ_destroy (h->mq);
365 h->mq = NULL;
366 while (NULL != (qe = h->op_head))
367 {
368 GNUNET_CONTAINER_DLL_remove (h->op_head,
369 h->op_tail,
370 qe);
371 if (NULL != qe->cont)
372 qe->cont (qe->cont_cls,
373 GNUNET_SYSERR,
374 _ ("Error communicating with namecache service"));
375 GNUNET_free (qe);
376 }
377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
378 "Reconnecting to namecache\n");
379 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
380 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_delay,
381 &reconnect_task,
382 h);
383}
384
385
386/**
387 * Get a fresh operation id to distinguish between namecache requests
388 *
389 * @param h the namecache handle
390 * @return next operation id to use
391 */
392static uint32_t
393get_op_id (struct GNUNET_NAMECACHE_Handle *h)
394{
395 return h->last_op_id_used++;
396}
397
398
399/**
400 * Initialize the connection with the NAMECACHE service.
401 *
402 * @param cfg configuration to use
403 * @return handle to the GNS service, or NULL on error
404 */
405struct GNUNET_NAMECACHE_Handle *
406GNUNET_NAMECACHE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
407{
408 struct GNUNET_NAMECACHE_Handle *h;
409
410 h = GNUNET_new (struct GNUNET_NAMECACHE_Handle);
411 h->cfg = cfg;
412 reconnect (h);
413 if (NULL == h->mq)
414 {
415 GNUNET_free (h);
416 return NULL;
417 }
418 return h;
419}
420
421
422/**
423 * Disconnect from the namecache service (and free associated
424 * resources).
425 *
426 * @param h handle to the namecache
427 */
428void
429GNUNET_NAMECACHE_disconnect (struct GNUNET_NAMECACHE_Handle *h)
430{
431 struct GNUNET_NAMECACHE_QueueEntry *q;
432
433 GNUNET_break (NULL == h->op_head);
434 while (NULL != (q = h->op_head))
435 {
436 GNUNET_CONTAINER_DLL_remove (h->op_head,
437 h->op_tail,
438 q);
439 GNUNET_free (q);
440 }
441 if (NULL != h->mq)
442 {
443 GNUNET_MQ_destroy (h->mq);
444 h->mq = NULL;
445 }
446 if (NULL != h->reconnect_task)
447 {
448 GNUNET_SCHEDULER_cancel (h->reconnect_task);
449 h->reconnect_task = NULL;
450 }
451 GNUNET_free (h);
452}
453
454
455/**
456 * Store an item in the namecache. If the item is already present,
457 * it is replaced with the new record.
458 *
459 * @param h handle to the namecache
460 * @param block block to store
461 * @param cont continuation to call when done
462 * @param cont_cls closure for @a cont
463 * @return handle to abort the request, NULL on error
464 */
465struct GNUNET_NAMECACHE_QueueEntry *
466GNUNET_NAMECACHE_block_cache (struct GNUNET_NAMECACHE_Handle *h,
467 const struct GNUNET_GNSRECORD_Block *block,
468 GNUNET_NAMECACHE_ContinuationWithStatus cont,
469 void *cont_cls)
470{
471 struct GNUNET_NAMECACHE_QueueEntry *qe;
472 struct BlockCacheMessage *msg;
473 struct GNUNET_MQ_Envelope *env;
474 uint32_t rid;
475 size_t blen;
476
477 if (NULL == h->mq)
478 return NULL;
479 blen = GNUNET_GNSRECORD_block_get_size (block);
480 rid = get_op_id (h);
481 qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
482 qe->nsh = h;
483 qe->cont = cont;
484 qe->cont_cls = cont_cls;
485 qe->op_id = rid;
486 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
487 h->op_tail,
488 qe);
489 /* send msg */
490 env = GNUNET_MQ_msg_extra (msg,
491 blen,
492 GNUNET_MESSAGE_TYPE_NAMECACHE_BLOCK_CACHE);
493 msg->gns_header.r_id = htonl (rid);
494 GNUNET_memcpy (&msg[1],
495 block,
496 blen);
497 GNUNET_MQ_send (h->mq,
498 env);
499 return qe;
500}
501
502
503/**
504 * Get a result for a particular key from the namecache. The processor
505 * will only be called once.
506 *
507 * @param h handle to the namecache
508 * @param derived_hash hash of zone key combined with name to lookup
509 * @param proc function to call on the matching block, or with
510 * NULL if there is no matching block
511 * @param proc_cls closure for @a proc
512 * @return a handle that can be used to cancel, NULL on error
513 */
514struct GNUNET_NAMECACHE_QueueEntry *
515GNUNET_NAMECACHE_lookup_block (struct GNUNET_NAMECACHE_Handle *h,
516 const struct GNUNET_HashCode *derived_hash,
517 GNUNET_NAMECACHE_BlockProcessor proc,
518 void *proc_cls)
519{
520 struct GNUNET_NAMECACHE_QueueEntry *qe;
521 struct LookupBlockMessage *msg;
522 struct GNUNET_MQ_Envelope *env;
523 uint32_t rid;
524
525 if (NULL == h->mq)
526 return NULL;
527 LOG (GNUNET_ERROR_TYPE_DEBUG,
528 "Looking for block under %s\n",
529 GNUNET_h2s (derived_hash));
530 rid = get_op_id (h);
531 qe = GNUNET_new (struct GNUNET_NAMECACHE_QueueEntry);
532 qe->nsh = h;
533 qe->block_proc = proc;
534 qe->block_proc_cls = proc_cls;
535 qe->op_id = rid;
536 GNUNET_CONTAINER_DLL_insert_tail (h->op_head,
537 h->op_tail,
538 qe);
539 env = GNUNET_MQ_msg (msg,
540 GNUNET_MESSAGE_TYPE_NAMECACHE_LOOKUP_BLOCK);
541 msg->gns_header.r_id = htonl (rid);
542 msg->query = *derived_hash;
543 GNUNET_MQ_send (h->mq,
544 env);
545 return qe;
546}
547
548
549/**
550 * Cancel a namecache operation. The final callback from the
551 * operation must not have been done yet.
552 *
553 * @param qe operation to cancel
554 */
555void
556GNUNET_NAMECACHE_cancel (struct GNUNET_NAMECACHE_QueueEntry *qe)
557{
558 struct GNUNET_NAMECACHE_Handle *h = qe->nsh;
559
560 GNUNET_CONTAINER_DLL_remove (h->op_head,
561 h->op_tail,
562 qe);
563 GNUNET_free (qe);
564}
565
566
567/* end of namecache_api.c */
diff --git a/src/namecache/plugin_namecache_flat.c b/src/namecache/plugin_namecache_flat.c
deleted file mode 100644
index eb7800051..000000000
--- a/src/namecache/plugin_namecache_flat.c
+++ /dev/null
@@ -1,430 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2015 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 */
20
21/**
22 * @file namecache/plugin_namecache_flat.c
23 * @brief flat file-based namecache backend
24 * @author Martin Schanzenbach
25 */
26
27#include "platform.h"
28#include "gnunet_namecache_plugin.h"
29#include "gnunet_namecache_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "namecache.h"
32
33/**
34 * Context for all functions in this plugin.
35 */
36struct Plugin
37{
38 const struct GNUNET_CONFIGURATION_Handle *cfg;
39
40 /**
41 * Database filename.
42 */
43 char *fn;
44
45 /**
46 * HashMap
47 */
48 struct GNUNET_CONTAINER_MultiHashMap *hm;
49};
50
51struct FlatFileEntry
52{
53 /**
54 * Block
55 */
56 struct GNUNET_GNSRECORD_Block *block;
57
58 /**
59 * query
60 */
61 struct GNUNET_HashCode query;
62};
63
64/**
65 * Initialize the database connections and associated
66 * data structures (create tables and indices
67 * as needed as well).
68 *
69 * @param plugin the plugin context (state for this module)
70 * @return #GNUNET_OK on success
71 */
72static int
73database_setup (struct Plugin *plugin)
74{
75 char *afsdir;
76 char*block_buffer;
77 char*buffer;
78 char*line;
79 char*query;
80 char*block;
81 uint64_t size;
82 struct FlatFileEntry *entry;
83 struct GNUNET_DISK_FileHandle *fh;
84
85 if (GNUNET_OK !=
86 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
87 "namecache-flat",
88 "FILENAME",
89 &afsdir))
90 {
91 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
92 "namecache-flat", "FILENAME");
93 return GNUNET_SYSERR;
94 }
95 if (GNUNET_OK != GNUNET_DISK_file_test (afsdir))
96 {
97 if (GNUNET_OK != GNUNET_DISK_directory_create_for_file (afsdir))
98 {
99 GNUNET_break (0);
100 GNUNET_free (afsdir);
101 return GNUNET_SYSERR;
102 }
103 }
104 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
105 plugin->fn = afsdir;
106
107 /* Load data from file into hashmap */
108 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
109 GNUNET_NO);
110 fh = GNUNET_DISK_file_open (afsdir,
111 GNUNET_DISK_OPEN_CREATE
112 | GNUNET_DISK_OPEN_READWRITE,
113 GNUNET_DISK_PERM_USER_WRITE
114 | GNUNET_DISK_PERM_USER_READ);
115 if (NULL == fh)
116 {
117 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118 _ ("Unable to initialize file: %s.\n"),
119 afsdir);
120 return GNUNET_SYSERR;
121 }
122
123 if (GNUNET_SYSERR == GNUNET_DISK_file_size (afsdir,
124 &size,
125 GNUNET_YES,
126 GNUNET_YES))
127 {
128 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
129 _ ("Unable to get filesize: %s.\n"),
130 afsdir);
131 GNUNET_DISK_file_close (fh);
132 return GNUNET_SYSERR;
133 }
134
135 if (0 == size)
136 {
137 GNUNET_DISK_file_close (fh);
138 return GNUNET_OK;
139 }
140
141 buffer = GNUNET_malloc (size + 1);
142
143 if (GNUNET_SYSERR == GNUNET_DISK_file_read (fh,
144 buffer,
145 size))
146 {
147 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
148 _ ("Unable to read file: %s.\n"),
149 afsdir);
150 GNUNET_free (buffer);
151 GNUNET_DISK_file_close (fh);
152 return GNUNET_SYSERR;
153 }
154 buffer[size] = '\0';
155
156 GNUNET_DISK_file_close (fh);
157 if (0 < size)
158 {
159 line = strtok (buffer, "\n");
160 while (line != NULL)
161 {
162 query = strtok (line, ",");
163 if (NULL == query)
164 break;
165 block = strtok (NULL, ",");
166 if (NULL == block)
167 break;
168 line = strtok (NULL, "\n");
169 entry = GNUNET_malloc (sizeof(struct FlatFileEntry));
170 GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_hash_from_string (query,
171 &entry->query));
172 GNUNET_STRINGS_base64_decode (block,
173 strlen (block),
174 (void **) &block_buffer);
175 entry->block = (struct GNUNET_GNSRECORD_Block *) block_buffer;
176 if (GNUNET_OK !=
177 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
178 &entry->query,
179 entry,
180 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
181 {
182 GNUNET_free (entry);
183 GNUNET_break (0);
184 }
185 }
186 }
187 GNUNET_free (buffer);
188 return GNUNET_OK;
189}
190
191
192/**
193 * Store values in hashmap in file and free data
194 *
195 * @param plugin the plugin context
196 */
197static int
198store_and_free_entries (void *cls,
199 const struct GNUNET_HashCode *key,
200 void *value)
201{
202 struct GNUNET_DISK_FileHandle *fh = cls;
203 struct FlatFileEntry *entry = value;
204
205 char *line;
206 char *block_b64;
207 struct GNUNET_CRYPTO_HashAsciiEncoded query;
208 size_t block_size;
209
210 block_size = GNUNET_GNSRECORD_block_get_size (entry->block);
211 GNUNET_STRINGS_base64_encode ((char *) entry->block,
212 block_size,
213 &block_b64);
214 GNUNET_CRYPTO_hash_to_enc (&entry->query,
215 &query);
216 GNUNET_asprintf (&line,
217 "%s,%s\n",
218 (char *) &query,
219 block_b64);
220
221 GNUNET_free (block_b64);
222
223 GNUNET_DISK_file_write (fh,
224 line,
225 strlen (line));
226
227 GNUNET_free (entry->block);
228 GNUNET_free (entry);
229 GNUNET_free (line);
230 return GNUNET_YES;
231}
232
233
234/**
235 * Shutdown database connection and associate data
236 * structures.
237 * @param plugin the plugin context (state for this module)
238 */
239static void
240database_shutdown (struct Plugin *plugin)
241{
242 struct GNUNET_DISK_FileHandle *fh;
243
244 fh = GNUNET_DISK_file_open (plugin->fn,
245 GNUNET_DISK_OPEN_CREATE
246 | GNUNET_DISK_OPEN_TRUNCATE
247 | GNUNET_DISK_OPEN_READWRITE,
248 GNUNET_DISK_PERM_USER_WRITE
249 | GNUNET_DISK_PERM_USER_READ);
250 if (NULL == fh)
251 {
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
253 _ ("Unable to initialize file: %s.\n"),
254 plugin->fn);
255 return;
256 }
257
258 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
259 &store_and_free_entries,
260 fh);
261 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
262 GNUNET_DISK_file_close (fh);
263}
264
265
266static int
267expire_blocks (void *cls,
268 const struct GNUNET_HashCode *key,
269 void *value)
270{
271 struct Plugin *plugin = cls;
272 struct FlatFileEntry *entry = value;
273 struct GNUNET_TIME_Absolute now;
274 struct GNUNET_TIME_Absolute expiration;
275
276 now = GNUNET_TIME_absolute_get ();
277 expiration = GNUNET_GNSRECORD_block_get_expiration (entry->block);
278
279 if (0 == GNUNET_TIME_absolute_get_difference (now,
280 expiration).rel_value_us)
281 {
282 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, key);
283 }
284 return GNUNET_YES;
285}
286
287
288/**
289 * Removes any expired block.
290 *
291 * @param plugin the plugin
292 */
293static void
294namecache_expire_blocks (struct Plugin *plugin)
295{
296 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
297 &expire_blocks,
298 plugin);
299}
300
301
302/**
303 * Cache a block in the datastore.
304 *
305 * @param cls closure (internal context for the plugin)
306 * @param block block to cache
307 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
308 */
309static int
310namecache_cache_block (void *cls,
311 const struct GNUNET_GNSRECORD_Block *block)
312{
313 struct Plugin *plugin = cls;
314 struct GNUNET_HashCode query;
315 struct FlatFileEntry *entry;
316 size_t block_size;
317
318 namecache_expire_blocks (plugin);
319 GNUNET_GNSRECORD_query_from_block (block,
320 &query);
321 block_size = GNUNET_GNSRECORD_block_get_size (block);
322 if (block_size > 64 * 65536)
323 {
324 GNUNET_break (0);
325 return GNUNET_SYSERR;
326 }
327 entry = GNUNET_malloc (sizeof(struct FlatFileEntry));
328 entry->block = GNUNET_malloc (block_size);
329 GNUNET_memcpy (entry->block, block, block_size);
330 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm, &query);
331 if (GNUNET_OK !=
332 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
333 &query,
334 entry,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
336 {
337 GNUNET_free (entry);
338 GNUNET_break (0);
339 return GNUNET_SYSERR;
340 }
341 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
342 "Caching block under derived key `%s'\n",
343 GNUNET_h2s_full (&query));
344 return GNUNET_OK;
345}
346
347
348/**
349 * Get the block for a particular zone and label in the
350 * datastore. Will return at most one result to the iterator.
351 *
352 * @param cls closure (internal context for the plugin)
353 * @param query hash of public key derived from the zone and the label
354 * @param iter function to call with the result
355 * @param iter_cls closure for @a iter
356 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
357 */
358static int
359namecache_lookup_block (void *cls,
360 const struct GNUNET_HashCode *query,
361 GNUNET_NAMECACHE_BlockCallback iter, void *iter_cls)
362{
363 struct Plugin *plugin = cls;
364 const struct GNUNET_GNSRECORD_Block *block;
365
366 block = GNUNET_CONTAINER_multihashmap_get (plugin->hm, query);
367 if (NULL == block)
368 return GNUNET_NO;
369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
370 "Found block under derived key `%s'\n",
371 GNUNET_h2s_full (query));
372 iter (iter_cls, block);
373 return GNUNET_YES;
374}
375
376
377/**
378 * Entry point for the plugin.
379 *
380 * @param cls the "struct GNUNET_NAMECACHE_PluginEnvironment*"
381 * @return NULL on error, otherwise the plugin context
382 */
383void *
384libgnunet_plugin_namecache_flat_init (void *cls)
385{
386 static struct Plugin plugin;
387 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
388 struct GNUNET_NAMECACHE_PluginFunctions *api;
389
390 if (NULL != plugin.cfg)
391 return NULL; /* can only initialize once! */
392 memset (&plugin, 0, sizeof(struct Plugin));
393 plugin.cfg = cfg;
394 if (GNUNET_OK != database_setup (&plugin))
395 {
396 database_shutdown (&plugin);
397 return NULL;
398 }
399 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions);
400 api->cls = &plugin;
401 api->cache_block = &namecache_cache_block;
402 api->lookup_block = &namecache_lookup_block;
403 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
404 _ ("flat plugin running\n"));
405 return api;
406}
407
408
409/**
410 * Exit point from the plugin.
411 *
412 * @param cls the plugin context (as returned by "init")
413 * @return always NULL
414 */
415void *
416libgnunet_plugin_namecache_flat_done (void *cls)
417{
418 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
419 struct Plugin *plugin = api->cls;
420
421 database_shutdown (plugin);
422 plugin->cfg = NULL;
423 GNUNET_free (api);
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "flat plugin is finished\n");
426 return NULL;
427}
428
429
430/* end of plugin_namecache_sqlite.c */
diff --git a/src/namecache/plugin_namecache_postgres.c b/src/namecache/plugin_namecache_postgres.c
deleted file mode 100644
index ae0f71a1f..000000000
--- a/src/namecache/plugin_namecache_postgres.c
+++ /dev/null
@@ -1,347 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013, 2016, 2017 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 */
20
21/**
22 * @file namecache/plugin_namecache_postgres.c
23 * @brief postgres-based namecache backend
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_namecache_plugin.h"
28#include "gnunet_namecache_service.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_pq_lib.h"
31#include "namecache.h"
32
33
34#define LOG(kind, ...) GNUNET_log_from (kind, "namecache-postgres", __VA_ARGS__)
35
36
37/**
38 * Context for all functions in this plugin.
39 */
40struct Plugin
41{
42 const struct GNUNET_CONFIGURATION_Handle *cfg;
43
44 /**
45 * Postgres database handle.
46 */
47 struct GNUNET_PQ_Context *dbh;
48};
49
50
51/**
52 * Initialize the database connections and associated
53 * data structures (create tables and indices
54 * as needed as well).
55 *
56 * @param plugin the plugin context (state for this module)
57 * @return #GNUNET_OK on success
58 */
59static int
60database_setup (struct Plugin *plugin)
61{
62 struct GNUNET_PQ_ExecuteStatement es_temporary =
63 GNUNET_PQ_make_execute ("CREATE TEMPORARY TABLE IF NOT EXISTS ns096blocks ("
64 " query BYTEA NOT NULL DEFAULT '',"
65 " block BYTEA NOT NULL DEFAULT '',"
66 " expiration_time BIGINT NOT NULL DEFAULT 0"
67 ")");
68 struct GNUNET_PQ_ExecuteStatement es_default =
69 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns096blocks ("
70 " query BYTEA NOT NULL DEFAULT '',"
71 " block BYTEA NOT NULL DEFAULT '',"
72 " expiration_time BIGINT NOT NULL DEFAULT 0"
73 ")");
74 const struct GNUNET_PQ_ExecuteStatement *cr;
75
76 if (GNUNET_YES ==
77 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
78 "namecache-postgres",
79 "TEMPORARY_TABLE"))
80 {
81 cr = &es_temporary;
82 }
83 else
84 {
85 cr = &es_default;
86 }
87 {
88 struct GNUNET_PQ_ExecuteStatement es[] = {
89 *cr,
90 GNUNET_PQ_make_try_execute (
91 "CREATE INDEX ir_query_hash ON ns096blocks (query,expiration_time)"),
92 GNUNET_PQ_make_try_execute (
93 "CREATE INDEX ir_block_expiration ON ns096blocks (expiration_time)"),
94 GNUNET_PQ_EXECUTE_STATEMENT_END
95 };
96 struct GNUNET_PQ_PreparedStatement ps[] = {
97 GNUNET_PQ_make_prepare ("cache_block",
98 "INSERT INTO ns096blocks (query, block, expiration_time) VALUES "
99 "($1, $2, $3)", 3),
100 GNUNET_PQ_make_prepare ("expire_blocks",
101 "DELETE FROM ns096blocks WHERE expiration_time<$1",
102 1),
103 GNUNET_PQ_make_prepare ("delete_block",
104 "DELETE FROM ns096blocks WHERE query=$1 AND expiration_time<=$2",
105 2),
106 GNUNET_PQ_make_prepare ("lookup_block",
107 "SELECT block FROM ns096blocks WHERE query=$1"
108 " ORDER BY expiration_time DESC LIMIT 1", 1),
109 GNUNET_PQ_PREPARED_STATEMENT_END
110 };
111
112 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
113 "namecache-postgres",
114 NULL,
115 es,
116 ps);
117 }
118 if (NULL == plugin->dbh)
119 return GNUNET_SYSERR;
120 return GNUNET_OK;
121}
122
123
124/**
125 * Removes any expired block.
126 *
127 * @param plugin the plugin
128 */
129static void
130namecache_postgres_expire_blocks (struct Plugin *plugin)
131{
132 struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
133 struct GNUNET_PQ_QueryParam params[] = {
134 GNUNET_PQ_query_param_absolute_time (&now),
135 GNUNET_PQ_query_param_end
136 };
137 enum GNUNET_DB_QueryStatus res;
138
139 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
140 "expire_blocks",
141 params);
142 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res);
143}
144
145
146/**
147 * Delete older block in the datastore.
148 *
149 * @param plugin the plugin
150 * @param query query for the block
151 * @param expiration_time how old does the block have to be for deletion
152 */
153static void
154delete_old_block (struct Plugin *plugin,
155 const struct GNUNET_HashCode *query,
156 struct GNUNET_TIME_Absolute expiration_time)
157{
158 struct GNUNET_PQ_QueryParam params[] = {
159 GNUNET_PQ_query_param_auto_from_type (query),
160 GNUNET_PQ_query_param_absolute_time (&expiration_time),
161 GNUNET_PQ_query_param_end
162 };
163 enum GNUNET_DB_QueryStatus res;
164
165 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
166 "delete_block",
167 params);
168 GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR != res);
169}
170
171
172/**
173 * Cache a block in the datastore.
174 *
175 * @param cls closure (internal context for the plugin)
176 * @param block block to cache
177 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
178 */
179static int
180namecache_postgres_cache_block (void *cls,
181 const struct GNUNET_GNSRECORD_Block *block)
182{
183 struct Plugin *plugin = cls;
184 struct GNUNET_HashCode query;
185 size_t block_size = GNUNET_GNSRECORD_block_get_size (block);
186 struct GNUNET_TIME_Absolute exp;
187 exp = GNUNET_GNSRECORD_block_get_expiration (block);
188 struct GNUNET_PQ_QueryParam params[] = {
189 GNUNET_PQ_query_param_auto_from_type (&query),
190 GNUNET_PQ_query_param_fixed_size (block, block_size),
191 GNUNET_PQ_query_param_absolute_time (&exp),
192 GNUNET_PQ_query_param_end
193 };
194 enum GNUNET_DB_QueryStatus res;
195
196 namecache_postgres_expire_blocks (plugin);
197 GNUNET_GNSRECORD_query_from_block (block,
198 &query);
199 if (block_size > 64 * 65536)
200 {
201 GNUNET_break (0);
202 return GNUNET_SYSERR;
203 }
204 delete_old_block (plugin,
205 &query,
206 exp);
207
208 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
209 "cache_block",
210 params);
211 if (0 > res)
212 return GNUNET_SYSERR;
213 return GNUNET_OK;
214}
215
216
217/**
218 * Get the block for a particular zone and label in the
219 * datastore. Will return at most one result to the iterator.
220 *
221 * @param cls closure (internal context for the plugin)
222 * @param query hash of public key derived from the zone and the label
223 * @param iter function to call with the result
224 * @param iter_cls closure for @a iter
225 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
226 */
227static int
228namecache_postgres_lookup_block (void *cls,
229 const struct GNUNET_HashCode *query,
230 GNUNET_NAMECACHE_BlockCallback iter,
231 void *iter_cls)
232{
233 struct Plugin *plugin = cls;
234 size_t bsize;
235 struct GNUNET_GNSRECORD_Block *block;
236 struct GNUNET_PQ_QueryParam params[] = {
237 GNUNET_PQ_query_param_auto_from_type (query),
238 GNUNET_PQ_query_param_end
239 };
240 struct GNUNET_PQ_ResultSpec rs[] = {
241 GNUNET_PQ_result_spec_variable_size ("block",
242 (void **) &block,
243 &bsize),
244 GNUNET_PQ_result_spec_end
245 };
246 enum GNUNET_DB_QueryStatus res;
247
248 res = GNUNET_PQ_eval_prepared_singleton_select (plugin->dbh,
249 "lookup_block",
250 params,
251 rs);
252 if (0 > res)
253 {
254 LOG (GNUNET_ERROR_TYPE_WARNING,
255 "Failing lookup block in namecache (postgres error)\n");
256 return GNUNET_SYSERR;
257 }
258 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
259 {
260 /* no result */
261 LOG (GNUNET_ERROR_TYPE_DEBUG,
262 "Ending iteration (no more results)\n");
263 return GNUNET_NO;
264 }
265 if ((bsize < sizeof(*block)))
266 {
267 GNUNET_break (0);
268 LOG (GNUNET_ERROR_TYPE_DEBUG,
269 "Failing lookup (corrupt block)\n");
270 GNUNET_PQ_cleanup_result (rs);
271 return GNUNET_SYSERR;
272 }
273 iter (iter_cls,
274 block);
275 GNUNET_PQ_cleanup_result (rs);
276 return GNUNET_OK;
277}
278
279
280/**
281 * Shutdown database connection and associate data
282 * structures.
283 *
284 * @param plugin the plugin context (state for this module)
285 */
286static void
287database_shutdown (struct Plugin *plugin)
288{
289 GNUNET_PQ_disconnect (plugin->dbh);
290 plugin->dbh = NULL;
291}
292
293
294/**
295 * Entry point for the plugin.
296 *
297 * @param cls the `struct GNUNET_NAMECACHE_PluginEnvironment *`
298 * @return NULL on error, otherwise the plugin context
299 */
300void *
301libgnunet_plugin_namecache_postgres_init (void *cls)
302{
303 static struct Plugin plugin;
304 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
305 struct GNUNET_NAMECACHE_PluginFunctions *api;
306
307 if (NULL != plugin.cfg)
308 return NULL; /* can only initialize once! */
309 memset (&plugin, 0, sizeof(struct Plugin));
310 plugin.cfg = cfg;
311 if (GNUNET_OK != database_setup (&plugin))
312 {
313 database_shutdown (&plugin);
314 return NULL;
315 }
316 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions);
317 api->cls = &plugin;
318 api->cache_block = &namecache_postgres_cache_block;
319 api->lookup_block = &namecache_postgres_lookup_block;
320 LOG (GNUNET_ERROR_TYPE_INFO,
321 "Postgres namecache plugin running\n");
322 return api;
323}
324
325
326/**
327 * Exit point from the plugin.
328 *
329 * @param cls the plugin context (as returned by "init")
330 * @return always NULL
331 */
332void *
333libgnunet_plugin_namecache_postgres_done (void *cls)
334{
335 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
336 struct Plugin *plugin = api->cls;
337
338 database_shutdown (plugin);
339 plugin->cfg = NULL;
340 GNUNET_free (api);
341 LOG (GNUNET_ERROR_TYPE_DEBUG,
342 "Postgres namecache plugin is finished\n");
343 return NULL;
344}
345
346
347/* end of plugin_namecache_postgres.c */
diff --git a/src/namecache/plugin_namecache_sqlite.c b/src/namecache/plugin_namecache_sqlite.c
deleted file mode 100644
index 82008c837..000000000
--- a/src/namecache/plugin_namecache_sqlite.c
+++ /dev/null
@@ -1,590 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013 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 */
20
21/**
22 * @file namecache/plugin_namecache_sqlite.c
23 * @brief sqlite-based namecache backend
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_sq_lib.h"
28#include "gnunet_namecache_plugin.h"
29#include "gnunet_namecache_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "namecache.h"
32#include <sqlite3.h>
33
34/**
35 * After how many ms "busy" should a DB operation fail for good? A
36 * low value makes sure that we are more responsive to requests
37 * (especially PUTs). A high value guarantees a higher success rate
38 * (SELECTs in iterate can take several seconds despite LIMIT=1).
39 *
40 * The default value of 1s should ensure that users do not experience
41 * huge latencies while at the same time allowing operations to
42 * succeed with reasonable probability.
43 */
44#define BUSY_TIMEOUT_MS 1000
45
46
47/**
48 * Log an error message at log-level 'level' that indicates
49 * a failure of the command 'cmd' on file 'filename'
50 * with the message given by strerror(errno).
51 */
52#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, \
53 "namecache-sqlite", _ ( \
54 "`%s' failed at %s:%d with error: %s\n"), \
55 cmd, \
56 __FILE__, __LINE__, \
57 sqlite3_errmsg ( \
58 db->dbh)); \
59} while (0)
60
61#define LOG(kind, ...) GNUNET_log_from (kind, "namecache-sqlite", __VA_ARGS__)
62
63
64/**
65 * Context for all functions in this plugin.
66 */
67struct Plugin
68{
69 const struct GNUNET_CONFIGURATION_Handle *cfg;
70
71 /**
72 * Database filename.
73 */
74 char *fn;
75
76 /**
77 * Native SQLite database handle.
78 */
79 sqlite3 *dbh;
80
81 /**
82 * Precompiled SQL for caching a block
83 */
84 sqlite3_stmt *cache_block;
85
86 /**
87 * Precompiled SQL for deleting an older block
88 */
89 sqlite3_stmt *delete_block;
90
91 /**
92 * Precompiled SQL for looking up a block
93 */
94 sqlite3_stmt *lookup_block;
95
96 /**
97 * Precompiled SQL for removing expired blocks
98 */
99 sqlite3_stmt *expire_blocks;
100};
101
102
103/**
104 * Initialize the database connections and associated
105 * data structures (create tables and indices
106 * as needed as well).
107 *
108 * @param plugin the plugin context (state for this module)
109 * @return #GNUNET_OK on success
110 */
111static int
112database_setup (struct Plugin *plugin)
113{
114 struct GNUNET_SQ_ExecuteStatement es[] = {
115 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
116 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
117 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
118 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
119 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
120 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"),
121 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
122 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
123 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns096blocks ("
124 " query BLOB NOT NULL,"
125 " block BLOB NOT NULL,"
126 " expiration_time INT8 NOT NULL"
127 ")"),
128 GNUNET_SQ_make_execute ("CREATE INDEX IF NOT EXISTS ir_query_hash "
129 "ON ns096blocks (query,expiration_time)"),
130 GNUNET_SQ_make_execute ("CREATE INDEX IF NOT EXISTS ir_block_expiration "
131 "ON ns096blocks (expiration_time)"),
132 GNUNET_SQ_EXECUTE_STATEMENT_END
133 };
134 struct GNUNET_SQ_PrepareStatement ps[] = {
135 GNUNET_SQ_make_prepare (
136 "INSERT INTO ns096blocks (query,block,expiration_time) VALUES (?, ?, ?)",
137 &plugin->cache_block),
138 GNUNET_SQ_make_prepare ("DELETE FROM ns096blocks WHERE expiration_time<?",
139 &plugin->expire_blocks),
140 GNUNET_SQ_make_prepare (
141 "DELETE FROM ns096blocks WHERE query=? AND expiration_time<=?",
142 &plugin->delete_block),
143 GNUNET_SQ_make_prepare ("SELECT block FROM ns096blocks WHERE query=? "
144 "ORDER BY expiration_time DESC LIMIT 1",
145 &plugin->lookup_block),
146 GNUNET_SQ_PREPARE_END
147 };
148 char *afsdir;
149
150 if (GNUNET_OK !=
151 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
152 "namecache-sqlite",
153 "FILENAME",
154 &afsdir))
155 {
156 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
157 "namecache-sqlite",
158 "FILENAME");
159 return GNUNET_SYSERR;
160 }
161 if (GNUNET_OK !=
162 GNUNET_DISK_file_test (afsdir))
163 {
164 if (GNUNET_OK !=
165 GNUNET_DISK_directory_create_for_file (afsdir))
166 {
167 GNUNET_break (0);
168 GNUNET_free (afsdir);
169 return GNUNET_SYSERR;
170 }
171 }
172 /* afsdir should be UTF-8-encoded. If it isn't, it's a bug */
173 plugin->fn = afsdir;
174
175 /* Open database and precompile statements */
176 if (SQLITE_OK !=
177 sqlite3_open (plugin->fn, &plugin->dbh))
178 {
179 LOG (GNUNET_ERROR_TYPE_ERROR,
180 _ ("Unable to initialize SQLite: %s.\n"),
181 sqlite3_errmsg (plugin->dbh));
182 return GNUNET_SYSERR;
183 }
184 if (GNUNET_OK !=
185 GNUNET_SQ_exec_statements (plugin->dbh,
186 es))
187 {
188 GNUNET_break (0);
189 LOG (GNUNET_ERROR_TYPE_ERROR,
190 _ ("Failed to setup database at `%s'\n"),
191 plugin->fn);
192 return GNUNET_SYSERR;
193 }
194 GNUNET_break (SQLITE_OK ==
195 sqlite3_busy_timeout (plugin->dbh,
196 BUSY_TIMEOUT_MS));
197
198 if (GNUNET_OK !=
199 GNUNET_SQ_prepare (plugin->dbh,
200 ps))
201 {
202 GNUNET_break (0);
203 LOG (GNUNET_ERROR_TYPE_ERROR,
204 _ ("Failed to setup database at `%s'\n"),
205 plugin->fn);
206 return GNUNET_SYSERR;
207 }
208
209 return GNUNET_OK;
210}
211
212
213/**
214 * Shutdown database connection and associate data
215 * structures.
216 * @param plugin the plugin context (state for this module)
217 */
218static void
219database_shutdown (struct Plugin *plugin)
220{
221 int result;
222 sqlite3_stmt *stmt;
223
224 if (NULL != plugin->cache_block)
225 sqlite3_finalize (plugin->cache_block);
226 if (NULL != plugin->lookup_block)
227 sqlite3_finalize (plugin->lookup_block);
228 if (NULL != plugin->expire_blocks)
229 sqlite3_finalize (plugin->expire_blocks);
230 if (NULL != plugin->delete_block)
231 sqlite3_finalize (plugin->delete_block);
232 result = sqlite3_close (plugin->dbh);
233 if (result == SQLITE_BUSY)
234 {
235 LOG (GNUNET_ERROR_TYPE_WARNING,
236 _ (
237 "Tried to close sqlite without finalizing all prepared statements.\n"));
238 stmt = sqlite3_next_stmt (plugin->dbh,
239 NULL);
240 while (stmt != NULL)
241 {
242 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
243 "sqlite",
244 "Closing statement %p\n",
245 stmt);
246 result = sqlite3_finalize (stmt);
247 if (result != SQLITE_OK)
248 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
249 "sqlite",
250 "Failed to close statement %p: %d\n",
251 stmt,
252 result);
253 stmt = sqlite3_next_stmt (plugin->dbh,
254 NULL);
255 }
256 result = sqlite3_close (plugin->dbh);
257 }
258 if (SQLITE_OK != result)
259 LOG_SQLITE (plugin,
260 GNUNET_ERROR_TYPE_ERROR,
261 "sqlite3_close");
262
263 GNUNET_free (plugin->fn);
264}
265
266
267/**
268 * Removes any expired block.
269 *
270 * @param plugin the plugin
271 */
272static void
273namecache_sqlite_expire_blocks (struct Plugin *plugin)
274{
275 struct GNUNET_TIME_Absolute now;
276 struct GNUNET_SQ_QueryParam params[] = {
277 GNUNET_SQ_query_param_absolute_time (&now),
278 GNUNET_SQ_query_param_end
279 };
280 int n;
281
282 now = GNUNET_TIME_absolute_get ();
283 if (GNUNET_OK !=
284 GNUNET_SQ_bind (plugin->expire_blocks,
285 params))
286 {
287 LOG_SQLITE (plugin,
288 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
289 "sqlite3_bind_XXXX");
290 GNUNET_SQ_reset (plugin->dbh,
291 plugin->expire_blocks);
292 return;
293 }
294 n = sqlite3_step (plugin->expire_blocks);
295 GNUNET_SQ_reset (plugin->dbh,
296 plugin->expire_blocks);
297 switch (n)
298 {
299 case SQLITE_DONE:
300 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
301 "sqlite",
302 "Records expired\n");
303 return;
304
305 case SQLITE_BUSY:
306 LOG_SQLITE (plugin,
307 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
308 "sqlite3_step");
309 return;
310
311 default:
312 LOG_SQLITE (plugin,
313 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
314 "sqlite3_step");
315 return;
316 }
317}
318
319
320/**
321 * Cache a block in the datastore.
322 *
323 * @param cls closure (internal context for the plugin)
324 * @param block block to cache
325 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
326 */
327static int
328namecache_sqlite_cache_block (void *cls,
329 const struct GNUNET_GNSRECORD_Block *block)
330{
331 static struct GNUNET_TIME_Absolute last_expire;
332 struct Plugin *plugin = cls;
333 struct GNUNET_HashCode query;
334 struct GNUNET_TIME_Absolute expiration;
335 size_t block_size = GNUNET_GNSRECORD_block_get_size (block);
336 struct GNUNET_SQ_QueryParam del_params[] = {
337 GNUNET_SQ_query_param_auto_from_type (&query),
338 GNUNET_SQ_query_param_absolute_time (&expiration),
339 GNUNET_SQ_query_param_end
340 };
341 struct GNUNET_SQ_QueryParam ins_params[] = {
342 GNUNET_SQ_query_param_auto_from_type (&query),
343 GNUNET_SQ_query_param_fixed_size (block,
344 block_size),
345 GNUNET_SQ_query_param_absolute_time (&expiration),
346 GNUNET_SQ_query_param_end
347 };
348 int n;
349
350 /* run expiration of old cache entries once per hour */
351 if (GNUNET_TIME_absolute_get_duration (last_expire).rel_value_us >
352 GNUNET_TIME_UNIT_HOURS.rel_value_us)
353 {
354 last_expire = GNUNET_TIME_absolute_get ();
355 namecache_sqlite_expire_blocks (plugin);
356 }
357 GNUNET_assert (GNUNET_OK ==
358 GNUNET_GNSRECORD_query_from_block (block, &query));
359 expiration = GNUNET_GNSRECORD_block_get_expiration (block);
360 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
361 "Caching new version of block %s (expires %s)\n",
362 GNUNET_h2s (&query),
363 GNUNET_STRINGS_absolute_time_to_string (expiration));
364 if (block_size > 64 * 65536)
365 {
366 GNUNET_break (0);
367 return GNUNET_SYSERR;
368 }
369
370 /* delete old version of the block */
371 if (GNUNET_OK !=
372 GNUNET_SQ_bind (plugin->delete_block,
373 del_params))
374 {
375 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
376 "sqlite3_bind_XXXX");
377 GNUNET_SQ_reset (plugin->dbh,
378 plugin->delete_block);
379 return GNUNET_SYSERR;
380 }
381 n = sqlite3_step (plugin->delete_block);
382 switch (n)
383 {
384 case SQLITE_DONE:
385 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
386 "sqlite",
387 "Old block deleted\n");
388 break;
389
390 case SQLITE_BUSY:
391 LOG_SQLITE (plugin,
392 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
393 "sqlite3_step");
394 break;
395
396 default:
397 LOG_SQLITE (plugin,
398 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
399 "sqlite3_step");
400 break;
401 }
402 GNUNET_SQ_reset (plugin->dbh,
403 plugin->delete_block);
404
405 /* insert new version of the block */
406 if (GNUNET_OK !=
407 GNUNET_SQ_bind (plugin->cache_block,
408 ins_params))
409 {
410 LOG_SQLITE (plugin,
411 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
412 "sqlite3_bind_XXXX");
413 GNUNET_SQ_reset (plugin->dbh,
414 plugin->cache_block);
415 return GNUNET_SYSERR;
416 }
417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
418 "Caching block under derived key `%s'\n",
419 GNUNET_h2s_full (&query));
420 n = sqlite3_step (plugin->cache_block);
421 GNUNET_SQ_reset (plugin->dbh,
422 plugin->cache_block);
423 switch (n)
424 {
425 case SQLITE_DONE:
426 LOG (GNUNET_ERROR_TYPE_DEBUG,
427 "Record stored\n");
428 return GNUNET_OK;
429
430 case SQLITE_BUSY:
431 LOG_SQLITE (plugin,
432 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
433 "sqlite3_step");
434 return GNUNET_NO;
435
436 default:
437 LOG_SQLITE (plugin,
438 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
439 "sqlite3_step");
440 return GNUNET_SYSERR;
441 }
442}
443
444
445/**
446 * Get the block for a particular zone and label in the
447 * datastore. Will return at most one result to the iterator.
448 *
449 * @param cls closure (internal context for the plugin)
450 * @param query hash of public key derived from the zone and the label
451 * @param iter function to call with the result
452 * @param iter_cls closure for @a iter
453 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
454 */
455static int
456namecache_sqlite_lookup_block (void *cls,
457 const struct GNUNET_HashCode *query,
458 GNUNET_NAMECACHE_BlockCallback iter,
459 void *iter_cls)
460{
461 struct Plugin *plugin = cls;
462 int ret;
463 int sret;
464 size_t block_size;
465 const struct GNUNET_GNSRECORD_Block *block;
466 struct GNUNET_SQ_QueryParam params[] = {
467 GNUNET_SQ_query_param_auto_from_type (query),
468 GNUNET_SQ_query_param_end
469 };
470 struct GNUNET_SQ_ResultSpec rs[] = {
471 GNUNET_SQ_result_spec_variable_size ((void **) &block,
472 &block_size),
473 GNUNET_SQ_result_spec_end
474 };
475
476 if (GNUNET_OK !=
477 GNUNET_SQ_bind (plugin->lookup_block,
478 params))
479 {
480 LOG_SQLITE (plugin,
481 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
482 "sqlite3_bind_XXXX");
483 GNUNET_SQ_reset (plugin->dbh,
484 plugin->lookup_block);
485 return GNUNET_SYSERR;
486 }
487 ret = GNUNET_NO;
488 if (SQLITE_ROW ==
489 (sret = sqlite3_step (plugin->lookup_block)))
490 {
491 if (GNUNET_OK !=
492 GNUNET_SQ_extract_result (plugin->lookup_block,
493 rs))
494 {
495 GNUNET_break (0);
496 ret = GNUNET_SYSERR;
497 }
498 else if ((block_size < sizeof(struct GNUNET_GNSRECORD_Block)))
499 {
500 GNUNET_break (0);
501 GNUNET_SQ_cleanup_result (rs);
502 ret = GNUNET_SYSERR;
503 }
504 else
505 {
506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
507 "Found block under derived key `%s'\n",
508 GNUNET_h2s_full (query));
509 iter (iter_cls,
510 block);
511 GNUNET_SQ_cleanup_result (rs);
512 ret = GNUNET_YES;
513 }
514 }
515 else
516 {
517 if (SQLITE_DONE != sret)
518 {
519 LOG_SQLITE (plugin,
520 GNUNET_ERROR_TYPE_ERROR,
521 "sqlite_step");
522 ret = GNUNET_SYSERR;
523 }
524 else
525 {
526 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
527 "No block found under derived key `%s'\n",
528 GNUNET_h2s_full (query));
529 }
530 }
531 GNUNET_SQ_reset (plugin->dbh,
532 plugin->lookup_block);
533 return ret;
534}
535
536
537/**
538 * Entry point for the plugin.
539 *
540 * @param cls the "struct GNUNET_NAMECACHE_PluginEnvironment*"
541 * @return NULL on error, otherwise the plugin context
542 */
543void *
544libgnunet_plugin_namecache_sqlite_init (void *cls)
545{
546 static struct Plugin plugin;
547 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
548 struct GNUNET_NAMECACHE_PluginFunctions *api;
549
550 if (NULL != plugin.cfg)
551 return NULL; /* can only initialize once! */
552 memset (&plugin, 0, sizeof(struct Plugin));
553 plugin.cfg = cfg;
554 if (GNUNET_OK != database_setup (&plugin))
555 {
556 database_shutdown (&plugin);
557 return NULL;
558 }
559 api = GNUNET_new (struct GNUNET_NAMECACHE_PluginFunctions);
560 api->cls = &plugin;
561 api->cache_block = &namecache_sqlite_cache_block;
562 api->lookup_block = &namecache_sqlite_lookup_block;
563 LOG (GNUNET_ERROR_TYPE_INFO,
564 _ ("Sqlite database running\n"));
565 return api;
566}
567
568
569/**
570 * Exit point from the plugin.
571 *
572 * @param cls the plugin context (as returned by "init")
573 * @return always NULL
574 */
575void *
576libgnunet_plugin_namecache_sqlite_done (void *cls)
577{
578 struct GNUNET_NAMECACHE_PluginFunctions *api = cls;
579 struct Plugin *plugin = api->cls;
580
581 database_shutdown (plugin);
582 plugin->cfg = NULL;
583 GNUNET_free (api);
584 LOG (GNUNET_ERROR_TYPE_DEBUG,
585 "sqlite plugin is finished\n");
586 return NULL;
587}
588
589
590/* end of plugin_namecache_sqlite.c */
diff --git a/src/namecache/test_namecache_api.conf b/src/namecache/test_namecache_api.conf
deleted file mode 100644
index b1ae31f14..000000000
--- a/src/namecache/test_namecache_api.conf
+++ /dev/null
@@ -1,13 +0,0 @@
1[PATHS]
2GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-namecache/
3
4[namecache]
5DATABASE = sqlite
6
7[namecache-sqlite]
8FILENAME = $GNUNET_TEST_HOME/namecache/sqlite_test.db
9
10[namecache-postgres]
11CONFIG = connect_timeout=10; dbname=gnunetcheck
12TEMPORARY_TABLE = YES
13
diff --git a/src/namecache/test_namecache_api_cache_block.c b/src/namecache/test_namecache_api_cache_block.c
deleted file mode 100644
index 310c4de42..000000000
--- a/src/namecache/test_namecache_api_cache_block.c
+++ /dev/null
@@ -1,242 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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 */
20/**
21 * @file namecache/test_namecache_api.c
22 * @brief testcase for namecache_api.c: store a record and perform a lookup
23 */
24#include "platform.h"
25#include "gnunet_namecache_service.h"
26#include "gnunet_testing_lib.h"
27#include "gnunet_dnsparser_lib.h"
28
29#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
30
31#define TEST_RECORD_DATALEN 123
32
33#define TEST_RECORD_DATA 'a'
34
35#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
36
37
38static struct GNUNET_NAMECACHE_Handle *nsh;
39
40static struct GNUNET_SCHEDULER_Task *endbadly_task;
41
42static struct GNUNET_IDENTITY_PrivateKey privkey;
43
44static struct GNUNET_IDENTITY_PublicKey pubkey;
45
46static int res;
47
48static struct GNUNET_NAMECACHE_QueueEntry *nsqe;
49
50
51static void
52cleanup ()
53{
54 if (NULL != nsh)
55 {
56 GNUNET_NAMECACHE_disconnect (nsh);
57 nsh = NULL;
58 }
59 GNUNET_SCHEDULER_shutdown ();
60}
61
62
63/**
64 * Re-establish the connection to the service.
65 *
66 * @param cls handle to use to re-connect.
67 */
68static void
69endbadly (void *cls)
70{
71 if (NULL != nsqe)
72 {
73 GNUNET_NAMECACHE_cancel (nsqe);
74 nsqe = NULL;
75 }
76 cleanup ();
77 res = 1;
78}
79
80
81static void
82end (void *cls)
83{
84 cleanup ();
85 res = 0;
86}
87
88
89static void
90rd_decrypt_cb (void *cls,
91 unsigned int rd_count,
92 const struct GNUNET_GNSRECORD_Data *rd)
93{
94 char rd_cmp_data[TEST_RECORD_DATALEN];
95
96 GNUNET_assert (1 == rd_count);
97 GNUNET_assert (NULL != rd);
98
99 memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN);
100
101 GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type);
102 GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size);
103 GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN));
104
105 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
106 "Block was decrypted successfully \n");
107
108 GNUNET_SCHEDULER_add_now (&end, NULL);
109}
110
111
112static void
113name_lookup_proc (void *cls,
114 const struct GNUNET_GNSRECORD_Block *block)
115{
116 const char *name = cls;
117
118 nsqe = NULL;
119
120 GNUNET_assert (NULL != cls);
121
122 if (endbadly_task != NULL)
123 {
124 GNUNET_SCHEDULER_cancel (endbadly_task);
125 endbadly_task = NULL;
126 }
127
128 if (NULL == block)
129 {
130 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
131 _ ("Namecache returned no block\n"));
132 if (NULL != endbadly_task)
133 GNUNET_SCHEDULER_cancel (endbadly_task);
134 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
135 return;
136 }
137
138 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
139 "Namecache returned block, decrypting \n");
140 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block,
141 &pubkey, name,
142 &rd_decrypt_cb,
143 (void *) name));
144}
145
146
147static void
148cache_cont (void *cls, int32_t success, const char *emsg)
149{
150 const char *name = cls;
151 struct GNUNET_HashCode derived_hash;
152
153 GNUNET_assert (NULL != cls);
154
155 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156 "Name store cached record for `%s': %s\n",
157 name,
158 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
159
160 /* Create derived hash */
161 GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash);
162
163 nsqe = GNUNET_NAMECACHE_lookup_block (nsh, &derived_hash,
164 &name_lookup_proc, (void *) name);
165}
166
167
168static void
169run (void *cls,
170 const struct GNUNET_CONFIGURATION_Handle *cfg,
171 struct GNUNET_TESTING_Peer *peer)
172{
173 struct GNUNET_GNSRECORD_Data rd;
174 struct GNUNET_GNSRECORD_Block *block;
175 const char *name = "dummy.dummy.gnunet";
176
177 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
178 &endbadly, NULL);
179 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
180 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
181 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
182
183
184 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 10000000000;
185 rd.record_type = TEST_RECORD_TYPE;
186 rd.data_size = TEST_RECORD_DATALEN;
187 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
188 rd.flags = 0;
189 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
190 block = GNUNET_GNSRECORD_block_create (&privkey,
191 GNUNET_TIME_UNIT_FOREVER_ABS,
192 name, &rd, 1);
193 if (NULL == block)
194 {
195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
196 "Namecache cannot cache no block!\n");
197 GNUNET_SCHEDULER_shutdown ();
198 GNUNET_free (block);
199 return;
200 }
201
202 nsh = GNUNET_NAMECACHE_connect (cfg);
203 if (NULL == nsh)
204 {
205 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
206 _ ("Namecache cannot connect to namecache\n"));
207 GNUNET_SCHEDULER_shutdown ();
208 GNUNET_free (block);
209 return;
210 }
211 GNUNET_break (NULL != nsh);
212
213 nsqe = GNUNET_NAMECACHE_block_cache (nsh,
214 block,
215 &cache_cont, (void *) name);
216 if (NULL == nsqe)
217 {
218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 _ ("Namecache cannot cache no block\n"));
220 }
221 GNUNET_free (block);
222 GNUNET_free_nz ((void *) rd.data);
223}
224
225
226int
227main (int argc, char *argv[])
228{
229 GNUNET_DISK_directory_remove ("/tmp/test-gnunet-namecache/");
230 res = 1;
231 if (0 !=
232 GNUNET_TESTING_service_run ("test-namecache-api",
233 "namecache",
234 "test_namecache_api.conf",
235 &run,
236 NULL))
237 return 1;
238 return res;
239}
240
241
242/* end of test_namecache_api_cache_block.c */
diff --git a/src/namecache/test_plugin_namecache.c b/src/namecache/test_plugin_namecache.c
deleted file mode 100644
index f3cb46c02..000000000
--- a/src/namecache/test_plugin_namecache.c
+++ /dev/null
@@ -1,132 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012 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 */
20/*
21 * @file namecache/test_plugin_namecache.c
22 * @brief Test for the namecache plugins
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_namecache_plugin.h"
28#include "gnunet_testing_lib.h"
29
30
31static int ok;
32
33/**
34 * Name of plugin under test.
35 */
36static const char *plugin_name;
37
38
39/**
40 * Function called when the service shuts down. Unloads our namecache
41 * plugin.
42 *
43 * @param api api to unload
44 */
45static void
46unload_plugin (struct GNUNET_NAMECACHE_PluginFunctions *api)
47{
48 char *libname;
49
50 GNUNET_asprintf (&libname, "libgnunet_plugin_namecache_%s", plugin_name);
51 GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api));
52 GNUNET_free (libname);
53}
54
55
56/**
57 * Load the namecache plugin.
58 *
59 * @param cfg configuration to pass
60 * @return NULL on error
61 */
62static struct GNUNET_NAMECACHE_PluginFunctions *
63load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg)
64{
65 struct GNUNET_NAMECACHE_PluginFunctions *ret;
66 char *libname;
67
68 GNUNET_log (GNUNET_ERROR_TYPE_INFO, _ ("Loading `%s' namecache plugin\n"),
69 plugin_name);
70 GNUNET_asprintf (&libname, "libgnunet_plugin_namecache_%s", plugin_name);
71 if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void *) cfg)))
72 {
73 fprintf (stderr, "Failed to load plugin `%s'!\n", plugin_name);
74 GNUNET_free (libname);
75 return NULL;
76 }
77 GNUNET_free (libname);
78 return ret;
79}
80
81
82static void
83run (void *cls, char *const *args, const char *cfgfile,
84 const struct GNUNET_CONFIGURATION_Handle *cfg)
85{
86 struct GNUNET_NAMECACHE_PluginFunctions *nsp;
87
88 ok = 0;
89 nsp = load_plugin (cfg);
90 if (NULL == nsp)
91 {
92 fprintf (stderr,
93 "%s",
94 "Failed to initialize namecache. Database likely not setup, skipping test.\n");
95 return;
96 }
97
98 unload_plugin (nsp);
99}
100
101
102int
103main (int argc, char *argv[])
104{
105 char cfg_name[PATH_MAX];
106 char *const xargv[] = {
107 "test-plugin-namecache",
108 "-c",
109 cfg_name,
110 NULL
111 };
112 struct GNUNET_GETOPT_CommandLineOption options[] = {
113 GNUNET_GETOPT_OPTION_END
114 };
115
116 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namecache-sqlite");
117 GNUNET_log_setup ("test-plugin-namecache",
118 "WARNING",
119 NULL);
120 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
121 GNUNET_snprintf (cfg_name, sizeof(cfg_name), "test_plugin_namecache_%s.conf",
122 plugin_name);
123 GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1, xargv,
124 "test-plugin-namecache", "nohelp", options, &run, NULL);
125 if (ok != 0)
126 fprintf (stderr, "Missed some testcases: %d\n", ok);
127 GNUNET_DISK_directory_remove ("/tmp/gnunet-test-plugin-namecache-sqlite");
128 return ok;
129}
130
131
132/* end of test_plugin_namecache.c */
diff --git a/src/namecache/test_plugin_namecache_flat.conf b/src/namecache/test_plugin_namecache_flat.conf
deleted file mode 100644
index efe77e37a..000000000
--- a/src/namecache/test_plugin_namecache_flat.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[namecache-flat]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namecache-flat/flatdb
diff --git a/src/namecache/test_plugin_namecache_postgres.conf b/src/namecache/test_plugin_namecache_postgres.conf
deleted file mode 100644
index 8473857d5..000000000
--- a/src/namecache/test_plugin_namecache_postgres.conf
+++ /dev/null
@@ -1,3 +0,0 @@
1[namestore-postgres]
2CONFIG = connect_timeout=10; dbname=gnunetcheck
3TEMPORARY_TABLE = YES
diff --git a/src/namecache/test_plugin_namecache_sqlite.conf b/src/namecache/test_plugin_namecache_sqlite.conf
deleted file mode 100644
index 24eecd286..000000000
--- a/src/namecache/test_plugin_namecache_sqlite.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[namestore-sqlite]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db