aboutsummaryrefslogtreecommitdiff
path: root/src/namestore
diff options
context:
space:
mode:
Diffstat (limited to 'src/namestore')
-rw-r--r--src/namestore/.gitignore88
-rw-r--r--src/namestore/Makefile.am749
-rw-r--r--src/namestore/gnunet-namestore-fcfsd.c1167
-rw-r--r--src/namestore/gnunet-namestore.c1660
-rw-r--r--src/namestore/gnunet-service-namestore.c2401
-rw-r--r--src/namestore/gnunet-zoneimport.c1884
-rw-r--r--src/namestore/namestore.conf.in50
-rw-r--r--src/namestore/namestore.h408
-rw-r--r--src/namestore/namestore_api.c1387
-rw-r--r--src/namestore/namestore_api_monitor.c388
-rw-r--r--src/namestore/perf_namestore_api_flat.conf10
-rw-r--r--src/namestore/perf_namestore_api_postgres.conf11
-rw-r--r--src/namestore/perf_namestore_api_sqlite.conf7
-rw-r--r--src/namestore/perf_namestore_api_zone_iteration.c379
-rw-r--r--src/namestore/plugin_namestore_flat.c818
-rw-r--r--src/namestore/plugin_namestore_postgres.c626
-rw-r--r--src/namestore/plugin_namestore_sqlite.c801
-rw-r--r--src/namestore/plugin_rest_namestore.c1153
-rw-r--r--src/namestore/test_common.c80
-rw-r--r--src/namestore/test_hostkey0
-rw-r--r--src/namestore/test_namestore_api.conf22
-rw-r--r--src/namestore/test_namestore_api_flat.conf7
-rw-r--r--src/namestore/test_namestore_api_lookup_nick.c347
-rw-r--r--src/namestore/test_namestore_api_lookup_private.c246
-rw-r--r--src/namestore/test_namestore_api_lookup_public.c255
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow.c288
-rw-r--r--src/namestore/test_namestore_api_lookup_shadow_filter.c371
-rw-r--r--src/namestore/test_namestore_api_monitoring.c379
-rw-r--r--src/namestore/test_namestore_api_monitoring_existing.c397
-rw-r--r--src/namestore/test_namestore_api_postgres.conf9
-rw-r--r--src/namestore/test_namestore_api_remove.c221
-rw-r--r--src/namestore/test_namestore_api_remove_not_existing_record.c180
-rw-r--r--src/namestore/test_namestore_api_sqlite.conf8
-rw-r--r--src/namestore/test_namestore_api_store.c172
-rw-r--r--src/namestore/test_namestore_api_store_update.c309
-rw-r--r--src/namestore/test_namestore_api_zone_iteration.c465
-rw-r--r--src/namestore/test_namestore_api_zone_iteration_nick.c462
-rw-r--r--src/namestore/test_namestore_api_zone_iteration_specific_zone.c448
-rw-r--r--src/namestore/test_namestore_api_zone_iteration_stop.c449
-rw-r--r--src/namestore/test_namestore_api_zone_to_name.c266
-rwxr-xr-xsrc/namestore/test_namestore_delete.sh68
-rwxr-xr-xsrc/namestore/test_namestore_lookup.sh63
-rwxr-xr-xsrc/namestore/test_namestore_put.sh55
-rw-r--r--src/namestore/test_namestore_put_multiple.sh123
-rw-r--r--src/namestore/test_plugin_namestore.c205
-rw-r--r--src/namestore/test_plugin_namestore_flat.conf2
-rw-r--r--src/namestore/test_plugin_namestore_postgres.conf3
-rw-r--r--src/namestore/test_plugin_namestore_sqlite.conf2
-rwxr-xr-xsrc/namestore/test_plugin_rest_namestore.sh135
49 files changed, 0 insertions, 20024 deletions
diff --git a/src/namestore/.gitignore b/src/namestore/.gitignore
deleted file mode 100644
index f159cdaff..000000000
--- a/src/namestore/.gitignore
+++ /dev/null
@@ -1,88 +0,0 @@
1gnunet-service-namestore
2gnunet-namestore
3gnunet-namestore-fcfsd
4test_namestore_api_lookup_nick.nc
5test_namestore_api_lookup_private.nc
6test_namestore_api_lookup_public.nc
7test_namestore_api_lookup_shadow.nc
8test_namestore_api_lookup_shadow_filter.nc
9test_namestore_api_monitoring.nc
10test_namestore_api_monitoring_existing.nc
11test_namestore_api_remove.nc
12test_namestore_api_remove_not_existing_record.nc
13test_namestore_api_store.nc
14test_namestore_api_store_update.nc
15test_namestore_api_zone_iteration.nc
16test_namestore_api_zone_iteration_nick.nc
17test_namestore_api_zone_iteration_specific_zone.nc
18test_namestore_api_zone_iteration_stop.nc
19test_plugin_namestore_postgres
20test_plugin_namestore_sqlite
21test_plugin_namestore_flat
22gnunet-zoneimport
23test_namestore_api_lookup_nick_flat
24test_namestore_api_lookup_nick_postgres
25test_namestore_api_lookup_nick_sqlite
26test_namestore_api_lookup_private_flat
27test_namestore_api_lookup_private_postgres
28test_namestore_api_lookup_private_sqlite
29test_namestore_api_lookup_public_flat
30test_namestore_api_lookup_public_postgres
31test_namestore_api_lookup_public_sqlite
32test_namestore_api_lookup_shadow_filter_flat
33test_namestore_api_lookup_shadow_filter_postgres
34test_namestore_api_lookup_shadow_filter_sqlite
35test_namestore_api_lookup_shadow_flat
36test_namestore_api_lookup_shadow_postgres
37test_namestore_api_lookup_shadow_sqlite
38test_namestore_api_monitoring_existing_flat
39test_namestore_api_monitoring_existing_postgres
40test_namestore_api_monitoring_existing_sqlite
41test_namestore_api_monitoring_flat
42test_namestore_api_monitoring_postgres
43test_namestore_api_monitoring_sqlite
44test_namestore_api_remove_flat
45test_namestore_api_remove_not_existing_record_flat
46test_namestore_api_remove_not_existing_record_postgres
47test_namestore_api_remove_not_existing_record_sqlite
48test_namestore_api_remove_postgres
49test_namestore_api_remove_sqlite
50test_namestore_api_store_flat
51test_namestore_api_store_postgres
52test_namestore_api_store_sqlite
53test_namestore_api_store_update_flat
54test_namestore_api_store_update_postgres
55test_namestore_api_store_update_sqlite
56test_namestore_api_zone_iteration_flat
57test_namestore_api_zone_iteration_nick_flat
58test_namestore_api_zone_iteration_nick_postgres
59test_namestore_api_zone_iteration_nick_sqlite
60test_namestore_api_zone_iteration_postgres
61test_namestore_api_zone_iteration_specific_zone_flat
62test_namestore_api_zone_iteration_specific_zone_postgres
63test_namestore_api_zone_iteration_specific_zone_sqlite
64test_namestore_api_zone_iteration_sqlite
65test_namestore_api_zone_iteration_stop_flat
66test_namestore_api_zone_iteration_stop_postgres
67test_namestore_api_zone_iteration_stop_sqlite
68test_namestore_api_zone_to_name_flat
69test_namestore_api_zone_to_name_postgres
70test_namestore_api_zone_to_name_sqlite
71test_namestore_api_lookup_nick_flat
72test_namestore_api_lookup_private_flat
73test_namestore_api_lookup_public_flat
74test_namestore_api_lookup_shadow_filter_flat
75test_namestore_api_lookup_shadow_flat
76test_namestore_api_monitoring_existing_flat
77test_namestore_api_monitoring_flat
78test_namestore_api_remove_flat
79test_namestore_api_remove_not_existing_record_flat
80test_namestore_api_store_flat
81test_namestore_api_store_update_flat
82test_namestore_api_zone_iteration_flat
83test_namestore_api_zone_iteration_nick_flat
84test_namestore_api_zone_iteration_specific_zone_flat
85test_namestore_api_zone_iteration_stop_flat
86test_namestore_api_zone_to_name_flat
87test_plugin_namestore_flat
88perf_namestore_api_zone_iteration_flat
diff --git a/src/namestore/Makefile.am b/src/namestore/Makefile.am
deleted file mode 100644
index 51708dd67..000000000
--- a/src/namestore/Makefile.am
+++ /dev/null
@@ -1,749 +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 namestore.conf
12
13if USE_COVERAGE
14 AM_CFLAGS = --coverage -O0
15 XLIBS = -lgcov
16endif
17
18HEAP_PLUGIN = libgnunet_plugin_namestore_flat.la
19HEAP_TESTS = test_plugin_namestore_flat \
20 test_namestore_api_store_flat \
21 test_namestore_api_store_update_flat \
22 test_namestore_api_remove_flat \
23 test_namestore_api_zone_iteration_flat \
24 test_namestore_api_lookup_nick_flat \
25 test_namestore_api_monitoring_flat \
26 test_namestore_api_lookup_public_flat \
27 test_namestore_api_lookup_private_flat \
28 test_namestore_api_lookup_shadow_flat \
29 test_namestore_api_lookup_shadow_filter_flat \
30 test_namestore_api_remove_not_existing_record_flat \
31 test_namestore_api_zone_iteration_nick_flat \
32 test_namestore_api_zone_iteration_specific_zone_flat \
33 test_namestore_api_zone_iteration_stop_flat \
34 test_namestore_api_monitoring_existing_flat \
35 test_namestore_api_zone_to_name_flat \
36 perf_namestore_api_zone_iteration_flat
37
38if HAVE_SQLITE
39SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
40SQLITE_TESTS = test_plugin_namestore_sqlite \
41 test_namestore_api_store_sqlite \
42 test_namestore_api_store_update_sqlite \
43 test_namestore_api_zone_iteration_sqlite \
44 test_namestore_api_remove_sqlite \
45 test_namestore_api_lookup_nick_sqlite \
46 test_namestore_api_monitoring_sqlite \
47 test_namestore_api_lookup_public_sqlite \
48 test_namestore_api_lookup_private_sqlite \
49 test_namestore_api_lookup_shadow_sqlite \
50 test_namestore_api_lookup_shadow_filter_sqlite \
51 test_namestore_api_remove_not_existing_record_sqlite \
52 test_namestore_api_zone_iteration_nick_sqlite \
53 test_namestore_api_zone_iteration_specific_zone_sqlite \
54 test_namestore_api_zone_iteration_stop_sqlite \
55 test_namestore_api_monitoring_existing_sqlite \
56 test_namestore_api_zone_to_name_sqlite \
57 perf_namestore_api_zone_iteration_sqlite
58endif
59
60if HAVE_POSTGRESQL
61POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la
62POSTGRES_TESTS = test_plugin_namestore_postgres \
63 test_namestore_api_store_postgres \
64 test_namestore_api_store_update_postgres \
65 test_namestore_api_remove_postgres \
66 test_namestore_api_zone_iteration_postgres \
67 test_namestore_api_lookup_nick_postgres \
68 test_namestore_api_monitoring_postgres \
69 test_namestore_api_lookup_public_postgres \
70 test_namestore_api_lookup_private_postgres \
71 test_namestore_api_lookup_shadow_postgres \
72 test_namestore_api_lookup_shadow_filter_postgres \
73 test_namestore_api_remove_not_existing_record_postgres \
74 test_namestore_api_zone_iteration_nick_postgres \
75 test_namestore_api_zone_iteration_specific_zone_postgres \
76 test_namestore_api_zone_iteration_stop_postgres \
77 test_namestore_api_monitoring_existing_postgres \
78 test_namestore_api_zone_to_name_postgres \
79 perf_namestore_api_zone_iteration_postgres
80endif
81
82if HAVE_SQLITE
83check_PROGRAMS = \
84 $(SQLITE_TESTS) \
85 $(POSTGRES_TESTS) \
86 $(HEAP_TESTS)
87endif
88
89if ENABLE_TEST_RUN
90AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
91TESTS = \
92 $(check_PROGRAMS) \
93 $(check_SCRIPTS)
94endif
95
96REST_PLUGIN = libgnunet_plugin_rest_namestore.la
97
98lib_LTLIBRARIES = \
99 libgnunetnamestore.la
100
101
102libexec_PROGRAMS = \
103 gnunet-service-namestore
104
105bin_PROGRAMS = \
106 gnunet-namestore \
107 gnunet-zoneimport
108
109libexec_PROGRAMS += \
110 gnunet-namestore-fcfsd
111
112
113plugin_LTLIBRARIES = \
114 $(SQLITE_PLUGIN) \
115 $(POSTGRES_PLUGIN) \
116 $(HEAP_PLUGIN) \
117 $(REST_PLUGIN)
118
119
120libgnunet_plugin_rest_namestore_la_SOURCES = \
121 plugin_rest_namestore.c
122libgnunet_plugin_rest_namestore_la_LIBADD = \
123 libgnunetnamestore.la \
124 $(top_builddir)/src/rest/libgnunetrest.la \
125 $(top_builddir)/src/identity/libgnunetidentity.la \
126 $(top_builddir)/src/json/libgnunetjson.la \
127 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
128 $(top_builddir)/src/gnsrecord/libgnunetgnsrecordjson.la \
129 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
130 $(LTLIBINTL) -ljansson $(MHD_LIBS)
131libgnunet_plugin_rest_namestore_la_LDFLAGS = \
132 $(GN_PLUGIN_LDFLAGS)
133libgnunet_plugin_rest_namestore_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
134
135
136libgnunetnamestore_la_SOURCES = \
137 namestore_api.c \
138 namestore_api_monitor.c \
139 namestore.h
140libgnunetnamestore_la_LIBADD = \
141 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
142 $(top_builddir)/src/identity/libgnunetidentity.la \
143 $(top_builddir)/src/statistics/libgnunetstatistics.la \
144 $(top_builddir)/src/util/libgnunetutil.la \
145 $(GN_LIBINTL)
146libgnunetnamestore_la_LDFLAGS = \
147 $(GN_LIB_LDFLAGS) \
148 -version-info 0:1:0
149
150
151
152gnunet_zoneimport_SOURCES = \
153 gnunet-zoneimport.c
154gnunet_zoneimport_LDADD = \
155 libgnunetnamestore.la \
156 $(top_builddir)/src/statistics/libgnunetstatistics.la \
157 $(top_builddir)/src/identity/libgnunetidentity.la \
158 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
159 $(top_builddir)/src/util/libgnunetutil.la \
160 $(GN_LIBINTL)
161
162gnunet_namestore_SOURCES = \
163 gnunet-namestore.c
164gnunet_namestore_LDADD = \
165 $(top_builddir)/src/identity/libgnunetidentity.la \
166 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
167 $(top_builddir)/src/util/libgnunetutil.la \
168 libgnunetnamestore.la \
169 $(GN_LIBINTL)
170
171
172gnunet_namestore_fcfsd_SOURCES = \
173 gnunet-namestore-fcfsd.c
174gnunet_namestore_fcfsd_LDADD = $(MHD_LIBS) \
175 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
176 $(top_builddir)/src/identity/libgnunetidentity.la \
177 libgnunetnamestore.la \
178 $(top_builddir)/src/util/libgnunetutil.la \
179 $(top_builddir)/src/json/libgnunetjson.la \
180 $(GN_LIBINTL) -ljansson
181gnunet_namestore_fcfsd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
182
183
184gnunet_service_namestore_SOURCES = \
185 gnunet-service-namestore.c
186
187gnunet_service_namestore_LDADD = \
188 $(top_builddir)/src/namecache/libgnunetnamecache.la \
189 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
190 $(top_builddir)/src/identity/libgnunetidentity.la \
191 $(top_builddir)/src/statistics/libgnunetstatistics.la \
192 $(top_builddir)/src/util/libgnunetutil.la \
193 libgnunetnamestore.la \
194 $(GN_LIBINTL)
195
196
197
198libgnunet_plugin_namestore_flat_la_SOURCES = \
199 plugin_namestore_flat.c
200libgnunet_plugin_namestore_flat_la_LIBADD = \
201 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
202 $(top_builddir)/src/identity/libgnunetidentity.la \
203 $(top_builddir)/src/statistics/libgnunetstatistics.la \
204 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
205 $(LTLIBINTL)
206libgnunet_plugin_namestore_flat_la_LDFLAGS = \
207 $(GN_PLUGIN_LDFLAGS)
208
209
210libgnunet_plugin_namestore_sqlite_la_SOURCES = \
211 plugin_namestore_sqlite.c
212libgnunet_plugin_namestore_sqlite_la_LIBADD = \
213 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
214 $(top_builddir)/src/identity/libgnunetidentity.la \
215 $(top_builddir)/src/sq/libgnunetsq.la \
216 $(top_builddir)/src/statistics/libgnunetstatistics.la \
217 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
218 $(LTLIBINTL)
219libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \
220 $(GN_PLUGIN_LDFLAGS)
221
222libgnunet_plugin_namestore_postgres_la_SOURCES = \
223 plugin_namestore_postgres.c
224libgnunet_plugin_namestore_postgres_la_LIBADD = \
225 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
226 $(top_builddir)/src/identity/libgnunetidentity.la \
227 $(top_builddir)/src/pq/libgnunetpq.la \
228 $(top_builddir)/src/statistics/libgnunetstatistics.la \
229 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \
230 $(LTLIBINTL)
231libgnunet_plugin_namestore_postgres_la_LDFLAGS = \
232 $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
233
234test_namestore_api_store_flat_SOURCES = \
235 test_namestore_api_store.c
236test_namestore_api_store_flat_LDADD = \
237 $(top_builddir)/src/testing/libgnunettesting.la \
238 $(top_builddir)/src/util/libgnunetutil.la \
239 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
240 $(top_builddir)/src/identity/libgnunetidentity.la \
241 libgnunetnamestore.la
242
243test_namestore_api_store_sqlite_SOURCES = \
244 test_namestore_api_store.c
245test_namestore_api_store_sqlite_LDADD = \
246 $(top_builddir)/src/testing/libgnunettesting.la \
247 $(top_builddir)/src/util/libgnunetutil.la \
248 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
249 $(top_builddir)/src/identity/libgnunetidentity.la \
250 libgnunetnamestore.la
251
252test_namestore_api_store_postgres_SOURCES = \
253 test_namestore_api_store.c
254test_namestore_api_store_postgres_LDADD = \
255 $(top_builddir)/src/testing/libgnunettesting.la \
256 $(top_builddir)/src/util/libgnunetutil.la \
257 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
258 $(top_builddir)/src/identity/libgnunetidentity.la \
259 libgnunetnamestore.la
260
261test_namestore_api_store_update_flat_SOURCES = \
262 test_namestore_api_store_update.c
263test_namestore_api_store_update_flat_LDADD = \
264 $(top_builddir)/src/testing/libgnunettesting.la \
265 $(top_builddir)/src/util/libgnunetutil.la \
266 $(top_builddir)/src/identity/libgnunetidentity.la \
267 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
268 $(top_builddir)/src/namecache/libgnunetnamecache.la \
269 libgnunetnamestore.la
270
271test_namestore_api_store_update_sqlite_SOURCES = \
272 test_namestore_api_store_update.c
273test_namestore_api_store_update_sqlite_LDADD = \
274 $(top_builddir)/src/testing/libgnunettesting.la \
275 $(top_builddir)/src/util/libgnunetutil.la \
276 $(top_builddir)/src/identity/libgnunetidentity.la \
277 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
278 $(top_builddir)/src/namecache/libgnunetnamecache.la \
279 libgnunetnamestore.la
280
281test_namestore_api_store_update_postgres_SOURCES = \
282 test_namestore_api_store_update.c
283test_namestore_api_store_update_postgres_LDADD = \
284 $(top_builddir)/src/testing/libgnunettesting.la \
285 $(top_builddir)/src/util/libgnunetutil.la \
286 $(top_builddir)/src/identity/libgnunetidentity.la \
287 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
288 $(top_builddir)/src/namecache/libgnunetnamecache.la \
289 libgnunetnamestore.la
290
291test_namestore_api_lookup_public_flat_SOURCES = \
292 test_namestore_api_lookup_public.c
293test_namestore_api_lookup_public_flat_LDADD = \
294 $(top_builddir)/src/testing/libgnunettesting.la \
295 $(top_builddir)/src/identity/libgnunetidentity.la \
296 $(top_builddir)/src/util/libgnunetutil.la \
297 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
298 $(top_builddir)/src/namecache/libgnunetnamecache.la \
299 libgnunetnamestore.la
300
301test_namestore_api_lookup_public_sqlite_SOURCES = \
302 test_namestore_api_lookup_public.c
303test_namestore_api_lookup_public_sqlite_LDADD = \
304 $(top_builddir)/src/testing/libgnunettesting.la \
305 $(top_builddir)/src/util/libgnunetutil.la \
306 $(top_builddir)/src/identity/libgnunetidentity.la \
307 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
308 $(top_builddir)/src/namecache/libgnunetnamecache.la \
309 libgnunetnamestore.la
310
311test_namestore_api_lookup_public_postgres_SOURCES = \
312 test_namestore_api_lookup_public.c
313test_namestore_api_lookup_public_postgres_LDADD = \
314 $(top_builddir)/src/testing/libgnunettesting.la \
315 $(top_builddir)/src/util/libgnunetutil.la \
316 $(top_builddir)/src/identity/libgnunetidentity.la \
317 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
318 $(top_builddir)/src/namecache/libgnunetnamecache.la \
319 libgnunetnamestore.la
320
321test_namestore_api_lookup_nick_sqlite_SOURCES = \
322 test_namestore_api_lookup_nick.c
323test_namestore_api_lookup_nick_sqlite_LDADD = \
324 $(top_builddir)/src/testing/libgnunettesting.la \
325 $(top_builddir)/src/util/libgnunetutil.la \
326 $(top_builddir)/src/identity/libgnunetidentity.la \
327 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
328 $(top_builddir)/src/namecache/libgnunetnamecache.la \
329 libgnunetnamestore.la
330
331test_namestore_api_lookup_nick_postgres_SOURCES = \
332 test_namestore_api_lookup_nick.c
333test_namestore_api_lookup_nick_postgres_LDADD = \
334 $(top_builddir)/src/testing/libgnunettesting.la \
335 $(top_builddir)/src/util/libgnunetutil.la \
336 $(top_builddir)/src/identity/libgnunetidentity.la \
337 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
338 $(top_builddir)/src/namecache/libgnunetnamecache.la \
339 libgnunetnamestore.la
340
341test_namestore_api_lookup_nick_flat_SOURCES = \
342 test_namestore_api_lookup_nick.c
343test_namestore_api_lookup_nick_flat_LDADD = \
344 $(top_builddir)/src/testing/libgnunettesting.la \
345 $(top_builddir)/src/identity/libgnunetidentity.la \
346 $(top_builddir)/src/util/libgnunetutil.la \
347 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
348 $(top_builddir)/src/namecache/libgnunetnamecache.la \
349 libgnunetnamestore.la
350
351test_namestore_api_lookup_private_flat_SOURCES = \
352 test_namestore_api_lookup_private.c
353test_namestore_api_lookup_private_flat_LDADD = \
354 $(top_builddir)/src/testing/libgnunettesting.la \
355 $(top_builddir)/src/identity/libgnunetidentity.la \
356 $(top_builddir)/src/util/libgnunetutil.la \
357 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
358 $(top_builddir)/src/namecache/libgnunetnamecache.la \
359 libgnunetnamestore.la
360
361test_namestore_api_lookup_private_sqlite_SOURCES = \
362 test_namestore_api_lookup_private.c
363test_namestore_api_lookup_private_sqlite_LDADD = \
364 $(top_builddir)/src/testing/libgnunettesting.la \
365 $(top_builddir)/src/identity/libgnunetidentity.la \
366 $(top_builddir)/src/util/libgnunetutil.la \
367 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
368 $(top_builddir)/src/namecache/libgnunetnamecache.la \
369 libgnunetnamestore.la
370
371test_namestore_api_lookup_private_postgres_SOURCES = \
372 test_namestore_api_lookup_private.c
373test_namestore_api_lookup_private_postgres_LDADD = \
374 $(top_builddir)/src/identity/libgnunetidentity.la \
375 $(top_builddir)/src/testing/libgnunettesting.la \
376 $(top_builddir)/src/util/libgnunetutil.la \
377 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
378 $(top_builddir)/src/namecache/libgnunetnamecache.la \
379 libgnunetnamestore.la
380
381test_namestore_api_lookup_shadow_flat_SOURCES = \
382 test_namestore_api_lookup_shadow.c
383test_namestore_api_lookup_shadow_flat_LDADD = \
384 $(top_builddir)/src/testing/libgnunettesting.la \
385 $(top_builddir)/src/identity/libgnunetidentity.la \
386 $(top_builddir)/src/util/libgnunetutil.la \
387 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
388 $(top_builddir)/src/namecache/libgnunetnamecache.la \
389 libgnunetnamestore.la
390
391test_namestore_api_lookup_shadow_sqlite_SOURCES = \
392 test_namestore_api_lookup_shadow.c
393test_namestore_api_lookup_shadow_sqlite_LDADD = \
394 $(top_builddir)/src/testing/libgnunettesting.la \
395 $(top_builddir)/src/util/libgnunetutil.la \
396 $(top_builddir)/src/identity/libgnunetidentity.la \
397 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
398 $(top_builddir)/src/namecache/libgnunetnamecache.la \
399 libgnunetnamestore.la
400
401test_namestore_api_lookup_shadow_postgres_SOURCES = \
402 test_namestore_api_lookup_shadow.c
403test_namestore_api_lookup_shadow_postgres_LDADD = \
404 $(top_builddir)/src/testing/libgnunettesting.la \
405 $(top_builddir)/src/util/libgnunetutil.la \
406 $(top_builddir)/src/identity/libgnunetidentity.la \
407 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
408 $(top_builddir)/src/namecache/libgnunetnamecache.la \
409 libgnunetnamestore.la
410
411test_namestore_api_lookup_shadow_filter_flat_SOURCES = \
412 test_namestore_api_lookup_shadow_filter.c
413test_namestore_api_lookup_shadow_filter_flat_LDADD = \
414 $(top_builddir)/src/testing/libgnunettesting.la \
415 $(top_builddir)/src/util/libgnunetutil.la \
416 $(top_builddir)/src/identity/libgnunetidentity.la \
417 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
418 $(top_builddir)/src/namecache/libgnunetnamecache.la \
419 libgnunetnamestore.la
420
421test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \
422 test_namestore_api_lookup_shadow_filter.c
423test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \
424 $(top_builddir)/src/testing/libgnunettesting.la \
425 $(top_builddir)/src/identity/libgnunetidentity.la \
426 $(top_builddir)/src/util/libgnunetutil.la \
427 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
428 $(top_builddir)/src/namecache/libgnunetnamecache.la \
429 libgnunetnamestore.la
430test_namestore_api_lookup_shadow_filter_postgres_SOURCES = \
431 test_namestore_api_lookup_shadow_filter.c
432test_namestore_api_lookup_shadow_filter_postgres_LDADD = \
433 $(top_builddir)/src/testing/libgnunettesting.la \
434 $(top_builddir)/src/identity/libgnunetidentity.la \
435 $(top_builddir)/src/util/libgnunetutil.la \
436 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
437 $(top_builddir)/src/namecache/libgnunetnamecache.la \
438 libgnunetnamestore.la
439
440test_namestore_api_remove_sqlite_SOURCES = \
441 test_namestore_api_remove.c
442test_namestore_api_remove_sqlite_LDADD = \
443 $(top_builddir)/src/identity/libgnunetidentity.la \
444 $(top_builddir)/src/testing/libgnunettesting.la \
445 $(top_builddir)/src/util/libgnunetutil.la \
446 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
447 libgnunetnamestore.la
448
449test_namestore_api_remove_postgres_SOURCES = \
450 test_namestore_api_remove.c
451test_namestore_api_remove_postgres_LDADD = \
452 $(top_builddir)/src/identity/libgnunetidentity.la \
453 $(top_builddir)/src/testing/libgnunettesting.la \
454 $(top_builddir)/src/util/libgnunetutil.la \
455 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
456 libgnunetnamestore.la
457
458test_namestore_api_remove_flat_SOURCES = \
459 test_namestore_api_remove.c
460test_namestore_api_remove_flat_LDADD = \
461 $(top_builddir)/src/testing/libgnunettesting.la \
462 $(top_builddir)/src/identity/libgnunetidentity.la \
463 $(top_builddir)/src/util/libgnunetutil.la \
464 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
465 libgnunetnamestore.la
466
467test_namestore_api_remove_not_existing_record_flat_SOURCES = \
468 test_namestore_api_remove_not_existing_record.c
469test_namestore_api_remove_not_existing_record_flat_LDADD = \
470 $(top_builddir)/src/testing/libgnunettesting.la \
471 $(top_builddir)/src/identity/libgnunetidentity.la \
472 $(top_builddir)/src/util/libgnunetutil.la \
473 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
474 libgnunetnamestore.la
475
476test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \
477 test_namestore_api_remove_not_existing_record.c
478test_namestore_api_remove_not_existing_record_sqlite_LDADD = \
479 $(top_builddir)/src/testing/libgnunettesting.la \
480 $(top_builddir)/src/util/libgnunetutil.la \
481 $(top_builddir)/src/identity/libgnunetidentity.la \
482 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
483 libgnunetnamestore.la
484
485test_namestore_api_remove_not_existing_record_postgres_SOURCES = \
486 test_namestore_api_remove_not_existing_record.c
487test_namestore_api_remove_not_existing_record_postgres_LDADD = \
488 $(top_builddir)/src/testing/libgnunettesting.la \
489 $(top_builddir)/src/identity/libgnunetidentity.la \
490 $(top_builddir)/src/util/libgnunetutil.la \
491 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
492 libgnunetnamestore.la
493
494test_namestore_api_zone_to_name_flat_SOURCES = \
495 test_namestore_api_zone_to_name.c
496test_namestore_api_zone_to_name_flat_LDADD = \
497 $(top_builddir)/src/identity/libgnunetidentity.la \
498 $(top_builddir)/src/testing/libgnunettesting.la \
499 $(top_builddir)/src/util/libgnunetutil.la \
500 libgnunetnamestore.la
501
502test_namestore_api_zone_to_name_sqlite_SOURCES = \
503 test_namestore_api_zone_to_name.c
504test_namestore_api_zone_to_name_sqlite_LDADD = \
505 $(top_builddir)/src/identity/libgnunetidentity.la \
506 $(top_builddir)/src/testing/libgnunettesting.la \
507 $(top_builddir)/src/util/libgnunetutil.la \
508 libgnunetnamestore.la
509
510test_namestore_api_zone_to_name_postgres_SOURCES = \
511 test_namestore_api_zone_to_name.c
512test_namestore_api_zone_to_name_postgres_LDADD = \
513 $(top_builddir)/src/identity/libgnunetidentity.la \
514 $(top_builddir)/src/testing/libgnunettesting.la \
515 $(top_builddir)/src/util/libgnunetutil.la \
516 libgnunetnamestore.la
517
518test_namestore_api_monitoring_flat_SOURCES = \
519 test_namestore_api_monitoring.c
520test_namestore_api_monitoring_flat_LDADD = \
521 $(top_builddir)/src/testing/libgnunettesting.la \
522 libgnunetnamestore.la \
523 $(top_builddir)/src/identity/libgnunetidentity.la \
524 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
525 $(top_builddir)/src/util/libgnunetutil.la
526
527test_namestore_api_monitoring_sqlite_SOURCES = \
528 test_namestore_api_monitoring.c
529test_namestore_api_monitoring_sqlite_LDADD = \
530 $(top_builddir)/src/identity/libgnunetidentity.la \
531 $(top_builddir)/src/testing/libgnunettesting.la \
532 libgnunetnamestore.la \
533 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
534 $(top_builddir)/src/util/libgnunetutil.la
535
536test_namestore_api_monitoring_postgres_SOURCES = \
537 test_namestore_api_monitoring.c
538test_namestore_api_monitoring_postgres_LDADD = \
539 $(top_builddir)/src/testing/libgnunettesting.la \
540 $(top_builddir)/src/identity/libgnunetidentity.la \
541 libgnunetnamestore.la \
542 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
543 $(top_builddir)/src/util/libgnunetutil.la
544
545test_namestore_api_monitoring_existing_flat_SOURCES = \
546 test_namestore_api_monitoring_existing.c
547test_namestore_api_monitoring_existing_flat_LDADD = \
548 $(top_builddir)/src/testing/libgnunettesting.la \
549 $(top_builddir)/src/identity/libgnunetidentity.la \
550 libgnunetnamestore.la \
551 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
552 $(top_builddir)/src/util/libgnunetutil.la
553
554test_namestore_api_monitoring_existing_sqlite_SOURCES = \
555 test_namestore_api_monitoring_existing.c
556test_namestore_api_monitoring_existing_sqlite_LDADD = \
557 $(top_builddir)/src/testing/libgnunettesting.la \
558 $(top_builddir)/src/identity/libgnunetidentity.la \
559 libgnunetnamestore.la \
560 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
561 $(top_builddir)/src/util/libgnunetutil.la
562
563test_namestore_api_monitoring_existing_postgres_SOURCES = \
564 test_namestore_api_monitoring_existing.c
565test_namestore_api_monitoring_existing_postgres_LDADD = \
566 $(top_builddir)/src/testing/libgnunettesting.la \
567 libgnunetnamestore.la \
568 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
569 $(top_builddir)/src/identity/libgnunetidentity.la \
570 $(top_builddir)/src/util/libgnunetutil.la
571
572test_namestore_api_zone_iteration_flat_SOURCES = \
573 test_namestore_api_zone_iteration.c
574test_namestore_api_zone_iteration_flat_LDADD = \
575 $(top_builddir)/src/testing/libgnunettesting.la \
576 $(top_builddir)/src/identity/libgnunetidentity.la \
577 $(top_builddir)/src/util/libgnunetutil.la \
578 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
579 libgnunetnamestore.la
580
581test_namestore_api_zone_iteration_sqlite_SOURCES = \
582 test_namestore_api_zone_iteration.c
583test_namestore_api_zone_iteration_sqlite_LDADD = \
584 $(top_builddir)/src/testing/libgnunettesting.la \
585 $(top_builddir)/src/identity/libgnunetidentity.la \
586 $(top_builddir)/src/util/libgnunetutil.la \
587 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
588 libgnunetnamestore.la
589
590test_namestore_api_zone_iteration_postgres_SOURCES = \
591 test_namestore_api_zone_iteration.c
592test_namestore_api_zone_iteration_postgres_LDADD = \
593 $(top_builddir)/src/testing/libgnunettesting.la \
594 $(top_builddir)/src/identity/libgnunetidentity.la \
595 $(top_builddir)/src/util/libgnunetutil.la \
596 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
597 libgnunetnamestore.la
598
599perf_namestore_api_zone_iteration_postgres_SOURCES = \
600 perf_namestore_api_zone_iteration.c
601perf_namestore_api_zone_iteration_postgres_LDADD = \
602 $(top_builddir)/src/testing/libgnunettesting.la \
603 $(top_builddir)/src/util/libgnunetutil.la \
604 $(top_builddir)/src/identity/libgnunetidentity.la \
605 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
606 libgnunetnamestore.la
607
608perf_namestore_api_zone_iteration_sqlite_SOURCES = \
609 perf_namestore_api_zone_iteration.c
610perf_namestore_api_zone_iteration_sqlite_LDADD = \
611 $(top_builddir)/src/testing/libgnunettesting.la \
612 $(top_builddir)/src/identity/libgnunetidentity.la \
613 $(top_builddir)/src/util/libgnunetutil.la \
614 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
615 libgnunetnamestore.la
616
617perf_namestore_api_zone_iteration_flat_SOURCES = \
618 perf_namestore_api_zone_iteration.c
619perf_namestore_api_zone_iteration_flat_LDADD = \
620 $(top_builddir)/src/testing/libgnunettesting.la \
621 $(top_builddir)/src/identity/libgnunetidentity.la \
622 $(top_builddir)/src/util/libgnunetutil.la \
623 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
624 libgnunetnamestore.la
625
626test_namestore_api_zone_iteration_nick_flat_SOURCES = \
627 test_namestore_api_zone_iteration_nick.c
628test_namestore_api_zone_iteration_nick_flat_LDADD = \
629 $(top_builddir)/src/testing/libgnunettesting.la \
630 $(top_builddir)/src/util/libgnunetutil.la \
631 $(top_builddir)/src/identity/libgnunetidentity.la \
632 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
633 libgnunetnamestore.la
634
635test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \
636 test_namestore_api_zone_iteration_nick.c
637test_namestore_api_zone_iteration_nick_sqlite_LDADD = \
638 $(top_builddir)/src/testing/libgnunettesting.la \
639 $(top_builddir)/src/identity/libgnunetidentity.la \
640 $(top_builddir)/src/util/libgnunetutil.la \
641 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
642 libgnunetnamestore.la
643
644test_namestore_api_zone_iteration_nick_postgres_SOURCES = \
645 test_namestore_api_zone_iteration_nick.c
646test_namestore_api_zone_iteration_nick_postgres_LDADD = \
647 $(top_builddir)/src/testing/libgnunettesting.la \
648 $(top_builddir)/src/identity/libgnunetidentity.la \
649 $(top_builddir)/src/util/libgnunetutil.la \
650 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
651 libgnunetnamestore.la
652
653test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \
654 test_namestore_api_zone_iteration_specific_zone.c
655test_namestore_api_zone_iteration_specific_zone_flat_LDADD = \
656 $(top_builddir)/src/testing/libgnunettesting.la \
657 $(top_builddir)/src/identity/libgnunetidentity.la \
658 $(top_builddir)/src/util/libgnunetutil.la \
659 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
660 libgnunetnamestore.la
661
662test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \
663 test_namestore_api_zone_iteration_specific_zone.c
664test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \
665 $(top_builddir)/src/testing/libgnunettesting.la \
666 $(top_builddir)/src/identity/libgnunetidentity.la \
667 $(top_builddir)/src/util/libgnunetutil.la \
668 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
669 libgnunetnamestore.la
670
671test_namestore_api_zone_iteration_specific_zone_postgres_SOURCES = \
672 test_namestore_api_zone_iteration_specific_zone.c
673test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \
674 $(top_builddir)/src/testing/libgnunettesting.la \
675 $(top_builddir)/src/identity/libgnunetidentity.la \
676 $(top_builddir)/src/util/libgnunetutil.la \
677 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
678 libgnunetnamestore.la
679
680test_namestore_api_zone_iteration_stop_flat_SOURCES = \
681 test_namestore_api_zone_iteration_stop.c
682test_namestore_api_zone_iteration_stop_flat_LDADD = \
683 $(top_builddir)/src/testing/libgnunettesting.la \
684 $(top_builddir)/src/identity/libgnunetidentity.la \
685 $(top_builddir)/src/util/libgnunetutil.la \
686 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
687 libgnunetnamestore.la
688
689test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \
690 test_namestore_api_zone_iteration_stop.c
691test_namestore_api_zone_iteration_stop_sqlite_LDADD = \
692 $(top_builddir)/src/testing/libgnunettesting.la \
693 $(top_builddir)/src/identity/libgnunetidentity.la \
694 $(top_builddir)/src/util/libgnunetutil.la \
695 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
696 libgnunetnamestore.la
697
698test_namestore_api_zone_iteration_stop_postgres_SOURCES = \
699 test_namestore_api_zone_iteration_stop.c
700test_namestore_api_zone_iteration_stop_postgres_LDADD = \
701 $(top_builddir)/src/testing/libgnunettesting.la \
702 $(top_builddir)/src/identity/libgnunetidentity.la \
703 $(top_builddir)/src/util/libgnunetutil.la \
704 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
705 libgnunetnamestore.la
706
707test_plugin_namestore_flat_SOURCES = \
708 test_plugin_namestore.c
709test_plugin_namestore_flat_LDADD = \
710 $(top_builddir)/src/testing/libgnunettesting.la \
711 $(top_builddir)/src/identity/libgnunetidentity.la \
712 $(top_builddir)/src/util/libgnunetutil.la
713
714test_plugin_namestore_sqlite_SOURCES = \
715 test_plugin_namestore.c
716test_plugin_namestore_sqlite_LDADD = \
717 $(top_builddir)/src/testing/libgnunettesting.la \
718 $(top_builddir)/src/identity/libgnunetidentity.la \
719 $(top_builddir)/src/util/libgnunetutil.la
720
721test_plugin_namestore_postgres_SOURCES = \
722 test_plugin_namestore.c
723test_plugin_namestore_postgres_LDADD = \
724 $(top_builddir)/src/identity/libgnunetidentity.la \
725 $(top_builddir)/src/testing/libgnunettesting.la \
726 $(top_builddir)/src/util/libgnunetutil.la
727
728check_SCRIPTS = \
729 test_namestore_put.sh \
730 test_namestore_lookup.sh \
731 test_namestore_delete.sh
732
733check_SCRIPTS += \
734 test_plugin_rest_namestore.sh
735
736EXTRA_DIST = \
737 test_common.c \
738 test_namestore_api.conf \
739 test_namestore_api_postgres.conf \
740 test_namestore_api_sqlite.conf \
741 test_namestore_api_flat.conf \
742 perf_namestore_api_postgres.conf \
743 perf_namestore_api_sqlite.conf \
744 perf_namestore_api_flat.conf \
745 test_plugin_namestore_sqlite.conf \
746 test_plugin_namestore_postgres.conf \
747 test_plugin_namestore_flat.conf \
748 test_hostkey \
749 $(check_SCRIPTS)
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c
deleted file mode 100644
index 7e96ffa43..000000000
--- a/src/namestore/gnunet-namestore-fcfsd.c
+++ /dev/null
@@ -1,1167 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-2021 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 gnunet-namestore-fcfsd.c
23 * @brief HTTP daemon that offers first-come-first-serve GNS domain registration
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include <microhttpd.h>
29#include "gnunet_util_lib.h"
30#include "gnunet_identity_service.h"
31#include "gnunet_gnsrecord_lib.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_mhd_compat.h"
34#include "gnunet_json_lib.h"
35
36/**
37 * Structure representing a static page.
38 * "Static" means that the server does not process the page before sending it
39 * to the client. Clients can still process the received data, for example
40 * because there are scripting elements within.
41 */
42struct StaticPage
43{
44 /**
45 * Handle to file on disk.
46 */
47 struct GNUNET_DISK_FileHandle *handle;
48
49 /**
50 * Size in bytes of the file.
51 */
52 uint64_t size;
53
54 /**
55 * Cached response object to send to clients.
56 */
57 struct MHD_Response *response;
58};
59
60/**
61 * Structure containing some request-specific data.
62 */
63struct RequestData
64{
65 /**
66 * The connection this request was sent in.
67 */
68 struct MHD_Connection *c;
69
70 /**
71 * Body of the response object.
72 */
73 char *body;
74
75 /**
76 * Length in bytes of the body.
77 */
78 size_t body_length;
79
80 /**
81 * Response code.
82 */
83 int code;
84
85 /**
86 * Task started to search for an entry in the namestore.
87 */
88 struct GNUNET_NAMESTORE_QueueEntry *searching;
89
90 /**
91 * Task started to iterate over the namestore.
92 */
93 struct GNUNET_NAMESTORE_ZoneIterator *iterating;
94
95 /**
96 * Pointer used while processing POST data.
97 */
98 void *ptr;
99
100 /**
101 * Name requested to be registered.
102 */
103 char *register_name;
104
105 /**
106 * Key (encoded as a string) to be associated with the requested name.
107 */
108 char *register_key;
109
110 /**
111 * Key to be associated with the requested name.
112 */
113 struct GNUNET_IDENTITY_PublicKey key;
114};
115
116/**
117 * Name of the zone being managed.
118 */
119static char *zone = NULL;
120
121/**
122 * The port the daemon is listening to for HTTP requests.
123 */
124static unsigned long long port = 18080;
125
126/**
127 * Connection with the namestore service.
128 */
129static struct GNUNET_NAMESTORE_Handle *namestore = NULL;
130
131/**
132 * Connection with the identity service.
133 */
134static struct GNUNET_IDENTITY_Handle *identity = NULL;
135
136/**
137 * Private key of the zone.
138 */
139static const struct GNUNET_IDENTITY_PrivateKey *zone_key = NULL;
140
141/**
142 * The HTTP daemon.
143 */
144static struct MHD_Daemon *httpd = NULL;
145
146/**
147 * Task executing the HTTP daemon.
148 */
149static struct GNUNET_SCHEDULER_Task *httpd_task = NULL;
150
151/**
152 * The main page, a.k.a. "index.html"
153 */
154static struct StaticPage *main_page = NULL;
155
156/**
157 * Page indicating the requested resource could not be found.
158 */
159static struct StaticPage *notfound_page = NULL;
160
161/**
162 * Page indicating the requested resource could not be accessed, and other
163 * errors.
164 */
165static struct StaticPage *forbidden_page = NULL;
166
167/**
168 * The relative expiration time for added records
169 */
170static struct GNUNET_TIME_Relative record_exp;
171
172/**
173 * Task ran at shutdown to clean up everything.
174 *
175 * @param cls unused
176 */
177static void
178do_shutdown (void *cls)
179{
180 /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so
181 calling `GNUNET_DISK_file_close' would generate a spurious warning message
182 in the log. Since that function does nothing but close the descriptor and
183 free the allocated memory, After destroying the response all that's left to
184 do is call `GNUNET_free'. */
185 if (NULL != main_page)
186 {
187 MHD_destroy_response (main_page->response);
188 GNUNET_free (main_page->handle);
189 GNUNET_free (main_page);
190 }
191 if (NULL != notfound_page)
192 {
193 MHD_destroy_response (notfound_page->response);
194 GNUNET_free (notfound_page->handle);
195 GNUNET_free (notfound_page);
196 }
197 if (NULL != forbidden_page)
198 {
199 MHD_destroy_response (forbidden_page->response);
200 GNUNET_free (forbidden_page->handle);
201 GNUNET_free (forbidden_page);
202 }
203
204 if (NULL != namestore)
205 {
206 GNUNET_NAMESTORE_disconnect (namestore);
207 }
208
209 if (NULL != identity)
210 {
211 GNUNET_IDENTITY_disconnect (identity);
212 }
213
214 if (NULL != httpd_task)
215 {
216 GNUNET_SCHEDULER_cancel (httpd_task);
217 }
218 if (NULL != httpd)
219 {
220 MHD_stop_daemon (httpd);
221 }
222}
223
224
225/**
226 * Called when the HTTP server has some pending operations.
227 *
228 * @param cls unused
229 */
230static void
231do_httpd (void *cls);
232
233/**
234 * Schedule a task to run MHD.
235 */
236static void
237run_httpd (void)
238{
239 fd_set rs;
240 fd_set ws;
241 fd_set es;
242
243 struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create ();
244 struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create ();
245 struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create ();
246
247 FD_ZERO (&rs);
248 FD_ZERO (&ws);
249 FD_ZERO (&es);
250
251 int max = -1;
252 GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
253
254 unsigned MHD_LONG_LONG timeout = 0;
255 struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL;
256 if (MHD_YES == MHD_get_timeout (httpd, &timeout))
257 {
258 gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
259 timeout);
260 }
261
262 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
263 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
264 GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1);
265
266 httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
267 gtime,
268 grs,
269 gws,
270 &do_httpd,
271 NULL);
272 GNUNET_NETWORK_fdset_destroy (grs);
273 GNUNET_NETWORK_fdset_destroy (gws);
274 GNUNET_NETWORK_fdset_destroy (ges);
275}
276
277
278/**
279 * Called when the HTTP server has some pending operations.
280 *
281 * @param cls unused
282 */
283static void
284do_httpd (void *cls)
285{
286 httpd_task = NULL;
287 MHD_run (httpd);
288 run_httpd ();
289}
290
291
292static void
293run_httpd_now (void)
294{
295 if (NULL != httpd_task)
296 {
297 GNUNET_SCHEDULER_cancel (httpd_task);
298 httpd_task = NULL;
299 }
300 httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
301}
302
303
304/**
305 * Generate a JSON object.
306 *
307 * @param key the key for the first element
308 * @param value the value for the first element
309 * @param ... key-value pairs of the object, terminated by NULL
310 * @return a JSON string (allocated)
311 */
312static char *
313make_json (const char *key, const char *value, ...)
314{
315 va_list args;
316 va_start (args, value);
317
318 json_t *obj = NULL;
319
320 obj = json_object ();
321 if ((NULL == key) || (NULL == value))
322 {
323 va_end (args);
324 return json_dumps (obj, JSON_COMPACT);
325 }
326
327 json_object_set (obj, key, json_string (value));
328
329 char *k = va_arg (args, char *);
330 if (NULL == k)
331 {
332 va_end (args);
333 return json_dumps (obj, JSON_COMPACT);
334 }
335 char *v = va_arg (args, char *);
336 if (NULL == v)
337 {
338 va_end (args);
339 return json_dumps (obj, JSON_COMPACT);
340 }
341
342 while (NULL != k && NULL != v)
343 {
344 json_object_set (obj, k, json_string (v));
345 k = va_arg (args, char *);
346 if (NULL != k)
347 {
348 v = va_arg (args, char *);
349 }
350 }
351
352 va_end (args);
353
354 char *json = json_dumps (obj, JSON_COMPACT);
355 json_decref (obj);
356
357 return json;
358}
359
360
361/**
362 * The namestore search task failed.
363 *
364 * @param cls the request data
365 */
366static void
367search_error_cb (void *cls)
368{
369 struct RequestData *rd = cls;
370 MHD_resume_connection (rd->c);
371 rd->searching = NULL;
372 rd->body = make_json ("error", "true",
373 "message", _ ("can not search the namestore"),
374 NULL);
375 rd->body_length = strlen (rd->body);
376 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
377 run_httpd_now ();
378}
379
380
381/**
382 * The lookup terminated with some results.
383 *
384 * @param cls closure
385 * @param zone the private key of the zone
386 * @param label the result label
387 * @param count number of records found
388 * @param d records found
389 */
390static void
391search_done_cb (void *cls,
392 const struct GNUNET_IDENTITY_PrivateKey *zone,
393 const char *label,
394 unsigned int count,
395 const struct GNUNET_GNSRECORD_Data *d)
396{
397 (void) zone;
398 (void) d;
399
400 struct RequestData *rd = cls;
401 MHD_resume_connection (rd->c);
402
403 rd->searching = NULL;
404 rd->body = make_json ("error", "false",
405 "free", (0 == count) ? "true" : "false",
406 NULL);
407 rd->body_length = strlen (rd->body);
408 rd->code = MHD_HTTP_OK;
409
410 run_httpd_now ();
411}
412
413
414/**
415 * An error occurred while registering a name.
416 *
417 * @param cls the connection
418 */
419static void
420register_error_cb (void *cls)
421{
422 struct RequestData *rd = cls;
423
424 MHD_resume_connection (rd->c);
425 rd->searching = NULL;
426 rd->body = make_json ("error", "true",
427 "message", _ ("unable to scan namestore"),
428 NULL);
429 rd->body_length = strlen (rd->body);
430 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
431 run_httpd_now ();
432}
433
434
435/**
436 * A name/key pair has been successfully registered, or maybe not.
437 *
438 * @param cls the connection
439 * @param status result of the operation
440 * @param emsg error message if any
441 */
442static void
443register_done_cb (void *cls,
444 int32_t status,
445 const char *emsg)
446{
447 struct RequestData *rd = cls;
448
449 MHD_resume_connection (rd->c);
450 rd->searching = NULL;
451
452 if ((GNUNET_SYSERR == status) || (GNUNET_NO == status))
453 {
454 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
455 _ ("Failed to create record for `%s': %s\n"),
456 rd->register_name,
457 emsg);
458 rd->body = make_json ("error", "true",
459 "message", emsg,
460 NULL);
461 rd->body_length = strlen (rd->body);
462 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
463 }
464 else
465 {
466 rd->body = make_json ("error", "false",
467 "message", _ ("no errors"),
468 NULL);
469 rd->body_length = strlen (rd->body);
470 rd->code = MHD_HTTP_OK;
471 }
472
473 run_httpd_now ();
474}
475
476
477/**
478 * Attempt to register the requested name.
479 *
480 * @param cls the connection
481 * @param key the zone key
482 * @param label name of the record
483 * @param count number of records found
484 * @param d records
485 */
486static void
487register_do_cb (void *cls,
488 const struct GNUNET_IDENTITY_PrivateKey *key,
489 const char *label,
490 unsigned int count,
491 const struct GNUNET_GNSRECORD_Data *d)
492{
493 (void) key;
494 (void) d;
495
496 struct RequestData *rd = cls;
497
498 rd->searching = NULL;
499
500 if (0 != count)
501 {
502 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
503 _ ("The requested key `%s' exists as `%s'\n"),
504 rd->register_key,
505 label);
506
507 MHD_resume_connection (rd->c);
508 rd->searching = NULL;
509 rd->body = make_json ("error", "true",
510 "message", _ ("key exists"),
511 NULL);
512 rd->body_length = strlen (rd->body);
513 rd->code = MHD_HTTP_FORBIDDEN;
514 run_httpd_now ();
515 return;
516 }
517
518 struct GNUNET_GNSRECORD_Data gd;
519 char *gdraw = NULL;
520
521 if (GNUNET_OK != GNUNET_GNSRECORD_data_from_identity (&(rd->key),
522 &gdraw,
523 &(gd.data_size),
524 &(gd.record_type)))
525 {
526 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
527 _ ("Error creating record data\n"));
528 MHD_resume_connection (rd->c);
529 rd->searching = NULL;
530 rd->body = make_json ("error", "true",
531 "message", _ ("unable to store record"),
532 NULL);
533 rd->body_length = strlen (rd->body);
534 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
535 run_httpd_now ();
536 return;
537 }
538
539 gd.data = gdraw;
540 gd.expiration_time = record_exp.rel_value_us;
541 gd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
542
543 rd->searching = GNUNET_NAMESTORE_records_store (namestore,
544 zone_key,
545 rd->register_name,
546 1,
547 &gd,
548 &register_done_cb,
549 rd);
550
551 GNUNET_free (gdraw);
552}
553
554
555/**
556 * An error occurred while iterating the namestore.
557 *
558 * @param cls the connection
559 */
560static void
561iterate_error_cb (void *cls)
562{
563 struct RequestData *rd = cls;
564
565 MHD_resume_connection (rd->c);
566 rd->iterating = NULL;
567 rd->body = make_json ("error", "true",
568 "message", _ ("unable to scan namestore"),
569 NULL);
570 rd->body_length = strlen (rd->body);
571 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
572 run_httpd_now ();
573}
574
575
576/**
577 * A block was received from the namestore.
578 *
579 * @param cls the connection
580 * @param key the zone key
581 * @param label the records' label
582 * @param count number of records found
583 * @param d the found records
584 */
585static void
586iterate_do_cb (void *cls,
587 const struct GNUNET_IDENTITY_PrivateKey *key,
588 const char *label,
589 unsigned int count,
590 const struct GNUNET_GNSRECORD_Data *d)
591{
592 (void) key;
593 (void) label;
594 (void) d;
595
596 struct RequestData *rd = cls;
597
598 if (0 == strcmp (label, rd->register_name))
599 {
600 GNUNET_break (0 != count);
601 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
602 _ ("Requested name `%s' exists with `%u' records\n"),
603 rd->register_name,
604 count);
605
606 MHD_resume_connection (rd->c);
607 rd->body = make_json ("error", "true",
608 "message", _ ("name exists\n"),
609 NULL);
610 rd->body_length = strlen (rd->body);
611 rd->code = MHD_HTTP_FORBIDDEN;
612 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
613 run_httpd_now ();
614 return;
615 }
616
617 GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1);
618}
619
620
621/**
622 * All entries in the namestore have been iterated over.
623 *
624 * @param cls the connection
625 */
626static void
627iterate_done_cb (void *cls)
628{
629 struct RequestData *rd = cls;
630
631 rd->iterating = NULL;
632
633 /* See if the key was not registered already */
634 rd->searching = GNUNET_NAMESTORE_zone_to_name (namestore,
635 zone_key,
636 &(rd->key),
637 &register_error_cb,
638 rd,
639 &register_do_cb,
640 rd);
641}
642
643
644/**
645 * Generate a response containing JSON and send it to the client.
646 *
647 * @param c the connection
648 * @param body the response body
649 * @param length the body length in bytes
650 * @param code the response code
651 * @return MHD_NO on error
652 */
653static MHD_RESULT
654serve_json (struct MHD_Connection *c,
655 char *body,
656 size_t length,
657 int code)
658{
659 struct MHD_Response *response =
660 MHD_create_response_from_buffer (length,
661 body,
662 MHD_RESPMEM_PERSISTENT);
663 MHD_RESULT r = MHD_queue_response (c, code, response);
664 MHD_destroy_response (response);
665 return r;
666}
667
668
669/**
670 * Send a response back to a connected client.
671 *
672 * @param cls unused
673 * @param connection the connection with the client
674 * @param url the requested address
675 * @param method the HTTP method used
676 * @param version the protocol version (including the "HTTP/" part)
677 * @param upload_data data sent with a POST request
678 * @param upload_data_size length in bytes of the POST data
679 * @param ptr used to pass data between request handling phases
680 * @return MHD_NO on error
681 */
682static MHD_RESULT
683create_response (void *cls,
684 struct MHD_Connection *connection,
685 const char *url,
686 const char *method,
687 const char *version,
688 const char *upload_data,
689 size_t *upload_data_size,
690 void **ptr)
691{
692 (void) cls;
693 (void) version;
694
695 struct RequestData *rd = *ptr;
696
697 if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
698 {
699 /* Handle a previously suspended request */
700 if (NULL != rd)
701 {
702 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
703 }
704
705 if (0 == strcmp ("/", url))
706 {
707 return MHD_queue_response (connection,
708 MHD_HTTP_OK,
709 main_page->response);
710 }
711
712 if (0 == strcmp ("/search", url))
713 {
714 const char *name = MHD_lookup_connection_value (connection,
715 MHD_GET_ARGUMENT_KIND,
716 "name");
717 if (NULL == name)
718 {
719 return MHD_queue_response (connection,
720 MHD_HTTP_BAD_REQUEST,
721 forbidden_page->response);
722 }
723
724 MHD_suspend_connection (connection);
725 rd = GNUNET_new (struct RequestData);
726 rd->c = connection;
727 rd->searching = GNUNET_NAMESTORE_records_lookup (namestore,
728 zone_key,
729 name,
730 &search_error_cb,
731 rd,
732 &search_done_cb,
733 rd);
734 *ptr = rd;
735 return MHD_YES;
736 }
737
738 return MHD_queue_response (connection,
739 MHD_HTTP_NOT_FOUND,
740 notfound_page->response);
741 }
742
743 if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD))
744 {
745 /* We take a shortcut here by always serving the main page: starting a
746 namestore lookup, allocating the necessary resources, waiting for the
747 lookup to complete and then discard everything just because it was a HEAD
748 and thus only the headers are significative, is an unnecessary waste of
749 resources. The handling of this method could be smarter, for example by
750 sending a proper content type header based on the endpoint, but this is
751 not a service in which HEAD requests are significant, so there's no need
752 to spend too much time here. */
753 return MHD_queue_response (connection,
754 MHD_HTTP_OK,
755 main_page->response);
756 }
757
758 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
759 {
760 if (0 == strcmp ("/register", url))
761 {
762 /* Handle a previously suspended request */
763 if ((NULL != rd) && (NULL != rd->body))
764 {
765 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
766 }
767
768 if (NULL == rd)
769 {
770 rd = GNUNET_new (struct RequestData);
771 rd->c = connection;
772 rd->body = NULL;
773 rd->ptr = NULL;
774 *ptr = rd;
775 }
776
777 json_t *json = NULL;
778 enum GNUNET_JSON_PostResult result =
779 GNUNET_JSON_post_parser (32 * 1024,
780 connection,
781 &(rd->ptr),
782 upload_data,
783 upload_data_size,
784 &json);
785
786 switch (result)
787 {
788 case GNUNET_JSON_PR_CONTINUE:
789 /* Keep processing POST data */
790 return MHD_YES;
791 case GNUNET_JSON_PR_OUT_OF_MEMORY:
792 case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
793 rd->body = make_json ("error", "true",
794 "message", _ ("unable to process submitted data"),
795 NULL);
796 rd->body_length = strlen (rd->body);
797#ifdef MHD_HTTP_CONTENT_TOO_LARGE
798 rd->code = MHD_HTTP_CONTENT_TOO_LARGE;
799#else
800 rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
801#endif
802 return MHD_YES;
803 case GNUNET_JSON_PR_JSON_INVALID:
804 rd->body = make_json ("error", "true",
805 "message", _ ("the submitted data is invalid"),
806 NULL);
807 rd->body_length = strlen (rd->body);
808 rd->code = MHD_HTTP_BAD_REQUEST;
809 return MHD_YES;
810 default:
811 break;
812 }
813
814 /* POST data has been read in its entirety */
815
816 const char *name = json_string_value (json_object_get (json, "name"));
817 const char *key = json_string_value (json_object_get (json, "key"));
818 if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 ==
819 strlen (
820 key)))
821 {
822 json_decref (json);
823 rd->body = make_json ("error", "true",
824 "message", _ ("invalid parameters"),
825 NULL);
826 rd->body_length = strlen (rd->body);
827 rd->code = MHD_HTTP_BAD_REQUEST;
828 return MHD_YES;
829 }
830
831 rd->register_name = strdup (name);
832 rd->register_key = strdup (key);
833
834 json_decref (json);
835 GNUNET_JSON_post_parser_cleanup (rd->ptr);
836
837 if ((NULL != strchr (rd->register_name, '.')) ||
838 (NULL != strchr (rd->register_name, '+')))
839 {
840 rd->body = make_json ("error", "true",
841 "message", _ ("invalid name"),
842 NULL);
843 rd->body_length = strlen (rd->body);
844 rd->code = MHD_HTTP_BAD_REQUEST;
845 return MHD_YES;
846 }
847
848 if (GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (rd->register_key,
849 &(rd->key)))
850 {
851 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
852 _ ("Unable to parse key %s\n"),
853 rd->register_key);
854
855 rd->body = make_json ("error", "true",
856 "message", _ ("unable to parse key"),
857 NULL);
858 rd->body_length = strlen (rd->body);
859 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
860 return MHD_YES;
861 }
862
863 MHD_suspend_connection (connection);
864 /* See if the requested name is free */
865 rd->iterating =
866 GNUNET_NAMESTORE_zone_iteration_start (namestore,
867 zone_key,
868 &iterate_error_cb,
869 rd,
870 &iterate_do_cb,
871 rd,
872 &iterate_done_cb,
873 rd);
874 return MHD_YES;
875 }
876
877 return MHD_queue_response (connection,
878 MHD_HTTP_FORBIDDEN,
879 forbidden_page->response);
880 }
881
882 return MHD_queue_response (connection,
883 MHD_HTTP_NOT_IMPLEMENTED,
884 forbidden_page->response);
885}
886
887
888/**
889 * Called when a request is completed.
890 *
891 * @param cls unused
892 * @param connection the connection
893 * @param ptr connection-specific data
894 * @param status status code
895 */
896static void
897completed_cb (void *cls,
898 struct MHD_Connection *connection,
899 void **ptr,
900 enum MHD_RequestTerminationCode status)
901{
902 (void) cls;
903 (void) connection;
904 (void) status;
905
906 struct RequestData *rd = *ptr;
907
908 if (NULL == rd)
909 {
910 return;
911 }
912
913 if (NULL == rd->body)
914 {
915 GNUNET_free (rd->body);
916 }
917
918 if (NULL != rd->searching)
919 {
920 GNUNET_NAMESTORE_cancel (rd->searching);
921 }
922
923 if (NULL != rd->register_name)
924 {
925 GNUNET_free (rd->register_name);
926 }
927
928 if (NULL != rd->register_key)
929 {
930 GNUNET_free (rd->register_key);
931 }
932
933 if (NULL != rd->iterating)
934 {
935 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
936 }
937
938 GNUNET_free (rd);
939}
940
941
942/**
943 * Called for each ego provided by the identity service.
944 *
945 * @param cls closure
946 * @param ego the ego
947 * @param ctx application-provided data for the ego
948 * @param name the ego name
949 */
950static void
951identity_cb (void *cls,
952 struct GNUNET_IDENTITY_Ego *ego,
953 void **ctx,
954 const char *name)
955{
956 (void) cls;
957 (void) ctx;
958
959 if ((NULL == name) || (0 != strcmp (name, zone)))
960 {
961 return;
962 }
963
964 if (NULL == ego)
965 {
966 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
967 _ ("No ego configured for `fcfsd` subsystem\n"));
968 GNUNET_SCHEDULER_shutdown ();
969 return;
970 }
971
972 zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
973
974 int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
975 do
976 {
977 httpd = MHD_start_daemon (flags,
978 (uint16_t) port,
979 NULL, NULL,
980 &create_response, NULL,
981 MHD_OPTION_CONNECTION_LIMIT, 128,
982 MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1,
983 MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024,
984 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
985 MHD_OPTION_END);
986 flags = MHD_USE_DEBUG;
987 } while (NULL == httpd && flags != MHD_USE_DEBUG);
988
989 if (NULL == httpd)
990 {
991 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
992 _ ("Failed to start HTTP server\n"));
993 GNUNET_SCHEDULER_shutdown ();
994 return;
995 }
996
997 run_httpd ();
998}
999
1000
1001/**
1002 * Open a file on disk and generate a response object for it.
1003 *
1004 * @param name name of the file to open
1005 * @param basedir directory where the file is located
1006 * @return NULL on error
1007 */
1008static struct StaticPage *
1009open_static_page (const char *name, const char *basedir)
1010{
1011 char *fullname = NULL;
1012 GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name);
1013
1014 struct GNUNET_DISK_FileHandle *f =
1015 GNUNET_DISK_file_open (fullname,
1016 GNUNET_DISK_OPEN_READ,
1017 GNUNET_DISK_PERM_NONE);
1018 GNUNET_free (fullname);
1019
1020 if (NULL == f)
1021 {
1022 return NULL;
1023 }
1024
1025 off_t size = 0;
1026 if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size))
1027 {
1028 GNUNET_DISK_file_close (f);
1029 return NULL;
1030 }
1031
1032 struct MHD_Response *response =
1033 MHD_create_response_from_fd64 (size,
1034 f->fd);
1035
1036 if (NULL == response)
1037 {
1038 GNUNET_DISK_file_close (f);
1039 return NULL;
1040 }
1041
1042 struct StaticPage *page = GNUNET_new (struct StaticPage);
1043 page->handle = f;
1044 page->size = (uint64_t) size;
1045 page->response = response;
1046 return page;
1047}
1048
1049
1050/**
1051 * Called after the service is up.
1052 *
1053 * @param cls closure
1054 * @param args remaining command line arguments
1055 * @param cfgfile name of the configuration file
1056 * @param cfg the service configuration
1057 */
1058static void
1059run_service (void *cls,
1060 char *const *args,
1061 const char *cfgfile,
1062 const struct GNUNET_CONFIGURATION_Handle *cfg)
1063{
1064 (void) cls;
1065 (void) args;
1066 (void) cfgfile;
1067
1068 GNUNET_log_setup ("fcfsd", "WARNING", NULL);
1069
1070 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1071 "fcfsd",
1072 "RELATIVE_RECORD_EXPIRATION",
1073 &record_exp))
1074 {
1075 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1076 _("No expiration specified for records.\n"));
1077 GNUNET_SCHEDULER_shutdown ();
1078 return;
1079 }
1080
1081 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1082 "fcfsd",
1083 "HTTPPORT",
1084 &port))
1085 {
1086 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1087 _ ("No port specified, using default value\n"));
1088 }
1089
1090 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1091
1092 namestore = GNUNET_NAMESTORE_connect (cfg);
1093 if (NULL == namestore)
1094 {
1095 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1096 _ ("Failed to connect to namestore\n"));
1097 GNUNET_SCHEDULER_shutdown ();
1098 return;
1099 }
1100
1101 identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1102 if (NULL == identity)
1103 {
1104 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1105 _ ("Failed to connect to identity\n"));
1106 GNUNET_SCHEDULER_shutdown ();
1107 return;
1108 }
1109
1110 char *basedir = NULL;
1111 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1112 "fcfsd",
1113 "HTMLDIR",
1114 &basedir))
1115 {
1116 basedir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
1117 }
1118
1119 main_page = open_static_page ("index.html", basedir);
1120 notfound_page = open_static_page ("notfound.html", basedir);
1121 forbidden_page = open_static_page ("forbidden.html", basedir);
1122
1123 GNUNET_free (basedir);
1124
1125 if ((NULL == main_page) || (NULL == notfound_page) || (NULL ==
1126 forbidden_page) )
1127 {
1128 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1129 _ ("Unable to set up the daemon\n"));
1130 GNUNET_SCHEDULER_shutdown ();
1131 return;
1132 }
1133}
1134
1135
1136/**
1137 * The main function of the fcfs daemon.
1138 *
1139 * @param argc number of arguments from the command line
1140 * @parsm argv the command line arguments
1141 * @return 0 successful exit, a different value otherwise
1142 */
1143int
1144main (int argc, char *const *argv)
1145{
1146 struct GNUNET_GETOPT_CommandLineOption options[] = {
1147 GNUNET_GETOPT_option_mandatory
1148 (GNUNET_GETOPT_option_string ('z',
1149 "zone",
1150 "EGO",
1151 gettext_noop (
1152 "name of the zone managed by FCFSD"),
1153 &zone)),
1154 GNUNET_GETOPT_OPTION_END
1155 };
1156
1157 return ((GNUNET_OK == GNUNET_PROGRAM_run (argc,
1158 argv,
1159 "gnunet-namestore-fcfsd",
1160 _ (
1161 "GNU Name System First-Come-First-Served name registration service"),
1162 options,
1163 &run_service,
1164 NULL)) ?
1165 0 :
1166 1);
1167}
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
deleted file mode 100644
index af40f2dbe..000000000
--- a/src/namestore/gnunet-namestore.c
+++ /dev/null
@@ -1,1660 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 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
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file gnunet-namestore.c
22 * @brief command line tool to manipulate the local zone
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_gns_service.h>
34#include <gnunet_namestore_service.h>
35
36/**
37 * The upper bound for the zone iteration interval
38 * (per record).
39 */
40#define WARN_RELATIVE_EXPIRATION_LIMIT GNUNET_TIME_relative_multiply ( \
41 GNUNET_TIME_UNIT_MINUTES, 15)
42
43/**
44 * Entry in record set for bulk processing.
45 */
46struct RecordSetEntry
47{
48 /**
49 * Kept in a linked list.
50 */
51 struct RecordSetEntry *next;
52
53 /**
54 * The record to add/remove.
55 */
56 struct GNUNET_GNSRECORD_Data record;
57};
58
59
60/**
61 * Handle to the namestore.
62 */
63static struct GNUNET_NAMESTORE_Handle *ns;
64
65/**
66 * Private key for the our zone.
67 */
68static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
69
70/**
71 * Handle to identity lookup.
72 */
73static struct GNUNET_IDENTITY_EgoLookup *el;
74
75/**
76 * Identity service handle
77 */
78static struct GNUNET_IDENTITY_Handle *idh;
79
80/**
81 * Obtain default ego
82 */
83struct GNUNET_IDENTITY_Operation *get_default;
84
85/**
86 * Name of the ego controlling the zone.
87 */
88static char *ego_name;
89
90/**
91 * Desired action is to add a record.
92 */
93static int add;
94
95/**
96 * Queue entry for the 'add-uri' operation.
97 */
98static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri;
99
100/**
101 * Queue entry for the 'add' operation.
102 */
103static struct GNUNET_NAMESTORE_QueueEntry *add_qe;
104
105/**
106 * Queue entry for the 'lookup' operation.
107 */
108static struct GNUNET_NAMESTORE_QueueEntry *get_qe;
109
110/**
111 * Queue entry for the 'reverse lookup' operation (in combination with a name).
112 */
113static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe;
114
115/**
116 * Desired action is to list records.
117 */
118static int list;
119
120/**
121 * List iterator for the 'list' operation.
122 */
123static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
124
125/**
126 * Desired action is to remove a record.
127 */
128static int del;
129
130/**
131 * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE)
132 */
133static int is_public;
134
135/**
136 * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD)
137 */
138static int is_shadow;
139
140/**
141 * Queue entry for the 'del' operation.
142 */
143static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
144
145/**
146 * Queue entry for the 'set/replace' operation.
147 */
148static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
149
150/**
151 * Name of the records to add/list/remove.
152 */
153static char *name;
154
155/**
156 * Value of the record to add/remove.
157 */
158static char *value;
159
160/**
161 * URI to import.
162 */
163static char *uri;
164
165/**
166 * Reverse lookup to perform.
167 */
168static char *reverse_pkey;
169
170/**
171 * Type of the record to add/remove, NULL to remove all.
172 */
173static char *typestring;
174
175/**
176 * Desired expiration time.
177 */
178static char *expirationstring;
179
180/**
181 * Desired nick name.
182 */
183static char *nickstring;
184
185/**
186 * Global return value
187 */
188static int ret;
189
190/**
191 * Type string converted to DNS type value.
192 */
193static uint32_t type;
194
195/**
196 * Value in binary format.
197 */
198static void *data;
199
200/**
201 * Number of bytes in #data.
202 */
203static size_t data_size;
204
205/**
206 * Expiration string converted to numeric value.
207 */
208static uint64_t etime;
209
210/**
211 * Is expiration time relative or absolute time?
212 */
213static int etime_is_rel = GNUNET_SYSERR;
214
215/**
216 * Monitor handle.
217 */
218static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
219
220/**
221 * Enables monitor mode.
222 */
223static int monitor;
224
225/**
226 * Entry in record set for processing records in bulk.
227 */
228static struct RecordSetEntry *recordset;
229
230
231/**
232 * Task run on shutdown. Cleans up everything.
233 *
234 * @param cls unused
235 */
236static void
237do_shutdown (void *cls)
238{
239 (void) cls;
240 if (NULL != get_default)
241 {
242 GNUNET_IDENTITY_cancel (get_default);
243 get_default = NULL;
244 }
245 if (NULL != idh)
246 {
247 GNUNET_IDENTITY_disconnect (idh);
248 idh = NULL;
249 }
250 if (NULL != el)
251 {
252 GNUNET_IDENTITY_ego_lookup_cancel (el);
253 el = NULL;
254 }
255 if (NULL != list_it)
256 {
257 GNUNET_NAMESTORE_zone_iteration_stop (list_it);
258 list_it = NULL;
259 }
260 if (NULL != add_qe)
261 {
262 GNUNET_NAMESTORE_cancel (add_qe);
263 add_qe = NULL;
264 }
265 if (NULL != set_qe)
266 {
267 GNUNET_NAMESTORE_cancel (set_qe);
268 set_qe = NULL;
269 }
270 if (NULL != add_qe_uri)
271 {
272 GNUNET_NAMESTORE_cancel (add_qe_uri);
273 add_qe_uri = NULL;
274 }
275 if (NULL != get_qe)
276 {
277 GNUNET_NAMESTORE_cancel (get_qe);
278 get_qe = NULL;
279 }
280 if (NULL != del_qe)
281 {
282 GNUNET_NAMESTORE_cancel (del_qe);
283 del_qe = NULL;
284 }
285 if (NULL != ns)
286 {
287 GNUNET_NAMESTORE_disconnect (ns);
288 ns = NULL;
289 }
290 memset (&zone_pkey, 0, sizeof(zone_pkey));
291 if (NULL != uri)
292 {
293 GNUNET_free (uri);
294 uri = NULL;
295 }
296 if (NULL != zm)
297 {
298 GNUNET_NAMESTORE_zone_monitor_stop (zm);
299 zm = NULL;
300 }
301 if (NULL != data)
302 {
303 GNUNET_free (data);
304 data = NULL;
305 }
306}
307
308
309/**
310 * Check if we are finished, and if so, perform shutdown.
311 */
312static void
313test_finished ()
314{
315 if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) &&
316 (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it))
317 GNUNET_SCHEDULER_shutdown ();
318}
319
320
321/**
322 * Continuation called to notify client about result of the
323 * operation.
324 *
325 * @param cls closure, location of the QueueEntry pointer to NULL out
326 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
327 * #GNUNET_NO if content was already there
328 * #GNUNET_YES (or other positive value) on success
329 * @param emsg NULL on success, otherwise an error message
330 */
331static void
332add_continuation (void *cls, int32_t success, const char *emsg)
333{
334 struct GNUNET_NAMESTORE_QueueEntry **qe = cls;
335
336 *qe = NULL;
337 if (GNUNET_YES != success)
338 {
339 fprintf (stderr,
340 _ ("Adding record failed: %s\n"),
341 (GNUNET_NO == success) ? "record exists" : emsg);
342 if (GNUNET_NO != success)
343 ret = 1;
344 }
345 ret = 0;
346 test_finished ();
347}
348
349
350/**
351 * Continuation called to notify client about result of the
352 * operation.
353 *
354 * @param cls closure, unused
355 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
356 * #GNUNET_NO if content was already there
357 * #GNUNET_YES (or other positive value) on success
358 * @param emsg NULL on success, otherwise an error message
359 */
360static void
361del_continuation (void *cls, int32_t success, const char *emsg)
362{
363 (void) cls;
364 del_qe = NULL;
365 if (GNUNET_NO == success)
366 {
367 fprintf (stderr,
368 _ ("Deleting record failed, record does not exist%s%s\n"),
369 (NULL != emsg) ? ": " : "",
370 (NULL != emsg) ? emsg : "");
371 }
372 if (GNUNET_SYSERR == success)
373 {
374 fprintf (stderr,
375 _ ("Deleting record failed%s%s\n"),
376 (NULL != emsg) ? ": " : "",
377 (NULL != emsg) ? emsg : "");
378 }
379 test_finished ();
380}
381
382
383/**
384 * Function called when we are done with a zone iteration.
385 */
386static void
387zone_iteration_finished (void *cls)
388{
389 (void) cls;
390 list_it = NULL;
391 test_finished ();
392}
393
394
395/**
396 * Function called when we encountered an error in a zone iteration.
397 */
398static void
399zone_iteration_error_cb (void *cls)
400{
401 (void) cls;
402 list_it = NULL;
403 fprintf (stderr, "Error iterating over zone\n");
404 ret = 1;
405 test_finished ();
406}
407
408
409/**
410 * Process a record that was stored in the namestore.
411 *
412 * @param rname name that is being mapped (at most 255 characters long)
413 * @param rd_len number of entries in @a rd array
414 * @param rd array of records with data to store
415 */
416static void
417display_record (const char *rname,
418 unsigned int rd_len,
419 const struct GNUNET_GNSRECORD_Data *rd)
420{
421 const char *typestr;
422 char *s;
423 const char *ets;
424 struct GNUNET_TIME_Absolute at;
425 struct GNUNET_TIME_Relative rt;
426 int have_record;
427
428 if ((NULL != name) && (0 != strcmp (name, rname)))
429 {
430 GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
431 return;
432 }
433 have_record = GNUNET_NO;
434 for (unsigned int i = 0; i < rd_len; i++)
435 {
436 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
437 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
438 continue;
439 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
440 continue;
441 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
442 continue;
443 have_record = GNUNET_YES;
444 break;
445 }
446 if (GNUNET_NO == have_record)
447 return;
448 fprintf (stdout, "%s:\n", rname);
449 if (NULL != typestring)
450 type = GNUNET_GNSRECORD_typename_to_number (typestring);
451 else
452 type = GNUNET_GNSRECORD_TYPE_ANY;
453 for (unsigned int i = 0; i < rd_len; i++)
454 {
455 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
456 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
457 continue;
458 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
459 continue;
460 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
461 continue;
462 typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
463 s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
464 rd[i].data,
465 rd[i].data_size);
466 if (NULL == s)
467 {
468 fprintf (stdout,
469 _ ("\tCorrupt or unsupported record of type %u\n"),
470 (unsigned int) rd[i].record_type);
471 continue;
472 }
473 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
474 {
475 rt.rel_value_us = rd[i].expiration_time;
476 ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES);
477 }
478 else
479 {
480 at.abs_value_us = rd[i].expiration_time;
481 ets = GNUNET_STRINGS_absolute_time_to_string (at);
482 }
483 fprintf (stdout,
484 "\t%s: %s (%s)\t%s\t%s\n",
485 typestr,
486 s,
487 ets,
488 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE"
489 : "PUBLIC",
490 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW"
491 : "");
492 GNUNET_free (s);
493 }
494 fprintf (stdout, "%s", "\n");
495}
496
497
498/**
499 * Process a record that was stored in the namestore.
500 *
501 * @param cls closure
502 * @param zone_key private key of the zone
503 * @param rname name that is being mapped (at most 255 characters long)
504 * @param rd_len number of entries in @a rd array
505 * @param rd array of records with data to store
506 */
507static void
508display_record_iterator (void *cls,
509 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
510 const char *rname,
511 unsigned int rd_len,
512 const struct GNUNET_GNSRECORD_Data *rd)
513{
514 (void) cls;
515 (void) zone_key;
516 display_record (rname, rd_len, rd);
517 GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
518}
519
520
521/**
522 * Process a record that was stored in the namestore.
523 *
524 * @param cls closure
525 * @param zone_key private key of the zone
526 * @param rname name that is being mapped (at most 255 characters long)
527 * @param rd_len number of entries in @a rd array
528 * @param rd array of records with data to store
529 */
530static void
531display_record_monitor (void *cls,
532 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
533 const char *rname,
534 unsigned int rd_len,
535 const struct GNUNET_GNSRECORD_Data *rd)
536{
537 (void) cls;
538 (void) zone_key;
539 display_record (rname, rd_len, rd);
540 GNUNET_NAMESTORE_zone_monitor_next (zm, 1);
541}
542
543
544/**
545 * Process a record that was stored in the namestore.
546 *
547 * @param cls closure
548 * @param zone_key private key of the zone
549 * @param rname name that is being mapped (at most 255 characters long)
550 * @param rd_len number of entries in @a rd array
551 * @param rd array of records with data to store
552 */
553static void
554display_record_lookup (void *cls,
555 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
556 const char *rname,
557 unsigned int rd_len,
558 const struct GNUNET_GNSRECORD_Data *rd)
559{
560 (void) cls;
561 (void) zone_key;
562 get_qe = NULL;
563 display_record (rname, rd_len, rd);
564 test_finished ();
565}
566
567
568/**
569 * Function called once we are in sync in monitor mode.
570 *
571 * @param cls NULL
572 */
573static void
574sync_cb (void *cls)
575{
576 (void) cls;
577 fprintf (stdout, "%s", "Monitor is now in sync.\n");
578}
579
580
581/**
582 * Function called on errors while monitoring.
583 *
584 * @param cls NULL
585 */
586static void
587monitor_error_cb (void *cls)
588{
589 (void) cls;
590 fprintf (stderr, "%s", "Monitor disconnected and out of sync.\n");
591}
592
593
594/**
595 * Function called on errors while monitoring.
596 *
597 * @param cls NULL
598 */
599static void
600lookup_error_cb (void *cls)
601{
602 (void) cls;
603 get_qe = NULL;
604 fprintf (stderr, "%s", "Failed to lookup record.\n");
605 test_finished ();
606}
607
608
609/**
610 * Function called if lookup fails.
611 */
612static void
613add_error_cb (void *cls)
614{
615 (void) cls;
616 add_qe = NULL;
617 GNUNET_break (0);
618 ret = 1;
619 test_finished ();
620}
621
622
623/**
624 * We're storing a record; this function is given the existing record
625 * so that we can merge the information.
626 *
627 * @param cls closure, unused
628 * @param zone_key private key of the zone
629 * @param rec_name name that is being mapped (at most 255 characters long)
630 * @param rd_count number of entries in @a rd array
631 * @param rd array of records with data to store
632 */
633static void
634get_existing_record (void *cls,
635 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
636 const char *rec_name,
637 unsigned int rd_count,
638 const struct GNUNET_GNSRECORD_Data *rd)
639{
640 struct GNUNET_GNSRECORD_Data rdn[rd_count + 1];
641 struct GNUNET_GNSRECORD_Data *rde;
642
643 (void) cls;
644 (void) zone_key;
645 add_qe = NULL;
646 if (0 != strcmp (rec_name, name))
647 {
648 GNUNET_break (0);
649 ret = 1;
650 test_finished ();
651 return;
652 }
653
654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
655 "Received %u records for name `%s'\n",
656 rd_count,
657 rec_name);
658 for (unsigned int i = 0; i < rd_count; i++)
659 {
660 switch (rd[i].record_type)
661 {
662 case GNUNET_DNSPARSER_TYPE_SOA:
663 if (GNUNET_DNSPARSER_TYPE_SOA == type)
664 {
665 fprintf (
666 stderr,
667 _ (
668 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"),
669 rec_name);
670 ret = 1;
671 test_finished ();
672 return;
673 }
674 break;
675 }
676 }
677 memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data));
678 GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data));
679 rde = &rdn[0];
680 rde->data = data;
681 rde->data_size = data_size;
682 rde->record_type = type;
683 if (1 == is_shadow)
684 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
685 if (1 != is_public)
686 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
687 rde->expiration_time = etime;
688 if (GNUNET_YES == etime_is_rel)
689 rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
690 else if (GNUNET_NO != etime_is_rel)
691 rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
692 GNUNET_assert (NULL != name);
693 add_qe = GNUNET_NAMESTORE_records_store (ns,
694 &zone_pkey,
695 name,
696 rd_count + 1,
697 rde,
698 &add_continuation,
699 &add_qe);
700}
701
702
703/**
704 * Function called if we encountered an error in zone-to-name.
705 */
706static void
707reverse_error_cb (void *cls)
708{
709 (void) cls;
710 reverse_qe = NULL;
711 fprintf (stdout, "%s.zkey\n", reverse_pkey);
712}
713
714
715/**
716 * Function called with the result of our attempt to obtain a name for a given
717 * public key.
718 *
719 * @param cls NULL
720 * @param zone private key of the zone; NULL on disconnect
721 * @param label label of the records; NULL on disconnect
722 * @param rd_count number of entries in @a rd array, 0 if label was deleted
723 * @param rd array of records with data to store
724 */
725static void
726handle_reverse_lookup (void *cls,
727 const struct GNUNET_IDENTITY_PrivateKey *zone,
728 const char *label,
729 unsigned int rd_count,
730 const struct GNUNET_GNSRECORD_Data *rd)
731{
732 (void) cls;
733 (void) zone;
734 (void) rd_count;
735 (void) rd;
736 reverse_qe = NULL;
737 if (NULL == label)
738 fprintf (stdout, "%s\n", reverse_pkey);
739 else
740 fprintf (stdout, "%s.%s\n", label, ego_name);
741 test_finished ();
742}
743
744
745/**
746 * Function called if lookup for deletion fails.
747 */
748static void
749del_lookup_error_cb (void *cls)
750{
751 (void) cls;
752 del_qe = NULL;
753 GNUNET_break (0);
754 ret = 1;
755 test_finished ();
756}
757
758
759/**
760 * We were asked to delete something; this function is called with
761 * the existing records. Now we should determine what should be
762 * deleted and then issue the deletion operation.
763 *
764 * @param cls NULL
765 * @param zone private key of the zone we are deleting from
766 * @param label name of the records we are editing
767 * @param rd_count size of the @a rd array
768 * @param rd existing records
769 */
770static void
771del_monitor (void *cls,
772 const struct GNUNET_IDENTITY_PrivateKey *zone,
773 const char *label,
774 unsigned int rd_count,
775 const struct GNUNET_GNSRECORD_Data *rd)
776{
777 struct GNUNET_GNSRECORD_Data rdx[rd_count];
778 unsigned int rd_left;
779 uint32_t type;
780 char *vs;
781
782 (void) cls;
783 (void) zone;
784 del_qe = NULL;
785 if (0 == rd_count)
786 {
787 fprintf (stderr,
788 _ (
789 "There are no records under label `%s' that could be deleted.\n"),
790 label);
791 ret = 1;
792 test_finished ();
793 return;
794 }
795 if ((NULL == value) && (NULL == typestring))
796 {
797 /* delete everything */
798 del_qe = GNUNET_NAMESTORE_records_store (ns,
799 &zone_pkey,
800 name,
801 0,
802 NULL,
803 &del_continuation,
804 NULL);
805 return;
806 }
807 rd_left = 0;
808 if (NULL != typestring)
809 type = GNUNET_GNSRECORD_typename_to_number (typestring);
810 else
811 type = GNUNET_GNSRECORD_TYPE_ANY;
812 for (unsigned int i = 0; i < rd_count; i++)
813 {
814 vs = NULL;
815 if (! (((GNUNET_GNSRECORD_TYPE_ANY == type) ||
816 (rd[i].record_type == type)) &&
817 ((NULL == value) ||
818 (NULL ==
819 (vs = (GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
820 rd[i].data,
821 rd[i].data_size)))) ||
822 (0 == strcmp (vs, value)))))
823 rdx[rd_left++] = rd[i];
824 GNUNET_free (vs);
825 }
826 if (rd_count == rd_left)
827 {
828 /* nothing got deleted */
829 fprintf (
830 stderr,
831 _ (
832 "There are no records under label `%s' that match the request for deletion.\n"),
833 label);
834 test_finished ();
835 return;
836 }
837 /* delete everything but what we copied to 'rdx' */
838 del_qe = GNUNET_NAMESTORE_records_store (ns,
839 &zone_pkey,
840 name,
841 rd_left,
842 rdx,
843 &del_continuation,
844 NULL);
845}
846
847
848/**
849 * Parse expiration time.
850 *
851 * @param expirationstring text to parse
852 * @param etime_is_rel[out] set to #GNUNET_YES if time is relative
853 * @param etime[out] set to expiration time (abs or rel)
854 * @return #GNUNET_OK on success
855 */
856static int
857parse_expiration (const char *expirationstring,
858 int *etime_is_rel,
859 uint64_t *etime)
860{
861 struct GNUNET_TIME_Relative etime_rel;
862 struct GNUNET_TIME_Absolute etime_abs;
863
864 if (0 == strcmp (expirationstring, "never"))
865 {
866 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
867 *etime_is_rel = GNUNET_NO;
868 return GNUNET_OK;
869 }
870 if (GNUNET_OK ==
871 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
872 {
873 *etime_is_rel = GNUNET_YES;
874 *etime = etime_rel.rel_value_us;
875 if (GNUNET_TIME_relative_cmp (etime_rel, <, WARN_RELATIVE_EXPIRATION_LIMIT))
876 {
877 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
878 "Relative expiration times of less than %s are not recommended. To improve availability, consider increasing this value.\n",
879 GNUNET_STRINGS_relative_time_to_string (
880 WARN_RELATIVE_EXPIRATION_LIMIT, GNUNET_NO));
881 }
882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
883 "Storing record with relative expiration time of %s\n",
884 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
885 return GNUNET_OK;
886 }
887 if (GNUNET_OK ==
888 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
889 {
890 *etime_is_rel = GNUNET_NO;
891 *etime = etime_abs.abs_value_us;
892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
893 "Storing record with absolute expiration time of %s\n",
894 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
895 return GNUNET_OK;
896 }
897 return GNUNET_SYSERR;
898}
899
900
901/**
902 * Function called when namestore is done with the replace
903 * operation.
904 *
905 * @param cls NULL
906 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
907 * #GNUNET_NO if content was already there or not found
908 * #GNUNET_YES (or other positive value) on success
909 * @param emsg NULL on success, otherwise an error message
910 */
911static void
912replace_cont (void *cls, int success, const char *emsg)
913{
914 (void) cls;
915
916 set_qe = NULL;
917 if (GNUNET_OK != success)
918 {
919 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
920 _ ("Failed to replace records: %s\n"),
921 emsg);
922 ret = 1; /* fail from 'main' */
923 }
924 GNUNET_SCHEDULER_shutdown ();
925}
926
927
928/**
929 * We have obtained the zone's private key, so now process
930 * the main commands using it.
931 *
932 * @param cfg configuration to use
933 */
934static void
935run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
936{
937 struct GNUNET_GNSRECORD_Data rd;
938
939 if (! (add | del | list | (NULL != nickstring) | (NULL != uri)
940 | (NULL != reverse_pkey) | (NULL != recordset)))
941 {
942 /* nothing more to be done */
943 fprintf (stderr, _ ("No options given\n"));
944 GNUNET_SCHEDULER_shutdown ();
945 return;
946 }
947 ns = GNUNET_NAMESTORE_connect (cfg);
948 if (NULL == ns)
949 {
950 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
951 _ ("Failed to connect to namestore\n"));
952 return;
953 }
954
955 if (NULL != recordset)
956 {
957 /* replace entire record set */
958 unsigned int rd_count;
959 struct GNUNET_GNSRECORD_Data *rd;
960
961 if (NULL == name)
962 {
963 fprintf (stderr,
964 _ ("Missing option `%s' for operation `%s'\n"),
965 "-R",
966 _ ("replace"));
967 GNUNET_SCHEDULER_shutdown ();
968 ret = 1;
969 return;
970 }
971 rd_count = 0;
972 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
973 rd_count++;
974 rd = GNUNET_new_array (rd_count, struct GNUNET_GNSRECORD_Data);
975 rd_count = 0;
976 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
977 {
978 rd[rd_count] = e->record;
979 rd_count++;
980 }
981 set_qe = GNUNET_NAMESTORE_records_store (ns,
982 &zone_pkey,
983 name,
984 rd_count,
985 rd,
986 &replace_cont,
987 NULL);
988 GNUNET_free (rd);
989 return;
990 }
991 if (NULL != nickstring)
992 {
993 if (0 == strlen (nickstring))
994 {
995 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring);
996 GNUNET_SCHEDULER_shutdown ();
997 ret = 1;
998 return;
999 }
1000 add = 1;
1001 typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename (
1002 GNUNET_GNSRECORD_TYPE_NICK));
1003 name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT);
1004 value = GNUNET_strdup (nickstring);
1005 is_public = 0;
1006 expirationstring = GNUNET_strdup ("never");
1007 GNUNET_free (nickstring);
1008 nickstring = NULL;
1009 }
1010
1011 if (add)
1012 {
1013 if (NULL == name)
1014 {
1015 fprintf (stderr,
1016 _ ("Missing option `%s' for operation `%s'\n"),
1017 "-n",
1018 _ ("add"));
1019 GNUNET_SCHEDULER_shutdown ();
1020 ret = 1;
1021 return;
1022 }
1023 if (NULL == typestring)
1024 {
1025 fprintf (stderr,
1026 _ ("Missing option `%s' for operation `%s'\n"),
1027 "-t",
1028 _ ("add"));
1029 GNUNET_SCHEDULER_shutdown ();
1030 ret = 1;
1031 return;
1032 }
1033 type = GNUNET_GNSRECORD_typename_to_number (typestring);
1034 if (UINT32_MAX == type)
1035 {
1036 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring);
1037 GNUNET_SCHEDULER_shutdown ();
1038 ret = 1;
1039 return;
1040 }
1041 if ((GNUNET_DNSPARSER_TYPE_SRV == type) ||
1042 (GNUNET_DNSPARSER_TYPE_TLSA == type) ||
1043 (GNUNET_DNSPARSER_TYPE_OPENPGPKEY == type))
1044 {
1045 fprintf (stderr,
1046 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"));
1047 fprintf (stderr, ", please use a `BOX' record instead\n");
1048 GNUNET_SCHEDULER_shutdown ();
1049 ret = 1;
1050 return;
1051 }
1052 if (NULL == value)
1053 {
1054 fprintf (stderr,
1055 _ ("Missing option `%s' for operation `%s'\n"),
1056 "-V",
1057 _ ("add"));
1058 ret = 1;
1059 GNUNET_SCHEDULER_shutdown ();
1060 return;
1061 }
1062 if (GNUNET_OK !=
1063 GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size))
1064 {
1065 fprintf (stderr,
1066 _ ("Value `%s' invalid for record type `%s'\n"),
1067 value,
1068 typestring);
1069 GNUNET_SCHEDULER_shutdown ();
1070 ret = 1;
1071 return;
1072 }
1073 if (NULL == expirationstring)
1074 {
1075 fprintf (stderr,
1076 _ ("Missing option `%s' for operation `%s'\n"),
1077 "-e",
1078 _ ("add"));
1079 GNUNET_SCHEDULER_shutdown ();
1080 ret = 1;
1081 return;
1082 }
1083 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1084 {
1085 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1086 GNUNET_SCHEDULER_shutdown ();
1087 ret = 1;
1088 return;
1089 }
1090 add_qe = GNUNET_NAMESTORE_records_lookup (ns,
1091 &zone_pkey,
1092 name,
1093 &add_error_cb,
1094 NULL,
1095 &get_existing_record,
1096 NULL);
1097 }
1098 if (del)
1099 {
1100 if (NULL == name)
1101 {
1102 fprintf (stderr,
1103 _ ("Missing option `%s' for operation `%s'\n"),
1104 "-n",
1105 _ ("del"));
1106 GNUNET_SCHEDULER_shutdown ();
1107 ret = 1;
1108 return;
1109 }
1110 del_qe = GNUNET_NAMESTORE_records_lookup (ns,
1111 &zone_pkey,
1112 name,
1113 &del_lookup_error_cb,
1114 NULL,
1115 &del_monitor,
1116 NULL);
1117 }
1118 if (list)
1119 {
1120 if (NULL != name)
1121 get_qe = GNUNET_NAMESTORE_records_lookup (ns,
1122 &zone_pkey,
1123 name,
1124 &lookup_error_cb,
1125 NULL,
1126 &display_record_lookup,
1127 NULL);
1128 else
1129 list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
1130 &zone_pkey,
1131 &zone_iteration_error_cb,
1132 NULL,
1133 &display_record_iterator,
1134 NULL,
1135 &zone_iteration_finished,
1136 NULL);
1137 }
1138 if (NULL != reverse_pkey)
1139 {
1140 struct GNUNET_IDENTITY_PublicKey pubkey;
1141
1142 if (GNUNET_OK !=
1143 GNUNET_IDENTITY_public_key_from_string (reverse_pkey,
1144 &pubkey))
1145 {
1146 fprintf (stderr,
1147 _ ("Invalid public key for reverse lookup `%s'\n"),
1148 reverse_pkey);
1149 GNUNET_SCHEDULER_shutdown ();
1150 }
1151 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns,
1152 &zone_pkey,
1153 &pubkey,
1154 &reverse_error_cb,
1155 NULL,
1156 &handle_reverse_lookup,
1157 NULL);
1158 }
1159 if (NULL != uri)
1160 {
1161 char sh[105];
1162 char sname[64];
1163 struct GNUNET_IDENTITY_PublicKey pkey;
1164
1165 memset (sh, 0, 105);
1166 memset (sname, 0, 64);
1167
1168 if ((2 != (sscanf (uri, "gnunet://gns/%58s/%63s", sh, sname))) ||
1169 (GNUNET_OK !=
1170 GNUNET_IDENTITY_public_key_from_string (sh, &pkey)))
1171 {
1172 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri);
1173 GNUNET_SCHEDULER_shutdown ();
1174 ret = 1;
1175 return;
1176 }
1177 if (NULL == expirationstring)
1178 {
1179 fprintf (stderr,
1180 _ ("Missing option `%s' for operation `%s'\n"),
1181 "-e",
1182 _ ("add"));
1183 GNUNET_SCHEDULER_shutdown ();
1184 ret = 1;
1185 return;
1186 }
1187 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1188 {
1189 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1190 GNUNET_SCHEDULER_shutdown ();
1191 ret = 1;
1192 return;
1193 }
1194 memset (&rd, 0, sizeof(rd));
1195 rd.data = &pkey;
1196 rd.data_size = GNUNET_IDENTITY_key_get_length (&pkey);
1197 rd.record_type = ntohl (pkey.type);
1198 rd.expiration_time = etime;
1199 if (GNUNET_YES == etime_is_rel)
1200 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1201 if (1 == is_shadow)
1202 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1203 add_qe_uri = GNUNET_NAMESTORE_records_store (ns,
1204 &zone_pkey,
1205 sname,
1206 1,
1207 &rd,
1208 &add_continuation,
1209 &add_qe_uri);
1210 }
1211 if (monitor)
1212 {
1213 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
1214 &zone_pkey,
1215 GNUNET_YES,
1216 &monitor_error_cb,
1217 NULL,
1218 &display_record_monitor,
1219 NULL,
1220 &sync_cb,
1221 NULL);
1222 }
1223}
1224
1225
1226/**
1227 * Callback invoked from identity service with ego information.
1228 * An @a ego of NULL means the ego was not found.
1229 *
1230 * @param cls closure with the configuration
1231 * @param ego an ego known to identity service, or NULL
1232 */
1233static void
1234identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
1235{
1236 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1237
1238 el = NULL;
1239
1240 if (NULL == ego)
1241 {
1242 if (NULL != ego_name)
1243 {
1244 fprintf (stderr,
1245 _ ("Ego `%s' not known to identity service\n"),
1246 ego_name);
1247 }
1248 GNUNET_SCHEDULER_shutdown ();
1249 ret = -1;
1250 return;
1251 }
1252 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1253 GNUNET_free (ego_name);
1254 ego_name = NULL;
1255 run_with_zone_pkey (cfg);
1256}
1257
1258
1259/**
1260 * Function called with the default ego to be used for GNS
1261 * operations. Used if the user did not specify a zone via
1262 * command-line or environment variables.
1263 *
1264 * @param cls NULL
1265 * @param ego default ego, NULL for none
1266 * @param ctx NULL
1267 * @param name unused
1268 */
1269static void
1270default_ego_cb (void *cls,
1271 struct GNUNET_IDENTITY_Ego *ego,
1272 void **ctx,
1273 const char *name)
1274{
1275 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1276
1277 (void) ctx;
1278 (void) name;
1279 get_default = NULL;
1280 if (NULL == ego)
1281 {
1282 fprintf (stderr,
1283 _ ("No default identity configured for `namestore' subsystem\n"
1284 "Run gnunet-identity -s namestore -e $NAME to set the default to $NAME\n"
1285 "Run gnunet-identity -d to get a list of choices for $NAME\n"));
1286 GNUNET_SCHEDULER_shutdown ();
1287 ret = -1;
1288 return;
1289 }
1290 else
1291 {
1292 identity_cb ((void *) cfg, ego);
1293 }
1294}
1295
1296
1297/**
1298 * Function called with ALL of the egos known to the
1299 * identity service, used on startup if the user did
1300 * not specify a zone on the command-line.
1301 * Once the iteration is done (@a ego is NULL), we
1302 * ask for the default ego for "namestore".
1303 *
1304 * @param cls a `struct GNUNET_CONFIGURATION_Handle`
1305 * @param ego an ego, NULL for end of iteration
1306 * @param ctx NULL
1307 * @param name name associated with @a ego
1308 */
1309static void
1310id_connect_cb (void *cls,
1311 struct GNUNET_IDENTITY_Ego *ego,
1312 void **ctx,
1313 const char *name)
1314{
1315 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1316
1317 (void) ctx;
1318 (void) name;
1319 if (NULL != ego)
1320 return;
1321 get_default =
1322 GNUNET_IDENTITY_get (idh, "namestore", &default_ego_cb, (void *) cfg);
1323}
1324
1325
1326/**
1327 * Main function that will be run.
1328 *
1329 * @param cls closure
1330 * @param args remaining command-line arguments
1331 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1332 * @param cfg configuration
1333 */
1334static void
1335run (void *cls,
1336 char *const *args,
1337 const char *cfgfile,
1338 const struct GNUNET_CONFIGURATION_Handle *cfg)
1339{
1340 const char *pkey_str;
1341
1342 (void) cls;
1343 (void) args;
1344 (void) cfgfile;
1345 if (NULL != args[0])
1346 GNUNET_log (
1347 GNUNET_ERROR_TYPE_WARNING,
1348 _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
1349 args[0]);
1350 if ((NULL != args[0]) && (NULL == uri))
1351 uri = GNUNET_strdup (args[0]);
1352
1353 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
1354 pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1355 if (NULL != pkey_str)
1356 {
1357 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str,
1358 strlen (pkey_str),
1359 &zone_pkey,
1360 sizeof(zone_pkey)))
1361 {
1362 fprintf (stderr,
1363 "Malformed private key `%s' in $%s\n",
1364 pkey_str,
1365 "GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1366 ret = 1;
1367 GNUNET_SCHEDULER_shutdown ();
1368 return;
1369 }
1370 run_with_zone_pkey (cfg);
1371 return;
1372 }
1373 if (NULL == ego_name)
1374 {
1375 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg);
1376 if (NULL == idh)
1377 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1378 ret = -1;
1379 return;
1380 }
1381 el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
1382}
1383
1384
1385/**
1386 * Command-line option parser function that allows the user to specify
1387 * a complete record as one argument for adding/removing. A pointer
1388 * to the head of the list of record sets must be passed as the "scls"
1389 * argument.
1390 *
1391 * @param ctx command line processor context
1392 * @param scls must be of type "struct GNUNET_FS_Uri **"
1393 * @param option name of the option (typically 'R')
1394 * @param value command line argument given; format is
1395 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
1396 * always given in seconds (without the unit),
1397 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
1398 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
1399 * value (in human-readable format)
1400 * @return #GNUNET_OK on success
1401 */
1402static int
1403multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1404 void *scls,
1405 const char *option,
1406 const char *value)
1407{
1408 struct RecordSetEntry **head = scls;
1409 struct RecordSetEntry *r;
1410 struct GNUNET_GNSRECORD_Data record;
1411 char *cp;
1412 char *tok;
1413 char *saveptr;
1414 int etime_is_rel;
1415 void *raw_data;
1416
1417 (void) ctx;
1418 (void) option;
1419 cp = GNUNET_strdup (value);
1420 tok = strtok_r (cp, " ", &saveptr);
1421 if (NULL == tok)
1422 {
1423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1424 _ ("Empty record line argument is not allowed.\n"));
1425 GNUNET_free (cp);
1426 return GNUNET_SYSERR;
1427 }
1428 {
1429 char *etime_in_s;
1430
1431 GNUNET_asprintf (&etime_in_s, "%s s", tok);
1432 if (GNUNET_OK !=
1433 parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
1434 {
1435 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1436 _ ("Invalid expiration time `%s' (must be without unit)\n"),
1437 tok);
1438 GNUNET_free (cp);
1439 GNUNET_free (etime_in_s);
1440 return GNUNET_SYSERR;
1441 }
1442 GNUNET_free (etime_in_s);
1443 }
1444 tok = strtok_r (NULL, " ", &saveptr);
1445 if (NULL == tok)
1446 {
1447 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1448 _ ("Missing entries in record line `%s'.\n"),
1449 value);
1450 GNUNET_free (cp);
1451 return GNUNET_SYSERR;
1452 }
1453 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
1454 if (UINT32_MAX == record.record_type)
1455 {
1456 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
1457 GNUNET_free (cp);
1458 return GNUNET_SYSERR;
1459 }
1460 tok = strtok_r (NULL, " ", &saveptr);
1461 if (NULL == tok)
1462 {
1463 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1464 _ ("Missing entries in record line `%s'.\n"),
1465 value);
1466 GNUNET_free (cp);
1467 return GNUNET_SYSERR;
1468 }
1469 record.flags = GNUNET_GNSRECORD_RF_NONE;
1470 if (etime_is_rel)
1471 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1472 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
1473 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1474 if (NULL != strchr (tok, (unsigned char) 's'))
1475 record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1476 /* find beginning of record value */
1477 tok = strchr (&value[tok - cp], (unsigned char) ' ');
1478 if (NULL == tok)
1479 {
1480 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1481 _ ("Missing entries in record line `%s'.\n"),
1482 value);
1483 GNUNET_free (cp);
1484 return GNUNET_SYSERR;
1485 }
1486 GNUNET_free (cp);
1487 tok++; /* skip space */
1488 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
1489 tok,
1490 &raw_data,
1491 &record.data_size))
1492 {
1493 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1494 _ ("Invalid record data for type %s: `%s'.\n"),
1495 GNUNET_GNSRECORD_number_to_typename (record.record_type),
1496 tok);
1497 return GNUNET_SYSERR;
1498 }
1499
1500 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
1501 r->next = *head;
1502 record.data = &r[1];
1503 memcpy (&r[1], raw_data, record.data_size);
1504 GNUNET_free (raw_data);
1505 r->record = record;
1506 *head = r;
1507 return GNUNET_OK;
1508}
1509
1510
1511/**
1512 * Allow user to specify keywords.
1513 *
1514 * @param shortName short name of the option
1515 * @param name long name of the option
1516 * @param argumentHelp help text for the option argument
1517 * @param description long help text for the option
1518 * @param[out] topKeywords set to the desired value
1519 */
1520struct GNUNET_GETOPT_CommandLineOption
1521multirecord_option (char shortName,
1522 const char *name,
1523 const char *argumentHelp,
1524 const char *description,
1525 struct RecordSetEntry **rs)
1526{
1527 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
1528 .name = name,
1529 .argumentHelp = argumentHelp,
1530 .description = description,
1531 .require_argument = 1,
1532 .processor =
1533 &multirecord_process,
1534 .scls = (void *) rs };
1535
1536 return clo;
1537}
1538
1539
1540/**
1541 * The main function for gnunet-namestore.
1542 *
1543 * @param argc number of arguments from the command line
1544 * @param argv command line arguments
1545 * @return 0 ok, 1 on error
1546 */
1547int
1548main (int argc, char *const *argv)
1549{
1550 struct GNUNET_GETOPT_CommandLineOption options[] =
1551 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
1552 GNUNET_GETOPT_option_flag ('d',
1553 "delete",
1554 gettext_noop ("delete record"),
1555 &del),
1556 GNUNET_GETOPT_option_flag ('D',
1557 "display",
1558 gettext_noop ("display records"),
1559 &list),
1560 GNUNET_GETOPT_option_string (
1561 'e',
1562 "expiration",
1563 "TIME",
1564 gettext_noop (
1565 "expiration time for record to use (for adding only), \"never\" is possible"),
1566 &expirationstring),
1567 GNUNET_GETOPT_option_string ('i',
1568 "nick",
1569 "NICKNAME",
1570 gettext_noop (
1571 "set the desired nick name for the zone"),
1572 &nickstring),
1573 GNUNET_GETOPT_option_flag ('m',
1574 "monitor",
1575 gettext_noop (
1576 "monitor changes in the namestore"),
1577 &monitor),
1578 GNUNET_GETOPT_option_string ('n',
1579 "name",
1580 "NAME",
1581 gettext_noop (
1582 "name of the record to add/delete/display"),
1583 &name),
1584 GNUNET_GETOPT_option_string ('r',
1585 "reverse",
1586 "PKEY",
1587 gettext_noop (
1588 "determine our name for the given PKEY"),
1589 &reverse_pkey),
1590 multirecord_option (
1591 'R',
1592 "replace",
1593 "RECORDLINE",
1594 gettext_noop (
1595 "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
1596 &recordset),
1597 GNUNET_GETOPT_option_string ('t',
1598 "type",
1599 "TYPE",
1600 gettext_noop (
1601 "type of the record to add/delete/display"),
1602 &typestring),
1603 GNUNET_GETOPT_option_string ('u',
1604 "uri",
1605 "URI",
1606 gettext_noop ("URI to import into our zone"),
1607 &uri),
1608 GNUNET_GETOPT_option_string ('V',
1609 "value",
1610 "VALUE",
1611 gettext_noop (
1612 "value of the record to add/delete"),
1613 &value),
1614 GNUNET_GETOPT_option_flag ('p',
1615 "public",
1616 gettext_noop ("create or list public record"),
1617 &is_public),
1618 GNUNET_GETOPT_option_flag (
1619 's',
1620 "shadow",
1621 gettext_noop (
1622 "create shadow record (only valid if all other records of the same type have expired"),
1623 &is_shadow),
1624 GNUNET_GETOPT_option_string ('z',
1625 "zone",
1626 "EGO",
1627 gettext_noop (
1628 "name of the ego controlling the zone"),
1629 &ego_name),
1630 GNUNET_GETOPT_OPTION_END };
1631 int lret;
1632
1633 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1634 return 2;
1635
1636 is_public = -1;
1637 is_shadow = -1;
1638 GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL);
1639 if (GNUNET_OK !=
1640 (lret = GNUNET_PROGRAM_run (argc,
1641 argv,
1642 "gnunet-namestore",
1643 _ ("GNUnet zone manipulation tool"),
1644 options,
1645 &run,
1646 NULL)))
1647 {
1648 GNUNET_free_nz ((void *) argv);
1649 // FIXME
1650 // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1651 return lret;
1652 }
1653 GNUNET_free_nz ((void *) argv);
1654 // FIXME
1655 // GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1656 return ret;
1657}
1658
1659
1660/* end of gnunet-namestore.c */
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c
deleted file mode 100644
index 6d3cc45ec..000000000
--- a/src/namestore/gnunet-service-namestore.c
+++ /dev/null
@@ -1,2401 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2014, 2018 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 namestore/gnunet-service-namestore.c
23 * @brief namestore 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_gns_service.h"
31#include "gnunet_namecache_service.h"
32#include "gnunet_namestore_service.h"
33#include "gnunet_namestore_plugin.h"
34#include "gnunet_statistics_service.h"
35#include "gnunet_signatures.h"
36#include "namestore.h"
37
38#define LOG_STRERROR_FILE(kind, syscall, filename) \
39 GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
40
41/**
42 * If a monitor takes more than 1 minute to process an event, print a warning.
43 */
44#define MONITOR_STALL_WARN_DELAY GNUNET_TIME_UNIT_MINUTES
45
46/**
47 * Size of the cache used by #get_nick_record()
48 */
49#define NC_SIZE 16
50
51/**
52 * A namestore client
53 */
54struct NamestoreClient;
55
56
57/**
58 * A namestore iteration operation.
59 */
60struct ZoneIteration
61{
62 /**
63 * Next element in the DLL
64 */
65 struct ZoneIteration *next;
66
67 /**
68 * Previous element in the DLL
69 */
70 struct ZoneIteration *prev;
71
72 /**
73 * Namestore client which intiated this zone iteration
74 */
75 struct NamestoreClient *nc;
76
77 /**
78 * The nick to add to the records
79 */
80 struct GNUNET_GNSRECORD_Data *nick;
81
82 /**
83 * Key of the zone we are iterating over.
84 */
85 struct GNUNET_IDENTITY_PrivateKey zone;
86
87 /**
88 * Last sequence number in the zone iteration used to address next
89 * result of the zone iteration in the store
90 *
91 * Initially set to 0.
92 * Updated in #zone_iterate_proc()
93 */
94 uint64_t seq;
95
96 /**
97 * The operation id for the zone iteration in the response for the client
98 */
99 uint32_t request_id;
100
101 /**
102 * Offset of the zone iteration used to address next result of the zone
103 * iteration in the store
104 *
105 * Initially set to 0 in #handle_iteration_start
106 * Incremented with by every call to #handle_iteration_next
107 */
108 uint32_t offset;
109
110 /**
111 * Number of pending cache operations triggered by this zone iteration which we
112 * need to wait for before allowing the client to continue.
113 */
114 unsigned int cache_ops;
115
116 /**
117 * Set to #GNUNET_YES if the last iteration exhausted the limit set by the
118 * client and we should send the #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
119 * message and free the data structure once @e cache_ops is zero.
120 */
121 int send_end;
122};
123
124/**
125 * A namestore client
126 */
127struct NamestoreClient
128{
129 /**
130 * The client
131 */
132 struct GNUNET_SERVICE_Client *client;
133
134 /**
135 * Message queue for transmission to @e client
136 */
137 struct GNUNET_MQ_Handle *mq;
138
139 /**
140 * Head of the DLL of
141 * Zone iteration operations in progress initiated by this client
142 */
143 struct ZoneIteration *op_head;
144
145 /**
146 * Tail of the DLL of
147 * Zone iteration operations in progress initiated by this client
148 */
149 struct ZoneIteration *op_tail;
150};
151
152
153/**
154 * A namestore monitor.
155 */
156struct ZoneMonitor
157{
158 /**
159 * Next element in the DLL
160 */
161 struct ZoneMonitor *next;
162
163 /**
164 * Previous element in the DLL
165 */
166 struct ZoneMonitor *prev;
167
168 /**
169 * Namestore client which intiated this zone monitor
170 */
171 struct NamestoreClient *nc;
172
173 /**
174 * Private key of the zone.
175 */
176 struct GNUNET_IDENTITY_PrivateKey zone;
177
178 /**
179 * Task active during initial iteration.
180 */
181 struct GNUNET_SCHEDULER_Task *task;
182
183 /**
184 * Task to warn about slow monitors.
185 */
186 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
187
188 /**
189 * Since when are we blocked on this monitor?
190 */
191 struct GNUNET_TIME_Absolute sa_waiting_start;
192
193 /**
194 * Last sequence number in the zone iteration used to address next
195 * result of the zone iteration in the store
196 *
197 * Initially set to 0.
198 * Updated in #monitor_iterate_cb()
199 */
200 uint64_t seq;
201
202 /**
203 * Current limit of how many more messages we are allowed
204 * to queue to this monitor.
205 */
206 uint64_t limit;
207
208 /**
209 * How many more requests may we receive from the iterator
210 * before it is at the limit we gave it? Will be below or
211 * equal to @e limit. The effective limit for monitor
212 * events is thus @e iteration_cnt - @e limit!
213 */
214 uint64_t iteration_cnt;
215
216 /**
217 * Are we (still) in the initial iteration pass?
218 */
219 int in_first_iteration;
220
221 /**
222 * Is there a store activity waiting for this monitor? We only raise the
223 * flag when it happens and search the DLL for the store activity when we
224 * had a limit increase. If we cannot find any waiting store activity at
225 * that time, we clear the flag again.
226 */
227 int sa_waiting;
228};
229
230
231/**
232 * Pending operation on the namecache.
233 */
234struct CacheOperation
235{
236 /**
237 * Kept in a DLL.
238 */
239 struct CacheOperation *prev;
240
241 /**
242 * Kept in a DLL.
243 */
244 struct CacheOperation *next;
245
246 /**
247 * Handle to namecache queue.
248 */
249 struct GNUNET_NAMECACHE_QueueEntry *qe;
250
251 /**
252 * Client to notify about the result, can be NULL.
253 */
254 struct NamestoreClient *nc;
255
256 /**
257 * Zone iteration to call #zone_iteration_done_client_continue()
258 * for if applicable, can be NULL.
259 */
260 struct ZoneIteration *zi;
261
262 /**
263 * Client's request ID.
264 */
265 uint32_t rid;
266};
267
268
269/**
270 * Information for an ongoing #handle_record_store() operation.
271 * Needed as we may wait for monitors to be ready for the notification.
272 */
273struct StoreActivity
274{
275 /**
276 * Kept in a DLL.
277 */
278 struct StoreActivity *next;
279
280 /**
281 * Kept in a DLL.
282 */
283 struct StoreActivity *prev;
284
285 /**
286 * Which client triggered the store activity?
287 */
288 struct NamestoreClient *nc;
289
290 /**
291 * Copy of the original store message (as data fields in @e rd will
292 * point into it!).
293 */
294 const struct RecordStoreMessage *rsm;
295
296 /**
297 * Next zone monitor that still needs to be notified about this PUT.
298 */
299 struct ZoneMonitor *zm_pos;
300
301 /**
302 * Label nicely canonicalized (lower case).
303 */
304 char *conv_name;
305};
306
307
308/**
309 * Entry in list of cached nick resolutions.
310 */
311struct NickCache
312{
313 /**
314 * Zone the cache entry is for.
315 */
316 struct GNUNET_IDENTITY_PrivateKey zone;
317
318 /**
319 * Cached record data.
320 */
321 struct GNUNET_GNSRECORD_Data *rd;
322
323 /**
324 * Timestamp when this cache entry was used last.
325 */
326 struct GNUNET_TIME_Absolute last_used;
327};
328
329
330/**
331 * We cache nick records to reduce DB load.
332 */
333static struct NickCache nick_cache[NC_SIZE];
334
335/**
336 * Public key of all zeros.
337 */
338static const struct GNUNET_IDENTITY_PrivateKey zero;
339
340/**
341 * Configuration handle.
342 */
343static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
344
345/**
346 * Handle to the statistics service
347 */
348static struct GNUNET_STATISTICS_Handle *statistics;
349
350/**
351 * Namecache handle.
352 */
353static struct GNUNET_NAMECACHE_Handle *namecache;
354
355/**
356 * Database handle
357 */
358static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
359
360/**
361 * Name of the database plugin
362 */
363static char *db_lib_name;
364
365/**
366 * Head of cop DLL.
367 */
368static struct CacheOperation *cop_head;
369
370/**
371 * Tail of cop DLL.
372 */
373static struct CacheOperation *cop_tail;
374
375/**
376 * First active zone monitor.
377 */
378static struct ZoneMonitor *monitor_head;
379
380/**
381 * Last active zone monitor.
382 */
383static struct ZoneMonitor *monitor_tail;
384
385/**
386 * Head of DLL of monitor-blocked store activities.
387 */
388static struct StoreActivity *sa_head;
389
390/**
391 * Tail of DLL of monitor-blocked store activities.
392 */
393static struct StoreActivity *sa_tail;
394
395/**
396 * Notification context shared by all monitors.
397 */
398static struct GNUNET_NotificationContext *monitor_nc;
399
400/**
401 * Optimize block insertion by caching map of private keys to
402 * public keys in memory?
403 */
404static int cache_keys;
405
406/**
407 * Use the namecache? Doing so creates additional cryptographic
408 * operations whenever we touch a record.
409 */
410static int disable_namecache;
411
412
413/**
414 * Task run during shutdown.
415 *
416 * @param cls unused
417 */
418static void
419cleanup_task (void *cls)
420{
421 struct CacheOperation *cop;
422
423 (void) cls;
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
425 while (NULL != (cop = cop_head))
426 {
427 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
428 "Aborting incomplete namecache operation\n");
429 GNUNET_NAMECACHE_cancel (cop->qe);
430 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
431 GNUNET_free (cop);
432 }
433
434 if (NULL != namecache)
435 {
436 GNUNET_NAMECACHE_disconnect (namecache);
437 namecache = NULL;
438 }
439 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, GSN_database));
440 GNUNET_free (db_lib_name);
441 db_lib_name = NULL;
442 if (NULL != monitor_nc)
443 {
444 GNUNET_notification_context_destroy (monitor_nc);
445 monitor_nc = NULL;
446 }
447 if (NULL != statistics)
448 {
449 GNUNET_STATISTICS_destroy (statistics, GNUNET_NO);
450 statistics = NULL;
451 }
452}
453
454
455/**
456 * Release memory used by @a sa.
457 *
458 * @param sa activity to free
459 */
460static void
461free_store_activity (struct StoreActivity *sa)
462{
463 GNUNET_CONTAINER_DLL_remove (sa_head, sa_tail, sa);
464 GNUNET_free (sa->conv_name);
465 GNUNET_free (sa);
466}
467
468
469/**
470 * Function called with the records for the #GNUNET_GNS_EMPTY_LABEL_AT
471 * label in the zone. Used to locate the #GNUNET_GNSRECORD_TYPE_NICK
472 * record, which (if found) is then copied to @a cls for future use.
473 *
474 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
475 * @param seq sequence number of the record, MUST NOT BE ZERO
476 * @param private_key the private key of the zone (unused)
477 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
478 * @param rd_count number of records in @a rd
479 * @param rd records stored under @a label in the zone
480 */
481static void
482lookup_nick_it (void *cls,
483 uint64_t seq,
484 const struct GNUNET_IDENTITY_PrivateKey *private_key,
485 const char *label,
486 unsigned int rd_count,
487 const struct GNUNET_GNSRECORD_Data *rd)
488{
489 struct GNUNET_GNSRECORD_Data **res = cls;
490
491 (void) private_key;
492 GNUNET_assert (0 != seq);
493 if (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT))
494 {
495 GNUNET_break (0);
496 return;
497 }
498 for (unsigned int c = 0; c < rd_count; c++)
499 {
500 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
501 {
502 (*res) =
503 GNUNET_malloc (rd[c].data_size + sizeof(struct GNUNET_GNSRECORD_Data));
504 (*res)->data = &(*res)[1];
505 GNUNET_memcpy ((void *) (*res)->data, rd[c].data, rd[c].data_size);
506 (*res)->data_size = rd[c].data_size;
507 (*res)->expiration_time = rd[c].expiration_time;
508 (*res)->flags = rd[c].flags;
509 (*res)->record_type = GNUNET_GNSRECORD_TYPE_NICK;
510 return;
511 }
512 }
513 (*res) = NULL;
514}
515
516
517/**
518 * Add entry to the cache for @a zone and @a nick
519 *
520 * @param zone zone key to cache under
521 * @param nick nick entry to cache
522 */
523static void
524cache_nick (const struct GNUNET_IDENTITY_PrivateKey *zone,
525 const struct GNUNET_GNSRECORD_Data *nick)
526{
527 struct NickCache *oldest;
528
529 oldest = NULL;
530 for (unsigned int i = 0; i < NC_SIZE; i++)
531 {
532 struct NickCache *pos = &nick_cache[i];
533
534 if ((NULL == oldest) ||
535 (oldest->last_used.abs_value_us > pos->last_used.abs_value_us))
536 oldest = pos;
537 if (0 == GNUNET_memcmp (zone, &pos->zone))
538 {
539 oldest = pos;
540 break;
541 }
542 }
543 GNUNET_free (oldest->rd);
544 oldest->zone = *zone;
545 if (NULL != nick)
546 {
547 oldest->rd = GNUNET_malloc (sizeof(*nick) + nick->data_size);
548 *oldest->rd = *nick;
549 oldest->rd->data = &oldest->rd[1];
550 memcpy (&oldest->rd[1], nick->data, nick->data_size);
551 }
552 else
553 {
554 oldest->rd = NULL;
555 }
556 oldest->last_used = GNUNET_TIME_absolute_get ();
557}
558
559
560/**
561 * Return the NICK record for the zone (if it exists).
562 *
563 * @param zone private key for the zone to look for nick
564 * @return NULL if no NICK record was found
565 */
566static struct GNUNET_GNSRECORD_Data *
567get_nick_record (const struct GNUNET_IDENTITY_PrivateKey *zone)
568{
569 struct GNUNET_IDENTITY_PublicKey pub;
570 struct GNUNET_GNSRECORD_Data *nick;
571 int res;
572
573 /* check cache first */
574 for (unsigned int i = 0; i < NC_SIZE; i++)
575 {
576 struct NickCache *pos = &nick_cache[i];
577 if ((NULL != pos->rd) && (0 == GNUNET_memcmp (zone, &pos->zone)))
578 {
579 if (NULL == pos->rd)
580 return NULL;
581 nick = GNUNET_malloc (sizeof(*nick) + pos->rd->data_size);
582 *nick = *pos->rd;
583 nick->data = &nick[1];
584 memcpy (&nick[1], pos->rd->data, pos->rd->data_size);
585 pos->last_used = GNUNET_TIME_absolute_get ();
586 return nick;
587 }
588 }
589
590 nick = NULL;
591 res = GSN_database->lookup_records (GSN_database->cls,
592 zone,
593 GNUNET_GNS_EMPTY_LABEL_AT,
594 &lookup_nick_it,
595 &nick);
596 if ((GNUNET_OK != res) || (NULL == nick))
597 {
598#if ! defined(GNUNET_CULL_LOGGING)
599 static int do_log = GNUNET_LOG_CALL_STATUS;
600
601 if (0 == do_log)
602 do_log = GNUNET_get_log_call_status (GNUNET_ERROR_TYPE_DEBUG,
603 "namestore",
604 __FILE__,
605 __FUNCTION__,
606 __LINE__);
607 if (1 == do_log)
608 {
609 GNUNET_IDENTITY_key_get_public (zone, &pub);
610 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG | GNUNET_ERROR_TYPE_BULK,
611 "No nick name set for zone `%s'\n",
612 GNUNET_GNSRECORD_z2s (&pub));
613 }
614#endif
615 /* update cache */
616 cache_nick (zone, NULL);
617 return NULL;
618 }
619
620 /* update cache */
621 cache_nick (zone, nick);
622 return nick;
623}
624
625
626/**
627 * Merge the nick record @a nick_rd with the rest of the
628 * record set given in @a rd2. Store the result in @a rdc_res
629 * and @a rd_res. The @a nick_rd's expiration time is set to
630 * the maximum expiration time of all of the records in @a rd2.
631 *
632 * @param nick_rd the nick record to integrate
633 * @param rd2_length length of the @a rd2 array
634 * @param rd2 array of records
635 * @param rdc_res[out] length of the resulting @a rd_res array
636 * @param rd_res[out] set to an array of records,
637 * including @a nick_rd and @a rd2;
638 * all of the variable-size 'data' fields in @a rd2 are
639 * allocated in the same chunk of memory!
640 */
641static void
642merge_with_nick_records (const struct GNUNET_GNSRECORD_Data *nick_rd,
643 unsigned int rd2_length,
644 const struct GNUNET_GNSRECORD_Data *rd2,
645 unsigned int *rdc_res,
646 struct GNUNET_GNSRECORD_Data **rd_res)
647{
648 uint64_t latest_expiration;
649 size_t req;
650 char *data;
651 size_t data_offset;
652 struct GNUNET_GNSRECORD_Data *target;
653
654 (*rdc_res) = 1 + rd2_length;
655 if (0 == 1 + rd2_length)
656 {
657 GNUNET_break (0);
658 (*rd_res) = NULL;
659 return;
660 }
661 req = sizeof(struct GNUNET_GNSRECORD_Data) + nick_rd->data_size;
662 for (unsigned int i = 0; i < rd2_length; i++)
663 {
664 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
665
666 if (req + sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size < req)
667 {
668 GNUNET_break (0);
669 (*rd_res) = NULL;
670 return;
671 }
672 req += sizeof(struct GNUNET_GNSRECORD_Data) + orig->data_size;
673 }
674 target = GNUNET_malloc (req);
675 (*rd_res) = target;
676 data = (char *) &target[1 + rd2_length];
677 data_offset = 0;
678 latest_expiration = 0;
679 for (unsigned int i = 0; i < rd2_length; i++)
680 {
681 const struct GNUNET_GNSRECORD_Data *orig = &rd2[i];
682
683 if (0 != (orig->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
684 {
685 if ((GNUNET_TIME_absolute_get ().abs_value_us + orig->expiration_time) >
686 latest_expiration)
687 latest_expiration = orig->expiration_time;
688 }
689 else if (orig->expiration_time > latest_expiration)
690 latest_expiration = orig->expiration_time;
691 target[i] = *orig;
692 target[i].data = (void *) &data[data_offset];
693 GNUNET_memcpy (&data[data_offset], orig->data, orig->data_size);
694 data_offset += orig->data_size;
695 }
696 /* append nick */
697 target[rd2_length] = *nick_rd;
698 /* Mark as supplemental */
699 target[rd2_length].flags = nick_rd->flags | GNUNET_GNSRECORD_RF_SUPPLEMENTAL;
700 target[rd2_length].expiration_time = latest_expiration;
701 target[rd2_length].data = (void *) &data[data_offset];
702 GNUNET_memcpy (&data[data_offset], nick_rd->data, nick_rd->data_size);
703 data_offset += nick_rd->data_size;
704 GNUNET_assert (req == (sizeof(struct GNUNET_GNSRECORD_Data)) * (*rdc_res)
705 + data_offset);
706}
707
708
709/**
710 * Generate a `struct LookupNameResponseMessage` and send it to the
711 * given client using the given notification context.
712 *
713 * @param nc client to unicast to
714 * @param request_id request ID to use
715 * @param zone_key zone key of the zone
716 * @param name name
717 * @param rd_count number of records in @a rd
718 * @param rd array of records
719 */
720static void
721send_lookup_response (struct NamestoreClient *nc,
722 uint32_t request_id,
723 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
724 const char *name,
725 unsigned int rd_count,
726 const struct GNUNET_GNSRECORD_Data *rd)
727{
728 struct GNUNET_MQ_Envelope *env;
729 struct RecordResultMessage *zir_msg;
730 struct GNUNET_GNSRECORD_Data *nick;
731 struct GNUNET_GNSRECORD_Data *res;
732 unsigned int res_count;
733 size_t name_len;
734 ssize_t rd_ser_len;
735 char *name_tmp;
736 char *rd_ser;
737
738 nick = get_nick_record (zone_key);
739 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (rd_count, rd));
740
741 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
742 {
743 nick->flags =
744 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
745 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
746 }
747 else
748 {
749 res_count = rd_count;
750 res = (struct GNUNET_GNSRECORD_Data *) rd;
751 }
752 if (NULL != nick)
753 GNUNET_free (nick);
754
755 GNUNET_assert (-1 != GNUNET_GNSRECORD_records_get_size (res_count, res));
756
757
758 name_len = strlen (name) + 1;
759 rd_ser_len = GNUNET_GNSRECORD_records_get_size (res_count, res);
760 if (rd_ser_len < 0)
761 {
762 if (rd != res)
763 GNUNET_free (res);
764 GNUNET_break (0);
765 GNUNET_SERVICE_client_drop (nc->client);
766 return;
767 }
768 if (((size_t) rd_ser_len) >= UINT16_MAX - name_len - sizeof(*zir_msg))
769 {
770 if (rd != res)
771 GNUNET_free (res);
772 GNUNET_break (0);
773 GNUNET_SERVICE_client_drop (nc->client);
774 return;
775 }
776 env = GNUNET_MQ_msg_extra (zir_msg,
777 name_len + rd_ser_len,
778 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT);
779 zir_msg->gns_header.r_id = htonl (request_id);
780 zir_msg->name_len = htons (name_len);
781 zir_msg->rd_count = htons (res_count);
782 zir_msg->rd_len = htons ((uint16_t) rd_ser_len);
783 zir_msg->private_key = *zone_key;
784 name_tmp = (char *) &zir_msg[1];
785 GNUNET_memcpy (name_tmp, name, name_len);
786 rd_ser = &name_tmp[name_len];
787 GNUNET_assert (
788 rd_ser_len ==
789 GNUNET_GNSRECORD_records_serialize (res_count, res, rd_ser_len, rd_ser));
790 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
791 "Sending RECORD_RESULT message with %u records\n",
792 res_count);
793 GNUNET_STATISTICS_update (statistics,
794 "Record sets sent to clients",
795 1,
796 GNUNET_NO);
797 GNUNET_MQ_send (nc->mq, env);
798 if (rd != res)
799 GNUNET_free (res);
800}
801
802
803/**
804 * Send response to the store request to the client.
805 *
806 * @param client client to talk to
807 * @param res status of the operation
808 * @param rid client's request ID
809 */
810static void
811send_store_response (struct NamestoreClient *nc, int res, const char*emsg,
812 uint32_t rid)
813{
814 struct GNUNET_MQ_Envelope *env;
815 struct RecordStoreResponseMessage *rcr_msg;
816
817 GNUNET_assert (NULL != nc);
818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
819 "Sending RECORD_STORE_RESPONSE message\n");
820 GNUNET_STATISTICS_update (statistics,
821 "Store requests completed",
822 1,
823 GNUNET_NO);
824 env = GNUNET_MQ_msg_extra (rcr_msg,
825 (NULL != emsg) ? strlen (emsg) + 1 : 0,
826 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
827 rcr_msg->gns_header.r_id = htonl (rid);
828 rcr_msg->op_result = htonl (res);
829 rcr_msg->reserved = htons (0);
830 if (NULL != emsg)
831 {
832 rcr_msg->emsg_len = htons (strlen (emsg) + 1);
833 memcpy (&rcr_msg[1], emsg, strlen (emsg) + 1);
834 }
835 GNUNET_MQ_send (nc->mq, env);
836}
837
838
839/**
840 * Function called once we are done with the zone iteration and
841 * allow the zone iteration client to send us more messages.
842 *
843 * @param zi zone iteration we are processing
844 */
845static void
846zone_iteration_done_client_continue (struct ZoneIteration *zi)
847{
848 struct GNUNET_MQ_Envelope *env;
849 struct GNUNET_NAMESTORE_Header *em;
850
851 GNUNET_SERVICE_client_continue (zi->nc->client);
852 if (! zi->send_end)
853 return;
854 /* send empty response to indicate end of list */
855 env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
856 em->r_id = htonl (zi->request_id);
857 GNUNET_MQ_send (zi->nc->mq, env);
858
859 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi);
860 GNUNET_free (zi);
861}
862
863
864/**
865 * Cache operation complete, clean up.
866 *
867 * @param cls the `struct CacheOperation`
868 * @param success success
869 * @param emsg error messages
870 */
871static void
872finish_cache_operation (void *cls, int32_t success, const char *emsg)
873{
874 struct CacheOperation *cop = cls;
875 struct ZoneIteration *zi;
876
877 if (NULL != emsg)
878 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
879 _ ("Failed to replicate block in namecache: %s\n"),
880 emsg);
881 else
882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
883 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
884 if (NULL != cop->nc)
885 send_store_response (cop->nc, success, emsg, cop->rid);
886 if (NULL != (zi = cop->zi))
887 {
888 zi->cache_ops--;
889 if (0 == zi->cache_ops)
890 {
891 /* unchoke zone iteration, cache has caught up */
892 zone_iteration_done_client_continue (zi);
893 }
894 }
895 GNUNET_free (cop);
896}
897
898
899/**
900 * We just touched the plaintext information about a name in our zone;
901 * refresh the corresponding (encrypted) block in the namecache.
902 *
903 * @param nc client responsible for the request, can be NULL
904 * @param zi zone iteration response for the request, can be NULL
905 * @param rid request ID of the client
906 * @param zone_key private key of the zone
907 * @param name label for the records
908 * @param rd_count number of records
909 * @param rd records stored under the given @a name
910 */
911static void
912refresh_block (struct NamestoreClient *nc,
913 struct ZoneIteration *zi,
914 uint32_t rid,
915 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
916 const char *name,
917 unsigned int rd_count,
918 const struct GNUNET_GNSRECORD_Data *rd)
919{
920 struct GNUNET_GNSRECORD_Block *block;
921 struct GNUNET_GNSRECORD_Data rd_clean[rd_count];
922 struct CacheOperation *cop;
923 struct GNUNET_IDENTITY_PublicKey pkey;
924 struct GNUNET_GNSRECORD_Data *nick;
925 struct GNUNET_GNSRECORD_Data *res;
926 unsigned int res_count;
927 unsigned int rd_count_clean;
928 struct GNUNET_TIME_Absolute exp_time;
929
930 /** Do not block-cache tombstones */
931 rd_count_clean = 0;
932 for (int i = 0; i < rd_count; i++)
933 {
934 if (GNUNET_GNSRECORD_TYPE_TOMBSTONE == rd[i].record_type)
935 continue;
936 rd_clean[rd_count_clean++] = rd[i];
937 }
938
939 nick = get_nick_record (zone_key);
940 res_count = rd_count_clean;
941 res = (struct GNUNET_GNSRECORD_Data *) rd_clean; /* fixme: a bit unclean... */
942 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
943 {
944 nick->flags =
945 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
946 merge_with_nick_records (nick, rd_count_clean, rd_clean, &res_count, &res);
947 }
948 if (NULL != nick)
949 GNUNET_free (nick);
950 if (0 == res_count)
951 {
952 if (NULL != nc)
953 send_store_response (nc, GNUNET_OK, NULL, rid);
954 if (rd_clean != res)
955 GNUNET_free (res);
956 return; /* no data, no need to update cache */
957 }
958 if (GNUNET_YES == disable_namecache)
959 {
960 GNUNET_STATISTICS_update (statistics,
961 "Namecache updates skipped (NC disabled)",
962 1,
963 GNUNET_NO);
964 if (NULL != nc)
965 send_store_response (nc, GNUNET_OK, NULL, rid);
966 if (rd_clean != res)
967 GNUNET_free (res);
968 return;
969 }
970 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res,
971 GNUNET_TIME_UNIT_ZERO_ABS);
972 if (cache_keys)
973 GNUNET_assert (GNUNET_OK ==
974 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name,
975 res, res_count, &block));
976 else
977 GNUNET_assert (GNUNET_OK ==
978 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name,
979 res, res_count, &block));
980 GNUNET_assert (NULL != block);
981 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
982 GNUNET_log (
983 GNUNET_ERROR_TYPE_DEBUG,
984 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
985 name,
986 res_count,
987 GNUNET_STRINGS_absolute_time_to_string (exp_time),
988 GNUNET_GNSRECORD_z2s (&pkey));
989 GNUNET_STATISTICS_update (statistics,
990 "Namecache updates pushed",
991 1,
992 GNUNET_NO);
993 cop = GNUNET_new (struct CacheOperation);
994 cop->nc = nc;
995 cop->zi = zi;
996 if (NULL != zi)
997 zi->cache_ops ++;
998 cop->rid = rid;
999 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
1000 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
1001 block,
1002 &finish_cache_operation,
1003 cop);
1004 GNUNET_free (block);
1005 if (rd_clean != res)
1006 GNUNET_free (res);
1007}
1008
1009
1010/**
1011 * Print a warning that one of our monitors is no longer reacting.
1012 *
1013 * @param cls a `struct ZoneMonitor` to warn about
1014 */
1015static void
1016warn_monitor_slow (void *cls)
1017{
1018 struct ZoneMonitor *zm = cls;
1019
1020 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1021 "No response from monitor since %s\n",
1022 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
1023 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1024 &warn_monitor_slow,
1025 zm);
1026}
1027
1028
1029/**
1030 * Continue processing the @a sa.
1031 *
1032 * @param sa store activity to process
1033 */
1034static void
1035continue_store_activity (struct StoreActivity *sa)
1036{
1037 const struct RecordStoreMessage *rp_msg = sa->rsm;
1038 unsigned int rd_count;
1039 size_t name_len;
1040 size_t rd_ser_len;
1041 uint32_t rid;
1042 const char *name_tmp;
1043 const char *rd_ser;
1044
1045 rid = ntohl (rp_msg->gns_header.r_id);
1046 name_len = ntohs (rp_msg->name_len);
1047 rd_count = ntohs (rp_msg->rd_count);
1048 rd_ser_len = ntohs (rp_msg->rd_len);
1049 name_tmp = (const char *) &rp_msg[1];
1050 rd_ser = &name_tmp[name_len];
1051 {
1052 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1053
1054 /* We did this before, must succeed again */
1055 GNUNET_assert (
1056 GNUNET_OK ==
1057 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd));
1058
1059 for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
1060 {
1061 if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) &&
1062 (0 != GNUNET_memcmp (&zm->zone, &zero)))
1063 {
1064 sa->zm_pos = zm->next; /* not interesting to this monitor */
1065 continue;
1066 }
1067 if (zm->limit == zm->iteration_cnt)
1068 {
1069 zm->sa_waiting = GNUNET_YES;
1070 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1071 if (NULL != zm->sa_wait_warning)
1072 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1073 zm->sa_wait_warning =
1074 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1075 &warn_monitor_slow,
1076 zm);
1077 return; /* blocked on zone monitor */
1078 }
1079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1080 "Notifying monitor about changes under label `%s'\n",
1081 sa->conv_name);
1082 zm->limit--;
1083 send_lookup_response (zm->nc,
1084 0,
1085 &rp_msg->private_key,
1086 sa->conv_name,
1087 rd_count,
1088 rd);
1089 sa->zm_pos = zm->next;
1090 }
1091 /* great, done with the monitors, unpack (again) for refresh_block operation */
1092 refresh_block (sa->nc,
1093 NULL,
1094 rid,
1095 &rp_msg->private_key,
1096 sa->conv_name,
1097 rd_count,
1098 rd);
1099 }
1100 GNUNET_SERVICE_client_continue (sa->nc->client);
1101 free_store_activity (sa);
1102}
1103
1104
1105/**
1106 * Called whenever a client is disconnected.
1107 * Frees our resources associated with that client.
1108 *
1109 * @param cls closure
1110 * @param client identification of the client
1111 * @param app_ctx the `struct NamestoreClient` of @a client
1112 */
1113static void
1114client_disconnect_cb (void *cls,
1115 struct GNUNET_SERVICE_Client *client,
1116 void *app_ctx)
1117{
1118 struct NamestoreClient *nc = app_ctx;
1119 struct ZoneIteration *no;
1120 struct CacheOperation *cop;
1121
1122 (void) cls;
1123 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1124 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1125 {
1126 struct StoreActivity *san;
1127
1128 if (nc != zm->nc)
1129 continue;
1130 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1131 if (NULL != zm->task)
1132 {
1133 GNUNET_SCHEDULER_cancel (zm->task);
1134 zm->task = NULL;
1135 }
1136 if (NULL != zm->sa_wait_warning)
1137 {
1138 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1139 zm->sa_wait_warning = NULL;
1140 }
1141 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1142 {
1143 san = sa->next;
1144 if (zm == sa->zm_pos)
1145 {
1146 sa->zm_pos = zm->next;
1147 /* this may free sa */
1148 continue_store_activity (sa);
1149 }
1150 }
1151 GNUNET_free (zm);
1152 break;
1153 }
1154 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1155 {
1156 if (sa->nc == nc)
1157 {
1158 /* this may free sa */
1159 free_store_activity (sa);
1160 break; /* there can only be one per nc */
1161 }
1162 }
1163 while (NULL != (no = nc->op_head))
1164 {
1165 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
1166 GNUNET_free (no);
1167 }
1168 for (cop = cop_head; NULL != cop; cop = cop->next)
1169 if (nc == cop->nc)
1170 cop->nc = NULL;
1171 GNUNET_free (nc);
1172}
1173
1174
1175/**
1176 * Add a client to our list of active clients.
1177 *
1178 * @param cls NULL
1179 * @param client client to add
1180 * @param mq message queue for @a client
1181 * @return internal namestore client structure for this client
1182 */
1183static void *
1184client_connect_cb (void *cls,
1185 struct GNUNET_SERVICE_Client *client,
1186 struct GNUNET_MQ_Handle *mq)
1187{
1188 struct NamestoreClient *nc;
1189
1190 (void) cls;
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1192 nc = GNUNET_new (struct NamestoreClient);
1193 nc->client = client;
1194 nc->mq = mq;
1195 return nc;
1196}
1197
1198
1199/**
1200 * Closure for #lookup_it().
1201 */
1202struct RecordLookupContext
1203{
1204 /**
1205 * FIXME.
1206 */
1207 const char *label;
1208
1209 /**
1210 * FIXME.
1211 */
1212 char *res_rd;
1213
1214 /**
1215 * FIXME.
1216 */
1217 struct GNUNET_GNSRECORD_Data *nick;
1218
1219 /**
1220 * FIXME.
1221 */
1222 int found;
1223
1224 /**
1225 * FIXME.
1226 */
1227 unsigned int res_rd_count;
1228
1229 /**
1230 * FIXME.
1231 */
1232 ssize_t rd_ser_len;
1233};
1234
1235
1236/**
1237 * Function called by the namestore plugin when we are trying to lookup
1238 * a record as part of #handle_record_lookup(). Merges all results into
1239 * the context.
1240 *
1241 * @param cls closure with a `struct RecordLookupContext`
1242 * @param seq unique serial number of the record, MUST NOT BE ZERO
1243 * @param zone_key private key of the zone
1244 * @param label name that is being mapped (at most 255 characters long)
1245 * @param rd_count number of entries in @a rd array
1246 * @param rd array of records with data to store
1247 */
1248static void
1249lookup_it (void *cls,
1250 uint64_t seq,
1251 const struct GNUNET_IDENTITY_PrivateKey *private_key,
1252 const char *label,
1253 unsigned int rd_count,
1254 const struct GNUNET_GNSRECORD_Data *rd)
1255{
1256 struct RecordLookupContext *rlc = cls;
1257
1258 (void) private_key;
1259 GNUNET_assert (0 != seq);
1260 if (0 != strcmp (label, rlc->label))
1261 return;
1262 rlc->found = GNUNET_YES;
1263 if (0 == rd_count)
1264 {
1265 rlc->rd_ser_len = 0;
1266 rlc->res_rd_count = 0;
1267 rlc->res_rd = NULL;
1268 return;
1269 }
1270 if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1271 {
1272 /* Merge */
1273 struct GNUNET_GNSRECORD_Data *rd_res;
1274 unsigned int rdc_res;
1275
1276 rd_res = NULL;
1277 rdc_res = 0;
1278 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1279 ^ GNUNET_GNSRECORD_RF_PRIVATE;
1280 merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1281 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1282 if (rlc->rd_ser_len < 0)
1283 {
1284 GNUNET_break (0);
1285 GNUNET_free (rd_res);
1286 rlc->found = GNUNET_NO;
1287 rlc->rd_ser_len = 0;
1288 return;
1289 }
1290 rlc->res_rd_count = rdc_res;
1291 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1292 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1293 rd_res,
1294 rlc->rd_ser_len,
1295 rlc->res_rd))
1296 {
1297 GNUNET_break (0);
1298 GNUNET_free (rlc->res_rd);
1299 rlc->res_rd = NULL;
1300 rlc->res_rd_count = 0;
1301 rlc->rd_ser_len = 0;
1302 GNUNET_free (rd_res);
1303 rlc->found = GNUNET_NO;
1304 return;
1305 }
1306 GNUNET_free (rd_res);
1307 GNUNET_free (rlc->nick);
1308 rlc->nick = NULL;
1309 }
1310 else
1311 {
1312 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1313 if (rlc->rd_ser_len < 0)
1314 {
1315 GNUNET_break (0);
1316 rlc->found = GNUNET_NO;
1317 rlc->rd_ser_len = 0;
1318 return;
1319 }
1320 rlc->res_rd_count = rd_count;
1321 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1322 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1323 rd,
1324 rlc->rd_ser_len,
1325 rlc->res_rd))
1326 {
1327 GNUNET_break (0);
1328 GNUNET_free (rlc->res_rd);
1329 rlc->res_rd = NULL;
1330 rlc->res_rd_count = 0;
1331 rlc->rd_ser_len = 0;
1332 rlc->found = GNUNET_NO;
1333 return;
1334 }
1335 }
1336}
1337
1338
1339/**
1340 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1341 *
1342 * @param cls client sending the message
1343 * @param ll_msg message of type `struct LabelLookupMessage`
1344 * @return #GNUNET_OK if @a ll_msg is well-formed
1345 */
1346static int
1347check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1348{
1349 uint32_t name_len;
1350 size_t src_size;
1351
1352 (void) cls;
1353 name_len = ntohl (ll_msg->label_len);
1354 src_size = ntohs (ll_msg->gns_header.header.size);
1355 if (name_len != src_size - sizeof(struct LabelLookupMessage))
1356 {
1357 GNUNET_break (0);
1358 return GNUNET_SYSERR;
1359 }
1360 GNUNET_MQ_check_zero_termination (ll_msg);
1361 return GNUNET_OK;
1362}
1363
1364
1365/**
1366 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1367 *
1368 * @param cls client sending the message
1369 * @param ll_msg message of type `struct LabelLookupMessage`
1370 */
1371static void
1372handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1373{
1374 struct NamestoreClient *nc = cls;
1375 struct GNUNET_MQ_Envelope *env;
1376 struct LabelLookupResponseMessage *llr_msg;
1377 struct RecordLookupContext rlc;
1378 const char *name_tmp;
1379 char *res_name;
1380 char *conv_name;
1381 uint32_t name_len;
1382 int res;
1383
1384 name_tmp = (const char *) &ll_msg[1];
1385 GNUNET_SERVICE_client_continue (nc->client);
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1387 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1388 name_tmp);
1389
1390 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1391 if (NULL == conv_name)
1392 {
1393 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1394 "Error converting name `%s'\n",
1395 name_tmp);
1396 GNUNET_SERVICE_client_drop (nc->client);
1397 return;
1398 }
1399 name_len = strlen (conv_name) + 1;
1400 rlc.label = conv_name;
1401 rlc.found = GNUNET_NO;
1402 rlc.res_rd_count = 0;
1403 rlc.res_rd = NULL;
1404 rlc.rd_ser_len = 0;
1405 rlc.nick = get_nick_record (&ll_msg->zone);
1406 res = GSN_database->lookup_records (GSN_database->cls,
1407 &ll_msg->zone,
1408 conv_name,
1409 &lookup_it,
1410 &rlc);
1411 env =
1412 GNUNET_MQ_msg_extra (llr_msg,
1413 name_len + rlc.rd_ser_len,
1414 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1415 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1416 llr_msg->private_key = ll_msg->zone;
1417 llr_msg->name_len = htons (name_len);
1418 llr_msg->rd_count = htons (rlc.res_rd_count);
1419 llr_msg->rd_len = htons (rlc.rd_ser_len);
1420 res_name = (char *) &llr_msg[1];
1421 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1422 llr_msg->found = htons (GNUNET_YES);
1423 else
1424 llr_msg->found = htons (GNUNET_NO);
1425 GNUNET_memcpy (&llr_msg[1], conv_name, name_len);
1426 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1427 GNUNET_MQ_send (nc->mq, env);
1428 GNUNET_free (rlc.res_rd);
1429 GNUNET_free (conv_name);
1430}
1431
1432
1433
1434/**
1435 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1436 *
1437 * @param cls client sending the message
1438 * @param rp_msg message of type `struct RecordStoreMessage`
1439 * @return #GNUNET_OK if @a rp_msg is well-formed
1440 */
1441static int
1442check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1443{
1444 size_t name_len;
1445 size_t msg_size;
1446 size_t msg_size_exp;
1447 size_t rd_ser_len;
1448 const char *name_tmp;
1449
1450 (void) cls;
1451 name_len = ntohs (rp_msg->name_len);
1452 msg_size = ntohs (rp_msg->gns_header.header.size);
1453 rd_ser_len = ntohs (rp_msg->rd_len);
1454 msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len;
1455 if (msg_size != msg_size_exp)
1456 {
1457 GNUNET_break (0);
1458 return GNUNET_SYSERR;
1459 }
1460 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1461 {
1462 GNUNET_break (0);
1463 return GNUNET_SYSERR;
1464 }
1465 name_tmp = (const char *) &rp_msg[1];
1466 if ('\0' != name_tmp[name_len - 1])
1467 {
1468 GNUNET_break (0);
1469 return GNUNET_SYSERR;
1470 }
1471 return GNUNET_OK;
1472}
1473
1474
1475/**
1476 * Check if set contains a tombstone, store if necessary
1477 *
1478 * @param cls a `struct GNUNET_GNSRECORD_Data **` for storing the nick (if found)
1479 * @param seq sequence number of the record, MUST NOT BE ZERO
1480 * @param private_key the private key of the zone (unused)
1481 * @param label should be #GNUNET_GNS_EMPTY_LABEL_AT
1482 * @param rd_count number of records in @a rd
1483 * @param rd records stored under @a label in the zone
1484 */
1485static void
1486get_block_exp_existing (void *cls,
1487 uint64_t seq,
1488 const struct
1489 GNUNET_IDENTITY_PrivateKey *private_key,
1490 const char *label,
1491 unsigned int rd_count,
1492 const struct GNUNET_GNSRECORD_Data *rd)
1493{
1494 struct GNUNET_TIME_Absolute *exp = cls;
1495 struct GNUNET_GNSRECORD_Data rd_pub[rd_count];
1496 unsigned int rd_pub_count;
1497 char *emsg;
1498
1499 if (GNUNET_OK != GNUNET_GNSRECORD_convert_records_for_export (label,
1500 rd,
1501 rd_count,
1502 rd_pub,
1503 &rd_pub_count,
1504 exp,
1505 &emsg))
1506 {
1507 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1508 "%s\n", emsg);
1509 GNUNET_free (emsg);
1510 }
1511}
1512
1513
1514/**
1515 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1516 *
1517 * @param cls client sending the message
1518 * @param rp_msg message of type `struct RecordStoreMessage`
1519 */
1520static void
1521handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1522{
1523 struct NamestoreClient *nc = cls;
1524 size_t name_len;
1525 size_t rd_ser_len;
1526 uint32_t rid;
1527 const char *name_tmp;
1528 char *conv_name;
1529 const char *rd_ser;
1530 unsigned int rd_count;
1531 int res;
1532 struct StoreActivity *sa;
1533 struct GNUNET_TIME_Absolute existing_block_exp;
1534 struct GNUNET_TIME_Absolute new_block_exp;
1535
1536 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1537 "Received NAMESTORE_RECORD_STORE message\n");
1538 existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1539 new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS;
1540 rid = ntohl (rp_msg->gns_header.r_id);
1541 name_len = ntohs (rp_msg->name_len);
1542 rd_count = ntohs (rp_msg->rd_count);
1543 rd_ser_len = ntohs (rp_msg->rd_len);
1544 name_tmp = (const char *) &rp_msg[1];
1545 rd_ser = &name_tmp[name_len];
1546 {
1547 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1548 char *emsg;
1549
1550 /* Extracting and converting private key */
1551 conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp);
1552 if (NULL == conv_name)
1553 {
1554 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1555 "Error normalizing name `%s'\n",
1556 name_tmp);
1557 send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."),
1558 rid);
1559 GNUNET_SERVICE_client_continue (nc->client);
1560 return;
1561 }
1562
1563 /* Check name for validity */
1564 if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg))
1565 {
1566 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1567 "Label invalid: `%s'\n",
1568 emsg);
1569 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1570 GNUNET_free (emsg);
1571 GNUNET_free (conv_name);
1572 GNUNET_SERVICE_client_continue (nc->client);
1573 return;
1574 }
1575
1576 if (GNUNET_OK !=
1577 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1578 {
1579 send_store_response (nc, GNUNET_SYSERR,
1580 _ ("Error deserializing records."), rid);
1581 GNUNET_free (conv_name);
1582 GNUNET_SERVICE_client_continue (nc->client);
1583 return;
1584 }
1585
1586 GNUNET_STATISTICS_update (statistics,
1587 "Well-formed store requests received",
1588 1,
1589 GNUNET_NO);
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1591 "Creating %u records for name `%s'\n",
1592 (unsigned int) rd_count,
1593 conv_name);
1594 if ((GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1595 &rp_msg->private_key,
1596 conv_name,
1597 &get_block_exp_existing,
1598 &existing_block_exp)) &&
1599 (rd_count == 0))
1600 {
1601 /* This name does not exist, so cannot be removed */
1602 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1603 "Name `%s' does not exist, no deletion required\n",
1604 conv_name);
1605 res = GNUNET_NO;
1606 }
1607 else
1608 {
1609 /* remove "NICK" records, unless this is for the
1610 #GNUNET_GNS_EMPTY_LABEL_AT label
1611 We may need one additional record later for tombstone.
1612 FIXME: Since we must normalize the record set (check for
1613 consistency etc) we have to iterate the set twice.
1614 May be inefficient.
1615 We cannot really move the nick caching into GNSRECORD.
1616 */
1617 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1618 struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1];
1619 unsigned int rd_clean_off;
1620 unsigned int rd_nf_count;
1621 char *emsg;
1622 int have_nick;
1623
1624 rd_clean_off = 0;
1625 have_nick = GNUNET_NO;
1626 for (unsigned int i = 0; i < rd_count; i++)
1627 {
1628 rd_clean[rd_clean_off] = rd[i];
1629
1630 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1631 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1632 rd_clean_off++;
1633
1634 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1635 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1636 {
1637 cache_nick (&rp_msg->private_key, &rd[i]);
1638 have_nick = GNUNET_YES;
1639 }
1640 }
1641 if (GNUNET_OK != GNUNET_GNSRECORD_normalize_record_set (conv_name,
1642 rd_clean,
1643 rd_clean_off,
1644 rd_nf,
1645 &rd_nf_count,
1646 &new_block_exp,
1647 GNUNET_YES,
1648 &emsg))
1649 {
1650 send_store_response (nc, GNUNET_SYSERR, emsg, rid);
1651 GNUNET_free (emsg);
1652 GNUNET_SERVICE_client_continue (nc->client);
1653 GNUNET_free (conv_name);
1654 return;
1655 }
1656 /*
1657 * If existing_block_exp is 0, then there was not record set
1658 * and no tombstone.
1659 * Otherwise, if the existing block expiration is after the
1660 * new block expiration would be, we need to add a tombstone
1661 * or update it.
1662 */
1663 if (GNUNET_TIME_absolute_cmp (new_block_exp, <=, existing_block_exp))
1664 {
1665 rd_nf[rd_nf_count].record_type = GNUNET_GNSRECORD_TYPE_TOMBSTONE;
1666 rd_nf[rd_nf_count].expiration_time =
1667 existing_block_exp.abs_value_us;
1668 rd_nf[rd_nf_count].data = NULL;
1669 rd_nf[rd_nf_count].data_size = 0;
1670 rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE;
1671 rd_nf_count++;
1672 }
1673 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1674 (GNUNET_NO == have_nick))
1675 {
1676 /* remove nick record from cache, in case we have one there */
1677 cache_nick (&rp_msg->private_key, NULL);
1678 }
1679 res = GSN_database->store_records (GSN_database->cls,
1680 &rp_msg->private_key,
1681 conv_name,
1682 rd_nf_count,
1683 rd_nf);
1684 }
1685
1686 if (GNUNET_OK != res)
1687 {
1688 /* store not successful, no need to tell monitors */
1689 send_store_response (nc, res, _ ("Store failed"), rid);
1690 GNUNET_SERVICE_client_continue (nc->client);
1691 GNUNET_free (conv_name);
1692 return;
1693 }
1694 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1695 + ntohs (rp_msg->gns_header.header.size));
1696 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1697 sa->nc = nc;
1698 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1699 GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size));
1700 sa->zm_pos = monitor_head;
1701 sa->conv_name = conv_name;
1702 continue_store_activity (sa);
1703 }
1704}
1705
1706
1707/**
1708 * Context for record remove operations passed from #handle_zone_to_name to
1709 * #handle_zone_to_name_it as closure
1710 */
1711struct ZoneToNameCtx
1712{
1713 /**
1714 * Namestore client
1715 */
1716 struct NamestoreClient *nc;
1717
1718 /**
1719 * Request id (to be used in the response to the client).
1720 */
1721 uint32_t rid;
1722
1723 /**
1724 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1725 * not finding a name for the zone still counts as a 'success' here,
1726 * as this field is about the success of executing the IPC protocol.
1727 */
1728 int success;
1729};
1730
1731
1732/**
1733 * Zone to name iterator
1734 *
1735 * @param cls struct ZoneToNameCtx *
1736 * @param seq sequence number of the record, MUST NOT BE ZERO
1737 * @param zone_key the zone key
1738 * @param name name
1739 * @param rd_count number of records in @a rd
1740 * @param rd record data
1741 */
1742static void
1743handle_zone_to_name_it (void *cls,
1744 uint64_t seq,
1745 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1746 const char *name,
1747 unsigned int rd_count,
1748 const struct GNUNET_GNSRECORD_Data *rd)
1749{
1750 struct ZoneToNameCtx *ztn_ctx = cls;
1751 struct GNUNET_MQ_Envelope *env;
1752 struct ZoneToNameResponseMessage *ztnr_msg;
1753 int16_t res;
1754 size_t name_len;
1755 ssize_t rd_ser_len;
1756 size_t msg_size;
1757 char *name_tmp;
1758 char *rd_tmp;
1759
1760 GNUNET_assert (0 != seq);
1761 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1762 "Found result for zone-to-name lookup: `%s'\n",
1763 name);
1764 res = GNUNET_YES;
1765 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1766 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1767 if (rd_ser_len < 0)
1768 {
1769 GNUNET_break (0);
1770 ztn_ctx->success = GNUNET_SYSERR;
1771 return;
1772 }
1773 msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1774 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1775 {
1776 GNUNET_break (0);
1777 ztn_ctx->success = GNUNET_SYSERR;
1778 return;
1779 }
1780 env =
1781 GNUNET_MQ_msg_extra (ztnr_msg,
1782 name_len + rd_ser_len,
1783 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1784 ztnr_msg->gns_header.header.size = htons (msg_size);
1785 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1786 ztnr_msg->res = htons (res);
1787 ztnr_msg->rd_len = htons (rd_ser_len);
1788 ztnr_msg->rd_count = htons (rd_count);
1789 ztnr_msg->name_len = htons (name_len);
1790 ztnr_msg->zone = *zone_key;
1791 name_tmp = (char *) &ztnr_msg[1];
1792 GNUNET_memcpy (name_tmp, name, name_len);
1793 rd_tmp = &name_tmp[name_len];
1794 GNUNET_assert (
1795 rd_ser_len ==
1796 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
1797 ztn_ctx->success = GNUNET_OK;
1798 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
1799}
1800
1801
1802/**
1803 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1804 *
1805 * @param cls client client sending the message
1806 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1807 */
1808static void
1809handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1810{
1811 struct NamestoreClient *nc = cls;
1812 struct ZoneToNameCtx ztn_ctx;
1813 struct GNUNET_MQ_Envelope *env;
1814 struct ZoneToNameResponseMessage *ztnr_msg;
1815
1816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
1817 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1818 ztn_ctx.nc = nc;
1819 ztn_ctx.success = GNUNET_NO;
1820 if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls,
1821 &ztn_msg->zone,
1822 &ztn_msg->value_zone,
1823 &handle_zone_to_name_it,
1824 &ztn_ctx))
1825 {
1826 /* internal error, hang up instead of signalling something
1827 that might be wrong */
1828 GNUNET_break (0);
1829 GNUNET_SERVICE_client_drop (nc->client);
1830 return;
1831 }
1832 if (GNUNET_NO == ztn_ctx.success)
1833 {
1834 /* no result found, send empty response */
1835 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1836 "Found no result for zone-to-name lookup.\n");
1837 env = GNUNET_MQ_msg (ztnr_msg,
1838 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1839 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1840 ztnr_msg->res = htons (GNUNET_NO);
1841 GNUNET_MQ_send (nc->mq, env);
1842 }
1843 GNUNET_SERVICE_client_continue (nc->client);
1844}
1845
1846
1847/**
1848 * Context for record remove operations passed from
1849 * #run_zone_iteration_round to #zone_iterate_proc as closure
1850 */
1851struct ZoneIterationProcResult
1852{
1853 /**
1854 * The zone iteration handle
1855 */
1856 struct ZoneIteration *zi;
1857
1858 /**
1859 * Number of results left to be returned in this iteration.
1860 */
1861 uint64_t limit;
1862};
1863
1864
1865/**
1866 * Process results for zone iteration from database
1867 *
1868 * @param cls struct ZoneIterationProcResult
1869 * @param seq sequence number of the record, MUST NOT BE ZERO
1870 * @param zone_key the zone key
1871 * @param name name
1872 * @param rd_count number of records for this name
1873 * @param rd record data
1874 */
1875static void
1876zone_iterate_proc (void *cls,
1877 uint64_t seq,
1878 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1879 const char *name,
1880 unsigned int rd_count,
1881 const struct GNUNET_GNSRECORD_Data *rd)
1882{
1883 struct ZoneIterationProcResult *proc = cls;
1884 int do_refresh_block;
1885
1886 GNUNET_assert (0 != seq);
1887 if ((NULL == zone_key) && (NULL == name))
1888 {
1889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1890 return;
1891 }
1892 if ((NULL == zone_key) || (NULL == name))
1893 {
1894 /* what is this!? should never happen */
1895 GNUNET_break (0);
1896 return;
1897 }
1898 if (0 == proc->limit)
1899 {
1900 /* what is this!? should never happen */
1901 GNUNET_break (0);
1902 return;
1903 }
1904 proc->limit--;
1905 proc->zi->seq = seq;
1906 send_lookup_response (proc->zi->nc,
1907 proc->zi->request_id,
1908 zone_key,
1909 name,
1910 rd_count,
1911 rd);
1912
1913
1914 do_refresh_block = GNUNET_NO;
1915 for (unsigned int i = 0; i < rd_count; i++)
1916 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1917 {
1918 do_refresh_block = GNUNET_YES;
1919 break;
1920 }
1921 if (GNUNET_YES == do_refresh_block)
1922 refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd);
1923}
1924
1925
1926/**
1927 * Perform the next round of the zone iteration.
1928 *
1929 * @param zi zone iterator to process
1930 * @param limit number of results to return in one pass
1931 */
1932static void
1933run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1934{
1935 struct ZoneIterationProcResult proc;
1936 struct GNUNET_TIME_Absolute start;
1937 struct GNUNET_TIME_Relative duration;
1938
1939 memset (&proc, 0, sizeof(proc));
1940 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1941 "Asked to return up to %llu records at position %llu\n",
1942 (unsigned long long) limit,
1943 (unsigned long long) zi->seq);
1944 proc.zi = zi;
1945 proc.limit = limit;
1946 start = GNUNET_TIME_absolute_get ();
1947 GNUNET_break (GNUNET_SYSERR !=
1948 GSN_database->iterate_records (GSN_database->cls,
1949 (GNUNET_YES == GNUNET_is_zero (
1950 &zi->zone))
1951 ? NULL
1952 : &zi->zone,
1953 zi->seq,
1954 limit,
1955 &zone_iterate_proc,
1956 &proc));
1957 duration = GNUNET_TIME_absolute_get_duration (start);
1958 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1959 GNUNET_STATISTICS_set (statistics,
1960 "NAMESTORE iteration delay (μs/record)",
1961 duration.rel_value_us,
1962 GNUNET_NO);
1963 if (0 == proc.limit)
1964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1965 "Returned %llu results, more results available\n",
1966 (unsigned long long) limit);
1967 zi->send_end = (0 != proc.limit);
1968 if (0 == zi->cache_ops)
1969 zone_iteration_done_client_continue (zi);
1970}
1971
1972
1973/**
1974 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1975 *
1976 * @param cls the client sending the message
1977 * @param zis_msg message from the client
1978 */
1979static void
1980handle_iteration_start (void *cls,
1981 const struct ZoneIterationStartMessage *zis_msg)
1982{
1983 struct NamestoreClient *nc = cls;
1984 struct ZoneIteration *zi;
1985
1986 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1987 "Received ZONE_ITERATION_START message\n");
1988 zi = GNUNET_new (struct ZoneIteration);
1989 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1990 zi->offset = 0;
1991 zi->nc = nc;
1992 zi->zone = zis_msg->zone;
1993
1994 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1995 run_zone_iteration_round (zi, 1);
1996}
1997
1998
1999/**
2000 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
2001 *
2002 * @param cls the client sending the message
2003 * @param zis_msg message from the client
2004 */
2005static void
2006handle_iteration_stop (void *cls,
2007 const struct ZoneIterationStopMessage *zis_msg)
2008{
2009 struct NamestoreClient *nc = cls;
2010 struct ZoneIteration *zi;
2011 uint32_t rid;
2012
2013 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2014 "Received ZONE_ITERATION_STOP message\n");
2015 rid = ntohl (zis_msg->gns_header.r_id);
2016 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2017 if (zi->request_id == rid)
2018 break;
2019 if (NULL == zi)
2020 {
2021 GNUNET_break (0);
2022 GNUNET_SERVICE_client_drop (nc->client);
2023 return;
2024 }
2025 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
2026 GNUNET_free (zi);
2027 GNUNET_SERVICE_client_continue (nc->client);
2028}
2029
2030
2031/**
2032 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
2033 *
2034 * @param cls the client sending the message
2035 * @param message message from the client
2036 */
2037static void
2038handle_iteration_next (void *cls,
2039 const struct ZoneIterationNextMessage *zis_msg)
2040{
2041 struct NamestoreClient *nc = cls;
2042 struct ZoneIteration *zi;
2043 uint32_t rid;
2044 uint64_t limit;
2045
2046 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2047 "Received ZONE_ITERATION_NEXT message\n");
2048 GNUNET_STATISTICS_update (statistics,
2049 "Iteration NEXT messages received",
2050 1,
2051 GNUNET_NO);
2052 rid = ntohl (zis_msg->gns_header.r_id);
2053 limit = GNUNET_ntohll (zis_msg->limit);
2054 for (zi = nc->op_head; NULL != zi; zi = zi->next)
2055 if (zi->request_id == rid)
2056 break;
2057 if (NULL == zi)
2058 {
2059 GNUNET_break (0);
2060 GNUNET_SERVICE_client_drop (nc->client);
2061 return;
2062 }
2063 run_zone_iteration_round (zi, limit);
2064}
2065
2066
2067/**
2068 * Function called when the monitor is ready for more data, and we
2069 * should thus unblock PUT operations that were blocked on the
2070 * monitor not being ready.
2071 */
2072static void
2073monitor_unblock (struct ZoneMonitor *zm)
2074{
2075 struct StoreActivity *sa = sa_head;
2076
2077 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
2078 {
2079 struct StoreActivity *sn = sa->next;
2080
2081 if (sa->zm_pos == zm)
2082 continue_store_activity (sa);
2083 sa = sn;
2084 }
2085 if (zm->limit > zm->iteration_cnt)
2086 {
2087 zm->sa_waiting = GNUNET_NO;
2088 if (NULL != zm->sa_wait_warning)
2089 {
2090 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2091 zm->sa_wait_warning = NULL;
2092 }
2093 }
2094 else if (GNUNET_YES == zm->sa_waiting)
2095 {
2096 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2097 if (NULL != zm->sa_wait_warning)
2098 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2099 zm->sa_wait_warning =
2100 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2101 &warn_monitor_slow,
2102 zm);
2103 }
2104}
2105
2106
2107/**
2108 * Send 'sync' message to zone monitor, we're now in sync.
2109 *
2110 * @param zm monitor that is now in sync
2111 */
2112static void
2113monitor_sync (struct ZoneMonitor *zm)
2114{
2115 struct GNUNET_MQ_Envelope *env;
2116 struct GNUNET_MessageHeader *sync;
2117
2118 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
2119 GNUNET_MQ_send (zm->nc->mq, env);
2120 /* mark iteration done */
2121 zm->in_first_iteration = GNUNET_NO;
2122 zm->iteration_cnt = 0;
2123 if ((zm->limit > 0) && (zm->sa_waiting))
2124 monitor_unblock (zm);
2125}
2126
2127
2128/**
2129 * Obtain the next datum during the zone monitor's zone initial iteration.
2130 *
2131 * @param cls zone monitor that does its initial iteration
2132 */
2133static void
2134monitor_iteration_next (void *cls);
2135
2136
2137/**
2138 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2139 *
2140 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2141 * @param seq sequence number of the record, MUST NOT BE ZERO
2142 * @param zone_key zone key of the zone
2143 * @param name name
2144 * @param rd_count number of records in @a rd
2145 * @param rd array of records
2146 */
2147static void
2148monitor_iterate_cb (void *cls,
2149 uint64_t seq,
2150 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2151 const char *name,
2152 unsigned int rd_count,
2153 const struct GNUNET_GNSRECORD_Data *rd)
2154{
2155 struct ZoneMonitor *zm = cls;
2156
2157 GNUNET_assert (0 != seq);
2158 zm->seq = seq;
2159 GNUNET_assert (NULL != name);
2160 GNUNET_STATISTICS_update (statistics,
2161 "Monitor notifications sent",
2162 1,
2163 GNUNET_NO);
2164 zm->limit--;
2165 zm->iteration_cnt--;
2166 send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd);
2167 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2168 {
2169 /* We are done with the current iteration batch, AND the
2170 client would right now accept more, so go again! */
2171 GNUNET_assert (NULL == zm->task);
2172 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2173 }
2174}
2175
2176
2177/**
2178 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2179 *
2180 * @param cls the client sending the message
2181 * @param zis_msg message from the client
2182 */
2183static void
2184handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg)
2185{
2186 struct NamestoreClient *nc = cls;
2187 struct ZoneMonitor *zm;
2188
2189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n");
2190 zm = GNUNET_new (struct ZoneMonitor);
2191 zm->nc = nc;
2192 zm->zone = zis_msg->zone;
2193 zm->limit = 1;
2194 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2195 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2196 GNUNET_SERVICE_client_mark_monitor (nc->client);
2197 GNUNET_SERVICE_client_continue (nc->client);
2198 GNUNET_notification_context_add (monitor_nc, nc->mq);
2199 if (zm->in_first_iteration)
2200 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2201 else
2202 monitor_sync (zm);
2203}
2204
2205
2206/**
2207 * Obtain the next datum during the zone monitor's zone initial iteration.
2208 *
2209 * @param cls zone monitor that does its initial iteration
2210 */
2211static void
2212monitor_iteration_next (void *cls)
2213{
2214 struct ZoneMonitor *zm = cls;
2215 int ret;
2216
2217 zm->task = NULL;
2218 GNUNET_assert (0 == zm->iteration_cnt);
2219 if (zm->limit > 16)
2220 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2221 else
2222 zm->iteration_cnt = zm->limit; /* use it all */
2223 ret = GSN_database->iterate_records (GSN_database->cls,
2224 (GNUNET_YES == GNUNET_is_zero (
2225 &zm->zone))
2226 ? NULL
2227 : &zm->zone,
2228 zm->seq,
2229 zm->iteration_cnt,
2230 &monitor_iterate_cb,
2231 zm);
2232 if (GNUNET_SYSERR == ret)
2233 {
2234 GNUNET_SERVICE_client_drop (zm->nc->client);
2235 return;
2236 }
2237 if (GNUNET_NO == ret)
2238 {
2239 /* empty zone */
2240 monitor_sync (zm);
2241 return;
2242 }
2243}
2244
2245
2246/**
2247 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2248 *
2249 * @param cls the client sending the message
2250 * @param nm message from the client
2251 */
2252static void
2253handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2254{
2255 struct NamestoreClient *nc = cls;
2256 struct ZoneMonitor *zm;
2257 uint64_t inc;
2258
2259 inc = GNUNET_ntohll (nm->limit);
2260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2261 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2262 (unsigned long long) inc);
2263 for (zm = monitor_head; NULL != zm; zm = zm->next)
2264 if (zm->nc == nc)
2265 break;
2266 if (NULL == zm)
2267 {
2268 GNUNET_break (0);
2269 GNUNET_SERVICE_client_drop (nc->client);
2270 return;
2271 }
2272 GNUNET_SERVICE_client_continue (nc->client);
2273 if (zm->limit + inc < zm->limit)
2274 {
2275 GNUNET_break (0);
2276 GNUNET_SERVICE_client_drop (nc->client);
2277 return;
2278 }
2279 zm->limit += inc;
2280 if ((zm->in_first_iteration) && (zm->limit == inc))
2281 {
2282 /* We are still iterating, and the previous iteration must
2283 have stopped due to the client's limit, so continue it! */
2284 GNUNET_assert (NULL == zm->task);
2285 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2286 }
2287 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2288 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2289 {
2290 monitor_unblock (zm);
2291 }
2292 else if (GNUNET_YES == zm->sa_waiting)
2293 {
2294 if (NULL != zm->sa_wait_warning)
2295 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2296 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2297 zm->sa_wait_warning =
2298 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2299 &warn_monitor_slow,
2300 zm);
2301 }
2302}
2303
2304
2305/**
2306 * Process namestore requests.
2307 *
2308 * @param cls closure
2309 * @param cfg configuration to use
2310 * @param service the initialized service
2311 */
2312static void
2313run (void *cls,
2314 const struct GNUNET_CONFIGURATION_Handle *cfg,
2315 struct GNUNET_SERVICE_Handle *service)
2316{
2317 char *database;
2318
2319 (void) cls;
2320 (void) service;
2321 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2322 cache_keys =
2323 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS");
2324 disable_namecache =
2325 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE");
2326 GSN_cfg = cfg;
2327 monitor_nc = GNUNET_notification_context_create (1);
2328 if (GNUNET_YES != disable_namecache)
2329 {
2330 namecache = GNUNET_NAMECACHE_connect (cfg);
2331 GNUNET_assert (NULL != namecache);
2332 }
2333 /* Loading database plugin */
2334 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2335 "namestore",
2336 "database",
2337 &database))
2338 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2339
2340 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2341 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2342 GNUNET_free (database);
2343 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2344 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2345 if (NULL == GSN_database)
2346 {
2347 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2348 "Could not load database backend `%s'\n",
2349 db_lib_name);
2350 GNUNET_SCHEDULER_shutdown ();
2351 return;
2352 }
2353}
2354
2355
2356/**
2357 * Define "main" method using service macro.
2358 */
2359GNUNET_SERVICE_MAIN (
2360 "namestore",
2361 GNUNET_SERVICE_OPTION_NONE,
2362 &run,
2363 &client_connect_cb,
2364 &client_disconnect_cb,
2365 NULL,
2366 GNUNET_MQ_hd_var_size (record_store,
2367 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2368 struct RecordStoreMessage,
2369 NULL),
2370 GNUNET_MQ_hd_var_size (record_lookup,
2371 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2372 struct LabelLookupMessage,
2373 NULL),
2374 GNUNET_MQ_hd_fixed_size (zone_to_name,
2375 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2376 struct ZoneToNameMessage,
2377 NULL),
2378 GNUNET_MQ_hd_fixed_size (iteration_start,
2379 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2380 struct ZoneIterationStartMessage,
2381 NULL),
2382 GNUNET_MQ_hd_fixed_size (iteration_next,
2383 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2384 struct ZoneIterationNextMessage,
2385 NULL),
2386 GNUNET_MQ_hd_fixed_size (iteration_stop,
2387 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2388 struct ZoneIterationStopMessage,
2389 NULL),
2390 GNUNET_MQ_hd_fixed_size (monitor_start,
2391 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2392 struct ZoneMonitorStartMessage,
2393 NULL),
2394 GNUNET_MQ_hd_fixed_size (monitor_next,
2395 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2396 struct ZoneMonitorNextMessage,
2397 NULL),
2398 GNUNET_MQ_handler_end ());
2399
2400
2401/* end of gnunet-service-namestore.c */
diff --git a/src/namestore/gnunet-zoneimport.c b/src/namestore/gnunet-zoneimport.c
deleted file mode 100644
index 68b43a016..000000000
--- a/src/namestore/gnunet-zoneimport.c
+++ /dev/null
@@ -1,1884 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2018 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 src/namestore/gnunet-zoneimport.c
22 * @brief import a DNS zone for publication in GNS, incremental
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include <gnunet_util_lib.h>
27#include <gnunet_dnsstub_lib.h>
28#include <gnunet_dnsparser_lib.h>
29#include <gnunet_gnsrecord_lib.h>
30#include <gnunet_namestore_service.h>
31#include <gnunet_statistics_service.h>
32#include <gnunet_identity_service.h>
33
34
35/**
36 * Maximum number of queries pending at the same time.
37 */
38#define THRESH 100
39
40/**
41 * TIME_THRESH is in usecs. How quickly do we submit fresh queries.
42 * Used as an additional throttle.
43 */
44#define TIME_THRESH 10
45
46/**
47 * How often do we retry a query before giving up for good?
48 */
49#define MAX_RETRIES 5
50
51/**
52 * How many DNS requests do we at most issue in rapid series?
53 */
54#define MAX_SERIES 10
55
56/**
57 * How long do we wait at least between series of requests?
58 */
59#define SERIES_DELAY \
60 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MICROSECONDS, 10)
61
62/**
63 * How long do DNS records have to last at least after being imported?
64 */
65static struct GNUNET_TIME_Relative minimum_expiration_time;
66
67/**
68 * How many requests do we request from NAMESTORE in one batch
69 * during our initial iteration?
70 */
71#define NS_BATCH_SIZE 1024
72
73/**
74 * Some zones may include authoritative records for other
75 * zones, such as foo.com.uk or bar.com.fr. As for GNS
76 * each dot represents a zone cut, we then need to create a
77 * zone on-the-fly to capture those records properly.
78 */
79struct Zone
80{
81 /**
82 * Kept in a DLL.
83 */
84 struct Zone *next;
85
86 /**
87 * Kept in a DLL.
88 */
89 struct Zone *prev;
90
91 /**
92 * Domain of the zone (i.e. "fr" or "com.fr")
93 */
94 char *domain;
95
96 /**
97 * Private key of the zone.
98 */
99 struct GNUNET_IDENTITY_PrivateKey key;
100};
101
102
103/**
104 * Record for the request to be stored by GNS.
105 */
106struct Record
107{
108 /**
109 * Kept in a DLL.
110 */
111 struct Record *next;
112
113 /**
114 * Kept in a DLL.
115 */
116 struct Record *prev;
117
118 /**
119 * GNS record.
120 */
121 struct GNUNET_GNSRECORD_Data grd;
122};
123
124
125/**
126 * Request we should make. We keep this struct in memory per request,
127 * thus optimizing it is crucial for the overall memory consumption of
128 * the zone importer.
129 */
130struct Request
131{
132 /**
133 * Requests are kept in a heap while waiting to be resolved.
134 */
135 struct GNUNET_CONTAINER_HeapNode *hn;
136
137 /**
138 * Active requests are kept in a DLL.
139 */
140 struct Request *next;
141
142 /**
143 * Active requests are kept in a DLL.
144 */
145 struct Request *prev;
146
147 /**
148 * Head of records that should be published in GNS for
149 * this hostname.
150 */
151 struct Record *rec_head;
152
153 /**
154 * Tail of records that should be published in GNS for
155 * this hostname.
156 */
157 struct Record *rec_tail;
158
159 /**
160 * Socket used to make the request, NULL if not active.
161 */
162 struct GNUNET_DNSSTUB_RequestSocket *rs;
163
164 /**
165 * Hostname we are resolving, allocated at the end of
166 * this struct (optimizing memory consumption by reducing
167 * total number of allocations).
168 */
169 char *hostname;
170
171 /**
172 * Namestore operation pending for this record.
173 */
174 struct GNUNET_NAMESTORE_QueueEntry *qe;
175
176 /**
177 * Zone responsible for this request.
178 */
179 const struct Zone *zone;
180
181 /**
182 * At what time does the (earliest) of the returned records
183 * for this name expire? At this point, we need to re-fetch
184 * the record.
185 */
186 struct GNUNET_TIME_Absolute expires;
187
188 /**
189 * While we are fetching the record, the value is set to the
190 * starting time of the DNS operation. While doing a
191 * NAMESTORE store, again set to the start time of the
192 * NAMESTORE operation.
193 */
194 struct GNUNET_TIME_Absolute op_start_time;
195
196 /**
197 * How often did we issue this query? (And failed, reset
198 * to zero once we were successful.)
199 */
200 unsigned int issue_num;
201
202 /**
203 * random 16-bit DNS query identifier.
204 */
205 uint16_t id;
206};
207
208
209/**
210 * Command-line argument specifying desired size of the hash map with
211 * all of our pending names. Usually, we use an automatically growing
212 * map, but this is only OK up to about a million entries. Above that
213 * number, the user must explicitly specify the size at startup.
214 */
215static unsigned int map_size = 1024;
216
217/**
218 * Handle to the identity service.
219 */
220static struct GNUNET_IDENTITY_Handle *id;
221
222/**
223 * Namestore handle.
224 */
225static struct GNUNET_NAMESTORE_Handle *ns;
226
227/**
228 * Handle to the statistics service.
229 */
230static struct GNUNET_STATISTICS_Handle *stats;
231
232/**
233 * Context for DNS resolution.
234 */
235static struct GNUNET_DNSSTUB_Context *ctx;
236
237/**
238 * The number of DNS queries that are outstanding
239 */
240static unsigned int pending;
241
242/**
243 * The number of NAMESTORE record store operations that are outstanding
244 */
245static unsigned int pending_rs;
246
247/**
248 * Number of lookups we performed overall.
249 */
250static unsigned int lookups;
251
252/**
253 * Number of records we had cached.
254 */
255static unsigned int cached;
256
257/**
258 * How many hostnames did we reject (malformed).
259 */
260static unsigned int rejects;
261
262/**
263 * Number of lookups that failed.
264 */
265static unsigned int failures;
266
267/**
268 * Number of records we found.
269 */
270static unsigned int records;
271
272/**
273 * Number of record sets given to namestore.
274 */
275static unsigned int record_sets;
276
277/**
278 * Heap of all requests to perform, sorted by
279 * the time we should next do the request (i.e. by expires).
280 */
281static struct GNUNET_CONTAINER_Heap *req_heap;
282
283/**
284 * Active requests are kept in a DLL.
285 */
286static struct Request *req_head;
287
288/**
289 * Active requests are kept in a DLL.
290 */
291static struct Request *req_tail;
292
293/**
294 * Main task.
295 */
296static struct GNUNET_SCHEDULER_Task *t;
297
298/**
299 * Hash map of requests for which we may still get a response from
300 * the namestore. Set to NULL once the initial namestore iteration
301 * is done.
302 */
303static struct GNUNET_CONTAINER_MultiHashMap *ns_pending;
304
305/**
306 * Current zone iteration handle.
307 */
308static struct GNUNET_NAMESTORE_ZoneIterator *zone_it;
309
310/**
311 * Head of list of zones we are managing.
312 */
313static struct Zone *zone_head;
314
315/**
316 * Tail of list of zones we are managing.
317 */
318static struct Zone *zone_tail;
319
320/**
321 * After how many more results must #ns_lookup_result_cb() ask
322 * the namestore for more?
323 */
324static uint64_t ns_iterator_trigger_next;
325
326/**
327 * Number of DNS requests counted in latency total.
328 */
329static uint64_t total_dns_latency_cnt;
330
331/**
332 * Sum of DNS latencies observed.
333 */
334static struct GNUNET_TIME_Relative total_dns_latency;
335
336/**
337 * Number of records processed (DNS lookup, no NAMESTORE) in total.
338 */
339static uint64_t total_reg_proc_dns;
340
341/**
342 * Number of records processed (DNS lookup, with NAMESTORE) in total.
343 */
344static uint64_t total_reg_proc_dns_ns;
345
346/**
347 * Start time of the regular processing.
348 */
349static struct GNUNET_TIME_Absolute start_time_reg_proc;
350
351/**
352 * Last time we worked before going idle.
353 */
354static struct GNUNET_TIME_Absolute sleep_time_reg_proc;
355
356/**
357 * Time we slept just waiting for work.
358 */
359static struct GNUNET_TIME_Relative idle_time;
360
361
362/**
363 * Callback for #for_all_records
364 *
365 * @param cls closure
366 * @param rec a DNS record
367 */
368typedef void (*RecordProcessor) (void *cls,
369 const struct GNUNET_DNSPARSER_Record *rec);
370
371
372/**
373 * Call @a rp for each record in @a p, regardless of
374 * what response section it is in.
375 *
376 * @param p packet from DNS
377 * @param rp function to call
378 * @param rp_cls closure for @a rp
379 */
380static void
381for_all_records (const struct GNUNET_DNSPARSER_Packet *p,
382 RecordProcessor rp,
383 void *rp_cls)
384{
385 for (unsigned int i = 0; i < p->num_answers; i++)
386 {
387 struct GNUNET_DNSPARSER_Record *rs = &p->answers[i];
388
389 rp (rp_cls, rs);
390 }
391 for (unsigned int i = 0; i < p->num_authority_records; i++)
392 {
393 struct GNUNET_DNSPARSER_Record *rs = &p->authority_records[i];
394
395 rp (rp_cls, rs);
396 }
397 for (unsigned int i = 0; i < p->num_additional_records; i++)
398 {
399 struct GNUNET_DNSPARSER_Record *rs = &p->additional_records[i];
400
401 rp (rp_cls, rs);
402 }
403}
404
405
406/**
407 * Return just the label of the hostname in @a req.
408 *
409 * @param req request to process hostname of
410 * @return statically allocated pointer to the label,
411 * overwritten upon the next request!
412 */
413static const char *
414get_label (struct Request *req)
415{
416 static char label[64];
417 const char *dot;
418
419 dot = strchr (req->hostname, (unsigned char) '.');
420 if (NULL == dot)
421 {
422 GNUNET_break (0);
423 return NULL;
424 }
425 if (((size_t) (dot - req->hostname)) >= sizeof(label))
426 {
427 GNUNET_break (0);
428 return NULL;
429 }
430 GNUNET_memcpy (label, req->hostname, dot - req->hostname);
431 label[dot - req->hostname] = '\0';
432 return label;
433}
434
435
436/**
437 * Build DNS query for @a hostname.
438 *
439 * @param hostname host to build query for
440 * @param raw_size[out] number of bytes in the query
441 * @return NULL on error, otherwise pointer to statically (!)
442 * allocated query buffer
443 */
444static void *
445build_dns_query (struct Request *req, size_t *raw_size)
446{
447 static char raw[512];
448 char *rawp;
449 struct GNUNET_DNSPARSER_Packet p;
450 struct GNUNET_DNSPARSER_Query q;
451 int ret;
452
453 q.name = (char *) req->hostname;
454 q.type = GNUNET_DNSPARSER_TYPE_NS;
455 q.dns_traffic_class = GNUNET_TUN_DNS_CLASS_INTERNET;
456
457 memset (&p, 0, sizeof(p));
458 p.num_queries = 1;
459 p.queries = &q;
460 p.id = req->id;
461 ret = GNUNET_DNSPARSER_pack (&p, UINT16_MAX, &rawp, raw_size);
462 if (GNUNET_OK != ret)
463 {
464 if (GNUNET_NO == ret)
465 GNUNET_free (rawp);
466 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
467 "Failed to pack query for hostname `%s'\n",
468 req->hostname);
469 rejects++;
470 return NULL;
471 }
472 if (*raw_size > sizeof(raw))
473 {
474 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
475 "Failed to pack query for hostname `%s'\n",
476 req->hostname);
477 rejects++;
478 GNUNET_break (0);
479 GNUNET_free (rawp);
480 return NULL;
481 }
482 GNUNET_memcpy (raw, rawp, *raw_size);
483 GNUNET_free (rawp);
484 return raw;
485}
486
487
488/**
489 * Free records associated with @a req.
490 *
491 * @param req request to free records of
492 */
493static void
494free_records (struct Request *req)
495{
496 struct Record *rec;
497
498 /* Free records */
499 while (NULL != (rec = req->rec_head))
500 {
501 GNUNET_CONTAINER_DLL_remove (req->rec_head, req->rec_tail, rec);
502 GNUNET_free (rec);
503 }
504}
505
506
507/**
508 * Free @a req and data structures reachable from it.
509 *
510 * @param req request to free
511 */
512static void
513free_request (struct Request *req)
514{
515 free_records (req);
516 GNUNET_free (req);
517}
518
519
520/**
521 * Process as many requests as possible from the queue.
522 *
523 * @param cls NULL
524 */
525static void
526process_queue (void *cls);
527
528
529/**
530 * Insert @a req into DLL sorted by next fetch time.
531 *
532 * @param req request to insert into #req_heap
533 */
534static void
535insert_sorted (struct Request *req)
536{
537 req->hn =
538 GNUNET_CONTAINER_heap_insert (req_heap, req, req->expires.abs_value_us);
539 if (req == GNUNET_CONTAINER_heap_peek (req_heap))
540 {
541 if (NULL != t)
542 GNUNET_SCHEDULER_cancel (t);
543 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
544 t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
545 }
546}
547
548
549/**
550 * Add record to the GNS record set for @a req.
551 *
552 * @param req the request to expand GNS record set for
553 * @param type type to use
554 * @param expiration_time when should @a rec expire
555 * @param data raw data to store
556 * @param data_len number of bytes in @a data
557 */
558static void
559add_record (struct Request *req,
560 uint32_t type,
561 struct GNUNET_TIME_Absolute expiration_time,
562 const void *data,
563 size_t data_len)
564{
565 struct Record *rec;
566
567 rec = GNUNET_malloc (sizeof(struct Record) + data_len);
568 rec->grd.data = &rec[1];
569 rec->grd.expiration_time = expiration_time.abs_value_us;
570 rec->grd.data_size = data_len;
571 rec->grd.record_type = type;
572 rec->grd.flags = GNUNET_GNSRECORD_RF_NONE;
573 GNUNET_memcpy (&rec[1], data, data_len);
574 GNUNET_CONTAINER_DLL_insert (req->rec_head, req->rec_tail, rec);
575}
576
577
578/**
579 * Closure for #check_for_glue.
580 */
581struct GlueClosure
582{
583 /**
584 * Overall request we are processing.
585 */
586 struct Request *req;
587
588 /**
589 * NS name we are looking for glue for.
590 */
591 const char *ns;
592
593 /**
594 * Set to #GNUNET_YES if glue was found.
595 */
596 int found;
597};
598
599
600/**
601 * Try to find glue records for a given NS record.
602 *
603 * @param cls a `struct GlueClosure *`
604 * @param rec record that may contain glue information
605 */
606static void
607check_for_glue (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
608{
609 struct GlueClosure *gc = cls;
610 char dst[65536];
611 size_t dst_len;
612 size_t off;
613 char ip[INET6_ADDRSTRLEN + 1];
614 socklen_t ip_size = (socklen_t) sizeof(ip);
615 struct GNUNET_TIME_Absolute expiration_time;
616 struct GNUNET_TIME_Relative left;
617
618 if (0 != strcasecmp (rec->name, gc->ns))
619 return;
620 expiration_time = rec->expiration_time;
621 left = GNUNET_TIME_absolute_get_remaining (expiration_time);
622 if (0 == left.rel_value_us)
623 return; /* ignore expired glue records */
624 /* if expiration window is too short, bump it to configured minimum */
625 if (left.rel_value_us < minimum_expiration_time.rel_value_us)
626 expiration_time =
627 GNUNET_TIME_relative_to_absolute (minimum_expiration_time);
628 dst_len = sizeof(dst);
629 off = 0;
630 switch (rec->type)
631 {
632 case GNUNET_DNSPARSER_TYPE_A:
633 if (sizeof(struct in_addr) != rec->data.raw.data_len)
634 {
635 GNUNET_break (0);
636 return;
637 }
638 if (NULL == inet_ntop (AF_INET, rec->data.raw.data, ip, ip_size))
639 {
640 GNUNET_break (0);
641 return;
642 }
643 if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
644 dst_len,
645 &off,
646 gc->req->hostname)) &&
647 (GNUNET_OK ==
648 GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
649 {
650 add_record (gc->req,
651 GNUNET_GNSRECORD_TYPE_GNS2DNS,
652 expiration_time,
653 dst,
654 off);
655 gc->found = GNUNET_YES;
656 }
657 break;
658
659 case GNUNET_DNSPARSER_TYPE_AAAA:
660 if (sizeof(struct in6_addr) != rec->data.raw.data_len)
661 {
662 GNUNET_break (0);
663 return;
664 }
665 if (NULL == inet_ntop (AF_INET6, rec->data.raw.data, ip, ip_size))
666 {
667 GNUNET_break (0);
668 return;
669 }
670 if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
671 dst_len,
672 &off,
673 gc->req->hostname)) &&
674 (GNUNET_OK ==
675 GNUNET_DNSPARSER_builder_add_name (dst, dst_len, &off, ip)))
676 {
677 add_record (gc->req,
678 GNUNET_GNSRECORD_TYPE_GNS2DNS,
679 expiration_time,
680 dst,
681 off);
682 gc->found = GNUNET_YES;
683 }
684 break;
685
686 case GNUNET_DNSPARSER_TYPE_CNAME:
687 if ((GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
688 dst_len,
689 &off,
690 gc->req->hostname)) &&
691 (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
692 dst_len,
693 &off,
694 rec->data.hostname)))
695 {
696 add_record (gc->req,
697 GNUNET_GNSRECORD_TYPE_GNS2DNS,
698 expiration_time,
699 dst,
700 off);
701 gc->found = GNUNET_YES;
702 }
703 break;
704
705 default:
706 /* useless, do nothing */
707 break;
708 }
709}
710
711
712/**
713 * Closure for #process_record().
714 */
715struct ProcessRecordContext
716{
717 /**
718 * Answer we got back and are currently parsing, or NULL
719 * if not active.
720 */
721 struct GNUNET_DNSPARSER_Packet *p;
722
723 /**
724 * Request we are processing.
725 */
726 struct Request *req;
727};
728
729
730/**
731 * We received @a rec for @a req. Remember the answer.
732 *
733 * @param cls a `struct ProcessRecordContext`
734 * @param rec response
735 */
736static void
737process_record (void *cls, const struct GNUNET_DNSPARSER_Record *rec)
738{
739 struct ProcessRecordContext *prc = cls;
740 struct Request *req = prc->req;
741 char dst[65536];
742 size_t dst_len;
743 size_t off;
744 struct GNUNET_TIME_Absolute expiration_time;
745 struct GNUNET_TIME_Relative left;
746
747 dst_len = sizeof(dst);
748 off = 0;
749 records++;
750 if (0 != strcasecmp (rec->name, req->hostname))
751 {
752 GNUNET_log (
753 GNUNET_ERROR_TYPE_DEBUG,
754 "DNS returned record from zone `%s' of type %u while resolving `%s'\n",
755 rec->name,
756 (unsigned int) rec->type,
757 req->hostname);
758 return; /* does not match hostname, might be glue, but
759 not useful for this pass! */
760 }
761 expiration_time = rec->expiration_time;
762 left = GNUNET_TIME_absolute_get_remaining (expiration_time);
763 if (0 == left.rel_value_us)
764 {
765 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
766 "DNS returned expired record for `%s'\n",
767 req->hostname);
768 GNUNET_STATISTICS_update (stats,
769 "# expired records obtained from DNS",
770 1,
771 GNUNET_NO);
772 return; /* record expired */
773 }
774
775 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
776 "DNS returned record that expires at %s for `%s'\n",
777 GNUNET_STRINGS_absolute_time_to_string (expiration_time),
778 req->hostname);
779 /* if expiration window is too short, bump it to configured minimum */
780 if (left.rel_value_us < minimum_expiration_time.rel_value_us)
781 expiration_time =
782 GNUNET_TIME_relative_to_absolute (minimum_expiration_time);
783 switch (rec->type)
784 {
785 case GNUNET_DNSPARSER_TYPE_NS: {
786 struct GlueClosure gc;
787
788 /* check for glue */
789 gc.req = req;
790 gc.ns = rec->data.hostname;
791 gc.found = GNUNET_NO;
792 for_all_records (prc->p, &check_for_glue, &gc);
793 if ((GNUNET_NO == gc.found) &&
794 (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
795 dst_len,
796 &off,
797 req->hostname)) &&
798 (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
799 dst_len,
800 &off,
801 rec->data.hostname)))
802 {
803 /* FIXME: actually check if this is out-of-bailiwick,
804 and if not request explicit resolution... */
805 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
806 "Converted OOB (`%s') NS record for `%s'\n",
807 rec->data.hostname,
808 rec->name);
809 add_record (req,
810 GNUNET_GNSRECORD_TYPE_GNS2DNS,
811 expiration_time,
812 dst,
813 off);
814 }
815 else
816 {
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "Converted NS record for `%s' using glue\n",
819 rec->name);
820 }
821 break;
822 }
823
824 case GNUNET_DNSPARSER_TYPE_CNAME:
825 if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
826 dst_len,
827 &off,
828 rec->data.hostname))
829 {
830 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
831 "Converting CNAME (`%s') record for `%s'\n",
832 rec->data.hostname,
833 rec->name);
834 add_record (req, rec->type, expiration_time, dst, off);
835 }
836 break;
837
838 case GNUNET_DNSPARSER_TYPE_DNAME:
839 /* No support for DNAME in GNS yet! FIXME: support later! */
840 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
841 "FIXME: not supported: %s DNAME %s\n",
842 rec->name,
843 rec->data.hostname);
844 break;
845
846 case GNUNET_DNSPARSER_TYPE_MX:
847 if (GNUNET_OK ==
848 GNUNET_DNSPARSER_builder_add_mx (dst, dst_len, &off, rec->data.mx))
849 {
850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
851 "Converting MX (`%s') record for `%s'\n",
852 rec->data.mx->mxhost,
853 rec->name);
854 add_record (req, rec->type, expiration_time, dst, off);
855 }
856 break;
857
858 case GNUNET_DNSPARSER_TYPE_SOA:
859 if (GNUNET_OK ==
860 GNUNET_DNSPARSER_builder_add_soa (dst, dst_len, &off, rec->data.soa))
861 {
862 /* NOTE: GNS does not really use SOAs */
863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
864 "Converting SOA record for `%s'\n",
865 rec->name);
866 add_record (req, rec->type, expiration_time, dst, off);
867 }
868 break;
869
870 case GNUNET_DNSPARSER_TYPE_SRV:
871 if (GNUNET_OK ==
872 GNUNET_DNSPARSER_builder_add_srv (dst, dst_len, &off, rec->data.srv))
873 {
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
875 "Converting SRV record for `%s'\n",
876 rec->name);
877 add_record (req, rec->type, expiration_time, dst, off);
878 }
879 break;
880
881 case GNUNET_DNSPARSER_TYPE_PTR:
882 if (GNUNET_OK == GNUNET_DNSPARSER_builder_add_name (dst,
883 dst_len,
884 &off,
885 rec->data.hostname))
886 {
887 /* !?: what does a PTR record do in a regular TLD??? */
888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
889 "Converting PTR record for `%s' (weird)\n",
890 rec->name);
891 add_record (req, rec->type, expiration_time, dst, off);
892 }
893 break;
894
895 case GNUNET_DNSPARSER_TYPE_CERT:
896 if (GNUNET_OK ==
897 GNUNET_DNSPARSER_builder_add_cert (dst, dst_len, &off, rec->data.cert))
898 {
899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
900 "Converting CERT record for `%s'\n",
901 rec->name);
902 add_record (req, rec->type, expiration_time, dst, off);
903 }
904 break;
905
906 /* Rest is 'raw' encoded and just needs to be copied IF
907 the hostname matches the requested name; otherwise we
908 simply cannot use it. */
909 case GNUNET_DNSPARSER_TYPE_A:
910 case GNUNET_DNSPARSER_TYPE_AAAA:
911 case GNUNET_DNSPARSER_TYPE_TXT:
912 default:
913 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
914 "Converting record of type %u for `%s'\n",
915 (unsigned int) rec->type,
916 rec->name);
917 add_record (req,
918 rec->type,
919 expiration_time,
920 rec->data.raw.data,
921 rec->data.raw.data_len);
922 break;
923 }
924}
925
926
927/**
928 * Continuation called to notify client about result of the
929 * operation.
930 *
931 * @param cls closure with our `struct Request`
932 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
933 * #GNUNET_NO if content was already there or not found
934 * #GNUNET_YES (or other positive value) on success
935 * @param emsg NULL on success, otherwise an error message
936 */
937static void
938store_completed_cb (void *cls, int32_t success, const char *emsg)
939{
940 static struct GNUNET_TIME_Absolute last;
941 struct Request *req = cls;
942
943 req->qe = NULL;
944 if (GNUNET_SYSERR == success)
945 {
946 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
947 "Failed to store zone data for `%s': %s\n",
948 req->hostname,
949 emsg);
950 }
951 else
952 {
953 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
954 "Stored records under `%s' (%d)\n",
955 req->hostname,
956 success);
957 }
958 total_reg_proc_dns_ns++; /* finished regular processing */
959 pending_rs--;
960 free_records (req);
961 /* compute NAMESTORE statistics */
962 {
963 static uint64_t total_ns_latency_cnt;
964 static struct GNUNET_TIME_Relative total_ns_latency;
965 struct GNUNET_TIME_Relative ns_latency;
966
967 ns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time);
968 total_ns_latency = GNUNET_TIME_relative_add (total_ns_latency, ns_latency);
969 if (0 == total_ns_latency_cnt)
970 last = GNUNET_TIME_absolute_get ();
971 total_ns_latency_cnt++;
972 if (0 == (total_ns_latency_cnt % 1000))
973 {
974 struct GNUNET_TIME_Relative delta;
975
976 delta = GNUNET_TIME_absolute_get_duration (last);
977 last = GNUNET_TIME_absolute_get ();
978 fprintf (stderr,
979 "Processed 1000 records in %s\n",
980 GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES));
981 GNUNET_STATISTICS_set (stats,
982 "# average NAMESTORE PUT latency (μs)",
983 total_ns_latency.rel_value_us
984 / total_ns_latency_cnt,
985 GNUNET_NO);
986 }
987 }
988 /* compute and publish overall velocity */
989 if (0 == (total_reg_proc_dns_ns % 100))
990 {
991 struct GNUNET_TIME_Relative runtime;
992
993 runtime = GNUNET_TIME_absolute_get_duration (start_time_reg_proc);
994 runtime = GNUNET_TIME_relative_subtract (runtime, idle_time);
995 runtime =
996 GNUNET_TIME_relative_divide (runtime,
997 total_reg_proc_dns + total_reg_proc_dns_ns);
998 GNUNET_STATISTICS_set (stats,
999 "# Regular processing completed without NAMESTORE",
1000 total_reg_proc_dns,
1001 GNUNET_NO);
1002 GNUNET_STATISTICS_set (stats,
1003 "# Regular processing completed with NAMESTORE PUT",
1004 total_reg_proc_dns_ns,
1005 GNUNET_NO);
1006 GNUNET_STATISTICS_set (stats,
1007 "# average request processing latency (μs)",
1008 runtime.rel_value_us,
1009 GNUNET_NO);
1010 GNUNET_STATISTICS_set (stats,
1011 "# total time spent idle (μs)",
1012 idle_time.rel_value_us,
1013 GNUNET_NO);
1014 }
1015
1016 if (NULL == t)
1017 {
1018 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
1019 t = GNUNET_SCHEDULER_add_now (&process_queue, NULL);
1020 }
1021}
1022
1023
1024/**
1025 * Function called with the result of a DNS resolution.
1026 *
1027 * @param cls closure with the `struct Request`
1028 * @param dns dns response, never NULL
1029 * @param dns_len number of bytes in @a dns
1030 */
1031static void
1032process_result (void *cls,
1033 const struct GNUNET_TUN_DnsHeader *dns,
1034 size_t dns_len)
1035{
1036 struct Request *req = cls;
1037 struct Record *rec;
1038 struct GNUNET_DNSPARSER_Packet *p;
1039 unsigned int rd_count;
1040
1041 GNUNET_assert (NULL == req->hn);
1042 if (NULL == dns)
1043 {
1044 /* stub gave up */
1045 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1046 pending--;
1047 if (NULL == t)
1048 {
1049 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
1050 t = GNUNET_SCHEDULER_add_now (&process_queue, NULL);
1051 }
1052 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1053 "Stub gave up on DNS reply for `%s'\n",
1054 req->hostname);
1055 GNUNET_STATISTICS_update (stats, "# DNS lookups timed out", 1, GNUNET_NO);
1056 if (req->issue_num > MAX_RETRIES)
1057 {
1058 failures++;
1059 free_request (req);
1060 GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1061 return;
1062 }
1063 total_reg_proc_dns++;
1064 req->rs = NULL;
1065 insert_sorted (req);
1066 return;
1067 }
1068 if (req->id != dns->id)
1069 {
1070 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1071 "DNS ID did not match request, ignoring reply\n");
1072 GNUNET_STATISTICS_update (stats, "# DNS ID mismatches", 1, GNUNET_NO);
1073 return;
1074 }
1075 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1076 GNUNET_DNSSTUB_resolve_cancel (req->rs);
1077 req->rs = NULL;
1078 pending--;
1079 p = GNUNET_DNSPARSER_parse ((const char *) dns, dns_len);
1080 if (NULL == p)
1081 {
1082 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1083 "Failed to parse DNS reply for `%s'\n",
1084 req->hostname);
1085 GNUNET_STATISTICS_update (stats, "# DNS parser errors", 1, GNUNET_NO);
1086 if (NULL == t)
1087 {
1088 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
1089 t = GNUNET_SCHEDULER_add_now (&process_queue, NULL);
1090 }
1091 if (req->issue_num > MAX_RETRIES)
1092 {
1093 failures++;
1094 free_request (req);
1095 GNUNET_STATISTICS_update (stats, "# requests given up on", 1, GNUNET_NO);
1096 return;
1097 }
1098 insert_sorted (req);
1099 return;
1100 }
1101 /* import new records */
1102 req->issue_num = 0; /* success, reset counter! */
1103 {
1104 struct ProcessRecordContext prc = { .req = req, .p = p };
1105
1106 for_all_records (p, &process_record, &prc);
1107 }
1108 GNUNET_DNSPARSER_free_packet (p);
1109 /* count records found, determine minimum expiration time */
1110 req->expires = GNUNET_TIME_UNIT_FOREVER_ABS;
1111 {
1112 struct GNUNET_TIME_Relative dns_latency;
1113
1114 dns_latency = GNUNET_TIME_absolute_get_duration (req->op_start_time);
1115 total_dns_latency =
1116 GNUNET_TIME_relative_add (total_dns_latency, dns_latency);
1117 total_dns_latency_cnt++;
1118 if (0 == (total_dns_latency_cnt % 1000))
1119 {
1120 GNUNET_STATISTICS_set (stats,
1121 "# average DNS lookup latency (μs)",
1122 total_dns_latency.rel_value_us
1123 / total_dns_latency_cnt,
1124 GNUNET_NO);
1125 }
1126 }
1127 rd_count = 0;
1128 for (rec = req->rec_head; NULL != rec; rec = rec->next)
1129 {
1130 struct GNUNET_TIME_Absolute at;
1131
1132 at.abs_value_us = rec->grd.expiration_time;
1133 req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1134 rd_count++;
1135 }
1136 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1137 "Obtained %u records for `%s'\n",
1138 rd_count,
1139 req->hostname);
1140 /* Instead of going for SOA, simplified for now to look each
1141 day in case we got an empty response */
1142 if (0 == rd_count)
1143 {
1144 req->expires = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_DAYS);
1145 GNUNET_STATISTICS_update (stats,
1146 "# empty DNS replies (usually NXDOMAIN)",
1147 1,
1148 GNUNET_NO);
1149 }
1150 else
1151 {
1152 record_sets++;
1153 }
1154 /* convert records to namestore import format */
1155 {
1156 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1157 unsigned int off = 0;
1158
1159 /* convert linked list into array */
1160 for (rec = req->rec_head; NULL != rec; rec = rec->next)
1161 rd[off++] = rec->grd;
1162 pending_rs++;
1163 req->op_start_time = GNUNET_TIME_absolute_get ();
1164 req->qe = GNUNET_NAMESTORE_records_store (ns,
1165 &req->zone->key,
1166 get_label (req),
1167 rd_count,
1168 rd,
1169 &store_completed_cb,
1170 req);
1171 GNUNET_assert (NULL != req->qe);
1172 }
1173 insert_sorted (req);
1174}
1175
1176
1177/**
1178 * Process as many requests as possible from the queue.
1179 *
1180 * @param cls NULL
1181 */
1182static void
1183process_queue (void *cls)
1184{
1185 struct Request *req;
1186 unsigned int series;
1187 void *raw;
1188 size_t raw_size;
1189 struct GNUNET_TIME_Relative delay;
1190
1191 (void) cls;
1192 delay = GNUNET_TIME_absolute_get_duration (sleep_time_reg_proc);
1193 idle_time = GNUNET_TIME_relative_add (idle_time, delay);
1194 series = 0;
1195 t = NULL;
1196 while (pending + pending_rs < THRESH)
1197 {
1198 req = GNUNET_CONTAINER_heap_peek (req_heap);
1199 if (NULL == req)
1200 break;
1201 if (NULL != req->qe)
1202 return; /* namestore op still pending */
1203 if (NULL != req->rs)
1204 {
1205 GNUNET_break (0);
1206 return; /* already submitted */
1207 }
1208 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0)
1209 break;
1210 GNUNET_assert (req == GNUNET_CONTAINER_heap_remove_root (req_heap));
1211 req->hn = NULL;
1212 GNUNET_CONTAINER_DLL_insert (req_head, req_tail, req);
1213 GNUNET_assert (NULL == req->rs);
1214 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1215 "Requesting resolution for `%s'\n",
1216 req->hostname);
1217 raw = build_dns_query (req, &raw_size);
1218 if (NULL == raw)
1219 {
1220 GNUNET_break (0);
1221 free_request (req);
1222 continue;
1223 }
1224 req->op_start_time = GNUNET_TIME_absolute_get ();
1225 req->rs = GNUNET_DNSSTUB_resolve (ctx, raw, raw_size, &process_result, req);
1226 GNUNET_assert (NULL != req->rs);
1227 req->issue_num++;
1228 lookups++;
1229 pending++;
1230 series++;
1231 if (series > MAX_SERIES)
1232 break;
1233 }
1234 if (pending + pending_rs >= THRESH)
1235 {
1236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1237 "Stopped processing queue (%u+%u/%u)]\n",
1238 pending,
1239 pending_rs,
1240 THRESH);
1241 return; /* wait for replies */
1242 }
1243 req = GNUNET_CONTAINER_heap_peek (req_heap);
1244 if (NULL == req)
1245 {
1246 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1247 "Stopped processing queue: empty queue\n");
1248 return;
1249 }
1250 if (GNUNET_TIME_absolute_get_remaining (req->expires).rel_value_us > 0)
1251 {
1252 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1253 "Waiting until %s for next record (`%s') to expire\n",
1254 GNUNET_STRINGS_absolute_time_to_string (req->expires),
1255 req->hostname);
1256 if (NULL != t)
1257 GNUNET_SCHEDULER_cancel (t);
1258 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
1259 t = GNUNET_SCHEDULER_add_at (req->expires, &process_queue, NULL);
1260 return;
1261 }
1262 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Throttling\n");
1263 if (NULL != t)
1264 GNUNET_SCHEDULER_cancel (t);
1265 sleep_time_reg_proc = GNUNET_TIME_absolute_get ();
1266 t = GNUNET_SCHEDULER_add_delayed (SERIES_DELAY, &process_queue, NULL);
1267}
1268
1269
1270/**
1271 * Iterator called during #do_shutdown() to free requests in
1272 * the #ns_pending map.
1273 *
1274 * @param cls NULL
1275 * @param key unused
1276 * @param value the `struct Request` to free
1277 * @return #GNUNET_OK
1278 */
1279static int
1280free_request_it (void *cls, const struct GNUNET_HashCode *key, void *value)
1281{
1282 struct Request *req = value;
1283
1284 (void) cls;
1285 (void) key;
1286 free_request (req);
1287 return GNUNET_OK;
1288}
1289
1290
1291/**
1292 * Clean up and terminate the process.
1293 *
1294 * @param cls NULL
1295 */
1296static void
1297do_shutdown (void *cls)
1298{
1299 struct Request *req;
1300 struct Zone *zone;
1301
1302 (void) cls;
1303 if (NULL != id)
1304 {
1305 GNUNET_IDENTITY_disconnect (id);
1306 id = NULL;
1307 }
1308 if (NULL != t)
1309 {
1310 GNUNET_SCHEDULER_cancel (t);
1311 t = NULL;
1312 }
1313 while (NULL != (req = req_head))
1314 {
1315 GNUNET_CONTAINER_DLL_remove (req_head, req_tail, req);
1316 if (NULL != req->qe)
1317 GNUNET_NAMESTORE_cancel (req->qe);
1318 free_request (req);
1319 }
1320 while (NULL != (req = GNUNET_CONTAINER_heap_remove_root (req_heap)))
1321 {
1322 req->hn = NULL;
1323 if (NULL != req->qe)
1324 GNUNET_NAMESTORE_cancel (req->qe);
1325 free_request (req);
1326 }
1327 if (NULL != zone_it)
1328 {
1329 GNUNET_NAMESTORE_zone_iteration_stop (zone_it);
1330 zone_it = NULL;
1331 }
1332 if (NULL != ns)
1333 {
1334 GNUNET_NAMESTORE_disconnect (ns);
1335 ns = NULL;
1336 }
1337 if (NULL != ctx)
1338 {
1339 GNUNET_DNSSTUB_stop (ctx);
1340 ctx = NULL;
1341 }
1342 if (NULL != req_heap)
1343 {
1344 GNUNET_CONTAINER_heap_destroy (req_heap);
1345 req_heap = NULL;
1346 }
1347 if (NULL != ns_pending)
1348 {
1349 GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &free_request_it, NULL);
1350 GNUNET_CONTAINER_multihashmap_destroy (ns_pending);
1351 ns_pending = NULL;
1352 }
1353 while (NULL != (zone = zone_head))
1354 {
1355 GNUNET_CONTAINER_DLL_remove (zone_head, zone_tail, zone);
1356 GNUNET_free (zone->domain);
1357 GNUNET_free (zone);
1358 }
1359 if (NULL != stats)
1360 {
1361 GNUNET_STATISTICS_destroy (stats, GNUNET_NO);
1362 stats = NULL;
1363 }
1364}
1365
1366
1367/**
1368 * Iterate over all of the zones we care about and see which records
1369 * we may need to re-fetch when.
1370 *
1371 * @param cls NULL
1372 */
1373static void
1374iterate_zones (void *cls);
1375
1376
1377/**
1378 * Function called if #GNUNET_NAMESTORE_records_lookup() failed.
1379 * Just logs an error.
1380 *
1381 * @param cls a `struct Zone`
1382 */
1383static void
1384ns_lookup_error_cb (void *cls)
1385{
1386 struct Zone *zone = cls;
1387
1388 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1389 "Failed to load data from namestore for zone `%s'\n",
1390 zone->domain);
1391 zone_it = NULL;
1392 ns_iterator_trigger_next = 0;
1393 iterate_zones (NULL);
1394}
1395
1396
1397/**
1398 * Process a record that was stored in the namestore.
1399 *
1400 * @param cls a `struct Zone *`
1401 * @param key private key of the zone
1402 * @param label label of the records
1403 * @param rd_count number of entries in @a rd array, 0 if label was deleted
1404 * @param rd array of records with data to store
1405 */
1406static void
1407ns_lookup_result_cb (void *cls,
1408 const struct GNUNET_IDENTITY_PrivateKey *key,
1409 const char *label,
1410 unsigned int rd_count,
1411 const struct GNUNET_GNSRECORD_Data *rd)
1412{
1413 struct Zone *zone = cls;
1414 struct Request *req;
1415 struct GNUNET_HashCode hc;
1416 char *fqdn;
1417
1418 ns_iterator_trigger_next--;
1419 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1420 "Obtained NAMESTORE reply, %llu left in round\n",
1421 (unsigned long long) ns_iterator_trigger_next);
1422 if (0 == ns_iterator_trigger_next)
1423 {
1424 ns_iterator_trigger_next = NS_BATCH_SIZE;
1425 GNUNET_STATISTICS_update (stats,
1426 "# NAMESTORE records requested from cache",
1427 ns_iterator_trigger_next,
1428 GNUNET_NO);
1429 GNUNET_NAMESTORE_zone_iterator_next (zone_it, ns_iterator_trigger_next);
1430 }
1431 GNUNET_asprintf (&fqdn, "%s.%s", label, zone->domain);
1432 GNUNET_CRYPTO_hash (fqdn, strlen (fqdn) + 1, &hc);
1433 GNUNET_free (fqdn);
1434 req = GNUNET_CONTAINER_multihashmap_get (ns_pending, &hc);
1435 if (NULL == req)
1436 {
1437 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1438 "Ignoring record `%s' in zone `%s': not on my list!\n",
1439 label,
1440 zone->domain);
1441 return;
1442 }
1443 GNUNET_assert (GNUNET_OK ==
1444 GNUNET_CONTAINER_multihashmap_remove (ns_pending, &hc, req));
1445 GNUNET_break (0 == GNUNET_memcmp (key, &req->zone->key));
1446 GNUNET_break (0 == strcasecmp (label, get_label (req)));
1447 for (unsigned int i = 0; i < rd_count; i++)
1448 {
1449 struct GNUNET_TIME_Absolute at;
1450
1451 if (0 != (rd->flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1452 {
1453 struct GNUNET_TIME_Relative rel;
1454
1455 rel.rel_value_us = rd->expiration_time;
1456 at = GNUNET_TIME_relative_to_absolute (rel);
1457 }
1458 else
1459 {
1460 at.abs_value_us = rd->expiration_time;
1461 }
1462 add_record (req, rd->record_type, at, rd->data, rd->data_size);
1463 }
1464 if (0 == rd_count)
1465 {
1466 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1467 "Empty record set in namestore for `%s'\n",
1468 req->hostname);
1469 }
1470 else
1471 {
1472 unsigned int pos = 0;
1473
1474 cached++;
1475 req->expires = GNUNET_TIME_UNIT_FOREVER_ABS;
1476 for (struct Record *rec = req->rec_head; NULL != rec; rec = rec->next)
1477 {
1478 struct GNUNET_TIME_Absolute at;
1479
1480 at.abs_value_us = rec->grd.expiration_time;
1481 req->expires = GNUNET_TIME_absolute_min (req->expires, at);
1482 pos++;
1483 }
1484 if (0 == pos)
1485 req->expires = GNUNET_TIME_UNIT_ZERO_ABS;
1486 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1487 "Hot-start with %u existing records for `%s'\n",
1488 pos,
1489 req->hostname);
1490 }
1491 free_records (req);
1492
1493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1494 "Adding `%s' to worklist to start at %s\n",
1495 req->hostname,
1496 GNUNET_STRINGS_absolute_time_to_string (req->expires));
1497 insert_sorted (req);
1498}
1499
1500
1501/**
1502 * Add @a hostname to the list of requests to be made.
1503 *
1504 * @param hostname name to resolve
1505 */
1506static void
1507queue (const char *hostname)
1508{
1509 struct Request *req;
1510 const char *dot;
1511 struct Zone *zone;
1512 size_t hlen;
1513 struct GNUNET_HashCode hc;
1514
1515 if (GNUNET_OK != GNUNET_DNSPARSER_check_name (hostname))
1516 {
1517 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1518 "Refusing invalid hostname `%s'\n",
1519 hostname);
1520 rejects++;
1521 return;
1522 }
1523 dot = strchr (hostname, (unsigned char) '.');
1524 if (NULL == dot)
1525 {
1526 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1527 "Refusing invalid hostname `%s' (lacks '.')\n",
1528 hostname);
1529 rejects++;
1530 return;
1531 }
1532 for (zone = zone_head; NULL != zone; zone = zone->next)
1533 if (0 == strcmp (zone->domain, dot + 1))
1534 break;
1535 if (NULL == zone)
1536 {
1537 rejects++;
1538 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1539 "Domain name `%s' not in ego list!\n",
1540 dot + 1);
1541 return;
1542 }
1543
1544 hlen = strlen (hostname) + 1;
1545 req = GNUNET_malloc (sizeof(struct Request) + hlen);
1546 req->zone = zone;
1547 req->hostname = (char *) &req[1];
1548 GNUNET_memcpy (req->hostname, hostname, hlen);
1549 req->id = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
1550 UINT16_MAX);
1551 GNUNET_CRYPTO_hash (req->hostname, hlen, &hc);
1552 if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put (
1553 ns_pending,
1554 &hc,
1555 req,
1556 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1557 {
1558 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1559 "Duplicate hostname `%s' ignored\n",
1560 hostname);
1561 GNUNET_free (req);
1562 return;
1563 }
1564}
1565
1566
1567/**
1568 * We have completed the initial iteration over the namestore's database.
1569 * This function is called on each of the remaining records in
1570 * #move_to_queue to #queue() them, as we will simply not find existing
1571 * records for them any longer.
1572 *
1573 * @param cls NULL
1574 * @param key unused
1575 * @param value a `struct Request`
1576 * @return #GNUNET_OK (continue to iterate)
1577 */
1578static int
1579move_to_queue (void *cls, const struct GNUNET_HashCode *key, void *value)
1580{
1581 struct Request *req = value;
1582
1583 (void) cls;
1584 (void) key;
1585 insert_sorted (req);
1586 return GNUNET_OK;
1587}
1588
1589
1590/**
1591 * Iterate over all of the zones we care about and see which records
1592 * we may need to re-fetch when.
1593 *
1594 * @param cls NULL
1595 */
1596static void
1597iterate_zones (void *cls)
1598{
1599 static struct Zone *last;
1600
1601 (void) cls;
1602 if (NULL != zone_it)
1603 {
1604 zone_it = NULL;
1605 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1606 "Finished iteration over zone `%s'!\n",
1607 last->domain);
1608 /* subtract left-overs from previous iteration */
1609 GNUNET_STATISTICS_update (stats,
1610 "# NAMESTORE records requested from cache",
1611 (long long) (-ns_iterator_trigger_next),
1612 GNUNET_NO);
1613 ns_iterator_trigger_next = 0;
1614 }
1615 GNUNET_assert (NULL != zone_tail);
1616 if (zone_tail == last)
1617 {
1618 /* Done iterating over relevant zones in NAMESTORE, move
1619 rest of hash map to work queue as well. */
1620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1621 "Finished all NAMESTORE iterations!\n");
1622 GNUNET_STATISTICS_set (stats,
1623 "# Domain names without cached reply",
1624 GNUNET_CONTAINER_multihashmap_size (ns_pending),
1625 GNUNET_NO);
1626 GNUNET_CONTAINER_multihashmap_iterate (ns_pending, &move_to_queue, NULL);
1627 GNUNET_CONTAINER_multihashmap_destroy (ns_pending);
1628 ns_pending = NULL;
1629 start_time_reg_proc = GNUNET_TIME_absolute_get ();
1630 total_reg_proc_dns = 0;
1631 total_reg_proc_dns_ns = 0;
1632 return;
1633 }
1634 if (NULL == last)
1635 last = zone_head;
1636 else
1637 last = last->next;
1638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1639 "Starting iteration over zone `%s'!\n",
1640 last->domain);
1641 /* subtract left-overs from previous iteration */
1642 GNUNET_STATISTICS_update (stats,
1643 "# NAMESTORE records requested from cache",
1644 1,
1645 GNUNET_NO);
1646 ns_iterator_trigger_next = 1;
1647 GNUNET_STATISTICS_update (stats, "# zones iterated", 1, GNUNET_NO);
1648 zone_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
1649 &last->key,
1650 &ns_lookup_error_cb,
1651 NULL,
1652 &ns_lookup_result_cb,
1653 last,
1654 &iterate_zones,
1655 NULL);
1656}
1657
1658
1659/**
1660 * Begin processing hostnames from stdin.
1661 *
1662 * @param cls NULL
1663 */
1664static void
1665process_stdin (void *cls)
1666{
1667 static struct GNUNET_TIME_Absolute last;
1668 static uint64_t idot;
1669 char hn[256];
1670
1671 (void) cls;
1672 t = NULL;
1673 if (NULL != id)
1674 {
1675 GNUNET_IDENTITY_disconnect (id);
1676 id = NULL;
1677 }
1678 while (NULL != fgets (hn, sizeof(hn), stdin))
1679 {
1680 if (strlen (hn) > 0)
1681 hn[strlen (hn) - 1] = '\0'; /* eat newline */
1682 if (0 == idot)
1683 last = GNUNET_TIME_absolute_get ();
1684 idot++;
1685 if (0 == idot % 100000)
1686 {
1687 struct GNUNET_TIME_Relative delta;
1688
1689 delta = GNUNET_TIME_absolute_get_duration (last);
1690 last = GNUNET_TIME_absolute_get ();
1691 fprintf (stderr,
1692 "Read 100000 domain names in %s\n",
1693 GNUNET_STRINGS_relative_time_to_string (delta, GNUNET_YES));
1694 GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1695 }
1696 queue (hn);
1697 }
1698 fprintf (stderr,
1699 "Done reading %llu domain names\n",
1700 (unsigned long long) idot);
1701 GNUNET_STATISTICS_set (stats, "# domain names provided", idot, GNUNET_NO);
1702 iterate_zones (NULL);
1703}
1704
1705
1706/**
1707 * Method called to inform about the egos of this peer.
1708 *
1709 * When used with #GNUNET_IDENTITY_connect, this function is
1710 * initially called for all egos and then again whenever a
1711 * ego's name changes or if it is deleted. At the end of
1712 * the initial pass over all egos, the function is once called
1713 * with 'NULL' for @a ego. That does NOT mean that the callback won't
1714 * be invoked in the future or that there was an error.
1715 *
1716 * When used with #GNUNET_IDENTITY_create or #GNUNET_IDENTITY_get, this
1717 * function is only called ONCE, and 'NULL' being passed in @a ego does
1718 * indicate an error (for example because name is taken or no default value is
1719 * known). If @a ego is non-NULL and if '*ctx' is set in those callbacks, the
1720 * value WILL be passed to a subsequent call to the identity callback of
1721 * #GNUNET_IDENTITY_connect (if that one was not NULL).
1722 *
1723 * When an identity is renamed, this function is called with the
1724 * (known) @a ego but the NEW @a name.
1725 *
1726 * When an identity is deleted, this function is called with the
1727 * (known) ego and "NULL" for the @a name. In this case,
1728 * the @a ego is henceforth invalid (and the @a ctx should also be
1729 * cleaned up).
1730 *
1731 * @param cls closure
1732 * @param ego ego handle, NULL for end of list
1733 * @param ctx context for application to store data for this ego
1734 * (during the lifetime of this process, initially NULL)
1735 * @param name name assigned by the user for this ego,
1736 * NULL if the user just deleted the ego and it
1737 * must thus no longer be used
1738 */
1739static void
1740identity_cb (void *cls,
1741 struct GNUNET_IDENTITY_Ego *ego,
1742 void **ctx,
1743 const char *name)
1744{
1745 (void) cls;
1746 (void) ctx;
1747
1748 if (NULL == ego)
1749 {
1750 /* end of iteration */
1751 if (NULL == zone_head)
1752 {
1753 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No zone found\n");
1754 GNUNET_SCHEDULER_shutdown ();
1755 return;
1756 }
1757 /* zone_head non-null, process hostnames from stdin */
1758 t = GNUNET_SCHEDULER_add_now (&process_stdin, NULL);
1759 return;
1760 }
1761 if (NULL != name)
1762 {
1763 struct Zone *zone;
1764
1765 zone = GNUNET_new (struct Zone);
1766 zone->key = *GNUNET_IDENTITY_ego_get_private_key (ego);
1767 zone->domain = GNUNET_strdup (name);
1768 GNUNET_CONTAINER_DLL_insert (zone_head, zone_tail, zone);
1769 }
1770}
1771
1772
1773/**
1774 * Process requests from the queue, then if the queue is
1775 * not empty, try again.
1776 *
1777 * @param cls NULL
1778 * @param args remaining command-line arguments
1779 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1780 * @param cfg configuration
1781 */
1782static void
1783run (void *cls,
1784 char *const *args,
1785 const char *cfgfile,
1786 const struct GNUNET_CONFIGURATION_Handle *cfg)
1787{
1788 (void) cls;
1789 (void) args;
1790 (void) cfgfile;
1791 stats = GNUNET_STATISTICS_create ("zoneimport", cfg);
1792 req_heap = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN);
1793 ns_pending = GNUNET_CONTAINER_multihashmap_create (map_size, GNUNET_NO);
1794 if (NULL == ns_pending)
1795 {
1796 fprintf (stderr, "Failed to allocate memory for main hash map\n");
1797 return;
1798 }
1799 ctx = GNUNET_DNSSTUB_start (256);
1800 if (NULL == ctx)
1801 {
1802 fprintf (stderr, "Failed to initialize GNUnet DNS STUB\n");
1803 return;
1804 }
1805 if (NULL == args[0])
1806 {
1807 fprintf (stderr,
1808 "You must provide a list of DNS resolvers on the command line\n");
1809 return;
1810 }
1811 for (unsigned int i = 0; NULL != args[i]; i++)
1812 {
1813 if (GNUNET_OK != GNUNET_DNSSTUB_add_dns_ip (ctx, args[i]))
1814 {
1815 fprintf (stderr, "Failed to use `%s' for DNS resolver\n", args[i]);
1816 return;
1817 }
1818 }
1819
1820
1821 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1822 ns = GNUNET_NAMESTORE_connect (cfg);
1823 if (NULL == ns)
1824 {
1825 GNUNET_SCHEDULER_shutdown ();
1826 return;
1827 }
1828 id = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1829}
1830
1831
1832/**
1833 * Call with IP address of resolver to query.
1834 *
1835 * @param argc should be 2
1836 * @param argv[1] should contain IP address
1837 * @return 0 on success
1838 */
1839int
1840main (int argc, char *const *argv)
1841{
1842 struct GNUNET_GETOPT_CommandLineOption options[] =
1843 { GNUNET_GETOPT_option_uint ('s',
1844 "size",
1845 "MAPSIZE",
1846 gettext_noop (
1847 "size to use for the main hash map"),
1848 &map_size),
1849 GNUNET_GETOPT_option_relative_time (
1850 'm',
1851 "minimum-expiration",
1852 "RELATIVETIME",
1853 gettext_noop ("minimum expiration time we assume for imported records"),
1854 &minimum_expiration_time),
1855 GNUNET_GETOPT_OPTION_END };
1856 int ret;
1857
1858 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1859 return 2;
1860 if (GNUNET_OK != (ret = GNUNET_PROGRAM_run (argc,
1861 argv,
1862 "gnunet-zoneimport",
1863 "import DNS zone into namestore",
1864 options,
1865 &run,
1866 NULL)))
1867 return ret;
1868 GNUNET_free_nz ((void *) argv);
1869 fprintf (stderr,
1870 "Rejected %u names, had %u cached, did %u lookups, stored %u record sets\n"
1871 "Found %u records, %u lookups failed, %u/%u pending on shutdown\n",
1872 rejects,
1873 cached,
1874 lookups,
1875 record_sets,
1876 records,
1877 failures,
1878 pending,
1879 pending_rs);
1880 return 0;
1881}
1882
1883
1884/* end of gnunet-zoneimport.c */
diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in
deleted file mode 100644
index a9c928c66..000000000
--- a/src/namestore/namestore.conf.in
+++ /dev/null
@@ -1,50 +0,0 @@
1[namestore]
2START_ON_DEMAND = @START_ON_DEMAND@
3RUN_PER_USER = YES
4UNIXPATH = $GNUNET_USER_RUNTIME_DIR/gnunet-service-namestore.sock
5UNIX_MATCH_UID = NO
6UNIX_MATCH_GID = YES
7@UNIXONLY@ PORT = 2099
8HOSTNAME = localhost
9BINARY = gnunet-service-namestore
10ACCEPT_FROM = 127.0.0.1;
11ACCEPT_FROM6 = ::1;
12
13# Which database should we use?
14DATABASE = sqlite
15
16# Should we optimize publishing record by caching the mapping
17# from zone private keys to zone public keys in memory?
18# (Set to NO if totally paranoid about keeping private keys
19# in RAM longer than necessary.)
20CACHE_KEYS = YES
21
22
23[namestore-sqlite]
24FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db
25
26[namestore-heap]
27FILENAME = $GNUNET_DATA_HOME/namestore/heap.db
28
29
30[namestore-postgres]
31# How to connect to the database
32CONFIG = postgres:///gnunet
33# Use temporary tables
34TEMPORARY_TABLE = NO
35# Use asynchronous commit (SET synchronous_commit TO OFF).
36ASYNC_COMMIT = NO
37
38[uri]
39gns = gnunet-namestore -e 1a -u
40
41
42[fcfsd]
43# Name of the fcfs registration service binary (for ARM)
44BINARY = gnunet-namestore-fcfsd
45START_ON_DEMAND = NO
46UNIXPATH = $GNUNET_RUNTIME_DIR/gnunet-service-fcfsd.sock
47RELATIVE_RECORD_EXPIRATION = 7 d
48
49# On what port does the FCFS daemon listen for HTTP clients?
50HTTPPORT = 18080
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
deleted file mode 100644
index 583ec1e68..000000000
--- a/src/namestore/namestore.h
+++ /dev/null
@@ -1,408 +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 namestore/namestore.h
23 * @brief common internal definitions for namestore service
24 * @author Matthias Wachs
25 * @author Christian Grothoff
26 */
27#ifndef NAMESTORE_H
28#define NAMESTORE_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 namestore message with op id
39 */
40struct GNUNET_NAMESTORE_Header
41{
42 /**
43 * header.type will be GNUNET_MESSAGE_TYPE_NAMESTORE_*
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 * Store a record to the namestore (as authority).
57 */
58struct RecordStoreMessage
59{
60 /**
61 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE
62 */
63 struct GNUNET_NAMESTORE_Header gns_header;
64
65 /**
66 * Expiration time
67 */
68 struct GNUNET_TIME_AbsoluteNBO expire;
69
70 /**
71 * Name length
72 */
73 uint16_t name_len GNUNET_PACKED;
74
75 /**
76 * Length of serialized record data
77 */
78 uint16_t rd_len GNUNET_PACKED;
79
80 /**
81 * Number of records contained
82 */
83 uint16_t rd_count GNUNET_PACKED;
84
85 /**
86 * Reserved for alignment.
87 */
88 uint16_t reserved GNUNET_PACKED;
89
90 /**
91 * The private key of the authority.
92 */
93 struct GNUNET_IDENTITY_PrivateKey private_key;
94
95 /* followed by:
96 * name with length name_len
97 * serialized record data with rd_count records
98 */
99};
100
101
102/**
103 * Response to a record storage request.
104 */
105struct RecordStoreResponseMessage
106{
107 /**
108 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
109 */
110 struct GNUNET_NAMESTORE_Header gns_header;
111
112 /**
113 * #GNUNET_SYSERR on failure, #GNUNET_OK on success
114 */
115 int32_t op_result GNUNET_PACKED;
116
117 /**
118 * Error message length
119 */
120 uint16_t emsg_len GNUNET_PACKED;
121
122 /**
123 * Reserved for alignment.
124 */
125 uint16_t reserved GNUNET_PACKED;
126
127 /**
128 * Followed by error message
129 */
130};
131
132
133/**
134 * Lookup a label
135 */
136struct LabelLookupMessage
137{
138 /**
139 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP
140 */
141 struct GNUNET_NAMESTORE_Header gns_header;
142
143 /**
144 * Length of the name
145 */
146 uint32_t label_len GNUNET_PACKED;
147
148 /**
149 * The private key of the zone to look up in
150 */
151 struct GNUNET_IDENTITY_PrivateKey zone;
152
153 /* followed by:
154 * name with length name_len
155 */
156};
157
158
159/**
160 * Lookup a label
161 */
162struct LabelLookupResponseMessage
163{
164 /**
165 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
166 */
167 struct GNUNET_NAMESTORE_Header gns_header;
168
169 /**
170 * Name length
171 */
172 uint16_t name_len GNUNET_PACKED;
173
174 /**
175 * Length of serialized record data
176 */
177 uint16_t rd_len GNUNET_PACKED;
178
179 /**
180 * Number of records contained
181 */
182 uint16_t rd_count GNUNET_PACKED;
183
184 /**
185 * Was the label found in the database??
186 * #GNUNET_YES or #GNUNET_NO
187 */
188 int16_t found GNUNET_PACKED;
189
190 /**
191 * The private key of the authority.
192 */
193 struct GNUNET_IDENTITY_PrivateKey private_key;
194
195 /* followed by:
196 * name with length name_len
197 * serialized record data with rd_count records
198 */
199};
200
201
202/**
203 * Lookup a name for a zone hash
204 */
205struct ZoneToNameMessage
206{
207 /**
208 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME
209 */
210 struct GNUNET_NAMESTORE_Header gns_header;
211
212 /**
213 * The private key of the zone to look up in
214 */
215 struct GNUNET_IDENTITY_PrivateKey zone;
216
217 /**
218 * The public key of the target zone
219 */
220 struct GNUNET_IDENTITY_PublicKey value_zone;
221};
222
223
224/**
225 * Respone for zone to name lookup
226 */
227struct ZoneToNameResponseMessage
228{
229 /**
230 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE
231 */
232 struct GNUNET_NAMESTORE_Header gns_header;
233
234 /**
235 * Length of the name
236 */
237 uint16_t name_len GNUNET_PACKED;
238
239 /**
240 * Length of serialized record data
241 */
242 uint16_t rd_len GNUNET_PACKED;
243
244 /**
245 * Number of records contained
246 */
247 uint16_t rd_count GNUNET_PACKED;
248
249 /**
250 * result in NBO: #GNUNET_OK on success, #GNUNET_NO if there were no
251 * results, #GNUNET_SYSERR on error
252 */
253 int16_t res GNUNET_PACKED;
254
255 /**
256 * The private key of the zone that contained the name.
257 */
258 struct GNUNET_IDENTITY_PrivateKey zone;
259
260 /* followed by:
261 * name with length name_len
262 * serialized record data with rd_count records
263 */
264};
265
266
267/**
268 * Record is returned from the namestore (as authority).
269 */
270struct RecordResultMessage
271{
272 /**
273 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
274 */
275 struct GNUNET_NAMESTORE_Header gns_header;
276
277 /**
278 * Name length
279 */
280 uint16_t name_len GNUNET_PACKED;
281
282 /**
283 * Length of serialized record data
284 */
285 uint16_t rd_len GNUNET_PACKED;
286
287 /**
288 * Number of records contained
289 */
290 uint16_t rd_count GNUNET_PACKED;
291
292 /**
293 * always zero (for alignment)
294 */
295 uint16_t reserved GNUNET_PACKED;
296
297 /**
298 * The private key of the authority.
299 */
300 struct GNUNET_IDENTITY_PrivateKey private_key;
301
302 /* followed by:
303 * name with length name_len
304 * serialized record data with rd_count records
305 */
306};
307
308
309/**
310 * Start monitoring a zone.
311 */
312struct ZoneMonitorStartMessage
313{
314 /**
315 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START
316 */
317 struct GNUNET_MessageHeader header;
318
319 /**
320 * #GNUNET_YES to first iterate over all records,
321 * #GNUNET_NO to only monitor changes.o
322 */
323 uint32_t iterate_first GNUNET_PACKED;
324
325 /**
326 * Zone key.
327 */
328 struct GNUNET_IDENTITY_PrivateKey zone;
329};
330
331
332/**
333 * Ask for next result of zone iteration for the given operation
334 */
335struct ZoneMonitorNextMessage
336{
337 /**
338 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT
339 */
340 struct GNUNET_MessageHeader header;
341
342 /**
343 * Always zero.
344 */
345 uint32_t reserved;
346
347 /**
348 * Number of records to return to the iterator in one shot
349 * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_MONITOR_NEXT
350 * should be send again). In NBO.
351 */
352 uint64_t limit;
353};
354
355
356/**
357 * Start a zone iteration for the given zone
358 */
359struct ZoneIterationStartMessage
360{
361 /**
362 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START
363 */
364 struct GNUNET_NAMESTORE_Header gns_header;
365
366 /**
367 * Zone key. All zeros for "all zones".
368 */
369 struct GNUNET_IDENTITY_PrivateKey zone;
370};
371
372
373/**
374 * Ask for next result of zone iteration for the given operation
375 */
376struct ZoneIterationNextMessage
377{
378 /**
379 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT
380 */
381 struct GNUNET_NAMESTORE_Header gns_header;
382
383 /**
384 * Number of records to return to the iterator in one shot
385 * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT
386 * should be send again). In NBO.
387 */
388 uint64_t limit;
389};
390
391
392/**
393 * Stop zone iteration for the given operation
394 */
395struct ZoneIterationStopMessage
396{
397 /**
398 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP
399 */
400 struct GNUNET_NAMESTORE_Header gns_header;
401};
402
403
404GNUNET_NETWORK_STRUCT_END
405
406
407/* end of namestore.h */
408#endif
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
deleted file mode 100644
index 73f985803..000000000
--- a/src/namestore/namestore_api.c
+++ /dev/null
@@ -1,1387 +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 namestore/namestore_api.c
23 * @brief API to access the NAMESTORE 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_arm_service.h"
35#include "gnunet_signatures.h"
36#include "gnunet_gns_service.h"
37#include "gnunet_namestore_service.h"
38#include "namestore.h"
39
40
41#define LOG(kind, ...) GNUNET_log_from (kind, "namestore-api", __VA_ARGS__)
42
43/**
44 * We grant the namestore up to 1 minute of latency, if it is slower than
45 * that, store queries will fail.
46 */
47#define NAMESTORE_DELAY_TOLERANCE GNUNET_TIME_UNIT_MINUTES
48
49/**
50 * An QueueEntry used to store information for a pending
51 * NAMESTORE record operation
52 */
53struct GNUNET_NAMESTORE_QueueEntry
54{
55 /**
56 * Kept in a DLL.
57 */
58 struct GNUNET_NAMESTORE_QueueEntry *next;
59
60 /**
61 * Kept in a DLL.
62 */
63 struct GNUNET_NAMESTORE_QueueEntry *prev;
64
65 /**
66 * Main handle to access the namestore.
67 */
68 struct GNUNET_NAMESTORE_Handle *h;
69
70 /**
71 * Continuation to call
72 */
73 GNUNET_NAMESTORE_ContinuationWithStatus cont;
74
75 /**
76 * Closure for @e cont.
77 */
78 void *cont_cls;
79
80 /**
81 * Function to call with the records we get back; or NULL.
82 */
83 GNUNET_NAMESTORE_RecordMonitor proc;
84
85 /**
86 * Closure for @e proc.
87 */
88 void *proc_cls;
89
90 /**
91 * Function to call on errors.
92 */
93 GNUNET_SCHEDULER_TaskCallback error_cb;
94
95 /**
96 * Closure for @e error_cb.
97 */
98 void *error_cb_cls;
99
100 /**
101 * Envelope of the message to send to the service, if not yet
102 * sent.
103 */
104 struct GNUNET_MQ_Envelope *env;
105
106 /**
107 * Task scheduled to warn us if the namestore is way too slow.
108 */
109 struct GNUNET_SCHEDULER_Task *timeout_task;
110
111 /**
112 * The operation id this zone iteration operation has
113 */
114 uint32_t op_id;
115};
116
117
118/**
119 * Handle for a zone iterator operation
120 */
121struct GNUNET_NAMESTORE_ZoneIterator
122{
123 /**
124 * Kept in a DLL.
125 */
126 struct GNUNET_NAMESTORE_ZoneIterator *next;
127
128 /**
129 * Kept in a DLL.
130 */
131 struct GNUNET_NAMESTORE_ZoneIterator *prev;
132
133 /**
134 * Main handle to access the namestore.
135 */
136 struct GNUNET_NAMESTORE_Handle *h;
137
138 /**
139 * Function to call on completion.
140 */
141 GNUNET_SCHEDULER_TaskCallback finish_cb;
142
143 /**
144 * Closure for @e error_cb.
145 */
146 void *finish_cb_cls;
147
148 /**
149 * The continuation to call with the results
150 */
151 GNUNET_NAMESTORE_RecordMonitor proc;
152
153 /**
154 * Closure for @e proc.
155 */
156 void *proc_cls;
157
158 /**
159 * Function to call on errors.
160 */
161 GNUNET_SCHEDULER_TaskCallback error_cb;
162
163 /**
164 * Closure for @e error_cb.
165 */
166 void *error_cb_cls;
167
168 /**
169 * Envelope of the message to send to the service, if not yet
170 * sent.
171 */
172 struct GNUNET_MQ_Envelope *env;
173
174 /**
175 * Private key of the zone.
176 */
177 struct GNUNET_IDENTITY_PrivateKey zone;
178
179 /**
180 * The operation id this zone iteration operation has
181 */
182 uint32_t op_id;
183};
184
185
186/**
187 * Connection to the NAMESTORE service.
188 */
189struct GNUNET_NAMESTORE_Handle
190{
191 /**
192 * Configuration to use.
193 */
194 const struct GNUNET_CONFIGURATION_Handle *cfg;
195
196 /**
197 * Connection to the service (if available).
198 */
199 struct GNUNET_MQ_Handle *mq;
200
201 /**
202 * Head of pending namestore queue entries
203 */
204 struct GNUNET_NAMESTORE_QueueEntry *op_head;
205
206 /**
207 * Tail of pending namestore queue entries
208 */
209 struct GNUNET_NAMESTORE_QueueEntry *op_tail;
210
211 /**
212 * Head of pending namestore zone iterator entries
213 */
214 struct GNUNET_NAMESTORE_ZoneIterator *z_head;
215
216 /**
217 * Tail of pending namestore zone iterator entries
218 */
219 struct GNUNET_NAMESTORE_ZoneIterator *z_tail;
220
221 /**
222 * Reconnect task
223 */
224 struct GNUNET_SCHEDULER_Task *reconnect_task;
225
226 /**
227 * Delay introduced before we reconnect.
228 */
229 struct GNUNET_TIME_Relative reconnect_delay;
230
231 /**
232 * Should we reconnect to service due to some serious error?
233 */
234 int reconnect;
235
236 /**
237 * The last operation id used for a NAMESTORE operation
238 */
239 uint32_t last_op_id_used;
240};
241
242
243/**
244 * Disconnect from service and then reconnect.
245 *
246 * @param h our handle
247 */
248static void
249force_reconnect (struct GNUNET_NAMESTORE_Handle *h);
250
251
252/**
253 * Find the queue entry that matches the @a rid
254 *
255 * @param h namestore handle
256 * @param rid id to look up
257 * @return NULL if @a rid was not found
258 */
259static struct GNUNET_NAMESTORE_QueueEntry *
260find_qe (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid)
261{
262 struct GNUNET_NAMESTORE_QueueEntry *qe;
263
264 for (qe = h->op_head; qe != NULL; qe = qe->next)
265 if (qe->op_id == rid)
266 return qe;
267 return NULL;
268}
269
270
271/**
272 * Find the zone iteration entry that matches the @a rid
273 *
274 * @param h namestore handle
275 * @param rid id to look up
276 * @return NULL if @a rid was not found
277 */
278static struct GNUNET_NAMESTORE_ZoneIterator *
279find_zi (struct GNUNET_NAMESTORE_Handle *h, uint32_t rid)
280{
281 struct GNUNET_NAMESTORE_ZoneIterator *ze;
282
283 for (ze = h->z_head; ze != NULL; ze = ze->next)
284 if (ze->op_id == rid)
285 return ze;
286 return NULL;
287}
288
289
290/**
291 * Free @a qe.
292 *
293 * @param qe entry to free
294 */
295static void
296free_qe (struct GNUNET_NAMESTORE_QueueEntry *qe)
297{
298 struct GNUNET_NAMESTORE_Handle *h = qe->h;
299
300 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, qe);
301 if (NULL != qe->env)
302 GNUNET_MQ_discard (qe->env);
303 if (NULL != qe->timeout_task)
304 GNUNET_SCHEDULER_cancel (qe->timeout_task);
305 GNUNET_free (qe);
306}
307
308
309/**
310 * Free @a ze.
311 *
312 * @param ze entry to free
313 */
314static void
315free_ze (struct GNUNET_NAMESTORE_ZoneIterator *ze)
316{
317 struct GNUNET_NAMESTORE_Handle *h = ze->h;
318
319 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, ze);
320 if (NULL != ze->env)
321 GNUNET_MQ_discard (ze->env);
322 GNUNET_free (ze);
323}
324
325
326/**
327 * Check that @a rd_buf of length @a rd_len contains
328 * @a rd_count records.
329 *
330 * @param rd_len length of @a rd_buf
331 * @param rd_buf buffer with serialized records
332 * @param rd_count number of records expected
333 * @return #GNUNET_OK if @a rd_buf is well-formed
334 */
335static int
336check_rd (size_t rd_len, const void *rd_buf, unsigned int rd_count)
337{
338 struct GNUNET_GNSRECORD_Data rd[rd_count];
339
340 if (GNUNET_OK !=
341 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_buf, rd_count, rd))
342 {
343 GNUNET_break (0);
344 return GNUNET_SYSERR;
345 }
346 return GNUNET_OK;
347}
348
349/**
350 * Handle an incoming message of type
351 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
352 *
353 * @param cls
354 * @param msg the message we received
355 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
356 */
357static int
358check_record_store_response (void *cls,
359 const struct RecordStoreResponseMessage *msg)
360{
361 const char *emsg;
362 size_t msg_len;
363 size_t emsg_len;
364
365 (void) cls;
366 msg_len = ntohs (msg->gns_header.header.size);
367 emsg_len = ntohs (msg->emsg_len);
368 if (0 != ntohs (msg->reserved))
369 {
370 GNUNET_break (0);
371 return GNUNET_SYSERR;
372 }
373 if (msg_len != sizeof(struct RecordStoreResponseMessage) + emsg_len)
374 {
375 GNUNET_break (0);
376 return GNUNET_SYSERR;
377 }
378 emsg = (const char *) &msg[1];
379 if ((0 != emsg_len) && ('\0' != emsg[emsg_len - 1]))
380 {
381 GNUNET_break (0);
382 return GNUNET_SYSERR;
383 }
384 return GNUNET_OK;
385}
386
387
388/**
389 * Handle an incoming message of type
390 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
391 *
392 * @param cls
393 * @param msg the message we received
394 */
395static void
396handle_record_store_response (void *cls,
397 const struct RecordStoreResponseMessage *msg)
398{
399 struct GNUNET_NAMESTORE_Handle *h = cls;
400 struct GNUNET_NAMESTORE_QueueEntry *qe;
401 int res;
402 const char *emsg;
403
404 qe = find_qe (h, ntohl (msg->gns_header.r_id));
405 emsg = (const char *) &msg[1];
406 res = ntohl (msg->op_result);
407 LOG (GNUNET_ERROR_TYPE_DEBUG,
408 "Received RECORD_STORE_RESPONSE with result %d\n",
409 res);
410 if (NULL == qe)
411 return;
412 if (NULL != qe->cont)
413 qe->cont (qe->cont_cls, res,
414 (GNUNET_OK == res) ? NULL : emsg);
415 free_qe (qe);
416}
417
418
419/**
420 * Check validity of an incoming message of type
421 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
422 *
423 * @param cls
424 * @param msg the message we received
425 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
426 */
427static int
428check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
429{
430 const char *name;
431 size_t exp_msg_len;
432 size_t msg_len;
433 size_t name_len;
434 size_t rd_len;
435
436 (void) cls;
437 rd_len = ntohs (msg->rd_len);
438 msg_len = ntohs (msg->gns_header.header.size);
439 name_len = ntohs (msg->name_len);
440 exp_msg_len = sizeof(*msg) + name_len + rd_len;
441 if (msg_len != exp_msg_len)
442 {
443 GNUNET_break (0);
444 return GNUNET_SYSERR;
445 }
446 name = (const char *) &msg[1];
447 if ((name_len > 0) && ('\0' != name[name_len - 1]))
448 {
449 GNUNET_break (0);
450 return GNUNET_SYSERR;
451 }
452 if (GNUNET_NO == ntohs (msg->found))
453 {
454 if (0 != ntohs (msg->rd_count))
455 {
456 GNUNET_break (0);
457 return GNUNET_SYSERR;
458 }
459 return GNUNET_OK;
460 }
461 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
462}
463
464
465/**
466 * Handle an incoming message of type
467 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
468 *
469 * @param cls
470 * @param msg the message we received
471 */
472static void
473handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
474{
475 struct GNUNET_NAMESTORE_Handle *h = cls;
476 struct GNUNET_NAMESTORE_QueueEntry *qe;
477 const char *name;
478 const char *rd_tmp;
479 size_t name_len;
480 size_t rd_len;
481 unsigned int rd_count;
482 int16_t found = (int16_t) ntohs (msg->found);
483
484 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT (found=%i)\n",
485 found);
486 qe = find_qe (h, ntohl (msg->gns_header.r_id));
487 if (NULL == qe)
488 return;
489 rd_len = ntohs (msg->rd_len);
490 rd_count = ntohs (msg->rd_count);
491 name_len = ntohs (msg->name_len);
492 name = (const char *) &msg[1];
493 if (GNUNET_NO == found)
494 {
495 /* label was not in namestore */
496 if (NULL != qe->proc)
497 qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL);
498 free_qe (qe);
499 return;
500 }
501 if (GNUNET_SYSERR == found)
502 {
503 if (NULL != qe->error_cb)
504 qe->error_cb (qe->error_cb_cls);
505 free_qe (qe);
506 return;
507 }
508
509 rd_tmp = &name[name_len];
510 {
511 struct GNUNET_GNSRECORD_Data rd[rd_count];
512
513 GNUNET_assert (
514 GNUNET_OK ==
515 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
516 if (0 == name_len)
517 name = NULL;
518 if (NULL != qe->proc)
519 qe->proc (qe->proc_cls,
520 &msg->private_key,
521 name,
522 rd_count,
523 (rd_count > 0) ? rd : NULL);
524 }
525 free_qe (qe);
526}
527
528
529/**
530 * Handle an incoming message of type
531 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
532 *
533 * @param cls
534 * @param msg the message we received
535 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
536 */
537static int
538check_record_result (void *cls, const struct RecordResultMessage *msg)
539{
540 static struct GNUNET_IDENTITY_PrivateKey priv_dummy;
541 const char *name;
542 size_t msg_len;
543 size_t name_len;
544 size_t rd_len;
545
546 (void) cls;
547 rd_len = ntohs (msg->rd_len);
548 msg_len = ntohs (msg->gns_header.header.size);
549 name_len = ntohs (msg->name_len);
550 if (0 != ntohs (msg->reserved))
551 {
552 GNUNET_break (0);
553 return GNUNET_SYSERR;
554 }
555 if (msg_len != sizeof(struct RecordResultMessage) + name_len + rd_len)
556 {
557 GNUNET_break (0);
558 return GNUNET_SYSERR;
559 }
560 name = (const char *) &msg[1];
561 if ((0 == name_len) || ('\0' != name[name_len - 1]))
562 {
563 GNUNET_break (0);
564 return GNUNET_SYSERR;
565 }
566 if (0 == GNUNET_memcmp (&msg->private_key, &priv_dummy))
567 {
568 GNUNET_break (0);
569 return GNUNET_SYSERR;
570 }
571 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
572}
573
574
575/**
576 * Handle an incoming message of type
577 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
578 *
579 * @param cls
580 * @param msg the message we received
581 */
582static void
583handle_record_result (void *cls, const struct RecordResultMessage *msg)
584{
585 struct GNUNET_NAMESTORE_Handle *h = cls;
586 struct GNUNET_NAMESTORE_QueueEntry *qe;
587 struct GNUNET_NAMESTORE_ZoneIterator *ze;
588 const char *name;
589 const char *rd_tmp;
590 size_t name_len;
591 size_t rd_len;
592 unsigned int rd_count;
593
594 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n");
595 rd_len = ntohs (msg->rd_len);
596 rd_count = ntohs (msg->rd_count);
597 name_len = ntohs (msg->name_len);
598 ze = find_zi (h, ntohl (msg->gns_header.r_id));
599 qe = find_qe (h, ntohl (msg->gns_header.r_id));
600 if ((NULL == ze) && (NULL == qe))
601 return; /* rid not found */
602 if ((NULL != ze) && (NULL != qe))
603 {
604 GNUNET_break (0); /* rid ambiguous */
605 force_reconnect (h);
606 return;
607 }
608 name = (const char *) &msg[1];
609 rd_tmp = &name[name_len];
610 {
611 struct GNUNET_GNSRECORD_Data rd[rd_count];
612
613 GNUNET_assert (
614 GNUNET_OK ==
615 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
616 if (0 == name_len)
617 name = NULL;
618 if (NULL != qe)
619 {
620 if (NULL != qe->proc)
621 qe->proc (qe->proc_cls,
622 &msg->private_key,
623 name,
624 rd_count,
625 (rd_count > 0) ? rd : NULL);
626 free_qe (qe);
627 return;
628 }
629 if (NULL != ze)
630 {
631 if (NULL != ze->proc)
632 ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd);
633 return;
634 }
635 }
636 GNUNET_assert (0);
637}
638
639
640/**
641 * Handle an incoming message of type
642 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
643 *
644 * @param cls
645 * @param msg the message we received
646 */
647static void
648handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg)
649{
650 struct GNUNET_NAMESTORE_Handle *h = cls;
651 struct GNUNET_NAMESTORE_QueueEntry *qe;
652 struct GNUNET_NAMESTORE_ZoneIterator *ze;
653
654 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n");
655 ze = find_zi (h, ntohl (msg->r_id));
656 qe = find_qe (h, ntohl (msg->r_id));
657 if ((NULL == ze) && (NULL == qe))
658 return; /* rid not found */
659 if ((NULL != ze) && (NULL != qe))
660 {
661 GNUNET_break (0); /* rid ambiguous */
662 force_reconnect (h);
663 return;
664 }
665 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n");
666 if (NULL == ze)
667 {
668 GNUNET_break (0);
669 force_reconnect (h);
670 return;
671 }
672 if (NULL != ze->finish_cb)
673 ze->finish_cb (ze->finish_cb_cls);
674 free_ze (ze);
675}
676
677
678/**
679 * Handle an incoming message of type
680 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
681 *
682 * @param qe the respective entry in the message queue
683 * @param msg the message we received
684 * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
685 */
686static int
687check_zone_to_name_response (void *cls,
688 const struct ZoneToNameResponseMessage *msg)
689{
690 size_t name_len;
691 size_t rd_ser_len;
692 const char *name_tmp;
693
694 (void) cls;
695 if (GNUNET_OK != ntohs (msg->res))
696 return GNUNET_OK;
697 name_len = ntohs (msg->name_len);
698 rd_ser_len = ntohs (msg->rd_len);
699 if (ntohs (msg->gns_header.header.size) !=
700 sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
701 {
702 GNUNET_break (0);
703 return GNUNET_SYSERR;
704 }
705 name_tmp = (const char *) &msg[1];
706 if ((name_len > 0) && ('\0' != name_tmp[name_len - 1]))
707 {
708 GNUNET_break (0);
709 return GNUNET_SYSERR;
710 }
711 return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count));
712}
713
714
715/**
716 * Handle an incoming message of type
717 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
718 *
719 * @param cls
720 * @param msg the message we received
721 */
722static void
723handle_zone_to_name_response (void *cls,
724 const struct ZoneToNameResponseMessage *msg)
725{
726 struct GNUNET_NAMESTORE_Handle *h = cls;
727 struct GNUNET_NAMESTORE_QueueEntry *qe;
728 int res;
729 size_t name_len;
730 size_t rd_ser_len;
731 unsigned int rd_count;
732 const char *name_tmp;
733 const char *rd_tmp;
734
735 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n");
736 qe = find_qe (h, ntohl (msg->gns_header.r_id));
737 if (NULL == qe)
738 {
739 LOG (GNUNET_ERROR_TYPE_WARNING,
740 "Response queue already gone...\n");
741 return;
742 }
743 res = ntohs (msg->res);
744 switch (res)
745 {
746 case GNUNET_SYSERR:
747 LOG (GNUNET_ERROR_TYPE_DEBUG,
748 "An error occurred during zone to name operation\n");
749 break;
750
751 case GNUNET_NO:
752 LOG (GNUNET_ERROR_TYPE_DEBUG,
753 "Namestore has no result for zone to name mapping \n");
754 if (NULL != qe->proc)
755 qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
756 free_qe (qe);
757 return;
758
759 case GNUNET_YES:
760 LOG (GNUNET_ERROR_TYPE_DEBUG,
761 "Namestore has result for zone to name mapping \n");
762 name_len = ntohs (msg->name_len);
763 rd_count = ntohs (msg->rd_count);
764 rd_ser_len = ntohs (msg->rd_len);
765 name_tmp = (const char *) &msg[1];
766 rd_tmp = &name_tmp[name_len];
767 {
768 struct GNUNET_GNSRECORD_Data rd[rd_count];
769
770 GNUNET_assert (GNUNET_OK ==
771 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
772 rd_tmp,
773 rd_count,
774 rd));
775 /* normal end, call continuation with result */
776 if (NULL != qe->proc)
777 qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd);
778 /* return is important here: break would call continuation with error! */
779 free_qe (qe);
780 return;
781 }
782
783 default:
784 GNUNET_break (0);
785 force_reconnect (h);
786 return;
787 }
788 /* error case, call continuation with error */
789 if (NULL != qe->error_cb)
790 qe->error_cb (qe->error_cb_cls);
791 free_qe (qe);
792}
793
794
795/**
796 * Generic error handler, called with the appropriate error code and
797 * the same closure specified at the creation of the message queue.
798 * Not every message queue implementation supports an error handler.
799 *
800 * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
801 * @param error error code
802 */
803static void
804mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
805{
806 struct GNUNET_NAMESTORE_Handle *h = cls;
807
808 (void) error;
809 force_reconnect (h);
810}
811
812
813/**
814 * Reconnect to namestore service.
815 *
816 * @param h the handle to the NAMESTORE service
817 */
818static void
819reconnect (struct GNUNET_NAMESTORE_Handle *h)
820{
821 struct GNUNET_MQ_MessageHandler handlers[] =
822 { GNUNET_MQ_hd_var_size (record_store_response,
823 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
824 struct RecordStoreResponseMessage,
825 h),
826 GNUNET_MQ_hd_var_size (zone_to_name_response,
827 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
828 struct ZoneToNameResponseMessage,
829 h),
830 GNUNET_MQ_hd_var_size (record_result,
831 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
832 struct RecordResultMessage,
833 h),
834 GNUNET_MQ_hd_fixed_size (record_result_end,
835 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END,
836 struct GNUNET_NAMESTORE_Header,
837 h),
838 GNUNET_MQ_hd_var_size (lookup_result,
839 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
840 struct LabelLookupResponseMessage,
841 h),
842 GNUNET_MQ_handler_end () };
843 struct GNUNET_NAMESTORE_ZoneIterator *it;
844 struct GNUNET_NAMESTORE_QueueEntry *qe;
845
846 GNUNET_assert (NULL == h->mq);
847 h->mq =
848 GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h);
849 if (NULL == h->mq)
850 return;
851 /* re-transmit pending requests that waited for a reconnect... */
852 for (it = h->z_head; NULL != it; it = it->next)
853 {
854 GNUNET_MQ_send (h->mq, it->env);
855 it->env = NULL;
856 }
857 for (qe = h->op_head; NULL != qe; qe = qe->next)
858 {
859 GNUNET_MQ_send (h->mq, qe->env);
860 qe->env = NULL;
861 }
862}
863
864
865/**
866 * Re-establish the connection to the service.
867 *
868 * @param cls handle to use to re-connect.
869 */
870static void
871reconnect_task (void *cls)
872{
873 struct GNUNET_NAMESTORE_Handle *h = cls;
874
875 h->reconnect_task = NULL;
876 reconnect (h);
877}
878
879
880/**
881 * Disconnect from service and then reconnect.
882 *
883 * @param h our handle
884 */
885static void
886force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
887{
888 struct GNUNET_NAMESTORE_ZoneIterator *ze;
889 struct GNUNET_NAMESTORE_QueueEntry *qe;
890
891 GNUNET_MQ_destroy (h->mq);
892 h->mq = NULL;
893 while (NULL != (ze = h->z_head))
894 {
895 if (NULL != ze->error_cb)
896 ze->error_cb (ze->error_cb_cls);
897 free_ze (ze);
898 }
899 while (NULL != (qe = h->op_head))
900 {
901 if (NULL != qe->error_cb)
902 qe->error_cb (qe->error_cb_cls);
903 if (NULL != qe->cont)
904 qe->cont (qe->cont_cls,
905 GNUNET_SYSERR,
906 "failure in communication with namestore service");
907 free_qe (qe);
908 }
909
910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n");
911 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
912 h->reconnect_task =
913 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h);
914}
915
916
917/**
918 * Get a fresh operation id to distinguish between namestore requests
919 *
920 * @param h the namestore handle
921 * @return next operation id to use
922 */
923static uint32_t
924get_op_id (struct GNUNET_NAMESTORE_Handle *h)
925{
926 return h->last_op_id_used++;
927}
928
929
930/**
931 * Initialize the connection with the NAMESTORE service.
932 *
933 * @param cfg configuration to use
934 * @return handle to the GNS service, or NULL on error
935 */
936struct GNUNET_NAMESTORE_Handle *
937GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
938{
939 struct GNUNET_NAMESTORE_Handle *h;
940
941 h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
942 h->cfg = cfg;
943 reconnect (h);
944 if (NULL == h->mq)
945 {
946 GNUNET_free (h);
947 return NULL;
948 }
949 return h;
950}
951
952
953/**
954 * Disconnect from the namestore service (and free associated
955 * resources).
956 *
957 * @param h handle to the namestore
958 */
959void
960GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
961{
962 struct GNUNET_NAMESTORE_QueueEntry *q;
963 struct GNUNET_NAMESTORE_ZoneIterator *z;
964
965 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
966 GNUNET_break (NULL == h->op_head);
967 while (NULL != (q = h->op_head))
968 {
969 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
970 GNUNET_free (q);
971 }
972 GNUNET_break (NULL == h->z_head);
973 while (NULL != (z = h->z_head))
974 {
975 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
976 GNUNET_free (z);
977 }
978 if (NULL != h->mq)
979 {
980 GNUNET_MQ_destroy (h->mq);
981 h->mq = NULL;
982 }
983 if (NULL != h->reconnect_task)
984 {
985 GNUNET_SCHEDULER_cancel (h->reconnect_task);
986 h->reconnect_task = NULL;
987 }
988 GNUNET_free (h);
989}
990
991
992/**
993 * Task launched to warn the user that the namestore is
994 * excessively slow and that a query was thus dropped.
995 *
996 * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
997 */
998static void
999warn_delay (void *cls)
1000{
1001 struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
1002
1003 qe->timeout_task = NULL;
1004 LOG (GNUNET_ERROR_TYPE_WARNING,
1005 "Did not receive response from namestore after %s!\n",
1006 GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
1007 GNUNET_YES));
1008 if (NULL != qe->cont)
1009 {
1010 qe->cont (qe->cont_cls, GNUNET_SYSERR, "timeout");
1011 qe->cont = NULL;
1012 }
1013 GNUNET_NAMESTORE_cancel (qe);
1014}
1015
1016
1017struct GNUNET_NAMESTORE_QueueEntry *
1018GNUNET_NAMESTORE_records_store (
1019 struct GNUNET_NAMESTORE_Handle *h,
1020 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1021 const char *label,
1022 unsigned int rd_count,
1023 const struct GNUNET_GNSRECORD_Data *rd,
1024 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1025 void *cont_cls)
1026{
1027 struct GNUNET_NAMESTORE_QueueEntry *qe;
1028 struct GNUNET_MQ_Envelope *env;
1029 char *name_tmp;
1030 char *rd_ser;
1031 ssize_t rd_ser_len;
1032 size_t name_len;
1033 uint32_t rid;
1034 struct RecordStoreMessage *msg;
1035 ssize_t sret;
1036
1037 name_len = strlen (label) + 1;
1038 if (name_len > MAX_NAME_LEN)
1039 {
1040 GNUNET_break (0);
1041 return NULL;
1042 }
1043 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1044 if (rd_ser_len < 0)
1045 {
1046 GNUNET_break (0);
1047 return NULL;
1048 }
1049 if (rd_ser_len > UINT16_MAX)
1050 {
1051 GNUNET_break (0);
1052 return NULL;
1053 }
1054 rid = get_op_id (h);
1055 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1056 qe->h = h;
1057 qe->cont = cont;
1058 qe->cont_cls = cont_cls;
1059 qe->op_id = rid;
1060 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1061
1062 /* setup msg */
1063 env = GNUNET_MQ_msg_extra (msg,
1064 name_len + rd_ser_len,
1065 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1066 msg->gns_header.r_id = htonl (rid);
1067 msg->name_len = htons (name_len);
1068 msg->rd_count = htons (rd_count);
1069 msg->rd_len = htons (rd_ser_len);
1070 msg->reserved = ntohs (0);
1071 msg->private_key = *pkey;
1072
1073 name_tmp = (char *) &msg[1];
1074 GNUNET_memcpy (name_tmp, label, name_len);
1075 rd_ser = &name_tmp[name_len];
1076 sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser);
1077 if ((0 > sret) || (sret != rd_ser_len))
1078 {
1079 GNUNET_break (0);
1080 GNUNET_free (env);
1081 return NULL;
1082 }
1083 GNUNET_assert (rd_ser_len == sret);
1084 LOG (GNUNET_ERROR_TYPE_DEBUG,
1085 "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1086 label,
1087 rd_count);
1088 qe->timeout_task =
1089 GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe);
1090 if (NULL == h->mq)
1091 {
1092 qe->env = env;
1093 LOG (GNUNET_ERROR_TYPE_WARNING,
1094 "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1095 }
1096 else
1097 {
1098 GNUNET_MQ_send (h->mq, env);
1099 }
1100 return qe;
1101}
1102
1103/**
1104 * TODO: Experimental API will replace API above.
1105 */
1106struct GNUNET_NAMESTORE_QueueEntry *
1107GNUNET_NAMESTORE_records_replace (
1108 struct GNUNET_NAMESTORE_Handle *h,
1109 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1110 const char *label,
1111 unsigned int rd_count,
1112 const struct GNUNET_GNSRECORD_Data *rd,
1113 GNUNET_NAMESTORE_ContinuationWithStatus cont,
1114 void *cont_cls)
1115{
1116 return GNUNET_NAMESTORE_records_store (h, pkey, label, rd_count, rd,
1117 cont, cont_cls);
1118}
1119
1120struct GNUNET_NAMESTORE_QueueEntry *
1121GNUNET_NAMESTORE_records_lookup (
1122 struct GNUNET_NAMESTORE_Handle *h,
1123 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1124 const char *label,
1125 GNUNET_SCHEDULER_TaskCallback error_cb,
1126 void *error_cb_cls,
1127 GNUNET_NAMESTORE_RecordMonitor rm,
1128 void *rm_cls)
1129{
1130 struct GNUNET_NAMESTORE_QueueEntry *qe;
1131 struct GNUNET_MQ_Envelope *env;
1132 struct LabelLookupMessage *msg;
1133 size_t label_len;
1134
1135 if (1 == (label_len = strlen (label) + 1))
1136 {
1137 GNUNET_break (0);
1138 return NULL;
1139 }
1140
1141 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1142 qe->h = h;
1143 qe->error_cb = error_cb;
1144 qe->error_cb_cls = error_cb_cls;
1145 qe->proc = rm;
1146 qe->proc_cls = rm_cls;
1147 qe->op_id = get_op_id (h);
1148 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1149
1150 env = GNUNET_MQ_msg_extra (msg,
1151 label_len,
1152 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1153 msg->gns_header.r_id = htonl (qe->op_id);
1154 msg->zone = *pkey;
1155 msg->label_len = htonl (label_len);
1156 GNUNET_memcpy (&msg[1], label, label_len);
1157 if (NULL == h->mq)
1158 qe->env = env;
1159 else
1160 GNUNET_MQ_send (h->mq, env);
1161 return qe;
1162}
1163
1164
1165/**
1166 * TODO experimental API. Will replace old API above.
1167 */
1168struct GNUNET_NAMESTORE_QueueEntry *
1169GNUNET_NAMESTORE_records_select (
1170 struct GNUNET_NAMESTORE_Handle *h,
1171 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1172 const char *label,
1173 GNUNET_SCHEDULER_TaskCallback error_cb,
1174 void *error_cb_cls,
1175 GNUNET_NAMESTORE_RecordMonitor rm,
1176 void *rm_cls)
1177{
1178 return GNUNET_NAMESTORE_records_lookup (h, pkey, label,
1179 error_cb, error_cb_cls,
1180 rm, rm_cls);
1181}
1182
1183struct GNUNET_NAMESTORE_QueueEntry *
1184GNUNET_NAMESTORE_zone_to_name (
1185 struct GNUNET_NAMESTORE_Handle *h,
1186 const struct GNUNET_IDENTITY_PrivateKey *zone,
1187 const struct GNUNET_IDENTITY_PublicKey *value_zone,
1188 GNUNET_SCHEDULER_TaskCallback error_cb,
1189 void *error_cb_cls,
1190 GNUNET_NAMESTORE_RecordMonitor proc,
1191 void *proc_cls)
1192{
1193 struct GNUNET_NAMESTORE_QueueEntry *qe;
1194 struct GNUNET_MQ_Envelope *env;
1195 struct ZoneToNameMessage *msg;
1196 uint32_t rid;
1197
1198 rid = get_op_id (h);
1199 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1200 qe->h = h;
1201 qe->error_cb = error_cb;
1202 qe->error_cb_cls = error_cb_cls;
1203 qe->proc = proc;
1204 qe->proc_cls = proc_cls;
1205 qe->op_id = rid;
1206 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1207
1208 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1209 msg->gns_header.r_id = htonl (rid);
1210 msg->zone = *zone;
1211 msg->value_zone = *value_zone;
1212 if (NULL == h->mq)
1213 qe->env = env;
1214 else
1215 GNUNET_MQ_send (h->mq, env);
1216 return qe;
1217}
1218
1219
1220/**
1221 * Starts a new zone iteration (used to periodically PUT all of our
1222 * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1223 * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1224 * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1225 * immediately, and then again after
1226 * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1227 *
1228 * @param h handle to the namestore
1229 * @param zone zone to access, NULL for all zones
1230 * @param error_cb function to call on error (i.e. disconnect)
1231 * @param error_cb_cls closure for @a error_cb
1232 * @param proc function to call on each name from the zone; it
1233 * will be called repeatedly with a value (if available)
1234 * @param proc_cls closure for @a proc
1235 * @param finish_cb function to call on completion
1236 * @param finish_cb_cls closure for @a finish_cb
1237 * @return an iterator handle to use for iteration
1238 */
1239struct GNUNET_NAMESTORE_ZoneIterator *
1240GNUNET_NAMESTORE_zone_iteration_start (
1241 struct GNUNET_NAMESTORE_Handle *h,
1242 const struct GNUNET_IDENTITY_PrivateKey *zone,
1243 GNUNET_SCHEDULER_TaskCallback error_cb,
1244 void *error_cb_cls,
1245 GNUNET_NAMESTORE_RecordMonitor proc,
1246 void *proc_cls,
1247 GNUNET_SCHEDULER_TaskCallback finish_cb,
1248 void *finish_cb_cls)
1249{
1250 struct GNUNET_NAMESTORE_ZoneIterator *it;
1251 struct GNUNET_MQ_Envelope *env;
1252 struct ZoneIterationStartMessage *msg;
1253 uint32_t rid;
1254
1255 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n");
1256 rid = get_op_id (h);
1257 it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1258 it->h = h;
1259 it->error_cb = error_cb;
1260 it->error_cb_cls = error_cb_cls;
1261 it->finish_cb = finish_cb;
1262 it->finish_cb_cls = finish_cb_cls;
1263 it->proc = proc;
1264 it->proc_cls = proc_cls;
1265 it->op_id = rid;
1266 if (NULL != zone)
1267 it->zone = *zone;
1268 GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1269 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1270 msg->gns_header.r_id = htonl (rid);
1271 if (NULL != zone)
1272 msg->zone = *zone;
1273 if (NULL == h->mq)
1274 it->env = env;
1275 else
1276 GNUNET_MQ_send (h->mq, env);
1277 return it;
1278}
1279
1280
1281/**
1282 * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1283 * for the next record.
1284 *
1285 * @param it the iterator
1286 * @param limit number of records to return to the iterator in one shot
1287 * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1288 */
1289void
1290GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1291 uint64_t limit)
1292{
1293 struct GNUNET_NAMESTORE_Handle *h = it->h;
1294 struct ZoneIterationNextMessage *msg;
1295 struct GNUNET_MQ_Envelope *env;
1296
1297 LOG (GNUNET_ERROR_TYPE_DEBUG,
1298 "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1299 (unsigned long long) limit);
1300 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1301 msg->gns_header.r_id = htonl (it->op_id);
1302 msg->limit = GNUNET_htonll (limit);
1303 GNUNET_MQ_send (h->mq, env);
1304}
1305
1306
1307/**
1308 * Stops iteration and releases the namestore handle for further calls.
1309 *
1310 * @param it the iterator
1311 */
1312void
1313GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1314{
1315 struct GNUNET_NAMESTORE_Handle *h = it->h;
1316 struct GNUNET_MQ_Envelope *env;
1317 struct ZoneIterationStopMessage *msg;
1318
1319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n");
1320 if (NULL != h->mq)
1321 {
1322 env =
1323 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1324 msg->gns_header.r_id = htonl (it->op_id);
1325 GNUNET_MQ_send (h->mq, env);
1326 }
1327 free_ze (it);
1328}
1329
1330
1331/**
1332 * Cancel a namestore operation. The final callback from the
1333 * operation must not have been done yet.
1334 *
1335 * @param qe operation to cancel
1336 */
1337void
1338GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1339{
1340 free_qe (qe);
1341}
1342
1343/**
1344 * New API draft. Experimental
1345 */
1346
1347struct GNUNET_NAMESTORE_QueueEntry *
1348GNUNET_NAMESTORE_transaction_begin (struct GNUNET_NAMESTORE_Handle *h,
1349 GNUNET_SCHEDULER_TaskCallback error_cb,
1350 void *error_cb_cls)
1351{
1352 GNUNET_break (0);
1353 return NULL;
1354}
1355
1356
1357struct GNUNET_NAMESTORE_QueueEntry *
1358GNUNET_NAMESTORE_transaction_abort (struct GNUNET_NAMESTORE_Handle *h,
1359 GNUNET_SCHEDULER_TaskCallback error_cb,
1360 void *error_cb_cls)
1361{
1362 GNUNET_break (0);
1363 return NULL;
1364}
1365
1366
1367/**
1368 * Commit a namestore transaction.
1369 * Saves all actions performed since #GNUNET_NAMESTORE_transaction_begin
1370 *
1371 * @param h handle to the namestore
1372 * @param error_cb function to call on error (i.e. disconnect or unable to get lock)
1373 * the handle is afterwards invalid
1374 * @param error_cb_cls closure for @a error_cb
1375 * @return handle to abort the request
1376 */
1377struct GNUNET_NAMESTORE_QueueEntry *
1378GNUNET_NAMESTORE_transaction_commit (struct GNUNET_NAMESTORE_Handle *h,
1379 GNUNET_SCHEDULER_TaskCallback error_cb,
1380 void *error_cb_cls)
1381{
1382 GNUNET_break (0);
1383 return NULL;
1384}
1385
1386
1387/* end of namestore_api.c */
diff --git a/src/namestore/namestore_api_monitor.c b/src/namestore/namestore_api_monitor.c
deleted file mode 100644
index 6670e54ce..000000000
--- a/src/namestore/namestore_api_monitor.c
+++ /dev/null
@@ -1,388 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2016, 2018 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 namestore/namestore_api_monitor.c
22 * @brief API to monitor changes in the NAMESTORE
23 * @author Christian Grothoff
24 */
25
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_crypto_lib.h"
29#include "gnunet_constants.h"
30#include "gnunet_dnsparser_lib.h"
31#include "gnunet_arm_service.h"
32#include "gnunet_signatures.h"
33#include "gnunet_namestore_service.h"
34#include "namestore.h"
35
36
37/**
38 * Handle for a monitoring activity.
39 */
40struct GNUNET_NAMESTORE_ZoneMonitor
41{
42 /**
43 * Configuration (to reconnect).
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Handle to namestore service.
49 */
50 struct GNUNET_MQ_Handle *mq;
51
52 /**
53 * Function to call on errors.
54 */
55 GNUNET_SCHEDULER_TaskCallback error_cb;
56
57 /**
58 * Closure for @e error_cb.
59 */
60 void *error_cb_cls;
61
62 /**
63 * Function to call on events.
64 */
65 GNUNET_NAMESTORE_RecordMonitor monitor;
66
67 /**
68 * Closure for @e monitor.
69 */
70 void *monitor_cls;
71
72 /**
73 * Function called when we've synchronized.
74 */
75 GNUNET_SCHEDULER_TaskCallback sync_cb;
76
77 /**
78 * Closure for @e sync_cb.
79 */
80 void *sync_cb_cls;
81
82 /**
83 * Monitored zone.
84 */
85 struct GNUNET_IDENTITY_PrivateKey zone;
86
87 /**
88 * Do we first iterate over all existing records?
89 */
90 int iterate_first;
91};
92
93
94/**
95 * Reconnect to the namestore service.
96 *
97 * @param zm monitor to reconnect
98 */
99static void
100reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm);
101
102
103/**
104 * Handle SYNC message from the namestore service.
105 *
106 * @param cls the monitor
107 * @param msg the sync message
108 */
109static void
110handle_sync (void *cls, const struct GNUNET_MessageHeader *msg)
111{
112 struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
113
114 (void) cls;
115 (void) msg;
116 if (NULL != zm->sync_cb)
117 zm->sync_cb (zm->sync_cb_cls);
118}
119
120
121/**
122 * We've received a notification about a change to our zone.
123 * Check that it is well-formed.
124 *
125 * @param cls the zone monitor handle
126 * @param lrm the message from the service.
127 */
128static int
129check_result (void *cls, const struct RecordResultMessage *lrm)
130{
131 struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
132 size_t lrm_len;
133 size_t exp_lrm_len;
134 size_t name_len;
135 size_t rd_len;
136 unsigned rd_count;
137 const char *name_tmp;
138 const char *rd_ser_tmp;
139
140 (void) cls;
141 if ((0 != GNUNET_memcmp (&lrm->private_key, &zm->zone)) &&
142 (GNUNET_NO == GNUNET_is_zero (&zm->zone)))
143 {
144 GNUNET_break (0);
145 return GNUNET_SYSERR;
146 }
147 lrm_len = ntohs (lrm->gns_header.header.size);
148 rd_len = ntohs (lrm->rd_len);
149 rd_count = ntohs (lrm->rd_count);
150 name_len = ntohs (lrm->name_len);
151 if (name_len > MAX_NAME_LEN)
152 {
153 GNUNET_break (0);
154 return GNUNET_SYSERR;
155 }
156 exp_lrm_len = sizeof(struct RecordResultMessage) + name_len + rd_len;
157 if (lrm_len != exp_lrm_len)
158 {
159 GNUNET_break (0);
160 return GNUNET_SYSERR;
161 }
162 if (0 == name_len)
163 {
164 GNUNET_break (0);
165 return GNUNET_SYSERR;
166 }
167 name_tmp = (const char *) &lrm[1];
168 if (name_tmp[name_len - 1] != '\0')
169 {
170 GNUNET_break (0);
171 return GNUNET_SYSERR;
172 }
173 rd_ser_tmp = (const char *) &name_tmp[name_len];
174 {
175 struct GNUNET_GNSRECORD_Data rd[rd_count];
176
177 if (GNUNET_OK !=
178 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd))
179 {
180 GNUNET_break (0);
181 return GNUNET_SYSERR;
182 }
183 }
184 return GNUNET_OK;
185}
186
187
188/**
189 * We've received a notification about a change to our zone.
190 * Forward to monitor callback.
191 *
192 * @param cls the zone monitor handle
193 * @param lrm the message from the service.
194 */
195static void
196handle_result (void *cls, const struct RecordResultMessage *lrm)
197{
198 struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
199 size_t name_len;
200 size_t rd_len;
201 unsigned rd_count;
202 const char *name_tmp;
203 const char *rd_ser_tmp;
204
205 rd_len = ntohs (lrm->rd_len);
206 rd_count = ntohs (lrm->rd_count);
207 name_len = ntohs (lrm->name_len);
208 name_tmp = (const char *) &lrm[1];
209 rd_ser_tmp = (const char *) &name_tmp[name_len];
210 {
211 struct GNUNET_GNSRECORD_Data rd[rd_count];
212
213 GNUNET_assert (
214 GNUNET_OK ==
215 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_ser_tmp, rd_count, rd));
216 zm->monitor (zm->monitor_cls, &lrm->private_key, name_tmp, rd_count, rd);
217 }
218}
219
220
221/**
222 * Generic error handler, called with the appropriate error code and
223 * the same closure specified at the creation of the message queue.
224 * Not every message queue implementation supports an error handler.
225 *
226 * @param cls closure with the `struct GNUNET_NAMESTORE_ZoneMonitor *`
227 * @param error error code
228 */
229static void
230mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
231{
232 struct GNUNET_NAMESTORE_ZoneMonitor *zm = cls;
233
234 (void) error;
235 reconnect (zm);
236}
237
238
239/**
240 * Reconnect to the namestore service.
241 *
242 * @param zm monitor to reconnect
243 */
244static void
245reconnect (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
246{
247 struct GNUNET_MQ_MessageHandler handlers[] =
248 { GNUNET_MQ_hd_fixed_size (sync,
249 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC,
250 struct GNUNET_MessageHeader,
251 zm),
252 GNUNET_MQ_hd_var_size (result,
253 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
254 struct RecordResultMessage,
255 zm),
256 GNUNET_MQ_handler_end () };
257 struct GNUNET_MQ_Envelope *env;
258 struct ZoneMonitorStartMessage *sm;
259
260 if (NULL != zm->mq)
261 {
262 GNUNET_MQ_destroy (zm->mq);
263 zm->error_cb (zm->error_cb_cls);
264 }
265 zm->mq = GNUNET_CLIENT_connect (zm->cfg,
266 "namestore",
267 handlers,
268 &mq_error_handler,
269 zm);
270 if (NULL == zm->mq)
271 return;
272 env = GNUNET_MQ_msg (sm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START);
273 sm->iterate_first = htonl (zm->iterate_first);
274 sm->zone = zm->zone;
275 GNUNET_MQ_send (zm->mq, env);
276}
277
278
279/**
280 * Begin monitoring a zone for changes. If @a iterate_first is set,
281 * we Will first call the @a monitor function on all existing records
282 * in the selected zone(s). In any case, we will call @a sync and
283 * afterwards call @a monitor whenever a record changes.
284 *
285 * @param cfg configuration to use to connect to namestore
286 * @param zone zone to monitor
287 * @param iterate_first #GNUNET_YES to first iterate over all existing records,
288 * #GNUNET_NO to only return changes that happen from now
289 * on
290 * @param error_cb function to call on error (i.e. disconnect); note that
291 * unlike the other error callbacks in this API, a call to this
292 * function does NOT destroy the monitor handle, it merely signals
293 * that monitoring is down. You need to still explicitly call
294 * #GNUNET_NAMESTORE_zone_monitor_stop().
295 * @param error_cb_cls closure for @a error_cb
296 * @param monitor function to call on zone changes
297 * @param monitor_cls closure for @a monitor
298 * @param sync_cb function called when we're in sync with the namestore
299 * @param cls closure for @a sync_cb
300 * @return handle to stop monitoring
301 */
302struct GNUNET_NAMESTORE_ZoneMonitor *
303GNUNET_NAMESTORE_zone_monitor_start (
304 const struct GNUNET_CONFIGURATION_Handle *cfg,
305 const struct GNUNET_IDENTITY_PrivateKey *zone,
306 int iterate_first,
307 GNUNET_SCHEDULER_TaskCallback error_cb,
308 void *error_cb_cls,
309 GNUNET_NAMESTORE_RecordMonitor monitor,
310 void *monitor_cls,
311 GNUNET_SCHEDULER_TaskCallback sync_cb,
312 void *sync_cb_cls)
313{
314 struct GNUNET_NAMESTORE_ZoneMonitor *zm;
315
316 zm = GNUNET_new (struct GNUNET_NAMESTORE_ZoneMonitor);
317 if (NULL != zone)
318 zm->zone = *zone;
319 zm->iterate_first = iterate_first;
320 zm->error_cb = error_cb;
321 zm->error_cb_cls = error_cb_cls;
322 zm->monitor = monitor;
323 zm->monitor_cls = monitor_cls;
324 zm->sync_cb = sync_cb;
325 zm->sync_cb_cls = sync_cb_cls;
326 zm->cfg = cfg;
327 reconnect (zm);
328 if (NULL == zm->mq)
329 {
330 GNUNET_free (zm);
331 return NULL;
332 }
333 return zm;
334}
335
336
337/**
338 * Calls the monitor processor specified in #GNUNET_NAMESTORE_zone_monitor_start
339 * for the next record(s). This function is used to allow clients that merely
340 * monitor the NAMESTORE to still throttle namestore operations, so we can be
341 * sure that the monitors can keep up.
342 *
343 * Note that #GNUNET_NAMESTORE_records_store() only waits for this
344 * call if the previous limit set by the client was already reached.
345 * Thus, by using a @a limit greater than 1, monitors basically enable
346 * a queue of notifications to be processed asynchronously with some
347 * delay. Note that even with a limit of 1 the
348 * #GNUNET_NAMESTORE_records_store() function will run asynchronously
349 * and the continuation may be invoked before the monitors completed
350 * (or even started) processing the notification. Thus, monitors will
351 * only closely track the current state of the namestore, but not
352 * be involved in the transactions.
353 *
354 * @param zm the monitor
355 * @param limit number of records to return to the iterator in one shot
356 * (before #GNUNET_NAMESTORE_zone_monitor_next is to be called again)
357 */
358void
359GNUNET_NAMESTORE_zone_monitor_next (struct GNUNET_NAMESTORE_ZoneMonitor *zm,
360 uint64_t limit)
361{
362 struct GNUNET_MQ_Envelope *env;
363 struct ZoneMonitorNextMessage *nm;
364
365 env = GNUNET_MQ_msg (nm, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT);
366 nm->limit = GNUNET_htonll (limit);
367 GNUNET_MQ_send (zm->mq, env);
368}
369
370
371/**
372 * Stop monitoring a zone for changes.
373 *
374 * @param zm handle to the monitor activity to stop
375 */
376void
377GNUNET_NAMESTORE_zone_monitor_stop (struct GNUNET_NAMESTORE_ZoneMonitor *zm)
378{
379 if (NULL != zm->mq)
380 {
381 GNUNET_MQ_destroy (zm->mq);
382 zm->mq = NULL;
383 }
384 GNUNET_free (zm);
385}
386
387
388/* end of namestore_api_monitor.c */
diff --git a/src/namestore/perf_namestore_api_flat.conf b/src/namestore/perf_namestore_api_flat.conf
deleted file mode 100644
index 30759ce7a..000000000
--- a/src/namestore/perf_namestore_api_flat.conf
+++ /dev/null
@@ -1,10 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = flat
5
6[namecache]
7DISABLE = YES
8
9[namestore-heap]
10FILENAME = $GNUNET_TEST_HOME/namestore/heap.db
diff --git a/src/namestore/perf_namestore_api_postgres.conf b/src/namestore/perf_namestore_api_postgres.conf
deleted file mode 100644
index 52d0ecdd5..000000000
--- a/src/namestore/perf_namestore_api_postgres.conf
+++ /dev/null
@@ -1,11 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = postgres
5
6[namecache]
7DISABLE = YES
8
9[namestore-postgres]
10CONFIG = connect_timeout=10 dbname=gnunetcheck
11TEMPORARY_TABLE = YES
diff --git a/src/namestore/perf_namestore_api_sqlite.conf b/src/namestore/perf_namestore_api_sqlite.conf
deleted file mode 100644
index de0fa3f1f..000000000
--- a/src/namestore/perf_namestore_api_sqlite.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namecache]
4DISABLE = YES
5
6[namestore-sqlite]
7FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
diff --git a/src/namestore/perf_namestore_api_zone_iteration.c b/src/namestore/perf_namestore_api_zone_iteration.c
deleted file mode 100644
index ce1cddf87..000000000
--- a/src/namestore/perf_namestore_api_zone_iteration.c
+++ /dev/null
@@ -1,379 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018 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 namestore/perf_namestore_api_zone_iteration.c
22 * @brief testcase for zone iteration functionality: iterate all zones
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_namestore_service.h"
27#include "gnunet_testing_lib.h"
28#include "namestore.h"
29#include "gnunet_dnsparser_lib.h"
30
31#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
32
33/**
34 * A #BENCHMARK_SIZE of 1000 takes less than a minute on a reasonably
35 * modern system, so 30 minutes should be OK even for very, very
36 * slow systems.
37 */
38#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 30)
39
40/**
41 * The runtime of the benchmark is expected to be linear
42 * for the iteration phase with a *good* database. The FLAT
43 * database uses a quadratic retrieval algorithm,
44 * hence it should be quadratic in the size.
45 */
46#define BENCHMARK_SIZE 1000
47
48/**
49 * Maximum record size
50 */
51#define MAX_REC_SIZE 500
52
53/**
54 * How big are the blocks we fetch? Note that the first block is
55 * always just 1 record set per current API. Smaller block
56 * sizes will make quadratic iteration-by-offset penalties
57 * more pronounced.
58 */
59#define BLOCK_SIZE 100
60
61static struct GNUNET_NAMESTORE_Handle *nsh;
62
63static struct GNUNET_SCHEDULER_Task *timeout_task;
64
65static struct GNUNET_SCHEDULER_Task *t;
66
67static struct GNUNET_IDENTITY_PrivateKey privkey;
68
69static struct GNUNET_NAMESTORE_ZoneIterator *zi;
70
71static struct GNUNET_NAMESTORE_QueueEntry *qe;
72
73static int res;
74
75static unsigned int off;
76
77static unsigned int left_until_next;
78
79static uint8_t seen[1 + BENCHMARK_SIZE / 8];
80
81static struct GNUNET_TIME_Absolute start;
82
83
84/**
85 * Terminate everything
86 *
87 * @param cls NULL
88 */
89static void
90end (void *cls)
91{
92 (void) cls;
93 if (NULL != qe)
94 {
95 GNUNET_NAMESTORE_cancel (qe);
96 qe = NULL;
97 }
98 if (NULL != zi)
99 {
100 GNUNET_NAMESTORE_zone_iteration_stop (zi);
101 zi = NULL;
102 }
103 if (NULL != nsh)
104 {
105 GNUNET_NAMESTORE_disconnect (nsh);
106 nsh = NULL;
107 }
108 if (NULL != t)
109 {
110 GNUNET_SCHEDULER_cancel (t);
111 t = NULL;
112 }
113 if (NULL != timeout_task)
114 {
115 GNUNET_SCHEDULER_cancel (timeout_task);
116 timeout_task = NULL;
117 }
118}
119
120
121/**
122 * End with timeout. As this is a benchmark, we do not
123 * fail hard but return "skipped".
124 */
125static void
126timeout (void *cls)
127{
128 (void) cls;
129 timeout_task = NULL;
130 GNUNET_SCHEDULER_shutdown ();
131 res = 77;
132}
133
134
135static struct GNUNET_GNSRECORD_Data *
136create_record (unsigned int count)
137{
138 struct GNUNET_GNSRECORD_Data *rd;
139
140 rd = GNUNET_malloc (count + sizeof(struct GNUNET_GNSRECORD_Data));
141 rd->expiration_time = GNUNET_TIME_relative_to_absolute (
142 GNUNET_TIME_UNIT_HOURS).abs_value_us;
143 rd->record_type = TEST_RECORD_TYPE;
144 rd->data_size = count;
145 rd->data = (void *) &rd[1];
146 rd->flags = 0;
147 memset (&rd[1],
148 'a',
149 count);
150 return rd;
151}
152
153
154static void
155zone_end (void *cls)
156{
157 struct GNUNET_TIME_Relative delay;
158
159 zi = NULL;
160 delay = GNUNET_TIME_absolute_get_duration (start);
161 fprintf (stdout,
162 "Iterating over %u records took %s\n",
163 off,
164 GNUNET_STRINGS_relative_time_to_string (delay,
165 GNUNET_YES));
166 if (BENCHMARK_SIZE == off)
167 {
168 res = 0;
169 }
170 else
171 {
172 GNUNET_break (0);
173 res = 1;
174 }
175 GNUNET_SCHEDULER_shutdown ();
176}
177
178
179static void
180fail_cb (void *cls)
181{
182 zi = NULL;
183 res = 2;
184 GNUNET_break (0);
185 GNUNET_SCHEDULER_shutdown ();
186}
187
188
189static void
190zone_proc (void *cls,
191 const struct GNUNET_IDENTITY_PrivateKey *zone,
192 const char *label,
193 unsigned int rd_count,
194 const struct GNUNET_GNSRECORD_Data *rd)
195{
196 struct GNUNET_GNSRECORD_Data *wrd;
197 unsigned int xoff;
198
199 GNUNET_assert (NULL != zone);
200 if (1 != sscanf (label,
201 "l%u",
202 &xoff))
203 {
204 res = 3;
205 GNUNET_break (0);
206 GNUNET_SCHEDULER_shutdown ();
207 return;
208 }
209 if ((xoff > BENCHMARK_SIZE) ||
210 (0 != (seen[xoff / 8] & (1U << (xoff % 8)))))
211 {
212 res = 3;
213 GNUNET_break (0);
214 GNUNET_SCHEDULER_shutdown ();
215 return;
216 }
217 seen[xoff / 8] |= (1U << (xoff % 8));
218 wrd = create_record (xoff % MAX_REC_SIZE);
219 if ((rd->record_type != wrd->record_type) ||
220 (rd->data_size != wrd->data_size) ||
221 (rd->flags != wrd->flags))
222 {
223 res = 4;
224 GNUNET_break (0);
225 GNUNET_SCHEDULER_shutdown ();
226 GNUNET_free (wrd);
227 return;
228 }
229 if (0 != memcmp (rd->data,
230 wrd->data,
231 wrd->data_size))
232 {
233 res = 4;
234 GNUNET_break (0);
235 GNUNET_SCHEDULER_shutdown ();
236 GNUNET_free (wrd);
237 return;
238 }
239 GNUNET_free (wrd);
240 if (0 != GNUNET_memcmp (zone,
241 &privkey))
242 {
243 res = 5;
244 GNUNET_break (0);
245 GNUNET_SCHEDULER_shutdown ();
246 return;
247 }
248 off++;
249 left_until_next--;
250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251 "Obtained record %u, expecting %u more until asking for more explicitly\n",
252 off,
253 left_until_next);
254 if (0 == left_until_next)
255 {
256 left_until_next = BLOCK_SIZE;
257 GNUNET_NAMESTORE_zone_iterator_next (zi,
258 left_until_next);
259 }
260}
261
262
263static void
264publish_record (void *cls);
265
266
267static void
268put_cont (void *cls,
269 int32_t success,
270 const char *emsg)
271{
272 (void) cls;
273 qe = NULL;
274 if (GNUNET_OK != success)
275 {
276 GNUNET_break (0);
277 GNUNET_SCHEDULER_shutdown ();
278 return;
279 }
280 t = GNUNET_SCHEDULER_add_now (&publish_record,
281 NULL);
282}
283
284
285static void
286publish_record (void *cls)
287{
288 struct GNUNET_GNSRECORD_Data *rd;
289 char *label;
290
291 (void) cls;
292 t = NULL;
293 if (BENCHMARK_SIZE == off)
294 {
295 struct GNUNET_TIME_Relative delay;
296
297 delay = GNUNET_TIME_absolute_get_duration (start);
298 fprintf (stdout,
299 "Inserting %u records took %s\n",
300 off,
301 GNUNET_STRINGS_relative_time_to_string (delay,
302 GNUNET_YES));
303 start = GNUNET_TIME_absolute_get ();
304 off = 0;
305 left_until_next = 1;
306 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
307 NULL,
308 &fail_cb,
309 NULL,
310 &zone_proc,
311 NULL,
312 &zone_end,
313 NULL);
314 GNUNET_assert (NULL != zi);
315 return;
316 }
317 rd = create_record ((++off) % MAX_REC_SIZE);
318 GNUNET_asprintf (&label,
319 "l%u",
320 off);
321 qe = GNUNET_NAMESTORE_records_store (nsh,
322 &privkey,
323 label,
324 1, rd,
325 &put_cont,
326 NULL);
327 GNUNET_free (label);
328 GNUNET_free (rd);
329}
330
331
332static void
333run (void *cls,
334 const struct GNUNET_CONFIGURATION_Handle *cfg,
335 struct GNUNET_TESTING_Peer *peer)
336{
337 GNUNET_SCHEDULER_add_shutdown (&end,
338 NULL);
339 timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
340 &timeout,
341 NULL);
342 nsh = GNUNET_NAMESTORE_connect (cfg);
343 GNUNET_assert (NULL != nsh);
344 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
345 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
346 start = GNUNET_TIME_absolute_get ();
347 t = GNUNET_SCHEDULER_add_now (&publish_record,
348 NULL);
349}
350
351
352#include "test_common.c"
353
354
355int
356main (int argc,
357 char *argv[])
358{
359 const char *plugin_name;
360 char *cfg_name;
361
362 SETUP_CFG (plugin_name, cfg_name);
363 res = 1;
364 if (0 !=
365 GNUNET_TESTING_peer_run ("perf-namestore-api-zone-iteration",
366 cfg_name,
367 &run,
368 NULL))
369 {
370 res = 1;
371 }
372 GNUNET_DISK_purge_cfg_dir (cfg_name,
373 "GNUNET_TEST_HOME");
374 GNUNET_free (cfg_name);
375 return res;
376}
377
378
379/* end of perf_namestore_api_zone_iteration.c */
diff --git a/src/namestore/plugin_namestore_flat.c b/src/namestore/plugin_namestore_flat.c
deleted file mode 100644
index 3576b14e0..000000000
--- a/src/namestore/plugin_namestore_flat.c
+++ /dev/null
@@ -1,818 +0,0 @@
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
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file namestore/plugin_namestore_flat.c
22 * @brief file-based namestore backend
23 * @author Martin Schanzenbach
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_namestore_plugin.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "namestore.h"
32
33/**
34 * Context for all functions in this plugin.
35 */
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
51
52struct FlatFileEntry
53{
54 /**
55 * Entry zone
56 */
57 struct GNUNET_IDENTITY_PrivateKey private_key;
58
59 /**
60 * Record count.
61 */
62 uint32_t record_count;
63
64 /**
65 * Rvalue
66 */
67 uint64_t rvalue;
68
69 /**
70 * Record data
71 */
72 struct GNUNET_GNSRECORD_Data *record_data;
73
74 /**
75 * Label
76 */
77 char *label;
78};
79
80
81/**
82 * Hash contactenation of @a pkey and @a label into @a h
83 *
84 * @param pkey a key
85 * @param label a label
86 * @param h[out] initialized hash
87 */
88static void
89hash_pkey_and_label (const struct GNUNET_IDENTITY_PrivateKey *pkey,
90 const char *label,
91 struct GNUNET_HashCode *h)
92{
93 char *key;
94 size_t label_len;
95 size_t key_len;
96
97 label_len = strlen (label);
98 key_len = label_len + sizeof(struct GNUNET_IDENTITY_PrivateKey);
99 key = GNUNET_malloc (key_len);
100 GNUNET_memcpy (key,
101 label,
102 label_len);
103 GNUNET_memcpy (key + label_len,
104 pkey,
105 sizeof(struct GNUNET_IDENTITY_PrivateKey));
106 GNUNET_CRYPTO_hash (key,
107 key_len,
108 h);
109 GNUNET_free (key);
110}
111
112
113/**
114 * Initialize the database connections and associated
115 * data structures (create tables and indices
116 * as needed as well).
117 *
118 * @param plugin the plugin context (state for this module)
119 * @return #GNUNET_OK on success
120 */
121static int
122database_setup (struct Plugin *plugin)
123{
124 char *flatdbfile;
125 char *record_data;
126 char *zone_private_key;
127 char *record_data_b64;
128 char *buffer;
129 char *line;
130 char *label;
131 char *rvalue;
132 char *record_count;
133 size_t record_data_size;
134 uint64_t size;
135 struct GNUNET_HashCode hkey;
136 struct GNUNET_DISK_FileHandle *fh;
137 struct FlatFileEntry *entry;
138 struct GNUNET_DISK_MapHandle *mh;
139
140 if (GNUNET_OK !=
141 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
142 "namestore-flat",
143 "FILENAME",
144 &flatdbfile))
145 {
146 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
147 "namestore-flat",
148 "FILENAME");
149 return GNUNET_SYSERR;
150 }
151 if (GNUNET_OK !=
152 GNUNET_DISK_file_test (flatdbfile))
153 {
154 if (GNUNET_OK !=
155 GNUNET_DISK_directory_create_for_file (flatdbfile))
156 {
157 GNUNET_break (0);
158 GNUNET_free (flatdbfile);
159 return GNUNET_SYSERR;
160 }
161 }
162 /* flatdbfile should be UTF-8-encoded. If it isn't, it's a bug */
163 plugin->fn = flatdbfile;
164
165 /* Load data from file into hashmap */
166 plugin->hm = GNUNET_CONTAINER_multihashmap_create (10,
167 GNUNET_NO);
168 fh = GNUNET_DISK_file_open (flatdbfile,
169 GNUNET_DISK_OPEN_CREATE
170 | GNUNET_DISK_OPEN_READWRITE,
171 GNUNET_DISK_PERM_USER_WRITE
172 | GNUNET_DISK_PERM_USER_READ);
173 if (NULL == fh)
174 {
175 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
176 _ ("Unable to initialize file: %s.\n"),
177 flatdbfile);
178 return GNUNET_SYSERR;
179 }
180 if (GNUNET_SYSERR ==
181 GNUNET_DISK_file_size (flatdbfile,
182 &size,
183 GNUNET_YES,
184 GNUNET_YES))
185 {
186 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
187 _ ("Unable to get filesize: %s.\n"),
188 flatdbfile);
189 GNUNET_DISK_file_close (fh);
190 return GNUNET_SYSERR;
191 }
192 if (size > SIZE_MAX)
193 {
194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
195 _ ("File too big to map: %llu bytes.\n"),
196 (unsigned long long) size);
197 GNUNET_DISK_file_close (fh);
198 return GNUNET_SYSERR;
199 }
200 if (0 == size)
201 {
202 GNUNET_DISK_file_close (fh);
203 return GNUNET_OK;
204 }
205 buffer = GNUNET_DISK_file_map (fh,
206 &mh,
207 GNUNET_DISK_MAP_TYPE_READ,
208 size);
209 if (NULL == buffer)
210 {
211 GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
212 "mmap");
213 GNUNET_DISK_file_close (fh);
214 return GNUNET_SYSERR;
215 }
216 if ('\0' != buffer[size - 1])
217 {
218 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
219 _ ("Namestore database file `%s' malformed\n"),
220 flatdbfile);
221 GNUNET_DISK_file_unmap (mh);
222 GNUNET_DISK_file_close (fh);
223 return GNUNET_SYSERR;
224 }
225
226 line = strtok (buffer, "\n");
227 while (NULL != line)
228 {
229 zone_private_key = strtok (line, ",");
230 if (NULL == zone_private_key)
231 break;
232 rvalue = strtok (NULL, ",");
233 if (NULL == rvalue)
234 break;
235 record_count = strtok (NULL, ",");
236 if (NULL == record_count)
237 break;
238 record_data_b64 = strtok (NULL, ",");
239 if (NULL == record_data_b64)
240 break;
241 label = strtok (NULL, ",");
242 if (NULL == label)
243 break;
244 line = strtok (NULL, "\n");
245 entry = GNUNET_new (struct FlatFileEntry);
246 {
247 unsigned long long ll;
248
249 if (1 != sscanf (rvalue,
250 "%llu",
251 &ll))
252 {
253 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
254 "Error parsing entry\n");
255 GNUNET_free (entry);
256 break;
257 }
258 entry->rvalue = (uint64_t) ll;
259 }
260 {
261 unsigned int ui;
262
263 if (1 != sscanf (record_count,
264 "%u",
265 &ui))
266 {
267 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
268 "Error parsing entry\n");
269 GNUNET_free (entry);
270 break;
271 }
272 entry->record_count = (uint32_t) ui;
273 }
274 entry->label = GNUNET_strdup (label);
275 record_data_size
276 = GNUNET_STRINGS_base64_decode (record_data_b64,
277 strlen (record_data_b64),
278 (void **) &record_data);
279 entry->record_data =
280 GNUNET_new_array (entry->record_count,
281 struct GNUNET_GNSRECORD_Data);
282 if (GNUNET_OK !=
283 GNUNET_GNSRECORD_records_deserialize (record_data_size,
284 record_data,
285 entry->record_count,
286 entry->record_data))
287 {
288 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
289 "Unable to deserialize record %s\n",
290 label);
291 GNUNET_free (entry->label);
292 GNUNET_free (entry);
293 GNUNET_free (record_data);
294 break;
295 }
296 GNUNET_free (record_data);
297
298 {
299 struct GNUNET_IDENTITY_PrivateKey *private_key;
300
301 GNUNET_STRINGS_base64_decode (zone_private_key,
302 strlen (zone_private_key),
303 (void **) &private_key);
304 entry->private_key = *private_key;
305 GNUNET_free (private_key);
306 }
307
308 hash_pkey_and_label (&entry->private_key,
309 label,
310 &hkey);
311 if (GNUNET_OK !=
312 GNUNET_CONTAINER_multihashmap_put (plugin->hm,
313 &hkey,
314 entry,
315 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
316 {
317 GNUNET_free (entry);
318 GNUNET_break (0);
319 }
320 }
321 GNUNET_DISK_file_unmap (mh);
322 GNUNET_DISK_file_close (fh);
323 return GNUNET_OK;
324}
325
326
327/**
328 * Store values in hashmap in file and free data
329 *
330 * @param plugin the plugin context
331 * @param key key in the map
332 * @param value a `struct FlatFileEntry`
333 */
334static int
335store_and_free_entries (void *cls,
336 const struct GNUNET_HashCode *key,
337 void *value)
338{
339 struct GNUNET_DISK_FileHandle *fh = cls;
340 struct FlatFileEntry *entry = value;
341 char *line;
342 char *zone_private_key;
343 char *record_data_b64;
344 ssize_t data_size;
345
346 (void) key;
347 GNUNET_STRINGS_base64_encode (&entry->private_key,
348 sizeof(struct GNUNET_IDENTITY_PrivateKey),
349 &zone_private_key);
350 data_size = GNUNET_GNSRECORD_records_get_size (entry->record_count,
351 entry->record_data);
352 if (data_size < 0)
353 {
354 GNUNET_break (0);
355 GNUNET_free (zone_private_key);
356 return GNUNET_SYSERR;
357 }
358 if (data_size >= UINT16_MAX)
359 {
360 GNUNET_break (0);
361 GNUNET_free (zone_private_key);
362 return GNUNET_SYSERR;
363 }
364 {
365 char data[data_size];
366 ssize_t ret;
367
368 ret = GNUNET_GNSRECORD_records_serialize (entry->record_count,
369 entry->record_data,
370 data_size,
371 data);
372 if ((ret < 0) ||
373 (data_size != ret))
374 {
375 GNUNET_break (0);
376 GNUNET_free (zone_private_key);
377 return GNUNET_SYSERR;
378 }
379 GNUNET_STRINGS_base64_encode (data,
380 data_size,
381 &record_data_b64);
382 }
383 GNUNET_asprintf (&line,
384 "%s,%llu,%u,%s,%s\n",
385 zone_private_key,
386 (unsigned long long) entry->rvalue,
387 (unsigned int) entry->record_count,
388 record_data_b64,
389 entry->label);
390 GNUNET_free (record_data_b64);
391 GNUNET_free (zone_private_key);
392
393 GNUNET_DISK_file_write (fh,
394 line,
395 strlen (line));
396
397 GNUNET_free (line);
398 GNUNET_free (entry->label);
399 GNUNET_free (entry->record_data);
400 GNUNET_free (entry);
401 return GNUNET_YES;
402}
403
404
405/**
406 * Shutdown database connection and associate data
407 * structures.
408 * @param plugin the plugin context (state for this module)
409 */
410static void
411database_shutdown (struct Plugin *plugin)
412{
413 struct GNUNET_DISK_FileHandle *fh;
414
415 fh = GNUNET_DISK_file_open (plugin->fn,
416 GNUNET_DISK_OPEN_CREATE
417 | GNUNET_DISK_OPEN_TRUNCATE
418 | GNUNET_DISK_OPEN_READWRITE,
419 GNUNET_DISK_PERM_USER_WRITE
420 | GNUNET_DISK_PERM_USER_READ);
421 if (NULL == fh)
422 {
423 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
424 _ ("Unable to initialize file: %s.\n"),
425 plugin->fn);
426 return;
427 }
428
429 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
430 &store_and_free_entries,
431 fh);
432 GNUNET_CONTAINER_multihashmap_destroy (plugin->hm);
433 /* append 0-terminator */
434 GNUNET_DISK_file_write (fh,
435 "",
436 1);
437 GNUNET_DISK_file_close (fh);
438}
439
440
441/**
442 * Store a record in the datastore. Removes any existing record in the
443 * same zone with the same name.
444 *
445 * @param cls closure (internal context for the plugin)
446 * @param zone_key private key of the zone
447 * @param label name that is being mapped (at most 255 characters long)
448 * @param rd_count number of entries in @a rd array
449 * @param rd array of records with data to store
450 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
451 */
452static int
453namestore_flat_store_records (void *cls,
454 const struct
455 GNUNET_IDENTITY_PrivateKey *zone_key,
456 const char *label,
457 unsigned int rd_count,
458 const struct GNUNET_GNSRECORD_Data *rd)
459{
460 struct Plugin *plugin = cls;
461 uint64_t rvalue;
462 struct GNUNET_HashCode hkey;
463 struct FlatFileEntry *entry;
464
465 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
466 UINT64_MAX);
467 hash_pkey_and_label (zone_key,
468 label,
469 &hkey);
470 GNUNET_CONTAINER_multihashmap_remove_all (plugin->hm,
471 &hkey);
472 if (0 == rd_count)
473 {
474 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
475 "sqlite",
476 "Record deleted\n");
477 return GNUNET_OK;
478 }
479 entry = GNUNET_new (struct FlatFileEntry);
480 GNUNET_asprintf (&entry->label,
481 label,
482 strlen (label));
483 GNUNET_memcpy (&entry->private_key,
484 zone_key,
485 sizeof(struct GNUNET_IDENTITY_PrivateKey));
486 entry->rvalue = rvalue;
487 entry->record_count = rd_count;
488 entry->record_data = GNUNET_new_array (rd_count,
489 struct GNUNET_GNSRECORD_Data);
490 for (unsigned int i = 0; i < rd_count; i++)
491 {
492 entry->record_data[i].expiration_time = rd[i].expiration_time;
493 entry->record_data[i].record_type = rd[i].record_type;
494 entry->record_data[i].flags = rd[i].flags;
495 entry->record_data[i].data_size = rd[i].data_size;
496 entry->record_data[i].data = GNUNET_malloc (rd[i].data_size);
497 GNUNET_memcpy ((char *) entry->record_data[i].data,
498 rd[i].data,
499 rd[i].data_size);
500 }
501 return GNUNET_CONTAINER_multihashmap_put (plugin->hm,
502 &hkey,
503 entry,
504 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
505}
506
507
508/**
509 * Lookup records in the datastore for which we are the authority.
510 *
511 * @param cls closure (internal context for the plugin)
512 * @param zone private key of the zone
513 * @param label name of the record in the zone
514 * @param iter function to call with the result
515 * @param iter_cls closure for @a iter
516 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
517 */
518static int
519namestore_flat_lookup_records (void *cls,
520 const struct GNUNET_IDENTITY_PrivateKey *zone,
521 const char *label,
522 GNUNET_NAMESTORE_RecordIterator iter,
523 void *iter_cls)
524{
525 struct Plugin *plugin = cls;
526 struct FlatFileEntry *entry;
527 struct GNUNET_HashCode hkey;
528
529 if (NULL == zone)
530 {
531 GNUNET_break (0);
532 return GNUNET_SYSERR;
533 }
534 hash_pkey_and_label (zone,
535 label,
536 &hkey);
537 entry = GNUNET_CONTAINER_multihashmap_get (plugin->hm,
538 &hkey);
539
540 if (NULL == entry)
541 return GNUNET_NO;
542 if (NULL != iter)
543 iter (iter_cls,
544 1, /* zero is illegal */
545 &entry->private_key,
546 entry->label,
547 entry->record_count,
548 entry->record_data);
549 return GNUNET_YES;
550}
551
552
553/**
554 * Closure for #iterate_zones.
555 */
556struct IterateContext
557{
558 /**
559 * How many more records should we skip before returning results?
560 */
561 uint64_t offset;
562
563 /**
564 * How many more records should we return?
565 */
566 uint64_t limit;
567
568 /**
569 * What is the position of the current entry, counting
570 * starts from 1.
571 */
572 uint64_t pos;
573
574 /**
575 * Target zone.
576 */
577 const struct GNUNET_IDENTITY_PrivateKey *zone;
578
579 /**
580 * Function to call on each record.
581 */
582 GNUNET_NAMESTORE_RecordIterator iter;
583
584 /**
585 * Closure for @e iter.
586 */
587 void *iter_cls;
588};
589
590
591/**
592 * Helper function for #namestore_flat_iterate_records().
593 *
594 * @param cls a `struct IterateContext`
595 * @param key unused
596 * @param value a `struct FlatFileEntry`
597 * @return #GNUNET_YES to continue the iteration
598 */
599static int
600iterate_zones (void *cls,
601 const struct GNUNET_HashCode *key,
602 void *value)
603{
604 struct IterateContext *ic = cls;
605 struct FlatFileEntry *entry = value;
606
607 (void) key;
608 if (0 == ic->limit)
609 return GNUNET_NO;
610 if ((NULL != ic->zone) &&
611 (0 != GNUNET_memcmp (&entry->private_key,
612 ic->zone)))
613 return GNUNET_YES;
614 ic->pos++;
615 if (ic->offset > 0)
616 {
617 ic->offset--;
618 return GNUNET_YES;
619 }
620 ic->iter (ic->iter_cls,
621 ic->pos,
622 (NULL == ic->zone)
623 ? &entry->private_key
624 : ic->zone,
625 entry->label,
626 entry->record_count,
627 entry->record_data);
628 ic->limit--;
629 if (0 == ic->limit)
630 return GNUNET_NO;
631 return GNUNET_YES;
632}
633
634
635/**
636 * Iterate over the results for a particular key and zone in the
637 * datastore. Will return at most one result to the iterator.
638 *
639 * @param cls closure (internal context for the plugin)
640 * @param zone hash of public key of the zone, NULL to iterate over all zones
641 * @param serial serial number to exclude in the list of all matching records
642 * @param limit maximum number of results to return to @a iter
643 * @param iter function to call with the result
644 * @param iter_cls closure for @a iter
645 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
646 */
647static int
648namestore_flat_iterate_records (void *cls,
649 const struct
650 GNUNET_IDENTITY_PrivateKey *zone,
651 uint64_t serial,
652 uint64_t limit,
653 GNUNET_NAMESTORE_RecordIterator iter,
654 void *iter_cls)
655{
656 struct Plugin *plugin = cls;
657 struct IterateContext ic;
658
659 ic.offset = serial;
660 ic.pos = 0;
661 ic.limit = limit;
662 ic.iter = iter;
663 ic.iter_cls = iter_cls;
664 ic.zone = zone;
665 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
666 &iterate_zones,
667 &ic);
668 return (0 == ic.limit) ? GNUNET_OK : GNUNET_NO;
669}
670
671
672/**
673 * Closure for #zone_to_name.
674 */
675struct ZoneToNameContext
676{
677 const struct GNUNET_IDENTITY_PrivateKey *zone;
678 const struct GNUNET_IDENTITY_PublicKey *value_zone;
679 GNUNET_NAMESTORE_RecordIterator iter;
680 void *iter_cls;
681
682 int result_found;
683};
684
685
686static int
687zone_to_name (void *cls,
688 const struct GNUNET_HashCode *key,
689 void *value)
690{
691 struct ZoneToNameContext *ztn = cls;
692 struct FlatFileEntry *entry = value;
693
694 (void) key;
695 if (0 != GNUNET_memcmp (&entry->private_key,
696 ztn->zone))
697 return GNUNET_YES;
698
699 for (unsigned int i = 0; i < entry->record_count; i++)
700 {
701 if (GNUNET_NO ==
702 GNUNET_GNSRECORD_is_zonekey_type (entry->record_data[i].record_type))
703 continue;
704 if (ztn->value_zone->type != entry->record_data[i].record_type)
705 continue;
706 if (0 == memcmp (ztn->value_zone,
707 entry->record_data[i].data,
708 entry->record_data[i].data_size))
709 {
710 ztn->iter (ztn->iter_cls,
711 i + 1, /* zero is illegal! */
712 &entry->private_key,
713 entry->label,
714 entry->record_count,
715 entry->record_data);
716 ztn->result_found = GNUNET_YES;
717 }
718 }
719 return GNUNET_YES;
720}
721
722
723/**
724 * Look for an existing PKEY delegation record for a given public key.
725 * Returns at most one result to the iterator.
726 *
727 * @param cls closure (internal context for the plugin)
728 * @param zone private key of the zone to look up in, never NULL
729 * @param value_zone public key of the target zone (value), never NULL
730 * @param iter function to call with the result
731 * @param iter_cls closure for @a iter
732 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
733 */
734static int
735namestore_flat_zone_to_name (void *cls,
736 const struct GNUNET_IDENTITY_PrivateKey *zone,
737 const struct
738 GNUNET_IDENTITY_PublicKey *value_zone,
739 GNUNET_NAMESTORE_RecordIterator iter,
740 void *iter_cls)
741{
742 struct Plugin *plugin = cls;
743 struct ZoneToNameContext ztn = {
744 .iter = iter,
745 .iter_cls = iter_cls,
746 .zone = zone,
747 .value_zone = value_zone,
748 .result_found = GNUNET_NO
749 };
750
751 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
752 "Performing reverse lookup for `%s'\n",
753 GNUNET_GNSRECORD_z2s (value_zone));
754 GNUNET_CONTAINER_multihashmap_iterate (plugin->hm,
755 &zone_to_name,
756 &ztn);
757 return ztn.result_found;
758}
759
760
761/**
762 * Entry point for the plugin.
763 *
764 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
765 * @return NULL on error, otherwise the plugin context
766 */
767void *
768libgnunet_plugin_namestore_flat_init (void *cls)
769{
770 static struct Plugin plugin;
771 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
772 struct GNUNET_NAMESTORE_PluginFunctions *api;
773
774 if (NULL != plugin.cfg)
775 return NULL; /* can only initialize once! */
776 memset (&plugin,
777 0,
778 sizeof(struct Plugin));
779 plugin.cfg = cfg;
780 if (GNUNET_OK != database_setup (&plugin))
781 {
782 database_shutdown (&plugin);
783 return NULL;
784 }
785 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
786 api->cls = &plugin;
787 api->store_records = &namestore_flat_store_records;
788 api->iterate_records = &namestore_flat_iterate_records;
789 api->zone_to_name = &namestore_flat_zone_to_name;
790 api->lookup_records = &namestore_flat_lookup_records;
791 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
792 _ ("Flat file database running\n"));
793 return api;
794}
795
796
797/**
798 * Exit point from the plugin.
799 *
800 * @param cls the plugin context (as returned by "init")
801 * @return always NULL
802 */
803void *
804libgnunet_plugin_namestore_flat_done (void *cls)
805{
806 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
807 struct Plugin *plugin = api->cls;
808
809 database_shutdown (plugin);
810 plugin->cfg = NULL;
811 GNUNET_free (api);
812 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
813 "Flat file plugin is finished\n");
814 return NULL;
815}
816
817
818/* end of plugin_namestore_flat.c */
diff --git a/src/namestore/plugin_namestore_postgres.c b/src/namestore/plugin_namestore_postgres.c
deleted file mode 100644
index bdbaf96b3..000000000
--- a/src/namestore/plugin_namestore_postgres.c
+++ /dev/null
@@ -1,626 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-2013, 2016-2018 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 namestore/plugin_namestore_postgres.c
23 * @brief postgres-based namestore backend
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_namestore_plugin.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_gnsrecord_lib.h"
30#include "gnunet_pq_lib.h"
31#include "namestore.h"
32
33
34#define LOG(kind, ...) GNUNET_log_from (kind, "namestore-postgres", __VA_ARGS__)
35
36
37/**
38 * Context for all functions in this plugin.
39 */
40struct Plugin
41{
42 /**
43 * Our configuration.
44 */
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
46
47 /**
48 * Postgres database handle.
49 */
50 struct GNUNET_PQ_Context *dbh;
51};
52
53
54/**
55 * Initialize the database connections and associated
56 * data structures (create tables and indices
57 * as needed as well).
58 *
59 * @param plugin the plugin context (state for this module)
60 * @return #GNUNET_OK on success
61 */
62static int
63database_setup (struct Plugin *plugin)
64{
65 struct GNUNET_PQ_ExecuteStatement es_temporary =
66 GNUNET_PQ_make_execute (
67 "CREATE TEMPORARY TABLE IF NOT EXISTS ns098records ("
68 " seq BIGSERIAL PRIMARY KEY,"
69 " zone_private_key BYTEA NOT NULL DEFAULT '',"
70 " pkey BYTEA DEFAULT '',"
71 " rvalue BYTEA NOT NULL DEFAULT '',"
72 " record_count INTEGER NOT NULL DEFAULT 0,"
73 " record_data BYTEA NOT NULL DEFAULT '',"
74 " label TEXT NOT NULL DEFAULT '',"
75 " CONSTRAINT zl UNIQUE (zone_private_key,label)"
76 ")");
77 struct GNUNET_PQ_ExecuteStatement es_default =
78 GNUNET_PQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
79 " seq BIGSERIAL PRIMARY KEY,"
80 " zone_private_key BYTEA NOT NULL DEFAULT '',"
81 " pkey BYTEA DEFAULT '',"
82 " rvalue BYTEA NOT NULL DEFAULT '',"
83 " record_count INTEGER NOT NULL DEFAULT 0,"
84 " record_data BYTEA NOT NULL DEFAULT '',"
85 " label TEXT NOT NULL DEFAULT '',"
86 " CONSTRAINT zl UNIQUE (zone_private_key,label)"
87 ")");
88 const struct GNUNET_PQ_ExecuteStatement *cr;
89 struct GNUNET_PQ_ExecuteStatement sc = GNUNET_PQ_EXECUTE_STATEMENT_END;
90
91 if (GNUNET_YES ==
92 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
93 "namestore-postgres",
94 "TEMPORARY_TABLE"))
95 {
96 cr = &es_temporary;
97 }
98 else
99 {
100 cr = &es_default;
101 }
102
103 if (GNUNET_YES ==
104 GNUNET_CONFIGURATION_get_value_yesno (plugin->cfg,
105 "namestore-postgres",
106 "ASYNC_COMMIT"))
107 sc = GNUNET_PQ_make_try_execute ("SET synchronous_commit TO off");
108
109 {
110 struct GNUNET_PQ_ExecuteStatement es[] = {
111 *cr,
112 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
113 "ON ns098records (zone_private_key,pkey)"),
114 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
115 "ON ns098records (zone_private_key,seq)"),
116 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_label "
117 "ON ns098records (label)"),
118 GNUNET_PQ_make_try_execute ("CREATE INDEX IF NOT EXISTS zone_label "
119 "ON ns098records (zone_private_key,label)"),
120 sc,
121 GNUNET_PQ_EXECUTE_STATEMENT_END
122 };
123 struct GNUNET_PQ_PreparedStatement ps[] = {
124 GNUNET_PQ_make_prepare ("store_records",
125 "INSERT INTO ns098records"
126 " (zone_private_key, pkey, rvalue, record_count, record_data, label)"
127 " VALUES ($1, $2, $3, $4, $5, $6)"
128 " ON CONFLICT ON CONSTRAINT zl"
129 " DO UPDATE"
130 " SET pkey=$2,rvalue=$3,record_count=$4,record_data=$5"
131 " WHERE ns098records.zone_private_key = $1"
132 " AND ns098records.label = $6",
133 6),
134 GNUNET_PQ_make_prepare ("delete_records",
135 "DELETE FROM ns098records "
136 "WHERE zone_private_key=$1 AND label=$2",
137 2),
138 GNUNET_PQ_make_prepare ("zone_to_name",
139 "SELECT seq,record_count,record_data,label FROM ns098records"
140 " WHERE zone_private_key=$1 AND pkey=$2",
141 2),
142 GNUNET_PQ_make_prepare ("iterate_zone",
143 "SELECT seq,record_count,record_data,label FROM ns098records "
144 "WHERE zone_private_key=$1 AND seq > $2 ORDER BY seq ASC LIMIT $3",
145 3),
146 GNUNET_PQ_make_prepare ("iterate_all_zones",
147 "SELECT seq,record_count,record_data,label,zone_private_key"
148 " FROM ns098records WHERE seq > $1 ORDER BY seq ASC LIMIT $2",
149 2),
150 GNUNET_PQ_make_prepare ("lookup_label",
151 "SELECT seq,record_count,record_data,label "
152 "FROM ns098records WHERE zone_private_key=$1 AND label=$2",
153 2),
154 GNUNET_PQ_PREPARED_STATEMENT_END
155 };
156
157 plugin->dbh = GNUNET_PQ_connect_with_cfg (plugin->cfg,
158 "namestore-postgres",
159 NULL,
160 es,
161 ps);
162 }
163 if (NULL == plugin->dbh)
164 return GNUNET_SYSERR;
165 return GNUNET_OK;
166}
167
168
169/**
170 * Store a record in the datastore. Removes any existing record in the
171 * same zone with the same name.
172 *
173 * @param cls closure (internal context for the plugin)
174 * @param zone_key private key of the zone
175 * @param label name that is being mapped (at most 255 characters long)
176 * @param rd_count number of entries in @a rd array
177 * @param rd array of records with data to store
178 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
179 */
180static int
181namestore_postgres_store_records (void *cls,
182 const struct
183 GNUNET_IDENTITY_PrivateKey *zone_key,
184 const char *label,
185 unsigned int rd_count,
186 const struct GNUNET_GNSRECORD_Data *rd)
187{
188 struct Plugin *plugin = cls;
189 struct GNUNET_IDENTITY_PublicKey pkey;
190 uint64_t rvalue;
191 uint32_t rd_count32 = (uint32_t) rd_count;
192 ssize_t data_size;
193
194 memset (&pkey,
195 0,
196 sizeof(pkey));
197 for (unsigned int i = 0; i < rd_count; i++)
198 if (GNUNET_YES ==
199 GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
200 {
201 GNUNET_break (GNUNET_OK ==
202 GNUNET_GNSRECORD_identity_from_data (rd[i].data,
203 rd[i].data_size,
204 rd[i].record_type,
205 &pkey));
206 break;
207 }
208 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
209 UINT64_MAX);
210 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
211 rd);
212 if (data_size < 0)
213 {
214 GNUNET_break (0);
215 return GNUNET_SYSERR;
216 }
217 if (data_size >= UINT16_MAX)
218 {
219 GNUNET_break (0);
220 return GNUNET_SYSERR;
221 }
222 /* if record set is empty, delete existing records */
223 if (0 == rd_count)
224 {
225 struct GNUNET_PQ_QueryParam params[] = {
226 GNUNET_PQ_query_param_auto_from_type (zone_key),
227 GNUNET_PQ_query_param_string (label),
228 GNUNET_PQ_query_param_end
229 };
230 enum GNUNET_DB_QueryStatus res;
231
232 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
233 "delete_records",
234 params);
235 if ((GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res) &&
236 (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS != res))
237 {
238 GNUNET_break (0);
239 return GNUNET_SYSERR;
240 }
241 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
242 "postgres",
243 "Record deleted\n");
244 return GNUNET_OK;
245 }
246 /* otherwise, UPSERT (i.e. UPDATE if exists, otherwise INSERT) */
247 {
248 char data[data_size];
249 struct GNUNET_PQ_QueryParam params[] = {
250 GNUNET_PQ_query_param_auto_from_type (zone_key),
251 GNUNET_PQ_query_param_auto_from_type (&pkey),
252 GNUNET_PQ_query_param_uint64 (&rvalue),
253 GNUNET_PQ_query_param_uint32 (&rd_count32),
254 GNUNET_PQ_query_param_fixed_size (data, data_size),
255 GNUNET_PQ_query_param_string (label),
256 GNUNET_PQ_query_param_end
257 };
258 enum GNUNET_DB_QueryStatus res;
259 ssize_t ret;
260
261 ret = GNUNET_GNSRECORD_records_serialize (rd_count,
262 rd,
263 data_size,
264 data);
265 if ((ret < 0) ||
266 (data_size != ret))
267 {
268 GNUNET_break (0);
269 return GNUNET_SYSERR;
270 }
271
272 res = GNUNET_PQ_eval_prepared_non_select (plugin->dbh,
273 "store_records",
274 params);
275 if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT != res)
276 return GNUNET_SYSERR;
277 }
278 return GNUNET_OK;
279}
280
281
282/**
283 * Closure for #parse_result_call_iterator.
284 */
285struct ParserContext
286{
287 /**
288 * Function to call for each result.
289 */
290 GNUNET_NAMESTORE_RecordIterator iter;
291
292 /**
293 * Closure for @e iter.
294 */
295 void *iter_cls;
296
297 /**
298 * Zone key, NULL if part of record.
299 */
300 const struct GNUNET_IDENTITY_PrivateKey *zone_key;
301
302 /**
303 * Number of results still to return (counted down by
304 * number of results given to iterator).
305 */
306 uint64_t limit;
307};
308
309
310/**
311 * A statement has been run. We should evaluate the result, and if possible
312 * call the @a iter in @a cls with the result.
313 *
314 * @param cls closure of type `struct ParserContext *`
315 * @param result the postgres result
316 * @param num_result the number of results in @a result
317 */
318static void
319parse_result_call_iterator (void *cls,
320 PGresult *res,
321 unsigned int num_results)
322{
323 struct ParserContext *pc = cls;
324
325 if (NULL == pc->iter)
326 return; /* no need to do more work */
327 for (unsigned int i = 0; i < num_results; i++)
328 {
329 uint64_t serial;
330 void *data;
331 size_t data_size;
332 uint32_t record_count;
333 char *label;
334 struct GNUNET_IDENTITY_PrivateKey zk;
335 struct GNUNET_PQ_ResultSpec rs_with_zone[] = {
336 GNUNET_PQ_result_spec_uint64 ("seq", &serial),
337 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
338 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
339 GNUNET_PQ_result_spec_string ("label", &label),
340 GNUNET_PQ_result_spec_auto_from_type ("zone_private_key", &zk),
341 GNUNET_PQ_result_spec_end
342 };
343 struct GNUNET_PQ_ResultSpec rs_without_zone[] = {
344 GNUNET_PQ_result_spec_uint64 ("seq", &serial),
345 GNUNET_PQ_result_spec_uint32 ("record_count", &record_count),
346 GNUNET_PQ_result_spec_variable_size ("record_data", &data, &data_size),
347 GNUNET_PQ_result_spec_string ("label", &label),
348 GNUNET_PQ_result_spec_end
349 };
350 struct GNUNET_PQ_ResultSpec *rs;
351
352 rs = (NULL == pc->zone_key) ? rs_with_zone : rs_without_zone;
353 if (GNUNET_YES !=
354 GNUNET_PQ_extract_result (res,
355 rs,
356 i))
357 {
358 GNUNET_break (0);
359 return;
360 }
361
362 if (record_count > 64 * 1024)
363 {
364 /* sanity check, don't stack allocate far too much just
365 because database might contain a large value here */
366 GNUNET_break (0);
367 GNUNET_PQ_cleanup_result (rs);
368 return;
369 }
370
371 {
372 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (record_count)];
373
374 GNUNET_assert (0 != serial);
375 if (GNUNET_OK !=
376 GNUNET_GNSRECORD_records_deserialize (data_size,
377 data,
378 record_count,
379 rd))
380 {
381 GNUNET_break (0);
382 GNUNET_PQ_cleanup_result (rs);
383 return;
384 }
385 pc->iter (pc->iter_cls,
386 serial,
387 (NULL == pc->zone_key) ? &zk : pc->zone_key,
388 label,
389 record_count,
390 rd);
391 }
392 GNUNET_PQ_cleanup_result (rs);
393 }
394 pc->limit -= num_results;
395}
396
397
398/**
399 * Lookup records in the datastore for which we are the authority.
400 *
401 * @param cls closure (internal context for the plugin)
402 * @param zone private key of the zone
403 * @param label name of the record in the zone
404 * @param iter function to call with the result
405 * @param iter_cls closure for @a iter
406 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
407 */
408static int
409namestore_postgres_lookup_records (void *cls,
410 const struct
411 GNUNET_IDENTITY_PrivateKey *zone,
412 const char *label,
413 GNUNET_NAMESTORE_RecordIterator iter,
414 void *iter_cls)
415{
416 struct Plugin *plugin = cls;
417 struct GNUNET_PQ_QueryParam params[] = {
418 GNUNET_PQ_query_param_auto_from_type (zone),
419 GNUNET_PQ_query_param_string (label),
420 GNUNET_PQ_query_param_end
421 };
422 struct ParserContext pc;
423 enum GNUNET_DB_QueryStatus res;
424
425 if (NULL == zone)
426 {
427 GNUNET_break (0);
428 return GNUNET_SYSERR;
429 }
430 pc.iter = iter;
431 pc.iter_cls = iter_cls;
432 pc.zone_key = zone;
433 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
434 "lookup_label",
435 params,
436 &parse_result_call_iterator,
437 &pc);
438 if (res < 0)
439 return GNUNET_SYSERR;
440 if (GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res)
441 return GNUNET_NO;
442 return GNUNET_OK;
443}
444
445
446/**
447 * Iterate over the results for a particular key and zone in the
448 * datastore. Will return at most one result to the iterator.
449 *
450 * @param cls closure (internal context for the plugin)
451 * @param zone hash of public key of the zone, NULL to iterate over all zones
452 * @param serial serial number to exclude in the list of all matching records
453 * @param limit maximum number of results to fetch
454 * @param iter function to call with the result
455 * @param iter_cls closure for @a iter
456 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
457 */
458static int
459namestore_postgres_iterate_records (void *cls,
460 const struct
461 GNUNET_IDENTITY_PrivateKey *zone,
462 uint64_t serial,
463 uint64_t limit,
464 GNUNET_NAMESTORE_RecordIterator iter,
465 void *iter_cls)
466{
467 struct Plugin *plugin = cls;
468 enum GNUNET_DB_QueryStatus res;
469 struct ParserContext pc;
470
471 pc.iter = iter;
472 pc.iter_cls = iter_cls;
473 pc.zone_key = zone;
474 pc.limit = limit;
475 if (NULL == zone)
476 {
477 struct GNUNET_PQ_QueryParam params_without_zone[] = {
478 GNUNET_PQ_query_param_uint64 (&serial),
479 GNUNET_PQ_query_param_uint64 (&limit),
480 GNUNET_PQ_query_param_end
481 };
482
483 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
484 "iterate_all_zones",
485 params_without_zone,
486 &parse_result_call_iterator,
487 &pc);
488 }
489 else
490 {
491 struct GNUNET_PQ_QueryParam params_with_zone[] = {
492 GNUNET_PQ_query_param_auto_from_type (zone),
493 GNUNET_PQ_query_param_uint64 (&serial),
494 GNUNET_PQ_query_param_uint64 (&limit),
495 GNUNET_PQ_query_param_end
496 };
497
498 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
499 "iterate_zone",
500 params_with_zone,
501 &parse_result_call_iterator,
502 &pc);
503 }
504 if (res < 0)
505 return GNUNET_SYSERR;
506
507 if ((GNUNET_DB_STATUS_SUCCESS_NO_RESULTS == res) ||
508 (pc.limit > 0))
509 return GNUNET_NO;
510 return GNUNET_OK;
511}
512
513
514/**
515 * Look for an existing PKEY delegation record for a given public key.
516 * Returns at most one result to the iterator.
517 *
518 * @param cls closure (internal context for the plugin)
519 * @param zone private key of the zone to look up in, never NULL
520 * @param value_zone public key of the target zone (value), never NULL
521 * @param iter function to call with the result
522 * @param iter_cls closure for @a iter
523 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
524 */
525static int
526namestore_postgres_zone_to_name (void *cls,
527 const struct
528 GNUNET_IDENTITY_PrivateKey *zone,
529 const struct
530 GNUNET_IDENTITY_PublicKey *value_zone,
531 GNUNET_NAMESTORE_RecordIterator iter,
532 void *iter_cls)
533{
534 struct Plugin *plugin = cls;
535 struct GNUNET_PQ_QueryParam params[] = {
536 GNUNET_PQ_query_param_auto_from_type (zone),
537 GNUNET_PQ_query_param_auto_from_type (value_zone),
538 GNUNET_PQ_query_param_end
539 };
540 enum GNUNET_DB_QueryStatus res;
541 struct ParserContext pc;
542
543 pc.iter = iter;
544 pc.iter_cls = iter_cls;
545 pc.zone_key = zone;
546 res = GNUNET_PQ_eval_prepared_multi_select (plugin->dbh,
547 "zone_to_name",
548 params,
549 &parse_result_call_iterator,
550 &pc);
551 if (res < 0)
552 return GNUNET_SYSERR;
553 return GNUNET_OK;
554}
555
556
557/**
558 * Shutdown database connection and associate data
559 * structures.
560 *
561 * @param plugin the plugin context (state for this module)
562 */
563static void
564database_shutdown (struct Plugin *plugin)
565{
566 GNUNET_PQ_disconnect (plugin->dbh);
567 plugin->dbh = NULL;
568}
569
570
571/**
572 * Entry point for the plugin.
573 *
574 * @param cls the `struct GNUNET_NAMESTORE_PluginEnvironment*`
575 * @return NULL on error, othrewise the plugin context
576 */
577void *
578libgnunet_plugin_namestore_postgres_init (void *cls)
579{
580 static struct Plugin plugin;
581 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
582 struct GNUNET_NAMESTORE_PluginFunctions *api;
583
584 if (NULL != plugin.cfg)
585 return NULL; /* can only initialize once! */
586 memset (&plugin, 0, sizeof(struct Plugin));
587 plugin.cfg = cfg;
588 if (GNUNET_OK != database_setup (&plugin))
589 {
590 database_shutdown (&plugin);
591 return NULL;
592 }
593 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
594 api->cls = &plugin;
595 api->store_records = &namestore_postgres_store_records;
596 api->iterate_records = &namestore_postgres_iterate_records;
597 api->zone_to_name = &namestore_postgres_zone_to_name;
598 api->lookup_records = &namestore_postgres_lookup_records;
599 LOG (GNUNET_ERROR_TYPE_INFO,
600 "Postgres namestore plugin running\n");
601 return api;
602}
603
604
605/**
606 * Exit point from the plugin.
607 *
608 * @param cls the plugin context (as returned by "init")
609 * @return always NULL
610 */
611void *
612libgnunet_plugin_namestore_postgres_done (void *cls)
613{
614 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
615 struct Plugin *plugin = api->cls;
616
617 database_shutdown (plugin);
618 plugin->cfg = NULL;
619 GNUNET_free (api);
620 LOG (GNUNET_ERROR_TYPE_DEBUG,
621 "Postgres namestore plugin is finished\n");
622 return NULL;
623}
624
625
626/* end of plugin_namestore_postgres.c */
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c
deleted file mode 100644
index 0b3aac84f..000000000
--- a/src/namestore/plugin_namestore_sqlite.c
+++ /dev/null
@@ -1,801 +0,0 @@
1/*
2 * This file is part of GNUnet
3 * Copyright (C) 2009-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 namestore/plugin_namestore_sqlite.c
23 * @brief sqlite-based namestore backend
24 * @author Christian Grothoff
25 */
26
27#include "platform.h"
28#include "gnunet_namestore_plugin.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_gnsrecord_lib.h"
31#include "gnunet_sq_lib.h"
32#include "namestore.h"
33#include <sqlite3.h>
34
35/**
36 * After how many ms "busy" should a DB operation fail for good? A
37 * low value makes sure that we are more responsive to requests
38 * (especially PUTs). A high value guarantees a higher success rate
39 * (SELECTs in iterate can take several seconds despite LIMIT=1).
40 *
41 * The default value of 1s should ensure that users do not experience
42 * huge latencies while at the same time allowing operations to
43 * succeed with reasonable probability.
44 */
45#define BUSY_TIMEOUT_MS 1000
46
47
48/**
49 * Log an error message at log-level 'level' that indicates
50 * a failure of the command 'cmd' on file 'filename'
51 * with the message given by strerror(errno).
52 */
53#define LOG_SQLITE(db, level, cmd) do { GNUNET_log_from (level, \
54 "namestore-sqlite", _ ( \
55 "`%s' failed at %s:%d with error: %s\n"), \
56 cmd, \
57 __FILE__, __LINE__, \
58 sqlite3_errmsg ( \
59 db->dbh)); \
60} while (0)
61
62#define LOG(kind, ...) GNUNET_log_from (kind, "namestore-sqlite", __VA_ARGS__)
63
64
65/**
66 * Context for all functions in this plugin.
67 */
68struct Plugin
69{
70 const struct GNUNET_CONFIGURATION_Handle *cfg;
71
72 /**
73 * Database filename.
74 */
75 char *fn;
76
77 /**
78 * Native SQLite database handle.
79 */
80 sqlite3 *dbh;
81
82 /**
83 * Precompiled SQL to store records.
84 */
85 sqlite3_stmt *store_records;
86
87 /**
88 * Precompiled SQL to deltete existing records.
89 */
90 sqlite3_stmt *delete_records;
91
92 /**
93 * Precompiled SQL for iterate records within a zone.
94 */
95 sqlite3_stmt *iterate_zone;
96
97 /**
98 * Precompiled SQL for iterate all records within all zones.
99 */
100 sqlite3_stmt *iterate_all_zones;
101
102 /**
103 * Precompiled SQL to for reverse lookup based on PKEY.
104 */
105 sqlite3_stmt *zone_to_name;
106
107 /**
108 * Precompiled SQL to lookup records based on label.
109 */
110 sqlite3_stmt *lookup_label;
111};
112
113
114/**
115 * Initialize the database connections and associated
116 * data structures (create tables and indices
117 * as needed as well).
118 *
119 * @param plugin the plugin context (state for this module)
120 * @return #GNUNET_OK on success
121 */
122static int
123database_setup (struct Plugin *plugin)
124{
125 char *sqlite_filename;
126 struct GNUNET_SQ_ExecuteStatement es[] = {
127 GNUNET_SQ_make_try_execute ("PRAGMA temp_store=MEMORY"),
128 GNUNET_SQ_make_try_execute ("PRAGMA synchronous=NORMAL"),
129 GNUNET_SQ_make_try_execute ("PRAGMA legacy_file_format=OFF"),
130 GNUNET_SQ_make_try_execute ("PRAGMA auto_vacuum=INCREMENTAL"),
131 GNUNET_SQ_make_try_execute ("PRAGMA encoding=\"UTF-8\""),
132 GNUNET_SQ_make_try_execute ("PRAGMA locking_mode=EXCLUSIVE"),
133 GNUNET_SQ_make_try_execute ("PRAGMA journal_mode=WAL"),
134 GNUNET_SQ_make_try_execute ("PRAGMA page_size=4092"),
135 GNUNET_SQ_make_execute ("CREATE TABLE IF NOT EXISTS ns098records ("
136 " uid INTEGER PRIMARY KEY,"
137 " zone_private_key BLOB NOT NULL,"
138 " pkey BLOB,"
139 " rvalue INT8 NOT NULL,"
140 " record_count INT NOT NULL,"
141 " record_data BLOB NOT NULL,"
142 " label TEXT NOT NULL"
143 ")"),
144 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_reverse "
145 "ON ns098records (zone_private_key,pkey)"),
146 GNUNET_SQ_make_try_execute ("CREATE INDEX IF NOT EXISTS ir_pkey_iter "
147 "ON ns098records (zone_private_key,uid)"),
148 GNUNET_SQ_EXECUTE_STATEMENT_END
149 };
150 struct GNUNET_SQ_PrepareStatement ps[] = {
151 GNUNET_SQ_make_prepare ("INSERT INTO ns098records "
152 "(zone_private_key,pkey,rvalue,record_count,record_data,label)"
153 " VALUES (?, ?, ?, ?, ?, ?)",
154 &plugin->store_records),
155 GNUNET_SQ_make_prepare ("DELETE FROM ns098records "
156 "WHERE zone_private_key=? AND label=?",
157 &plugin->delete_records),
158 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
159 " FROM ns098records"
160 " WHERE zone_private_key=? AND pkey=?",
161 &plugin->zone_to_name),
162 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
163 " FROM ns098records"
164 " WHERE zone_private_key=? AND uid > ?"
165 " ORDER BY uid ASC"
166 " LIMIT ?",
167 &plugin->iterate_zone),
168 GNUNET_SQ_make_prepare (
169 "SELECT uid,record_count,record_data,label,zone_private_key"
170 " FROM ns098records"
171 " WHERE uid > ?"
172 " ORDER BY uid ASC"
173 " LIMIT ?",
174 &plugin->iterate_all_zones),
175 GNUNET_SQ_make_prepare ("SELECT uid,record_count,record_data,label"
176 " FROM ns098records"
177 " WHERE zone_private_key=? AND label=?",
178 &plugin->lookup_label),
179 GNUNET_SQ_PREPARE_END
180 };
181
182 if (GNUNET_OK !=
183 GNUNET_CONFIGURATION_get_value_filename (plugin->cfg,
184 "namestore-sqlite",
185 "FILENAME",
186 &sqlite_filename))
187 {
188 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
189 "namestore-sqlite",
190 "FILENAME");
191 return GNUNET_SYSERR;
192 }
193 if (GNUNET_OK !=
194 GNUNET_DISK_file_test (sqlite_filename))
195 {
196 if (GNUNET_OK !=
197 GNUNET_DISK_directory_create_for_file (sqlite_filename))
198 {
199 GNUNET_break (0);
200 GNUNET_free (sqlite_filename);
201 return GNUNET_SYSERR;
202 }
203 }
204 /* sqlite_filename should be UTF-8-encoded. If it isn't, it's a bug */
205 plugin->fn = sqlite_filename;
206
207 /* Open database and precompile statements */
208 if (SQLITE_OK !=
209 sqlite3_open (plugin->fn,
210 &plugin->dbh))
211 {
212 LOG (GNUNET_ERROR_TYPE_ERROR,
213 _ ("Unable to initialize SQLite: %s.\n"),
214 sqlite3_errmsg (plugin->dbh));
215 return GNUNET_SYSERR;
216 }
217 GNUNET_break (SQLITE_OK ==
218 sqlite3_busy_timeout (plugin->dbh,
219 BUSY_TIMEOUT_MS));
220 if (GNUNET_OK !=
221 GNUNET_SQ_exec_statements (plugin->dbh,
222 es))
223 {
224 GNUNET_break (0);
225 LOG (GNUNET_ERROR_TYPE_ERROR,
226 _ ("Failed to setup database at `%s'\n"),
227 plugin->fn);
228 return GNUNET_SYSERR;
229 }
230
231 if (GNUNET_OK !=
232 GNUNET_SQ_prepare (plugin->dbh,
233 ps))
234 {
235 GNUNET_break (0);
236 LOG (GNUNET_ERROR_TYPE_ERROR,
237 _ ("Failed to setup database at `%s'\n"),
238 plugin->fn);
239 return GNUNET_SYSERR;
240 }
241 return GNUNET_OK;
242}
243
244
245/**
246 * Shutdown database connection and associate data
247 * structures.
248 * @param plugin the plugin context (state for this module)
249 */
250static void
251database_shutdown (struct Plugin *plugin)
252{
253 int result;
254 sqlite3_stmt *stmt;
255
256 if (NULL != plugin->store_records)
257 sqlite3_finalize (plugin->store_records);
258 if (NULL != plugin->delete_records)
259 sqlite3_finalize (plugin->delete_records);
260 if (NULL != plugin->iterate_zone)
261 sqlite3_finalize (plugin->iterate_zone);
262 if (NULL != plugin->iterate_all_zones)
263 sqlite3_finalize (plugin->iterate_all_zones);
264 if (NULL != plugin->zone_to_name)
265 sqlite3_finalize (plugin->zone_to_name);
266 if (NULL != plugin->lookup_label)
267 sqlite3_finalize (plugin->lookup_label);
268 result = sqlite3_close (plugin->dbh);
269 if (result == SQLITE_BUSY)
270 {
271 LOG (GNUNET_ERROR_TYPE_WARNING,
272 _ (
273 "Tried to close sqlite without finalizing all prepared statements.\n"));
274 stmt = sqlite3_next_stmt (plugin->dbh,
275 NULL);
276 while (NULL != stmt)
277 {
278 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
279 "sqlite",
280 "Closing statement %p\n",
281 stmt);
282 result = sqlite3_finalize (stmt);
283 if (result != SQLITE_OK)
284 GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING,
285 "sqlite",
286 "Failed to close statement %p: %d\n",
287 stmt,
288 result);
289 stmt = sqlite3_next_stmt (plugin->dbh,
290 NULL);
291 }
292 result = sqlite3_close (plugin->dbh);
293 }
294 if (SQLITE_OK != result)
295 LOG_SQLITE (plugin,
296 GNUNET_ERROR_TYPE_ERROR,
297 "sqlite3_close");
298
299 GNUNET_free (plugin->fn);
300}
301
302
303/**
304 * Store a record in the datastore. Removes any existing record in the
305 * same zone with the same name.
306 *
307 * @param cls closure (internal context for the plugin)
308 * @param zone_key private key of the zone
309 * @param label name that is being mapped (at most 255 characters long)
310 * @param rd_count number of entries in @a rd array
311 * @param rd array of records with data to store
312 * @return #GNUNET_OK on success, else #GNUNET_SYSERR
313 */
314static int
315namestore_sqlite_store_records (void *cls,
316 const struct
317 GNUNET_IDENTITY_PrivateKey *zone_key,
318 const char *label,
319 unsigned int rd_count,
320 const struct GNUNET_GNSRECORD_Data *rd)
321{
322 struct Plugin *plugin = cls;
323 int n;
324 struct GNUNET_IDENTITY_PublicKey pkey;
325 uint64_t rvalue;
326 ssize_t data_size;
327
328 memset (&pkey,
329 0,
330 sizeof(pkey));
331 for (unsigned int i = 0; i < rd_count; i++)
332 {
333 LOG (GNUNET_ERROR_TYPE_DEBUG,
334 "Checking if `%d' is zonekey type\n",
335 rd[i].record_type);
336
337 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
338 {
339 GNUNET_break (GNUNET_YES ==
340 GNUNET_GNSRECORD_identity_from_data (rd[i].data,
341 rd[i].data_size,
342 rd[i].record_type,
343 &pkey));
344 LOG (GNUNET_ERROR_TYPE_DEBUG,
345 "Storing delegation zone record value `%s'\n",
346 GNUNET_GNSRECORD_z2s (&pkey));
347
348 break;
349 }
350 }
351 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
352 UINT64_MAX);
353 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
354 rd);
355 if (data_size < 0)
356 {
357 GNUNET_break (0);
358 return GNUNET_SYSERR;
359 }
360 if (data_size > 64 * 65536)
361 {
362 GNUNET_break (0);
363 return GNUNET_SYSERR;
364 }
365 {
366 /* First delete 'old' records */
367 char data[data_size];
368 struct GNUNET_SQ_QueryParam dparams[] = {
369 GNUNET_SQ_query_param_auto_from_type (zone_key),
370 GNUNET_SQ_query_param_string (label),
371 GNUNET_SQ_query_param_end
372 };
373 ssize_t ret;
374
375 ret = GNUNET_GNSRECORD_records_serialize (rd_count,
376 rd,
377 data_size,
378 data);
379 if ((ret < 0) ||
380 (data_size != ret))
381 {
382 GNUNET_break (0);
383 return GNUNET_SYSERR;
384 }
385 if (GNUNET_OK !=
386 GNUNET_SQ_bind (plugin->delete_records,
387 dparams))
388 {
389 LOG_SQLITE (plugin,
390 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
391 "sqlite3_bind_XXXX");
392 GNUNET_SQ_reset (plugin->dbh,
393 plugin->delete_records);
394 return GNUNET_SYSERR;
395 }
396 n = sqlite3_step (plugin->delete_records);
397 GNUNET_SQ_reset (plugin->dbh,
398 plugin->delete_records);
399
400 if (0 != rd_count)
401 {
402 uint32_t rd_count32 = (uint32_t) rd_count;
403 struct GNUNET_SQ_QueryParam sparams[] = {
404 GNUNET_SQ_query_param_auto_from_type (zone_key),
405 GNUNET_SQ_query_param_auto_from_type (&pkey),
406 GNUNET_SQ_query_param_uint64 (&rvalue),
407 GNUNET_SQ_query_param_uint32 (&rd_count32),
408 GNUNET_SQ_query_param_fixed_size (data, data_size),
409 GNUNET_SQ_query_param_string (label),
410 GNUNET_SQ_query_param_end
411 };
412
413 if (GNUNET_OK !=
414 GNUNET_SQ_bind (plugin->store_records,
415 sparams))
416 {
417 LOG_SQLITE (plugin,
418 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
419 "sqlite3_bind_XXXX");
420 GNUNET_SQ_reset (plugin->dbh,
421 plugin->store_records);
422 return GNUNET_SYSERR;
423 }
424 n = sqlite3_step (plugin->store_records);
425 GNUNET_SQ_reset (plugin->dbh,
426 plugin->store_records);
427 }
428 }
429 switch (n)
430 {
431 case SQLITE_DONE:
432 if (0 != rd_count)
433 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
434 "sqlite",
435 "Record stored\n");
436 else
437 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
438 "sqlite",
439 "Record deleted\n");
440 return GNUNET_OK;
441
442 case SQLITE_BUSY:
443 LOG_SQLITE (plugin,
444 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
445 "sqlite3_step");
446 return GNUNET_NO;
447
448 default:
449 LOG_SQLITE (plugin,
450 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
451 "sqlite3_step");
452 return GNUNET_SYSERR;
453 }
454}
455
456
457/**
458 * The given 'sqlite' statement has been prepared to be run.
459 * It will return a record which should be given to the iterator.
460 * Runs the statement and parses the returned record.
461 *
462 * @param plugin plugin context
463 * @param stmt to run (and then clean up)
464 * @param zone_key private key of the zone
465 * @param limit maximum number of results to fetch
466 * @param iter iterator to call with the result
467 * @param iter_cls closure for @a iter
468 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
469 */
470static int
471get_records_and_call_iterator (struct Plugin *plugin,
472 sqlite3_stmt *stmt,
473 const struct
474 GNUNET_IDENTITY_PrivateKey *zone_key,
475 uint64_t limit,
476 GNUNET_NAMESTORE_RecordIterator iter,
477 void *iter_cls)
478{
479 int ret;
480 int sret;
481
482 ret = GNUNET_OK;
483 for (uint64_t i = 0; i < limit; i++)
484 {
485 sret = sqlite3_step (stmt);
486
487 if (SQLITE_DONE == sret)
488 {
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Iteration done (no results)\n");
491 ret = GNUNET_NO;
492 break;
493 }
494 if (SQLITE_ROW != sret)
495 {
496 LOG_SQLITE (plugin,
497 GNUNET_ERROR_TYPE_ERROR,
498 "sqlite_step");
499 ret = GNUNET_SYSERR;
500 break;
501 }
502
503 {
504 uint64_t seq;
505 uint32_t record_count;
506 size_t data_size;
507 void *data;
508 char *label;
509 struct GNUNET_IDENTITY_PrivateKey zk;
510 struct GNUNET_SQ_ResultSpec rs[] = {
511 GNUNET_SQ_result_spec_uint64 (&seq),
512 GNUNET_SQ_result_spec_uint32 (&record_count),
513 GNUNET_SQ_result_spec_variable_size (&data,
514 &data_size),
515 GNUNET_SQ_result_spec_string (&label),
516 GNUNET_SQ_result_spec_end
517 };
518 struct GNUNET_SQ_ResultSpec rsx[] = {
519 GNUNET_SQ_result_spec_uint64 (&seq),
520 GNUNET_SQ_result_spec_uint32 (&record_count),
521 GNUNET_SQ_result_spec_variable_size (&data,
522 &data_size),
523 GNUNET_SQ_result_spec_string (&label),
524 GNUNET_SQ_result_spec_auto_from_type (&zk),
525 GNUNET_SQ_result_spec_end
526 };
527
528 ret = GNUNET_SQ_extract_result (stmt,
529 (NULL == zone_key)
530 ? rsx
531 : rs);
532 if ((GNUNET_OK != ret) ||
533 (record_count > 64 * 1024))
534 {
535 /* sanity check, don't stack allocate far too much just
536 because database might contain a large value here */
537 GNUNET_break (0);
538 ret = GNUNET_SYSERR;
539 break;
540 }
541 else
542 {
543 struct GNUNET_GNSRECORD_Data rd[record_count];
544
545 GNUNET_assert (0 != seq);
546 if (GNUNET_OK !=
547 GNUNET_GNSRECORD_records_deserialize (data_size,
548 data,
549 record_count,
550 rd))
551 {
552 GNUNET_break (0);
553 ret = GNUNET_SYSERR;
554 break;
555 }
556 else
557 {
558 if (NULL != zone_key)
559 zk = *zone_key;
560 if (NULL != iter)
561 iter (iter_cls,
562 seq,
563 &zk,
564 label,
565 record_count,
566 rd);
567 }
568 }
569 GNUNET_SQ_cleanup_result (rs);
570 }
571 }
572 GNUNET_SQ_reset (plugin->dbh,
573 stmt);
574 return ret;
575}
576
577
578/**
579 * Lookup records in the datastore for which we are the authority.
580 *
581 * @param cls closure (internal context for the plugin)
582 * @param zone private key of the zone
583 * @param label name of the record in the zone
584 * @param iter function to call with the result
585 * @param iter_cls closure for @a iter
586 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
587 */
588static int
589namestore_sqlite_lookup_records (void *cls,
590 const struct
591 GNUNET_IDENTITY_PrivateKey *zone,
592 const char *label,
593 GNUNET_NAMESTORE_RecordIterator iter,
594 void *iter_cls)
595{
596 struct Plugin *plugin = cls;
597 struct GNUNET_SQ_QueryParam params[] = {
598 GNUNET_SQ_query_param_auto_from_type (zone),
599 GNUNET_SQ_query_param_string (label),
600 GNUNET_SQ_query_param_end
601 };
602
603 if (NULL == zone)
604 {
605 GNUNET_break (0);
606 return GNUNET_SYSERR;
607 }
608 if (GNUNET_OK !=
609 GNUNET_SQ_bind (plugin->lookup_label,
610 params))
611 {
612 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
613 "sqlite3_bind_XXXX");
614 GNUNET_SQ_reset (plugin->dbh,
615 plugin->lookup_label);
616 return GNUNET_SYSERR;
617 }
618 return get_records_and_call_iterator (plugin,
619 plugin->lookup_label,
620 zone,
621 1,
622 iter,
623 iter_cls);
624}
625
626
627/**
628 * Iterate over the results for a particular key and zone in the
629 * datastore. Will return at most one result to the iterator.
630 *
631 * @param cls closure (internal context for the plugin)
632 * @param zone hash of public key of the zone, NULL to iterate over all zones
633 * @param serial serial number to exclude in the list of all matching records
634 * @param limit maximum number of results to return
635 * @param iter function to call with the result
636 * @param iter_cls closure for @a iter
637 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
638 */
639static int
640namestore_sqlite_iterate_records (void *cls,
641 const struct
642 GNUNET_IDENTITY_PrivateKey *zone,
643 uint64_t serial,
644 uint64_t limit,
645 GNUNET_NAMESTORE_RecordIterator iter,
646 void *iter_cls)
647{
648 struct Plugin *plugin = cls;
649 sqlite3_stmt *stmt;
650 int err;
651
652 if (NULL == zone)
653 {
654 struct GNUNET_SQ_QueryParam params[] = {
655 GNUNET_SQ_query_param_uint64 (&serial),
656 GNUNET_SQ_query_param_uint64 (&limit),
657 GNUNET_SQ_query_param_end
658 };
659
660 stmt = plugin->iterate_all_zones;
661 err = GNUNET_SQ_bind (stmt,
662 params);
663 }
664 else
665 {
666 struct GNUNET_SQ_QueryParam params[] = {
667 GNUNET_SQ_query_param_auto_from_type (zone),
668 GNUNET_SQ_query_param_uint64 (&serial),
669 GNUNET_SQ_query_param_uint64 (&limit),
670 GNUNET_SQ_query_param_end
671 };
672
673 stmt = plugin->iterate_zone;
674 err = GNUNET_SQ_bind (stmt,
675 params);
676 }
677 if (GNUNET_OK != err)
678 {
679 LOG_SQLITE (plugin,
680 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
681 "sqlite3_bind_XXXX");
682 GNUNET_SQ_reset (plugin->dbh,
683 stmt);
684 return GNUNET_SYSERR;
685 }
686 return get_records_and_call_iterator (plugin,
687 stmt,
688 zone,
689 limit,
690 iter,
691 iter_cls);
692}
693
694
695/**
696 * Look for an existing PKEY delegation record for a given public key.
697 * Returns at most one result to the iterator.
698 *
699 * @param cls closure (internal context for the plugin)
700 * @param zone private key of the zone to look up in, never NULL
701 * @param value_zone public key of the target zone (value), never NULL
702 * @param iter function to call with the result
703 * @param iter_cls closure for @a iter
704 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
705 */
706static int
707namestore_sqlite_zone_to_name (void *cls,
708 const struct GNUNET_IDENTITY_PrivateKey *zone,
709 const struct
710 GNUNET_IDENTITY_PublicKey *value_zone,
711 GNUNET_NAMESTORE_RecordIterator iter,
712 void *iter_cls)
713{
714 struct Plugin *plugin = cls;
715 struct GNUNET_SQ_QueryParam params[] = {
716 GNUNET_SQ_query_param_auto_from_type (zone),
717 GNUNET_SQ_query_param_auto_from_type (value_zone),
718 GNUNET_SQ_query_param_end
719 };
720
721 if (GNUNET_OK !=
722 GNUNET_SQ_bind (plugin->zone_to_name,
723 params))
724 {
725 LOG_SQLITE (plugin,
726 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
727 "sqlite3_bind_XXXX");
728 GNUNET_SQ_reset (plugin->dbh,
729 plugin->zone_to_name);
730 return GNUNET_SYSERR;
731 }
732 LOG (GNUNET_ERROR_TYPE_DEBUG,
733 "Performing reverse lookup for `%s'\n",
734 GNUNET_GNSRECORD_z2s (value_zone));
735 return get_records_and_call_iterator (plugin,
736 plugin->zone_to_name,
737 zone,
738 1,
739 iter,
740 iter_cls);
741}
742
743
744/**
745 * Entry point for the plugin.
746 *
747 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
748 * @return NULL on error, otherwise the plugin context
749 */
750void *
751libgnunet_plugin_namestore_sqlite_init (void *cls)
752{
753 static struct Plugin plugin;
754 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
755 struct GNUNET_NAMESTORE_PluginFunctions *api;
756
757 if (NULL != plugin.cfg)
758 return NULL; /* can only initialize once! */
759 memset (&plugin,
760 0,
761 sizeof(struct Plugin));
762 plugin.cfg = cfg;
763 if (GNUNET_OK != database_setup (&plugin))
764 {
765 database_shutdown (&plugin);
766 return NULL;
767 }
768 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
769 api->cls = &plugin;
770 api->store_records = &namestore_sqlite_store_records;
771 api->iterate_records = &namestore_sqlite_iterate_records;
772 api->zone_to_name = &namestore_sqlite_zone_to_name;
773 api->lookup_records = &namestore_sqlite_lookup_records;
774 LOG (GNUNET_ERROR_TYPE_INFO,
775 _ ("Sqlite database running\n"));
776 return api;
777}
778
779
780/**
781 * Exit point from the plugin.
782 *
783 * @param cls the plugin context (as returned by "init")
784 * @return always NULL
785 */
786void *
787libgnunet_plugin_namestore_sqlite_done (void *cls)
788{
789 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
790 struct Plugin *plugin = api->cls;
791
792 database_shutdown (plugin);
793 plugin->cfg = NULL;
794 GNUNET_free (api);
795 LOG (GNUNET_ERROR_TYPE_DEBUG,
796 "sqlite plugin is finished\n");
797 return NULL;
798}
799
800
801/* end of plugin_namestore_sqlite.c */
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c
deleted file mode 100644
index 0475960eb..000000000
--- a/src/namestore/plugin_rest_namestore.c
+++ /dev/null
@@ -1,1153 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012-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 * @author Martin Schanzenbach
22 * @author Philippe Buschmann
23 * @file namestore/plugin_rest_namestore.c
24 * @brief GNUnet Namestore REST plugin
25 */
26
27#include "platform.h"
28#include "gnunet_rest_plugin.h"
29#include "gnunet_gns_service.h"
30#include "gnunet_namestore_service.h"
31#include "gnunet_identity_service.h"
32#include "gnunet_rest_lib.h"
33#include "gnunet_gnsrecord_json_lib.h"
34#include "microhttpd.h"
35#include <jansson.h>
36
37/**
38 * Namestore Namespace
39 */
40#define GNUNET_REST_API_NS_NAMESTORE "/namestore"
41
42/**
43 * Error message Unknown Error
44 */
45#define GNUNET_REST_NAMESTORE_ERROR_UNKNOWN "Unknown Error"
46
47/**
48 * Error message No identity found
49 */
50#define GNUNET_REST_IDENTITY_NOT_FOUND "No identity found"
51
52
53/**
54 * Error message Failed request
55 */
56#define GNUNET_REST_NAMESTORE_FAILED "Namestore action failed"
57
58/**
59 * Error message invalid data
60 */
61#define GNUNET_REST_NAMESTORE_INVALID_DATA "Data invalid"
62
63/**
64 * Error message No data
65 */
66#define GNUNET_REST_NAMESTORE_NO_DATA "No data"
67
68/**
69 * State while collecting all egos
70 */
71#define ID_REST_STATE_INIT 0
72
73/**
74 * Done collecting egos
75 */
76#define ID_REST_STATE_POST_INIT 1
77/**
78 * The configuration handle
79 */
80const struct GNUNET_CONFIGURATION_Handle *cfg;
81
82/**
83 * HTTP methods allows for this plugin
84 */
85static char *allow_methods;
86
87/**
88 * Ego list
89 */
90static struct EgoEntry *ego_head;
91
92/**
93 * Ego list
94 */
95static struct EgoEntry *ego_tail;
96
97/**
98 * The processing state
99 */
100static int state;
101
102/**
103 * Handle to NAMESTORE
104 */
105static struct GNUNET_NAMESTORE_Handle *ns_handle;
106
107/**
108 * Handle to Identity service.
109 */
110static struct GNUNET_IDENTITY_Handle *identity_handle;
111
112/**
113 * @brief struct returned by the initialization function of the plugin
114 */
115struct Plugin
116{
117 const struct GNUNET_CONFIGURATION_Handle *cfg;
118};
119
120/**
121 * The default namestore ego
122 */
123struct EgoEntry
124{
125 /**
126 * DLL
127 */
128 struct EgoEntry *next;
129
130 /**
131 * DLL
132 */
133 struct EgoEntry *prev;
134
135 /**
136 * Ego Identifier
137 */
138 char *identifier;
139
140 /**
141 * Public key string
142 */
143 char *keystring;
144
145 /**
146 * The Ego
147 */
148 struct GNUNET_IDENTITY_Ego *ego;
149};
150
151
152enum UpdateStrategy
153{
154 UPDATE_STRATEGY_REPLACE,
155 UPDATE_STRATEGY_APPEND
156};
157
158/**
159 * The request handle
160 */
161struct RequestHandle
162{
163 /**
164 * DLL
165 */
166 struct RequestHandle *next;
167
168 /**
169 * DLL
170 */
171 struct RequestHandle *prev;
172
173 /**
174 * Records to store
175 */
176 char *record_name;
177
178 /**
179 * Record type filter
180 */
181 uint32_t record_type;
182
183 /**
184 * How to update the record set
185 */
186 enum UpdateStrategy update_strategy;
187
188 /**
189 * Records to store
190 */
191 struct GNUNET_GNSRECORD_Data *rd;
192
193 /**
194 * Number of records in rd
195 */
196 unsigned int rd_count;
197
198 /**
199 * NAMESTORE Operation
200 */
201 struct GNUNET_NAMESTORE_QueueEntry *ns_qe;
202
203 /**
204 * Response object
205 */
206 json_t *resp_object;
207
208
209 /**
210 * Handle to NAMESTORE it
211 */
212 struct GNUNET_NAMESTORE_ZoneIterator *list_it;
213
214 /**
215 * Private key for the zone
216 */
217 const struct GNUNET_IDENTITY_PrivateKey *zone_pkey;
218
219 /**
220 * IDENTITY Operation
221 */
222 struct EgoEntry *ego_entry;
223
224 /**
225 * IDENTITY Operation
226 */
227 struct GNUNET_IDENTITY_Operation *op;
228
229 /**
230 * Rest connection
231 */
232 struct GNUNET_REST_RequestHandle *rest_handle;
233
234 /**
235 * Desired timeout for the lookup (default is no timeout).
236 */
237 struct GNUNET_TIME_Relative timeout;
238
239 /**
240 * ID of a task associated with the resolution process.
241 */
242 struct GNUNET_SCHEDULER_Task *timeout_task;
243
244 /**
245 * The plugin result processor
246 */
247 GNUNET_REST_ResultProcessor proc;
248
249 /**
250 * The closure of the result processor
251 */
252 void *proc_cls;
253
254 /**
255 * The url
256 */
257 char *url;
258
259 /**
260 * Error response message
261 */
262 char *emsg;
263
264 /**
265 * Response code
266 */
267 int response_code;
268};
269
270/**
271 * DLL
272 */
273static struct RequestHandle *requests_head;
274
275/**
276 * DLL
277 */
278static struct RequestHandle *requests_tail;
279
280
281/**
282 * Cleanup lookup handle
283 * @param handle Handle to clean up
284 */
285static void
286cleanup_handle (void *cls)
287{
288 struct RequestHandle *handle = cls;
289
290 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
291 if (NULL != handle->timeout_task)
292 {
293 GNUNET_SCHEDULER_cancel (handle->timeout_task);
294 handle->timeout_task = NULL;
295 }
296 if (NULL != handle->record_name)
297 GNUNET_free (handle->record_name);
298 if (NULL != handle->url)
299 GNUNET_free (handle->url);
300 if (NULL != handle->emsg)
301 GNUNET_free (handle->emsg);
302 if (NULL != handle->rd)
303 {
304 for (int i = 0; i < handle->rd_count; i++)
305 {
306 if (NULL != handle->rd[i].data)
307 GNUNET_free_nz ((void *) handle->rd[i].data);
308 }
309 GNUNET_free (handle->rd);
310 }
311 if (NULL != handle->timeout_task)
312 GNUNET_SCHEDULER_cancel (handle->timeout_task);
313 if (NULL != handle->list_it)
314 GNUNET_NAMESTORE_zone_iteration_stop (handle->list_it);
315 if (NULL != handle->ns_qe)
316 GNUNET_NAMESTORE_cancel (handle->ns_qe);
317
318 if (NULL != handle->resp_object)
319 {
320 json_decref (handle->resp_object);
321 }
322 GNUNET_CONTAINER_DLL_remove (requests_head,
323 requests_tail,
324 handle);
325 GNUNET_free (handle);
326}
327
328
329/**
330 * Task run on errors. Reports an error and cleans up everything.
331 *
332 * @param cls the `struct RequestHandle`
333 */
334static void
335do_error (void *cls)
336{
337 struct RequestHandle *handle = cls;
338 struct MHD_Response *resp;
339 json_t *json_error = json_object ();
340 char *response;
341
342 if (NULL == handle->emsg)
343 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_ERROR_UNKNOWN);
344
345 json_object_set_new (json_error, "error", json_string (handle->emsg));
346
347 if (0 == handle->response_code)
348 handle->response_code = MHD_HTTP_INTERNAL_SERVER_ERROR;
349 response = json_dumps (json_error, 0);
350 resp = GNUNET_REST_create_response (response);
351 MHD_add_response_header (resp, "Content-Type", "application/json");
352 handle->proc (handle->proc_cls, resp, handle->response_code);
353 json_decref (json_error);
354 GNUNET_free (response);
355 cleanup_handle (handle);
356}
357
358
359/**
360 * Get EgoEntry from list with either a public key or a name
361 * If public key and name are not NULL, it returns the public key result first
362 *
363 * @param handle the RequestHandle
364 * @param pubkey the public key of an identity (only one can be NULL)
365 * @param name the name of an identity (only one can be NULL)
366 * @return EgoEntry or NULL if not found
367 */
368struct EgoEntry *
369get_egoentry_namestore (struct RequestHandle *handle, char *name)
370{
371 struct EgoEntry *ego_entry;
372 char *copy = GNUNET_strdup (name);
373 char *tmp;
374
375 if (NULL == name)
376 return NULL;
377 tmp = strtok (copy, "/");
378 if (NULL == tmp)
379 return NULL;
380 for (ego_entry = ego_head; NULL != ego_entry;
381 ego_entry = ego_entry->next)
382 {
383 if (0 != strcasecmp (tmp, ego_entry->identifier))
384 continue;
385 GNUNET_free (copy);
386 return ego_entry;
387 }
388 GNUNET_free (copy);
389 return NULL;
390}
391
392
393/**
394 * Does internal server error when iteration failed.
395 *
396 * @param cls the `struct RequestHandle`
397 */
398static void
399namestore_iteration_error (void *cls)
400{
401 struct RequestHandle *handle = cls;
402
403 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
404 GNUNET_SCHEDULER_add_now (&do_error, handle);
405 return;
406}
407
408
409/**
410 * Create finished callback
411 *
412 * @param cls the `struct RequestHandle`
413 * @param success the success indicating integer, GNUNET_OK on success
414 * @param emsg the error message (can be NULL)
415 */
416static void
417create_finished (void *cls, int32_t success, const char *emsg)
418{
419 struct RequestHandle *handle = cls;
420 struct MHD_Response *resp;
421
422 handle->ns_qe = NULL;
423 if (GNUNET_YES != success)
424 {
425 if (NULL != emsg)
426 {
427 handle->emsg = GNUNET_strdup (emsg);
428 GNUNET_SCHEDULER_add_now (&do_error, handle);
429 return;
430 }
431 handle->emsg = GNUNET_strdup ("Error storing records");
432 GNUNET_SCHEDULER_add_now (&do_error, handle);
433 return;
434 }
435 resp = GNUNET_REST_create_response (NULL);
436 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
437 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
438}
439
440
441/**
442 * Delete finished callback
443 *
444 * @param cls the `struct RequestHandle`
445 * @param success the success indicating integer, GNUNET_OK on success
446 * @param emsg the error message (can be NULL)
447 */
448static void
449del_finished (void *cls, int32_t success, const char *emsg)
450{
451 struct RequestHandle *handle = cls;
452
453 handle->ns_qe = NULL;
454 if (GNUNET_NO == success)
455 {
456 handle->response_code = MHD_HTTP_NOT_FOUND;
457 handle->emsg = GNUNET_strdup ("No record found");
458 GNUNET_SCHEDULER_add_now (&do_error, handle);
459 return;
460 }
461 if (GNUNET_SYSERR == success)
462 {
463 if (NULL != emsg)
464 {
465 handle->emsg = GNUNET_strdup (emsg);
466 GNUNET_SCHEDULER_add_now (&do_error, handle);
467 return;
468 }
469 handle->emsg = GNUNET_strdup ("Deleting record failed");
470 GNUNET_SCHEDULER_add_now (&do_error, handle);
471 return;
472 }
473 handle->proc (handle->proc_cls,
474 GNUNET_REST_create_response (NULL),
475 MHD_HTTP_NO_CONTENT);
476 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
477}
478
479
480/**
481 * Iteration over all results finished, build final
482 * response.
483 *
484 * @param cls the `struct RequestHandle`
485 */
486static void
487namestore_list_finished (void *cls)
488{
489 struct RequestHandle *handle = cls;
490 char *result_str;
491 struct MHD_Response *resp;
492
493 handle->list_it = NULL;
494
495 if (NULL == handle->resp_object)
496 handle->resp_object = json_array ();
497
498 result_str = json_dumps (handle->resp_object, 0);
499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
500 resp = GNUNET_REST_create_response (result_str);
501 MHD_add_response_header (resp, "Content-Type", "application/json");
502 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
503 GNUNET_free (result_str);
504 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
505}
506
507
508/**
509 * Create a response with requested records
510 *
511 * @param handle the RequestHandle
512 */
513static void
514namestore_list_iteration (void *cls,
515 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
516 const char *rname,
517 unsigned int rd_len,
518 const struct GNUNET_GNSRECORD_Data *rd)
519{
520 struct RequestHandle *handle = cls;
521 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
522 json_t *record_obj;
523 int i = 0;
524 int j = 0;
525
526 if (NULL == handle->resp_object)
527 handle->resp_object = json_array ();
528 for (i = 0; i < rd_len; i++)
529 {
530 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
531 (rd[i].record_type != handle->record_type))
532 continue; /* Apply filter */
533 rd_filtered[j] = rd[i];
534 rd_filtered[j].data = rd[i].data;
535 j++;
536 }
537 /** Only add if not empty **/
538 if (j > 0)
539 {
540 record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (rname,
541 rd_filtered,
542 j);
543 json_array_append_new (handle->resp_object, record_obj);
544 }
545 GNUNET_NAMESTORE_zone_iterator_next (handle->list_it, 1);
546}
547
548
549/**
550 * Handle lookup error
551 *
552 * @param cls the request handle
553 */
554static void
555ns_lookup_error_cb (void *cls)
556{
557 struct RequestHandle *handle = cls;
558
559 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
560 GNUNET_SCHEDULER_add_now (&do_error, handle);
561}
562
563
564static void
565ns_get_lookup_cb (void *cls,
566 const struct GNUNET_IDENTITY_PrivateKey *zone,
567 const char *label,
568 unsigned int rd_len,
569 const struct GNUNET_GNSRECORD_Data *rd)
570{
571 struct RequestHandle *handle = cls;
572 struct GNUNET_GNSRECORD_Data rd_filtered[rd_len];
573 json_t *record_obj;
574 int i = 0;
575 int j = 0;
576
577 handle->ns_qe = NULL;
578 if (NULL == handle->resp_object)
579 handle->resp_object = json_array ();
580 for (i = 0; i < rd_len; i++)
581 {
582 if ((GNUNET_GNSRECORD_TYPE_ANY != handle->record_type) &&
583 (rd[i].record_type != handle->record_type))
584 continue; /* Apply filter */
585 rd_filtered[j] = rd[i];
586 rd_filtered[j].data = rd[i].data;
587 j++;
588 }
589 /** Only add if not empty **/
590 if (j > 0)
591 {
592 record_obj = GNUNET_GNSRECORD_JSON_from_gnsrecord (label,
593 rd_filtered,
594 j);
595 json_array_append_new (handle->resp_object, record_obj);
596 }
597 GNUNET_SCHEDULER_add_now (&namestore_list_finished, handle);
598}
599
600
601/**
602 * Handle namestore GET request
603 *
604 * @param con_handle the connection handle
605 * @param url the url
606 * @param cls the RequestHandle
607 */
608void
609namestore_get (struct GNUNET_REST_RequestHandle *con_handle,
610 const char *url,
611 void *cls)
612{
613 struct RequestHandle *handle = cls;
614 struct EgoEntry *ego_entry;
615 struct GNUNET_HashCode key;
616 char *egoname;
617 char *labelname;
618 char *typename;
619
620 egoname = NULL;
621 ego_entry = NULL;
622
623 // set zone to name if given
624 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
625 {
626 handle->response_code = MHD_HTTP_NOT_FOUND;
627 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
628 GNUNET_SCHEDULER_add_now (&do_error, handle);
629 return;
630 }
631 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
632 ego_entry = get_egoentry_namestore (handle, egoname);
633 if (NULL == ego_entry)
634 {
635 handle->response_code = MHD_HTTP_NOT_FOUND;
636 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
637 GNUNET_SCHEDULER_add_now (&do_error, handle);
638 return;
639 }
640 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
641
642 GNUNET_CRYPTO_hash ("record_type", strlen ("record_type"), &key);
643 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
644 if (GNUNET_YES ==
645 GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key))
646 {
647 typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
648 &key);
649 if (NULL != typename)
650 handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename);
651 }
652 labelname = &egoname[strlen (ego_entry->identifier)];
653 // set zone to name if given
654 if (1 >= strlen (labelname))
655 {
656 handle->list_it =
657 GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
658 handle->zone_pkey,
659 &namestore_iteration_error,
660 handle,
661 &namestore_list_iteration,
662 handle,
663 &namestore_list_finished,
664 handle);
665 if (NULL == handle->list_it)
666 {
667 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
668 GNUNET_SCHEDULER_add_now (&do_error, handle);
669 return;
670 }
671 return;
672 }
673 handle->record_name = GNUNET_strdup (labelname + 1);
674 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
675 handle->zone_pkey,
676 handle->record_name,
677 &ns_lookup_error_cb,
678 handle,
679 &ns_get_lookup_cb,
680 handle);
681 if (NULL == handle->ns_qe)
682 {
683 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
684 GNUNET_SCHEDULER_add_now (&do_error, handle);
685 return;
686 }
687}
688
689
690static void
691ns_lookup_cb (void *cls,
692 const struct GNUNET_IDENTITY_PrivateKey *zone,
693 const char *label,
694 unsigned int rd_count,
695 const struct GNUNET_GNSRECORD_Data *rd)
696{
697 struct RequestHandle *handle = cls;
698 struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count];
699 int i = 0;
700 int j = 0;
701
702 if (UPDATE_STRATEGY_APPEND == handle->update_strategy)
703 {
704 for (i = 0; i < rd_count; i++)
705 rd_new[i] = rd[i];
706 }
707 for (j = 0; j < handle->rd_count; j++)
708 rd_new[i + j] = handle->rd[j];
709 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
710 handle->zone_pkey,
711 handle->record_name,
712 i + j,
713 rd_new,
714 &create_finished,
715 handle);
716 if (NULL == handle->ns_qe)
717 {
718 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
719 GNUNET_SCHEDULER_add_now (&do_error, handle);
720 return;
721 }
722}
723
724
725/**
726 * Handle namestore POST/PUT request
727 *
728 * @param con_handle the connection handle
729 * @param url the url
730 * @param cls the RequestHandle
731 */
732void
733namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle,
734 const char *url,
735 void *cls)
736{
737 struct RequestHandle *handle = cls;
738 struct EgoEntry *ego_entry;
739 char *egoname;
740 json_t *data_js;
741 json_error_t err;
742
743 char term_data[handle->rest_handle->data_size + 1];
744
745 if (0 >= handle->rest_handle->data_size)
746 {
747 handle->response_code = MHD_HTTP_BAD_REQUEST;
748 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA);
749 GNUNET_SCHEDULER_add_now (&do_error, handle);
750 return;
751 }
752 term_data[handle->rest_handle->data_size] = '\0';
753 GNUNET_memcpy (term_data,
754 handle->rest_handle->data,
755 handle->rest_handle->data_size);
756 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
757 struct GNUNET_JSON_Specification gnsspec[] =
758 { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count,
759 &handle->record_name),
760 GNUNET_JSON_spec_end () };
761 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
762 {
763 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
764 GNUNET_SCHEDULER_add_now (&do_error, handle);
765 json_decref (data_js);
766 return;
767 }
768 GNUNET_JSON_parse_free (gnsspec);
769 if (0 >= strlen (handle->record_name))
770 {
771 handle->response_code = MHD_HTTP_BAD_REQUEST;
772 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
773 GNUNET_SCHEDULER_add_now (&do_error, handle);
774 json_decref (data_js);
775 return;
776 }
777 json_decref (data_js);
778
779 egoname = NULL;
780 ego_entry = NULL;
781
782 // set zone to name if given
783 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
784 {
785 handle->response_code = MHD_HTTP_NOT_FOUND;
786 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
787 GNUNET_SCHEDULER_add_now (&do_error, handle);
788 return;
789 }
790 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
791 ego_entry = get_egoentry_namestore (handle, egoname);
792
793 if (NULL == ego_entry)
794 {
795 handle->response_code = MHD_HTTP_NOT_FOUND;
796 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
797 GNUNET_SCHEDULER_add_now (&do_error, handle);
798 return;
799 }
800 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
801 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
802 handle->zone_pkey,
803 handle->record_name,
804 &ns_lookup_error_cb,
805 handle,
806 &ns_lookup_cb,
807 handle);
808 if (NULL == handle->ns_qe)
809 {
810 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
811 GNUNET_SCHEDULER_add_now (&do_error, handle);
812 return;
813 }
814}
815
816
817/**
818 * Handle namestore PUT request
819 *
820 * @param con_handle the connection handle
821 * @param url the url
822 * @param cls the RequestHandle
823 */
824void
825namestore_update (struct GNUNET_REST_RequestHandle *con_handle,
826 const char *url,
827 void *cls)
828{
829 struct RequestHandle *handle = cls;
830 handle->update_strategy = UPDATE_STRATEGY_REPLACE;
831 namestore_add_or_update (con_handle, url, cls);
832}
833
834
835/**
836 * Handle namestore POST request
837 *
838 * @param con_handle the connection handle
839 * @param url the url
840 * @param cls the RequestHandle
841 */
842void
843namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
844 const char *url,
845 void *cls)
846{
847 struct RequestHandle *handle = cls;
848 handle->update_strategy = UPDATE_STRATEGY_APPEND;
849 namestore_add_or_update (con_handle, url, cls);
850}
851
852
853/**
854 * Handle namestore DELETE request
855 *
856 * @param con_handle the connection handle
857 * @param url the url
858 * @param cls the RequestHandle
859 */
860void
861namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
862 const char *url,
863 void *cls)
864{
865 struct RequestHandle *handle = cls;
866 struct EgoEntry *ego_entry;
867 char *egoname;
868 char *labelname;
869
870 egoname = NULL;
871 ego_entry = NULL;
872
873 // set zone to name if given
874 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
875 {
876 handle->response_code = MHD_HTTP_NOT_FOUND;
877 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
878 GNUNET_SCHEDULER_add_now (&do_error, handle);
879 return;
880 }
881 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
882 ego_entry = get_egoentry_namestore (handle, egoname);
883 if (NULL == ego_entry)
884 {
885 handle->response_code = MHD_HTTP_NOT_FOUND;
886 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
887 GNUNET_SCHEDULER_add_now (&do_error, handle);
888 return;
889 }
890 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
891 labelname = &egoname[strlen (ego_entry->identifier)];
892 // set zone to name if given
893 if (1 >= strlen (labelname))
894 {
895 /* label is only "/" */
896 handle->response_code = MHD_HTTP_BAD_REQUEST;
897 handle->emsg = GNUNET_strdup ("Label missing");
898 GNUNET_SCHEDULER_add_now (&do_error, handle);
899 }
900
901 handle->record_name = GNUNET_strdup (labelname + 1);
902 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
903 handle->zone_pkey,
904 handle->record_name,
905 0,
906 NULL,
907 &del_finished,
908 handle);
909 if (NULL == handle->ns_qe)
910 {
911 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
912 GNUNET_SCHEDULER_add_now (&do_error, handle);
913 return;
914 }
915}
916
917
918/**
919 * Respond to OPTIONS request
920 *
921 * @param con_handle the connection handle
922 * @param url the url
923 * @param cls the RequestHandle
924 */
925static void
926options_cont (struct GNUNET_REST_RequestHandle *con_handle,
927 const char *url,
928 void *cls)
929{
930 struct MHD_Response *resp;
931 struct RequestHandle *handle = cls;
932
933 // independent of path return all options
934 resp = GNUNET_REST_create_response (NULL);
935 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
936 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
937 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
938 return;
939}
940
941
942static void
943list_ego (void *cls,
944 struct GNUNET_IDENTITY_Ego *ego,
945 void **ctx,
946 const char *identifier)
947{
948 struct EgoEntry *ego_entry;
949 struct GNUNET_IDENTITY_PublicKey pk;
950
951 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
952 {
953 state = ID_REST_STATE_POST_INIT;
954 return;
955 }
956 if (NULL == ego)
957 {
958 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
959 "Called with NULL ego\n");
960 return;
961 }
962 if (ID_REST_STATE_INIT == state)
963 {
964 ego_entry = GNUNET_new (struct EgoEntry);
965 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
966 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
967 ego_entry->ego = ego;
968 ego_entry->identifier = GNUNET_strdup (identifier);
969 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
970 ego_tail,
971 ego_entry);
972 }
973 /* Ego renamed or added */
974 if (identifier != NULL)
975 {
976 for (ego_entry = ego_head; NULL != ego_entry;
977 ego_entry = ego_entry->next)
978 {
979 if (ego_entry->ego == ego)
980 {
981 /* Rename */
982 GNUNET_free (ego_entry->identifier);
983 ego_entry->identifier = GNUNET_strdup (identifier);
984 break;
985 }
986 }
987 if (NULL == ego_entry)
988 {
989 /* Add */
990 ego_entry = GNUNET_new (struct EgoEntry);
991 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
992 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
993 ego_entry->ego = ego;
994 ego_entry->identifier = GNUNET_strdup (identifier);
995 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
996 ego_tail,
997 ego_entry);
998 }
999 }
1000 else
1001 {
1002 /* Delete */
1003 for (ego_entry = ego_head; NULL != ego_entry;
1004 ego_entry = ego_entry->next)
1005 {
1006 if (ego_entry->ego == ego)
1007 break;
1008 }
1009 if (NULL == ego_entry)
1010 return; /* Not found */
1011
1012 GNUNET_CONTAINER_DLL_remove (ego_head,
1013 ego_tail,
1014 ego_entry);
1015 GNUNET_free (ego_entry->identifier);
1016 GNUNET_free (ego_entry->keystring);
1017 GNUNET_free (ego_entry);
1018 return;
1019 }
1020
1021}
1022
1023
1024/**
1025 * Function processing the REST call
1026 *
1027 * @param method HTTP method
1028 * @param url URL of the HTTP request
1029 * @param data body of the HTTP request (optional)
1030 * @param data_size length of the body
1031 * @param proc callback function for the result
1032 * @param proc_cls closure for callback function
1033 * @return GNUNET_OK if request accepted
1034 */
1035static enum GNUNET_GenericReturnValue
1036rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1037 GNUNET_REST_ResultProcessor proc,
1038 void *proc_cls)
1039{
1040 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1041 struct GNUNET_REST_RequestHandlerError err;
1042 static const struct GNUNET_REST_RequestHandler handlers[] =
1043 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1044 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1045 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1046 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete },
1047 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1048 GNUNET_REST_HANDLER_END };
1049
1050 handle->response_code = 0;
1051 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1052 handle->proc_cls = proc_cls;
1053 handle->proc = proc;
1054 handle->rest_handle = rest_handle;
1055 handle->zone_pkey = NULL;
1056 handle->timeout_task =
1057 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1058 handle->url = GNUNET_strdup (rest_handle->url);
1059 if (handle->url[strlen (handle->url) - 1] == '/')
1060 handle->url[strlen (handle->url) - 1] = '\0';
1061 GNUNET_CONTAINER_DLL_insert (requests_head,
1062 requests_tail,
1063 handle);
1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1065 if (GNUNET_NO ==
1066 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1067 {
1068 cleanup_handle (handle);
1069 return GNUNET_NO;
1070 }
1071
1072 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1073 return GNUNET_YES;
1074}
1075
1076
1077/**
1078 * Entry point for the plugin.
1079 *
1080 * @param cls Config info
1081 * @return NULL on error, otherwise the plugin context
1082 */
1083void *
1084libgnunet_plugin_rest_namestore_init (void *cls)
1085{
1086 static struct Plugin plugin;
1087 struct GNUNET_REST_Plugin *api;
1088
1089 cfg = cls;
1090 if (NULL != plugin.cfg)
1091 return NULL; /* can only initialize once! */
1092 memset (&plugin, 0, sizeof(struct Plugin));
1093 plugin.cfg = cfg;
1094 api = GNUNET_new (struct GNUNET_REST_Plugin);
1095 api->cls = &plugin;
1096 api->name = GNUNET_REST_API_NS_NAMESTORE;
1097 api->process_request = &rest_process_request;
1098 state = ID_REST_STATE_INIT;
1099 GNUNET_asprintf (&allow_methods,
1100 "%s, %s, %s, %s, %s",
1101 MHD_HTTP_METHOD_GET,
1102 MHD_HTTP_METHOD_POST,
1103 MHD_HTTP_METHOD_PUT,
1104 MHD_HTTP_METHOD_DELETE,
1105 MHD_HTTP_METHOD_OPTIONS);
1106 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1107 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1108
1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n"));
1110 return api;
1111}
1112
1113
1114/**
1115 * Exit point from the plugin.
1116 *
1117 * @param cls the plugin context (as returned by "init")
1118 * @return always NULL
1119 */
1120void *
1121libgnunet_plugin_rest_namestore_done (void *cls)
1122{
1123 struct GNUNET_REST_Plugin *api = cls;
1124 struct Plugin *plugin = api->cls;
1125 struct RequestHandle *request;
1126 struct EgoEntry *ego_entry;
1127 struct EgoEntry *ego_tmp;
1128
1129 plugin->cfg = NULL;
1130 while (NULL != (request = requests_head))
1131 do_error (request);
1132 if (NULL != identity_handle)
1133 GNUNET_IDENTITY_disconnect (identity_handle);
1134 if (NULL != ns_handle)
1135 GNUNET_NAMESTORE_disconnect (ns_handle);
1136
1137 for (ego_entry = ego_head; NULL != ego_entry;)
1138 {
1139 ego_tmp = ego_entry;
1140 ego_entry = ego_entry->next;
1141 GNUNET_free (ego_tmp->identifier);
1142 GNUNET_free (ego_tmp->keystring);
1143 GNUNET_free (ego_tmp);
1144 }
1145
1146 GNUNET_free (allow_methods);
1147 GNUNET_free (api);
1148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1149 return NULL;
1150}
1151
1152
1153/* end of plugin_rest_namestore.c */
diff --git a/src/namestore/test_common.c b/src/namestore/test_common.c
deleted file mode 100644
index 58afb0a32..000000000
--- a/src/namestore/test_common.c
+++ /dev/null
@@ -1,80 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20/**
21 * @file namestore/test_common.c
22 * @brief common functions for testcase setup
23 */
24
25/**
26 * test if we can load the plugin @a name.
27 */
28static int
29TNC_test_plugin (const char *cfg_name)
30{
31 char *database;
32 char *db_lib_name;
33 struct GNUNET_NAMESTORE_PluginFunctions *db;
34 struct GNUNET_CONFIGURATION_Handle *cfg;
35
36 cfg = GNUNET_CONFIGURATION_create ();
37 if (GNUNET_OK != GNUNET_CONFIGURATION_load (cfg, cfg_name))
38 {
39 GNUNET_break (0);
40 GNUNET_CONFIGURATION_destroy (cfg);
41 return GNUNET_SYSERR;
42 }
43 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
44 "namestore",
45 "database",
46 &database))
47 {
48 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
49 GNUNET_CONFIGURATION_destroy (cfg);
50 return GNUNET_SYSERR;
51 }
52 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
53 GNUNET_free (database);
54 db = GNUNET_PLUGIN_load (db_lib_name, (void *) cfg);
55 if (NULL != db)
56 GNUNET_break (NULL == GNUNET_PLUGIN_unload (db_lib_name, db));
57 GNUNET_free (db_lib_name);
58 GNUNET_CONFIGURATION_destroy (cfg);
59 if (NULL == db)
60 return GNUNET_NO;
61 return GNUNET_YES;
62}
63
64
65/**
66 * General setup logic for starting the tests. Obtains the @a
67 * plugin_name and initializes the @a cfg_name.
68 */
69#define SETUP_CFG(plugin_name, cfg_name) \
70 do \
71 { \
72 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]); \
73 GNUNET_asprintf (&cfg_name, "test_namestore_api_%s.conf", plugin_name); \
74 if (! TNC_test_plugin (cfg_name)) \
75 { \
76 GNUNET_free (cfg_name); \
77 return 77; \
78 } \
79 GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TEST_HOME"); \
80 } while (0)
diff --git a/src/namestore/test_hostkey b/src/namestore/test_hostkey
deleted file mode 100644
index e69de29bb..000000000
--- a/src/namestore/test_hostkey
+++ /dev/null
diff --git a/src/namestore/test_namestore_api.conf b/src/namestore/test_namestore_api.conf
deleted file mode 100644
index 3e75c2ded..000000000
--- a/src/namestore/test_namestore_api.conf
+++ /dev/null
@@ -1,22 +0,0 @@
1@INLINE@ ../../contrib/conf/gnunet/no_forcestart.conf
2@INLINE@ ../../contrib/conf/gnunet/no_autostart_above_core.conf
3
4[PATHS]
5GNUNET_TEST_HOME = $GNUNET_TMP/test-gnunet-namestore/
6
7[namestore]
8DATABASE = sqlite
9START_ON_DEMAND = YES
10
11[namecache]
12DATABASE = sqlite
13START_ON_DEMAND = YES
14
15[identity]
16START_ON_DEMAND = YES
17
18[nse]
19WORKBITS = 0
20
21[transport]
22PLUGINS =
diff --git a/src/namestore/test_namestore_api_flat.conf b/src/namestore/test_namestore_api_flat.conf
deleted file mode 100644
index 8460d143c..000000000
--- a/src/namestore/test_namestore_api_flat.conf
+++ /dev/null
@@ -1,7 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = flat
5
6[namestore-heap]
7FILENAME = $GNUNET_TEST_HOME/namestore/flat.db
diff --git a/src/namestore/test_namestore_api_lookup_nick.c b/src/namestore/test_namestore_api_lookup_nick.c
deleted file mode 100644
index 7decf39f8..000000000
--- a/src/namestore/test_namestore_api_lookup_nick.c
+++ /dev/null
@@ -1,347 +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 namestore/test_namestore_api_lookup_nick.c
22 * @brief testcase for namestore_api.c: NICK records
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_gns_service.h"
27#include "gnunet_testing_lib.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32#define TEST_RECORD_DATALEN 123
33
34#define TEST_NICK "gnunettestnick"
35
36#define TEST_RECORD_DATA 'a'
37
38#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
39
40static struct GNUNET_NAMESTORE_Handle *nsh;
41
42static struct GNUNET_SCHEDULER_Task *endbadly_task;
43
44static struct GNUNET_IDENTITY_PrivateKey privkey;
45
46static struct GNUNET_IDENTITY_PublicKey pubkey;
47
48static int res;
49
50static struct GNUNET_GNSRECORD_Data rd_orig;
51
52static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
53
54// static const char * name = "dummy.dummy.gnunet";
55static const char *name = "d";
56
57static char *record_data;
58
59static void
60cleanup ()
61{
62 GNUNET_free (record_data);
63 if (NULL != nsh)
64 {
65 GNUNET_NAMESTORE_disconnect (nsh);
66 nsh = NULL;
67 }
68 GNUNET_SCHEDULER_shutdown ();
69}
70
71
72/**
73 * Re-establish the connection to the service.
74 *
75 * @param cls handle to use to re-connect.
76 * @param tc scheduler context
77 */
78static void
79endbadly (void *cls)
80{
81 if (NULL != nsqe)
82 {
83 GNUNET_NAMESTORE_cancel (nsqe);
84 nsqe = NULL;
85 }
86 cleanup ();
87 res = 1;
88}
89
90
91static void
92end (void *cls)
93{
94 cleanup ();
95 res = 0;
96}
97
98
99static void
100lookup_it (void *cls,
101 const struct GNUNET_IDENTITY_PrivateKey *zone,
102 const char *label,
103 unsigned int rd_count,
104 const struct GNUNET_GNSRECORD_Data *rd)
105{
106 nsqe = NULL;
107 int c;
108 int found_record = GNUNET_NO;
109 int found_nick = GNUNET_NO;
110
111 if (0 != GNUNET_memcmp (&privkey, zone))
112 {
113 GNUNET_break (0);
114 GNUNET_SCHEDULER_cancel (endbadly_task);
115 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
116 return;
117 }
118
119 if (NULL == label)
120 {
121 GNUNET_break (0);
122 GNUNET_SCHEDULER_cancel (endbadly_task);
123 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
124 return;
125 }
126
127 if (0 != strcmp (label, name))
128 {
129 GNUNET_break (0);
130 GNUNET_SCHEDULER_cancel (endbadly_task);
131 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
132 return;
133 }
134
135 if (2 != rd_count)
136 {
137 GNUNET_break (0);
138 GNUNET_SCHEDULER_cancel (endbadly_task);
139 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
140 return;
141 }
142
143 for (c = 0; c < rd_count; c++)
144 {
145 if (GNUNET_GNSRECORD_TYPE_NICK == rd[c].record_type)
146 {
147 if (rd[c].data_size != strlen (TEST_NICK) + 1)
148 {
149 GNUNET_break (0);
150 GNUNET_SCHEDULER_cancel (endbadly_task);
151 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
152 return;
153 }
154 if (0 != (rd[c].flags & GNUNET_GNSRECORD_RF_PRIVATE))
155 {
156 GNUNET_break (0);
157 GNUNET_SCHEDULER_cancel (endbadly_task);
158 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
159 return;
160 }
161 if (0 != strcmp (rd[c].data, TEST_NICK))
162 {
163 GNUNET_SCHEDULER_cancel (endbadly_task);
164 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
165 return;
166 }
167 found_nick = GNUNET_YES;
168 }
169 else
170 {
171 if (rd[c].record_type != TEST_RECORD_TYPE)
172 {
173 GNUNET_break (0);
174 GNUNET_SCHEDULER_cancel (endbadly_task);
175 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
176 return;
177 }
178 if (rd[c].data_size != TEST_RECORD_DATALEN)
179 {
180 GNUNET_break (0);
181 GNUNET_SCHEDULER_cancel (endbadly_task);
182 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
183 return;
184 }
185 if (0 != memcmp (rd[c].data, rd_orig.data, TEST_RECORD_DATALEN))
186 {
187 GNUNET_break (0);
188 GNUNET_SCHEDULER_cancel (endbadly_task);
189 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
190 return;
191 }
192 if (rd[c].flags != rd->flags)
193 {
194 GNUNET_break (0);
195 GNUNET_SCHEDULER_cancel (endbadly_task);
196 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
197 return;
198 }
199 found_record = GNUNET_YES;
200 }
201 }
202
203 /* Done */
204 if ((GNUNET_YES == found_nick) && (GNUNET_YES == found_record))
205 {
206 GNUNET_SCHEDULER_cancel (endbadly_task);
207 endbadly_task = NULL;
208 GNUNET_SCHEDULER_add_now (&end, NULL);
209 }
210 else
211 {
212 GNUNET_break (0);
213 GNUNET_SCHEDULER_cancel (endbadly_task);
214 endbadly_task = NULL;
215 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
216 }
217}
218
219
220static void
221fail_cb (void *cls)
222{
223 GNUNET_assert (0);
224}
225
226
227static void
228put_cont (void *cls, int32_t success, const char *emsg)
229{
230 const char *name = cls;
231
232 nsqe = NULL;
233 GNUNET_assert (NULL != cls);
234 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
235 "Name store added record for `%s': %s\n",
236 name,
237 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
238
239 if (GNUNET_OK != success)
240 {
241 GNUNET_SCHEDULER_cancel (endbadly_task);
242 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
243 return;
244 }
245 /* Lookup */
246 nsqe = GNUNET_NAMESTORE_records_lookup (nsh,
247 &privkey,
248 name,
249 &fail_cb,
250 NULL,
251 &lookup_it,
252 NULL);
253}
254
255
256static void
257nick_cont (void *cls, int32_t success, const char *emsg)
258{
259 const char *name = cls;
260
261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262 "Nick added : %s\n",
263 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
264
265 rd_orig.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
266 rd_orig.record_type = TEST_RECORD_TYPE;
267 rd_orig.data_size = TEST_RECORD_DATALEN;
268 record_data = GNUNET_malloc (TEST_RECORD_DATALEN);
269 rd_orig.data = record_data;
270 rd_orig.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
271 memset ((char *) rd_orig.data, 'a', TEST_RECORD_DATALEN);
272
273 nsqe = GNUNET_NAMESTORE_records_store (nsh, &privkey,
274 name,
275 1,
276 &rd_orig,
277 &put_cont, (void *) name);
278}
279
280
281static void
282run (void *cls,
283 const struct GNUNET_CONFIGURATION_Handle *cfg,
284 struct GNUNET_TESTING_Peer *peer)
285{
286 struct GNUNET_GNSRECORD_Data rd;
287
288 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
289 &endbadly,
290 NULL);
291 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
292 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
293 GNUNET_IDENTITY_key_get_public (&privkey,
294 &pubkey);
295
296 nsh = GNUNET_NAMESTORE_connect (cfg);
297 GNUNET_break (NULL != nsh);
298
299 memset (&rd, 0, sizeof(rd));
300 rd.data = TEST_NICK;
301 rd.data_size = strlen (TEST_NICK) + 1;
302 rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
303 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
304 rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
305 nsqe = GNUNET_NAMESTORE_records_store (nsh,
306 &privkey,
307 GNUNET_GNS_EMPTY_LABEL_AT,
308 1,
309 &rd,
310 &nick_cont,
311 (void *) name);
312
313 if (NULL == nsqe)
314 {
315 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
316 _ ("Namestore cannot store no block\n"));
317 }
318}
319
320
321#include "test_common.c"
322
323
324int
325main (int argc, char *argv[])
326{
327 const char *plugin_name;
328 char *cfg_name;
329
330 SETUP_CFG (plugin_name, cfg_name);
331 res = 1;
332 if (0 !=
333 GNUNET_TESTING_peer_run ("test-namestore-api-lookup-nick",
334 cfg_name,
335 &run,
336 NULL))
337 {
338 res = 1;
339 }
340 GNUNET_DISK_purge_cfg_dir (cfg_name,
341 "GNUNET_TEST_HOME");
342 GNUNET_free (cfg_name);
343 return res;
344}
345
346
347/* end of test_namestore_api_store.c */
diff --git a/src/namestore/test_namestore_api_lookup_private.c b/src/namestore/test_namestore_api_lookup_private.c
deleted file mode 100644
index 67cf54582..000000000
--- a/src/namestore/test_namestore_api_lookup_private.c
+++ /dev/null
@@ -1,246 +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 namestore/test_namestore_api_store.c
22 * @brief testcase for namestore_api.c: store a record
23 */
24#include "platform.h"
25#include "gnunet_namestore_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, 5)
36
37static struct GNUNET_NAMESTORE_Handle *nsh;
38
39static struct GNUNET_SCHEDULER_Task *endbadly_task;
40
41static struct GNUNET_IDENTITY_PrivateKey privkey;
42
43static struct GNUNET_IDENTITY_PublicKey pubkey;
44
45static int res;
46
47static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
48
49// static const char * name = "dummy.dummy.gnunet";
50static const char *name = "d";
51
52
53static void
54cleanup ()
55{
56 if (NULL != nsh)
57 {
58 GNUNET_NAMESTORE_disconnect (nsh);
59 nsh = NULL;
60 }
61 GNUNET_SCHEDULER_shutdown ();
62}
63
64
65/**
66 * Re-establish the connection to the service.
67 *
68 * @param cls handle to use to re-connect.
69 */
70static void
71endbadly (void *cls)
72{
73 endbadly_task = NULL;
74 if (NULL != nsqe)
75 {
76 GNUNET_NAMESTORE_cancel (nsqe);
77 nsqe = NULL;
78 }
79 cleanup ();
80 res = 1;
81}
82
83
84static void
85end (void *cls)
86{
87 cleanup ();
88 res = 0;
89}
90
91
92static void
93lookup_it (void *cls,
94 const struct GNUNET_IDENTITY_PrivateKey *zone,
95 const char *label,
96 unsigned int rd_count,
97 const struct GNUNET_GNSRECORD_Data *rd)
98{
99 nsqe = NULL;
100
101 if (0 != GNUNET_memcmp (&privkey,
102 zone))
103 {
104 GNUNET_break (0);
105 GNUNET_SCHEDULER_cancel (endbadly_task);
106 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
107 return;
108 }
109
110
111 if (NULL == label)
112 {
113 GNUNET_break (0);
114 GNUNET_SCHEDULER_cancel (endbadly_task);
115 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
116 return;
117 }
118
119 if (0 != strcmp (label, name))
120 {
121 GNUNET_break (0);
122 GNUNET_SCHEDULER_cancel (endbadly_task);
123 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
124 return;
125 }
126
127 if (1 != rd_count)
128 {
129 GNUNET_break (0);
130 GNUNET_SCHEDULER_cancel (endbadly_task);
131 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
132 return;
133 }
134
135 /* Done */
136 GNUNET_SCHEDULER_cancel (endbadly_task);
137 endbadly_task = NULL;
138 GNUNET_SCHEDULER_add_now (&end, NULL);
139}
140
141
142static void
143fail_cb (void *cls)
144{
145 GNUNET_assert (0);
146}
147
148
149static void
150put_cont (void *cls,
151 int32_t success,
152 const char *emsg)
153{
154 const char *name = cls;
155
156 nsqe = NULL;
157 GNUNET_assert (NULL != cls);
158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
159 "Name store added record for `%s': %s\n",
160 name,
161 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
162
163 if (GNUNET_OK != success)
164 {
165 GNUNET_SCHEDULER_cancel (endbadly_task);
166 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
167 return;
168 }
169 /* Lookup */
170 nsqe = GNUNET_NAMESTORE_records_lookup (nsh,
171 &privkey,
172 name,
173 &fail_cb,
174 NULL,
175 &lookup_it,
176 NULL);
177}
178
179
180static void
181run (void *cls,
182 const struct GNUNET_CONFIGURATION_Handle *cfg,
183 struct GNUNET_TESTING_Peer *peer)
184{
185 struct GNUNET_GNSRECORD_Data rd;
186
187 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
188 &endbadly,
189 NULL);
190 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
191 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
192 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
193
194 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
195 rd.record_type = TEST_RECORD_TYPE;
196 rd.data_size = TEST_RECORD_DATALEN;
197 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
198 rd.flags = 0;
199 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
200
201 nsh = GNUNET_NAMESTORE_connect (cfg);
202 GNUNET_break (NULL != nsh);
203 nsqe = GNUNET_NAMESTORE_records_store (nsh,
204 &privkey,
205 name,
206 1,
207 &rd,
208 &put_cont,
209 (void *) name);
210 if (NULL == nsqe)
211 {
212 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
213 _ ("Namestore cannot store no block\n"));
214 }
215
216 GNUNET_free_nz ((void *) rd.data);
217}
218
219
220#include "test_common.c"
221
222
223int
224main (int argc, char *argv[])
225{
226 const char *plugin_name;
227 char *cfg_name;
228
229 SETUP_CFG (plugin_name, cfg_name);
230 res = 1;
231 if (0 !=
232 GNUNET_TESTING_peer_run ("test-namestore-api-lookup-private",
233 cfg_name,
234 &run,
235 NULL))
236 {
237 res = 1;
238 }
239 GNUNET_DISK_purge_cfg_dir (cfg_name,
240 "GNUNET_TEST_HOME");
241 GNUNET_free (cfg_name);
242 return res;
243}
244
245
246/* end of test_namestore_api_lookup_private.c */
diff --git a/src/namestore/test_namestore_api_lookup_public.c b/src/namestore/test_namestore_api_lookup_public.c
deleted file mode 100644
index cd69b96ef..000000000
--- a/src/namestore/test_namestore_api_lookup_public.c
+++ /dev/null
@@ -1,255 +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 namestore/test_namestore_api.c
22 * @brief testcase for namestore_api.c: store a record and perform a lookup
23 */
24#include "platform.h"
25#include "gnunet_namecache_service.h"
26#include "gnunet_namestore_service.h"
27#include "gnunet_testing_lib.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32#define TEST_RECORD_DATALEN 123
33
34#define TEST_RECORD_DATA 'a'
35
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
37
38
39static struct GNUNET_NAMESTORE_Handle *nsh;
40
41static struct GNUNET_NAMECACHE_Handle *nch;
42
43static struct GNUNET_SCHEDULER_Task *endbadly_task;
44
45static struct GNUNET_IDENTITY_PrivateKey privkey;
46
47static struct GNUNET_IDENTITY_PublicKey pubkey;
48
49static int res;
50
51static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
52
53static struct GNUNET_NAMECACHE_QueueEntry *ncqe;
54
55
56static void
57cleanup ()
58{
59 if (NULL != nsh)
60 {
61 GNUNET_NAMESTORE_disconnect (nsh);
62 nsh = NULL;
63 }
64 if (NULL != nch)
65 {
66 GNUNET_NAMECACHE_disconnect (nch);
67 nch = NULL;
68 }
69 GNUNET_SCHEDULER_shutdown ();
70}
71
72
73/**
74 * Re-establish the connection to the service.
75 *
76 * @param cls handle to use to re-connect.
77 */
78static void
79endbadly (void *cls)
80{
81 if (NULL != nsqe)
82 {
83 GNUNET_NAMESTORE_cancel (nsqe);
84 nsqe = NULL;
85 }
86 if (NULL != ncqe)
87 {
88 GNUNET_NAMECACHE_cancel (ncqe);
89 ncqe = NULL;
90 }
91 cleanup ();
92 res = 1;
93}
94
95
96static void
97end (void *cls)
98{
99 cleanup ();
100 res = 0;
101}
102
103
104static void
105rd_decrypt_cb (void *cls,
106 unsigned int rd_count,
107 const struct GNUNET_GNSRECORD_Data *rd)
108{
109 char rd_cmp_data[TEST_RECORD_DATALEN];
110
111 GNUNET_assert (1 == rd_count);
112 GNUNET_assert (NULL != rd);
113
114 memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN);
115
116 GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type);
117 GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size);
118 GNUNET_assert (0 == memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN));
119
120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
121 "Block was decrypted successfully \n");
122
123 GNUNET_SCHEDULER_add_now (&end, NULL);
124}
125
126
127static void
128name_lookup_proc (void *cls,
129 const struct GNUNET_GNSRECORD_Block *block)
130{
131 const char *name = cls;
132
133 ncqe = NULL;
134 GNUNET_assert (NULL != cls);
135
136 if (endbadly_task != NULL)
137 {
138 GNUNET_SCHEDULER_cancel (endbadly_task);
139 endbadly_task = NULL;
140 }
141
142 if (NULL == block)
143 {
144 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
145 _ ("Namestore returned no block\n"));
146 if (endbadly_task != NULL)
147 GNUNET_SCHEDULER_cancel (endbadly_task);
148 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
149 return;
150 }
151
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153 "Namestore returned block, decrypting \n");
154 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block,
155 &pubkey, name,
156 &rd_decrypt_cb,
157 (void *) name));
158}
159
160
161static void
162put_cont (void *cls, int32_t success, const char *emsg)
163{
164 const char *name = cls;
165 struct GNUNET_HashCode derived_hash;
166 struct GNUNET_IDENTITY_PublicKey pubkey;
167
168 nsqe = NULL;
169 GNUNET_assert (NULL != cls);
170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
171 "Name store added record for `%s': %s\n",
172 name,
173 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
174
175 /* Create derived hash */
176 GNUNET_IDENTITY_key_get_public (&privkey,
177 &pubkey);
178 GNUNET_GNSRECORD_query_from_public_key (&pubkey, name, &derived_hash);
179
180 ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash,
181 &name_lookup_proc, (void *) name);
182}
183
184
185static void
186run (void *cls,
187 const struct GNUNET_CONFIGURATION_Handle *cfg,
188 struct GNUNET_TESTING_Peer *peer)
189{
190 struct GNUNET_GNSRECORD_Data rd;
191 const char *name = "dummy";
192
193 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
194 &endbadly,
195 NULL);
196 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
197 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
198 GNUNET_IDENTITY_key_get_public (&privkey,
199 &pubkey);
200
201 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000;
202 rd.record_type = TEST_RECORD_TYPE;
203 rd.data_size = TEST_RECORD_DATALEN;
204 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
205 rd.flags = 0;
206 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
207
208 nsh = GNUNET_NAMESTORE_connect (cfg);
209 nch = GNUNET_NAMECACHE_connect (cfg);
210 GNUNET_break (NULL != nsh);
211 GNUNET_break (NULL != nch);
212 nsqe = GNUNET_NAMESTORE_records_store (nsh,
213 &privkey,
214 name,
215 1,
216 &rd,
217 &put_cont,
218 (void *) name);
219 if (NULL == nsqe)
220 {
221 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
222 _ ("Namestore cannot store no block\n"));
223 }
224
225 GNUNET_free_nz ((void *) rd.data);
226}
227
228
229#include "test_common.c"
230
231
232int
233main (int argc, char *argv[])
234{
235 const char *plugin_name;
236 char *cfg_name;
237
238 SETUP_CFG (plugin_name, cfg_name);
239 res = 1;
240 if (0 !=
241 GNUNET_TESTING_peer_run ("test-namestore-api",
242 cfg_name,
243 &run,
244 NULL))
245 {
246 res = 1;
247 }
248 GNUNET_DISK_purge_cfg_dir (cfg_name,
249 "GNUNET_TEST_HOME");
250 GNUNET_free (cfg_name);
251 return res;
252}
253
254
255/* end of test_namestore_api_lookup_public.c */
diff --git a/src/namestore/test_namestore_api_lookup_shadow.c b/src/namestore/test_namestore_api_lookup_shadow.c
deleted file mode 100644
index 8f47d1280..000000000
--- a/src/namestore/test_namestore_api_lookup_shadow.c
+++ /dev/null
@@ -1,288 +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 namestore/test_namestore_api_lookup_shadow.c
22 * @brief testcase for namestore_api.c: store a shadow record and perform a lookup
23 * test passes if test returns the record but without the shadow flag since no
24 * other valid record is available
25 */
26#include "platform.h"
27#include "gnunet_namecache_service.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_dnsparser_lib.h"
31
32#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
33
34#define TEST_RECORD_DATALEN 123
35
36#define TEST_RECORD_DATA 'a'
37
38#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
39
40
41static struct GNUNET_NAMESTORE_Handle *nsh;
42
43static struct GNUNET_NAMECACHE_Handle *nch;
44
45static struct GNUNET_SCHEDULER_Task *endbadly_task;
46
47static struct GNUNET_IDENTITY_PrivateKey privkey;
48
49static struct GNUNET_IDENTITY_PublicKey pubkey;
50
51static int res;
52
53static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
54
55static struct GNUNET_NAMECACHE_QueueEntry *ncqe;
56
57
58static void
59cleanup ()
60{
61 if (NULL != nsh)
62 {
63 GNUNET_NAMESTORE_disconnect (nsh);
64 nsh = NULL;
65 }
66 if (NULL != nch)
67 {
68 GNUNET_NAMECACHE_disconnect (nch);
69 nch = NULL;
70 }
71 GNUNET_SCHEDULER_shutdown ();
72}
73
74
75/**
76 * Re-establish the connection to the service.
77 *
78 * @param cls handle to use to re-connect.
79 */
80static void
81endbadly (void *cls)
82{
83 if (NULL != nsqe)
84 {
85 GNUNET_NAMESTORE_cancel (nsqe);
86 nsqe = NULL;
87 }
88 if (NULL != ncqe)
89 {
90 GNUNET_NAMECACHE_cancel (ncqe);
91 ncqe = NULL;
92 }
93 cleanup ();
94 res = 1;
95}
96
97
98static void
99end (void *cls)
100{
101 cleanup ();
102 res = 0;
103}
104
105
106static void
107rd_decrypt_cb (void *cls,
108 unsigned int rd_count,
109 const struct GNUNET_GNSRECORD_Data *rd)
110{
111 char rd_cmp_data[TEST_RECORD_DATALEN];
112
113 if (1 != rd_count)
114 {
115 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
116 GNUNET_break (0);
117 return;
118 }
119 if (NULL == rd)
120 {
121 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
122 GNUNET_break (0);
123 return;
124 }
125 memset (rd_cmp_data, 'a', TEST_RECORD_DATALEN);
126
127 if (TEST_RECORD_TYPE != rd[0].record_type)
128 {
129 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
130 GNUNET_break (0);
131 return;
132 }
133 if (TEST_RECORD_DATALEN != rd[0].data_size)
134 {
135 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
136 GNUNET_break (0);
137 return;
138 }
139 if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN))
140 {
141 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
142 GNUNET_break (0);
143 return;
144 }
145 if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags))
146 {
147 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
148 GNUNET_break (0);
149 return;
150 }
151
152 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
153 "Block was decrypted successfully \n");
154
155 GNUNET_SCHEDULER_add_now (&end, NULL);
156}
157
158
159static void
160name_lookup_proc (void *cls,
161 const struct GNUNET_GNSRECORD_Block *block)
162{
163 const char *name = cls;
164
165 ncqe = NULL;
166 GNUNET_assert (NULL != cls);
167
168 if (endbadly_task != NULL)
169 {
170 GNUNET_SCHEDULER_cancel (endbadly_task);
171 endbadly_task = NULL;
172 }
173
174 if (NULL == block)
175 {
176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
177 _ ("Namestore returned no block\n"));
178 if (endbadly_task != NULL)
179 GNUNET_SCHEDULER_cancel (endbadly_task);
180 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
181 return;
182 }
183
184 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
185 "Namestore returned block, decrypting \n");
186 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block,
187 &pubkey, name,
188 &rd_decrypt_cb,
189 (void *) name));
190}
191
192
193static void
194put_cont (void *cls, int32_t success, const char *emsg)
195{
196 const char *name = cls;
197 struct GNUNET_HashCode derived_hash;
198 struct GNUNET_IDENTITY_PublicKey pubkey;
199
200 nsqe = NULL;
201 GNUNET_assert (NULL != cls);
202 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
203 "Name store added record for `%s': %s\n",
204 name,
205 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
206
207 /* Create derived hash */
208 GNUNET_IDENTITY_key_get_public (&privkey,
209 &pubkey);
210 GNUNET_GNSRECORD_query_from_public_key (&pubkey,
211 name,
212 &derived_hash);
213
214 ncqe = GNUNET_NAMECACHE_lookup_block (nch,
215 &derived_hash,
216 &name_lookup_proc, (void *) name);
217}
218
219
220static void
221run (void *cls,
222 const struct GNUNET_CONFIGURATION_Handle *cfg,
223 struct GNUNET_TESTING_Peer *peer)
224{
225 struct GNUNET_GNSRECORD_Data rd;
226 const char *name = "dummy";
227
228 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
229 &endbadly,
230 NULL);
231 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
232 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
233 GNUNET_IDENTITY_key_get_public (&privkey,
234 &pubkey);
235 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000;
236 rd.record_type = TEST_RECORD_TYPE;
237 rd.data_size = TEST_RECORD_DATALEN;
238 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
239 rd.flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD;
240 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
241
242 nsh = GNUNET_NAMESTORE_connect (cfg);
243 nch = GNUNET_NAMECACHE_connect (cfg);
244 GNUNET_break (NULL != nsh);
245 GNUNET_break (NULL != nch);
246 nsqe = GNUNET_NAMESTORE_records_store (nsh,
247 &privkey,
248 name,
249 1,
250 &rd,
251 &put_cont,
252 (void *) name);
253 if (NULL == nsqe)
254 {
255 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
256 _ ("Namestore cannot store no block\n"));
257 }
258 GNUNET_free_nz ((void *) rd.data);
259}
260
261
262#include "test_common.c"
263
264
265int
266main (int argc, char *argv[])
267{
268 const char *plugin_name;
269 char *cfg_name;
270
271 SETUP_CFG (plugin_name, cfg_name);
272 res = 1;
273 if (0 !=
274 GNUNET_TESTING_peer_run ("test-namestore-api-lookup-shadow",
275 cfg_name,
276 &run,
277 NULL))
278 {
279 res = 1;
280 }
281 GNUNET_DISK_purge_cfg_dir (cfg_name,
282 "GNUNET_TEST_HOME");
283 GNUNET_free (cfg_name);
284 return res;
285}
286
287
288/* end of test_namestore_api_lookup_shadow.c */
diff --git a/src/namestore/test_namestore_api_lookup_shadow_filter.c b/src/namestore/test_namestore_api_lookup_shadow_filter.c
deleted file mode 100644
index 0bcd130f9..000000000
--- a/src/namestore/test_namestore_api_lookup_shadow_filter.c
+++ /dev/null
@@ -1,371 +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 namestore/test_namestore_api_lookup_shadow_filter.c
22 * @brief testcase for namestore_api.c: store a record with short expiration
23 * and a shadow record, perform lookup:
24 * - when active record is valid, expect only active record
25 * - when active record is expired, expect shadow record only
26 */
27#include "platform.h"
28#include "gnunet_namecache_service.h"
29#include "gnunet_namestore_service.h"
30#include "gnunet_testing_lib.h"
31#include "gnunet_dnsparser_lib.h"
32
33#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
34
35#define TEST_NAME "gnunet"
36#define TEST_RECORD_DATALEN 123
37#define TEST_RECORD_DATA 'a'
38#define TEST_SHADOW_RECORD_DATA 'b'
39
40#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
41#define EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5)
42
43static struct GNUNET_NAMESTORE_Handle *nsh;
44
45static struct GNUNET_NAMECACHE_Handle *nch;
46
47static struct GNUNET_SCHEDULER_Task *endbadly_task;
48
49static struct GNUNET_SCHEDULER_Task *delayed_lookup_task;
50
51static struct GNUNET_IDENTITY_PrivateKey privkey;
52
53static struct GNUNET_IDENTITY_PublicKey pubkey;
54
55static int res;
56
57static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
58
59static struct GNUNET_NAMECACHE_QueueEntry *ncqe;
60
61static struct GNUNET_NAMECACHE_QueueEntry *ncqe_shadow;
62
63static struct GNUNET_GNSRECORD_Data records[2];
64
65static struct GNUNET_TIME_Absolute record_expiration;
66
67static struct GNUNET_HashCode derived_hash;
68
69static struct GNUNET_IDENTITY_PublicKey pubkey;
70
71
72static void
73cleanup ()
74{
75 if (NULL != nsh)
76 {
77 GNUNET_NAMESTORE_disconnect (nsh);
78 nsh = NULL;
79 }
80 if (NULL != nch)
81 {
82 GNUNET_NAMECACHE_disconnect (nch);
83 nch = NULL;
84 }
85 GNUNET_SCHEDULER_shutdown ();
86}
87
88
89/**
90 * Re-establish the connection to the service.
91 *
92 * @param cls handle to use to re-connect.
93 */
94static void
95endbadly (void *cls)
96{
97 if (NULL != delayed_lookup_task)
98 {
99 GNUNET_SCHEDULER_cancel (delayed_lookup_task);
100 delayed_lookup_task = NULL;
101 }
102 if (NULL != nsqe)
103 {
104 GNUNET_NAMESTORE_cancel (nsqe);
105 nsqe = NULL;
106 }
107 if (NULL != ncqe)
108 {
109 GNUNET_NAMECACHE_cancel (ncqe);
110 ncqe = NULL;
111 }
112 cleanup ();
113 res = 1;
114}
115
116
117static void
118end (void *cls)
119{
120 cleanup ();
121 res = 0;
122}
123
124
125static void
126rd_decrypt_cb (void *cls,
127 unsigned int rd_count,
128 const struct GNUNET_GNSRECORD_Data *rd)
129{
130 struct GNUNET_GNSRECORD_Data *expected_rd = cls;
131 char rd_cmp_data[TEST_RECORD_DATALEN];
132
133 if (1 != rd_count)
134 {
135 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
136 GNUNET_break (0);
137 return;
138 }
139 if (NULL == rd)
140 {
141 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
142 GNUNET_break (0);
143 return;
144 }
145 if (expected_rd == &records[0])
146 {
147 /* Expecting active record */
148 memset (rd_cmp_data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
149 if (TEST_RECORD_TYPE != rd[0].record_type)
150 {
151 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
152 GNUNET_break (0);
153 return;
154 }
155 if (TEST_RECORD_DATALEN != rd[0].data_size)
156 {
157 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
158 GNUNET_break (0);
159 return;
160 }
161 if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN))
162 {
163 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
164 GNUNET_break (0);
165 return;
166 }
167 if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags))
168 {
169 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
170 GNUNET_break (0);
171 return;
172 }
173 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
174 "Block was decrypted successfully with active record\n");
175 }
176 if (expected_rd == &records[1])
177 {
178 /* Expecting shadow record but without shadow flag*/
179 memset (rd_cmp_data, TEST_SHADOW_RECORD_DATA, TEST_RECORD_DATALEN);
180 if (TEST_RECORD_TYPE != rd[0].record_type)
181 {
182 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
183 GNUNET_break (0);
184 return;
185 }
186 if (TEST_RECORD_DATALEN != rd[0].data_size)
187 {
188 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
189 GNUNET_break (0);
190 return;
191 }
192 if (0 != memcmp (&rd_cmp_data, rd[0].data, TEST_RECORD_DATALEN))
193 {
194 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
195 GNUNET_break (0);
196 return;
197 }
198 if (0 != (GNUNET_GNSRECORD_RF_SHADOW_RECORD & rd[0].flags))
199 {
200 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
201 GNUNET_break (0);
202 return;
203 }
204 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
205 "Block was decrypted successfully with former shadow record \n");
206 GNUNET_SCHEDULER_add_now (&end, NULL);
207 }
208}
209
210
211static void
212name_lookup_active_proc (void *cls,
213 const struct GNUNET_GNSRECORD_Block *block)
214{
215 struct GNUNET_GNSRECORD_Data *expected_rd = cls;
216
217 GNUNET_assert (NULL != expected_rd);
218
219 ncqe = NULL;
220 ncqe_shadow = NULL;
221 if (endbadly_task != NULL)
222 {
223 GNUNET_SCHEDULER_cancel (endbadly_task);
224 endbadly_task = NULL;
225 }
226
227 if (NULL == block)
228 {
229 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
230 _ ("Namestore returned no block\n"));
231 if (endbadly_task != NULL)
232 GNUNET_SCHEDULER_cancel (endbadly_task);
233 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
234 return;
235 }
236
237 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
238 "Namestore returned block, decrypting \n");
239 GNUNET_assert (GNUNET_OK == GNUNET_GNSRECORD_block_decrypt (block,
240 &pubkey,
241 TEST_NAME,
242 &rd_decrypt_cb,
243 expected_rd));
244}
245
246
247static void
248name_lookup_shadow (void *cls)
249{
250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
251 "Performing lookup for shadow record \n");
252 delayed_lookup_task = NULL;
253 ncqe_shadow = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash,
254 &name_lookup_active_proc,
255 &records[1]);
256}
257
258
259static void
260put_cont (void *cls, int32_t success, const char *emsg)
261{
262 nsqe = NULL;
263
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "Name store added record for `%s': %s\n",
266 TEST_NAME,
267 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
268
269 /* Create derived hash */
270 GNUNET_IDENTITY_key_get_public (&privkey,
271 &pubkey);
272 GNUNET_GNSRECORD_query_from_public_key (&pubkey, TEST_NAME, &derived_hash);
273
274 if (0 == GNUNET_TIME_absolute_get_remaining (record_expiration).rel_value_us)
275 {
276 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
277 "Test to too long to store records, cannot run test!\n");
278 GNUNET_SCHEDULER_add_now (&end, NULL);
279 return;
280 }
281 /* Lookup active record now */
282 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
283 "Performing lookup for active record \n");
284 ncqe = GNUNET_NAMECACHE_lookup_block (nch, &derived_hash,
285 &name_lookup_active_proc, &records[0]);
286
287 delayed_lookup_task = GNUNET_SCHEDULER_add_delayed (
288 GNUNET_TIME_relative_multiply (EXPIRATION, 2), &name_lookup_shadow, NULL);
289}
290
291
292static void
293run (void *cls,
294 const struct GNUNET_CONFIGURATION_Handle *cfg,
295 struct GNUNET_TESTING_Peer *peer)
296{
297 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
298 &endbadly,
299 NULL);
300 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
301 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
302 GNUNET_IDENTITY_key_get_public (&privkey,
303 &pubkey);
304
305 record_expiration = GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
306 EXPIRATION);
307 records[0].expiration_time = record_expiration.abs_value_us;
308 records[0].record_type = TEST_RECORD_TYPE;
309 records[0].data_size = TEST_RECORD_DATALEN;
310 records[0].data = GNUNET_malloc (TEST_RECORD_DATALEN);
311 records[0].flags = GNUNET_GNSRECORD_RF_NONE;
312 memset ((char *) records[0].data, TEST_RECORD_DATA, TEST_RECORD_DATALEN);
313
314 records[1].expiration_time = GNUNET_TIME_absolute_get ().abs_value_us
315 + 1000000000;
316 records[1].record_type = TEST_RECORD_TYPE;
317 records[1].data_size = TEST_RECORD_DATALEN;
318 records[1].data = GNUNET_malloc (TEST_RECORD_DATALEN);
319 records[1].flags = GNUNET_GNSRECORD_RF_SHADOW_RECORD;
320 memset ((char *) records[1].data, TEST_SHADOW_RECORD_DATA,
321 TEST_RECORD_DATALEN);
322
323 nsh = GNUNET_NAMESTORE_connect (cfg);
324 nch = GNUNET_NAMECACHE_connect (cfg);
325 GNUNET_break (NULL != nsh);
326 GNUNET_break (NULL != nch);
327 nsqe = GNUNET_NAMESTORE_records_store (nsh,
328 &privkey,
329 TEST_NAME,
330 2,
331 records,
332 &put_cont,
333 NULL);
334 if (NULL == nsqe)
335 {
336 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
337 _ ("Namestore cannot store no block\n"));
338 }
339
340 GNUNET_free_nz ((void *) records[0].data);
341 GNUNET_free_nz ((void *) records[1].data);
342}
343
344
345#include "test_common.c"
346
347
348int
349main (int argc, char *argv[])
350{
351 const char *plugin_name;
352 char *cfg_name;
353
354 SETUP_CFG (plugin_name, cfg_name);
355 res = 1;
356 if (0 !=
357 GNUNET_TESTING_peer_run ("test-namestore-api-lookup-shadow-filter",
358 cfg_name,
359 &run,
360 NULL))
361 {
362 res = 1;
363 }
364 GNUNET_DISK_purge_cfg_dir (cfg_name,
365 "GNUNET_TEST_HOME");
366 GNUNET_free (cfg_name);
367 return res;
368}
369
370
371/* end of test_namestore_api_lookup_shadow_filter.c */
diff --git a/src/namestore/test_namestore_api_monitoring.c b/src/namestore/test_namestore_api_monitoring.c
deleted file mode 100644
index df0c38608..000000000
--- a/src/namestore/test_namestore_api_monitoring.c
+++ /dev/null
@@ -1,379 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018 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 namestore/test_namestore_api_monitoring.c
22 * @brief testcase for zone monitoring functionality: monitor first, then add records
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "namestore.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32
33#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
34
35
36static struct GNUNET_NAMESTORE_Handle *nsh;
37
38static struct GNUNET_SCHEDULER_Task *endbadly_task;
39
40static struct GNUNET_IDENTITY_PrivateKey privkey;
41
42static struct GNUNET_IDENTITY_PrivateKey privkey2;
43
44static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
45
46static int res;
47
48static char *s_name_1;
49
50static struct GNUNET_GNSRECORD_Data *s_rd_1;
51
52static char *s_name_2;
53
54static struct GNUNET_GNSRECORD_Data *s_rd_2;
55
56static char *s_name_3;
57
58static struct GNUNET_GNSRECORD_Data *s_rd_3;
59
60struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3];
61
62
63static void
64do_shutdown ()
65{
66 if (NULL != zm)
67 {
68 GNUNET_NAMESTORE_zone_monitor_stop (zm);
69 zm = NULL;
70 }
71 if (NULL != ns_ops[0])
72 {
73 GNUNET_NAMESTORE_cancel (ns_ops[0]);
74 ns_ops[0] = NULL;
75 }
76 if (NULL != ns_ops[1])
77 {
78 GNUNET_NAMESTORE_cancel (ns_ops[1]);
79 ns_ops[1] = NULL;
80 }
81 if (NULL != ns_ops[2])
82 {
83 GNUNET_NAMESTORE_cancel (ns_ops[2]);
84 ns_ops[2] = NULL;
85 }
86 if (NULL != nsh)
87 {
88 GNUNET_NAMESTORE_disconnect (nsh);
89 nsh = NULL;
90 }
91 GNUNET_free (s_name_1);
92 GNUNET_free (s_name_2);
93 GNUNET_free (s_name_3);
94
95 if (s_rd_1 != NULL)
96 {
97 GNUNET_free_nz ((void *) s_rd_1->data);
98 GNUNET_free (s_rd_1);
99 }
100 if (s_rd_2 != NULL)
101 {
102 GNUNET_free_nz ((void *) s_rd_2->data);
103 GNUNET_free (s_rd_2);
104 }
105 if (s_rd_3 != NULL)
106 {
107 GNUNET_free_nz ((void *) s_rd_3->data);
108 GNUNET_free (s_rd_3);
109 }
110}
111
112
113/**
114 * Re-establish the connection to the service.
115 *
116 * @param cls handle to use to re-connect.
117 */
118static void
119endbadly (void *cls)
120{
121 do_shutdown ();
122 res = 1;
123}
124
125
126static void
127end (void *cls)
128{
129 do_shutdown ();
130 res = 0;
131}
132
133
134static void
135zone_proc (void *cls,
136 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
137 const char *name,
138 unsigned int rd_count,
139 const struct GNUNET_GNSRECORD_Data *rd)
140{
141 static int returned_records;
142 static int fail = GNUNET_NO;
143
144 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
145 "Comparing results name %s\n",
146 name);
147 if (0 != GNUNET_memcmp (zone_key,
148 &privkey))
149 {
150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
151 "Monitoring returned wrong zone key\n");
152 GNUNET_break (0);
153 GNUNET_SCHEDULER_cancel (endbadly_task);
154 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
155 return;
156 }
157
158 if (0 == strcmp (name, s_name_1))
159 {
160 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
161 {
162 GNUNET_break (0);
163 fail = GNUNET_YES;
164 }
165 }
166 else if (0 == strcmp (name, s_name_2))
167 {
168 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
169 {
170 GNUNET_break (0);
171 fail = GNUNET_YES;
172 }
173 }
174 else
175 {
176 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
177 "Invalid name %s\n",
178 name);
179 GNUNET_break (0);
180 fail = GNUNET_YES;
181 }
182 GNUNET_NAMESTORE_zone_monitor_next (zm,
183 1);
184 if (2 == ++returned_records)
185 {
186 if (endbadly_task != NULL)
187 {
188 GNUNET_SCHEDULER_cancel (endbadly_task);
189 endbadly_task = NULL;
190 }
191 if (GNUNET_YES == fail)
192 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
193 else
194 GNUNET_SCHEDULER_add_now (&end, NULL);
195 }
196}
197
198
199static void
200put_cont (void *cls,
201 int32_t success,
202 const char *emsg)
203{
204 static int c = 0;
205 char *label = cls;
206
207 if (0 == strcmp (label, s_name_1))
208 ns_ops[0] = NULL;
209 else if (0 == strcmp (label, s_name_2))
210 ns_ops[1] = NULL;
211 else if (0 == strcmp (label, s_name_3))
212 ns_ops[2] = NULL;
213
214 if (success == GNUNET_OK)
215 {
216 c++;
217 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
218 "Created record %u: `%s'\n",
219 c,
220 label);
221 }
222 else
223 {
224 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
225 "Failed to create record `%s'\n",
226 label);
227 GNUNET_break (0);
228 GNUNET_SCHEDULER_cancel (endbadly_task);
229 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
230 NULL);
231 }
232}
233
234
235static struct GNUNET_GNSRECORD_Data *
236create_record (unsigned int count)
237{
238 struct GNUNET_GNSRECORD_Data *rd;
239
240 rd = GNUNET_new_array (count,
241 struct GNUNET_GNSRECORD_Data);
242 for (unsigned int c = 0; c < count; c++)
243 {
244 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
245 GNUNET_TIME_UNIT_HOURS).abs_value_us;
246 rd[c].record_type = TEST_RECORD_TYPE;
247 rd[c].data_size = 50;
248 rd[c].data = GNUNET_malloc (50);
249 rd[c].flags = 0;
250 memset ((char *) rd[c].data, 'a', 50);
251 }
252 return rd;
253}
254
255
256static void
257fail_cb (void *cls)
258{
259 GNUNET_assert (0);
260}
261
262
263static void
264sync_cb (void *cls)
265{
266 /* do nothing */
267}
268
269
270static void
271run (void *cls,
272 const struct GNUNET_CONFIGURATION_Handle *cfg,
273 struct GNUNET_TESTING_Peer *peer)
274{
275 res = 1;
276 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
277 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
278 /* Start monitoring */
279 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
280 &privkey,
281 GNUNET_YES,
282 &fail_cb,
283 NULL,
284 &zone_proc,
285 NULL,
286 &sync_cb,
287 NULL);
288 if (NULL == zm)
289 {
290 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
291 "Failed to create zone monitor\n");
292 GNUNET_break (0);
293 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
294 return;
295 }
296
297 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &endbadly, NULL);
298 /* Connect to namestore */
299 nsh = GNUNET_NAMESTORE_connect (cfg);
300 if (NULL == nsh)
301 {
302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Connect to namestore\n");
303 GNUNET_break (0);
304 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly, NULL);
305 return;
306 }
307
308 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
309 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
310
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
312 "Created record 3\n");
313 /* name in different zone */
314 GNUNET_asprintf (&s_name_3, "dummy3");
315 s_rd_3 = create_record (1);
316 GNUNET_assert (NULL != (ns_ops[2] =
317 GNUNET_NAMESTORE_records_store (nsh,
318 &privkey2,
319 s_name_3,
320 1,
321 s_rd_3,
322 &put_cont,
323 s_name_3)));
324 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
325 "Created record 1\n");
326 GNUNET_asprintf (&s_name_1, "dummy1");
327 s_rd_1 = create_record (1);
328 GNUNET_assert (NULL != (ns_ops[0] =
329 GNUNET_NAMESTORE_records_store (nsh,
330 &privkey,
331 s_name_1,
332 1,
333 s_rd_1,
334 &put_cont,
335 s_name_1)));
336
337
338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 2 \n");
339 GNUNET_asprintf (&s_name_2, "dummy2");
340 s_rd_2 = create_record (1);
341 GNUNET_assert (NULL != (ns_ops[1] =
342 GNUNET_NAMESTORE_records_store (nsh,
343 &privkey,
344 s_name_2,
345 1,
346 s_rd_2,
347 &put_cont,
348 s_name_2)));
349}
350
351
352#include "test_common.c"
353
354
355int
356main (int argc,
357 char *argv[])
358{
359 const char *plugin_name;
360 char *cfg_name;
361
362 SETUP_CFG (plugin_name, cfg_name);
363 res = 1;
364 if (0 !=
365 GNUNET_TESTING_peer_run ("test-namestore-api-monitoring",
366 cfg_name,
367 &run,
368 NULL))
369 {
370 res = 1;
371 }
372 GNUNET_DISK_purge_cfg_dir (cfg_name,
373 "GNUNET_TEST_HOME");
374 GNUNET_free (cfg_name);
375 return res;
376}
377
378
379/* end of test_namestore_api_monitoring.c */
diff --git a/src/namestore/test_namestore_api_monitoring_existing.c b/src/namestore/test_namestore_api_monitoring_existing.c
deleted file mode 100644
index 366f5739f..000000000
--- a/src/namestore/test_namestore_api_monitoring_existing.c
+++ /dev/null
@@ -1,397 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018 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 namestore/test_namestore_api_monitoring_existing.c
22 * @brief testcase for zone monitoring functionality: add records first, then monitor
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "namestore.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32
33#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10)
34
35static const struct GNUNET_CONFIGURATION_Handle *cfg;
36
37static struct GNUNET_NAMESTORE_Handle *nsh;
38
39static struct GNUNET_SCHEDULER_Task *endbadly_task;
40
41static struct GNUNET_IDENTITY_PrivateKey privkey;
42
43static struct GNUNET_IDENTITY_PrivateKey privkey2;
44
45static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
46
47static int res;
48
49static const char *s_name_1;
50
51static struct GNUNET_GNSRECORD_Data *s_rd_1;
52
53static const char *s_name_2;
54
55static struct GNUNET_GNSRECORD_Data *s_rd_2;
56
57static const char *s_name_3;
58
59static struct GNUNET_GNSRECORD_Data *s_rd_3;
60
61struct GNUNET_NAMESTORE_QueueEntry *ns_ops[3];
62
63
64/**
65 * Re-establish the connection to the service.
66 *
67 * @param cls handle to use to re-connect.
68 */
69static void
70endbadly (void *cls)
71{
72 endbadly_task = NULL;
73 GNUNET_break (0);
74 GNUNET_SCHEDULER_shutdown ();
75 res = 1;
76}
77
78
79static void
80end (void *cls)
81{
82 if (NULL != zm)
83 {
84 GNUNET_NAMESTORE_zone_monitor_stop (zm);
85 zm = NULL;
86 }
87 if (NULL != ns_ops[0])
88 {
89 GNUNET_NAMESTORE_cancel (ns_ops[0]);
90 ns_ops[0] = NULL;
91 }
92 if (NULL != ns_ops[1])
93 {
94 GNUNET_NAMESTORE_cancel (ns_ops[1]);
95 ns_ops[1] = NULL;
96 }
97 if (NULL != ns_ops[2])
98 {
99 GNUNET_NAMESTORE_cancel (ns_ops[2]);
100 ns_ops[2] = NULL;
101 }
102 if (NULL != endbadly_task)
103 {
104 GNUNET_SCHEDULER_cancel (endbadly_task);
105 endbadly_task = NULL;
106 }
107 if (NULL != nsh)
108 {
109 GNUNET_NAMESTORE_disconnect (nsh);
110 nsh = NULL;
111 }
112 if (NULL != s_rd_1)
113 {
114 GNUNET_free_nz ((void *) s_rd_1->data);
115 GNUNET_free (s_rd_1);
116 }
117 if (NULL != s_rd_2)
118 {
119 GNUNET_free_nz ((void *) s_rd_2->data);
120 GNUNET_free (s_rd_2);
121 }
122 if (NULL != s_rd_3)
123 {
124 GNUNET_free_nz ((void *) s_rd_3->data);
125 GNUNET_free (s_rd_3);
126 }
127}
128
129
130static void
131zone_proc (void *cls,
132 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
133 const char *name,
134 unsigned int rd_count,
135 const struct GNUNET_GNSRECORD_Data *rd)
136{
137 static int returned_records;
138 static int fail = GNUNET_NO;
139
140 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
141 "Comparing results name %s\n",
142 name);
143 if (0 != GNUNET_memcmp (zone_key,
144 &privkey))
145 {
146 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
147 "Monitoring returned wrong zone key\n");
148 GNUNET_break (0);
149 GNUNET_SCHEDULER_shutdown ();
150 return;
151 }
152
153 if (0 == strcmp (name,
154 s_name_1))
155 {
156 if (GNUNET_YES !=
157 GNUNET_GNSRECORD_records_cmp (rd,
158 s_rd_1))
159 {
160 GNUNET_break (0);
161 fail = GNUNET_YES;
162 }
163 }
164 else if (0 == strcmp (name,
165 s_name_2))
166 {
167 if (GNUNET_YES !=
168 GNUNET_GNSRECORD_records_cmp (rd,
169 s_rd_2))
170 {
171 GNUNET_break (0);
172 fail = GNUNET_YES;
173 }
174 }
175 else
176 {
177 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
178 "Invalid name %s\n",
179 name);
180 GNUNET_break (0);
181 fail = GNUNET_YES;
182 }
183 GNUNET_NAMESTORE_zone_monitor_next (zm,
184 1);
185 if (2 == ++returned_records)
186 {
187 GNUNET_SCHEDULER_shutdown ();
188 if (GNUNET_YES == fail)
189 {
190 GNUNET_break (0);
191 res = 1;
192 }
193 else
194 {
195 res = 0;
196 }
197 }
198}
199
200
201static void
202fail_cb (void *cls)
203{
204 GNUNET_assert (0);
205}
206
207
208static void
209sync_cb (void *cls)
210{
211 /* do nothing */
212}
213
214
215static void
216put_cont (void *cls,
217 int32_t success,
218 const char *emsg)
219{
220 static int c = 0;
221 const char *label = cls;
222
223 if (0 == strcmp (label,
224 s_name_1))
225 ns_ops[0] = NULL;
226 else if (0 == strcmp (label,
227 s_name_2))
228 ns_ops[1] = NULL;
229 else if (0 == strcmp (label,
230 s_name_3))
231 ns_ops[2] = NULL;
232
233 if (success == GNUNET_OK)
234 {
235 c++;
236 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
237 "Created record %u: `%s'\n",
238 c,
239 label);
240 }
241 else
242 {
243 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
244 "Failed to created records\n");
245 GNUNET_break (0);
246 res = 1;
247 GNUNET_SCHEDULER_shutdown ();
248 return;
249 }
250
251 if (3 == c)
252 {
253 /* Start monitoring */
254 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
255 &privkey,
256 GNUNET_YES,
257 &fail_cb,
258 NULL,
259 &zone_proc,
260 NULL,
261 &sync_cb,
262 NULL);
263 if (NULL == zm)
264 {
265 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
266 "Failed to create zone monitor\n");
267 GNUNET_break (0);
268 res = 1;
269 GNUNET_SCHEDULER_shutdown ();
270 return;
271 }
272 }
273}
274
275
276static struct GNUNET_GNSRECORD_Data *
277create_record (unsigned int count)
278{
279 struct GNUNET_GNSRECORD_Data *rd;
280
281 rd = GNUNET_new_array (count,
282 struct GNUNET_GNSRECORD_Data);
283 for (unsigned int c = 0; c < count; c++)
284 {
285 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
286 GNUNET_TIME_UNIT_HOURS).abs_value_us;
287 rd[c].record_type = TEST_RECORD_TYPE;
288 rd[c].data_size = 50;
289 rd[c].data = GNUNET_malloc (50);
290 rd[c].flags = 0;
291 memset ((char *) rd[c].data,
292 'a',
293 50);
294 }
295 return rd;
296}
297
298
299static void
300run (void *cls,
301 const struct GNUNET_CONFIGURATION_Handle *mycfg,
302 struct GNUNET_TESTING_Peer *peer)
303{
304 res = 1;
305 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
306 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
307 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
308 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
309
310 cfg = mycfg;
311 GNUNET_SCHEDULER_add_shutdown (&end,
312 NULL);
313 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
314 &endbadly,
315 NULL);
316 /* Connect to namestore */
317 nsh = GNUNET_NAMESTORE_connect (cfg);
318 if (NULL == nsh)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 "Connect to namestore failed\n");
322 GNUNET_break (0);
323 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
324 NULL);
325 return;
326 }
327
328 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
329 "Created record 3\n");
330 /* name in different zone */
331 s_name_3 = "dummy3";
332 s_rd_3 = create_record (1);
333 GNUNET_assert (NULL != (ns_ops[2] =
334 GNUNET_NAMESTORE_records_store (nsh,
335 &privkey2,
336 s_name_3,
337 1,
338 s_rd_3,
339 &put_cont,
340 (void *) s_name_3)));
341
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
343 "Created record 1\n");
344 s_name_1 = "dummy1";
345 s_rd_1 = create_record (1);
346 GNUNET_assert (NULL != (ns_ops[0] =
347 GNUNET_NAMESTORE_records_store (nsh,
348 &privkey,
349 s_name_1,
350 1,
351 s_rd_1,
352 &put_cont,
353 (void *) s_name_1)));
354 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
355 "Created record 2 \n");
356 s_name_2 = "dummy2";
357 s_rd_2 = create_record (1);
358 GNUNET_assert (NULL != (ns_ops[1] =
359 GNUNET_NAMESTORE_records_store (nsh,
360 &privkey,
361 s_name_2,
362 1,
363 s_rd_2,
364 &put_cont,
365 (void *) s_name_2)));
366}
367
368
369#include "test_common.c"
370
371
372int
373main (int argc,
374 char *argv[])
375{
376 const char *plugin_name;
377 char *cfg_name;
378
379 SETUP_CFG (plugin_name, cfg_name);
380 res = 1;
381 if (0 !=
382 GNUNET_TESTING_peer_run ("test-namestore-api-monitoring-existing",
383 cfg_name,
384 &run,
385 NULL))
386 {
387 GNUNET_break (0);
388 res = 1;
389 }
390 GNUNET_DISK_purge_cfg_dir (cfg_name,
391 "GNUNET_TEST_HOME");
392 GNUNET_free (cfg_name);
393 return res;
394}
395
396
397/* end of test_namestore_api_monitoring_existing.c */
diff --git a/src/namestore/test_namestore_api_postgres.conf b/src/namestore/test_namestore_api_postgres.conf
deleted file mode 100644
index 93ef935b5..000000000
--- a/src/namestore/test_namestore_api_postgres.conf
+++ /dev/null
@@ -1,9 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = postgres
5
6
7[namestore-postgres]
8CONFIG = connect_timeout=10 dbname=gnunetcheck
9TEMPORARY_TABLE = YES
diff --git a/src/namestore/test_namestore_api_remove.c b/src/namestore/test_namestore_api_remove.c
deleted file mode 100644
index e8124c595..000000000
--- a/src/namestore/test_namestore_api_remove.c
+++ /dev/null
@@ -1,221 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 namestore/test_namestore_api.c
22 * @brief testcase for namestore_api.c to: remove record
23 */
24#include "platform.h"
25#include "gnunet_namestore_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_NAMESTORE_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 int removed;
49
50static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
51
52
53static void
54cleanup ()
55{
56 if (NULL != nsh)
57 {
58 GNUNET_NAMESTORE_disconnect (nsh);
59 nsh = NULL;
60 }
61 GNUNET_SCHEDULER_shutdown ();
62}
63
64
65/**
66 * Re-establish the connection to the service.
67 *
68 * @param cls handle to use to re-connect.
69 */
70static void
71endbadly (void *cls)
72{
73 if (NULL != nsqe)
74 {
75 GNUNET_NAMESTORE_cancel (nsqe);
76 nsqe = NULL;
77 }
78 cleanup ();
79 res = 1;
80}
81
82
83static void
84end (void *cls)
85{
86 cleanup ();
87 res = 0;
88}
89
90
91static void
92remove_cont (void *cls,
93 int32_t success,
94 const char *emsg)
95{
96 nsqe = NULL;
97 if (GNUNET_YES != success)
98 {
99 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
100 _ ("Records could not be removed: `%s'\n"),
101 emsg);
102 if (NULL != endbadly_task)
103 GNUNET_SCHEDULER_cancel (endbadly_task);
104 endbadly_task = GNUNET_SCHEDULER_add_now (&endbadly,
105 NULL);
106 return;
107 }
108 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
109 "Records were removed, perform lookup\n");
110 removed = GNUNET_YES;
111 if (NULL != endbadly_task)
112 GNUNET_SCHEDULER_cancel (endbadly_task);
113 GNUNET_SCHEDULER_add_now (&end, NULL);
114}
115
116
117static void
118put_cont (void *cls,
119 int32_t success,
120 const char *emsg)
121{
122 const char *name = cls;
123
124 GNUNET_assert (NULL != cls);
125 nsqe = NULL;
126 if (GNUNET_SYSERR == success)
127 {
128 GNUNET_break (0);
129 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
130 "Namestore could not store record: `%s'\n",
131 emsg);
132 if (endbadly_task != NULL)
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 "Name store added record for `%s': %s\n",
140 name,
141 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
142 nsqe = GNUNET_NAMESTORE_records_store (nsh,
143 &privkey,
144 name,
145 0, NULL,
146 &remove_cont, (void *) name);
147}
148
149
150static void
151run (void *cls,
152 const struct GNUNET_CONFIGURATION_Handle *cfg,
153 struct GNUNET_TESTING_Peer *peer)
154{
155 struct GNUNET_GNSRECORD_Data rd;
156 const char *name = "dummy";
157
158 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
159 &endbadly,
160 NULL);
161 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
162 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
163 GNUNET_IDENTITY_key_get_public (&privkey,
164 &pubkey);
165
166 removed = GNUNET_NO;
167
168 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
169 rd.record_type = TEST_RECORD_TYPE;
170 rd.data_size = TEST_RECORD_DATALEN;
171 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
172 rd.flags = 0;
173 memset ((char *) rd.data,
174 'a',
175 TEST_RECORD_DATALEN);
176
177 nsh = GNUNET_NAMESTORE_connect (cfg);
178 GNUNET_break (NULL != nsh);
179 nsqe = GNUNET_NAMESTORE_records_store (nsh,
180 &privkey,
181 name,
182 1,
183 &rd,
184 &put_cont,
185 (void *) name);
186 if (NULL == nsqe)
187 {
188 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
189 _ ("Namestore cannot store no block\n"));
190 }
191 GNUNET_free_nz ((void *) rd.data);
192}
193
194
195#include "test_common.c"
196
197
198int
199main (int argc, char *argv[])
200{
201 const char *plugin_name;
202 char *cfg_name;
203
204 SETUP_CFG (plugin_name, cfg_name);
205 res = 1;
206 if (0 !=
207 GNUNET_TESTING_peer_run ("test-namestore-api-remove",
208 cfg_name,
209 &run,
210 NULL))
211 {
212 res = 1;
213 }
214 GNUNET_DISK_purge_cfg_dir (cfg_name,
215 "GNUNET_TEST_HOME");
216 GNUNET_free (cfg_name);
217 return res;
218}
219
220
221/* end of test_namestore_api_remove.c */
diff --git a/src/namestore/test_namestore_api_remove_not_existing_record.c b/src/namestore/test_namestore_api_remove_not_existing_record.c
deleted file mode 100644
index 958ea4bf2..000000000
--- a/src/namestore/test_namestore_api_remove_not_existing_record.c
+++ /dev/null
@@ -1,180 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 namestore/test_namestore_api_remove_not_existing_record.c
22 * @brief testcase for namestore_api.c
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27
28#define TEST_RECORD_TYPE 1234
29
30#define TEST_RECORD_DATALEN 123
31
32#define TEST_RECORD_DATA 'a'
33
34#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
35
36
37static struct GNUNET_NAMESTORE_Handle *nsh;
38
39static struct GNUNET_SCHEDULER_Task *endbadly_task;
40
41static struct GNUNET_IDENTITY_PrivateKey privkey;
42
43static struct GNUNET_IDENTITY_PublicKey pubkey;
44
45static int res;
46
47static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
48
49
50static void
51cleanup (void)
52{
53 if (NULL != nsh)
54 {
55 GNUNET_NAMESTORE_disconnect (nsh);
56 nsh = NULL;
57 }
58 GNUNET_SCHEDULER_shutdown ();
59}
60
61
62/**
63 * Re-establish the connection to the service.
64 *
65 * @param cls handle to use to re-connect.
66 */
67static void
68endbadly (void *cls)
69{
70 if (NULL != nsqe)
71 {
72 GNUNET_NAMESTORE_cancel (nsqe);
73 nsqe = NULL;
74 }
75 cleanup ();
76 res = 1;
77}
78
79
80static void
81end (void *cls)
82{
83 cleanup ();
84 res = 0;
85}
86
87
88static void
89put_cont (void *cls,
90 int32_t success,
91 const char *emsg)
92{
93 GNUNET_assert (NULL != cls);
94 nsqe = NULL;
95 if (endbadly_task != NULL)
96 {
97 GNUNET_SCHEDULER_cancel (endbadly_task);
98 endbadly_task = NULL;
99 }
100 switch (success)
101 {
102 case GNUNET_NO:
103 /* We expected GNUNET_NO, since record was not found */
104 GNUNET_SCHEDULER_add_now (&end, NULL);
105 break;
106
107 case GNUNET_OK:
108 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
109 "Namestore could remove non-existing record: `%s'\n",
110 (NULL != emsg) ? emsg : "");
111 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
112 break;
113
114 case GNUNET_SYSERR:
115 default:
116 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
117 "Namestore failed: `%s'\n",
118 (NULL != emsg) ? emsg : "");
119 GNUNET_SCHEDULER_add_now (&endbadly, NULL);
120 break;
121 }
122}
123
124
125static void
126run (void *cls,
127 const struct GNUNET_CONFIGURATION_Handle *cfg,
128 struct GNUNET_TESTING_Peer *peer)
129{
130 const char *name = "dummy";
131
132 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
133 &endbadly,
134 NULL);
135 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
136 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
137 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
138
139 nsh = GNUNET_NAMESTORE_connect (cfg);
140 GNUNET_break (NULL != nsh);
141 nsqe = GNUNET_NAMESTORE_records_store (nsh,
142 &privkey,
143 name,
144 0, NULL,
145 &put_cont, (void *) name);
146 if (NULL == nsqe)
147 {
148 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
149 _ ("Namestore cannot store no block\n"));
150 }
151}
152
153
154#include "test_common.c"
155
156
157int
158main (int argc, char *argv[])
159{
160 const char *plugin_name;
161 char *cfg_name;
162
163 SETUP_CFG (plugin_name, cfg_name);
164 res = 1;
165 if (0 !=
166 GNUNET_TESTING_peer_run ("test-namestore-api-remove-non-existing-record",
167 cfg_name,
168 &run,
169 NULL))
170 {
171 res = 1;
172 }
173 GNUNET_DISK_purge_cfg_dir (cfg_name,
174 "GNUNET_TEST_HOME");
175 GNUNET_free (cfg_name);
176 return res;
177}
178
179
180/* end of test_namestore_api_remove_not_existing_record.c */
diff --git a/src/namestore/test_namestore_api_sqlite.conf b/src/namestore/test_namestore_api_sqlite.conf
deleted file mode 100644
index cd4822097..000000000
--- a/src/namestore/test_namestore_api_sqlite.conf
+++ /dev/null
@@ -1,8 +0,0 @@
1@INLINE@ test_namestore_api.conf
2
3[namestore]
4DATABASE = sqlite
5# PREFIX = valgrind --leak-check=full --track-origins=yes --log-file=/tmp/v_log
6
7[namestore-sqlite]
8FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db
diff --git a/src/namestore/test_namestore_api_store.c b/src/namestore/test_namestore_api_store.c
deleted file mode 100644
index e0b7daa5d..000000000
--- a/src/namestore/test_namestore_api_store.c
+++ /dev/null
@@ -1,172 +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 namestore/test_namestore_api_store.c
22 * @brief testcase for namestore_api.c: store a record
23 */
24#include "platform.h"
25#include "gnunet_namestore_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_NAMESTORE_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_NAMESTORE_QueueEntry *nsqe;
49
50
51static void
52cleanup ()
53{
54 if (NULL != nsh)
55 {
56 GNUNET_NAMESTORE_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_NAMESTORE_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
90put_cont (void *cls, int32_t success, const char *emsg)
91{
92 const char *name = cls;
93
94 nsqe = NULL;
95 GNUNET_assert (NULL != cls);
96 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
97 "Name store added record for `%s': %s\n",
98 name,
99 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
100 GNUNET_SCHEDULER_cancel (endbadly_task);
101 endbadly_task = NULL;
102 GNUNET_SCHEDULER_add_now (&end, NULL);
103}
104
105
106static void
107run (void *cls,
108 const struct GNUNET_CONFIGURATION_Handle *cfg,
109 struct GNUNET_TESTING_Peer *peer)
110{
111 struct GNUNET_GNSRECORD_Data rd;
112 const char *name = "dummy.dummy.gnunet";
113
114 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
115 &endbadly, NULL);
116 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
117 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
118 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
119
120
121 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us;
122 rd.record_type = TEST_RECORD_TYPE;
123 rd.data_size = TEST_RECORD_DATALEN;
124 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
125 rd.flags = 0;
126 memset ((char *) rd.data, 'a', TEST_RECORD_DATALEN);
127
128 nsh = GNUNET_NAMESTORE_connect (cfg);
129 GNUNET_break (NULL != nsh);
130 nsqe = GNUNET_NAMESTORE_records_store (nsh,
131 &privkey,
132 name,
133 1,
134 &rd,
135 &put_cont,
136 (void *) name);
137 if (NULL == nsqe)
138 {
139 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
140 _ ("Namestore cannot store no block\n"));
141 }
142 GNUNET_free_nz ((void *) rd.data);
143}
144
145
146#include "test_common.c"
147
148
149int
150main (int argc, char *argv[])
151{
152 const char *plugin_name;
153 char *cfg_name;
154
155 SETUP_CFG (plugin_name, cfg_name);
156 res = 1;
157 if (0 !=
158 GNUNET_TESTING_peer_run ("test-namestore-api",
159 cfg_name,
160 &run,
161 NULL))
162 {
163 res = 1;
164 }
165 GNUNET_DISK_purge_cfg_dir (cfg_name,
166 "GNUNET_TEST_HOME");
167 GNUNET_free (cfg_name);
168 return res;
169}
170
171
172/* end of test_namestore_api_store.c */
diff --git a/src/namestore/test_namestore_api_store_update.c b/src/namestore/test_namestore_api_store_update.c
deleted file mode 100644
index 5c169734a..000000000
--- a/src/namestore/test_namestore_api_store_update.c
+++ /dev/null
@@ -1,309 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2012, 2013, 2018 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 namestore/test_namestore_api_store_update.c
22 * @brief testcase for namestore_api.c: store a record, update it and perform a lookup
23 * @author Matthias Wachs
24 * @author Christian Grothoff
25 */
26#include "platform.h"
27#include "gnunet_namecache_service.h"
28#include "gnunet_namestore_service.h"
29#include "gnunet_testing_lib.h"
30#include "gnunet_dnsparser_lib.h"
31
32#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
33
34#define TEST_RECORD_DATALEN 123
35
36#define TEST_RECORD_DATA 'a'
37
38#define TEST_RECORD_DATALEN2 234
39
40#define TEST_RECORD_DATA2 'b'
41
42#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
43
44
45static struct GNUNET_NAMESTORE_Handle *nsh;
46
47static struct GNUNET_NAMECACHE_Handle *nch;
48
49static struct GNUNET_SCHEDULER_Task *endbadly_task;
50
51static struct GNUNET_IDENTITY_PrivateKey privkey;
52
53static struct GNUNET_IDENTITY_PublicKey pubkey;
54
55static int res;
56
57static int update_performed;
58
59static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
60
61static struct GNUNET_NAMECACHE_QueueEntry *ncqe;
62
63static const char *name = "dummy";
64
65
66/**
67 * Terminate test with error.
68 *
69 * @param cls handle to use to re-connect.
70 */
71static void
72endbadly (void *cls)
73{
74 GNUNET_break (0);
75 endbadly_task = NULL;
76 GNUNET_SCHEDULER_shutdown ();
77 res = 1;
78}
79
80
81static void
82end (void *cls)
83{
84 if (NULL != endbadly_task)
85 {
86 GNUNET_SCHEDULER_cancel (endbadly_task);
87 endbadly_task = NULL;
88 }
89 if (NULL != nsqe)
90 {
91 GNUNET_NAMESTORE_cancel (nsqe);
92 nsqe = NULL;
93 }
94 if (NULL != ncqe)
95 {
96 GNUNET_NAMECACHE_cancel (ncqe);
97 ncqe = NULL;
98 }
99 if (NULL != nsh)
100 {
101 GNUNET_NAMESTORE_disconnect (nsh);
102 nsh = NULL;
103 }
104 if (NULL != nch)
105 {
106 GNUNET_NAMECACHE_disconnect (nch);
107 nch = NULL;
108 }
109}
110
111
112static void
113put_cont (void *cls,
114 int32_t success,
115 const char *emsg);
116
117
118static void
119rd_decrypt_cb (void *cls,
120 unsigned int rd_count,
121 const struct GNUNET_GNSRECORD_Data *rd)
122{
123 struct GNUNET_GNSRECORD_Data rd_new;
124
125 GNUNET_assert (1 == rd_count);
126 GNUNET_assert (NULL != rd);
127
128 if (GNUNET_NO == update_performed)
129 {
130 char rd_cmp_data[TEST_RECORD_DATALEN];
131
132 memset (rd_cmp_data,
133 TEST_RECORD_DATA,
134 TEST_RECORD_DATALEN);
135 GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type);
136 GNUNET_assert (TEST_RECORD_DATALEN == rd[0].data_size);
137 GNUNET_assert (0 == memcmp (&rd_cmp_data,
138 rd[0].data,
139 TEST_RECORD_DATALEN));
140
141 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
142 "Block was decrypted successfully, updating record \n");
143
144 rd_new.flags = GNUNET_GNSRECORD_RF_NONE;
145 rd_new.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us
146 + 1000000000;
147 rd_new.record_type = TEST_RECORD_TYPE;
148 rd_new.data_size = TEST_RECORD_DATALEN2;
149 rd_new.data = GNUNET_malloc (TEST_RECORD_DATALEN2);
150 memset ((char *) rd_new.data,
151 TEST_RECORD_DATA2,
152 TEST_RECORD_DATALEN2);
153
154 nsqe = GNUNET_NAMESTORE_records_store (nsh,
155 &privkey,
156 name,
157 1,
158 &rd_new,
159 &put_cont,
160 (void *) name);
161 update_performed = GNUNET_YES;
162 }
163 else
164 {
165 char rd_cmp_data[TEST_RECORD_DATALEN2];
166
167 memset (rd_cmp_data,
168 TEST_RECORD_DATA2,
169 TEST_RECORD_DATALEN2);
170 GNUNET_assert (TEST_RECORD_TYPE == rd[0].record_type);
171 GNUNET_assert (TEST_RECORD_DATALEN2 == rd[0].data_size);
172 GNUNET_assert (0 == memcmp (&rd_cmp_data,
173 rd[0].data,
174 TEST_RECORD_DATALEN2));
175 GNUNET_SCHEDULER_shutdown ();
176 res = 0;
177 }
178}
179
180
181static void
182name_lookup_proc (void *cls,
183 const struct GNUNET_GNSRECORD_Block *block)
184{
185 const char *name = cls;
186
187 ncqe = NULL;
188 GNUNET_assert (NULL != cls);
189 if (NULL == block)
190 {
191 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
192 _ ("Namecache returned no block for `%s'\n"),
193 name);
194 GNUNET_SCHEDULER_shutdown ();
195 return;
196 }
197
198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
199 "Namecache returned block, decrypting \n");
200 GNUNET_assert (GNUNET_OK ==
201 GNUNET_GNSRECORD_block_decrypt (block,
202 &pubkey,
203 name,
204 &rd_decrypt_cb,
205 (void *) name));
206}
207
208
209static void
210put_cont (void *cls,
211 int32_t success,
212 const char *emsg)
213{
214 const char *name = cls;
215 struct GNUNET_HashCode derived_hash;
216
217 nsqe = NULL;
218 GNUNET_assert (NULL != cls);
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220 "Name store added record for `%s': %s\n",
221 name,
222 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
223 /* Create derived hash */
224 GNUNET_GNSRECORD_query_from_private_key (&privkey,
225 name,
226 &derived_hash);
227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
228 "Looking in namecache for `%s'\n",
229 GNUNET_h2s (&derived_hash));
230 ncqe = GNUNET_NAMECACHE_lookup_block (nch,
231 &derived_hash,
232 &name_lookup_proc, (void *) name);
233}
234
235
236static void
237run (void *cls,
238 const struct GNUNET_CONFIGURATION_Handle *cfg,
239 struct GNUNET_TESTING_Peer *peer)
240{
241 struct GNUNET_GNSRECORD_Data rd;
242
243 update_performed = GNUNET_NO;
244 GNUNET_SCHEDULER_add_shutdown (&end,
245 NULL);
246 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
247 &endbadly,
248 NULL);
249 memset (&privkey, 0, sizeof (privkey));
250 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
251 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
252 GNUNET_IDENTITY_key_get_public (&privkey, &pubkey);
253 rd.flags = GNUNET_GNSRECORD_RF_NONE;
254 rd.expiration_time = GNUNET_TIME_absolute_get ().abs_value_us + 1000000000;
255 rd.record_type = TEST_RECORD_TYPE;
256 rd.data_size = TEST_RECORD_DATALEN;
257 rd.data = GNUNET_malloc (TEST_RECORD_DATALEN);
258 memset ((char *) rd.data,
259 TEST_RECORD_DATA,
260 TEST_RECORD_DATALEN);
261
262 nsh = GNUNET_NAMESTORE_connect (cfg);
263 GNUNET_break (NULL != nsh);
264 nch = GNUNET_NAMECACHE_connect (cfg);
265 GNUNET_break (NULL != nch);
266 nsqe = GNUNET_NAMESTORE_records_store (nsh,
267 &privkey,
268 name,
269 1,
270 &rd,
271 &put_cont,
272 (void *) name);
273 if (NULL == nsqe)
274 {
275 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
276 _ ("Namestore cannot store no block\n"));
277 }
278 GNUNET_free_nz ((void *) rd.data);
279}
280
281
282#include "test_common.c"
283
284
285int
286main (int argc,
287 char *argv[])
288{
289 const char *plugin_name;
290 char *cfg_name;
291
292 SETUP_CFG (plugin_name, cfg_name);
293 res = 1;
294 if (0 !=
295 GNUNET_TESTING_peer_run ("test--store-update",
296 cfg_name,
297 &run,
298 NULL))
299 {
300 res = 1;
301 }
302 GNUNET_DISK_purge_cfg_dir (cfg_name,
303 "GNUNET_TEST_HOME");
304 GNUNET_free (cfg_name);
305 return res;
306}
307
308
309/* end of test_namestore_api_store_update.c */
diff --git a/src/namestore/test_namestore_api_zone_iteration.c b/src/namestore/test_namestore_api_zone_iteration.c
deleted file mode 100644
index 55ca901e2..000000000
--- a/src/namestore/test_namestore_api_zone_iteration.c
+++ /dev/null
@@ -1,465 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2013, 2018 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 namestore/test_namestore_api_zone_iteration.c
22 * @brief testcase for zone iteration functionality: iterate all zones
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "namestore.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32
33#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
34
35
36static struct GNUNET_NAMESTORE_Handle *nsh;
37
38static struct GNUNET_SCHEDULER_Task *endbadly_task;
39
40static struct GNUNET_IDENTITY_PrivateKey privkey;
41
42static struct GNUNET_IDENTITY_PrivateKey privkey2;
43
44static struct GNUNET_NAMESTORE_ZoneIterator *zi;
45
46static int res;
47
48static int returned_records;
49
50static char *s_name_1;
51
52static struct GNUNET_GNSRECORD_Data *s_rd_1;
53
54static char *s_name_2;
55
56static struct GNUNET_GNSRECORD_Data *s_rd_2;
57
58static char *s_name_3;
59
60static struct GNUNET_GNSRECORD_Data *s_rd_3;
61
62
63/**
64 * Re-establish the connection to the service.
65 *
66 * @param cls handle to use to re-connect.
67 * @param tc scheduler context
68 */
69static void
70endbadly (void *cls)
71{
72 endbadly_task = NULL;
73 GNUNET_SCHEDULER_shutdown ();
74 res = 1;
75}
76
77
78static void
79end (void *cls)
80{
81 if (NULL != zi)
82 {
83 GNUNET_NAMESTORE_zone_iteration_stop (zi);
84 zi = NULL;
85 }
86 if (NULL != endbadly_task)
87 {
88 GNUNET_SCHEDULER_cancel (endbadly_task);
89 endbadly_task = NULL;
90 }
91 GNUNET_free (s_name_1);
92 GNUNET_free (s_name_2);
93 GNUNET_free (s_name_3);
94 if (NULL != s_rd_1)
95 {
96 GNUNET_free_nz ((void *) s_rd_1->data);
97 GNUNET_free (s_rd_1);
98 }
99 if (NULL != s_rd_2)
100 {
101 GNUNET_free_nz ((void *) s_rd_2->data);
102 GNUNET_free (s_rd_2);
103 }
104 if (NULL != s_rd_3)
105 {
106 GNUNET_free_nz ((void *) s_rd_3->data);
107 GNUNET_free (s_rd_3);
108 }
109 if (NULL != nsh)
110 {
111 GNUNET_NAMESTORE_disconnect (nsh);
112 nsh = NULL;
113 }
114}
115
116
117static void
118zone_end (void *cls)
119{
120 GNUNET_break (3 == returned_records);
121 if (3 == returned_records)
122 {
123 res = 0; /* Last iteraterator callback, we are done */
124 zi = NULL;
125 }
126 else
127 res = 1;
128
129 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
130 "Received last result, iteration done after receing %u results\n",
131 returned_records);
132 GNUNET_SCHEDULER_shutdown ();
133}
134
135
136static void
137fail_cb (void *cls)
138{
139 GNUNET_assert (0);
140}
141
142
143static void
144zone_proc (void *cls,
145 const struct GNUNET_IDENTITY_PrivateKey *zone,
146 const char *label,
147 unsigned int rd_count,
148 const struct GNUNET_GNSRECORD_Data *rd)
149{
150 int failed = GNUNET_NO;
151
152 GNUNET_assert (NULL != zone);
153 if (0 == GNUNET_memcmp (zone,
154 &privkey))
155 {
156 if (0 == strcmp (label, s_name_1))
157 {
158 if (rd_count == 1)
159 {
160 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
161 {
162 failed = GNUNET_YES;
163 GNUNET_break (0);
164 }
165 }
166 else
167 {
168 failed = GNUNET_YES;
169 GNUNET_break (0);
170 }
171 }
172 else if (0 == strcmp (label, s_name_2))
173 {
174 if (rd_count == 1)
175 {
176 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
177 {
178 failed = GNUNET_YES;
179 GNUNET_break (0);
180 }
181 }
182 else
183 {
184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
185 "Received invalid record count\n");
186 failed = GNUNET_YES;
187 GNUNET_break (0);
188 }
189 }
190 else
191 {
192 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
193 "Comparing result failed: got name `%s' for first zone\n",
194 label);
195 failed = GNUNET_YES;
196 GNUNET_break (0);
197 }
198 }
199 else if (0 == GNUNET_memcmp (zone,
200 &privkey2))
201 {
202 if (0 == strcmp (label, s_name_3))
203 {
204 if (rd_count == 1)
205 {
206 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3))
207 {
208 failed = GNUNET_YES;
209 GNUNET_break (0);
210 }
211 }
212 else
213 {
214 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
215 "Received invalid record count\n");
216 failed = GNUNET_YES;
217 GNUNET_break (0);
218 }
219 }
220 else
221 {
222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
223 "Comparing result failed: got name `%s' for first zone\n",
224 label);
225 failed = GNUNET_YES;
226 GNUNET_break (0);
227 }
228 }
229 else
230 {
231 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
232 "Received invalid zone\n");
233 failed = GNUNET_YES;
234 GNUNET_break (0);
235 }
236
237 if (failed == GNUNET_NO)
238 {
239 returned_records++;
240 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
241 "Telling namestore to send the next result\n");
242 GNUNET_NAMESTORE_zone_iterator_next (zi,
243 1);
244 }
245 else
246 {
247 GNUNET_break (0);
248 GNUNET_SCHEDULER_shutdown ();
249 res = 1;
250 }
251}
252
253
254static void
255put_cont (void *cls,
256 int32_t success,
257 const char *emsg)
258{
259 static int c = 0;
260
261 if (success == GNUNET_OK)
262 {
263 c++;
264 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
265 "Created record %u \n",
266 c);
267 }
268 else
269 {
270 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
271 "Failed to created records: `%s'\n",
272 emsg);
273 GNUNET_break (0);
274 GNUNET_SCHEDULER_shutdown ();
275 res = 1;
276 return;
277 }
278
279 if (c == 3)
280 {
281 res = 1;
282 returned_records = 0;
283 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
284 "All records created, starting iteration over all zones \n");
285 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
286 NULL,
287 &fail_cb,
288 NULL,
289 &zone_proc,
290 NULL,
291 &zone_end,
292 NULL);
293 if (zi == NULL)
294 {
295 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
296 "Failed to create zone iterator\n");
297 GNUNET_break (0);
298 GNUNET_SCHEDULER_shutdown ();
299 res = 1;
300 return;
301 }
302 }
303}
304
305
306static struct GNUNET_GNSRECORD_Data *
307create_record (unsigned int count)
308{
309 struct GNUNET_GNSRECORD_Data *rd;
310
311 rd = GNUNET_new_array (count,
312 struct GNUNET_GNSRECORD_Data);
313 for (unsigned int c = 0; c < count; c++)
314 {
315 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
316 GNUNET_TIME_UNIT_HOURS).abs_value_us;
317 rd[c].record_type = TEST_RECORD_TYPE;
318 rd[c].data_size = 50;
319 rd[c].data = GNUNET_malloc (50);
320 rd[c].flags = 0;
321 memset ((char *) rd[c].data, 'a', 50);
322 }
323 return rd;
324}
325
326
327/**
328 * Callback called from the zone iterator when we iterate over
329 * the empty zone. Check that we got no records and then
330 * start the actual tests by filling the zone.
331 */
332static void
333empty_zone_proc (void *cls,
334 const struct GNUNET_IDENTITY_PrivateKey *zone,
335 const char *label,
336 unsigned int rd_count,
337 const struct GNUNET_GNSRECORD_Data *rd)
338{
339 GNUNET_assert (nsh == cls);
340 if (NULL != zone)
341 {
342 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
343 _ ("Expected empty zone but received zone private key\n"));
344 GNUNET_break (0);
345 GNUNET_SCHEDULER_shutdown ();
346 res = 1;
347 return;
348 }
349 if ((NULL != label) || (NULL != rd) || (0 != rd_count))
350 {
351 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
352 _ ("Expected no zone content but received data\n"));
353 GNUNET_break (0);
354 GNUNET_SCHEDULER_shutdown ();
355 res = 1;
356 return;
357 }
358 GNUNET_assert (0);
359}
360
361
362static void
363empty_zone_end (void *cls)
364{
365 zi = NULL;
366 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
367 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
368 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
369 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
370
371 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
372
373 GNUNET_asprintf (&s_name_1, "dummy1");
374 s_rd_1 = create_record (1);
375 GNUNET_NAMESTORE_records_store (nsh,
376 &privkey,
377 s_name_1,
378 1, s_rd_1,
379 &put_cont,
380 NULL);
381 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
382 "Created record 2 \n");
383 GNUNET_asprintf (&s_name_2, "dummy2");
384 s_rd_2 = create_record (1);
385 GNUNET_NAMESTORE_records_store (nsh,
386 &privkey,
387 s_name_2,
388 1, s_rd_2,
389 &put_cont,
390 NULL);
391 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
392 "Created record 3\n");
393 /* name in different zone */
394 GNUNET_asprintf (&s_name_3, "dummy3");
395 s_rd_3 = create_record (1);
396 GNUNET_NAMESTORE_records_store (nsh,
397 &privkey2,
398 s_name_3,
399 1,
400 s_rd_3,
401 &put_cont,
402 NULL);
403}
404
405
406static void
407run (void *cls,
408 const struct GNUNET_CONFIGURATION_Handle *cfg,
409 struct GNUNET_TESTING_Peer *peer)
410{
411 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
412 &endbadly,
413 NULL);
414 GNUNET_SCHEDULER_add_shutdown (&end,
415 NULL);
416
417 nsh = GNUNET_NAMESTORE_connect (cfg);
418 GNUNET_break (NULL != nsh);
419 /* first, iterate over empty namestore */
420 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
421 NULL,
422 &fail_cb,
423 NULL,
424 &empty_zone_proc,
425 nsh,
426 &empty_zone_end,
427 NULL);
428 if (NULL == zi)
429 {
430 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
431 "Failed to create zone iterator\n");
432 GNUNET_break (0);
433 res = 1;
434 GNUNET_SCHEDULER_shutdown ();
435 }
436}
437
438
439#include "test_common.c"
440
441
442int
443main (int argc, char *argv[])
444{
445 const char *plugin_name;
446 char *cfg_name;
447
448 SETUP_CFG (plugin_name, cfg_name);
449 res = 1;
450 if (0 !=
451 GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration",
452 cfg_name,
453 &run,
454 NULL))
455 {
456 res = 1;
457 }
458 GNUNET_DISK_purge_cfg_dir (cfg_name,
459 "GNUNET_TEST_HOME");
460 GNUNET_free (cfg_name);
461 return res;
462}
463
464
465/* end of test_namestore_api_zone_iteration.c */
diff --git a/src/namestore/test_namestore_api_zone_iteration_nick.c b/src/namestore/test_namestore_api_zone_iteration_nick.c
deleted file mode 100644
index c203a63a6..000000000
--- a/src/namestore/test_namestore_api_zone_iteration_nick.c
+++ /dev/null
@@ -1,462 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 namestore/test_namestore_api_zone_iteration.c
22 * @brief testcase for zone iteration functionality: iterate all zones
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_gns_service.h"
27#include "gnunet_testing_lib.h"
28#include "namestore.h"
29#include "gnunet_dnsparser_lib.h"
30
31#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
32
33#define ZONE_NICK_1 "nick1"
34#define ZONE_NICK_2 "nick2"
35
36#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
37
38
39static struct GNUNET_NAMESTORE_Handle *nsh;
40
41static struct GNUNET_IDENTITY_PrivateKey privkey;
42
43static struct GNUNET_IDENTITY_PrivateKey privkey2;
44
45static struct GNUNET_NAMESTORE_ZoneIterator *zi;
46
47static int res;
48
49static int returned_records;
50
51static char *s_name_1;
52
53static struct GNUNET_GNSRECORD_Data *s_rd_1;
54
55static char *s_name_2;
56
57static struct GNUNET_GNSRECORD_Data *s_rd_2;
58
59static char *s_name_3;
60
61static struct GNUNET_GNSRECORD_Data *s_rd_3;
62
63static struct GNUNET_NAMESTORE_QueueEntry *nsqe;
64
65
66/**
67 * Re-establish the connection to the service.
68 *
69 * @param cls handle to use to re-connect.
70 * @param tc scheduler context
71 */
72static void
73end (void *cls)
74{
75 if (NULL != zi)
76 {
77 GNUNET_NAMESTORE_zone_iteration_stop (zi);
78 zi = NULL;
79 }
80 if (nsh != NULL)
81 {
82 GNUNET_NAMESTORE_disconnect (nsh);
83 nsh = NULL;
84 }
85 GNUNET_free (s_name_1);
86 GNUNET_free (s_name_2);
87 GNUNET_free (s_name_3);
88
89 if (s_rd_1 != NULL)
90 {
91 GNUNET_free_nz ((void *) s_rd_1->data);
92 GNUNET_free (s_rd_1);
93 }
94 if (s_rd_2 != NULL)
95 {
96 GNUNET_free_nz ((void *) s_rd_2->data);
97 GNUNET_free (s_rd_2);
98 }
99 if (s_rd_3 != NULL)
100 {
101 GNUNET_free_nz ((void *) s_rd_3->data);
102 GNUNET_free (s_rd_3);
103 }
104}
105
106
107static int
108check_zone_1 (const char *label, unsigned int rd_count,
109 const struct GNUNET_GNSRECORD_Data *rd)
110{
111 for (unsigned int c = 0; c < rd_count; c++)
112 {
113 if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) &&
114 (0 != strcmp (rd[c].data, ZONE_NICK_1)))
115 {
116 GNUNET_break (0);
117 return GNUNET_YES;
118 }
119 }
120 return GNUNET_NO;
121}
122
123
124static int
125check_zone_2 (const char *label,
126 unsigned int rd_count,
127 const struct GNUNET_GNSRECORD_Data *rd)
128{
129 for (unsigned int c = 0; c < rd_count; c++)
130 {
131 if ((rd[c].record_type == GNUNET_GNSRECORD_TYPE_NICK) &&
132 (0 != strcmp (rd[c].data, ZONE_NICK_2)))
133 {
134 GNUNET_break (0);
135 return GNUNET_YES;
136 }
137 }
138 return GNUNET_NO;
139}
140
141
142static void
143zone_proc_end (void *cls)
144{
145 zi = NULL;
146 res = 0;
147 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
148 "Received last result, iteration done after receing %u results\n",
149 returned_records);
150 GNUNET_SCHEDULER_shutdown ();
151}
152
153
154static void
155zone_proc (void *cls,
156 const struct GNUNET_IDENTITY_PrivateKey *zone,
157 const char *label,
158 unsigned int rd_count,
159 const struct GNUNET_GNSRECORD_Data *rd)
160{
161 int failed = GNUNET_NO;
162
163 GNUNET_assert (NULL != zone);
164 if (0 == GNUNET_memcmp (zone, &privkey))
165 {
166 failed = check_zone_1 (label, rd_count, rd);
167 if (GNUNET_YES == failed)
168 GNUNET_break (0);
169 }
170 else if (0 == GNUNET_memcmp (zone, &privkey2))
171 {
172 failed = check_zone_2 (label, rd_count, rd);
173 if (GNUNET_YES == failed)
174 GNUNET_break (0);
175 }
176 else
177 {
178 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
179 "Received invalid zone\n");
180 failed = GNUNET_YES;
181 GNUNET_break (0);
182 }
183
184 if (failed == GNUNET_NO)
185 {
186 returned_records++;
187 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
188 "Telling namestore to send the next result\n");
189 GNUNET_NAMESTORE_zone_iterator_next (zi,
190 1);
191 }
192 else
193 {
194 GNUNET_break (0);
195 res = 1;
196 GNUNET_SCHEDULER_shutdown ();
197 }
198}
199
200
201static void
202fail_cb (void *cls)
203{
204 GNUNET_assert (0);
205}
206
207
208static void
209put_cont (void *cls,
210 int32_t success,
211 const char *emsg)
212{
213 static int c = 0;
214
215 if (success == GNUNET_OK)
216 {
217 c++;
218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c);
219 }
220 else
221 {
222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n",
223 emsg);
224 GNUNET_break (0);
225 GNUNET_SCHEDULER_shutdown ();
226 return;
227 }
228
229 if (c == 3)
230 {
231 res = 1;
232 returned_records = 0;
233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
234 "All records created, starting iteration over all zones \n");
235 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
236 NULL,
237 &fail_cb,
238 NULL,
239 &zone_proc,
240 NULL,
241 &zone_proc_end,
242 NULL);
243 if (zi == NULL)
244 {
245 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to create zone iterator\n");
246 GNUNET_break (0);
247 GNUNET_SCHEDULER_shutdown ();
248 return;
249 }
250 }
251}
252
253
254static struct GNUNET_GNSRECORD_Data *
255create_record (unsigned int count)
256{
257 struct GNUNET_GNSRECORD_Data *rd;
258
259 rd = GNUNET_new_array (count,
260 struct GNUNET_GNSRECORD_Data);
261 for (unsigned int c = 0; c < count; c++)
262 {
263 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
264 GNUNET_TIME_UNIT_HOURS).abs_value_us;
265 rd[c].record_type = TEST_RECORD_TYPE;
266 rd[c].data_size = 50;
267 rd[c].data = GNUNET_malloc (50);
268 rd[c].flags = 0;
269 memset ((char *) rd[c].data, 'a', 50);
270 }
271 return rd;
272}
273
274
275static void
276nick_2_cont (void *cls,
277 int32_t success,
278 const char *emsg)
279{
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
281 "Nick added : %s\n",
282 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
283
284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record 1\n");
285
286 GNUNET_asprintf (&s_name_1, "dummy1");
287 s_rd_1 = create_record (1);
288 GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_1,
289 1, s_rd_1,
290 &put_cont, NULL);
291
292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
293 "Created record 2 \n");
294 GNUNET_asprintf (&s_name_2, "dummy2");
295 s_rd_2 = create_record (1);
296 GNUNET_NAMESTORE_records_store (nsh, &privkey, s_name_2,
297 1, s_rd_2, &put_cont, NULL);
298
299 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
300 "Created record 3\n");
301
302 /* name in different zone */
303 GNUNET_asprintf (&s_name_3, "dummy3");
304 s_rd_3 = create_record (1);
305 GNUNET_NAMESTORE_records_store (nsh, &privkey2, s_name_3,
306 1, s_rd_3,
307 &put_cont, NULL);
308}
309
310
311static void
312nick_1_cont (void *cls, int32_t success, const char *emsg)
313{
314 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
315 "Nick 1 added : %s\n",
316 (success == GNUNET_OK) ? "SUCCESS" : "FAIL");
317 struct GNUNET_GNSRECORD_Data rd;
318
319 memset (&rd, 0, sizeof(rd));
320 rd.data = ZONE_NICK_2;
321 rd.data_size = strlen (ZONE_NICK_2) + 1;
322 rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
323 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
324 rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
325 nsqe = GNUNET_NAMESTORE_records_store (nsh,
326 &privkey2,
327 GNUNET_GNS_EMPTY_LABEL_AT,
328 1,
329 &rd,
330 &nick_2_cont,
331 &privkey2);
332
333 if (NULL == nsqe)
334 {
335 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
336 _ ("Namestore cannot store no block\n"));
337 }
338}
339
340
341/**
342 * Callback called from the zone iterator when we iterate over
343 * the empty zone. Check that we got no records and then
344 * start the actual tests by filling the zone.
345 */
346static void
347empty_zone_proc (void *cls,
348 const struct GNUNET_IDENTITY_PrivateKey *zone,
349 const char *label,
350 unsigned int rd_count,
351 const struct GNUNET_GNSRECORD_Data *rd)
352{
353 GNUNET_assert (nsh == cls);
354
355 if (NULL != zone)
356 {
357 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
358 _ ("Expected empty zone but received zone private key\n"));
359 GNUNET_break (0);
360 GNUNET_SCHEDULER_shutdown ();
361 return;
362 }
363 if ((NULL != label) || (NULL != rd) || (0 != rd_count))
364 {
365 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
366 _ ("Expected no zone content but received data\n"));
367 GNUNET_break (0);
368 GNUNET_SCHEDULER_shutdown ();
369 return;
370 }
371 GNUNET_assert (0);
372}
373
374
375static void
376empty_zone_end (void *cls)
377{
378 GNUNET_assert (nsh == cls);
379 struct GNUNET_GNSRECORD_Data rd;
380
381 zi = NULL;
382 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
383 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
384 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
385 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
386
387 memset (&rd, 0, sizeof(rd));
388 rd.data = ZONE_NICK_1;
389 rd.data_size = strlen (ZONE_NICK_1) + 1;
390 rd.record_type = GNUNET_GNSRECORD_TYPE_NICK;
391 rd.expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
392 rd.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
393 nsqe = GNUNET_NAMESTORE_records_store (nsh,
394 &privkey,
395 GNUNET_GNS_EMPTY_LABEL_AT,
396 1,
397 &rd,
398 &nick_1_cont,
399 NULL);
400 if (NULL == nsqe)
401 {
402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
403 _ ("Namestore cannot store no block\n"));
404 }
405}
406
407
408static void
409run (void *cls,
410 const struct GNUNET_CONFIGURATION_Handle *cfg,
411 struct GNUNET_TESTING_Peer *peer)
412{
413 nsh = GNUNET_NAMESTORE_connect (cfg);
414 GNUNET_break (NULL != nsh);
415 GNUNET_SCHEDULER_add_shutdown (&end,
416 NULL);
417 /* first, iterate over empty namestore */
418 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
419 NULL,
420 &fail_cb,
421 NULL,
422 &empty_zone_proc,
423 nsh,
424 &empty_zone_end,
425 nsh);
426 if (NULL == zi)
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
429 "Failed to create zone iterator\n");
430 GNUNET_break (0);
431 GNUNET_SCHEDULER_shutdown ();
432 }
433}
434
435
436#include "test_common.c"
437
438
439int
440main (int argc, char *argv[])
441{
442 const char *plugin_name;
443 char *cfg_name;
444
445 SETUP_CFG (plugin_name, cfg_name);
446 res = 1;
447 if (0 !=
448 GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-nick",
449 cfg_name,
450 &run,
451 NULL))
452 {
453 res = 1;
454 }
455 GNUNET_DISK_purge_cfg_dir (cfg_name,
456 "GNUNET_TEST_HOME");
457 GNUNET_free (cfg_name);
458 return res;
459}
460
461
462/* end of test_namestore_api_zone_iteration.c */
diff --git a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c b/src/namestore/test_namestore_api_zone_iteration_specific_zone.c
deleted file mode 100644
index 70097a69e..000000000
--- a/src/namestore/test_namestore_api_zone_iteration_specific_zone.c
+++ /dev/null
@@ -1,448 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 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 namestore/test_namestore_api_zone_iteration_specific_zone.c
22 * @brief testcase for zone iteration functionality: iterate over a specific zone
23 * @author Matthias Wachs
24 */
25#include "platform.h"
26#include "gnunet_namestore_service.h"
27#include "gnunet_testing_lib.h"
28#include "namestore.h"
29#include "gnunet_dnsparser_lib.h"
30
31#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
32
33
34#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
35
36
37static struct GNUNET_NAMESTORE_Handle *nsh;
38
39static struct GNUNET_SCHEDULER_Task *endbadly_task;
40
41static struct GNUNET_IDENTITY_PrivateKey privkey;
42
43static struct GNUNET_IDENTITY_PrivateKey privkey2;
44
45static struct GNUNET_NAMESTORE_ZoneIterator *zi;
46
47static int res;
48
49static int returned_records;
50
51static char *s_name_1;
52
53static struct GNUNET_GNSRECORD_Data *s_rd_1;
54
55static char *s_name_2;
56
57static struct GNUNET_GNSRECORD_Data *s_rd_2;
58
59static char *s_name_3;
60
61static struct GNUNET_GNSRECORD_Data *s_rd_3;
62
63
64/**
65 * Handle timeout.
66 *
67 * @param cls handle to use to re-connect.
68 */
69static void
70endbadly (void *cls)
71{
72 endbadly_task = NULL;
73 GNUNET_SCHEDULER_shutdown ();
74 res = 1;
75}
76
77
78static void
79end (void *cls)
80{
81 if (NULL != zi)
82 {
83 GNUNET_NAMESTORE_zone_iteration_stop (zi);
84 zi = NULL;
85 }
86 if (NULL != endbadly_task)
87 {
88 GNUNET_SCHEDULER_cancel (endbadly_task);
89 endbadly_task = NULL;
90 }
91 GNUNET_free (s_name_1);
92 GNUNET_free (s_name_2);
93 GNUNET_free (s_name_3);
94 if (s_rd_1 != NULL)
95 {
96 GNUNET_free_nz ((void *) s_rd_1->data);
97 GNUNET_free (s_rd_1);
98 }
99 if (s_rd_2 != NULL)
100 {
101 GNUNET_free_nz ((void *) s_rd_2->data);
102 GNUNET_free (s_rd_2);
103 }
104 if (s_rd_3 != NULL)
105 {
106 GNUNET_free_nz ((void *) s_rd_3->data);
107 GNUNET_free (s_rd_3);
108 }
109 if (nsh != NULL)
110 {
111 GNUNET_NAMESTORE_disconnect (nsh);
112 nsh = NULL;
113 }
114}
115
116
117static void
118fail_cb (void *cls)
119{
120 GNUNET_assert (0);
121 zi = NULL;
122}
123
124
125static void
126zone_proc (void *cls,
127 const struct GNUNET_IDENTITY_PrivateKey *zone,
128 const char *label,
129 unsigned int rd_count,
130 const struct GNUNET_GNSRECORD_Data *rd)
131{
132 int failed = GNUNET_NO;
133
134 GNUNET_assert (NULL != zone);
135 if (0 == GNUNET_memcmp (zone,
136 &privkey))
137 {
138 if (0 == strcmp (label, s_name_1))
139 {
140 if (rd_count == 1)
141 {
142 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
143 {
144 failed = GNUNET_YES;
145 GNUNET_break (0);
146 }
147 }
148 else
149 {
150 failed = GNUNET_YES;
151 GNUNET_break (0);
152 }
153 }
154 else if (0 == strcmp (label, s_name_2))
155 {
156 if (rd_count == 1)
157 {
158 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
159 {
160 failed = GNUNET_YES;
161 GNUNET_break (0);
162 }
163 }
164 else
165 {
166 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
167 "Received invalid record count\n");
168 failed = GNUNET_YES;
169 GNUNET_break (0);
170 }
171 }
172 else
173 {
174 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175 "Comparing result failed: got name `%s' for first zone\n",
176 label);
177 failed = GNUNET_YES;
178 GNUNET_break (0);
179 }
180 }
181 else if (0 == GNUNET_memcmp (zone, &privkey2))
182 {
183 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
184 "Received data for not requested zone\n");
185 failed = GNUNET_YES;
186 GNUNET_break (0);
187 }
188 else
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
191 "Received invalid zone\n");
192 failed = GNUNET_YES;
193 GNUNET_break (0);
194 }
195 if (failed == GNUNET_NO)
196 {
197 returned_records++;
198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
199 "Telling namestore to send the next result\n");
200 GNUNET_NAMESTORE_zone_iterator_next (zi,
201 1);
202 }
203 else
204 {
205 GNUNET_break (0);
206 res = 2;
207 GNUNET_SCHEDULER_shutdown ();
208 }
209}
210
211
212static void
213zone_proc_end (void *cls)
214{
215 zi = NULL;
216 GNUNET_break (2 == returned_records);
217 if (2 == returned_records)
218 {
219 res = 0; /* Last iteraterator callback, we are done */
220 }
221 else
222 {
223 res = 1;
224 }
225
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
227 "Received last result, iteration done after receing %u results\n",
228 returned_records);
229 GNUNET_SCHEDULER_shutdown ();
230}
231
232
233static void
234put_cont (void *cls,
235 int32_t success,
236 const char *emsg)
237{
238 static int c = 0;
239
240 if (success == GNUNET_OK)
241 {
242 c++;
243 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
244 "Created record %u \n", c);
245 }
246 else
247 {
248 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
249 "Failed to created records: `%s'\n",
250 emsg);
251 GNUNET_break (0);
252 res = 2;
253 GNUNET_SCHEDULER_shutdown ();
254 return;
255 }
256
257 if (c == 3)
258 {
259 res = 1;
260 returned_records = 0;
261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
262 "All records created, starting iteration over all zones \n");
263 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
264 &privkey,
265 &fail_cb,
266 NULL,
267 &zone_proc,
268 NULL,
269 &zone_proc_end,
270 NULL);
271 if (zi == NULL)
272 {
273 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
274 "Failed to create zone iterator\n");
275 GNUNET_break (0);
276 res = 2;
277 GNUNET_SCHEDULER_shutdown ();
278 return;
279 }
280 }
281}
282
283
284static struct GNUNET_GNSRECORD_Data *
285create_record (unsigned int count)
286{
287 struct GNUNET_GNSRECORD_Data *rd;
288
289 rd = GNUNET_new_array (count,
290 struct GNUNET_GNSRECORD_Data);
291 for (unsigned int c = 0; c < count; c++)
292 {
293 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
294 GNUNET_TIME_UNIT_HOURS).abs_value_us;
295 rd[c].record_type = TEST_RECORD_TYPE;
296 rd[c].data_size = 50;
297 rd[c].data = GNUNET_malloc (50);
298 rd[c].flags = 0;
299 memset ((char *) rd[c].data, 'a', 50);
300 }
301 return rd;
302}
303
304
305/**
306 * Callback called from the zone iterator when we iterate over
307 * the empty zone. Check that we got no records and then
308 * start the actual tests by filling the zone.
309 */
310static void
311empty_zone_proc (void *cls,
312 const struct GNUNET_IDENTITY_PrivateKey *zone,
313 const char *label,
314 unsigned int rd_count,
315 const struct GNUNET_GNSRECORD_Data *rd)
316{
317 GNUNET_assert (nsh == cls);
318 if (NULL != zone)
319 {
320 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
321 _ ("Expected empty zone but received zone private key\n"));
322 GNUNET_break (0);
323 res = 2;
324 GNUNET_SCHEDULER_shutdown ();
325 return;
326 }
327 if ((NULL != label) || (NULL != rd) || (0 != rd_count))
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
330 _ ("Expected no zone content but received data\n"));
331 GNUNET_break (0);
332 res = 2;
333 GNUNET_SCHEDULER_shutdown ();
334 return;
335 }
336 GNUNET_assert (0);
337}
338
339
340static void
341empty_zone_proc_end (void *cls)
342{
343 zi = NULL;
344 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
345 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
346 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
347 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
348 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
349 "Created record 1\n");
350 GNUNET_asprintf (&s_name_1,
351 "dummy1");
352 s_rd_1 = create_record (1);
353 GNUNET_NAMESTORE_records_store (nsh,
354 &privkey,
355 s_name_1,
356 1,
357 s_rd_1,
358 &put_cont,
359 NULL);
360
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362 "Created record 2 \n");
363 GNUNET_asprintf (&s_name_2,
364 "dummy2");
365 s_rd_2 = create_record (1);
366 GNUNET_NAMESTORE_records_store (nsh,
367 &privkey,
368 s_name_2,
369 1,
370 s_rd_2,
371 &put_cont,
372 NULL);
373
374 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
375 "Created record 3\n");
376
377 /* name in different zone */
378 GNUNET_asprintf (&s_name_3,
379 "dummy3");
380 s_rd_3 = create_record (1);
381 GNUNET_NAMESTORE_records_store (nsh,
382 &privkey2,
383 s_name_3,
384 1, s_rd_3,
385 &put_cont,
386 NULL);
387}
388
389
390static void
391run (void *cls,
392 const struct GNUNET_CONFIGURATION_Handle *cfg,
393 struct GNUNET_TESTING_Peer *peer)
394{
395 GNUNET_SCHEDULER_add_shutdown (&end,
396 NULL);
397 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
398 &endbadly,
399 NULL);
400 nsh = GNUNET_NAMESTORE_connect (cfg);
401 GNUNET_break (NULL != nsh);
402 /* first, iterate over empty namestore */
403 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
404 NULL,
405 &fail_cb,
406 NULL,
407 &empty_zone_proc,
408 nsh,
409 &empty_zone_proc_end,
410 nsh);
411 if (NULL == zi)
412 {
413 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
414 "Failed to create zone iterator\n");
415 GNUNET_break (0);
416 GNUNET_SCHEDULER_shutdown ();
417 }
418}
419
420
421#include "test_common.c"
422
423
424int
425main (int argc, char *argv[])
426{
427 const char *plugin_name;
428 char *cfg_name;
429
430 SETUP_CFG (plugin_name, cfg_name);
431 res = 1;
432 if (0 !=
433 GNUNET_TESTING_peer_run (
434 "test-namestore-api-zone-iteration-specific-zone",
435 cfg_name,
436 &run,
437 NULL))
438 {
439 res = 1;
440 }
441 GNUNET_DISK_purge_cfg_dir (cfg_name,
442 "GNUNET_TEST_HOME");
443 GNUNET_free (cfg_name);
444 return res;
445}
446
447
448/* end of test_namestore_api_zone_iteration_specific_zone.c */
diff --git a/src/namestore/test_namestore_api_zone_iteration_stop.c b/src/namestore/test_namestore_api_zone_iteration_stop.c
deleted file mode 100644
index 71b36ba09..000000000
--- a/src/namestore/test_namestore_api_zone_iteration_stop.c
+++ /dev/null
@@ -1,449 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 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 namestore/test_namestore_api_zone_iteration_stop.c
22 * @brief testcase for zone iteration functionality: stop iterating of zones
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "namestore.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
33#define WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2)
34
35static struct GNUNET_NAMESTORE_Handle *nsh;
36
37static struct GNUNET_IDENTITY_PrivateKey privkey;
38
39static struct GNUNET_IDENTITY_PrivateKey privkey2;
40
41static struct GNUNET_NAMESTORE_ZoneIterator *zi;
42
43static int res;
44
45static int returned_records;
46
47static char *s_name_1;
48
49static struct GNUNET_GNSRECORD_Data *s_rd_1;
50
51static char *s_name_2;
52
53static struct GNUNET_GNSRECORD_Data *s_rd_2;
54
55static char *s_name_3;
56
57static struct GNUNET_GNSRECORD_Data *s_rd_3;
58
59
60/**
61 * Re-establish the connection to the service.
62 *
63 * @param cls handle to use to re-connect.
64 */
65static void
66end (void *cls)
67{
68 if (NULL != zi)
69 {
70 GNUNET_NAMESTORE_zone_iteration_stop (zi);
71 zi = NULL;
72 }
73 if (nsh != NULL)
74 {
75 GNUNET_NAMESTORE_disconnect (nsh);
76 nsh = NULL;
77 }
78 GNUNET_free (s_name_1);
79 GNUNET_free (s_name_2);
80 GNUNET_free (s_name_3);
81 if (s_rd_1 != NULL)
82 {
83 GNUNET_free_nz ((void *) s_rd_1->data);
84 GNUNET_free (s_rd_1);
85 }
86 if (s_rd_2 != NULL)
87 {
88 GNUNET_free_nz ((void *) s_rd_2->data);
89 GNUNET_free (s_rd_2);
90 }
91 if (s_rd_3 != NULL)
92 {
93 GNUNET_free_nz ((void *) s_rd_3->data);
94 GNUNET_free (s_rd_3);
95 }
96}
97
98
99static void
100delayed_end (void *cls)
101{
102 GNUNET_SCHEDULER_shutdown ();
103}
104
105
106static void
107fail_cb (void *cls)
108{
109 GNUNET_assert (0);
110}
111
112
113static void
114zone_proc (void *cls,
115 const struct GNUNET_IDENTITY_PrivateKey *zone,
116 const char *label,
117 unsigned int rd_count,
118 const struct GNUNET_GNSRECORD_Data *rd)
119{
120 int failed = GNUNET_NO;
121
122 GNUNET_assert (NULL != zone);
123 if (0 == GNUNET_memcmp (zone, &privkey))
124 {
125 if (0 == strcmp (label, s_name_1))
126 {
127 if (rd_count == 1)
128 {
129 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_1))
130 {
131 failed = GNUNET_YES;
132 GNUNET_break (0);
133 }
134 }
135 else
136 {
137 failed = GNUNET_YES;
138 GNUNET_break (0);
139 }
140 }
141 else if (0 == strcmp (label, s_name_2))
142 {
143 if (rd_count == 1)
144 {
145 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_2))
146 {
147 failed = GNUNET_YES;
148 GNUNET_break (0);
149 }
150 }
151 else
152 {
153 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
154 "Received invalid record count\n");
155 failed = GNUNET_YES;
156 GNUNET_break (0);
157 }
158 }
159 else
160 {
161 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162 "Comparing result failed: got name `%s' for first zone\n",
163 label);
164 failed = GNUNET_YES;
165 GNUNET_break (0);
166 }
167 }
168 else if (0 == GNUNET_memcmp (zone, &privkey2))
169 {
170 if (0 == strcmp (label, s_name_3))
171 {
172 if (rd_count == 1)
173 {
174 if (GNUNET_YES != GNUNET_GNSRECORD_records_cmp (rd, s_rd_3))
175 {
176 failed = GNUNET_YES;
177 GNUNET_break (0);
178 }
179 }
180 else
181 {
182 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
183 "Received invalid record count\n");
184 failed = GNUNET_YES;
185 GNUNET_break (0);
186 }
187 }
188 else
189 {
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191 "Comparing result failed: got name `%s' for first zone\n",
192 label);
193 failed = GNUNET_YES;
194 GNUNET_break (0);
195 }
196 }
197 else
198 {
199 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200 "Received invalid zone\n");
201 failed = GNUNET_YES;
202 GNUNET_break (0);
203 }
204 if (failed == GNUNET_NO)
205 {
206 if (1 == returned_records)
207 {
208 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
209 "Telling namestore to stop zone iteration\n");
210 GNUNET_NAMESTORE_zone_iteration_stop (zi);
211 zi = NULL;
212 res = 0;
213 GNUNET_SCHEDULER_add_delayed (WAIT,
214 &delayed_end,
215 NULL);
216 return;
217 }
218 returned_records++;
219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
220 "Telling namestore to send the next result\n");
221 GNUNET_NAMESTORE_zone_iterator_next (zi,
222 1);
223 }
224 else
225 {
226 GNUNET_break (0);
227 GNUNET_SCHEDULER_shutdown ();
228 }
229}
230
231
232static void
233zone_proc_end (void *cls)
234{
235 GNUNET_break (1 <= returned_records);
236 if (1 >= returned_records)
237 res = 1; /* Last iteraterator callback, we are done */
238 else
239 res = 0;
240 zi = NULL;
241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
242 "Received last result, iteration done after receing %u results\n",
243 returned_records);
244 GNUNET_SCHEDULER_add_now (&end, NULL);
245}
246
247
248static void
249put_cont (void *cls, int32_t success, const char *emsg)
250{
251 static int c = 0;
252
253 if (success == GNUNET_OK)
254 {
255 c++;
256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Created record %u \n", c);
257 }
258 else
259 {
260 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to created records: `%s'\n",
261 emsg);
262 GNUNET_break (0);
263 GNUNET_SCHEDULER_shutdown ();
264 return;
265 }
266
267 if (c == 3)
268 {
269 res = 1;
270 returned_records = 0;
271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
272 "All records created, starting iteration over all zones \n");
273 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
274 NULL,
275 &fail_cb,
276 NULL,
277 &zone_proc,
278 NULL,
279 &zone_proc_end,
280 NULL);
281 if (zi == NULL)
282 {
283 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
284 "Failed to create zone iterator\n");
285 GNUNET_break (0);
286 GNUNET_SCHEDULER_shutdown ();
287 return;
288 }
289 }
290}
291
292
293static struct GNUNET_GNSRECORD_Data *
294create_record (unsigned int count)
295{
296 struct GNUNET_GNSRECORD_Data *rd;
297
298 rd = GNUNET_new_array (count,
299 struct GNUNET_GNSRECORD_Data);
300 for (unsigned int c = 0; c < count; c++)
301 {
302 rd[c].expiration_time = GNUNET_TIME_relative_to_absolute (
303 GNUNET_TIME_UNIT_HOURS).abs_value_us;
304 rd[c].record_type = TEST_RECORD_TYPE;
305 rd[c].data_size = 50;
306 rd[c].data = GNUNET_malloc (50);
307 rd[c].flags = 0;
308 memset ((char *) rd[c].data, 'a', 50);
309 }
310 return rd;
311}
312
313
314/**
315 * Callback called from the zone iterator when we iterate over
316 * the empty zone. Check that we got no records and then
317 * start the actual tests by filling the zone.
318 */
319static void
320empty_zone_proc (void *cls,
321 const struct GNUNET_IDENTITY_PrivateKey *zone,
322 const char *label,
323 unsigned int rd_count,
324 const struct GNUNET_GNSRECORD_Data *rd)
325{
326 GNUNET_assert (nsh == cls);
327 if (NULL != zone)
328 {
329 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
330 _ ("Expected empty zone but received zone private key\n"));
331 GNUNET_break (0);
332 GNUNET_SCHEDULER_shutdown ();
333 return;
334 }
335 if ((NULL != label) || (NULL != rd) || (0 != rd_count))
336 {
337 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
338 _ ("Expected no zone content but received data\n"));
339 GNUNET_break (0);
340 GNUNET_SCHEDULER_shutdown ();
341 return;
342 }
343 GNUNET_assert (0);
344}
345
346
347static void
348empty_zone_proc_end (void *cls)
349{
350 GNUNET_assert (nsh == cls);
351 zi = NULL;
352 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
353 privkey2.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
354 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
355 GNUNET_CRYPTO_ecdsa_key_create (&privkey2.ecdsa_key);
356
357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
358 "Created record 1\n");
359
360 GNUNET_asprintf (&s_name_1,
361 "dummy1");
362 s_rd_1 = create_record (1);
363 GNUNET_NAMESTORE_records_store (nsh,
364 &privkey, s_name_1,
365 1, s_rd_1, &put_cont, NULL);
366
367 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
368 "Created record 2 \n");
369 GNUNET_asprintf (&s_name_2,
370 "dummy2");
371 s_rd_2 = create_record (1);
372 GNUNET_NAMESTORE_records_store (nsh,
373 &privkey,
374 s_name_2,
375 1,
376 s_rd_2,
377 &put_cont, NULL);
378
379 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
380 "Created record 3\n");
381
382 /* name in different zone */
383 GNUNET_asprintf (&s_name_3, "dummy3");
384 s_rd_3 = create_record (1);
385 GNUNET_NAMESTORE_records_store (nsh,
386 &privkey2,
387 s_name_3,
388 1,
389 s_rd_3,
390 &put_cont, NULL);
391}
392
393
394static void
395run (void *cls,
396 const struct GNUNET_CONFIGURATION_Handle *cfg,
397 struct GNUNET_TESTING_Peer *peer)
398{
399 nsh = GNUNET_NAMESTORE_connect (cfg);
400 GNUNET_break (NULL != nsh);
401 GNUNET_SCHEDULER_add_shutdown (&end,
402 NULL);
403 /* first, iterate over empty namestore */
404 zi = GNUNET_NAMESTORE_zone_iteration_start (nsh,
405 NULL,
406 &fail_cb,
407 NULL,
408 &empty_zone_proc,
409 nsh,
410 &empty_zone_proc_end,
411 nsh);
412 if (NULL == zi)
413 {
414 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
415 "Failed to create zone iterator\n");
416 GNUNET_break (0);
417 GNUNET_SCHEDULER_shutdown ();
418 }
419}
420
421
422#include "test_common.c"
423
424
425int
426main (int argc, char *argv[])
427{
428 const char *plugin_name;
429 char *cfg_name;
430
431 SETUP_CFG (plugin_name, cfg_name);
432 res = 1;
433 if (0 !=
434 GNUNET_TESTING_peer_run ("test-namestore-api-zone-iteration-stop",
435 cfg_name,
436 &run,
437 NULL))
438 {
439 res = 1;
440 }
441 GNUNET_DISK_purge_cfg_dir (cfg_name,
442 "GNUNET_TEST_HOME");
443 GNUNET_free (cfg_name);
444
445 return res;
446}
447
448
449/* end of test_namestore_api_zone_iteration_stop.c */
diff --git a/src/namestore/test_namestore_api_zone_to_name.c b/src/namestore/test_namestore_api_zone_to_name.c
deleted file mode 100644
index 1e2f8248b..000000000
--- a/src/namestore/test_namestore_api_zone_to_name.c
+++ /dev/null
@@ -1,266 +0,0 @@
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009 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 namestore/test_namestore_api_zone_to_name.c
22 * @brief testcase for zone to name translation
23 */
24#include "platform.h"
25#include "gnunet_namestore_service.h"
26#include "gnunet_testing_lib.h"
27#include "namestore.h"
28#include "gnunet_dnsparser_lib.h"
29
30#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
31
32#define RECORDS 5
33
34#define TEST_RECORD_DATALEN 123
35
36#define TEST_RECORD_DATA 'a'
37
38#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 100)
39
40
41static struct GNUNET_NAMESTORE_Handle *nsh;
42
43static struct GNUNET_SCHEDULER_Task *endbadly_task;
44
45static struct GNUNET_IDENTITY_PrivateKey privkey;
46
47static struct GNUNET_IDENTITY_PublicKey pubkey;
48
49static struct GNUNET_IDENTITY_PublicKey s_zone_value;
50
51static char *s_name;
52
53static int res;
54
55static struct GNUNET_NAMESTORE_QueueEntry *qe;
56
57
58/**
59 * Re-establish the connection to the service.
60 *
61 * @param cls handle to use to re-connect.
62 */
63static void
64endbadly (void *cls)
65{
66 (void) cls;
67 GNUNET_SCHEDULER_shutdown ();
68 res = 1;
69}
70
71
72static void
73end (void *cls)
74{
75 if (NULL != qe)
76 {
77 GNUNET_NAMESTORE_cancel (qe);
78 qe = NULL;
79 }
80 if (NULL != endbadly_task)
81 {
82 GNUNET_SCHEDULER_cancel (endbadly_task);
83 endbadly_task = NULL;
84 }
85 if (NULL != nsh)
86 {
87 GNUNET_NAMESTORE_disconnect (nsh);
88 nsh = NULL;
89 }
90}
91
92
93static void
94zone_to_name_proc (void *cls,
95 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
96 const char *n,
97 unsigned int rd_count,
98 const struct GNUNET_GNSRECORD_Data *rd)
99{
100 int fail = GNUNET_NO;
101
102 qe = NULL;
103 if ((NULL == zone_key) &&
104 (NULL == n) &&
105 (0 == rd_count) &&
106 (NULL == rd))
107 {
108 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
109 "No result found\n");
110 res = 1;
111 }
112 else
113 {
114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
115 "Result found: `%s'\n",
116 n);
117 if ((NULL == n) ||
118 (0 != strcmp (n,
119 s_name)))
120 {
121 fail = GNUNET_YES;
122 GNUNET_break (0);
123 }
124 if (1 != rd_count)
125 {
126 fail = GNUNET_YES;
127 GNUNET_break (0);
128 }
129 if ((NULL == zone_key) ||
130 (0 != GNUNET_memcmp (zone_key,
131 &privkey)))
132 {
133 fail = GNUNET_YES;
134 GNUNET_break (0);
135 }
136 if (fail == GNUNET_NO)
137 res = 0;
138 else
139 res = 1;
140 }
141 GNUNET_SCHEDULER_add_now (&end,
142 NULL);
143}
144
145
146static void
147error_cb (void *cls)
148{
149 (void) cls;
150 qe = NULL;
151 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
152 "Not found!\n");
153 GNUNET_SCHEDULER_shutdown ();
154 res = 2;
155}
156
157
158static void
159put_cont (void *cls,
160 int32_t success,
161 const char *emsg)
162{
163 char *name = cls;
164
165 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
166 "Name store added record for `%s': %s\n",
167 name,
168 (success == GNUNET_OK) ? "SUCCESS" : emsg);
169 if (success == GNUNET_OK)
170 {
171 res = 0;
172
173 qe = GNUNET_NAMESTORE_zone_to_name (nsh,
174 &privkey,
175 &s_zone_value,
176 &error_cb,
177 NULL,
178 &zone_to_name_proc,
179 NULL);
180 }
181 else
182 {
183 res = 1;
184 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
185 "Failed to put records for name `%s'\n",
186 name);
187 GNUNET_SCHEDULER_add_now (&end,
188 NULL);
189 }
190}
191
192
193static void
194run (void *cls,
195 const struct GNUNET_CONFIGURATION_Handle *cfg,
196 struct GNUNET_TESTING_Peer *peer)
197{
198 (void) cls;
199 (void) peer;
200 endbadly_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
201 &endbadly,
202 NULL);
203 GNUNET_SCHEDULER_add_shutdown (&end,
204 NULL);
205 GNUNET_asprintf (&s_name, "dummy");
206 privkey.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
207 GNUNET_CRYPTO_ecdsa_key_create (&privkey.ecdsa_key);
208 /* get public key */
209 GNUNET_IDENTITY_key_get_public (&privkey,
210 &pubkey);
211
212 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK,
213 &s_zone_value,
214 sizeof(s_zone_value));
215 s_zone_value.type = htonl (GNUNET_GNSRECORD_TYPE_PKEY);
216 {
217 struct GNUNET_GNSRECORD_Data rd;
218
219 rd.expiration_time = GNUNET_TIME_UNIT_HOURS.rel_value_us;
220 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
221 rd.data_size = sizeof (s_zone_value.ecdsa_key);
222 rd.data = &s_zone_value.ecdsa_key;
223 rd.flags = GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
224
225 nsh = GNUNET_NAMESTORE_connect (cfg);
226 GNUNET_break (NULL != nsh);
227 GNUNET_NAMESTORE_records_store (nsh,
228 &privkey,
229 s_name,
230 1,
231 &rd,
232 &put_cont,
233 s_name);
234 }
235}
236
237
238#include "test_common.c"
239
240
241int
242main (int argc,
243 char *argv[])
244{
245 const char *plugin_name;
246 char *cfg_name;
247
248 (void) argc;
249 SETUP_CFG (plugin_name, cfg_name);
250 res = 1;
251 if (0 !=
252 GNUNET_TESTING_peer_run ("test-namestore-api-zone-to-name",
253 cfg_name,
254 &run,
255 NULL))
256 {
257 res = 1;
258 }
259 GNUNET_DISK_purge_cfg_dir (cfg_name,
260 "GNUNET_TEST_HOME");
261 GNUNET_free (cfg_name);
262 return res;
263}
264
265
266/* end of test_namestore_api_zone_to_name.c */
diff --git a/src/namestore/test_namestore_delete.sh b/src/namestore/test_namestore_delete.sh
deleted file mode 100755
index b861a4bc0..000000000
--- a/src/namestore/test_namestore_delete.sh
+++ /dev/null
@@ -1,68 +0,0 @@
1#!/bin/bash
2CONFIGURATION="test_namestore_api.conf"
3trap "gnunet-arm -e -c $CONFIGURATION" SIGINT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME`
18TEST_DOMAIN_PLUS="www.gnu"
19TEST_DOMAIN_DNS="www3.gnu"
20TEST_IP_PLUS="127.0.0.1"
21TEST_IP_DNS="131.159.74.67"
22TEST_RECORD_CNAME_SERVER="server"
23TEST_RECORD_CNAME_PLUS="server.+"
24TEST_RECORD_CNAME_DNS="gnunet.org"
25TEST_RECORD_NAME_SERVER="server"
26TEST_RECORD_NAME_PLUS="www"
27TEST_RECORD_NAME_DNS="www3"
28which timeout &> /dev/null && DO_TIMEOUT="timeout 5"
29
30function start_peer
31{
32 gnunet-arm -s -c $CONFIGURATION
33 gnunet-identity -C testego -c $CONFIGURATION
34}
35
36function stop_peer
37{
38 gnunet-identity -D testego -c $CONFIGURATION
39 gnunet-arm -e -c $CONFIGURATION
40}
41
42
43start_peer
44# Create a public record
45gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION
46# Delete record
47gnunet-namestore -p -z testego -d -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION
48# List all records
49OUTPUT=`gnunet-namestore -p -z testego -D`
50FOUND_IP=false
51FOUND_NAME=false
52for LINE in $OUTPUT ;
53 do
54 if echo "$LINE" | grep -q "$TEST_RECORD_NAME_DNS"; then
55 FOUND_NAME=true;
56 fi
57 if echo "$LINE" | grep -q "$TEST_IP_PLUS"; then
58 FOUND_IP=true;
59 fi
60 done
61stop_peer
62
63
64if [ $FOUND_IP = true ]
65then
66 echo "FAIL: Delete name in namestore: IP returned"
67 exit 1
68fi
diff --git a/src/namestore/test_namestore_lookup.sh b/src/namestore/test_namestore_lookup.sh
deleted file mode 100755
index 1c96e102a..000000000
--- a/src/namestore/test_namestore_lookup.sh
+++ /dev/null
@@ -1,63 +0,0 @@
1#!/bin/bash
2CONFIGURATION="test_namestore_api.conf"
3trap "gnunet-arm -e -c $CONFIGURATION" SIGINT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME`
18TEST_IP_PLUS="127.0.0.1"
19TEST_RECORD_NAME_DNS="www3"
20which timeout &> /dev/null && DO_TIMEOUT="timeout 5"
21
22# start peer
23gnunet-arm -s -c $CONFIGURATION
24gnunet-identity -C testego -c $CONFIGURATION
25
26# Create a public record
27gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION
28NAMESTORE_RES=$?
29# Lookup specific name
30OUTPUT=`gnunet-namestore -p -z testego -n $TEST_RECORD_NAME_DNS -D`
31
32
33FOUND_IP=false
34FOUND_NAME=false
35for LINE in $OUTPUT ;
36 do
37 if echo "$LINE" | grep -q "$TEST_RECORD_NAME_DNS"; then
38 FOUND_NAME=true;
39 #echo $FOUND_NAME
40 fi
41 if echo "$LINE" | grep -q "$TEST_IP_PLUS"; then
42 FOUND_IP=true;
43 #echo $FOUND_IP
44 fi
45done
46# stop peer
47gnunet-identity -D testego -c $CONFIGURATION
48gnunet-arm -e -c $CONFIGURATION
49
50
51if [ $FOUND_NAME = true -a $FOUND_IP = true ]
52then
53 echo "PASS: Lookup name in namestore"
54 exit 0
55elif [ $FOUND_NAME = false ]
56then
57 echo "FAIL: Lookup name in namestore: name not returned"
58 exit 1
59elif [ $FOUND_IP = false ]
60then
61 echo "FAIL: Lookup name in namestore: IP not returned"
62 exit 1
63fi
diff --git a/src/namestore/test_namestore_put.sh b/src/namestore/test_namestore_put.sh
deleted file mode 100755
index eaf7d44b4..000000000
--- a/src/namestore/test_namestore_put.sh
+++ /dev/null
@@ -1,55 +0,0 @@
1#!/bin/bash
2CONFIGURATION="test_namestore_api.conf"
3trap "gnunet-arm -e -c $CONFIGURATION" SIGINT
4
5LOCATION=$(which gnunet-config)
6if [ -z $LOCATION ]
7then
8 LOCATION="gnunet-config"
9fi
10$LOCATION --version 1> /dev/null
11if test $? != 0
12then
13 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
14 exit 77
15fi
16
17rm -rf `$LOCATION -c $CONFIGURATION -s PATHS -o GNUNET_HOME`
18TEST_DOMAIN_PLUS="www.gnu"
19TEST_DOMAIN_DNS="www3.gnu"
20TEST_IP_PLUS="127.0.0.1"
21TEST_IP_DNS="131.159.74.67"
22TEST_RECORD_CNAME_SERVER="server"
23TEST_RECORD_CNAME_PLUS="server.+"
24TEST_RECORD_CNAME_DNS="gnunet.org"
25TEST_RECORD_NAME_SERVER="server"
26TEST_RECORD_NAME_PLUS="www"
27TEST_RECORD_NAME_DNS="www3"
28which timeout &> /dev/null && DO_TIMEOUT="timeout 5"
29
30function start_peer
31{
32 gnunet-arm -s -c $CONFIGURATION
33 gnunet-identity -C testego -c $CONFIGURATION
34}
35
36function stop_peer
37{
38 gnunet-identity -D testego -c $CONFIGURATION
39 gnunet-arm -e -c $CONFIGURATION
40}
41
42
43start_peer
44# Create a public record
45gnunet-namestore -p -z testego -a -n $TEST_RECORD_NAME_DNS -t A -V $TEST_IP_PLUS -e never -c $CONFIGURATION
46NAMESTORE_RES=$?
47stop_peer
48
49if [ $NAMESTORE_RES = 0 ]
50then
51 echo "PASS: Creating name in namestore"
52else
53 echo "FAIL: Creating name in namestore failed with $NAMESTORE_RES."
54 exit 1
55fi
diff --git a/src/namestore/test_namestore_put_multiple.sh b/src/namestore/test_namestore_put_multiple.sh
deleted file mode 100644
index f33fb1c3a..000000000
--- a/src/namestore/test_namestore_put_multiple.sh
+++ /dev/null
@@ -1,123 +0,0 @@
1#!/bin/bash
2
3# Check for required packages
4if ! [ -x "$(command -v gnunet-namestore)" ]; then
5 echo 'bind/named is not installed' >&2
6 exit 1
7fi
8
9# Check if gnunet is running
10gnunet-arm -I 2&>1 /dev/null
11ret=$?
12if [ 0 -ne $ret ]; then
13 echo 'gnunet services are not running'
14 exit 1
15fi
16
17## GNUNET part
18# Check if identity exists and deletes and readds it to get rid of entries in zone
19gnunet-identity -d | grep randomtestingid 2>&1 /dev/null
20ret=$?
21
22if [ 0 -ne $ret ]; then
23 gnunet-identity -D randomtestingid
24 gnunet-identity -C randomtestingid
25fi
26
27function minimize_ttl {
28 ttl=10000000
29 arr=$1
30 # parse each element and update ttl to smallest one
31 for i in "${arr[@]}"
32 do
33 currttl=$(echo -n "$i" | cut -d' ' -f1)
34 if [ "$currttl" -lt "$ttl" ]
35 then
36 ttl=$currttl
37 fi
38
39 done
40 echo "$ttl"
41}
42
43function get_record_type {
44 arr=$1
45 typ=$(echo -n "${arr[0]}" | cut -d' ' -f2)
46 echo "$typ"
47}
48
49function get_value {
50 arr=$1
51 val=$(echo -n "${arr[0]}" | cut -d' ' -f4-)
52 echo "$val"
53}
54
55function testing {
56 label=$1
57 records=$2
58 recordstring=""
59 typ=$(get_record_type "${records[@]}")
60 for i in "${records[@]}"
61 do
62 recordstring+="-R $i"
63 done
64 #echo "$recordstring"
65 gnunet-namestore -z randomtestingid -n "$label" "$recordstring" 2>&1 /dev/null
66 if [ 0 -ne $ret ]; then
67 echo "failed to add record $label: $recordstring"
68 fi
69 gnunet-gns -t "$typ" -u foo2.randomtestingid 2>&1 /dev/null
70 if [ 0 -ne $ret ]; then
71 echo "record $label could not be found"
72 fi
73}
74
75# TEST CASES
76# 1
77echo "Testing adding of single A record with -R"
78testing test1 "${arr[@]}"
79# 2
80echo "Testing adding of multiple A records with -R"
81declare -a arr=('1200 A n 127.0.0.1' '2400 A n 127.0.0.2')
82testing test2 "${arr[@]}"
83# 3
84echo "Testing adding of multiple different records with -R"
85declare -a arr=('1200 A n 127.0.0.1' '2400 AAAA n 2002::')
86testing test3 "${arr[@]}"
87# 4
88echo "Testing adding of single GNS2DNS record with -R"
89declare -a arr=('86400 GNS2DNS n gnu.org@127.0.0.1')
90testing test4 "${arr[@]}"
91# 5
92echo "Testing adding of single GNS2DNS shadow record with -R"
93declare -a arr=('86409 GNS2DNS s gnu.org@127.0.0.250')
94testing test5 "${arr[@]}"
95# 6
96echo "Testing adding of multiple GNS2DNS record with -R"
97declare -a arr=('1 GNS2DNS n gnunet.org@127.0.0.1' '3600 GNS2DNS s gnunet.org@127.0.0.2')
98testing test6 "${arr[@]}"
99val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
100if [[ $val == *"127.0.0.1"* ]]; then
101 echo "shadow!"
102fi
103echo "Sleeping to let record expire"
104sleep 5
105val=$(gnunet-gns -t GNS2DNS -u test6.randomtestingid)
106if [[ $val == *"127.0.0.2"* ]]; then
107 echo "no shadow!"
108fi
109# 7
110echo "Testing adding MX record with -R"
111declare -a arr=('3600 MX n 10,mail')
112testing test7 "${arr[@]}"
113# 8
114echo "Testing adding TXT record with -R"
115declare -a arr=('3600 TXT n Pretty_Unicorns')
116testing test8 "${arr[@]}"
117# 8
118echo "Testing adding TXT record with -R"
119declare -a arr=('3600 SRV n _autodiscover_old._tcp.bfh.ch.')
120testing test8 "${arr[@]}"
121
122# CLEANUP
123gnunet-identity -D randomtestingid
diff --git a/src/namestore/test_plugin_namestore.c b/src/namestore/test_plugin_namestore.c
deleted file mode 100644
index baea0e444..000000000
--- a/src/namestore/test_plugin_namestore.c
+++ /dev/null
@@ -1,205 +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 namestore/test_plugin_namestore.c
22 * @brief Test for the namestore plugins
23 * @author Christian Grothoff
24 */
25#include "platform.h"
26#include "gnunet_util_lib.h"
27#include "gnunet_namestore_plugin.h"
28#include "gnunet_testing_lib.h"
29#include "gnunet_dnsparser_lib.h"
30
31#define TEST_RECORD_TYPE GNUNET_DNSPARSER_TYPE_TXT
32
33static int ok;
34
35/**
36 * Name of plugin under test.
37 */
38static const char *plugin_name;
39
40
41/**
42 * Function called when the service shuts down. Unloads our namestore
43 * plugin.
44 *
45 * @param api api to unload
46 */
47static void
48unload_plugin (struct GNUNET_NAMESTORE_PluginFunctions *api)
49{
50 char *libname;
51
52 GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name);
53 GNUNET_break (NULL == GNUNET_PLUGIN_unload (libname, api));
54 GNUNET_free (libname);
55}
56
57
58/**
59 * Load the namestore plugin.
60 *
61 * @param cfg configuration to pass
62 * @return NULL on error
63 */
64static struct GNUNET_NAMESTORE_PluginFunctions *
65load_plugin (const struct GNUNET_CONFIGURATION_Handle *cfg)
66{
67 struct GNUNET_NAMESTORE_PluginFunctions *ret;
68 char *libname;
69
70 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
71 _ ("Loading `%s' namestore plugin\n"),
72 plugin_name);
73 GNUNET_asprintf (&libname, "libgnunet_plugin_namestore_%s", plugin_name);
74 if (NULL == (ret = GNUNET_PLUGIN_load (libname, (void *) cfg)))
75 {
76 fprintf (stderr, "Failed to load plugin `%s'!\n", plugin_name);
77 GNUNET_free (libname);
78 return NULL;
79 }
80 GNUNET_free (libname);
81 return ret;
82}
83
84
85static void
86test_record (void *cls,
87 uint64_t seq,
88 const struct GNUNET_IDENTITY_PrivateKey *private_key,
89 const char *label,
90 unsigned int rd_count,
91 const struct GNUNET_GNSRECORD_Data *rd)
92{
93 int *idp = cls;
94 int id = *idp;
95 struct GNUNET_IDENTITY_PrivateKey tzone_private_key;
96 char tname[64];
97 unsigned int trd_count = 1 + (id % 1024);
98
99 GNUNET_snprintf (tname, sizeof(tname), "a%u", (unsigned int) id);
100 GNUNET_assert (trd_count == rd_count);
101 for (unsigned int i = 0; i < trd_count; i++)
102 {
103 GNUNET_assert (rd[i].data_size == id % 10);
104 GNUNET_assert (0 == memcmp ("Hello World", rd[i].data, id % 10));
105 GNUNET_assert (rd[i].record_type == TEST_RECORD_TYPE);
106 GNUNET_assert (rd[i].flags == 0);
107 }
108 memset (&tzone_private_key, (id % 241), sizeof(tzone_private_key));
109 GNUNET_assert (0 == strcmp (label, tname));
110 GNUNET_assert (0 == GNUNET_memcmp (&tzone_private_key, private_key));
111}
112
113
114static void
115get_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id)
116{
117 GNUNET_assert (
118 GNUNET_OK ==
119 nsp->iterate_records (nsp->cls, NULL, 0, 1, &test_record, &id));
120}
121
122
123static void
124put_record (struct GNUNET_NAMESTORE_PluginFunctions *nsp, int id)
125{
126 struct GNUNET_IDENTITY_PrivateKey zone_private_key;
127 char label[64];
128 unsigned int rd_count = 1 + (id % 1024);
129 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
130 struct GNUNET_CRYPTO_EcdsaSignature signature;
131
132 GNUNET_snprintf (label, sizeof(label), "a%u", (unsigned int) id);
133 for (unsigned int i = 0; i < rd_count; i++)
134 {
135 rd[i].data = "Hello World";
136 rd[i].data_size = id % 10;
137 rd[i].expiration_time =
138 GNUNET_TIME_relative_to_absolute (GNUNET_TIME_UNIT_MINUTES).abs_value_us;
139 rd[i].record_type = TEST_RECORD_TYPE;
140 rd[i].flags = 0;
141 }
142 memset (&zone_private_key, (id % 241), sizeof(zone_private_key));
143 memset (&signature, (id % 243), sizeof(signature));
144 GNUNET_assert (
145 GNUNET_OK ==
146 nsp->store_records (nsp->cls, &zone_private_key, label, rd_count, rd));
147}
148
149
150static void
151run (void *cls,
152 char *const *args,
153 const char *cfgfile,
154 const struct GNUNET_CONFIGURATION_Handle *cfg)
155{
156 struct GNUNET_NAMESTORE_PluginFunctions *nsp;
157
158 ok = 0;
159 nsp = load_plugin (cfg);
160 if (NULL == nsp)
161 {
162 fprintf (
163 stderr,
164 "%s",
165 "Failed to initialize namestore. Database likely not setup, skipping test.\n");
166 return;
167 }
168 put_record (nsp, 1);
169 get_record (nsp, 1);
170#ifndef DARWIN // #5582
171 unload_plugin (nsp);
172#endif
173}
174
175
176int
177main (int argc, char *argv[])
178{
179 char cfg_name[PATH_MAX];
180 char *const xargv[] = { "test-plugin-namestore", "-c", cfg_name, NULL };
181 struct GNUNET_GETOPT_CommandLineOption options[] =
182 { GNUNET_GETOPT_OPTION_END };
183
184 GNUNET_log_setup ("test-plugin-namestore", "WARNING", NULL);
185 plugin_name = GNUNET_TESTING_get_testname_from_underscore (argv[0]);
186 GNUNET_snprintf (cfg_name,
187 sizeof(cfg_name),
188 "test_plugin_namestore_%s.conf",
189 plugin_name);
190 GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP");
191 GNUNET_PROGRAM_run ((sizeof(xargv) / sizeof(char *)) - 1,
192 xargv,
193 "test-plugin-namestore",
194 "nohelp",
195 options,
196 &run,
197 NULL);
198 GNUNET_DISK_purge_cfg_dir (cfg_name, "GNUNET_TMP");
199 if (ok != 0)
200 fprintf (stderr, "Missed some testcases: %d\n", ok);
201 return ok;
202}
203
204
205/* end of test_plugin_namestore.c */
diff --git a/src/namestore/test_plugin_namestore_flat.conf b/src/namestore/test_plugin_namestore_flat.conf
deleted file mode 100644
index 5c632f0d1..000000000
--- a/src/namestore/test_plugin_namestore_flat.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[namestore-flat]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-flat/flatdb
diff --git a/src/namestore/test_plugin_namestore_postgres.conf b/src/namestore/test_plugin_namestore_postgres.conf
deleted file mode 100644
index 2ce8a7792..000000000
--- a/src/namestore/test_plugin_namestore_postgres.conf
+++ /dev/null
@@ -1,3 +0,0 @@
1[namestore-postgres]
2CONFIG = connect_timeout=10 dbname=gnunetcheck
3TEMPORARY_TABLE = YES
diff --git a/src/namestore/test_plugin_namestore_sqlite.conf b/src/namestore/test_plugin_namestore_sqlite.conf
deleted file mode 100644
index 24eecd286..000000000
--- a/src/namestore/test_plugin_namestore_sqlite.conf
+++ /dev/null
@@ -1,2 +0,0 @@
1[namestore-sqlite]
2FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db
diff --git a/src/namestore/test_plugin_rest_namestore.sh b/src/namestore/test_plugin_rest_namestore.sh
deleted file mode 100755
index 50b3c8c12..000000000
--- a/src/namestore/test_plugin_rest_namestore.sh
+++ /dev/null
@@ -1,135 +0,0 @@
1#!/bin/sh
2trap "gnunet-arm -e -c test_gns_lookup.conf" SIGINT
3
4LOCATION=$(which gnunet-config)
5if [ -z $LOCATION ]
6then
7 LOCATION="gnunet-config"
8fi
9$LOCATION --version 1> /dev/null
10if test $? != 0
11then
12 echo "GNUnet command line tools cannot be found, check environmental variables PATH and GNUNET_PREFIX"
13 exit 77
14fi
15
16rm -rf `gnunet-config -c test_namestore_api.conf -f -s paths -o GNUNET_TEST_HOME`
17
18namestore_link="http://localhost:7776/namestore"
19wrong_link="http://localhost:7776/namestoreandmore"
20
21
22curl_get () {
23 #$1 is link
24 #$2 is grep
25 resp=$(curl -v "$1" 2>&1)
26 cache="$(echo $resp | grep "$2")"
27 #echo $cache
28 if [ "" = "$cache" ]
29 then
30 echo "Error in get response: $resp, expected $2"
31 gnunet-arm -e -c test_namestore_api.conf
32 exit 1
33 fi
34}
35
36curl_post () {
37 #$1 is link
38 #$2 is data
39 #$3 is grep
40 resp=$(curl -v -X "POST" "$1" --data "$2" 2>&1)
41 cache="$(echo $resp | grep "$3")"
42 #echo $cache
43 if [ "" = "$cache" ]
44 then
45 echo "Error in post response: $resp ($2), expected $3"
46 gnunet-arm -e -c test_namestore_api.conf
47 exit 1
48 fi
49}
50
51curl_delete () {
52 #$1 is link
53 #$2 is grep
54 resp=$(curl -v -X "DELETE" "$1" 2>&1)
55 cache="$(echo $resp | grep "$2")"
56 #echo $cache
57 if [ "" = "$cache" ]
58 then
59 echo "Error in delete response: $resp, expected $2"
60 gnunet-arm -e -c test_namestore_api.conf
61 exit 1
62 fi
63}
64
65# curl_put () {
66# #$1 is link
67# #$2 is data
68# #$3 is grep
69# cache="$(curl -v -X "PUT" "$1" --data "$2" 2>&1 | grep "$3")"
70# #echo $cache
71# if [ "" == "$cache" ]
72# then
73# exit 1
74# fi
75# }
76
77#Test subsystem default identity
78
79TEST_ID="test"
80gnunet-arm -s -c test_namestore_api.conf
81#Test GET
82gnunet-identity -C $TEST_ID -c test_namestore_api.conf
83test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)"
84name=$TEST_ID
85public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')"
86echo "$name $public"
87gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
88sleep 1
89gnunet-arm -i rest -c test_namestore_api.conf
90sleep 1
91curl_get "${namestore_link}/$name" "HTTP/1.1 200 OK"
92curl_get "${namestore_link}/$public" "error"
93gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf
94
95#Test POST with NAME
96curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "HTTP/1.1 204 No Content"
97gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
98
99# invalid values
100curl_post "${namestore_link}/$name" '{"data": [{"value":"HVX38H2CB7WJM0WCPWT9CFX6GASMYJVR65RN75SJSSKAYVYXHMRGxxx", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "error"
101gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
102
103
104curl_post "${namestore_link}/$name" '{"data": [{"value":"", "record_type":"PKEY", "expiration_time":"1d","flag":0,"record_name"}]:"test_entry"}' "error"
105gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
106
107curl_post "${namestore_link}/$name" '{"data": [{"record_type":"PKEY", "expiration_time":"1d","flag":0}],"record_name":"test_entry"}' "error"
108gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
109
110#expirations
111curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"0d","private": false, "relative_expiration": true, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "HTTP/1.1 204"
112gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
113
114curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"10000d","private": false, "relative_expiration": true, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "HTTP/1.1 204"
115gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
116
117curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"now","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "error"
118gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
119
120curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time_missing":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":"test_entry"}' "error"
121gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
122
123#record_name
124curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name":""}' "error"
125gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
126curl_post "${namestore_link}/$name" '{"data": [{"value":"000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8", "record_type":"PKEY", "expiration_time":"1d","private": false, "relative_expiration": false, "supplemental": false, "shadow": false}],"record_name_missing":"test_entry"}' "error"
127gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
128
129#Test DELETE
130gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
131curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204"
132
133gnunet-arm -e -c test_namestore_api.conf
134exit 0;
135