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.am755
-rw-r--r--src/namestore/gnunet-namestore-fcfsd.c1138
-rw-r--r--src/namestore/gnunet-namestore.c1717
-rw-r--r--src/namestore/gnunet-service-namestore.c2276
-rw-r--r--src/namestore/gnunet-zoneimport.c1884
-rw-r--r--src/namestore/namestore.conf.in49
-rw-r--r--src/namestore/namestore.h394
-rw-r--r--src/namestore/namestore_api.c1307
-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.c791
-rw-r--r--src/namestore/plugin_rest_namestore.c1155
-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.sh76
-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.sh137
49 files changed, 0 insertions, 19840 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 18e6a196b..000000000
--- a/src/namestore/Makefile.am
+++ /dev/null
@@ -1,755 +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
19if HAVE_TESTING
20HEAP_TESTS = test_plugin_namestore_flat \
21 test_namestore_api_store_flat \
22 test_namestore_api_store_update_flat \
23 test_namestore_api_remove_flat \
24 test_namestore_api_zone_iteration_flat \
25 test_namestore_api_lookup_nick_flat \
26 test_namestore_api_monitoring_flat \
27 test_namestore_api_lookup_public_flat \
28 test_namestore_api_lookup_private_flat \
29 test_namestore_api_lookup_shadow_flat \
30 test_namestore_api_lookup_shadow_filter_flat \
31 test_namestore_api_remove_not_existing_record_flat \
32 test_namestore_api_zone_iteration_nick_flat \
33 test_namestore_api_zone_iteration_specific_zone_flat \
34 test_namestore_api_zone_iteration_stop_flat \
35 test_namestore_api_monitoring_existing_flat \
36 test_namestore_api_zone_to_name_flat \
37 perf_namestore_api_zone_iteration_flat
38endif
39
40if HAVE_SQLITE
41SQLITE_PLUGIN = libgnunet_plugin_namestore_sqlite.la
42if HAVE_TESTING
43SQLITE_TESTS = test_plugin_namestore_sqlite \
44 test_namestore_api_store_sqlite \
45 test_namestore_api_store_update_sqlite \
46 test_namestore_api_zone_iteration_sqlite \
47 test_namestore_api_remove_sqlite \
48 test_namestore_api_lookup_nick_sqlite \
49 test_namestore_api_monitoring_sqlite \
50 test_namestore_api_lookup_public_sqlite \
51 test_namestore_api_lookup_private_sqlite \
52 test_namestore_api_lookup_shadow_sqlite \
53 test_namestore_api_lookup_shadow_filter_sqlite \
54 test_namestore_api_remove_not_existing_record_sqlite \
55 test_namestore_api_zone_iteration_nick_sqlite \
56 test_namestore_api_zone_iteration_specific_zone_sqlite \
57 test_namestore_api_zone_iteration_stop_sqlite \
58 test_namestore_api_monitoring_existing_sqlite \
59 test_namestore_api_zone_to_name_sqlite \
60 perf_namestore_api_zone_iteration_sqlite
61endif
62endif
63
64if HAVE_POSTGRESQL
65POSTGRES_PLUGIN = libgnunet_plugin_namestore_postgres.la
66if HAVE_TESTING
67POSTGRES_TESTS = test_plugin_namestore_postgres \
68 test_namestore_api_store_postgres \
69 test_namestore_api_store_update_postgres \
70 test_namestore_api_remove_postgres \
71 test_namestore_api_zone_iteration_postgres \
72 test_namestore_api_lookup_nick_postgres \
73 test_namestore_api_monitoring_postgres \
74 test_namestore_api_lookup_public_postgres \
75 test_namestore_api_lookup_private_postgres \
76 test_namestore_api_lookup_shadow_postgres \
77 test_namestore_api_lookup_shadow_filter_postgres \
78 test_namestore_api_remove_not_existing_record_postgres \
79 test_namestore_api_zone_iteration_nick_postgres \
80 test_namestore_api_zone_iteration_specific_zone_postgres \
81 test_namestore_api_zone_iteration_stop_postgres \
82 test_namestore_api_monitoring_existing_postgres \
83 test_namestore_api_zone_to_name_postgres \
84 perf_namestore_api_zone_iteration_postgres
85endif
86endif
87
88if HAVE_SQLITE
89check_PROGRAMS = \
90 $(SQLITE_TESTS) \
91 $(POSTGRES_TESTS) \
92 $(HEAP_TESTS)
93endif
94
95if ENABLE_TEST_RUN
96AM_TESTS_ENVIRONMENT=export GNUNET_PREFIX=$${GNUNET_PREFIX:-@libdir@};export PATH=$${GNUNET_PREFIX:-@prefix@}/bin:$$PATH;unset XDG_DATA_HOME;unset XDG_CONFIG_HOME;
97TESTS = \
98 $(check_PROGRAMS) \
99 $(check_SCRIPTS)
100endif
101
102REST_PLUGIN = libgnunet_plugin_rest_namestore.la
103
104lib_LTLIBRARIES = \
105 libgnunetnamestore.la
106
107
108libexec_PROGRAMS = \
109 gnunet-service-namestore
110
111bin_PROGRAMS = \
112 gnunet-namestore \
113 gnunet-zoneimport
114
115libexec_PROGRAMS += \
116 gnunet-namestore-fcfsd
117
118
119plugin_LTLIBRARIES = \
120 $(SQLITE_PLUGIN) \
121 $(POSTGRES_PLUGIN) \
122 $(HEAP_PLUGIN) \
123 $(REST_PLUGIN)
124
125
126libgnunet_plugin_rest_namestore_la_SOURCES = \
127 plugin_rest_namestore.c
128libgnunet_plugin_rest_namestore_la_LIBADD = \
129 libgnunetnamestore.la \
130 $(top_builddir)/src/rest/libgnunetrest.la \
131 $(top_builddir)/src/identity/libgnunetidentity.la \
132 $(top_builddir)/src/json/libgnunetjson.la \
133 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
134 $(top_builddir)/src/gnsrecord/libgnunetgnsrecordjson.la \
135 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
136 $(LTLIBINTL) -ljansson $(MHD_LIBS)
137libgnunet_plugin_rest_namestore_la_LDFLAGS = \
138 $(GN_PLUGIN_LDFLAGS)
139libgnunet_plugin_rest_namestore_la_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
140
141
142libgnunetnamestore_la_SOURCES = \
143 namestore_api.c \
144 namestore_api_monitor.c \
145 namestore.h
146libgnunetnamestore_la_LIBADD = \
147 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
148 $(top_builddir)/src/identity/libgnunetidentity.la \
149 $(top_builddir)/src/statistics/libgnunetstatistics.la \
150 $(top_builddir)/src/util/libgnunetutil.la \
151 $(GN_LIBINTL)
152libgnunetnamestore_la_LDFLAGS = \
153 $(GN_LIB_LDFLAGS) \
154 -version-info 0:1:0
155
156
157
158gnunet_zoneimport_SOURCES = \
159 gnunet-zoneimport.c
160gnunet_zoneimport_LDADD = \
161 libgnunetnamestore.la \
162 $(top_builddir)/src/statistics/libgnunetstatistics.la \
163 $(top_builddir)/src/identity/libgnunetidentity.la \
164 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
165 $(top_builddir)/src/util/libgnunetutil.la \
166 $(GN_LIBINTL)
167
168gnunet_namestore_SOURCES = \
169 gnunet-namestore.c
170gnunet_namestore_LDADD = \
171 $(top_builddir)/src/identity/libgnunetidentity.la \
172 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
173 $(top_builddir)/src/util/libgnunetutil.la \
174 libgnunetnamestore.la \
175 $(GN_LIBINTL)
176
177
178gnunet_namestore_fcfsd_SOURCES = \
179 gnunet-namestore-fcfsd.c
180gnunet_namestore_fcfsd_LDADD = $(MHD_LIBS) \
181 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
182 $(top_builddir)/src/identity/libgnunetidentity.la \
183 libgnunetnamestore.la \
184 $(top_builddir)/src/util/libgnunetutil.la \
185 $(top_builddir)/src/json/libgnunetjson.la \
186 $(GN_LIBINTL) -ljansson
187gnunet_namestore_fcfsd_CFLAGS = $(MHD_CFLAGS) $(AM_CFLAGS)
188
189
190gnunet_service_namestore_SOURCES = \
191 gnunet-service-namestore.c
192
193gnunet_service_namestore_LDADD = \
194 $(top_builddir)/src/namecache/libgnunetnamecache.la \
195 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
196 $(top_builddir)/src/identity/libgnunetidentity.la \
197 $(top_builddir)/src/statistics/libgnunetstatistics.la \
198 $(top_builddir)/src/util/libgnunetutil.la \
199 libgnunetnamestore.la \
200 $(GN_LIBINTL)
201
202
203
204libgnunet_plugin_namestore_flat_la_SOURCES = \
205 plugin_namestore_flat.c
206libgnunet_plugin_namestore_flat_la_LIBADD = \
207 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
208 $(top_builddir)/src/identity/libgnunetidentity.la \
209 $(top_builddir)/src/statistics/libgnunetstatistics.la \
210 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
211 $(LTLIBINTL)
212libgnunet_plugin_namestore_flat_la_LDFLAGS = \
213 $(GN_PLUGIN_LDFLAGS)
214
215
216libgnunet_plugin_namestore_sqlite_la_SOURCES = \
217 plugin_namestore_sqlite.c
218libgnunet_plugin_namestore_sqlite_la_LIBADD = \
219 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
220 $(top_builddir)/src/identity/libgnunetidentity.la \
221 $(top_builddir)/src/sq/libgnunetsq.la \
222 $(top_builddir)/src/statistics/libgnunetstatistics.la \
223 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lsqlite3 \
224 $(LTLIBINTL)
225libgnunet_plugin_namestore_sqlite_la_LDFLAGS = \
226 $(GN_PLUGIN_LDFLAGS)
227
228libgnunet_plugin_namestore_postgres_la_SOURCES = \
229 plugin_namestore_postgres.c
230libgnunet_plugin_namestore_postgres_la_LIBADD = \
231 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
232 $(top_builddir)/src/identity/libgnunetidentity.la \
233 $(top_builddir)/src/pq/libgnunetpq.la \
234 $(top_builddir)/src/statistics/libgnunetstatistics.la \
235 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) -lpq \
236 $(LTLIBINTL)
237libgnunet_plugin_namestore_postgres_la_LDFLAGS = \
238 $(GN_PLUGIN_LDFLAGS) $(POSTGRESQL_LDFLAGS)
239
240test_namestore_api_store_flat_SOURCES = \
241 test_namestore_api_store.c
242test_namestore_api_store_flat_LDADD = \
243 $(top_builddir)/src/testing/libgnunettesting.la \
244 $(top_builddir)/src/util/libgnunetutil.la \
245 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
246 $(top_builddir)/src/identity/libgnunetidentity.la \
247 libgnunetnamestore.la
248
249test_namestore_api_store_sqlite_SOURCES = \
250 test_namestore_api_store.c
251test_namestore_api_store_sqlite_LDADD = \
252 $(top_builddir)/src/testing/libgnunettesting.la \
253 $(top_builddir)/src/util/libgnunetutil.la \
254 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
255 $(top_builddir)/src/identity/libgnunetidentity.la \
256 libgnunetnamestore.la
257
258test_namestore_api_store_postgres_SOURCES = \
259 test_namestore_api_store.c
260test_namestore_api_store_postgres_LDADD = \
261 $(top_builddir)/src/testing/libgnunettesting.la \
262 $(top_builddir)/src/util/libgnunetutil.la \
263 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
264 $(top_builddir)/src/identity/libgnunetidentity.la \
265 libgnunetnamestore.la
266
267test_namestore_api_store_update_flat_SOURCES = \
268 test_namestore_api_store_update.c
269test_namestore_api_store_update_flat_LDADD = \
270 $(top_builddir)/src/testing/libgnunettesting.la \
271 $(top_builddir)/src/util/libgnunetutil.la \
272 $(top_builddir)/src/identity/libgnunetidentity.la \
273 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
274 $(top_builddir)/src/namecache/libgnunetnamecache.la \
275 libgnunetnamestore.la
276
277test_namestore_api_store_update_sqlite_SOURCES = \
278 test_namestore_api_store_update.c
279test_namestore_api_store_update_sqlite_LDADD = \
280 $(top_builddir)/src/testing/libgnunettesting.la \
281 $(top_builddir)/src/util/libgnunetutil.la \
282 $(top_builddir)/src/identity/libgnunetidentity.la \
283 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
284 $(top_builddir)/src/namecache/libgnunetnamecache.la \
285 libgnunetnamestore.la
286
287test_namestore_api_store_update_postgres_SOURCES = \
288 test_namestore_api_store_update.c
289test_namestore_api_store_update_postgres_LDADD = \
290 $(top_builddir)/src/testing/libgnunettesting.la \
291 $(top_builddir)/src/util/libgnunetutil.la \
292 $(top_builddir)/src/identity/libgnunetidentity.la \
293 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
294 $(top_builddir)/src/namecache/libgnunetnamecache.la \
295 libgnunetnamestore.la
296
297test_namestore_api_lookup_public_flat_SOURCES = \
298 test_namestore_api_lookup_public.c
299test_namestore_api_lookup_public_flat_LDADD = \
300 $(top_builddir)/src/testing/libgnunettesting.la \
301 $(top_builddir)/src/identity/libgnunetidentity.la \
302 $(top_builddir)/src/util/libgnunetutil.la \
303 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
304 $(top_builddir)/src/namecache/libgnunetnamecache.la \
305 libgnunetnamestore.la
306
307test_namestore_api_lookup_public_sqlite_SOURCES = \
308 test_namestore_api_lookup_public.c
309test_namestore_api_lookup_public_sqlite_LDADD = \
310 $(top_builddir)/src/testing/libgnunettesting.la \
311 $(top_builddir)/src/util/libgnunetutil.la \
312 $(top_builddir)/src/identity/libgnunetidentity.la \
313 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
314 $(top_builddir)/src/namecache/libgnunetnamecache.la \
315 libgnunetnamestore.la
316
317test_namestore_api_lookup_public_postgres_SOURCES = \
318 test_namestore_api_lookup_public.c
319test_namestore_api_lookup_public_postgres_LDADD = \
320 $(top_builddir)/src/testing/libgnunettesting.la \
321 $(top_builddir)/src/util/libgnunetutil.la \
322 $(top_builddir)/src/identity/libgnunetidentity.la \
323 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
324 $(top_builddir)/src/namecache/libgnunetnamecache.la \
325 libgnunetnamestore.la
326
327test_namestore_api_lookup_nick_sqlite_SOURCES = \
328 test_namestore_api_lookup_nick.c
329test_namestore_api_lookup_nick_sqlite_LDADD = \
330 $(top_builddir)/src/testing/libgnunettesting.la \
331 $(top_builddir)/src/util/libgnunetutil.la \
332 $(top_builddir)/src/identity/libgnunetidentity.la \
333 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
334 $(top_builddir)/src/namecache/libgnunetnamecache.la \
335 libgnunetnamestore.la
336
337test_namestore_api_lookup_nick_postgres_SOURCES = \
338 test_namestore_api_lookup_nick.c
339test_namestore_api_lookup_nick_postgres_LDADD = \
340 $(top_builddir)/src/testing/libgnunettesting.la \
341 $(top_builddir)/src/util/libgnunetutil.la \
342 $(top_builddir)/src/identity/libgnunetidentity.la \
343 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
344 $(top_builddir)/src/namecache/libgnunetnamecache.la \
345 libgnunetnamestore.la
346
347test_namestore_api_lookup_nick_flat_SOURCES = \
348 test_namestore_api_lookup_nick.c
349test_namestore_api_lookup_nick_flat_LDADD = \
350 $(top_builddir)/src/testing/libgnunettesting.la \
351 $(top_builddir)/src/identity/libgnunetidentity.la \
352 $(top_builddir)/src/util/libgnunetutil.la \
353 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
354 $(top_builddir)/src/namecache/libgnunetnamecache.la \
355 libgnunetnamestore.la
356
357test_namestore_api_lookup_private_flat_SOURCES = \
358 test_namestore_api_lookup_private.c
359test_namestore_api_lookup_private_flat_LDADD = \
360 $(top_builddir)/src/testing/libgnunettesting.la \
361 $(top_builddir)/src/identity/libgnunetidentity.la \
362 $(top_builddir)/src/util/libgnunetutil.la \
363 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
364 $(top_builddir)/src/namecache/libgnunetnamecache.la \
365 libgnunetnamestore.la
366
367test_namestore_api_lookup_private_sqlite_SOURCES = \
368 test_namestore_api_lookup_private.c
369test_namestore_api_lookup_private_sqlite_LDADD = \
370 $(top_builddir)/src/testing/libgnunettesting.la \
371 $(top_builddir)/src/identity/libgnunetidentity.la \
372 $(top_builddir)/src/util/libgnunetutil.la \
373 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
374 $(top_builddir)/src/namecache/libgnunetnamecache.la \
375 libgnunetnamestore.la
376
377test_namestore_api_lookup_private_postgres_SOURCES = \
378 test_namestore_api_lookup_private.c
379test_namestore_api_lookup_private_postgres_LDADD = \
380 $(top_builddir)/src/identity/libgnunetidentity.la \
381 $(top_builddir)/src/testing/libgnunettesting.la \
382 $(top_builddir)/src/util/libgnunetutil.la \
383 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
384 $(top_builddir)/src/namecache/libgnunetnamecache.la \
385 libgnunetnamestore.la
386
387test_namestore_api_lookup_shadow_flat_SOURCES = \
388 test_namestore_api_lookup_shadow.c
389test_namestore_api_lookup_shadow_flat_LDADD = \
390 $(top_builddir)/src/testing/libgnunettesting.la \
391 $(top_builddir)/src/identity/libgnunetidentity.la \
392 $(top_builddir)/src/util/libgnunetutil.la \
393 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
394 $(top_builddir)/src/namecache/libgnunetnamecache.la \
395 libgnunetnamestore.la
396
397test_namestore_api_lookup_shadow_sqlite_SOURCES = \
398 test_namestore_api_lookup_shadow.c
399test_namestore_api_lookup_shadow_sqlite_LDADD = \
400 $(top_builddir)/src/testing/libgnunettesting.la \
401 $(top_builddir)/src/util/libgnunetutil.la \
402 $(top_builddir)/src/identity/libgnunetidentity.la \
403 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
404 $(top_builddir)/src/namecache/libgnunetnamecache.la \
405 libgnunetnamestore.la
406
407test_namestore_api_lookup_shadow_postgres_SOURCES = \
408 test_namestore_api_lookup_shadow.c
409test_namestore_api_lookup_shadow_postgres_LDADD = \
410 $(top_builddir)/src/testing/libgnunettesting.la \
411 $(top_builddir)/src/util/libgnunetutil.la \
412 $(top_builddir)/src/identity/libgnunetidentity.la \
413 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
414 $(top_builddir)/src/namecache/libgnunetnamecache.la \
415 libgnunetnamestore.la
416
417test_namestore_api_lookup_shadow_filter_flat_SOURCES = \
418 test_namestore_api_lookup_shadow_filter.c
419test_namestore_api_lookup_shadow_filter_flat_LDADD = \
420 $(top_builddir)/src/testing/libgnunettesting.la \
421 $(top_builddir)/src/util/libgnunetutil.la \
422 $(top_builddir)/src/identity/libgnunetidentity.la \
423 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
424 $(top_builddir)/src/namecache/libgnunetnamecache.la \
425 libgnunetnamestore.la
426
427test_namestore_api_lookup_shadow_filter_sqlite_SOURCES = \
428 test_namestore_api_lookup_shadow_filter.c
429test_namestore_api_lookup_shadow_filter_sqlite_LDADD = \
430 $(top_builddir)/src/testing/libgnunettesting.la \
431 $(top_builddir)/src/identity/libgnunetidentity.la \
432 $(top_builddir)/src/util/libgnunetutil.la \
433 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
434 $(top_builddir)/src/namecache/libgnunetnamecache.la \
435 libgnunetnamestore.la
436test_namestore_api_lookup_shadow_filter_postgres_SOURCES = \
437 test_namestore_api_lookup_shadow_filter.c
438test_namestore_api_lookup_shadow_filter_postgres_LDADD = \
439 $(top_builddir)/src/testing/libgnunettesting.la \
440 $(top_builddir)/src/identity/libgnunetidentity.la \
441 $(top_builddir)/src/util/libgnunetutil.la \
442 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
443 $(top_builddir)/src/namecache/libgnunetnamecache.la \
444 libgnunetnamestore.la
445
446test_namestore_api_remove_sqlite_SOURCES = \
447 test_namestore_api_remove.c
448test_namestore_api_remove_sqlite_LDADD = \
449 $(top_builddir)/src/identity/libgnunetidentity.la \
450 $(top_builddir)/src/testing/libgnunettesting.la \
451 $(top_builddir)/src/util/libgnunetutil.la \
452 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
453 libgnunetnamestore.la
454
455test_namestore_api_remove_postgres_SOURCES = \
456 test_namestore_api_remove.c
457test_namestore_api_remove_postgres_LDADD = \
458 $(top_builddir)/src/identity/libgnunetidentity.la \
459 $(top_builddir)/src/testing/libgnunettesting.la \
460 $(top_builddir)/src/util/libgnunetutil.la \
461 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
462 libgnunetnamestore.la
463
464test_namestore_api_remove_flat_SOURCES = \
465 test_namestore_api_remove.c
466test_namestore_api_remove_flat_LDADD = \
467 $(top_builddir)/src/testing/libgnunettesting.la \
468 $(top_builddir)/src/identity/libgnunetidentity.la \
469 $(top_builddir)/src/util/libgnunetutil.la \
470 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
471 libgnunetnamestore.la
472
473test_namestore_api_remove_not_existing_record_flat_SOURCES = \
474 test_namestore_api_remove_not_existing_record.c
475test_namestore_api_remove_not_existing_record_flat_LDADD = \
476 $(top_builddir)/src/testing/libgnunettesting.la \
477 $(top_builddir)/src/identity/libgnunetidentity.la \
478 $(top_builddir)/src/util/libgnunetutil.la \
479 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
480 libgnunetnamestore.la
481
482test_namestore_api_remove_not_existing_record_sqlite_SOURCES = \
483 test_namestore_api_remove_not_existing_record.c
484test_namestore_api_remove_not_existing_record_sqlite_LDADD = \
485 $(top_builddir)/src/testing/libgnunettesting.la \
486 $(top_builddir)/src/util/libgnunetutil.la \
487 $(top_builddir)/src/identity/libgnunetidentity.la \
488 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
489 libgnunetnamestore.la
490
491test_namestore_api_remove_not_existing_record_postgres_SOURCES = \
492 test_namestore_api_remove_not_existing_record.c
493test_namestore_api_remove_not_existing_record_postgres_LDADD = \
494 $(top_builddir)/src/testing/libgnunettesting.la \
495 $(top_builddir)/src/identity/libgnunetidentity.la \
496 $(top_builddir)/src/util/libgnunetutil.la \
497 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
498 libgnunetnamestore.la
499
500test_namestore_api_zone_to_name_flat_SOURCES = \
501 test_namestore_api_zone_to_name.c
502test_namestore_api_zone_to_name_flat_LDADD = \
503 $(top_builddir)/src/identity/libgnunetidentity.la \
504 $(top_builddir)/src/testing/libgnunettesting.la \
505 $(top_builddir)/src/util/libgnunetutil.la \
506 libgnunetnamestore.la
507
508test_namestore_api_zone_to_name_sqlite_SOURCES = \
509 test_namestore_api_zone_to_name.c
510test_namestore_api_zone_to_name_sqlite_LDADD = \
511 $(top_builddir)/src/identity/libgnunetidentity.la \
512 $(top_builddir)/src/testing/libgnunettesting.la \
513 $(top_builddir)/src/util/libgnunetutil.la \
514 libgnunetnamestore.la
515
516test_namestore_api_zone_to_name_postgres_SOURCES = \
517 test_namestore_api_zone_to_name.c
518test_namestore_api_zone_to_name_postgres_LDADD = \
519 $(top_builddir)/src/identity/libgnunetidentity.la \
520 $(top_builddir)/src/testing/libgnunettesting.la \
521 $(top_builddir)/src/util/libgnunetutil.la \
522 libgnunetnamestore.la
523
524test_namestore_api_monitoring_flat_SOURCES = \
525 test_namestore_api_monitoring.c
526test_namestore_api_monitoring_flat_LDADD = \
527 $(top_builddir)/src/testing/libgnunettesting.la \
528 libgnunetnamestore.la \
529 $(top_builddir)/src/identity/libgnunetidentity.la \
530 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
531 $(top_builddir)/src/util/libgnunetutil.la
532
533test_namestore_api_monitoring_sqlite_SOURCES = \
534 test_namestore_api_monitoring.c
535test_namestore_api_monitoring_sqlite_LDADD = \
536 $(top_builddir)/src/identity/libgnunetidentity.la \
537 $(top_builddir)/src/testing/libgnunettesting.la \
538 libgnunetnamestore.la \
539 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
540 $(top_builddir)/src/util/libgnunetutil.la
541
542test_namestore_api_monitoring_postgres_SOURCES = \
543 test_namestore_api_monitoring.c
544test_namestore_api_monitoring_postgres_LDADD = \
545 $(top_builddir)/src/testing/libgnunettesting.la \
546 $(top_builddir)/src/identity/libgnunetidentity.la \
547 libgnunetnamestore.la \
548 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
549 $(top_builddir)/src/util/libgnunetutil.la
550
551test_namestore_api_monitoring_existing_flat_SOURCES = \
552 test_namestore_api_monitoring_existing.c
553test_namestore_api_monitoring_existing_flat_LDADD = \
554 $(top_builddir)/src/testing/libgnunettesting.la \
555 $(top_builddir)/src/identity/libgnunetidentity.la \
556 libgnunetnamestore.la \
557 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
558 $(top_builddir)/src/util/libgnunetutil.la
559
560test_namestore_api_monitoring_existing_sqlite_SOURCES = \
561 test_namestore_api_monitoring_existing.c
562test_namestore_api_monitoring_existing_sqlite_LDADD = \
563 $(top_builddir)/src/testing/libgnunettesting.la \
564 $(top_builddir)/src/identity/libgnunetidentity.la \
565 libgnunetnamestore.la \
566 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
567 $(top_builddir)/src/util/libgnunetutil.la
568
569test_namestore_api_monitoring_existing_postgres_SOURCES = \
570 test_namestore_api_monitoring_existing.c
571test_namestore_api_monitoring_existing_postgres_LDADD = \
572 $(top_builddir)/src/testing/libgnunettesting.la \
573 libgnunetnamestore.la \
574 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
575 $(top_builddir)/src/identity/libgnunetidentity.la \
576 $(top_builddir)/src/util/libgnunetutil.la
577
578test_namestore_api_zone_iteration_flat_SOURCES = \
579 test_namestore_api_zone_iteration.c
580test_namestore_api_zone_iteration_flat_LDADD = \
581 $(top_builddir)/src/testing/libgnunettesting.la \
582 $(top_builddir)/src/identity/libgnunetidentity.la \
583 $(top_builddir)/src/util/libgnunetutil.la \
584 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
585 libgnunetnamestore.la
586
587test_namestore_api_zone_iteration_sqlite_SOURCES = \
588 test_namestore_api_zone_iteration.c
589test_namestore_api_zone_iteration_sqlite_LDADD = \
590 $(top_builddir)/src/testing/libgnunettesting.la \
591 $(top_builddir)/src/identity/libgnunetidentity.la \
592 $(top_builddir)/src/util/libgnunetutil.la \
593 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
594 libgnunetnamestore.la
595
596test_namestore_api_zone_iteration_postgres_SOURCES = \
597 test_namestore_api_zone_iteration.c
598test_namestore_api_zone_iteration_postgres_LDADD = \
599 $(top_builddir)/src/testing/libgnunettesting.la \
600 $(top_builddir)/src/identity/libgnunetidentity.la \
601 $(top_builddir)/src/util/libgnunetutil.la \
602 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
603 libgnunetnamestore.la
604
605perf_namestore_api_zone_iteration_postgres_SOURCES = \
606 perf_namestore_api_zone_iteration.c
607perf_namestore_api_zone_iteration_postgres_LDADD = \
608 $(top_builddir)/src/testing/libgnunettesting.la \
609 $(top_builddir)/src/util/libgnunetutil.la \
610 $(top_builddir)/src/identity/libgnunetidentity.la \
611 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
612 libgnunetnamestore.la
613
614perf_namestore_api_zone_iteration_sqlite_SOURCES = \
615 perf_namestore_api_zone_iteration.c
616perf_namestore_api_zone_iteration_sqlite_LDADD = \
617 $(top_builddir)/src/testing/libgnunettesting.la \
618 $(top_builddir)/src/identity/libgnunetidentity.la \
619 $(top_builddir)/src/util/libgnunetutil.la \
620 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
621 libgnunetnamestore.la
622
623perf_namestore_api_zone_iteration_flat_SOURCES = \
624 perf_namestore_api_zone_iteration.c
625perf_namestore_api_zone_iteration_flat_LDADD = \
626 $(top_builddir)/src/testing/libgnunettesting.la \
627 $(top_builddir)/src/identity/libgnunetidentity.la \
628 $(top_builddir)/src/util/libgnunetutil.la \
629 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
630 libgnunetnamestore.la
631
632test_namestore_api_zone_iteration_nick_flat_SOURCES = \
633 test_namestore_api_zone_iteration_nick.c
634test_namestore_api_zone_iteration_nick_flat_LDADD = \
635 $(top_builddir)/src/testing/libgnunettesting.la \
636 $(top_builddir)/src/util/libgnunetutil.la \
637 $(top_builddir)/src/identity/libgnunetidentity.la \
638 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
639 libgnunetnamestore.la
640
641test_namestore_api_zone_iteration_nick_sqlite_SOURCES = \
642 test_namestore_api_zone_iteration_nick.c
643test_namestore_api_zone_iteration_nick_sqlite_LDADD = \
644 $(top_builddir)/src/testing/libgnunettesting.la \
645 $(top_builddir)/src/identity/libgnunetidentity.la \
646 $(top_builddir)/src/util/libgnunetutil.la \
647 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
648 libgnunetnamestore.la
649
650test_namestore_api_zone_iteration_nick_postgres_SOURCES = \
651 test_namestore_api_zone_iteration_nick.c
652test_namestore_api_zone_iteration_nick_postgres_LDADD = \
653 $(top_builddir)/src/testing/libgnunettesting.la \
654 $(top_builddir)/src/identity/libgnunetidentity.la \
655 $(top_builddir)/src/util/libgnunetutil.la \
656 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
657 libgnunetnamestore.la
658
659test_namestore_api_zone_iteration_specific_zone_flat_SOURCES = \
660 test_namestore_api_zone_iteration_specific_zone.c
661test_namestore_api_zone_iteration_specific_zone_flat_LDADD = \
662 $(top_builddir)/src/testing/libgnunettesting.la \
663 $(top_builddir)/src/identity/libgnunetidentity.la \
664 $(top_builddir)/src/util/libgnunetutil.la \
665 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
666 libgnunetnamestore.la
667
668test_namestore_api_zone_iteration_specific_zone_sqlite_SOURCES = \
669 test_namestore_api_zone_iteration_specific_zone.c
670test_namestore_api_zone_iteration_specific_zone_sqlite_LDADD = \
671 $(top_builddir)/src/testing/libgnunettesting.la \
672 $(top_builddir)/src/identity/libgnunetidentity.la \
673 $(top_builddir)/src/util/libgnunetutil.la \
674 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
675 libgnunetnamestore.la
676
677test_namestore_api_zone_iteration_specific_zone_postgres_SOURCES = \
678 test_namestore_api_zone_iteration_specific_zone.c
679test_namestore_api_zone_iteration_specific_zone_postgres_LDADD = \
680 $(top_builddir)/src/testing/libgnunettesting.la \
681 $(top_builddir)/src/identity/libgnunetidentity.la \
682 $(top_builddir)/src/util/libgnunetutil.la \
683 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
684 libgnunetnamestore.la
685
686test_namestore_api_zone_iteration_stop_flat_SOURCES = \
687 test_namestore_api_zone_iteration_stop.c
688test_namestore_api_zone_iteration_stop_flat_LDADD = \
689 $(top_builddir)/src/testing/libgnunettesting.la \
690 $(top_builddir)/src/identity/libgnunetidentity.la \
691 $(top_builddir)/src/util/libgnunetutil.la \
692 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
693 libgnunetnamestore.la
694
695test_namestore_api_zone_iteration_stop_sqlite_SOURCES = \
696 test_namestore_api_zone_iteration_stop.c
697test_namestore_api_zone_iteration_stop_sqlite_LDADD = \
698 $(top_builddir)/src/testing/libgnunettesting.la \
699 $(top_builddir)/src/identity/libgnunetidentity.la \
700 $(top_builddir)/src/util/libgnunetutil.la \
701 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
702 libgnunetnamestore.la
703
704test_namestore_api_zone_iteration_stop_postgres_SOURCES = \
705 test_namestore_api_zone_iteration_stop.c
706test_namestore_api_zone_iteration_stop_postgres_LDADD = \
707 $(top_builddir)/src/testing/libgnunettesting.la \
708 $(top_builddir)/src/identity/libgnunetidentity.la \
709 $(top_builddir)/src/util/libgnunetutil.la \
710 $(top_builddir)/src/gnsrecord/libgnunetgnsrecord.la \
711 libgnunetnamestore.la
712
713test_plugin_namestore_flat_SOURCES = \
714 test_plugin_namestore.c
715test_plugin_namestore_flat_LDADD = \
716 $(top_builddir)/src/testing/libgnunettesting.la \
717 $(top_builddir)/src/identity/libgnunetidentity.la \
718 $(top_builddir)/src/util/libgnunetutil.la
719
720test_plugin_namestore_sqlite_SOURCES = \
721 test_plugin_namestore.c
722test_plugin_namestore_sqlite_LDADD = \
723 $(top_builddir)/src/testing/libgnunettesting.la \
724 $(top_builddir)/src/identity/libgnunetidentity.la \
725 $(top_builddir)/src/util/libgnunetutil.la
726
727test_plugin_namestore_postgres_SOURCES = \
728 test_plugin_namestore.c
729test_plugin_namestore_postgres_LDADD = \
730 $(top_builddir)/src/identity/libgnunetidentity.la \
731 $(top_builddir)/src/testing/libgnunettesting.la \
732 $(top_builddir)/src/util/libgnunetutil.la
733
734check_SCRIPTS = \
735 test_namestore_put.sh \
736 test_namestore_lookup.sh \
737 test_namestore_delete.sh
738
739check_SCRIPTS += \
740 test_plugin_rest_namestore.sh
741
742EXTRA_DIST = \
743 test_common.c \
744 test_namestore_api.conf \
745 test_namestore_api_postgres.conf \
746 test_namestore_api_sqlite.conf \
747 test_namestore_api_flat.conf \
748 perf_namestore_api_postgres.conf \
749 perf_namestore_api_sqlite.conf \
750 perf_namestore_api_flat.conf \
751 test_plugin_namestore_sqlite.conf \
752 test_plugin_namestore_postgres.conf \
753 test_plugin_namestore_flat.conf \
754 test_hostkey \
755 $(check_SCRIPTS)
diff --git a/src/namestore/gnunet-namestore-fcfsd.c b/src/namestore/gnunet-namestore-fcfsd.c
deleted file mode 100644
index 95d4c5878..000000000
--- a/src/namestore/gnunet-namestore-fcfsd.c
+++ /dev/null
@@ -1,1138 +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 * Task ran at shutdown to clean up everything.
169 *
170 * @param cls unused
171 */
172static void
173do_shutdown (void *cls)
174{
175 /* We cheat a bit here: the file descriptor is implicitly closed by MHD, so
176 calling `GNUNET_DISK_file_close' would generate a spurious warning message
177 in the log. Since that function does nothing but close the descriptor and
178 free the allocated memory, After destroying the response all that's left to
179 do is call `GNUNET_free'. */
180 if (NULL != main_page)
181 {
182 MHD_destroy_response (main_page->response);
183 GNUNET_free (main_page->handle);
184 GNUNET_free (main_page);
185 }
186 if (NULL != notfound_page)
187 {
188 MHD_destroy_response (notfound_page->response);
189 GNUNET_free (notfound_page->handle);
190 GNUNET_free (notfound_page);
191 }
192 if (NULL != forbidden_page)
193 {
194 MHD_destroy_response (forbidden_page->response);
195 GNUNET_free (forbidden_page->handle);
196 GNUNET_free (forbidden_page);
197 }
198
199 if (NULL != namestore)
200 {
201 GNUNET_NAMESTORE_disconnect (namestore);
202 }
203
204 if (NULL != identity)
205 {
206 GNUNET_IDENTITY_disconnect (identity);
207 }
208}
209
210
211/**
212 * Called when the HTTP server has some pending operations.
213 *
214 * @param cls unused
215 */
216static void
217do_httpd (void *cls);
218
219/**
220 * Schedule a task to run MHD.
221 */
222static void
223run_httpd (void)
224{
225 fd_set rs;
226 fd_set ws;
227 fd_set es;
228
229 struct GNUNET_NETWORK_FDSet *grs = GNUNET_NETWORK_fdset_create ();
230 struct GNUNET_NETWORK_FDSet *gws = GNUNET_NETWORK_fdset_create ();
231 struct GNUNET_NETWORK_FDSet *ges = GNUNET_NETWORK_fdset_create ();
232
233 FD_ZERO (&rs);
234 FD_ZERO (&ws);
235 FD_ZERO (&es);
236
237 int max = -1;
238 GNUNET_assert (MHD_YES == MHD_get_fdset (httpd, &rs, &ws, &es, &max));
239
240 unsigned MHD_LONG_LONG timeout = 0;
241 struct GNUNET_TIME_Relative gtime = GNUNET_TIME_UNIT_FOREVER_REL;
242 if (MHD_YES == MHD_get_timeout (httpd, &timeout))
243 {
244 gtime = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
245 timeout);
246 }
247
248 GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
249 GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
250 GNUNET_NETWORK_fdset_copy_native (ges, &es, max + 1);
251
252 httpd_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_HIGH,
253 gtime,
254 grs,
255 gws,
256 &do_httpd,
257 NULL);
258 GNUNET_NETWORK_fdset_destroy (grs);
259 GNUNET_NETWORK_fdset_destroy (gws);
260 GNUNET_NETWORK_fdset_destroy (ges);
261}
262
263
264/**
265 * Called when the HTTP server has some pending operations.
266 *
267 * @param cls unused
268 */
269static void
270do_httpd (void *cls)
271{
272 httpd_task = NULL;
273 MHD_run (httpd);
274 run_httpd ();
275}
276
277
278static void
279run_httpd_now (void)
280{
281 if (NULL != httpd_task)
282 {
283 GNUNET_SCHEDULER_cancel (httpd_task);
284 httpd_task = NULL;
285 }
286 httpd_task = GNUNET_SCHEDULER_add_now (&do_httpd, NULL);
287}
288
289
290/**
291 * Generate a JSON object.
292 *
293 * @param key the key for the first element
294 * @param value the value for the first element
295 * @param ... key-value pairs of the object, terminated by NULL
296 * @return a JSON string (allocated)
297 */
298static char *
299make_json (const char *key, const char *value, ...)
300{
301 va_list args;
302 va_start (args, value);
303
304 json_t *obj = NULL;
305
306 obj = json_object ();
307 if ((NULL == key) || (NULL == value))
308 {
309 va_end (args);
310 return json_dumps (obj, JSON_COMPACT);
311 }
312
313 json_object_set (obj, key, json_string (value));
314
315 char *k = va_arg (args, char *);
316 if (NULL == k)
317 {
318 va_end (args);
319 return json_dumps (obj, JSON_COMPACT);
320 }
321 char *v = va_arg (args, char *);
322 if (NULL == v)
323 {
324 va_end (args);
325 return json_dumps (obj, JSON_COMPACT);
326 }
327
328 while (NULL != k && NULL != v)
329 {
330 json_object_set (obj, k, json_string (v));
331 k = va_arg (args, char *);
332 if (NULL != k)
333 {
334 v = va_arg (args, char *);
335 }
336 }
337
338 va_end (args);
339
340 char *json = json_dumps (obj, JSON_COMPACT);
341 json_decref (obj);
342
343 return json;
344}
345
346
347/**
348 * The namestore search task failed.
349 *
350 * @param cls the request data
351 */
352static void
353search_error_cb (void *cls)
354{
355 struct RequestData *rd = cls;
356 MHD_resume_connection (rd->c);
357 rd->searching = NULL;
358 rd->body = make_json ("error", "true",
359 "message", _ ("can not search the namestore"),
360 NULL);
361 rd->body_length = strlen (rd->body);
362 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
363 run_httpd_now ();
364}
365
366
367/**
368 * The lookup terminated with some results.
369 *
370 * @param cls closure
371 * @param zone the private key of the zone
372 * @param label the result label
373 * @param count number of records found
374 * @param d records found
375 */
376static void
377search_done_cb (void *cls,
378 const struct GNUNET_IDENTITY_PrivateKey *zone,
379 const char *label,
380 unsigned int count,
381 const struct GNUNET_GNSRECORD_Data *d)
382{
383 (void) zone;
384 (void) d;
385
386 struct RequestData *rd = cls;
387 MHD_resume_connection (rd->c);
388
389 rd->searching = NULL;
390 rd->body = make_json ("error", "false",
391 "free", (0 == count) ? "true" : "false",
392 NULL);
393 rd->body_length = strlen (rd->body);
394 rd->code = MHD_HTTP_OK;
395
396 run_httpd_now ();
397}
398
399
400/**
401 * An error occurred while registering a name.
402 *
403 * @param cls the connection
404 */
405static void
406register_error_cb (void *cls)
407{
408 struct RequestData *rd = cls;
409
410 MHD_resume_connection (rd->c);
411 rd->searching = NULL;
412 rd->body = make_json ("error", "true",
413 "message", _ ("unable to scan namestore"),
414 NULL);
415 rd->body_length = strlen (rd->body);
416 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
417 run_httpd_now ();
418}
419
420
421/**
422 * A name/key pair has been successfully registered, or maybe not.
423 *
424 * @param cls the connection
425 * @param status result of the operation
426 * @param emsg error message if any
427 */
428static void
429register_done_cb (void *cls,
430 int32_t status,
431 const char *emsg)
432{
433 struct RequestData *rd = cls;
434
435 MHD_resume_connection (rd->c);
436 rd->searching = NULL;
437
438 if ((GNUNET_SYSERR == status) || (GNUNET_NO == status))
439 {
440 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
441 _ ("Failed to create record for `%s': %s\n"),
442 rd->register_name,
443 emsg);
444 rd->body = make_json ("error", "true",
445 "message", emsg,
446 NULL);
447 rd->body_length = strlen (rd->body);
448 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
449 }
450 else
451 {
452 rd->body = make_json ("error", "false",
453 "message", _ ("no errors"),
454 NULL);
455 rd->body_length = strlen (rd->body);
456 rd->code = MHD_HTTP_OK;
457 }
458
459 run_httpd_now ();
460}
461
462
463/**
464 * Attempt to register the requested name.
465 *
466 * @param cls the connection
467 * @param key the zone key
468 * @param label name of the record
469 * @param count number of records found
470 * @param d records
471 */
472static void
473register_do_cb (void *cls,
474 const struct GNUNET_IDENTITY_PrivateKey *key,
475 const char *label,
476 unsigned int count,
477 const struct GNUNET_GNSRECORD_Data *d)
478{
479 (void) key;
480 (void) d;
481
482 struct RequestData *rd = cls;
483
484 rd->searching = NULL;
485
486 if (0 != count)
487 {
488 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
489 _ ("The requested key `%s' exists as `%s'\n"),
490 rd->register_key,
491 label);
492
493 MHD_resume_connection (rd->c);
494 rd->searching = NULL;
495 rd->body = make_json ("error", "true",
496 "message", _ ("key exists"),
497 NULL);
498 rd->body_length = strlen (rd->body);
499 rd->code = MHD_HTTP_FORBIDDEN;
500 run_httpd_now ();
501 return;
502 }
503
504 struct GNUNET_GNSRECORD_Data gd;
505 char *gdraw = NULL;
506
507 if (GNUNET_OK != GNUNET_GNSRECORD_data_from_identity (&(rd->key),
508 &gdraw,
509 &(gd.data_size),
510 &(gd.record_type)))
511 {
512 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
513 _ ("Error creating record data\n"));
514 MHD_resume_connection (rd->c);
515 rd->searching = NULL;
516 rd->body = make_json ("error", "true",
517 "message", _ ("unable to store record"),
518 NULL);
519 rd->body_length = strlen (rd->body);
520 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
521 run_httpd_now ();
522 return;
523 }
524
525 gd.data = gdraw;
526 gd.expiration_time = UINT64_MAX;
527 gd.flags = GNUNET_GNSRECORD_RF_NONE;
528
529 rd->searching = GNUNET_NAMESTORE_records_store (namestore,
530 zone_key,
531 rd->register_name,
532 1,
533 &gd,
534 &register_done_cb,
535 rd);
536
537 GNUNET_free (gdraw);
538}
539
540
541/**
542 * An error occurred while iterating the namestore.
543 *
544 * @param cls the connection
545 */
546static void
547iterate_error_cb (void *cls)
548{
549 struct RequestData *rd = cls;
550
551 MHD_resume_connection (rd->c);
552 rd->iterating = NULL;
553 rd->body = make_json ("error", "true",
554 "message", _ ("unable to scan namestore"),
555 NULL);
556 rd->body_length = strlen (rd->body);
557 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
558 run_httpd_now ();
559}
560
561
562/**
563 * A block was received from the namestore.
564 *
565 * @param cls the connection
566 * @param key the zone key
567 * @param label the records' label
568 * @param count number of records found
569 * @param d the found records
570 */
571static void
572iterate_do_cb (void *cls,
573 const struct GNUNET_IDENTITY_PrivateKey *key,
574 const char *label,
575 unsigned int count,
576 const struct GNUNET_GNSRECORD_Data *d)
577{
578 (void) key;
579 (void) label;
580 (void) d;
581
582 struct RequestData *rd = cls;
583
584 if (0 == strcmp (label, rd->register_name))
585 {
586 GNUNET_break (0 != count);
587 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
588 _ ("Requested name `%s' exists with `%u' records\n"),
589 rd->register_name,
590 count);
591
592 MHD_resume_connection (rd->c);
593 rd->body = make_json ("error", "true",
594 "message", _ ("name exists\n"),
595 NULL);
596 rd->body_length = strlen (rd->body);
597 rd->code = MHD_HTTP_FORBIDDEN;
598 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
599 run_httpd_now ();
600 return;
601 }
602
603 GNUNET_NAMESTORE_zone_iterator_next (rd->iterating, 1);
604}
605
606
607/**
608 * All entries in the namestore have been iterated over.
609 *
610 * @param cls the connection
611 */
612static void
613iterate_done_cb (void *cls)
614{
615 struct RequestData *rd = cls;
616
617 rd->iterating = NULL;
618
619 /* See if the key was not registered already */
620 rd->searching = GNUNET_NAMESTORE_zone_to_name (namestore,
621 zone_key,
622 &(rd->key),
623 &register_error_cb,
624 rd,
625 &register_do_cb,
626 rd);
627}
628
629
630/**
631 * Generate a response containing JSON and send it to the client.
632 *
633 * @param c the connection
634 * @param body the response body
635 * @param length the body length in bytes
636 * @param code the response code
637 * @return MHD_NO on error
638 */
639static MHD_RESULT
640serve_json (struct MHD_Connection *c,
641 char *body,
642 size_t length,
643 int code)
644{
645 struct MHD_Response *response =
646 MHD_create_response_from_buffer (length,
647 body,
648 MHD_RESPMEM_PERSISTENT);
649 MHD_RESULT r = MHD_queue_response (c, code, response);
650 MHD_destroy_response (response);
651 return r;
652}
653
654
655/**
656 * Send a response back to a connected client.
657 *
658 * @param cls unused
659 * @param connection the connection with the client
660 * @param url the requested address
661 * @param method the HTTP method used
662 * @param version the protocol version (including the "HTTP/" part)
663 * @param upload_data data sent with a POST request
664 * @param upload_data_size length in bytes of the POST data
665 * @param ptr used to pass data between request handling phases
666 * @return MHD_NO on error
667 */
668static MHD_RESULT
669create_response (void *cls,
670 struct MHD_Connection *connection,
671 const char *url,
672 const char *method,
673 const char *version,
674 const char *upload_data,
675 size_t *upload_data_size,
676 void **ptr)
677{
678 (void) cls;
679 (void) version;
680
681 struct RequestData *rd = *ptr;
682
683 if (0 == strcmp (method, MHD_HTTP_METHOD_GET))
684 {
685 /* Handle a previously suspended request */
686 if (NULL != rd)
687 {
688 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
689 }
690
691 if (0 == strcmp ("/", url))
692 {
693 return MHD_queue_response (connection,
694 MHD_HTTP_OK,
695 main_page->response);
696 }
697
698 if (0 == strcmp ("/search", url))
699 {
700 const char *name = MHD_lookup_connection_value (connection,
701 MHD_GET_ARGUMENT_KIND,
702 "name");
703 if (NULL == name)
704 {
705 return MHD_queue_response (connection,
706 MHD_HTTP_BAD_REQUEST,
707 forbidden_page->response);
708 }
709
710 MHD_suspend_connection (connection);
711 rd = GNUNET_new (struct RequestData);
712 rd->c = connection;
713 rd->searching = GNUNET_NAMESTORE_records_lookup (namestore,
714 zone_key,
715 name,
716 &search_error_cb,
717 rd,
718 &search_done_cb,
719 rd);
720 *ptr = rd;
721 return MHD_YES;
722 }
723
724 return MHD_queue_response (connection,
725 MHD_HTTP_NOT_FOUND,
726 notfound_page->response);
727 }
728
729 if (0 == strcmp (method, MHD_HTTP_METHOD_HEAD))
730 {
731 /* We take a shortcut here by always serving the main page: starting a
732 namestore lookup, allocating the necessary resources, waiting for the
733 lookup to complete and then discard everything just because it was a HEAD
734 and thus only the headers are significative, is an unnecessary waste of
735 resources. The handling of this method could be smarter, for example by
736 sending a proper content type header based on the endpoint, but this is
737 not a service in which HEAD requests are significant, so there's no need
738 to spend too much time here. */
739 return MHD_queue_response (connection,
740 MHD_HTTP_OK,
741 main_page->response);
742 }
743
744 if (0 == strcmp (method, MHD_HTTP_METHOD_POST))
745 {
746 if (0 == strcmp ("/register", url))
747 {
748 /* Handle a previously suspended request */
749 if ((NULL != rd) && (NULL != rd->body))
750 {
751 return serve_json (rd->c, rd->body, rd->body_length, rd->code);
752 }
753
754 if (NULL == rd)
755 {
756 rd = GNUNET_new (struct RequestData);
757 rd->c = connection;
758 rd->body = NULL;
759 rd->ptr = NULL;
760 *ptr = rd;
761 }
762
763 json_t *json = NULL;
764 enum GNUNET_JSON_PostResult result =
765 GNUNET_JSON_post_parser (32 * 1024,
766 connection,
767 &(rd->ptr),
768 upload_data,
769 upload_data_size,
770 &json);
771
772 switch (result)
773 {
774 case GNUNET_JSON_PR_CONTINUE:
775 /* Keep processing POST data */
776 return MHD_YES;
777 case GNUNET_JSON_PR_OUT_OF_MEMORY:
778 case GNUNET_JSON_PR_REQUEST_TOO_LARGE:
779 rd->body = make_json ("error", "true",
780 "message", _ ("unable to process submitted data"),
781 NULL);
782 rd->body_length = strlen (rd->body);
783 rd->code = MHD_HTTP_PAYLOAD_TOO_LARGE;
784 return MHD_YES;
785 case GNUNET_JSON_PR_JSON_INVALID:
786 rd->body = make_json ("error", "true",
787 "message", _ ("the submitted data is invalid"),
788 NULL);
789 rd->body_length = strlen (rd->body);
790 rd->code = MHD_HTTP_BAD_REQUEST;
791 return MHD_YES;
792 default:
793 break;
794 }
795
796 /* POST data has been read in its entirety */
797
798 const char *name = json_string_value (json_object_get (json, "name"));
799 const char *key = json_string_value (json_object_get (json, "key"));
800 if ((NULL == name) || (NULL == key) || (0 == strlen (name)) || (0 ==
801 strlen (
802 key)))
803 {
804 json_decref (json);
805 rd->body = make_json ("error", "true",
806 "message", _ ("invalid parameters"),
807 NULL);
808 rd->body_length = strlen (rd->body);
809 rd->code = MHD_HTTP_BAD_REQUEST;
810 return MHD_YES;
811 }
812
813 rd->register_name = strdup (name);
814 rd->register_key = strdup (key);
815
816 json_decref (json);
817 GNUNET_JSON_post_parser_cleanup (rd->ptr);
818
819 if ((NULL != strchr (rd->register_name, '.')) ||
820 (NULL != strchr (rd->register_name, '+')))
821 {
822 rd->body = make_json ("error", "true",
823 "message", _ ("invalid name"),
824 NULL);
825 rd->body_length = strlen (rd->body);
826 rd->code = MHD_HTTP_BAD_REQUEST;
827 return MHD_YES;
828 }
829
830 if (GNUNET_OK != GNUNET_IDENTITY_public_key_from_string (rd->register_key,
831 &(rd->key)))
832 {
833 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
834 _ ("Unable to parse key %s\n"),
835 rd->register_key);
836
837 rd->body = make_json ("error", "true",
838 "message", _ ("unable to parse key"),
839 NULL);
840 rd->body_length = strlen (rd->body);
841 rd->code = MHD_HTTP_INTERNAL_SERVER_ERROR;
842 return MHD_YES;
843 }
844
845 MHD_suspend_connection (connection);
846 /* See if the requested name is free */
847 rd->iterating =
848 GNUNET_NAMESTORE_zone_iteration_start (namestore,
849 zone_key,
850 &iterate_error_cb,
851 rd,
852 &iterate_do_cb,
853 rd,
854 &iterate_done_cb,
855 rd);
856 return MHD_YES;
857 }
858
859 return MHD_queue_response (connection,
860 MHD_HTTP_FORBIDDEN,
861 forbidden_page->response);
862 }
863
864 return MHD_queue_response (connection,
865 MHD_HTTP_NOT_IMPLEMENTED,
866 forbidden_page->response);
867}
868
869
870/**
871 * Called when a request is completed.
872 *
873 * @param cls unused
874 * @param connection the connection
875 * @param ptr connection-specific data
876 * @param status status code
877 */
878static void
879completed_cb (void *cls,
880 struct MHD_Connection *connection,
881 void **ptr,
882 enum MHD_RequestTerminationCode status)
883{
884 (void) cls;
885 (void) connection;
886 (void) status;
887
888 struct RequestData *rd = *ptr;
889
890 if (NULL == rd)
891 {
892 return;
893 }
894
895 if (NULL == rd->body)
896 {
897 GNUNET_free (rd->body);
898 }
899
900 if (NULL != rd->searching)
901 {
902 GNUNET_NAMESTORE_cancel (rd->searching);
903 }
904
905 if (NULL != rd->register_name)
906 {
907 GNUNET_free (rd->register_name);
908 }
909
910 if (NULL != rd->register_key)
911 {
912 GNUNET_free (rd->register_key);
913 }
914
915 if (NULL != rd->iterating)
916 {
917 GNUNET_NAMESTORE_zone_iteration_stop (rd->iterating);
918 }
919
920 GNUNET_free (rd);
921}
922
923
924/**
925 * Called for each ego provided by the identity service.
926 *
927 * @param cls closure
928 * @param ego the ego
929 * @param ctx application-provided data for the ego
930 * @param name the ego name
931 */
932static void
933identity_cb (void *cls,
934 struct GNUNET_IDENTITY_Ego *ego,
935 void **ctx,
936 const char *name)
937{
938 (void) cls;
939 (void) ctx;
940
941 if ((NULL == name) || (0 != strcmp (name, zone)))
942 {
943 return;
944 }
945
946 if (NULL == ego)
947 {
948 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
949 _ ("No ego configured for `fcfsd` subsystem\n"));
950 GNUNET_SCHEDULER_shutdown ();
951 return;
952 }
953
954 zone_key = GNUNET_IDENTITY_ego_get_private_key (ego);
955
956 int flags = MHD_USE_DUAL_STACK | MHD_USE_DEBUG | MHD_ALLOW_SUSPEND_RESUME;
957 do
958 {
959 httpd = MHD_start_daemon (flags,
960 (uint16_t) port,
961 NULL, NULL,
962 &create_response, NULL,
963 MHD_OPTION_CONNECTION_LIMIT, 128,
964 MHD_OPTION_PER_IP_CONNECTION_LIMIT, 1,
965 MHD_OPTION_CONNECTION_TIMEOUT, 4 * 1024,
966 MHD_OPTION_NOTIFY_COMPLETED, &completed_cb, NULL,
967 MHD_OPTION_END);
968 flags = MHD_USE_DEBUG;
969 } while (NULL == httpd && flags != MHD_USE_DEBUG);
970
971 if (NULL == httpd)
972 {
973 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
974 _ ("Failed to start HTTP server\n"));
975 GNUNET_SCHEDULER_shutdown ();
976 return;
977 }
978
979 run_httpd ();
980}
981
982
983/**
984 * Open a file on disk and generate a response object for it.
985 *
986 * @param name name of the file to open
987 * @param basedir directory where the file is located
988 * @return #GNUNET_SYSERR on error
989 */
990static struct StaticPage *
991open_static_page (const char *name, const char *basedir)
992{
993 char *fullname = NULL;
994 GNUNET_asprintf (&fullname, "%s/fcfsd-%s", basedir, name);
995
996 struct GNUNET_DISK_FileHandle *f =
997 GNUNET_DISK_file_open (fullname,
998 GNUNET_DISK_OPEN_READ,
999 GNUNET_DISK_PERM_NONE);
1000 GNUNET_free (fullname);
1001
1002 if (NULL == f)
1003 {
1004 return NULL;
1005 }
1006
1007 off_t size = 0;
1008 if (GNUNET_SYSERR == GNUNET_DISK_file_handle_size (f, &size))
1009 {
1010 GNUNET_DISK_file_close (f);
1011 return NULL;
1012 }
1013
1014 struct MHD_Response *response =
1015 MHD_create_response_from_fd64 (size,
1016 f->fd);
1017
1018 if (NULL == response)
1019 {
1020 GNUNET_DISK_file_close (f);
1021 return NULL;
1022 }
1023
1024 struct StaticPage *page = GNUNET_new (struct StaticPage);
1025 page->handle = f;
1026 page->size = (uint64_t) size;
1027 page->response = response;
1028 return page;
1029}
1030
1031
1032/**
1033 * Called after the service is up.
1034 *
1035 * @param cls closure
1036 * @param args remaining command line arguments
1037 * @param cfgfile name of the configuration file
1038 * @param cfg the service configuration
1039 */
1040static void
1041run_service (void *cls,
1042 char *const *args,
1043 const char *cfgfile,
1044 const struct GNUNET_CONFIGURATION_Handle *cfg)
1045{
1046 (void) cls;
1047 (void) args;
1048 (void) cfgfile;
1049
1050 GNUNET_log_setup ("fcfsd", "WARNING", NULL);
1051
1052 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg,
1053 "fcfsd",
1054 "HTTPPORT",
1055 &port))
1056 {
1057 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1058 _ ("No port specified, using default value\n"));
1059 }
1060
1061 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
1062
1063 namestore = GNUNET_NAMESTORE_connect (cfg);
1064 if (NULL == namestore)
1065 {
1066 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1067 _ ("Failed to connect to namestore\n"));
1068 GNUNET_SCHEDULER_shutdown ();
1069 return;
1070 }
1071
1072 identity = GNUNET_IDENTITY_connect (cfg, &identity_cb, NULL);
1073 if (NULL == identity)
1074 {
1075 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1076 _ ("Failed to connect to identity\n"));
1077 GNUNET_SCHEDULER_shutdown ();
1078 return;
1079 }
1080
1081 char *basedir = NULL;
1082 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg,
1083 "fcfsd",
1084 "HTMLDIR",
1085 &basedir))
1086 {
1087 basedir = GNUNET_OS_installation_get_path (GNUNET_OS_IPK_DATADIR);
1088 }
1089
1090 main_page = open_static_page ("index.html", basedir);
1091 notfound_page = open_static_page ("notfound.html", basedir);
1092 forbidden_page = open_static_page ("forbidden.html", basedir);
1093
1094 GNUNET_free (basedir);
1095
1096 if ((NULL == main_page) || (NULL == notfound_page) || (NULL ==
1097 forbidden_page) )
1098 {
1099 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1100 _ ("Unable to set up the daemon\n"));
1101 GNUNET_SCHEDULER_shutdown ();
1102 return;
1103 }
1104}
1105
1106
1107/**
1108 * The main function of the fcfs daemon.
1109 *
1110 * @param argc number of arguments from the command line
1111 * @parsm argv the command line arguments
1112 * @return 0 successful exit, a different value otherwise
1113 */
1114int
1115main (int argc, char *const *argv)
1116{
1117 struct GNUNET_GETOPT_CommandLineOption options[] = {
1118 GNUNET_GETOPT_option_mandatory
1119 (GNUNET_GETOPT_option_string ('z',
1120 "zone",
1121 "EGO",
1122 gettext_noop (
1123 "name of the zone managed by FCFSD"),
1124 &zone)),
1125 GNUNET_GETOPT_OPTION_END
1126 };
1127
1128 return ((GNUNET_OK == GNUNET_PROGRAM_run (argc,
1129 argv,
1130 "gnunet-namestore-fcfsd",
1131 _ (
1132 "GNU Name System First-Come-First-Served name registration service"),
1133 options,
1134 &run_service,
1135 NULL)) ?
1136 0 :
1137 1);
1138}
diff --git a/src/namestore/gnunet-namestore.c b/src/namestore/gnunet-namestore.c
deleted file mode 100644
index 92d2cf627..000000000
--- a/src/namestore/gnunet-namestore.c
+++ /dev/null
@@ -1,1717 +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/**
38 * Entry in record set for bulk processing.
39 */
40struct RecordSetEntry
41{
42 /**
43 * Kept in a linked list.
44 */
45 struct RecordSetEntry *next;
46
47 /**
48 * The record to add/remove.
49 */
50 struct GNUNET_GNSRECORD_Data record;
51};
52
53
54/**
55 * Handle to the namestore.
56 */
57static struct GNUNET_NAMESTORE_Handle *ns;
58
59/**
60 * Private key for the our zone.
61 */
62static struct GNUNET_IDENTITY_PrivateKey zone_pkey;
63
64/**
65 * Handle to identity lookup.
66 */
67static struct GNUNET_IDENTITY_EgoLookup *el;
68
69/**
70 * Identity service handle
71 */
72static struct GNUNET_IDENTITY_Handle *idh;
73
74/**
75 * Obtain default ego
76 */
77struct GNUNET_IDENTITY_Operation *get_default;
78
79/**
80 * Name of the ego controlling the zone.
81 */
82static char *ego_name;
83
84/**
85 * Desired action is to add a record.
86 */
87static int add;
88
89/**
90 * Queue entry for the 'add-uri' operation.
91 */
92static struct GNUNET_NAMESTORE_QueueEntry *add_qe_uri;
93
94/**
95 * Queue entry for the 'add' operation.
96 */
97static struct GNUNET_NAMESTORE_QueueEntry *add_qe;
98
99/**
100 * Queue entry for the 'lookup' operation.
101 */
102static struct GNUNET_NAMESTORE_QueueEntry *get_qe;
103
104/**
105 * Queue entry for the 'reverse lookup' operation (in combination with a name).
106 */
107static struct GNUNET_NAMESTORE_QueueEntry *reverse_qe;
108
109/**
110 * Desired action is to list records.
111 */
112static int list;
113
114/**
115 * List iterator for the 'list' operation.
116 */
117static struct GNUNET_NAMESTORE_ZoneIterator *list_it;
118
119/**
120 * Desired action is to remove a record.
121 */
122static int del;
123
124/**
125 * Is record public (opposite of #GNUNET_GNSRECORD_RF_PRIVATE)
126 */
127static int is_public;
128
129/**
130 * Is record a shadow record (#GNUNET_GNSRECORD_RF_SHADOW_RECORD)
131 */
132static int is_shadow;
133
134/**
135 * Queue entry for the 'del' operation.
136 */
137static struct GNUNET_NAMESTORE_QueueEntry *del_qe;
138
139/**
140 * Queue entry for the 'set/replace' operation.
141 */
142static struct GNUNET_NAMESTORE_QueueEntry *set_qe;
143
144/**
145 * Name of the records to add/list/remove.
146 */
147static char *name;
148
149/**
150 * Value of the record to add/remove.
151 */
152static char *value;
153
154/**
155 * URI to import.
156 */
157static char *uri;
158
159/**
160 * Reverse lookup to perform.
161 */
162static char *reverse_pkey;
163
164/**
165 * Type of the record to add/remove, NULL to remove all.
166 */
167static char *typestring;
168
169/**
170 * Desired expiration time.
171 */
172static char *expirationstring;
173
174/**
175 * Desired nick name.
176 */
177static char *nickstring;
178
179/**
180 * Global return value
181 */
182static int ret;
183
184/**
185 * Type string converted to DNS type value.
186 */
187static uint32_t type;
188
189/**
190 * Value in binary format.
191 */
192static void *data;
193
194/**
195 * Number of bytes in #data.
196 */
197static size_t data_size;
198
199/**
200 * Expiration string converted to numeric value.
201 */
202static uint64_t etime;
203
204/**
205 * Is expiration time relative or absolute time?
206 */
207static int etime_is_rel = GNUNET_SYSERR;
208
209/**
210 * Monitor handle.
211 */
212static struct GNUNET_NAMESTORE_ZoneMonitor *zm;
213
214/**
215 * Enables monitor mode.
216 */
217static int monitor;
218
219/**
220 * Entry in record set for processing records in bulk.
221 */
222static struct RecordSetEntry *recordset;
223
224
225/**
226 * Task run on shutdown. Cleans up everything.
227 *
228 * @param cls unused
229 */
230static void
231do_shutdown (void *cls)
232{
233 (void) cls;
234 if (NULL != get_default)
235 {
236 GNUNET_IDENTITY_cancel (get_default);
237 get_default = NULL;
238 }
239 if (NULL != idh)
240 {
241 GNUNET_IDENTITY_disconnect (idh);
242 idh = NULL;
243 }
244 if (NULL != el)
245 {
246 GNUNET_IDENTITY_ego_lookup_cancel (el);
247 el = NULL;
248 }
249 if (NULL != list_it)
250 {
251 GNUNET_NAMESTORE_zone_iteration_stop (list_it);
252 list_it = NULL;
253 }
254 if (NULL != add_qe)
255 {
256 GNUNET_NAMESTORE_cancel (add_qe);
257 add_qe = NULL;
258 }
259 if (NULL != set_qe)
260 {
261 GNUNET_NAMESTORE_cancel (set_qe);
262 set_qe = NULL;
263 }
264 if (NULL != add_qe_uri)
265 {
266 GNUNET_NAMESTORE_cancel (add_qe_uri);
267 add_qe_uri = NULL;
268 }
269 if (NULL != get_qe)
270 {
271 GNUNET_NAMESTORE_cancel (get_qe);
272 get_qe = NULL;
273 }
274 if (NULL != del_qe)
275 {
276 GNUNET_NAMESTORE_cancel (del_qe);
277 del_qe = NULL;
278 }
279 if (NULL != ns)
280 {
281 GNUNET_NAMESTORE_disconnect (ns);
282 ns = NULL;
283 }
284 memset (&zone_pkey, 0, sizeof(zone_pkey));
285 if (NULL != uri)
286 {
287 GNUNET_free (uri);
288 uri = NULL;
289 }
290 if (NULL != zm)
291 {
292 GNUNET_NAMESTORE_zone_monitor_stop (zm);
293 zm = NULL;
294 }
295 if (NULL != data)
296 {
297 GNUNET_free (data);
298 data = NULL;
299 }
300}
301
302
303/**
304 * Check if we are finished, and if so, perform shutdown.
305 */
306static void
307test_finished ()
308{
309 if ((NULL == add_qe) && (NULL == add_qe_uri) && (NULL == get_qe) &&
310 (NULL == del_qe) && (NULL == reverse_qe) && (NULL == list_it))
311 GNUNET_SCHEDULER_shutdown ();
312}
313
314
315/**
316 * Continuation called to notify client about result of the
317 * operation.
318 *
319 * @param cls closure, location of the QueueEntry pointer to NULL out
320 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
321 * #GNUNET_NO if content was already there
322 * #GNUNET_YES (or other positive value) on success
323 * @param emsg NULL on success, otherwise an error message
324 */
325static void
326add_continuation (void *cls, int32_t success, const char *emsg)
327{
328 struct GNUNET_NAMESTORE_QueueEntry **qe = cls;
329
330 *qe = NULL;
331 if (GNUNET_YES != success)
332 {
333 fprintf (stderr,
334 _ ("Adding record failed: %s\n"),
335 (GNUNET_NO == success) ? "record exists" : emsg);
336 if (GNUNET_NO != success)
337 ret = 1;
338 }
339 ret = 0;
340 test_finished ();
341}
342
343
344/**
345 * Continuation called to notify client about result of the
346 * operation.
347 *
348 * @param cls closure, unused
349 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
350 * #GNUNET_NO if content was already there
351 * #GNUNET_YES (or other positive value) on success
352 * @param emsg NULL on success, otherwise an error message
353 */
354static void
355del_continuation (void *cls, int32_t success, const char *emsg)
356{
357 (void) cls;
358 del_qe = NULL;
359 if (GNUNET_NO == success)
360 {
361 fprintf (stderr,
362 _ ("Deleting record failed, record does not exist%s%s\n"),
363 (NULL != emsg) ? ": " : "",
364 (NULL != emsg) ? emsg : "");
365 }
366 if (GNUNET_SYSERR == success)
367 {
368 fprintf (stderr,
369 _ ("Deleting record failed%s%s\n"),
370 (NULL != emsg) ? ": " : "",
371 (NULL != emsg) ? emsg : "");
372 }
373 test_finished ();
374}
375
376
377/**
378 * Function called when we are done with a zone iteration.
379 */
380static void
381zone_iteration_finished (void *cls)
382{
383 (void) cls;
384 list_it = NULL;
385 test_finished ();
386}
387
388
389/**
390 * Function called when we encountered an error in a zone iteration.
391 */
392static void
393zone_iteration_error_cb (void *cls)
394{
395 (void) cls;
396 list_it = NULL;
397 fprintf (stderr, "Error iterating over zone\n");
398 ret = 1;
399 test_finished ();
400}
401
402
403/**
404 * Process a record that was stored in the namestore.
405 *
406 * @param rname name that is being mapped (at most 255 characters long)
407 * @param rd_len number of entries in @a rd array
408 * @param rd array of records with data to store
409 */
410static void
411display_record (const char *rname,
412 unsigned int rd_len,
413 const struct GNUNET_GNSRECORD_Data *rd)
414{
415 const char *typestr;
416 char *s;
417 const char *ets;
418 struct GNUNET_TIME_Absolute at;
419 struct GNUNET_TIME_Relative rt;
420 int have_record;
421
422 if ((NULL != name) && (0 != strcmp (name, rname)))
423 {
424 GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
425 return;
426 }
427 have_record = GNUNET_NO;
428 for (unsigned int i = 0; i < rd_len; i++)
429 {
430 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
431 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
432 continue;
433 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
434 continue;
435 have_record = GNUNET_YES;
436 break;
437 }
438 if (GNUNET_NO == have_record)
439 return;
440 fprintf (stdout, "%s:\n", rname);
441 if (NULL != typestring)
442 type = GNUNET_GNSRECORD_typename_to_number (typestring);
443 else
444 type = GNUNET_GNSRECORD_TYPE_ANY;
445 for (unsigned int i = 0; i < rd_len; i++)
446 {
447 if ((GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type) &&
448 (0 != strcmp (rname, GNUNET_GNS_EMPTY_LABEL_AT)))
449 continue;
450 if ((type != rd[i].record_type) && (GNUNET_GNSRECORD_TYPE_ANY != type))
451 continue;
452 typestr = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
453 s = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
454 rd[i].data,
455 rd[i].data_size);
456 if (NULL == s)
457 {
458 fprintf (stdout,
459 _ ("\tCorrupt or unsupported record of type %u\n"),
460 (unsigned int) rd[i].record_type);
461 continue;
462 }
463 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
464 {
465 rt.rel_value_us = rd[i].expiration_time;
466 ets = GNUNET_STRINGS_relative_time_to_string (rt, GNUNET_YES);
467 }
468 else
469 {
470 at.abs_value_us = rd[i].expiration_time;
471 ets = GNUNET_STRINGS_absolute_time_to_string (at);
472 }
473 fprintf (stdout,
474 "\t%s: %s (%s)\t%s\t%s\n",
475 typestr,
476 s,
477 ets,
478 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_PRIVATE)) ? "PRIVATE"
479 : "PUBLIC",
480 (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) ? "SHADOW"
481 : "");
482 GNUNET_free (s);
483 }
484 fprintf (stdout, "%s", "\n");
485}
486
487
488/**
489 * Process a record that was stored in the namestore.
490 *
491 * @param cls closure
492 * @param zone_key private key of the zone
493 * @param rname name that is being mapped (at most 255 characters long)
494 * @param rd_len number of entries in @a rd array
495 * @param rd array of records with data to store
496 */
497static void
498display_record_iterator (void *cls,
499 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
500 const char *rname,
501 unsigned int rd_len,
502 const struct GNUNET_GNSRECORD_Data *rd)
503{
504 (void) cls;
505 (void) zone_key;
506 display_record (rname, rd_len, rd);
507 GNUNET_NAMESTORE_zone_iterator_next (list_it, 1);
508}
509
510
511/**
512 * Process a record that was stored in the namestore.
513 *
514 * @param cls closure
515 * @param zone_key private key of the zone
516 * @param rname name that is being mapped (at most 255 characters long)
517 * @param rd_len number of entries in @a rd array
518 * @param rd array of records with data to store
519 */
520static void
521display_record_monitor (void *cls,
522 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
523 const char *rname,
524 unsigned int rd_len,
525 const struct GNUNET_GNSRECORD_Data *rd)
526{
527 (void) cls;
528 (void) zone_key;
529 display_record (rname, rd_len, rd);
530 GNUNET_NAMESTORE_zone_monitor_next (zm, 1);
531}
532
533
534/**
535 * Process a record that was stored in the namestore.
536 *
537 * @param cls closure
538 * @param zone_key private key of the zone
539 * @param rname name that is being mapped (at most 255 characters long)
540 * @param rd_len number of entries in @a rd array
541 * @param rd array of records with data to store
542 */
543static void
544display_record_lookup (void *cls,
545 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
546 const char *rname,
547 unsigned int rd_len,
548 const struct GNUNET_GNSRECORD_Data *rd)
549{
550 (void) cls;
551 (void) zone_key;
552 get_qe = NULL;
553 display_record (rname, rd_len, rd);
554 test_finished ();
555}
556
557
558/**
559 * Function called once we are in sync in monitor mode.
560 *
561 * @param cls NULL
562 */
563static void
564sync_cb (void *cls)
565{
566 (void) cls;
567 fprintf (stdout, "%s", "Monitor is now in sync.\n");
568}
569
570
571/**
572 * Function called on errors while monitoring.
573 *
574 * @param cls NULL
575 */
576static void
577monitor_error_cb (void *cls)
578{
579 (void) cls;
580 fprintf (stderr, "%s", "Monitor disconnected and out of sync.\n");
581}
582
583
584/**
585 * Function called on errors while monitoring.
586 *
587 * @param cls NULL
588 */
589static void
590lookup_error_cb (void *cls)
591{
592 (void) cls;
593 get_qe = NULL;
594 fprintf (stderr, "%s", "Failed to lookup record.\n");
595 test_finished ();
596}
597
598
599/**
600 * Function called if lookup fails.
601 */
602static void
603add_error_cb (void *cls)
604{
605 (void) cls;
606 add_qe = NULL;
607 GNUNET_break (0);
608 ret = 1;
609 test_finished ();
610}
611
612
613/**
614 * We're storing a record; this function is given the existing record
615 * so that we can merge the information.
616 *
617 * @param cls closure, unused
618 * @param zone_key private key of the zone
619 * @param rec_name name that is being mapped (at most 255 characters long)
620 * @param rd_count number of entries in @a rd array
621 * @param rd array of records with data to store
622 */
623static void
624get_existing_record (void *cls,
625 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
626 const char *rec_name,
627 unsigned int rd_count,
628 const struct GNUNET_GNSRECORD_Data *rd)
629{
630 struct GNUNET_GNSRECORD_Data rdn[rd_count + 1];
631 struct GNUNET_GNSRECORD_Data *rde;
632
633 (void) cls;
634 (void) zone_key;
635 add_qe = NULL;
636 if (0 != strcmp (rec_name, name))
637 {
638 GNUNET_break (0);
639 ret = 1;
640 test_finished ();
641 return;
642 }
643
644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
645 "Received %u records for name `%s'\n",
646 rd_count,
647 rec_name);
648 for (unsigned int i = 0; i < rd_count; i++)
649 {
650 switch (rd[i].record_type)
651 {
652 case GNUNET_DNSPARSER_TYPE_CNAME:
653 fprintf (
654 stderr,
655 _ (
656 "A %s record exists already under `%s', no other records can be added.\n"),
657 "CNAME",
658 rec_name);
659 ret = 1;
660 test_finished ();
661 return;
662
663 case GNUNET_GNSRECORD_TYPE_PKEY:
664 case GNUNET_GNSRECORD_TYPE_EDKEY:
665 fprintf (
666 stderr,
667 _ (
668 "A zone key record exists already under `%s', no other records can be added.\n"),
669 rec_name);
670 ret = 1;
671 test_finished ();
672 return;
673
674 case GNUNET_DNSPARSER_TYPE_SOA:
675 if (GNUNET_DNSPARSER_TYPE_SOA == type)
676 {
677 fprintf (
678 stderr,
679 _ (
680 "A SOA record exists already under `%s', cannot add a second SOA to the same zone.\n"),
681 rec_name);
682 ret = 1;
683 test_finished ();
684 return;
685 }
686 break;
687 }
688 }
689 switch (type)
690 {
691 case GNUNET_DNSPARSER_TYPE_CNAME:
692 if (0 != rd_count)
693 {
694 fprintf (stderr,
695 _ (
696 "Records already exist under `%s', cannot add `%s' record.\n"),
697 rec_name,
698 "CNAME");
699 ret = 1;
700 test_finished ();
701 return;
702 }
703 break;
704
705 case GNUNET_GNSRECORD_TYPE_PKEY:
706 case GNUNET_GNSRECORD_TYPE_EDKEY:
707 if (0 != rd_count)
708 {
709 fprintf (stderr,
710 _ (
711 "Records already exist under `%s', cannot add record.\n"),
712 rec_name);
713 ret = 1;
714 test_finished ();
715 return;
716 }
717 break;
718
719 case GNUNET_GNSRECORD_TYPE_GNS2DNS:
720 for (unsigned int i = 0; i < rd_count; i++)
721 if (GNUNET_GNSRECORD_TYPE_GNS2DNS != rd[i].record_type)
722 {
723 fprintf (
724 stderr,
725 _ (
726 "Non-GNS2DNS records already exist under `%s', cannot add GNS2DNS record.\n"),
727 rec_name);
728 ret = 1;
729 test_finished ();
730 return;
731 }
732 break;
733 }
734 memset (rdn, 0, sizeof(struct GNUNET_GNSRECORD_Data));
735 GNUNET_memcpy (&rdn[1], rd, rd_count * sizeof(struct GNUNET_GNSRECORD_Data));
736 rde = &rdn[0];
737 rde->data = data;
738 rde->data_size = data_size;
739 rde->record_type = type;
740 if (1 == is_shadow)
741 rde->flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
742 if (1 != is_public)
743 rde->flags |= GNUNET_GNSRECORD_RF_PRIVATE;
744 rde->expiration_time = etime;
745 if (GNUNET_YES == etime_is_rel)
746 rde->flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
747 else if (GNUNET_NO != etime_is_rel)
748 rde->expiration_time = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
749 GNUNET_assert (NULL != name);
750 add_qe = GNUNET_NAMESTORE_records_store (ns,
751 &zone_pkey,
752 name,
753 rd_count + 1,
754 rde,
755 &add_continuation,
756 &add_qe);
757}
758
759
760/**
761 * Function called if we encountered an error in zone-to-name.
762 */
763static void
764reverse_error_cb (void *cls)
765{
766 (void) cls;
767 reverse_qe = NULL;
768 fprintf (stdout, "%s.zkey\n", reverse_pkey);
769}
770
771
772/**
773 * Function called with the result of our attempt to obtain a name for a given
774 * public key.
775 *
776 * @param cls NULL
777 * @param zone private key of the zone; NULL on disconnect
778 * @param label label of the records; NULL on disconnect
779 * @param rd_count number of entries in @a rd array, 0 if label was deleted
780 * @param rd array of records with data to store
781 */
782static void
783handle_reverse_lookup (void *cls,
784 const struct GNUNET_IDENTITY_PrivateKey *zone,
785 const char *label,
786 unsigned int rd_count,
787 const struct GNUNET_GNSRECORD_Data *rd)
788{
789 (void) cls;
790 (void) zone;
791 (void) rd_count;
792 (void) rd;
793 reverse_qe = NULL;
794 if (NULL == label)
795 fprintf (stdout, "%s\n", reverse_pkey);
796 else
797 fprintf (stdout, "%s.%s\n", label, ego_name);
798 test_finished ();
799}
800
801
802/**
803 * Function called if lookup for deletion fails.
804 */
805static void
806del_lookup_error_cb (void *cls)
807{
808 (void) cls;
809 del_qe = NULL;
810 GNUNET_break (0);
811 ret = 1;
812 test_finished ();
813}
814
815
816/**
817 * We were asked to delete something; this function is called with
818 * the existing records. Now we should determine what should be
819 * deleted and then issue the deletion operation.
820 *
821 * @param cls NULL
822 * @param zone private key of the zone we are deleting from
823 * @param label name of the records we are editing
824 * @param rd_count size of the @a rd array
825 * @param rd existing records
826 */
827static void
828del_monitor (void *cls,
829 const struct GNUNET_IDENTITY_PrivateKey *zone,
830 const char *label,
831 unsigned int rd_count,
832 const struct GNUNET_GNSRECORD_Data *rd)
833{
834 struct GNUNET_GNSRECORD_Data rdx[rd_count];
835 unsigned int rd_left;
836 uint32_t type;
837 char *vs;
838
839 (void) cls;
840 (void) zone;
841 del_qe = NULL;
842 if (0 == rd_count)
843 {
844 fprintf (stderr,
845 _ (
846 "There are no records under label `%s' that could be deleted.\n"),
847 label);
848 ret = 1;
849 test_finished ();
850 return;
851 }
852 if ((NULL == value) && (NULL == typestring))
853 {
854 /* delete everything */
855 del_qe = GNUNET_NAMESTORE_records_store (ns,
856 &zone_pkey,
857 name,
858 0,
859 NULL,
860 &del_continuation,
861 NULL);
862 return;
863 }
864 rd_left = 0;
865 if (NULL != typestring)
866 type = GNUNET_GNSRECORD_typename_to_number (typestring);
867 else
868 type = GNUNET_GNSRECORD_TYPE_ANY;
869 for (unsigned int i = 0; i < rd_count; i++)
870 {
871 vs = NULL;
872 if (! (((GNUNET_GNSRECORD_TYPE_ANY == type) ||
873 (rd[i].record_type == type)) &&
874 ((NULL == value) ||
875 (NULL ==
876 (vs = (GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
877 rd[i].data,
878 rd[i].data_size)))) ||
879 (0 == strcmp (vs, value)))))
880 rdx[rd_left++] = rd[i];
881 GNUNET_free (vs);
882 }
883 if (rd_count == rd_left)
884 {
885 /* nothing got deleted */
886 fprintf (
887 stderr,
888 _ (
889 "There are no records under label `%s' that match the request for deletion.\n"),
890 label);
891 test_finished ();
892 return;
893 }
894 /* delete everything but what we copied to 'rdx' */
895 del_qe = GNUNET_NAMESTORE_records_store (ns,
896 &zone_pkey,
897 name,
898 rd_left,
899 rdx,
900 &del_continuation,
901 NULL);
902}
903
904
905/**
906 * Parse expiration time.
907 *
908 * @param expirationstring text to parse
909 * @param etime_is_rel[out] set to #GNUNET_YES if time is relative
910 * @param etime[out] set to expiration time (abs or rel)
911 * @return #GNUNET_OK on success
912 */
913static int
914parse_expiration (const char *expirationstring,
915 int *etime_is_rel,
916 uint64_t *etime)
917{
918 struct GNUNET_TIME_Relative etime_rel;
919 struct GNUNET_TIME_Absolute etime_abs;
920
921 if (0 == strcmp (expirationstring, "never"))
922 {
923 *etime = GNUNET_TIME_UNIT_FOREVER_ABS.abs_value_us;
924 *etime_is_rel = GNUNET_NO;
925 return GNUNET_OK;
926 }
927 if (GNUNET_OK ==
928 GNUNET_STRINGS_fancy_time_to_relative (expirationstring, &etime_rel))
929 {
930 *etime_is_rel = GNUNET_YES;
931 *etime = etime_rel.rel_value_us;
932 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
933 "Storing record with relative expiration time of %s\n",
934 GNUNET_STRINGS_relative_time_to_string (etime_rel, GNUNET_NO));
935 return GNUNET_OK;
936 }
937 if (GNUNET_OK ==
938 GNUNET_STRINGS_fancy_time_to_absolute (expirationstring, &etime_abs))
939 {
940 *etime_is_rel = GNUNET_NO;
941 *etime = etime_abs.abs_value_us;
942 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
943 "Storing record with absolute expiration time of %s\n",
944 GNUNET_STRINGS_absolute_time_to_string (etime_abs));
945 return GNUNET_OK;
946 }
947 return GNUNET_SYSERR;
948}
949
950
951/**
952 * Function called when namestore is done with the replace
953 * operation.
954 *
955 * @param cls NULL
956 * @param success #GNUNET_SYSERR on failure (including timeout/queue drop/failure to validate)
957 * #GNUNET_NO if content was already there or not found
958 * #GNUNET_YES (or other positive value) on success
959 * @param emsg NULL on success, otherwise an error message
960 */
961static void
962replace_cont (void *cls, int success, const char *emsg)
963{
964 (void) cls;
965
966 set_qe = NULL;
967 if (GNUNET_OK != success)
968 {
969 GNUNET_log (GNUNET_ERROR_TYPE_MESSAGE,
970 _ ("Failed to replace records: %s\n"),
971 emsg);
972 ret = 1; /* fail from 'main' */
973 }
974 GNUNET_SCHEDULER_shutdown ();
975}
976
977
978/**
979 * We have obtained the zone's private key, so now process
980 * the main commands using it.
981 *
982 * @param cfg configuration to use
983 */
984static void
985run_with_zone_pkey (const struct GNUNET_CONFIGURATION_Handle *cfg)
986{
987 struct GNUNET_GNSRECORD_Data rd;
988
989 if (! (add | del | list | (NULL != nickstring) | (NULL != uri)
990 | (NULL != reverse_pkey) | (NULL != recordset)))
991 {
992 /* nothing more to be done */
993 fprintf (stderr, _ ("No options given\n"));
994 GNUNET_SCHEDULER_shutdown ();
995 return;
996 }
997 ns = GNUNET_NAMESTORE_connect (cfg);
998 if (NULL == ns)
999 {
1000 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1001 _ ("Failed to connect to namestore\n"));
1002 return;
1003 }
1004
1005 if (NULL != recordset)
1006 {
1007 /* replace entire record set */
1008 unsigned int rd_count;
1009 struct GNUNET_GNSRECORD_Data *rd;
1010
1011 if (NULL == name)
1012 {
1013 fprintf (stderr,
1014 _ ("Missing option `%s' for operation `%s'\n"),
1015 "-R",
1016 _ ("replace"));
1017 GNUNET_SCHEDULER_shutdown ();
1018 ret = 1;
1019 return;
1020 }
1021 rd_count = 0;
1022 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
1023 rd_count++;
1024 rd = GNUNET_new_array (rd_count, struct GNUNET_GNSRECORD_Data);
1025 rd_count = 0;
1026 for (struct RecordSetEntry *e = recordset; NULL != e; e = e->next)
1027 {
1028 rd[rd_count] = e->record;
1029 rd_count++;
1030 }
1031 set_qe = GNUNET_NAMESTORE_records_store (ns,
1032 &zone_pkey,
1033 name,
1034 rd_count,
1035 rd,
1036 &replace_cont,
1037 NULL);
1038 GNUNET_free (rd);
1039 return;
1040 }
1041 if (NULL != nickstring)
1042 {
1043 if (0 == strlen (nickstring))
1044 {
1045 fprintf (stderr, _ ("Invalid nick `%s'\n"), nickstring);
1046 GNUNET_SCHEDULER_shutdown ();
1047 ret = 1;
1048 return;
1049 }
1050 add = 1;
1051 typestring = GNUNET_strdup (GNUNET_GNSRECORD_number_to_typename (
1052 GNUNET_GNSRECORD_TYPE_NICK));
1053 name = GNUNET_strdup (GNUNET_GNS_EMPTY_LABEL_AT);
1054 value = GNUNET_strdup (nickstring);
1055 is_public = 0;
1056 expirationstring = GNUNET_strdup ("never");
1057 GNUNET_free (nickstring);
1058 nickstring = NULL;
1059 }
1060
1061 if (add)
1062 {
1063 if (NULL == name)
1064 {
1065 fprintf (stderr,
1066 _ ("Missing option `%s' for operation `%s'\n"),
1067 "-n",
1068 _ ("add"));
1069 GNUNET_SCHEDULER_shutdown ();
1070 ret = 1;
1071 return;
1072 }
1073 if (NULL == typestring)
1074 {
1075 fprintf (stderr,
1076 _ ("Missing option `%s' for operation `%s'\n"),
1077 "-t",
1078 _ ("add"));
1079 GNUNET_SCHEDULER_shutdown ();
1080 ret = 1;
1081 return;
1082 }
1083 type = GNUNET_GNSRECORD_typename_to_number (typestring);
1084 if (UINT32_MAX == type)
1085 {
1086 fprintf (stderr, _ ("Unsupported type `%s'\n"), typestring);
1087 GNUNET_SCHEDULER_shutdown ();
1088 ret = 1;
1089 return;
1090 }
1091 if ((GNUNET_DNSPARSER_TYPE_SRV == type) ||
1092 (GNUNET_DNSPARSER_TYPE_TLSA == type) ||
1093 (GNUNET_DNSPARSER_TYPE_OPENPGPKEY == type))
1094 {
1095 fprintf (stderr,
1096 _ ("For DNS record types `SRV', `TLSA' and `OPENPGPKEY'"));
1097 fprintf (stderr, ", please use a `BOX' record instead\n");
1098 GNUNET_SCHEDULER_shutdown ();
1099 ret = 1;
1100 return;
1101 }
1102 if (NULL == value)
1103 {
1104 fprintf (stderr,
1105 _ ("Missing option `%s' for operation `%s'\n"),
1106 "-V",
1107 _ ("add"));
1108 ret = 1;
1109 GNUNET_SCHEDULER_shutdown ();
1110 return;
1111 }
1112 if (GNUNET_OK !=
1113 GNUNET_GNSRECORD_string_to_value (type, value, &data, &data_size))
1114 {
1115 fprintf (stderr,
1116 _ ("Value `%s' invalid for record type `%s'\n"),
1117 value,
1118 typestring);
1119 GNUNET_SCHEDULER_shutdown ();
1120 ret = 1;
1121 return;
1122 }
1123 if (NULL == expirationstring)
1124 {
1125 fprintf (stderr,
1126 _ ("Missing option `%s' for operation `%s'\n"),
1127 "-e",
1128 _ ("add"));
1129 GNUNET_SCHEDULER_shutdown ();
1130 ret = 1;
1131 return;
1132 }
1133 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1134 {
1135 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1136 GNUNET_SCHEDULER_shutdown ();
1137 ret = 1;
1138 return;
1139 }
1140 add_qe = GNUNET_NAMESTORE_records_lookup (ns,
1141 &zone_pkey,
1142 name,
1143 &add_error_cb,
1144 NULL,
1145 &get_existing_record,
1146 NULL);
1147 }
1148 if (del)
1149 {
1150 if (NULL == name)
1151 {
1152 fprintf (stderr,
1153 _ ("Missing option `%s' for operation `%s'\n"),
1154 "-n",
1155 _ ("del"));
1156 GNUNET_SCHEDULER_shutdown ();
1157 ret = 1;
1158 return;
1159 }
1160 del_qe = GNUNET_NAMESTORE_records_lookup (ns,
1161 &zone_pkey,
1162 name,
1163 &del_lookup_error_cb,
1164 NULL,
1165 &del_monitor,
1166 NULL);
1167 }
1168 if (list)
1169 {
1170 if (NULL != name)
1171 get_qe = GNUNET_NAMESTORE_records_lookup (ns,
1172 &zone_pkey,
1173 name,
1174 &lookup_error_cb,
1175 NULL,
1176 &display_record_lookup,
1177 NULL);
1178 else
1179 list_it = GNUNET_NAMESTORE_zone_iteration_start (ns,
1180 &zone_pkey,
1181 &zone_iteration_error_cb,
1182 NULL,
1183 &display_record_iterator,
1184 NULL,
1185 &zone_iteration_finished,
1186 NULL);
1187 }
1188 if (NULL != reverse_pkey)
1189 {
1190 struct GNUNET_IDENTITY_PublicKey pubkey;
1191
1192 if (GNUNET_OK !=
1193 GNUNET_IDENTITY_public_key_from_string (reverse_pkey,
1194 &pubkey))
1195 {
1196 fprintf (stderr,
1197 _ ("Invalid public key for reverse lookup `%s'\n"),
1198 reverse_pkey);
1199 GNUNET_SCHEDULER_shutdown ();
1200 }
1201 reverse_qe = GNUNET_NAMESTORE_zone_to_name (ns,
1202 &zone_pkey,
1203 &pubkey,
1204 &reverse_error_cb,
1205 NULL,
1206 &handle_reverse_lookup,
1207 NULL);
1208 }
1209 if (NULL != uri)
1210 {
1211 char sh[105];
1212 char sname[64];
1213 struct GNUNET_IDENTITY_PublicKey pkey;
1214
1215 GNUNET_STRINGS_utf8_tolower (uri, uri);
1216 if ((2 != (sscanf (uri, "gnunet://gns/%52s/%63s", sh, sname))) ||
1217 (GNUNET_OK !=
1218 GNUNET_IDENTITY_public_key_from_string (sh, &pkey)))
1219 {
1220 fprintf (stderr, _ ("Invalid URI `%s'\n"), uri);
1221 GNUNET_SCHEDULER_shutdown ();
1222 ret = 1;
1223 return;
1224 }
1225 if (NULL == expirationstring)
1226 {
1227 fprintf (stderr,
1228 _ ("Missing option `%s' for operation `%s'\n"),
1229 "-e",
1230 _ ("add"));
1231 GNUNET_SCHEDULER_shutdown ();
1232 ret = 1;
1233 return;
1234 }
1235 if (GNUNET_OK != parse_expiration (expirationstring, &etime_is_rel, &etime))
1236 {
1237 fprintf (stderr, _ ("Invalid time format `%s'\n"), expirationstring);
1238 GNUNET_SCHEDULER_shutdown ();
1239 ret = 1;
1240 return;
1241 }
1242 memset (&rd, 0, sizeof(rd));
1243 rd.data = &pkey;
1244 rd.data_size = GNUNET_IDENTITY_key_get_length (&pkey);
1245 rd.record_type = ntohl (pkey.type);
1246 rd.expiration_time = etime;
1247 if (GNUNET_YES == etime_is_rel)
1248 rd.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1249 if (1 == is_shadow)
1250 rd.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1251 add_qe_uri = GNUNET_NAMESTORE_records_store (ns,
1252 &zone_pkey,
1253 sname,
1254 1,
1255 &rd,
1256 &add_continuation,
1257 &add_qe_uri);
1258 }
1259 if (monitor)
1260 {
1261 zm = GNUNET_NAMESTORE_zone_monitor_start (cfg,
1262 &zone_pkey,
1263 GNUNET_YES,
1264 &monitor_error_cb,
1265 NULL,
1266 &display_record_monitor,
1267 NULL,
1268 &sync_cb,
1269 NULL);
1270 }
1271}
1272
1273
1274/**
1275 * Callback invoked from identity service with ego information.
1276 * An @a ego of NULL means the ego was not found.
1277 *
1278 * @param cls closure with the configuration
1279 * @param ego an ego known to identity service, or NULL
1280 */
1281static void
1282identity_cb (void *cls, struct GNUNET_IDENTITY_Ego *ego)
1283{
1284 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1285
1286 el = NULL;
1287 if ((NULL != name) && (0 != strchr (name, '.')))
1288 {
1289 fprintf (stderr,
1290 _ ("Label `%s' contains `.' which is not allowed\n"),
1291 name);
1292 GNUNET_SCHEDULER_shutdown ();
1293 ret = -1;
1294 return;
1295 }
1296
1297 if (NULL == ego)
1298 {
1299 if (NULL != ego_name)
1300 {
1301 fprintf (stderr,
1302 _ ("Ego `%s' not known to identity service\n"),
1303 ego_name);
1304 }
1305 GNUNET_SCHEDULER_shutdown ();
1306 ret = -1;
1307 return;
1308 }
1309 zone_pkey = *GNUNET_IDENTITY_ego_get_private_key (ego);
1310 GNUNET_free (ego_name);
1311 ego_name = NULL;
1312 run_with_zone_pkey (cfg);
1313}
1314
1315
1316/**
1317 * Function called with the default ego to be used for GNS
1318 * operations. Used if the user did not specify a zone via
1319 * command-line or environment variables.
1320 *
1321 * @param cls NULL
1322 * @param ego default ego, NULL for none
1323 * @param ctx NULL
1324 * @param name unused
1325 */
1326static void
1327default_ego_cb (void *cls,
1328 struct GNUNET_IDENTITY_Ego *ego,
1329 void **ctx,
1330 const char *name)
1331{
1332 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1333
1334 (void) ctx;
1335 (void) name;
1336 get_default = NULL;
1337 if (NULL == ego)
1338 {
1339 fprintf (stderr,
1340 _ ("No default identity configured for `namestore' subsystem\n"
1341 "Run gnunet-identity -s namestore -e $NAME to set the default to $NAME\n"
1342 "Run gnunet-identity -d to get a list of choices for $NAME\n"));
1343 GNUNET_SCHEDULER_shutdown ();
1344 ret = -1;
1345 return;
1346 }
1347 else
1348 {
1349 identity_cb ((void *) cfg, ego);
1350 }
1351}
1352
1353
1354/**
1355 * Function called with ALL of the egos known to the
1356 * identity service, used on startup if the user did
1357 * not specify a zone on the command-line.
1358 * Once the iteration is done (@a ego is NULL), we
1359 * ask for the default ego for "namestore".
1360 *
1361 * @param cls a `struct GNUNET_CONFIGURATION_Handle`
1362 * @param ego an ego, NULL for end of iteration
1363 * @param ctx NULL
1364 * @param name name associated with @a ego
1365 */
1366static void
1367id_connect_cb (void *cls,
1368 struct GNUNET_IDENTITY_Ego *ego,
1369 void **ctx,
1370 const char *name)
1371{
1372 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
1373
1374 (void) ctx;
1375 (void) name;
1376 if (NULL != ego)
1377 return;
1378 get_default =
1379 GNUNET_IDENTITY_get (idh, "namestore", &default_ego_cb, (void *) cfg);
1380}
1381
1382
1383/**
1384 * Main function that will be run.
1385 *
1386 * @param cls closure
1387 * @param args remaining command-line arguments
1388 * @param cfgfile name of the configuration file used (for saving, can be NULL!)
1389 * @param cfg configuration
1390 */
1391static void
1392run (void *cls,
1393 char *const *args,
1394 const char *cfgfile,
1395 const struct GNUNET_CONFIGURATION_Handle *cfg)
1396{
1397 const char *pkey_str;
1398
1399 (void) cls;
1400 (void) args;
1401 (void) cfgfile;
1402 if (NULL != args[0])
1403 GNUNET_log (
1404 GNUNET_ERROR_TYPE_WARNING,
1405 _ ("Superfluous command line arguments (starting with `%s') ignored\n"),
1406 args[0]);
1407 if ((NULL != args[0]) && (NULL == uri))
1408 uri = GNUNET_strdup (args[0]);
1409
1410 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, (void *) cfg);
1411 pkey_str = getenv ("GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1412 if (NULL != pkey_str)
1413 {
1414 if (GNUNET_OK != GNUNET_STRINGS_string_to_data (pkey_str,
1415 strlen (pkey_str),
1416 &zone_pkey,
1417 sizeof(zone_pkey)))
1418 {
1419 fprintf (stderr,
1420 "Malformed private key `%s' in $%s\n",
1421 pkey_str,
1422 "GNUNET_NAMESTORE_EGO_PRIVATE_KEY");
1423 ret = 1;
1424 GNUNET_SCHEDULER_shutdown ();
1425 return;
1426 }
1427 run_with_zone_pkey (cfg);
1428 return;
1429 }
1430 if (NULL == ego_name)
1431 {
1432 idh = GNUNET_IDENTITY_connect (cfg, &id_connect_cb, (void *) cfg);
1433 if (NULL == idh)
1434 fprintf (stderr, _ ("Cannot connect to identity service\n"));
1435 ret = -1;
1436 return;
1437 }
1438 el = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &identity_cb, (void *) cfg);
1439}
1440
1441
1442/**
1443 * Command-line option parser function that allows the user to specify
1444 * a complete record as one argument for adding/removing. A pointer
1445 * to the head of the list of record sets must be passed as the "scls"
1446 * argument.
1447 *
1448 * @param ctx command line processor context
1449 * @param scls must be of type "struct GNUNET_FS_Uri **"
1450 * @param option name of the option (typically 'R')
1451 * @param value command line argument given; format is
1452 * "TTL TYPE FLAGS VALUE" where TTL is an expiration time (rel or abs),
1453 * always given in seconds (without the unit),
1454 * TYPE is a DNS/GNS record type, FLAGS is either "n" for no flags or
1455 * a combination of 's' (shadow) and 'p' (public) and VALUE is the
1456 * value (in human-readable format)
1457 * @return #GNUNET_OK on success
1458 */
1459static int
1460multirecord_process (struct GNUNET_GETOPT_CommandLineProcessorContext *ctx,
1461 void *scls,
1462 const char *option,
1463 const char *value)
1464{
1465 struct RecordSetEntry **head = scls;
1466 struct RecordSetEntry *r;
1467 struct GNUNET_GNSRECORD_Data record;
1468 char *cp;
1469 char *tok;
1470 char *saveptr;
1471 int etime_is_rel;
1472 void *raw_data;
1473
1474 (void) ctx;
1475 (void) option;
1476 cp = GNUNET_strdup (value);
1477 tok = strtok_r (cp, " ", &saveptr);
1478 if (NULL == tok)
1479 {
1480 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1481 _ ("Empty record line argument is not allowed.\n"));
1482 GNUNET_free (cp);
1483 return GNUNET_SYSERR;
1484 }
1485 {
1486 char *etime_in_s;
1487
1488 GNUNET_asprintf (&etime_in_s, "%s s", tok);
1489 if (GNUNET_OK !=
1490 parse_expiration (etime_in_s, &etime_is_rel, &record.expiration_time))
1491 {
1492 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1493 _ ("Invalid expiration time `%s' (must be without unit)\n"),
1494 tok);
1495 GNUNET_free (cp);
1496 GNUNET_free (etime_in_s);
1497 return GNUNET_SYSERR;
1498 }
1499 GNUNET_free (etime_in_s);
1500 }
1501 tok = strtok_r (NULL, " ", &saveptr);
1502 if (NULL == tok)
1503 {
1504 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1505 _ ("Missing entries in record line `%s'.\n"),
1506 value);
1507 GNUNET_free (cp);
1508 return GNUNET_SYSERR;
1509 }
1510 record.record_type = GNUNET_GNSRECORD_typename_to_number (tok);
1511 if (UINT32_MAX == record.record_type)
1512 {
1513 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _ ("Unknown record type `%s'\n"), tok);
1514 GNUNET_free (cp);
1515 return GNUNET_SYSERR;
1516 }
1517 tok = strtok_r (NULL, " ", &saveptr);
1518 if (NULL == tok)
1519 {
1520 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1521 _ ("Missing entries in record line `%s'.\n"),
1522 value);
1523 GNUNET_free (cp);
1524 return GNUNET_SYSERR;
1525 }
1526 record.flags = GNUNET_GNSRECORD_RF_NONE;
1527 if (etime_is_rel)
1528 record.flags |= GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION;
1529 if (NULL == strchr (tok, (unsigned char) 'p')) /* p = public */
1530 record.flags |= GNUNET_GNSRECORD_RF_PRIVATE;
1531 if (NULL != strchr (tok, (unsigned char) 's'))
1532 record.flags |= GNUNET_GNSRECORD_RF_SHADOW_RECORD;
1533 /* find beginning of record value */
1534 tok = strchr (&value[tok - cp], (unsigned char) ' ');
1535 if (NULL == tok)
1536 {
1537 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1538 _ ("Missing entries in record line `%s'.\n"),
1539 value);
1540 GNUNET_free (cp);
1541 return GNUNET_SYSERR;
1542 }
1543 GNUNET_free (cp);
1544 tok++; /* skip space */
1545 if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value (record.record_type,
1546 tok,
1547 &raw_data,
1548 &record.data_size))
1549 {
1550 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1551 _ ("Invalid record data for type %s: `%s'.\n"),
1552 GNUNET_GNSRECORD_number_to_typename (record.record_type),
1553 tok);
1554 return GNUNET_SYSERR;
1555 }
1556
1557 r = GNUNET_malloc (sizeof(struct RecordSetEntry) + record.data_size);
1558 r->next = *head;
1559 record.data = &r[1];
1560 memcpy (&r[1], raw_data, record.data_size);
1561 GNUNET_free (raw_data);
1562 r->record = record;
1563 *head = r;
1564 return GNUNET_OK;
1565}
1566
1567
1568/**
1569 * Allow user to specify keywords.
1570 *
1571 * @param shortName short name of the option
1572 * @param name long name of the option
1573 * @param argumentHelp help text for the option argument
1574 * @param description long help text for the option
1575 * @param[out] topKeywords set to the desired value
1576 */
1577struct GNUNET_GETOPT_CommandLineOption
1578multirecord_option (char shortName,
1579 const char *name,
1580 const char *argumentHelp,
1581 const char *description,
1582 struct RecordSetEntry **rs)
1583{
1584 struct GNUNET_GETOPT_CommandLineOption clo = { .shortName = shortName,
1585 .name = name,
1586 .argumentHelp = argumentHelp,
1587 .description = description,
1588 .require_argument = 1,
1589 .processor =
1590 &multirecord_process,
1591 .scls = (void *) rs };
1592
1593 return clo;
1594}
1595
1596
1597/**
1598 * The main function for gnunet-namestore.
1599 *
1600 * @param argc number of arguments from the command line
1601 * @param argv command line arguments
1602 * @return 0 ok, 1 on error
1603 */
1604int
1605main (int argc, char *const *argv)
1606{
1607 struct GNUNET_GETOPT_CommandLineOption options[] =
1608 { GNUNET_GETOPT_option_flag ('a', "add", gettext_noop ("add record"), &add),
1609 GNUNET_GETOPT_option_flag ('d',
1610 "delete",
1611 gettext_noop ("delete record"),
1612 &del),
1613 GNUNET_GETOPT_option_flag ('D',
1614 "display",
1615 gettext_noop ("display records"),
1616 &list),
1617 GNUNET_GETOPT_option_string (
1618 'e',
1619 "expiration",
1620 "TIME",
1621 gettext_noop (
1622 "expiration time for record to use (for adding only), \"never\" is possible"),
1623 &expirationstring),
1624 GNUNET_GETOPT_option_string ('i',
1625 "nick",
1626 "NICKNAME",
1627 gettext_noop (
1628 "set the desired nick name for the zone"),
1629 &nickstring),
1630 GNUNET_GETOPT_option_flag ('m',
1631 "monitor",
1632 gettext_noop (
1633 "monitor changes in the namestore"),
1634 &monitor),
1635 GNUNET_GETOPT_option_string ('n',
1636 "name",
1637 "NAME",
1638 gettext_noop (
1639 "name of the record to add/delete/display"),
1640 &name),
1641 GNUNET_GETOPT_option_string ('r',
1642 "reverse",
1643 "PKEY",
1644 gettext_noop (
1645 "determine our name for the given PKEY"),
1646 &reverse_pkey),
1647 multirecord_option (
1648 'R',
1649 "replace",
1650 "RECORDLINE",
1651 gettext_noop (
1652 "set record set to values given by (possibly multiple) RECORDLINES; can be specified multiple times"),
1653 &recordset),
1654 GNUNET_GETOPT_option_string ('t',
1655 "type",
1656 "TYPE",
1657 gettext_noop (
1658 "type of the record to add/delete/display"),
1659 &typestring),
1660 GNUNET_GETOPT_option_string ('u',
1661 "uri",
1662 "URI",
1663 gettext_noop ("URI to import into our zone"),
1664 &uri),
1665 GNUNET_GETOPT_option_string ('V',
1666 "value",
1667 "VALUE",
1668 gettext_noop (
1669 "value of the record to add/delete"),
1670 &value),
1671 GNUNET_GETOPT_option_flag ('p',
1672 "public",
1673 gettext_noop ("create or list public record"),
1674 &is_public),
1675 GNUNET_GETOPT_option_flag (
1676 's',
1677 "shadow",
1678 gettext_noop (
1679 "create shadow record (only valid if all other records of the same type have expired"),
1680 &is_shadow),
1681 GNUNET_GETOPT_option_string ('z',
1682 "zone",
1683 "EGO",
1684 gettext_noop (
1685 "name of the ego controlling the zone"),
1686 &ego_name),
1687 GNUNET_GETOPT_OPTION_END };
1688 int lret;
1689
1690 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
1691 return 2;
1692
1693 is_public = -1;
1694 is_shadow = -1;
1695 GNUNET_log_setup ("gnunet-namestore", "WARNING", NULL);
1696 if (GNUNET_OK !=
1697 (lret = GNUNET_PROGRAM_run (argc,
1698 argv,
1699 "gnunet-namestore",
1700 _ ("GNUnet zone manipulation tool"),
1701 options,
1702 &run,
1703 NULL)))
1704 {
1705 GNUNET_free_nz ((void *) argv);
1706 //FIXME
1707 //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1708 return lret;
1709 }
1710 GNUNET_free_nz ((void *) argv);
1711 //FIXME
1712 //GNUNET_CRYPTO_ecdsa_key_clear (&zone_pkey);
1713 return ret;
1714}
1715
1716
1717/* 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 cd953492e..000000000
--- a/src/namestore/gnunet-service-namestore.c
+++ /dev/null
@@ -1,2276 +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/**
126 * A namestore client
127 */
128struct NamestoreClient
129{
130 /**
131 * The client
132 */
133 struct GNUNET_SERVICE_Client *client;
134
135 /**
136 * Message queue for transmission to @e client
137 */
138 struct GNUNET_MQ_Handle *mq;
139
140 /**
141 * Head of the DLL of
142 * Zone iteration operations in progress initiated by this client
143 */
144 struct ZoneIteration *op_head;
145
146 /**
147 * Tail of the DLL of
148 * Zone iteration operations in progress initiated by this client
149 */
150 struct ZoneIteration *op_tail;
151};
152
153
154/**
155 * A namestore monitor.
156 */
157struct ZoneMonitor
158{
159 /**
160 * Next element in the DLL
161 */
162 struct ZoneMonitor *next;
163
164 /**
165 * Previous element in the DLL
166 */
167 struct ZoneMonitor *prev;
168
169 /**
170 * Namestore client which intiated this zone monitor
171 */
172 struct NamestoreClient *nc;
173
174 /**
175 * Private key of the zone.
176 */
177 struct GNUNET_IDENTITY_PrivateKey zone;
178
179 /**
180 * Task active during initial iteration.
181 */
182 struct GNUNET_SCHEDULER_Task *task;
183
184 /**
185 * Task to warn about slow monitors.
186 */
187 struct GNUNET_SCHEDULER_Task *sa_wait_warning;
188
189 /**
190 * Since when are we blocked on this monitor?
191 */
192 struct GNUNET_TIME_Absolute sa_waiting_start;
193
194 /**
195 * Last sequence number in the zone iteration used to address next
196 * result of the zone iteration in the store
197 *
198 * Initially set to 0.
199 * Updated in #monitor_iterate_cb()
200 */
201 uint64_t seq;
202
203 /**
204 * Current limit of how many more messages we are allowed
205 * to queue to this monitor.
206 */
207 uint64_t limit;
208
209 /**
210 * How many more requests may we receive from the iterator
211 * before it is at the limit we gave it? Will be below or
212 * equal to @e limit. The effective limit for monitor
213 * events is thus @e iteration_cnt - @e limit!
214 */
215 uint64_t iteration_cnt;
216
217 /**
218 * Are we (still) in the initial iteration pass?
219 */
220 int in_first_iteration;
221
222 /**
223 * Is there a store activity waiting for this monitor? We only raise the
224 * flag when it happens and search the DLL for the store activity when we
225 * had a limit increase. If we cannot find any waiting store activity at
226 * that time, we clear the flag again.
227 */
228 int sa_waiting;
229};
230
231
232/**
233 * Pending operation on the namecache.
234 */
235struct CacheOperation
236{
237 /**
238 * Kept in a DLL.
239 */
240 struct CacheOperation *prev;
241
242 /**
243 * Kept in a DLL.
244 */
245 struct CacheOperation *next;
246
247 /**
248 * Handle to namecache queue.
249 */
250 struct GNUNET_NAMECACHE_QueueEntry *qe;
251
252 /**
253 * Client to notify about the result, can be NULL.
254 */
255 struct NamestoreClient *nc;
256
257 /**
258 * Zone iteration to call #zone_iteration_done_client_continue()
259 * for if applicable, can be NULL.
260 */
261 struct ZoneIteration *zi;
262
263 /**
264 * Client's request ID.
265 */
266 uint32_t rid;
267};
268
269
270/**
271 * Information for an ongoing #handle_record_store() operation.
272 * Needed as we may wait for monitors to be ready for the notification.
273 */
274struct StoreActivity
275{
276 /**
277 * Kept in a DLL.
278 */
279 struct StoreActivity *next;
280
281 /**
282 * Kept in a DLL.
283 */
284 struct StoreActivity *prev;
285
286 /**
287 * Which client triggered the store activity?
288 */
289 struct NamestoreClient *nc;
290
291 /**
292 * Copy of the original store message (as data fields in @e rd will
293 * point into it!).
294 */
295 const struct RecordStoreMessage *rsm;
296
297 /**
298 * Next zone monitor that still needs to be notified about this PUT.
299 */
300 struct ZoneMonitor *zm_pos;
301
302 /**
303 * Label nicely canonicalized (lower case).
304 */
305 char *conv_name;
306};
307
308
309/**
310 * Entry in list of cached nick resolutions.
311 */
312struct NickCache
313{
314 /**
315 * Zone the cache entry is for.
316 */
317 struct GNUNET_IDENTITY_PrivateKey zone;
318
319 /**
320 * Cached record data.
321 */
322 struct GNUNET_GNSRECORD_Data *rd;
323
324 /**
325 * Timestamp when this cache entry was used last.
326 */
327 struct GNUNET_TIME_Absolute last_used;
328};
329
330
331/**
332 * We cache nick records to reduce DB load.
333 */
334static struct NickCache nick_cache[NC_SIZE];
335
336/**
337 * Public key of all zeros.
338 */
339static const struct GNUNET_IDENTITY_PrivateKey zero;
340
341/**
342 * Configuration handle.
343 */
344static const struct GNUNET_CONFIGURATION_Handle *GSN_cfg;
345
346/**
347 * Handle to the statistics service
348 */
349static struct GNUNET_STATISTICS_Handle *statistics;
350
351/**
352 * Namecache handle.
353 */
354static struct GNUNET_NAMECACHE_Handle *namecache;
355
356/**
357 * Database handle
358 */
359static struct GNUNET_NAMESTORE_PluginFunctions *GSN_database;
360
361/**
362 * Name of the database plugin
363 */
364static char *db_lib_name;
365
366/**
367 * Head of cop DLL.
368 */
369static struct CacheOperation *cop_head;
370
371/**
372 * Tail of cop DLL.
373 */
374static struct CacheOperation *cop_tail;
375
376/**
377 * First active zone monitor.
378 */
379static struct ZoneMonitor *monitor_head;
380
381/**
382 * Last active zone monitor.
383 */
384static struct ZoneMonitor *monitor_tail;
385
386/**
387 * Head of DLL of monitor-blocked store activities.
388 */
389static struct StoreActivity *sa_head;
390
391/**
392 * Tail of DLL of monitor-blocked store activities.
393 */
394static struct StoreActivity *sa_tail;
395
396/**
397 * Notification context shared by all monitors.
398 */
399static struct GNUNET_NotificationContext *monitor_nc;
400
401/**
402 * Optimize block insertion by caching map of private keys to
403 * public keys in memory?
404 */
405static int cache_keys;
406
407/**
408 * Use the namecache? Doing so creates additional cryptographic
409 * operations whenever we touch a record.
410 */
411static int disable_namecache;
412
413
414/**
415 * Task run during shutdown.
416 *
417 * @param cls unused
418 */
419static void
420cleanup_task (void *cls)
421{
422 struct CacheOperation *cop;
423
424 (void) cls;
425 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping namestore service\n");
426 while (NULL != (cop = cop_head))
427 {
428 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
429 "Aborting incomplete namecache operation\n");
430 GNUNET_NAMECACHE_cancel (cop->qe);
431 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
432 GNUNET_free (cop);
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, uint32_t rid)
812{
813 struct GNUNET_MQ_Envelope *env;
814 struct RecordStoreResponseMessage *rcr_msg;
815
816 GNUNET_assert (NULL != nc);
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
818 "Sending RECORD_STORE_RESPONSE message\n");
819 GNUNET_STATISTICS_update (statistics,
820 "Store requests completed",
821 1,
822 GNUNET_NO);
823 env = GNUNET_MQ_msg (rcr_msg,
824 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE);
825 rcr_msg->gns_header.r_id = htonl (rid);
826 rcr_msg->op_result = htonl (res);
827 GNUNET_MQ_send (nc->mq, env);
828}
829
830
831/**
832 * Function called once we are done with the zone iteration and
833 * allow the zone iteration client to send us more messages.
834 *
835 * @param zi zone iteration we are processing
836 */
837static void
838zone_iteration_done_client_continue (struct ZoneIteration *zi)
839{
840 struct GNUNET_MQ_Envelope *env;
841 struct GNUNET_NAMESTORE_Header *em;
842
843 GNUNET_SERVICE_client_continue (zi->nc->client);
844 if (! zi->send_end)
845 return;
846 /* send empty response to indicate end of list */
847 env = GNUNET_MQ_msg (em, GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END);
848 em->r_id = htonl (zi->request_id);
849 GNUNET_MQ_send (zi->nc->mq, env);
850
851 GNUNET_CONTAINER_DLL_remove (zi->nc->op_head, zi->nc->op_tail, zi);
852 GNUNET_free (zi);
853}
854
855
856/**
857 * Cache operation complete, clean up.
858 *
859 * @param cls the `struct CacheOperation`
860 * @param success success
861 * @param emsg error messages
862 */
863static void
864finish_cache_operation (void *cls, int32_t success, const char *emsg)
865{
866 struct CacheOperation *cop = cls;
867 struct ZoneIteration *zi;
868
869 if (NULL != emsg)
870 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
871 _ ("Failed to replicate block in namecache: %s\n"),
872 emsg);
873 else
874 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CACHE operation completed\n");
875 GNUNET_CONTAINER_DLL_remove (cop_head, cop_tail, cop);
876 if (NULL != cop->nc)
877 send_store_response (cop->nc, success, cop->rid);
878 if (NULL != (zi = cop->zi))
879 {
880 zi->cache_ops--;
881 if (0 == zi->cache_ops)
882 {
883 /* unchoke zone iteration, cache has caught up */
884 zone_iteration_done_client_continue (zi);
885 }
886 }
887 GNUNET_free (cop);
888}
889
890
891/**
892 * We just touched the plaintext information about a name in our zone;
893 * refresh the corresponding (encrypted) block in the namecache.
894 *
895 * @param nc client responsible for the request, can be NULL
896 * @param zi zone iteration response for the request, can be NULL
897 * @param rid request ID of the client
898 * @param zone_key private key of the zone
899 * @param name label for the records
900 * @param rd_count number of records
901 * @param rd records stored under the given @a name
902 */
903static void
904refresh_block (struct NamestoreClient *nc,
905 struct ZoneIteration *zi,
906 uint32_t rid,
907 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
908 const char *name,
909 unsigned int rd_count,
910 const struct GNUNET_GNSRECORD_Data *rd)
911{
912 struct GNUNET_GNSRECORD_Block *block;
913 struct CacheOperation *cop;
914 struct GNUNET_IDENTITY_PublicKey pkey;
915 struct GNUNET_GNSRECORD_Data *nick;
916 struct GNUNET_GNSRECORD_Data *res;
917 unsigned int res_count;
918 struct GNUNET_TIME_Absolute exp_time;
919
920 nick = get_nick_record (zone_key);
921 res_count = rd_count;
922 res = (struct GNUNET_GNSRECORD_Data *) rd; /* fixme: a bit unclean... */
923 if ((NULL != nick) && (0 != strcmp (name, GNUNET_GNS_EMPTY_LABEL_AT)))
924 {
925 nick->flags =
926 (nick->flags | GNUNET_GNSRECORD_RF_PRIVATE) ^ GNUNET_GNSRECORD_RF_PRIVATE;
927 merge_with_nick_records (nick, rd_count, rd, &res_count, &res);
928 }
929 if (NULL != nick)
930 GNUNET_free (nick);
931 if (0 == res_count)
932 {
933 if (NULL != nc)
934 send_store_response (nc, GNUNET_OK, rid);
935 if (rd != res)
936 GNUNET_free (res);
937 return; /* no data, no need to update cache */
938 }
939 if (GNUNET_YES == disable_namecache)
940 {
941 GNUNET_STATISTICS_update (statistics,
942 "Namecache updates skipped (NC disabled)",
943 1,
944 GNUNET_NO);
945 if (NULL != nc)
946 send_store_response (nc, GNUNET_OK, rid);
947 if (rd != res)
948 GNUNET_free (res);
949 return;
950 }
951 exp_time = GNUNET_GNSRECORD_record_get_expiration_time (res_count, res);
952 if (cache_keys)
953 block =
954 GNUNET_GNSRECORD_block_create2 (zone_key, exp_time, name, res, res_count);
955 else
956 block =
957 GNUNET_GNSRECORD_block_create (zone_key, exp_time, name, res, res_count);
958 GNUNET_assert (NULL != block);
959 GNUNET_IDENTITY_key_get_public (zone_key, &pkey);
960 GNUNET_log (
961 GNUNET_ERROR_TYPE_DEBUG,
962 "Caching block for label `%s' with %u records and expiration %s in zone `%s' in namecache\n",
963 name,
964 res_count,
965 GNUNET_STRINGS_absolute_time_to_string (exp_time),
966 GNUNET_GNSRECORD_z2s (&pkey));
967 GNUNET_STATISTICS_update (statistics,
968 "Namecache updates pushed",
969 1,
970 GNUNET_NO);
971 cop = GNUNET_new (struct CacheOperation);
972 cop->nc = nc;
973 cop->zi = zi;
974 if (NULL != zi)
975 zi->cache_ops++;
976 cop->rid = rid;
977 GNUNET_CONTAINER_DLL_insert (cop_head, cop_tail, cop);
978 cop->qe = GNUNET_NAMECACHE_block_cache (namecache,
979 block,
980 &finish_cache_operation,
981 cop);
982 GNUNET_free (block);
983 if (rd != res)
984 GNUNET_free (res);
985}
986
987
988/**
989 * Print a warning that one of our monitors is no longer reacting.
990 *
991 * @param cls a `struct ZoneMonitor` to warn about
992 */
993static void
994warn_monitor_slow (void *cls)
995{
996 struct ZoneMonitor *zm = cls;
997
998 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
999 "No response from monitor since %s\n",
1000 GNUNET_STRINGS_absolute_time_to_string (zm->sa_waiting_start));
1001 zm->sa_wait_warning = GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1002 &warn_monitor_slow,
1003 zm);
1004}
1005
1006
1007/**
1008 * Continue processing the @a sa.
1009 *
1010 * @param sa store activity to process
1011 */
1012static void
1013continue_store_activity (struct StoreActivity *sa)
1014{
1015 const struct RecordStoreMessage *rp_msg = sa->rsm;
1016 unsigned int rd_count;
1017 size_t name_len;
1018 size_t rd_ser_len;
1019 uint32_t rid;
1020 const char *name_tmp;
1021 const char *rd_ser;
1022
1023 rid = ntohl (rp_msg->gns_header.r_id);
1024 name_len = ntohs (rp_msg->name_len);
1025 rd_count = ntohs (rp_msg->rd_count);
1026 rd_ser_len = ntohs (rp_msg->rd_len);
1027 name_tmp = (const char *) &rp_msg[1];
1028 rd_ser = &name_tmp[name_len];
1029 {
1030 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1031
1032 /* We did this before, must succeed again */
1033 GNUNET_assert (
1034 GNUNET_OK ==
1035 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd));
1036
1037 for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos)
1038 {
1039 if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) &&
1040 (0 != GNUNET_memcmp (&zm->zone, &zero)))
1041 {
1042 sa->zm_pos = zm->next; /* not interesting to this monitor */
1043 continue;
1044 }
1045 if (zm->limit == zm->iteration_cnt)
1046 {
1047 zm->sa_waiting = GNUNET_YES;
1048 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1049 if (NULL != zm->sa_wait_warning)
1050 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1051 zm->sa_wait_warning =
1052 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1053 &warn_monitor_slow,
1054 zm);
1055 return; /* blocked on zone monitor */
1056 }
1057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1058 "Notifying monitor about changes under label `%s'\n",
1059 sa->conv_name);
1060 zm->limit--;
1061 send_lookup_response (zm->nc,
1062 0,
1063 &rp_msg->private_key,
1064 sa->conv_name,
1065 rd_count,
1066 rd);
1067 sa->zm_pos = zm->next;
1068 }
1069 /* great, done with the monitors, unpack (again) for refresh_block operation */
1070 refresh_block (sa->nc,
1071 NULL,
1072 rid,
1073 &rp_msg->private_key,
1074 sa->conv_name,
1075 rd_count,
1076 rd);
1077 }
1078 GNUNET_SERVICE_client_continue (sa->nc->client);
1079 free_store_activity (sa);
1080}
1081
1082
1083/**
1084 * Called whenever a client is disconnected.
1085 * Frees our resources associated with that client.
1086 *
1087 * @param cls closure
1088 * @param client identification of the client
1089 * @param app_ctx the `struct NamestoreClient` of @a client
1090 */
1091static void
1092client_disconnect_cb (void *cls,
1093 struct GNUNET_SERVICE_Client *client,
1094 void *app_ctx)
1095{
1096 struct NamestoreClient *nc = app_ctx;
1097 struct ZoneIteration *no;
1098 struct CacheOperation *cop;
1099
1100 (void) cls;
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p disconnected\n", client);
1102 for (struct ZoneMonitor *zm = monitor_head; NULL != zm; zm = zm->next)
1103 {
1104 struct StoreActivity *san;
1105
1106 if (nc != zm->nc)
1107 continue;
1108 GNUNET_CONTAINER_DLL_remove (monitor_head, monitor_tail, zm);
1109 if (NULL != zm->task)
1110 {
1111 GNUNET_SCHEDULER_cancel (zm->task);
1112 zm->task = NULL;
1113 }
1114 if (NULL != zm->sa_wait_warning)
1115 {
1116 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1117 zm->sa_wait_warning = NULL;
1118 }
1119 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = san)
1120 {
1121 san = sa->next;
1122 if (zm == sa->zm_pos)
1123 {
1124 sa->zm_pos = zm->next;
1125 /* this may free sa */
1126 continue_store_activity (sa);
1127 }
1128 }
1129 GNUNET_free (zm);
1130 break;
1131 }
1132 for (struct StoreActivity *sa = sa_head; NULL != sa; sa = sa->next)
1133 {
1134 if (sa->nc == nc)
1135 {
1136 /* this may free sa */
1137 free_store_activity (sa);
1138 break; /* there can only be one per nc */
1139 }
1140 }
1141 while (NULL != (no = nc->op_head))
1142 {
1143 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, no);
1144 GNUNET_free (no);
1145 }
1146 for (cop = cop_head; NULL != cop; cop = cop->next)
1147 if (nc == cop->nc)
1148 cop->nc = NULL;
1149 GNUNET_free (nc);
1150}
1151
1152
1153/**
1154 * Add a client to our list of active clients.
1155 *
1156 * @param cls NULL
1157 * @param client client to add
1158 * @param mq message queue for @a client
1159 * @return internal namestore client structure for this client
1160 */
1161static void *
1162client_connect_cb (void *cls,
1163 struct GNUNET_SERVICE_Client *client,
1164 struct GNUNET_MQ_Handle *mq)
1165{
1166 struct NamestoreClient *nc;
1167
1168 (void) cls;
1169 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client %p connected\n", client);
1170 nc = GNUNET_new (struct NamestoreClient);
1171 nc->client = client;
1172 nc->mq = mq;
1173 return nc;
1174}
1175
1176
1177/**
1178 * Closure for #lookup_it().
1179 */
1180struct RecordLookupContext
1181{
1182 /**
1183 * FIXME.
1184 */
1185 const char *label;
1186
1187 /**
1188 * FIXME.
1189 */
1190 char *res_rd;
1191
1192 /**
1193 * FIXME.
1194 */
1195 struct GNUNET_GNSRECORD_Data *nick;
1196
1197 /**
1198 * FIXME.
1199 */
1200 int found;
1201
1202 /**
1203 * FIXME.
1204 */
1205 unsigned int res_rd_count;
1206
1207 /**
1208 * FIXME.
1209 */
1210 ssize_t rd_ser_len;
1211};
1212
1213
1214/**
1215 * Function called by the namestore plugin when we are trying to lookup
1216 * a record as part of #handle_record_lookup(). Merges all results into
1217 * the context.
1218 *
1219 * @param cls closure with a `struct RecordLookupContext`
1220 * @param seq unique serial number of the record, MUST NOT BE ZERO
1221 * @param zone_key private key of the zone
1222 * @param label name that is being mapped (at most 255 characters long)
1223 * @param rd_count number of entries in @a rd array
1224 * @param rd array of records with data to store
1225 */
1226static void
1227lookup_it (void *cls,
1228 uint64_t seq,
1229 const struct GNUNET_IDENTITY_PrivateKey *private_key,
1230 const char *label,
1231 unsigned int rd_count,
1232 const struct GNUNET_GNSRECORD_Data *rd)
1233{
1234 struct RecordLookupContext *rlc = cls;
1235
1236 (void) private_key;
1237 GNUNET_assert (0 != seq);
1238 if (0 != strcmp (label, rlc->label))
1239 return;
1240 rlc->found = GNUNET_YES;
1241 if (0 == rd_count)
1242 {
1243 rlc->rd_ser_len = 0;
1244 rlc->res_rd_count = 0;
1245 rlc->res_rd = NULL;
1246 return;
1247 }
1248 if ((NULL != rlc->nick) && (0 != strcmp (label, GNUNET_GNS_EMPTY_LABEL_AT)))
1249 {
1250 /* Merge */
1251 struct GNUNET_GNSRECORD_Data *rd_res;
1252 unsigned int rdc_res;
1253
1254 rd_res = NULL;
1255 rdc_res = 0;
1256 rlc->nick->flags = (rlc->nick->flags | GNUNET_GNSRECORD_RF_PRIVATE)
1257 ^ GNUNET_GNSRECORD_RF_PRIVATE;
1258 merge_with_nick_records (rlc->nick, rd_count, rd, &rdc_res, &rd_res);
1259 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rdc_res, rd_res);
1260 if (rlc->rd_ser_len < 0)
1261 {
1262 GNUNET_break (0);
1263 GNUNET_free (rd_res);
1264 rlc->found = GNUNET_NO;
1265 rlc->rd_ser_len = 0;
1266 return;
1267 }
1268 rlc->res_rd_count = rdc_res;
1269 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1270 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rdc_res,
1271 rd_res,
1272 rlc->rd_ser_len,
1273 rlc->res_rd))
1274 {
1275 GNUNET_break (0);
1276 GNUNET_free (rlc->res_rd);
1277 rlc->res_rd = NULL;
1278 rlc->res_rd_count = 0;
1279 rlc->rd_ser_len = 0;
1280 GNUNET_free (rd_res);
1281 rlc->found = GNUNET_NO;
1282 return;
1283 }
1284 GNUNET_free (rd_res);
1285 GNUNET_free (rlc->nick);
1286 rlc->nick = NULL;
1287 }
1288 else
1289 {
1290 rlc->rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1291 if (rlc->rd_ser_len < 0)
1292 {
1293 GNUNET_break (0);
1294 rlc->found = GNUNET_NO;
1295 rlc->rd_ser_len = 0;
1296 return;
1297 }
1298 rlc->res_rd_count = rd_count;
1299 rlc->res_rd = GNUNET_malloc (rlc->rd_ser_len);
1300 if (rlc->rd_ser_len != GNUNET_GNSRECORD_records_serialize (rd_count,
1301 rd,
1302 rlc->rd_ser_len,
1303 rlc->res_rd))
1304 {
1305 GNUNET_break (0);
1306 GNUNET_free (rlc->res_rd);
1307 rlc->res_rd = NULL;
1308 rlc->res_rd_count = 0;
1309 rlc->rd_ser_len = 0;
1310 rlc->found = GNUNET_NO;
1311 return;
1312 }
1313 }
1314}
1315
1316
1317/**
1318 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1319 *
1320 * @param cls client sending the message
1321 * @param ll_msg message of type `struct LabelLookupMessage`
1322 * @return #GNUNET_OK if @a ll_msg is well-formed
1323 */
1324static int
1325check_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1326{
1327 uint32_t name_len;
1328 size_t src_size;
1329
1330 (void) cls;
1331 name_len = ntohl (ll_msg->label_len);
1332 src_size = ntohs (ll_msg->gns_header.header.size);
1333 if (name_len != src_size - sizeof(struct LabelLookupMessage))
1334 {
1335 GNUNET_break (0);
1336 return GNUNET_SYSERR;
1337 }
1338 GNUNET_MQ_check_zero_termination (ll_msg);
1339 return GNUNET_OK;
1340}
1341
1342
1343/**
1344 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP message
1345 *
1346 * @param cls client sending the message
1347 * @param ll_msg message of type `struct LabelLookupMessage`
1348 */
1349static void
1350handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg)
1351{
1352 struct NamestoreClient *nc = cls;
1353 struct GNUNET_MQ_Envelope *env;
1354 struct LabelLookupResponseMessage *llr_msg;
1355 struct RecordLookupContext rlc;
1356 const char *name_tmp;
1357 char *res_name;
1358 char *conv_name;
1359 uint32_t name_len;
1360 int res;
1361
1362 name_len = ntohl (ll_msg->label_len);
1363 name_tmp = (const char *) &ll_msg[1];
1364 GNUNET_SERVICE_client_continue (nc->client);
1365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1366 "Received NAMESTORE_RECORD_LOOKUP message for name `%s'\n",
1367 name_tmp);
1368
1369 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1370 if (NULL == conv_name)
1371 {
1372 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1373 "Error converting name `%s'\n",
1374 name_tmp);
1375 GNUNET_SERVICE_client_drop (nc->client);
1376 return;
1377 }
1378 rlc.label = conv_name;
1379 rlc.found = GNUNET_NO;
1380 rlc.res_rd_count = 0;
1381 rlc.res_rd = NULL;
1382 rlc.rd_ser_len = 0;
1383 rlc.nick = get_nick_record (&ll_msg->zone);
1384 res = GSN_database->lookup_records (GSN_database->cls,
1385 &ll_msg->zone,
1386 conv_name,
1387 &lookup_it,
1388 &rlc);
1389 GNUNET_free (conv_name);
1390 env =
1391 GNUNET_MQ_msg_extra (llr_msg,
1392 name_len + rlc.rd_ser_len,
1393 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE);
1394 llr_msg->gns_header.r_id = ll_msg->gns_header.r_id;
1395 llr_msg->private_key = ll_msg->zone;
1396 llr_msg->name_len = htons (name_len);
1397 llr_msg->rd_count = htons (rlc.res_rd_count);
1398 llr_msg->rd_len = htons (rlc.rd_ser_len);
1399 res_name = (char *) &llr_msg[1];
1400 if ((GNUNET_YES == rlc.found) && (GNUNET_OK == res))
1401 llr_msg->found = ntohs (GNUNET_YES);
1402 else
1403 llr_msg->found = ntohs (GNUNET_NO);
1404 GNUNET_memcpy (&llr_msg[1], name_tmp, name_len);
1405 GNUNET_memcpy (&res_name[name_len], rlc.res_rd, rlc.rd_ser_len);
1406 GNUNET_MQ_send (nc->mq, env);
1407 GNUNET_free (rlc.res_rd);
1408}
1409
1410
1411/**
1412 * Checks a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1413 *
1414 * @param cls client sending the message
1415 * @param rp_msg message of type `struct RecordStoreMessage`
1416 * @return #GNUNET_OK if @a rp_msg is well-formed
1417 */
1418static int
1419check_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1420{
1421 size_t name_len;
1422 size_t msg_size;
1423 size_t msg_size_exp;
1424 size_t rd_ser_len;
1425 const char *name_tmp;
1426
1427 (void) cls;
1428 name_len = ntohs (rp_msg->name_len);
1429 msg_size = ntohs (rp_msg->gns_header.header.size);
1430 rd_ser_len = ntohs (rp_msg->rd_len);
1431 msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len;
1432 if (msg_size != msg_size_exp)
1433 {
1434 GNUNET_break (0);
1435 return GNUNET_SYSERR;
1436 }
1437 if ((0 == name_len) || (name_len > MAX_NAME_LEN))
1438 {
1439 GNUNET_break (0);
1440 return GNUNET_SYSERR;
1441 }
1442 name_tmp = (const char *) &rp_msg[1];
1443 if ('\0' != name_tmp[name_len - 1])
1444 {
1445 GNUNET_break (0);
1446 return GNUNET_SYSERR;
1447 }
1448 return GNUNET_OK;
1449}
1450
1451
1452/**
1453 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message
1454 *
1455 * @param cls client sending the message
1456 * @param rp_msg message of type `struct RecordStoreMessage`
1457 */
1458static void
1459handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg)
1460{
1461 struct NamestoreClient *nc = cls;
1462 size_t name_len;
1463 size_t rd_ser_len;
1464 uint32_t rid;
1465 const char *name_tmp;
1466 char *conv_name;
1467 const char *rd_ser;
1468 unsigned int rd_count;
1469 int res;
1470 struct StoreActivity *sa;
1471
1472 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1473 "Received NAMESTORE_RECORD_STORE message\n");
1474 rid = ntohl (rp_msg->gns_header.r_id);
1475 name_len = ntohs (rp_msg->name_len);
1476 rd_count = ntohs (rp_msg->rd_count);
1477 rd_ser_len = ntohs (rp_msg->rd_len);
1478 GNUNET_break (0 == ntohs (rp_msg->reserved));
1479 name_tmp = (const char *) &rp_msg[1];
1480 rd_ser = &name_tmp[name_len];
1481 {
1482 struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)];
1483
1484 if (GNUNET_OK !=
1485 GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd))
1486 {
1487 GNUNET_break (0);
1488 GNUNET_SERVICE_client_drop (nc->client);
1489 return;
1490 }
1491
1492 /* Extracting and converting private key */
1493 conv_name = GNUNET_GNSRECORD_string_to_lowercase (name_tmp);
1494 if (NULL == conv_name)
1495 {
1496 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1497 "Error converting name `%s'\n",
1498 name_tmp);
1499 GNUNET_SERVICE_client_drop (nc->client);
1500 return;
1501 }
1502 GNUNET_STATISTICS_update (statistics,
1503 "Well-formed store requests received",
1504 1,
1505 GNUNET_NO);
1506 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1507 "Creating %u records for name `%s'\n",
1508 (unsigned int) rd_count,
1509 conv_name);
1510 if ((0 == rd_count) &&
1511 (GNUNET_NO == GSN_database->lookup_records (GSN_database->cls,
1512 &rp_msg->private_key,
1513 conv_name,
1514 NULL,
1515 0)))
1516 {
1517 /* This name does not exist, so cannot be removed */
1518 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1519 "Name `%s' does not exist, no deletion required\n",
1520 conv_name);
1521 res = GNUNET_NO;
1522 }
1523 else
1524 {
1525 /* remove "NICK" records, unless this is for the
1526 #GNUNET_GNS_EMPTY_LABEL_AT label */
1527 struct GNUNET_GNSRECORD_Data rd_clean[GNUNET_NZL (rd_count)];
1528 unsigned int rd_clean_off;
1529 int have_nick;
1530
1531 rd_clean_off = 0;
1532 have_nick = GNUNET_NO;
1533 for (unsigned int i = 0; i < rd_count; i++)
1534 {
1535 rd_clean[rd_clean_off] = rd[i];
1536 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) ||
1537 (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type))
1538 rd_clean_off++;
1539
1540 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1541 (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type))
1542 {
1543 cache_nick (&rp_msg->private_key, &rd[i]);
1544 have_nick = GNUNET_YES;
1545 }
1546 }
1547 if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) &&
1548 (GNUNET_NO == have_nick))
1549 {
1550 /* remove nick record from cache, in case we have one there */
1551 cache_nick (&rp_msg->private_key, NULL);
1552 }
1553 res = GSN_database->store_records (GSN_database->cls,
1554 &rp_msg->private_key,
1555 conv_name,
1556 rd_clean_off,
1557 rd_clean);
1558 }
1559
1560 if (GNUNET_OK != res)
1561 {
1562 /* store not successful, not need to tell monitors */
1563 send_store_response (nc, res, rid);
1564 GNUNET_SERVICE_client_continue (nc->client);
1565 GNUNET_free (conv_name);
1566 return;
1567 }
1568
1569 sa = GNUNET_malloc (sizeof(struct StoreActivity)
1570 + ntohs (rp_msg->gns_header.header.size));
1571 GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa);
1572 sa->nc = nc;
1573 sa->rsm = (const struct RecordStoreMessage *) &sa[1];
1574 GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size));
1575 sa->zm_pos = monitor_head;
1576 sa->conv_name = conv_name;
1577 continue_store_activity (sa);
1578 }
1579}
1580
1581
1582/**
1583 * Context for record remove operations passed from #handle_zone_to_name to
1584 * #handle_zone_to_name_it as closure
1585 */
1586struct ZoneToNameCtx
1587{
1588 /**
1589 * Namestore client
1590 */
1591 struct NamestoreClient *nc;
1592
1593 /**
1594 * Request id (to be used in the response to the client).
1595 */
1596 uint32_t rid;
1597
1598 /**
1599 * Set to #GNUNET_OK on success, #GNUNET_SYSERR on error. Note that
1600 * not finding a name for the zone still counts as a 'success' here,
1601 * as this field is about the success of executing the IPC protocol.
1602 */
1603 int success;
1604};
1605
1606
1607/**
1608 * Zone to name iterator
1609 *
1610 * @param cls struct ZoneToNameCtx *
1611 * @param seq sequence number of the record, MUST NOT BE ZERO
1612 * @param zone_key the zone key
1613 * @param name name
1614 * @param rd_count number of records in @a rd
1615 * @param rd record data
1616 */
1617static void
1618handle_zone_to_name_it (void *cls,
1619 uint64_t seq,
1620 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1621 const char *name,
1622 unsigned int rd_count,
1623 const struct GNUNET_GNSRECORD_Data *rd)
1624{
1625 struct ZoneToNameCtx *ztn_ctx = cls;
1626 struct GNUNET_MQ_Envelope *env;
1627 struct ZoneToNameResponseMessage *ztnr_msg;
1628 int16_t res;
1629 size_t name_len;
1630 ssize_t rd_ser_len;
1631 size_t msg_size;
1632 char *name_tmp;
1633 char *rd_tmp;
1634
1635 GNUNET_assert (0 != seq);
1636 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1637 "Found result for zone-to-name lookup: `%s'\n",
1638 name);
1639 res = GNUNET_YES;
1640 name_len = (NULL == name) ? 0 : strlen (name) + 1;
1641 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1642 if (rd_ser_len < 0)
1643 {
1644 GNUNET_break (0);
1645 ztn_ctx->success = GNUNET_SYSERR;
1646 return;
1647 }
1648 msg_size = sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len;
1649 if (msg_size >= GNUNET_MAX_MESSAGE_SIZE)
1650 {
1651 GNUNET_break (0);
1652 ztn_ctx->success = GNUNET_SYSERR;
1653 return;
1654 }
1655 env =
1656 GNUNET_MQ_msg_extra (ztnr_msg,
1657 name_len + rd_ser_len,
1658 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1659 ztnr_msg->gns_header.header.size = htons (msg_size);
1660 ztnr_msg->gns_header.r_id = htonl (ztn_ctx->rid);
1661 ztnr_msg->res = htons (res);
1662 ztnr_msg->rd_len = htons (rd_ser_len);
1663 ztnr_msg->rd_count = htons (rd_count);
1664 ztnr_msg->name_len = htons (name_len);
1665 ztnr_msg->zone = *zone_key;
1666 name_tmp = (char *) &ztnr_msg[1];
1667 GNUNET_memcpy (name_tmp, name, name_len);
1668 rd_tmp = &name_tmp[name_len];
1669 GNUNET_assert (
1670 rd_ser_len ==
1671 GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_tmp));
1672 ztn_ctx->success = GNUNET_OK;
1673 GNUNET_MQ_send (ztn_ctx->nc->mq, env);
1674}
1675
1676
1677/**
1678 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME message
1679 *
1680 * @param cls client client sending the message
1681 * @param ztn_msg message of type 'struct ZoneToNameMessage'
1682 */
1683static void
1684handle_zone_to_name (void *cls, const struct ZoneToNameMessage *ztn_msg)
1685{
1686 struct NamestoreClient *nc = cls;
1687 struct ZoneToNameCtx ztn_ctx;
1688 struct GNUNET_MQ_Envelope *env;
1689 struct ZoneToNameResponseMessage *ztnr_msg;
1690
1691 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME message\n");
1692 ztn_ctx.rid = ntohl (ztn_msg->gns_header.r_id);
1693 ztn_ctx.nc = nc;
1694 ztn_ctx.success = GNUNET_NO;
1695 if (GNUNET_SYSERR == GSN_database->zone_to_name (GSN_database->cls,
1696 &ztn_msg->zone,
1697 &ztn_msg->value_zone,
1698 &handle_zone_to_name_it,
1699 &ztn_ctx))
1700 {
1701 /* internal error, hang up instead of signalling something
1702 that might be wrong */
1703 GNUNET_break (0);
1704 GNUNET_SERVICE_client_drop (nc->client);
1705 return;
1706 }
1707 if (GNUNET_NO == ztn_ctx.success)
1708 {
1709 /* no result found, send empty response */
1710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1711 "Found no result for zone-to-name lookup.\n");
1712 env = GNUNET_MQ_msg (ztnr_msg,
1713 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE);
1714 ztnr_msg->gns_header.r_id = ztn_msg->gns_header.r_id;
1715 ztnr_msg->res = htons (GNUNET_NO);
1716 GNUNET_MQ_send (nc->mq, env);
1717 }
1718 GNUNET_SERVICE_client_continue (nc->client);
1719}
1720
1721
1722/**
1723 * Context for record remove operations passed from
1724 * #run_zone_iteration_round to #zone_iterate_proc as closure
1725 */
1726struct ZoneIterationProcResult
1727{
1728 /**
1729 * The zone iteration handle
1730 */
1731 struct ZoneIteration *zi;
1732
1733 /**
1734 * Number of results left to be returned in this iteration.
1735 */
1736 uint64_t limit;
1737};
1738
1739
1740/**
1741 * Process results for zone iteration from database
1742 *
1743 * @param cls struct ZoneIterationProcResult
1744 * @param seq sequence number of the record, MUST NOT BE ZERO
1745 * @param zone_key the zone key
1746 * @param name name
1747 * @param rd_count number of records for this name
1748 * @param rd record data
1749 */
1750static void
1751zone_iterate_proc (void *cls,
1752 uint64_t seq,
1753 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
1754 const char *name,
1755 unsigned int rd_count,
1756 const struct GNUNET_GNSRECORD_Data *rd)
1757{
1758 struct ZoneIterationProcResult *proc = cls;
1759 int do_refresh_block;
1760
1761 GNUNET_assert (0 != seq);
1762 if ((NULL == zone_key) && (NULL == name))
1763 {
1764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Iteration done\n");
1765 return;
1766 }
1767 if ((NULL == zone_key) || (NULL == name))
1768 {
1769 /* what is this!? should never happen */
1770 GNUNET_break (0);
1771 return;
1772 }
1773 if (0 == proc->limit)
1774 {
1775 /* what is this!? should never happen */
1776 GNUNET_break (0);
1777 return;
1778 }
1779 proc->limit--;
1780 proc->zi->seq = seq;
1781 send_lookup_response (proc->zi->nc,
1782 proc->zi->request_id,
1783 zone_key,
1784 name,
1785 rd_count,
1786 rd);
1787
1788
1789 do_refresh_block = GNUNET_NO;
1790 for (unsigned int i = 0; i < rd_count; i++)
1791 if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION))
1792 {
1793 do_refresh_block = GNUNET_YES;
1794 break;
1795 }
1796 if (GNUNET_YES == do_refresh_block)
1797 refresh_block (NULL, proc->zi, 0, zone_key, name, rd_count, rd);
1798}
1799
1800
1801/**
1802 * Perform the next round of the zone iteration.
1803 *
1804 * @param zi zone iterator to process
1805 * @param limit number of results to return in one pass
1806 */
1807static void
1808run_zone_iteration_round (struct ZoneIteration *zi, uint64_t limit)
1809{
1810 struct ZoneIterationProcResult proc;
1811 struct GNUNET_TIME_Absolute start;
1812 struct GNUNET_TIME_Relative duration;
1813
1814 memset (&proc, 0, sizeof(proc));
1815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1816 "Asked to return up to %llu records at position %llu\n",
1817 (unsigned long long) limit,
1818 (unsigned long long) zi->seq);
1819 proc.zi = zi;
1820 proc.limit = limit;
1821 start = GNUNET_TIME_absolute_get ();
1822 GNUNET_break (GNUNET_SYSERR !=
1823 GSN_database->iterate_records (GSN_database->cls,
1824 (GNUNET_YES == GNUNET_is_zero (
1825 &zi->zone))
1826 ? NULL
1827 : &zi->zone,
1828 zi->seq,
1829 limit,
1830 &zone_iterate_proc,
1831 &proc));
1832 duration = GNUNET_TIME_absolute_get_duration (start);
1833 duration = GNUNET_TIME_relative_divide (duration, limit - proc.limit);
1834 GNUNET_STATISTICS_set (statistics,
1835 "NAMESTORE iteration delay (μs/record)",
1836 duration.rel_value_us,
1837 GNUNET_NO);
1838 if (0 == proc.limit)
1839 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1840 "Returned %llu results, more results available\n",
1841 (unsigned long long) limit);
1842 zi->send_end = (0 != proc.limit);
1843 if (0 == zi->cache_ops)
1844 zone_iteration_done_client_continue (zi);
1845}
1846
1847
1848/**
1849 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START message
1850 *
1851 * @param cls the client sending the message
1852 * @param zis_msg message from the client
1853 */
1854static void
1855handle_iteration_start (void *cls,
1856 const struct ZoneIterationStartMessage *zis_msg)
1857{
1858 struct NamestoreClient *nc = cls;
1859 struct ZoneIteration *zi;
1860
1861 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1862 "Received ZONE_ITERATION_START message\n");
1863 zi = GNUNET_new (struct ZoneIteration);
1864 zi->request_id = ntohl (zis_msg->gns_header.r_id);
1865 zi->offset = 0;
1866 zi->nc = nc;
1867 zi->zone = zis_msg->zone;
1868
1869 GNUNET_CONTAINER_DLL_insert (nc->op_head, nc->op_tail, zi);
1870 run_zone_iteration_round (zi, 1);
1871}
1872
1873
1874/**
1875 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP message
1876 *
1877 * @param cls the client sending the message
1878 * @param zis_msg message from the client
1879 */
1880static void
1881handle_iteration_stop (void *cls,
1882 const struct ZoneIterationStopMessage *zis_msg)
1883{
1884 struct NamestoreClient *nc = cls;
1885 struct ZoneIteration *zi;
1886 uint32_t rid;
1887
1888 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1889 "Received ZONE_ITERATION_STOP message\n");
1890 rid = ntohl (zis_msg->gns_header.r_id);
1891 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1892 if (zi->request_id == rid)
1893 break;
1894 if (NULL == zi)
1895 {
1896 GNUNET_break (0);
1897 GNUNET_SERVICE_client_drop (nc->client);
1898 return;
1899 }
1900 GNUNET_CONTAINER_DLL_remove (nc->op_head, nc->op_tail, zi);
1901 GNUNET_free (zi);
1902 GNUNET_SERVICE_client_continue (nc->client);
1903}
1904
1905
1906/**
1907 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT message
1908 *
1909 * @param cls the client sending the message
1910 * @param message message from the client
1911 */
1912static void
1913handle_iteration_next (void *cls,
1914 const struct ZoneIterationNextMessage *zis_msg)
1915{
1916 struct NamestoreClient *nc = cls;
1917 struct ZoneIteration *zi;
1918 uint32_t rid;
1919 uint64_t limit;
1920
1921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1922 "Received ZONE_ITERATION_NEXT message\n");
1923 GNUNET_STATISTICS_update (statistics,
1924 "Iteration NEXT messages received",
1925 1,
1926 GNUNET_NO);
1927 rid = ntohl (zis_msg->gns_header.r_id);
1928 limit = GNUNET_ntohll (zis_msg->limit);
1929 for (zi = nc->op_head; NULL != zi; zi = zi->next)
1930 if (zi->request_id == rid)
1931 break;
1932 if (NULL == zi)
1933 {
1934 GNUNET_break (0);
1935 GNUNET_SERVICE_client_drop (nc->client);
1936 return;
1937 }
1938 run_zone_iteration_round (zi, limit);
1939}
1940
1941
1942/**
1943 * Function called when the monitor is ready for more data, and we
1944 * should thus unblock PUT operations that were blocked on the
1945 * monitor not being ready.
1946 */
1947static void
1948monitor_unblock (struct ZoneMonitor *zm)
1949{
1950 struct StoreActivity *sa = sa_head;
1951
1952 while ((NULL != sa) && (zm->limit > zm->iteration_cnt))
1953 {
1954 struct StoreActivity *sn = sa->next;
1955
1956 if (sa->zm_pos == zm)
1957 continue_store_activity (sa);
1958 sa = sn;
1959 }
1960 if (zm->limit > zm->iteration_cnt)
1961 {
1962 zm->sa_waiting = GNUNET_NO;
1963 if (NULL != zm->sa_wait_warning)
1964 {
1965 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1966 zm->sa_wait_warning = NULL;
1967 }
1968 }
1969 else if (GNUNET_YES == zm->sa_waiting)
1970 {
1971 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
1972 if (NULL != zm->sa_wait_warning)
1973 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
1974 zm->sa_wait_warning =
1975 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
1976 &warn_monitor_slow,
1977 zm);
1978 }
1979}
1980
1981
1982/**
1983 * Send 'sync' message to zone monitor, we're now in sync.
1984 *
1985 * @param zm monitor that is now in sync
1986 */
1987static void
1988monitor_sync (struct ZoneMonitor *zm)
1989{
1990 struct GNUNET_MQ_Envelope *env;
1991 struct GNUNET_MessageHeader *sync;
1992
1993 env = GNUNET_MQ_msg (sync, GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_SYNC);
1994 GNUNET_MQ_send (zm->nc->mq, env);
1995 /* mark iteration done */
1996 zm->in_first_iteration = GNUNET_NO;
1997 zm->iteration_cnt = 0;
1998 if ((zm->limit > 0) && (zm->sa_waiting))
1999 monitor_unblock (zm);
2000}
2001
2002
2003/**
2004 * Obtain the next datum during the zone monitor's zone initial iteration.
2005 *
2006 * @param cls zone monitor that does its initial iteration
2007 */
2008static void
2009monitor_iteration_next (void *cls);
2010
2011
2012/**
2013 * A #GNUNET_NAMESTORE_RecordIterator for monitors.
2014 *
2015 * @param cls a 'struct ZoneMonitor *' with information about the monitor
2016 * @param seq sequence number of the record, MUST NOT BE ZERO
2017 * @param zone_key zone key of the zone
2018 * @param name name
2019 * @param rd_count number of records in @a rd
2020 * @param rd array of records
2021 */
2022static void
2023monitor_iterate_cb (void *cls,
2024 uint64_t seq,
2025 const struct GNUNET_IDENTITY_PrivateKey *zone_key,
2026 const char *name,
2027 unsigned int rd_count,
2028 const struct GNUNET_GNSRECORD_Data *rd)
2029{
2030 struct ZoneMonitor *zm = cls;
2031
2032 GNUNET_assert (0 != seq);
2033 zm->seq = seq;
2034 GNUNET_assert (NULL != name);
2035 GNUNET_STATISTICS_update (statistics,
2036 "Monitor notifications sent",
2037 1,
2038 GNUNET_NO);
2039 zm->limit--;
2040 zm->iteration_cnt--;
2041 send_lookup_response (zm->nc, 0, zone_key, name, rd_count, rd);
2042 if ((0 == zm->iteration_cnt) && (0 != zm->limit))
2043 {
2044 /* We are done with the current iteration batch, AND the
2045 client would right now accept more, so go again! */
2046 GNUNET_assert (NULL == zm->task);
2047 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2048 }
2049}
2050
2051
2052/**
2053 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START message
2054 *
2055 * @param cls the client sending the message
2056 * @param zis_msg message from the client
2057 */
2058static void
2059handle_monitor_start (void *cls, const struct ZoneMonitorStartMessage *zis_msg)
2060{
2061 struct NamestoreClient *nc = cls;
2062 struct ZoneMonitor *zm;
2063
2064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_MONITOR_START message\n");
2065 zm = GNUNET_new (struct ZoneMonitor);
2066 zm->nc = nc;
2067 zm->zone = zis_msg->zone;
2068 zm->limit = 1;
2069 zm->in_first_iteration = (GNUNET_YES == ntohl (zis_msg->iterate_first));
2070 GNUNET_CONTAINER_DLL_insert (monitor_head, monitor_tail, zm);
2071 GNUNET_SERVICE_client_mark_monitor (nc->client);
2072 GNUNET_SERVICE_client_continue (nc->client);
2073 GNUNET_notification_context_add (monitor_nc, nc->mq);
2074 if (zm->in_first_iteration)
2075 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2076 else
2077 monitor_sync (zm);
2078}
2079
2080
2081/**
2082 * Obtain the next datum during the zone monitor's zone initial iteration.
2083 *
2084 * @param cls zone monitor that does its initial iteration
2085 */
2086static void
2087monitor_iteration_next (void *cls)
2088{
2089 struct ZoneMonitor *zm = cls;
2090 int ret;
2091
2092 zm->task = NULL;
2093 GNUNET_assert (0 == zm->iteration_cnt);
2094 if (zm->limit > 16)
2095 zm->iteration_cnt = zm->limit / 2; /* leave half for monitor events */
2096 else
2097 zm->iteration_cnt = zm->limit; /* use it all */
2098 ret = GSN_database->iterate_records (GSN_database->cls,
2099 (GNUNET_YES == GNUNET_is_zero (
2100 &zm->zone))
2101 ? NULL
2102 : &zm->zone,
2103 zm->seq,
2104 zm->iteration_cnt,
2105 &monitor_iterate_cb,
2106 zm);
2107 if (GNUNET_SYSERR == ret)
2108 {
2109 GNUNET_SERVICE_client_drop (zm->nc->client);
2110 return;
2111 }
2112 if (GNUNET_NO == ret)
2113 {
2114 /* empty zone */
2115 monitor_sync (zm);
2116 return;
2117 }
2118}
2119
2120
2121/**
2122 * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT message
2123 *
2124 * @param cls the client sending the message
2125 * @param nm message from the client
2126 */
2127static void
2128handle_monitor_next (void *cls, const struct ZoneMonitorNextMessage *nm)
2129{
2130 struct NamestoreClient *nc = cls;
2131 struct ZoneMonitor *zm;
2132 uint64_t inc;
2133
2134 inc = GNUNET_ntohll (nm->limit);
2135 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2136 "Received ZONE_MONITOR_NEXT message with limit %llu\n",
2137 (unsigned long long) inc);
2138 for (zm = monitor_head; NULL != zm; zm = zm->next)
2139 if (zm->nc == nc)
2140 break;
2141 if (NULL == zm)
2142 {
2143 GNUNET_break (0);
2144 GNUNET_SERVICE_client_drop (nc->client);
2145 return;
2146 }
2147 GNUNET_SERVICE_client_continue (nc->client);
2148 if (zm->limit + inc < zm->limit)
2149 {
2150 GNUNET_break (0);
2151 GNUNET_SERVICE_client_drop (nc->client);
2152 return;
2153 }
2154 zm->limit += inc;
2155 if ((zm->in_first_iteration) && (zm->limit == inc))
2156 {
2157 /* We are still iterating, and the previous iteration must
2158 have stopped due to the client's limit, so continue it! */
2159 GNUNET_assert (NULL == zm->task);
2160 zm->task = GNUNET_SCHEDULER_add_now (&monitor_iteration_next, zm);
2161 }
2162 GNUNET_assert (zm->iteration_cnt <= zm->limit);
2163 if ((zm->limit > zm->iteration_cnt) && (zm->sa_waiting))
2164 {
2165 monitor_unblock (zm);
2166 }
2167 else if (GNUNET_YES == zm->sa_waiting)
2168 {
2169 if (NULL != zm->sa_wait_warning)
2170 GNUNET_SCHEDULER_cancel (zm->sa_wait_warning);
2171 zm->sa_waiting_start = GNUNET_TIME_absolute_get ();
2172 zm->sa_wait_warning =
2173 GNUNET_SCHEDULER_add_delayed (MONITOR_STALL_WARN_DELAY,
2174 &warn_monitor_slow,
2175 zm);
2176 }
2177}
2178
2179
2180/**
2181 * Process namestore requests.
2182 *
2183 * @param cls closure
2184 * @param cfg configuration to use
2185 * @param service the initialized service
2186 */
2187static void
2188run (void *cls,
2189 const struct GNUNET_CONFIGURATION_Handle *cfg,
2190 struct GNUNET_SERVICE_Handle *service)
2191{
2192 char *database;
2193
2194 (void) cls;
2195 (void) service;
2196 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting namestore service\n");
2197 cache_keys =
2198 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namestore", "CACHE_KEYS");
2199 disable_namecache =
2200 GNUNET_CONFIGURATION_get_value_yesno (cfg, "namecache", "DISABLE");
2201 GSN_cfg = cfg;
2202 monitor_nc = GNUNET_notification_context_create (1);
2203 if (GNUNET_YES != disable_namecache)
2204 {
2205 namecache = GNUNET_NAMECACHE_connect (cfg);
2206 GNUNET_assert (NULL != namecache);
2207 }
2208 /* Loading database plugin */
2209 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg,
2210 "namestore",
2211 "database",
2212 &database))
2213 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "No database backend configured\n");
2214
2215 GNUNET_asprintf (&db_lib_name, "libgnunet_plugin_namestore_%s", database);
2216 GSN_database = GNUNET_PLUGIN_load (db_lib_name, (void *) GSN_cfg);
2217 GNUNET_free (database);
2218 statistics = GNUNET_STATISTICS_create ("namestore", cfg);
2219 GNUNET_SCHEDULER_add_shutdown (&cleanup_task, NULL);
2220 if (NULL == GSN_database)
2221 {
2222 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2223 "Could not load database backend `%s'\n",
2224 db_lib_name);
2225 GNUNET_SCHEDULER_shutdown ();
2226 return;
2227 }
2228}
2229
2230
2231/**
2232 * Define "main" method using service macro.
2233 */
2234GNUNET_SERVICE_MAIN (
2235 "namestore",
2236 GNUNET_SERVICE_OPTION_NONE,
2237 &run,
2238 &client_connect_cb,
2239 &client_disconnect_cb,
2240 NULL,
2241 GNUNET_MQ_hd_var_size (record_store,
2242 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE,
2243 struct RecordStoreMessage,
2244 NULL),
2245 GNUNET_MQ_hd_var_size (record_lookup,
2246 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP,
2247 struct LabelLookupMessage,
2248 NULL),
2249 GNUNET_MQ_hd_fixed_size (zone_to_name,
2250 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME,
2251 struct ZoneToNameMessage,
2252 NULL),
2253 GNUNET_MQ_hd_fixed_size (iteration_start,
2254 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START,
2255 struct ZoneIterationStartMessage,
2256 NULL),
2257 GNUNET_MQ_hd_fixed_size (iteration_next,
2258 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT,
2259 struct ZoneIterationNextMessage,
2260 NULL),
2261 GNUNET_MQ_hd_fixed_size (iteration_stop,
2262 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP,
2263 struct ZoneIterationStopMessage,
2264 NULL),
2265 GNUNET_MQ_hd_fixed_size (monitor_start,
2266 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START,
2267 struct ZoneMonitorStartMessage,
2268 NULL),
2269 GNUNET_MQ_hd_fixed_size (monitor_next,
2270 GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT,
2271 struct ZoneMonitorNextMessage,
2272 NULL),
2273 GNUNET_MQ_handler_end ());
2274
2275
2276/* 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 733e4e2f8..000000000
--- a/src/namestore/namestore.conf.in
+++ /dev/null
@@ -1,49 +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
47
48# On what port does the FCFS daemon listen for HTTP clients?
49HTTPPORT = 18080
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h
deleted file mode 100644
index fd9a8ed47..000000000
--- a/src/namestore/namestore.h
+++ /dev/null
@@ -1,394 +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 * always zero (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
119/**
120 * Lookup a label
121 */
122struct LabelLookupMessage
123{
124 /**
125 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP
126 */
127 struct GNUNET_NAMESTORE_Header gns_header;
128
129 /**
130 * Length of the name
131 */
132 uint32_t label_len GNUNET_PACKED;
133
134 /**
135 * The private key of the zone to look up in
136 */
137 struct GNUNET_IDENTITY_PrivateKey zone;
138
139 /* followed by:
140 * name with length name_len
141 */
142};
143
144
145/**
146 * Lookup a label
147 */
148struct LabelLookupResponseMessage
149{
150 /**
151 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
152 */
153 struct GNUNET_NAMESTORE_Header gns_header;
154
155 /**
156 * Name length
157 */
158 uint16_t name_len GNUNET_PACKED;
159
160 /**
161 * Length of serialized record data
162 */
163 uint16_t rd_len GNUNET_PACKED;
164
165 /**
166 * Number of records contained
167 */
168 uint16_t rd_count GNUNET_PACKED;
169
170 /**
171 * Was the label found in the database??
172 * #GNUNET_YES or #GNUNET_NO
173 */
174 uint16_t found GNUNET_PACKED;
175
176 /**
177 * The private key of the authority.
178 */
179 struct GNUNET_IDENTITY_PrivateKey private_key;
180
181 /* followed by:
182 * name with length name_len
183 * serialized record data with rd_count records
184 */
185};
186
187
188/**
189 * Lookup a name for a zone hash
190 */
191struct ZoneToNameMessage
192{
193 /**
194 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME
195 */
196 struct GNUNET_NAMESTORE_Header gns_header;
197
198 /**
199 * The private key of the zone to look up in
200 */
201 struct GNUNET_IDENTITY_PrivateKey zone;
202
203 /**
204 * The public key of the target zone
205 */
206 struct GNUNET_IDENTITY_PublicKey value_zone;
207};
208
209
210/**
211 * Respone for zone to name lookup
212 */
213struct ZoneToNameResponseMessage
214{
215 /**
216 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE
217 */
218 struct GNUNET_NAMESTORE_Header gns_header;
219
220 /**
221 * Length of the name
222 */
223 uint16_t name_len GNUNET_PACKED;
224
225 /**
226 * Length of serialized record data
227 */
228 uint16_t rd_len GNUNET_PACKED;
229
230 /**
231 * Number of records contained
232 */
233 uint16_t rd_count GNUNET_PACKED;
234
235 /**
236 * result in NBO: #GNUNET_OK on success, #GNUNET_NO if there were no
237 * results, #GNUNET_SYSERR on error
238 */
239 int16_t res GNUNET_PACKED;
240
241 /**
242 * The private key of the zone that contained the name.
243 */
244 struct GNUNET_IDENTITY_PrivateKey zone;
245
246 /* followed by:
247 * name with length name_len
248 * serialized record data with rd_count records
249 */
250};
251
252
253/**
254 * Record is returned from the namestore (as authority).
255 */
256struct RecordResultMessage
257{
258 /**
259 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
260 */
261 struct GNUNET_NAMESTORE_Header gns_header;
262
263 /**
264 * Name length
265 */
266 uint16_t name_len GNUNET_PACKED;
267
268 /**
269 * Length of serialized record data
270 */
271 uint16_t rd_len GNUNET_PACKED;
272
273 /**
274 * Number of records contained
275 */
276 uint16_t rd_count GNUNET_PACKED;
277
278 /**
279 * always zero (for alignment)
280 */
281 uint16_t reserved GNUNET_PACKED;
282
283 /**
284 * The private key of the authority.
285 */
286 struct GNUNET_IDENTITY_PrivateKey private_key;
287
288 /* followed by:
289 * name with length name_len
290 * serialized record data with rd_count records
291 */
292};
293
294
295/**
296 * Start monitoring a zone.
297 */
298struct ZoneMonitorStartMessage
299{
300 /**
301 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_START
302 */
303 struct GNUNET_MessageHeader header;
304
305 /**
306 * #GNUNET_YES to first iterate over all records,
307 * #GNUNET_NO to only monitor changes.o
308 */
309 uint32_t iterate_first GNUNET_PACKED;
310
311 /**
312 * Zone key.
313 */
314 struct GNUNET_IDENTITY_PrivateKey zone;
315};
316
317
318/**
319 * Ask for next result of zone iteration for the given operation
320 */
321struct ZoneMonitorNextMessage
322{
323 /**
324 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_MONITOR_NEXT
325 */
326 struct GNUNET_MessageHeader header;
327
328 /**
329 * Always zero.
330 */
331 uint32_t reserved;
332
333 /**
334 * Number of records to return to the iterator in one shot
335 * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_MONITOR_NEXT
336 * should be send again). In NBO.
337 */
338 uint64_t limit;
339};
340
341
342/**
343 * Start a zone iteration for the given zone
344 */
345struct ZoneIterationStartMessage
346{
347 /**
348 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START
349 */
350 struct GNUNET_NAMESTORE_Header gns_header;
351
352 /**
353 * Zone key. All zeros for "all zones".
354 */
355 struct GNUNET_IDENTITY_PrivateKey zone;
356};
357
358
359/**
360 * Ask for next result of zone iteration for the given operation
361 */
362struct ZoneIterationNextMessage
363{
364 /**
365 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT
366 */
367 struct GNUNET_NAMESTORE_Header gns_header;
368
369 /**
370 * Number of records to return to the iterator in one shot
371 * (before #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT
372 * should be send again). In NBO.
373 */
374 uint64_t limit;
375};
376
377
378/**
379 * Stop zone iteration for the given operation
380 */
381struct ZoneIterationStopMessage
382{
383 /**
384 * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP
385 */
386 struct GNUNET_NAMESTORE_Header gns_header;
387};
388
389
390GNUNET_NETWORK_STRUCT_END
391
392
393/* end of namestore.h */
394#endif
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c
deleted file mode 100644
index b24db9b26..000000000
--- a/src/namestore/namestore_api.c
+++ /dev/null
@@ -1,1307 +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/**
351 * Handle an incoming message of type
352 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE
353 *
354 * @param cls
355 * @param msg the message we received
356 */
357static void
358handle_record_store_response (void *cls,
359 const struct RecordStoreResponseMessage *msg)
360{
361 struct GNUNET_NAMESTORE_Handle *h = cls;
362 struct GNUNET_NAMESTORE_QueueEntry *qe;
363 int res;
364 const char *emsg;
365
366 qe = find_qe (h, ntohl (msg->gns_header.r_id));
367 res = ntohl (msg->op_result);
368 LOG (GNUNET_ERROR_TYPE_DEBUG,
369 "Received RECORD_STORE_RESPONSE with result %d\n",
370 res);
371 /* TODO: add actual error message from namestore to response... */
372 if (GNUNET_SYSERR == res)
373 emsg = _ ("Namestore failed to store record\n");
374 else
375 emsg = NULL;
376 if (NULL == qe)
377 return;
378 if (NULL != qe->cont)
379 qe->cont (qe->cont_cls, res, emsg);
380 free_qe (qe);
381}
382
383
384/**
385 * Check validity of an incoming message of type
386 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
387 *
388 * @param cls
389 * @param msg the message we received
390 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
391 */
392static int
393check_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
394{
395 const char *name;
396 size_t exp_msg_len;
397 size_t msg_len;
398 size_t name_len;
399 size_t rd_len;
400
401 (void) cls;
402 rd_len = ntohs (msg->rd_len);
403 msg_len = ntohs (msg->gns_header.header.size);
404 name_len = ntohs (msg->name_len);
405 exp_msg_len = sizeof(*msg) + name_len + rd_len;
406 if (msg_len != exp_msg_len)
407 {
408 GNUNET_break (0);
409 return GNUNET_SYSERR;
410 }
411 name = (const char *) &msg[1];
412 if ((name_len > 0) && ('\0' != name[name_len - 1]))
413 {
414 GNUNET_break (0);
415 return GNUNET_SYSERR;
416 }
417 if (GNUNET_NO == ntohs (msg->found))
418 {
419 if (0 != ntohs (msg->rd_count))
420 {
421 GNUNET_break (0);
422 return GNUNET_SYSERR;
423 }
424 return GNUNET_OK;
425 }
426 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
427}
428
429
430/**
431 * Handle an incoming message of type
432 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE
433 *
434 * @param cls
435 * @param msg the message we received
436 */
437static void
438handle_lookup_result (void *cls, const struct LabelLookupResponseMessage *msg)
439{
440 struct GNUNET_NAMESTORE_Handle *h = cls;
441 struct GNUNET_NAMESTORE_QueueEntry *qe;
442 const char *name;
443 const char *rd_tmp;
444 size_t name_len;
445 size_t rd_len;
446 unsigned int rd_count;
447
448 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_LOOKUP_RESULT\n");
449 qe = find_qe (h, ntohl (msg->gns_header.r_id));
450 if (NULL == qe)
451 return;
452 rd_len = ntohs (msg->rd_len);
453 rd_count = ntohs (msg->rd_count);
454 name_len = ntohs (msg->name_len);
455 name = (const char *) &msg[1];
456 if (GNUNET_NO == ntohs (msg->found))
457 {
458 /* label was not in namestore */
459 if (NULL != qe->proc)
460 qe->proc (qe->proc_cls, &msg->private_key, name, 0, NULL);
461 free_qe (qe);
462 return;
463 }
464
465 rd_tmp = &name[name_len];
466 {
467 struct GNUNET_GNSRECORD_Data rd[rd_count];
468
469 GNUNET_assert (
470 GNUNET_OK ==
471 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
472 if (0 == name_len)
473 name = NULL;
474 if (NULL != qe->proc)
475 qe->proc (qe->proc_cls,
476 &msg->private_key,
477 name,
478 rd_count,
479 (rd_count > 0) ? rd : NULL);
480 }
481 free_qe (qe);
482}
483
484
485/**
486 * Handle an incoming message of type
487 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
488 *
489 * @param cls
490 * @param msg the message we received
491 * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
492 */
493static int
494check_record_result (void *cls, const struct RecordResultMessage *msg)
495{
496 static struct GNUNET_IDENTITY_PrivateKey priv_dummy;
497 const char *name;
498 size_t msg_len;
499 size_t name_len;
500 size_t rd_len;
501
502 (void) cls;
503 rd_len = ntohs (msg->rd_len);
504 msg_len = ntohs (msg->gns_header.header.size);
505 name_len = ntohs (msg->name_len);
506 if (0 != ntohs (msg->reserved))
507 {
508 GNUNET_break (0);
509 return GNUNET_SYSERR;
510 }
511 if (msg_len != sizeof(struct RecordResultMessage) + name_len + rd_len)
512 {
513 GNUNET_break (0);
514 return GNUNET_SYSERR;
515 }
516 name = (const char *) &msg[1];
517 if ((0 == name_len) || ('\0' != name[name_len - 1]))
518 {
519 GNUNET_break (0);
520 return GNUNET_SYSERR;
521 }
522 if (0 == GNUNET_memcmp (&msg->private_key, &priv_dummy))
523 {
524 GNUNET_break (0);
525 return GNUNET_SYSERR;
526 }
527 return check_rd (rd_len, &name[name_len], ntohs (msg->rd_count));
528}
529
530
531/**
532 * Handle an incoming message of type
533 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT
534 *
535 * @param cls
536 * @param msg the message we received
537 */
538static void
539handle_record_result (void *cls, const struct RecordResultMessage *msg)
540{
541 struct GNUNET_NAMESTORE_Handle *h = cls;
542 struct GNUNET_NAMESTORE_QueueEntry *qe;
543 struct GNUNET_NAMESTORE_ZoneIterator *ze;
544 const char *name;
545 const char *rd_tmp;
546 size_t name_len;
547 size_t rd_len;
548 unsigned int rd_count;
549
550 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT\n");
551 rd_len = ntohs (msg->rd_len);
552 rd_count = ntohs (msg->rd_count);
553 name_len = ntohs (msg->name_len);
554 ze = find_zi (h, ntohl (msg->gns_header.r_id));
555 qe = find_qe (h, ntohl (msg->gns_header.r_id));
556 if ((NULL == ze) && (NULL == qe))
557 return; /* rid not found */
558 if ((NULL != ze) && (NULL != qe))
559 {
560 GNUNET_break (0); /* rid ambiguous */
561 force_reconnect (h);
562 return;
563 }
564 name = (const char *) &msg[1];
565 rd_tmp = &name[name_len];
566 {
567 struct GNUNET_GNSRECORD_Data rd[rd_count];
568
569 GNUNET_assert (
570 GNUNET_OK ==
571 GNUNET_GNSRECORD_records_deserialize (rd_len, rd_tmp, rd_count, rd));
572 if (0 == name_len)
573 name = NULL;
574 if (NULL != qe)
575 {
576 if (NULL != qe->proc)
577 qe->proc (qe->proc_cls,
578 &msg->private_key,
579 name,
580 rd_count,
581 (rd_count > 0) ? rd : NULL);
582 free_qe (qe);
583 return;
584 }
585 if (NULL != ze)
586 {
587 if (NULL != ze->proc)
588 ze->proc (ze->proc_cls, &msg->private_key, name, rd_count, rd);
589 return;
590 }
591 }
592 GNUNET_assert (0);
593}
594
595
596/**
597 * Handle an incoming message of type
598 * #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END
599 *
600 * @param cls
601 * @param msg the message we received
602 */
603static void
604handle_record_result_end (void *cls, const struct GNUNET_NAMESTORE_Header *msg)
605{
606 struct GNUNET_NAMESTORE_Handle *h = cls;
607 struct GNUNET_NAMESTORE_QueueEntry *qe;
608 struct GNUNET_NAMESTORE_ZoneIterator *ze;
609
610 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received RECORD_RESULT_END\n");
611 ze = find_zi (h, ntohl (msg->r_id));
612 qe = find_qe (h, ntohl (msg->r_id));
613 if ((NULL == ze) && (NULL == qe))
614 return; /* rid not found */
615 if ((NULL != ze) && (NULL != qe))
616 {
617 GNUNET_break (0); /* rid ambiguous */
618 force_reconnect (h);
619 return;
620 }
621 LOG (GNUNET_ERROR_TYPE_DEBUG, "Zone iteration completed!\n");
622 if (NULL == ze)
623 {
624 GNUNET_break (0);
625 force_reconnect (h);
626 return;
627 }
628 if (NULL != ze->finish_cb)
629 ze->finish_cb (ze->finish_cb_cls);
630 free_ze (ze);
631}
632
633
634/**
635 * Handle an incoming message of type
636 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
637 *
638 * @param qe the respective entry in the message queue
639 * @param msg the message we received
640 * @return #GNUNET_OK on success, #GNUNET_SYSERR if message malformed
641 */
642static int
643check_zone_to_name_response (void *cls,
644 const struct ZoneToNameResponseMessage *msg)
645{
646 size_t name_len;
647 size_t rd_ser_len;
648 const char *name_tmp;
649
650 (void) cls;
651 if (GNUNET_OK != ntohs (msg->res))
652 return GNUNET_OK;
653 name_len = ntohs (msg->name_len);
654 rd_ser_len = ntohs (msg->rd_len);
655 if (ntohs (msg->gns_header.header.size) !=
656 sizeof(struct ZoneToNameResponseMessage) + name_len + rd_ser_len)
657 {
658 GNUNET_break (0);
659 return GNUNET_SYSERR;
660 }
661 name_tmp = (const char *) &msg[1];
662 if ((name_len > 0) && ('\0' != name_tmp[name_len - 1]))
663 {
664 GNUNET_break (0);
665 return GNUNET_SYSERR;
666 }
667 return check_rd (rd_ser_len, &name_tmp[name_len], ntohs (msg->rd_count));
668}
669
670
671/**
672 * Handle an incoming message of type
673 * #GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE.
674 *
675 * @param cls
676 * @param msg the message we received
677 */
678static void
679handle_zone_to_name_response (void *cls,
680 const struct ZoneToNameResponseMessage *msg)
681{
682 struct GNUNET_NAMESTORE_Handle *h = cls;
683 struct GNUNET_NAMESTORE_QueueEntry *qe;
684 int res;
685 size_t name_len;
686 size_t rd_ser_len;
687 unsigned int rd_count;
688 const char *name_tmp;
689 const char *rd_tmp;
690
691 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received ZONE_TO_NAME_RESPONSE\n");
692 qe = find_qe (h, ntohl (msg->gns_header.r_id));
693 if (NULL == qe)
694 {
695 LOG (GNUNET_ERROR_TYPE_WARNING,
696 "Response queue already gone...\n");
697 return;
698 }
699 res = ntohs (msg->res);
700 switch (res)
701 {
702 case GNUNET_SYSERR:
703 LOG (GNUNET_ERROR_TYPE_DEBUG,
704 "An error occurred during zone to name operation\n");
705 break;
706
707 case GNUNET_NO:
708 LOG (GNUNET_ERROR_TYPE_DEBUG,
709 "Namestore has no result for zone to name mapping \n");
710 if (NULL != qe->proc)
711 qe->proc (qe->proc_cls, &msg->zone, NULL, 0, NULL);
712 free_qe (qe);
713 return;
714
715 case GNUNET_YES:
716 LOG (GNUNET_ERROR_TYPE_DEBUG,
717 "Namestore has result for zone to name mapping \n");
718 name_len = ntohs (msg->name_len);
719 rd_count = ntohs (msg->rd_count);
720 rd_ser_len = ntohs (msg->rd_len);
721 name_tmp = (const char *) &msg[1];
722 rd_tmp = &name_tmp[name_len];
723 {
724 struct GNUNET_GNSRECORD_Data rd[rd_count];
725
726 GNUNET_assert (GNUNET_OK ==
727 GNUNET_GNSRECORD_records_deserialize (rd_ser_len,
728 rd_tmp,
729 rd_count,
730 rd));
731 /* normal end, call continuation with result */
732 if (NULL != qe->proc)
733 qe->proc (qe->proc_cls, &msg->zone, name_tmp, rd_count, rd);
734 /* return is important here: break would call continuation with error! */
735 free_qe (qe);
736 return;
737 }
738
739 default:
740 GNUNET_break (0);
741 force_reconnect (h);
742 return;
743 }
744 /* error case, call continuation with error */
745 if (NULL != qe->error_cb)
746 qe->error_cb (qe->error_cb_cls);
747 free_qe (qe);
748}
749
750
751/**
752 * Generic error handler, called with the appropriate error code and
753 * the same closure specified at the creation of the message queue.
754 * Not every message queue implementation supports an error handler.
755 *
756 * @param cls closure with the `struct GNUNET_NAMESTORE_Handle *`
757 * @param error error code
758 */
759static void
760mq_error_handler (void *cls, enum GNUNET_MQ_Error error)
761{
762 struct GNUNET_NAMESTORE_Handle *h = cls;
763
764 (void) error;
765 force_reconnect (h);
766}
767
768
769/**
770 * Reconnect to namestore service.
771 *
772 * @param h the handle to the NAMESTORE service
773 */
774static void
775reconnect (struct GNUNET_NAMESTORE_Handle *h)
776{
777 struct GNUNET_MQ_MessageHandler handlers[] =
778 { GNUNET_MQ_hd_fixed_size (record_store_response,
779 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE_RESPONSE,
780 struct RecordStoreResponseMessage,
781 h),
782 GNUNET_MQ_hd_var_size (zone_to_name_response,
783 GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME_RESPONSE,
784 struct ZoneToNameResponseMessage,
785 h),
786 GNUNET_MQ_hd_var_size (record_result,
787 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT,
788 struct RecordResultMessage,
789 h),
790 GNUNET_MQ_hd_fixed_size (record_result_end,
791 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_RESULT_END,
792 struct GNUNET_NAMESTORE_Header,
793 h),
794 GNUNET_MQ_hd_var_size (lookup_result,
795 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP_RESPONSE,
796 struct LabelLookupResponseMessage,
797 h),
798 GNUNET_MQ_handler_end () };
799 struct GNUNET_NAMESTORE_ZoneIterator *it;
800 struct GNUNET_NAMESTORE_QueueEntry *qe;
801
802 GNUNET_assert (NULL == h->mq);
803 h->mq =
804 GNUNET_CLIENT_connect (h->cfg, "namestore", handlers, &mq_error_handler, h);
805 if (NULL == h->mq)
806 return;
807 /* re-transmit pending requests that waited for a reconnect... */
808 for (it = h->z_head; NULL != it; it = it->next)
809 {
810 GNUNET_MQ_send (h->mq, it->env);
811 it->env = NULL;
812 }
813 for (qe = h->op_head; NULL != qe; qe = qe->next)
814 {
815 GNUNET_MQ_send (h->mq, qe->env);
816 qe->env = NULL;
817 }
818}
819
820
821/**
822 * Re-establish the connection to the service.
823 *
824 * @param cls handle to use to re-connect.
825 */
826static void
827reconnect_task (void *cls)
828{
829 struct GNUNET_NAMESTORE_Handle *h = cls;
830
831 h->reconnect_task = NULL;
832 reconnect (h);
833}
834
835
836/**
837 * Disconnect from service and then reconnect.
838 *
839 * @param h our handle
840 */
841static void
842force_reconnect (struct GNUNET_NAMESTORE_Handle *h)
843{
844 struct GNUNET_NAMESTORE_ZoneIterator *ze;
845 struct GNUNET_NAMESTORE_QueueEntry *qe;
846
847 GNUNET_MQ_destroy (h->mq);
848 h->mq = NULL;
849 while (NULL != (ze = h->z_head))
850 {
851 if (NULL != ze->error_cb)
852 ze->error_cb (ze->error_cb_cls);
853 free_ze (ze);
854 }
855 while (NULL != (qe = h->op_head))
856 {
857 if (NULL != qe->error_cb)
858 qe->error_cb (qe->error_cb_cls);
859 if (NULL != qe->cont)
860 qe->cont (qe->cont_cls,
861 GNUNET_SYSERR,
862 "failure in communication with namestore service");
863 free_qe (qe);
864 }
865
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnecting to namestore\n");
867 h->reconnect_delay = GNUNET_TIME_STD_BACKOFF (h->reconnect_delay);
868 h->reconnect_task =
869 GNUNET_SCHEDULER_add_delayed (h->reconnect_delay, &reconnect_task, h);
870}
871
872
873/**
874 * Get a fresh operation id to distinguish between namestore requests
875 *
876 * @param h the namestore handle
877 * @return next operation id to use
878 */
879static uint32_t
880get_op_id (struct GNUNET_NAMESTORE_Handle *h)
881{
882 return h->last_op_id_used++;
883}
884
885
886/**
887 * Initialize the connection with the NAMESTORE service.
888 *
889 * @param cfg configuration to use
890 * @return handle to the GNS service, or NULL on error
891 */
892struct GNUNET_NAMESTORE_Handle *
893GNUNET_NAMESTORE_connect (const struct GNUNET_CONFIGURATION_Handle *cfg)
894{
895 struct GNUNET_NAMESTORE_Handle *h;
896
897 h = GNUNET_new (struct GNUNET_NAMESTORE_Handle);
898 h->cfg = cfg;
899 reconnect (h);
900 if (NULL == h->mq)
901 {
902 GNUNET_free (h);
903 return NULL;
904 }
905 return h;
906}
907
908
909/**
910 * Disconnect from the namestore service (and free associated
911 * resources).
912 *
913 * @param h handle to the namestore
914 */
915void
916GNUNET_NAMESTORE_disconnect (struct GNUNET_NAMESTORE_Handle *h)
917{
918 struct GNUNET_NAMESTORE_QueueEntry *q;
919 struct GNUNET_NAMESTORE_ZoneIterator *z;
920
921 LOG (GNUNET_ERROR_TYPE_DEBUG, "Cleaning up\n");
922 GNUNET_break (NULL == h->op_head);
923 while (NULL != (q = h->op_head))
924 {
925 GNUNET_CONTAINER_DLL_remove (h->op_head, h->op_tail, q);
926 GNUNET_free (q);
927 }
928 GNUNET_break (NULL == h->z_head);
929 while (NULL != (z = h->z_head))
930 {
931 GNUNET_CONTAINER_DLL_remove (h->z_head, h->z_tail, z);
932 GNUNET_free (z);
933 }
934 if (NULL != h->mq)
935 {
936 GNUNET_MQ_destroy (h->mq);
937 h->mq = NULL;
938 }
939 if (NULL != h->reconnect_task)
940 {
941 GNUNET_SCHEDULER_cancel (h->reconnect_task);
942 h->reconnect_task = NULL;
943 }
944 GNUNET_free (h);
945}
946
947
948/**
949 * Task launched to warn the user that the namestore is
950 * excessively slow and that a query was thus dropped.
951 *
952 * @param cls a `struct GNUNET_NAMESTORE_QueueEntry *`
953 */
954static void
955warn_delay (void *cls)
956{
957 struct GNUNET_NAMESTORE_QueueEntry *qe = cls;
958
959 qe->timeout_task = NULL;
960 LOG (GNUNET_ERROR_TYPE_WARNING,
961 "Did not receive response from namestore after %s!\n",
962 GNUNET_STRINGS_relative_time_to_string (NAMESTORE_DELAY_TOLERANCE,
963 GNUNET_YES));
964 if (NULL != qe->cont)
965 {
966 qe->cont (qe->cont_cls, GNUNET_SYSERR, "timeout");
967 qe->cont = NULL;
968 }
969 GNUNET_NAMESTORE_cancel (qe);
970}
971
972
973/**
974 * Store an item in the namestore. If the item is already present,
975 * it is replaced with the new record. Use an empty array to
976 * remove all records under the given name.
977 *
978 * @param h handle to the namestore
979 * @param pkey private key of the zone
980 * @param label name that is being mapped (at most 255 characters long)
981 * @param rd_count number of records in the @a rd array
982 * @param rd array of records with data to store
983 * @param cont continuation to call when done
984 * @param cont_cls closure for @a cont
985 * @return handle to abort the request
986 */
987struct GNUNET_NAMESTORE_QueueEntry *
988GNUNET_NAMESTORE_records_store (
989 struct GNUNET_NAMESTORE_Handle *h,
990 const struct GNUNET_IDENTITY_PrivateKey *pkey,
991 const char *label,
992 unsigned int rd_count,
993 const struct GNUNET_GNSRECORD_Data *rd,
994 GNUNET_NAMESTORE_ContinuationWithStatus cont,
995 void *cont_cls)
996{
997 struct GNUNET_NAMESTORE_QueueEntry *qe;
998 struct GNUNET_MQ_Envelope *env;
999 char *name_tmp;
1000 char *rd_ser;
1001 ssize_t rd_ser_len;
1002 size_t name_len;
1003 uint32_t rid;
1004 struct RecordStoreMessage *msg;
1005 ssize_t sret;
1006
1007 name_len = strlen (label) + 1;
1008 if (name_len > MAX_NAME_LEN)
1009 {
1010 GNUNET_break (0);
1011 return NULL;
1012 }
1013 rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd);
1014 if (rd_ser_len < 0)
1015 {
1016 GNUNET_break (0);
1017 return NULL;
1018 }
1019 if (rd_ser_len > UINT16_MAX)
1020 {
1021 GNUNET_break (0);
1022 return NULL;
1023 }
1024 rid = get_op_id (h);
1025 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1026 qe->h = h;
1027 qe->cont = cont;
1028 qe->cont_cls = cont_cls;
1029 qe->op_id = rid;
1030 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1031
1032 /* setup msg */
1033 env = GNUNET_MQ_msg_extra (msg,
1034 name_len + rd_ser_len,
1035 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE);
1036 msg->gns_header.r_id = htonl (rid);
1037 msg->name_len = htons (name_len);
1038 msg->rd_count = htons (rd_count);
1039 msg->rd_len = htons (rd_ser_len);
1040 msg->reserved = htons (0);
1041 msg->private_key = *pkey;
1042
1043 name_tmp = (char *) &msg[1];
1044 GNUNET_memcpy (name_tmp, label, name_len);
1045 rd_ser = &name_tmp[name_len];
1046 sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser);
1047 if ((0 > sret) || (sret != rd_ser_len))
1048 {
1049 GNUNET_break (0);
1050 GNUNET_free (env);
1051 return NULL;
1052 }
1053 GNUNET_assert (rd_ser_len == sret);
1054 LOG (GNUNET_ERROR_TYPE_DEBUG,
1055 "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n",
1056 label,
1057 rd_count);
1058 qe->timeout_task =
1059 GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe);
1060 if (NULL == h->mq)
1061 {
1062 qe->env = env;
1063 LOG (GNUNET_ERROR_TYPE_WARNING,
1064 "Delaying NAMESTORE_RECORD_STORE message as namestore is not ready!\n");
1065 }
1066 else
1067 {
1068 GNUNET_MQ_send (h->mq, env);
1069 }
1070 return qe;
1071}
1072
1073
1074/**
1075 * Lookup an item in the namestore.
1076 *
1077 * @param h handle to the namestore
1078 * @param pkey private key of the zone
1079 * @param label name that is being mapped (at most 255 characters long)
1080 * @param error_cb function to call on error (i.e. disconnect)
1081 * @param error_cb_cls closure for @a error_cb
1082 * @param rm function to call with the result (with 0 records if we don't have that label)
1083 * @param rm_cls closure for @a rm
1084 * @return handle to abort the request
1085 */
1086struct GNUNET_NAMESTORE_QueueEntry *
1087GNUNET_NAMESTORE_records_lookup (
1088 struct GNUNET_NAMESTORE_Handle *h,
1089 const struct GNUNET_IDENTITY_PrivateKey *pkey,
1090 const char *label,
1091 GNUNET_SCHEDULER_TaskCallback error_cb,
1092 void *error_cb_cls,
1093 GNUNET_NAMESTORE_RecordMonitor rm,
1094 void *rm_cls)
1095{
1096 struct GNUNET_NAMESTORE_QueueEntry *qe;
1097 struct GNUNET_MQ_Envelope *env;
1098 struct LabelLookupMessage *msg;
1099 size_t label_len;
1100
1101 if (1 == (label_len = strlen (label) + 1))
1102 {
1103 GNUNET_break (0);
1104 return NULL;
1105 }
1106
1107 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1108 qe->h = h;
1109 qe->error_cb = error_cb;
1110 qe->error_cb_cls = error_cb_cls;
1111 qe->proc = rm;
1112 qe->proc_cls = rm_cls;
1113 qe->op_id = get_op_id (h);
1114 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1115
1116 env = GNUNET_MQ_msg_extra (msg,
1117 label_len,
1118 GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_LOOKUP);
1119 msg->gns_header.r_id = htonl (qe->op_id);
1120 msg->zone = *pkey;
1121 msg->label_len = htonl (label_len);
1122 GNUNET_memcpy (&msg[1], label, label_len);
1123 if (NULL == h->mq)
1124 qe->env = env;
1125 else
1126 GNUNET_MQ_send (h->mq, env);
1127 return qe;
1128}
1129
1130
1131/**
1132 * Look for an existing PKEY delegation record for a given public key.
1133 * Returns at most one result to the processor.
1134 *
1135 * @param h handle to the namestore
1136 * @param zone public key of the zone to look up in, never NULL
1137 * @param value_zone public key of the target zone (value), never NULL
1138 * @param error_cb function to call on error (i.e. disconnect)
1139 * @param error_cb_cls closure for @a error_cb
1140 * @param proc function to call on the matching records, or with
1141 * NULL (rd_count == 0) if there are no matching records
1142 * @param proc_cls closure for @a proc
1143 * @return a handle that can be used to
1144 * cancel
1145 */
1146struct GNUNET_NAMESTORE_QueueEntry *
1147GNUNET_NAMESTORE_zone_to_name (
1148 struct GNUNET_NAMESTORE_Handle *h,
1149 const struct GNUNET_IDENTITY_PrivateKey *zone,
1150 const struct GNUNET_IDENTITY_PublicKey *value_zone,
1151 GNUNET_SCHEDULER_TaskCallback error_cb,
1152 void *error_cb_cls,
1153 GNUNET_NAMESTORE_RecordMonitor proc,
1154 void *proc_cls)
1155{
1156 struct GNUNET_NAMESTORE_QueueEntry *qe;
1157 struct GNUNET_MQ_Envelope *env;
1158 struct ZoneToNameMessage *msg;
1159 uint32_t rid;
1160
1161 rid = get_op_id (h);
1162 qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry);
1163 qe->h = h;
1164 qe->error_cb = error_cb;
1165 qe->error_cb_cls = error_cb_cls;
1166 qe->proc = proc;
1167 qe->proc_cls = proc_cls;
1168 qe->op_id = rid;
1169 GNUNET_CONTAINER_DLL_insert_tail (h->op_head, h->op_tail, qe);
1170
1171 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_TO_NAME);
1172 msg->gns_header.r_id = htonl (rid);
1173 msg->zone = *zone;
1174 msg->value_zone = *value_zone;
1175 if (NULL == h->mq)
1176 qe->env = env;
1177 else
1178 GNUNET_MQ_send (h->mq, env);
1179 return qe;
1180}
1181
1182
1183/**
1184 * Starts a new zone iteration (used to periodically PUT all of our
1185 * records into our DHT). This MUST lock the struct GNUNET_NAMESTORE_Handle
1186 * for any other calls than #GNUNET_NAMESTORE_zone_iterator_next and
1187 * #GNUNET_NAMESTORE_zone_iteration_stop. @a proc will be called once
1188 * immediately, and then again after
1189 * #GNUNET_NAMESTORE_zone_iterator_next is invoked.
1190 *
1191 * @param h handle to the namestore
1192 * @param zone zone to access, NULL for all zones
1193 * @param error_cb function to call on error (i.e. disconnect)
1194 * @param error_cb_cls closure for @a error_cb
1195 * @param proc function to call on each name from the zone; it
1196 * will be called repeatedly with a value (if available)
1197 * @param proc_cls closure for @a proc
1198 * @param finish_cb function to call on completion
1199 * @param finish_cb_cls closure for @a finish_cb
1200 * @return an iterator handle to use for iteration
1201 */
1202struct GNUNET_NAMESTORE_ZoneIterator *
1203GNUNET_NAMESTORE_zone_iteration_start (
1204 struct GNUNET_NAMESTORE_Handle *h,
1205 const struct GNUNET_IDENTITY_PrivateKey *zone,
1206 GNUNET_SCHEDULER_TaskCallback error_cb,
1207 void *error_cb_cls,
1208 GNUNET_NAMESTORE_RecordMonitor proc,
1209 void *proc_cls,
1210 GNUNET_SCHEDULER_TaskCallback finish_cb,
1211 void *finish_cb_cls)
1212{
1213 struct GNUNET_NAMESTORE_ZoneIterator *it;
1214 struct GNUNET_MQ_Envelope *env;
1215 struct ZoneIterationStartMessage *msg;
1216 uint32_t rid;
1217
1218 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_START message\n");
1219 rid = get_op_id (h);
1220 it = GNUNET_new (struct GNUNET_NAMESTORE_ZoneIterator);
1221 it->h = h;
1222 it->error_cb = error_cb;
1223 it->error_cb_cls = error_cb_cls;
1224 it->finish_cb = finish_cb;
1225 it->finish_cb_cls = finish_cb_cls;
1226 it->proc = proc;
1227 it->proc_cls = proc_cls;
1228 it->op_id = rid;
1229 if (NULL != zone)
1230 it->zone = *zone;
1231 GNUNET_CONTAINER_DLL_insert_tail (h->z_head, h->z_tail, it);
1232 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_START);
1233 msg->gns_header.r_id = htonl (rid);
1234 if (NULL != zone)
1235 msg->zone = *zone;
1236 if (NULL == h->mq)
1237 it->env = env;
1238 else
1239 GNUNET_MQ_send (h->mq, env);
1240 return it;
1241}
1242
1243
1244/**
1245 * Calls the record processor specified in #GNUNET_NAMESTORE_zone_iteration_start
1246 * for the next record.
1247 *
1248 * @param it the iterator
1249 * @param limit number of records to return to the iterator in one shot
1250 * (before #GNUNET_NAMESTORE_zone_iterator_next is to be called again)
1251 */
1252void
1253GNUNET_NAMESTORE_zone_iterator_next (struct GNUNET_NAMESTORE_ZoneIterator *it,
1254 uint64_t limit)
1255{
1256 struct GNUNET_NAMESTORE_Handle *h = it->h;
1257 struct ZoneIterationNextMessage *msg;
1258 struct GNUNET_MQ_Envelope *env;
1259
1260 LOG (GNUNET_ERROR_TYPE_DEBUG,
1261 "Sending ZONE_ITERATION_NEXT message with limit %llu\n",
1262 (unsigned long long) limit);
1263 env = GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_NEXT);
1264 msg->gns_header.r_id = htonl (it->op_id);
1265 msg->limit = GNUNET_htonll (limit);
1266 GNUNET_MQ_send (h->mq, env);
1267}
1268
1269
1270/**
1271 * Stops iteration and releases the namestore handle for further calls.
1272 *
1273 * @param it the iterator
1274 */
1275void
1276GNUNET_NAMESTORE_zone_iteration_stop (struct GNUNET_NAMESTORE_ZoneIterator *it)
1277{
1278 struct GNUNET_NAMESTORE_Handle *h = it->h;
1279 struct GNUNET_MQ_Envelope *env;
1280 struct ZoneIterationStopMessage *msg;
1281
1282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending ZONE_ITERATION_STOP message\n");
1283 if (NULL != h->mq)
1284 {
1285 env =
1286 GNUNET_MQ_msg (msg, GNUNET_MESSAGE_TYPE_NAMESTORE_ZONE_ITERATION_STOP);
1287 msg->gns_header.r_id = htonl (it->op_id);
1288 GNUNET_MQ_send (h->mq, env);
1289 }
1290 free_ze (it);
1291}
1292
1293
1294/**
1295 * Cancel a namestore operation. The final callback from the
1296 * operation must not have been done yet.
1297 *
1298 * @param qe operation to cancel
1299 */
1300void
1301GNUNET_NAMESTORE_cancel (struct GNUNET_NAMESTORE_QueueEntry *qe)
1302{
1303 free_qe (qe);
1304}
1305
1306
1307/* 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 7cb9b7ed0..000000000
--- a/src/namestore/plugin_namestore_sqlite.c
+++ /dev/null
@@ -1,791 +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 if (GNUNET_YES == GNUNET_GNSRECORD_is_zonekey_type (rd[i].record_type))
333 {
334 GNUNET_break (GNUNET_YES ==
335 GNUNET_GNSRECORD_identity_from_data (rd[i].data,
336 rd[i].data_size,
337 rd[i].record_type,
338 &pkey));
339 break;
340 }
341 rvalue = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
342 UINT64_MAX);
343 data_size = GNUNET_GNSRECORD_records_get_size (rd_count,
344 rd);
345 if (data_size < 0)
346 {
347 GNUNET_break (0);
348 return GNUNET_SYSERR;
349 }
350 if (data_size > 64 * 65536)
351 {
352 GNUNET_break (0);
353 return GNUNET_SYSERR;
354 }
355 {
356 /* First delete 'old' records */
357 char data[data_size];
358 struct GNUNET_SQ_QueryParam dparams[] = {
359 GNUNET_SQ_query_param_auto_from_type (zone_key),
360 GNUNET_SQ_query_param_string (label),
361 GNUNET_SQ_query_param_end
362 };
363 ssize_t ret;
364
365 ret = GNUNET_GNSRECORD_records_serialize (rd_count,
366 rd,
367 data_size,
368 data);
369 if ((ret < 0) ||
370 (data_size != ret))
371 {
372 GNUNET_break (0);
373 return GNUNET_SYSERR;
374 }
375 if (GNUNET_OK !=
376 GNUNET_SQ_bind (plugin->delete_records,
377 dparams))
378 {
379 LOG_SQLITE (plugin,
380 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
381 "sqlite3_bind_XXXX");
382 GNUNET_SQ_reset (plugin->dbh,
383 plugin->delete_records);
384 return GNUNET_SYSERR;
385 }
386 n = sqlite3_step (plugin->delete_records);
387 GNUNET_SQ_reset (plugin->dbh,
388 plugin->delete_records);
389
390 if (0 != rd_count)
391 {
392 uint32_t rd_count32 = (uint32_t) rd_count;
393 struct GNUNET_SQ_QueryParam sparams[] = {
394 GNUNET_SQ_query_param_auto_from_type (zone_key),
395 GNUNET_SQ_query_param_auto_from_type (&pkey),
396 GNUNET_SQ_query_param_uint64 (&rvalue),
397 GNUNET_SQ_query_param_uint32 (&rd_count32),
398 GNUNET_SQ_query_param_fixed_size (data, data_size),
399 GNUNET_SQ_query_param_string (label),
400 GNUNET_SQ_query_param_end
401 };
402
403 if (GNUNET_OK !=
404 GNUNET_SQ_bind (plugin->store_records,
405 sparams))
406 {
407 LOG_SQLITE (plugin,
408 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
409 "sqlite3_bind_XXXX");
410 GNUNET_SQ_reset (plugin->dbh,
411 plugin->store_records);
412 return GNUNET_SYSERR;
413 }
414 n = sqlite3_step (plugin->store_records);
415 GNUNET_SQ_reset (plugin->dbh,
416 plugin->store_records);
417 }
418 }
419 switch (n)
420 {
421 case SQLITE_DONE:
422 if (0 != rd_count)
423 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
424 "sqlite",
425 "Record stored\n");
426 else
427 GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG,
428 "sqlite",
429 "Record deleted\n");
430 return GNUNET_OK;
431
432 case SQLITE_BUSY:
433 LOG_SQLITE (plugin,
434 GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK,
435 "sqlite3_step");
436 return GNUNET_NO;
437
438 default:
439 LOG_SQLITE (plugin,
440 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
441 "sqlite3_step");
442 return GNUNET_SYSERR;
443 }
444}
445
446
447/**
448 * The given 'sqlite' statement has been prepared to be run.
449 * It will return a record which should be given to the iterator.
450 * Runs the statement and parses the returned record.
451 *
452 * @param plugin plugin context
453 * @param stmt to run (and then clean up)
454 * @param zone_key private key of the zone
455 * @param limit maximum number of results to fetch
456 * @param iter iterator to call with the result
457 * @param iter_cls closure for @a iter
458 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
459 */
460static int
461get_records_and_call_iterator (struct Plugin *plugin,
462 sqlite3_stmt *stmt,
463 const struct
464 GNUNET_IDENTITY_PrivateKey *zone_key,
465 uint64_t limit,
466 GNUNET_NAMESTORE_RecordIterator iter,
467 void *iter_cls)
468{
469 int ret;
470 int sret;
471
472 ret = GNUNET_OK;
473 for (uint64_t i = 0; i < limit; i++)
474 {
475 sret = sqlite3_step (stmt);
476
477 if (SQLITE_DONE == sret)
478 {
479 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
480 "Iteration done (no results)\n");
481 ret = GNUNET_NO;
482 break;
483 }
484 if (SQLITE_ROW != sret)
485 {
486 LOG_SQLITE (plugin,
487 GNUNET_ERROR_TYPE_ERROR,
488 "sqlite_step");
489 ret = GNUNET_SYSERR;
490 break;
491 }
492
493 {
494 uint64_t seq;
495 uint32_t record_count;
496 size_t data_size;
497 void *data;
498 char *label;
499 struct GNUNET_IDENTITY_PrivateKey zk;
500 struct GNUNET_SQ_ResultSpec rs[] = {
501 GNUNET_SQ_result_spec_uint64 (&seq),
502 GNUNET_SQ_result_spec_uint32 (&record_count),
503 GNUNET_SQ_result_spec_variable_size (&data,
504 &data_size),
505 GNUNET_SQ_result_spec_string (&label),
506 GNUNET_SQ_result_spec_end
507 };
508 struct GNUNET_SQ_ResultSpec rsx[] = {
509 GNUNET_SQ_result_spec_uint64 (&seq),
510 GNUNET_SQ_result_spec_uint32 (&record_count),
511 GNUNET_SQ_result_spec_variable_size (&data,
512 &data_size),
513 GNUNET_SQ_result_spec_string (&label),
514 GNUNET_SQ_result_spec_auto_from_type (&zk),
515 GNUNET_SQ_result_spec_end
516 };
517
518 ret = GNUNET_SQ_extract_result (stmt,
519 (NULL == zone_key)
520 ? rsx
521 : rs);
522 if ((GNUNET_OK != ret) ||
523 (record_count > 64 * 1024))
524 {
525 /* sanity check, don't stack allocate far too much just
526 because database might contain a large value here */
527 GNUNET_break (0);
528 ret = GNUNET_SYSERR;
529 break;
530 }
531 else
532 {
533 struct GNUNET_GNSRECORD_Data rd[record_count];
534
535 GNUNET_assert (0 != seq);
536 if (GNUNET_OK !=
537 GNUNET_GNSRECORD_records_deserialize (data_size,
538 data,
539 record_count,
540 rd))
541 {
542 GNUNET_break (0);
543 ret = GNUNET_SYSERR;
544 break;
545 }
546 else
547 {
548 if (NULL != zone_key)
549 zk = *zone_key;
550 if (NULL != iter)
551 iter (iter_cls,
552 seq,
553 &zk,
554 label,
555 record_count,
556 rd);
557 }
558 }
559 GNUNET_SQ_cleanup_result (rs);
560 }
561 }
562 GNUNET_SQ_reset (plugin->dbh,
563 stmt);
564 return ret;
565}
566
567
568/**
569 * Lookup records in the datastore for which we are the authority.
570 *
571 * @param cls closure (internal context for the plugin)
572 * @param zone private key of the zone
573 * @param label name of the record in the zone
574 * @param iter function to call with the result
575 * @param iter_cls closure for @a iter
576 * @return #GNUNET_OK on success, #GNUNET_NO for no results, else #GNUNET_SYSERR
577 */
578static int
579namestore_sqlite_lookup_records (void *cls,
580 const struct
581 GNUNET_IDENTITY_PrivateKey *zone,
582 const char *label,
583 GNUNET_NAMESTORE_RecordIterator iter,
584 void *iter_cls)
585{
586 struct Plugin *plugin = cls;
587 struct GNUNET_SQ_QueryParam params[] = {
588 GNUNET_SQ_query_param_auto_from_type (zone),
589 GNUNET_SQ_query_param_string (label),
590 GNUNET_SQ_query_param_end
591 };
592
593 if (NULL == zone)
594 {
595 GNUNET_break (0);
596 return GNUNET_SYSERR;
597 }
598 if (GNUNET_OK !=
599 GNUNET_SQ_bind (plugin->lookup_label,
600 params))
601 {
602 LOG_SQLITE (plugin, GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
603 "sqlite3_bind_XXXX");
604 GNUNET_SQ_reset (plugin->dbh,
605 plugin->lookup_label);
606 return GNUNET_SYSERR;
607 }
608 return get_records_and_call_iterator (plugin,
609 plugin->lookup_label,
610 zone,
611 1,
612 iter,
613 iter_cls);
614}
615
616
617/**
618 * Iterate over the results for a particular key and zone in the
619 * datastore. Will return at most one result to the iterator.
620 *
621 * @param cls closure (internal context for the plugin)
622 * @param zone hash of public key of the zone, NULL to iterate over all zones
623 * @param serial serial number to exclude in the list of all matching records
624 * @param limit maximum number of results to return
625 * @param iter function to call with the result
626 * @param iter_cls closure for @a iter
627 * @return #GNUNET_OK on success, #GNUNET_NO if there were no more results, #GNUNET_SYSERR on error
628 */
629static int
630namestore_sqlite_iterate_records (void *cls,
631 const struct
632 GNUNET_IDENTITY_PrivateKey *zone,
633 uint64_t serial,
634 uint64_t limit,
635 GNUNET_NAMESTORE_RecordIterator iter,
636 void *iter_cls)
637{
638 struct Plugin *plugin = cls;
639 sqlite3_stmt *stmt;
640 int err;
641
642 if (NULL == zone)
643 {
644 struct GNUNET_SQ_QueryParam params[] = {
645 GNUNET_SQ_query_param_uint64 (&serial),
646 GNUNET_SQ_query_param_uint64 (&limit),
647 GNUNET_SQ_query_param_end
648 };
649
650 stmt = plugin->iterate_all_zones;
651 err = GNUNET_SQ_bind (stmt,
652 params);
653 }
654 else
655 {
656 struct GNUNET_SQ_QueryParam params[] = {
657 GNUNET_SQ_query_param_auto_from_type (zone),
658 GNUNET_SQ_query_param_uint64 (&serial),
659 GNUNET_SQ_query_param_uint64 (&limit),
660 GNUNET_SQ_query_param_end
661 };
662
663 stmt = plugin->iterate_zone;
664 err = GNUNET_SQ_bind (stmt,
665 params);
666 }
667 if (GNUNET_OK != err)
668 {
669 LOG_SQLITE (plugin,
670 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
671 "sqlite3_bind_XXXX");
672 GNUNET_SQ_reset (plugin->dbh,
673 stmt);
674 return GNUNET_SYSERR;
675 }
676 return get_records_and_call_iterator (plugin,
677 stmt,
678 zone,
679 limit,
680 iter,
681 iter_cls);
682}
683
684
685/**
686 * Look for an existing PKEY delegation record for a given public key.
687 * Returns at most one result to the iterator.
688 *
689 * @param cls closure (internal context for the plugin)
690 * @param zone private key of the zone to look up in, never NULL
691 * @param value_zone public key of the target zone (value), never NULL
692 * @param iter function to call with the result
693 * @param iter_cls closure for @a iter
694 * @return #GNUNET_OK on success, #GNUNET_NO if there were no results, #GNUNET_SYSERR on error
695 */
696static int
697namestore_sqlite_zone_to_name (void *cls,
698 const struct GNUNET_IDENTITY_PrivateKey *zone,
699 const struct
700 GNUNET_IDENTITY_PublicKey *value_zone,
701 GNUNET_NAMESTORE_RecordIterator iter,
702 void *iter_cls)
703{
704 struct Plugin *plugin = cls;
705 struct GNUNET_SQ_QueryParam params[] = {
706 GNUNET_SQ_query_param_auto_from_type (zone),
707 GNUNET_SQ_query_param_auto_from_type (value_zone),
708 GNUNET_SQ_query_param_end
709 };
710
711 if (GNUNET_OK !=
712 GNUNET_SQ_bind (plugin->zone_to_name,
713 params))
714 {
715 LOG_SQLITE (plugin,
716 GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
717 "sqlite3_bind_XXXX");
718 GNUNET_SQ_reset (plugin->dbh,
719 plugin->zone_to_name);
720 return GNUNET_SYSERR;
721 }
722 LOG (GNUNET_ERROR_TYPE_DEBUG,
723 "Performing reverse lookup for `%s'\n",
724 GNUNET_GNSRECORD_z2s (value_zone));
725 return get_records_and_call_iterator (plugin,
726 plugin->zone_to_name,
727 zone,
728 1,
729 iter,
730 iter_cls);
731}
732
733
734/**
735 * Entry point for the plugin.
736 *
737 * @param cls the "struct GNUNET_NAMESTORE_PluginEnvironment*"
738 * @return NULL on error, otherwise the plugin context
739 */
740void *
741libgnunet_plugin_namestore_sqlite_init (void *cls)
742{
743 static struct Plugin plugin;
744 const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
745 struct GNUNET_NAMESTORE_PluginFunctions *api;
746
747 if (NULL != plugin.cfg)
748 return NULL; /* can only initialize once! */
749 memset (&plugin,
750 0,
751 sizeof(struct Plugin));
752 plugin.cfg = cfg;
753 if (GNUNET_OK != database_setup (&plugin))
754 {
755 database_shutdown (&plugin);
756 return NULL;
757 }
758 api = GNUNET_new (struct GNUNET_NAMESTORE_PluginFunctions);
759 api->cls = &plugin;
760 api->store_records = &namestore_sqlite_store_records;
761 api->iterate_records = &namestore_sqlite_iterate_records;
762 api->zone_to_name = &namestore_sqlite_zone_to_name;
763 api->lookup_records = &namestore_sqlite_lookup_records;
764 LOG (GNUNET_ERROR_TYPE_INFO,
765 _ ("Sqlite database running\n"));
766 return api;
767}
768
769
770/**
771 * Exit point from the plugin.
772 *
773 * @param cls the plugin context (as returned by "init")
774 * @return always NULL
775 */
776void *
777libgnunet_plugin_namestore_sqlite_done (void *cls)
778{
779 struct GNUNET_NAMESTORE_PluginFunctions *api = cls;
780 struct Plugin *plugin = api->cls;
781
782 database_shutdown (plugin);
783 plugin->cfg = NULL;
784 GNUNET_free (api);
785 LOG (GNUNET_ERROR_TYPE_DEBUG,
786 "sqlite plugin is finished\n");
787 return NULL;
788}
789
790
791/* 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 ff5494dc7..000000000
--- a/src/namestore/plugin_rest_namestore.c
+++ /dev/null
@@ -1,1155 +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 if (GNUNET_NO ==
644 GNUNET_CONTAINER_multihashmap_contains (con_handle->url_param_map, &key))
645 {
646 handle->record_type = GNUNET_GNSRECORD_TYPE_ANY;
647 }
648 else
649 {
650 typename = GNUNET_CONTAINER_multihashmap_get (con_handle->url_param_map,
651 &key);
652 handle->record_type = GNUNET_GNSRECORD_typename_to_number (typename);
653 }
654 labelname = &egoname[strlen (ego_entry->identifier)];
655 // set zone to name if given
656 if (1 >= strlen (labelname))
657 {
658 handle->list_it =
659 GNUNET_NAMESTORE_zone_iteration_start (ns_handle,
660 handle->zone_pkey,
661 &namestore_iteration_error,
662 handle,
663 &namestore_list_iteration,
664 handle,
665 &namestore_list_finished,
666 handle);
667 if (NULL == handle->list_it)
668 {
669 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
670 GNUNET_SCHEDULER_add_now (&do_error, handle);
671 return;
672 }
673 return;
674 }
675 handle->record_name = GNUNET_strdup (labelname + 1);
676 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
677 handle->zone_pkey,
678 handle->record_name,
679 &ns_lookup_error_cb,
680 handle,
681 &ns_get_lookup_cb,
682 handle);
683 if (NULL == handle->ns_qe)
684 {
685 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
686 GNUNET_SCHEDULER_add_now (&do_error, handle);
687 return;
688 }
689}
690
691
692static void
693ns_lookup_cb (void *cls,
694 const struct GNUNET_IDENTITY_PrivateKey *zone,
695 const char *label,
696 unsigned int rd_count,
697 const struct GNUNET_GNSRECORD_Data *rd)
698{
699 struct RequestHandle *handle = cls;
700 struct GNUNET_GNSRECORD_Data rd_new[rd_count + handle->rd_count];
701 int i = 0;
702 int j = 0;
703
704 if (UPDATE_STRATEGY_APPEND == handle->update_strategy)
705 {
706 for (i = 0; i < rd_count; i++)
707 rd_new[i] = rd[i];
708 }
709 for (j = 0; j < handle->rd_count; j++)
710 rd_new[i + j] = handle->rd[j];
711 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
712 handle->zone_pkey,
713 handle->record_name,
714 i + j,
715 rd_new,
716 &create_finished,
717 handle);
718 if (NULL == handle->ns_qe)
719 {
720 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
721 GNUNET_SCHEDULER_add_now (&do_error, handle);
722 return;
723 }
724}
725
726
727/**
728 * Handle namestore POST/PUT request
729 *
730 * @param con_handle the connection handle
731 * @param url the url
732 * @param cls the RequestHandle
733 */
734void
735namestore_add_or_update (struct GNUNET_REST_RequestHandle *con_handle,
736 const char *url,
737 void *cls)
738{
739 struct RequestHandle *handle = cls;
740 struct EgoEntry *ego_entry;
741 char *egoname;
742 json_t *data_js;
743 json_error_t err;
744
745 char term_data[handle->rest_handle->data_size + 1];
746
747 if (0 >= handle->rest_handle->data_size)
748 {
749 handle->response_code = MHD_HTTP_BAD_REQUEST;
750 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA);
751 GNUNET_SCHEDULER_add_now (&do_error, handle);
752 return;
753 }
754 term_data[handle->rest_handle->data_size] = '\0';
755 GNUNET_memcpy (term_data,
756 handle->rest_handle->data,
757 handle->rest_handle->data_size);
758 data_js = json_loads (term_data, JSON_DECODE_ANY, &err);
759 struct GNUNET_JSON_Specification gnsspec[] =
760 { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count,
761 &handle->record_name),
762 GNUNET_JSON_spec_end () };
763 if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL))
764 {
765 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
766 GNUNET_SCHEDULER_add_now (&do_error, handle);
767 json_decref (data_js);
768 return;
769 }
770 GNUNET_JSON_parse_free (gnsspec);
771 if (0 >= strlen (handle->record_name))
772 {
773 handle->response_code = MHD_HTTP_BAD_REQUEST;
774 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA);
775 GNUNET_SCHEDULER_add_now (&do_error, handle);
776 json_decref (data_js);
777 return;
778 }
779 json_decref (data_js);
780
781 egoname = NULL;
782 ego_entry = NULL;
783
784 // set zone to name if given
785 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
786 {
787 handle->response_code = MHD_HTTP_NOT_FOUND;
788 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
789 GNUNET_SCHEDULER_add_now (&do_error, handle);
790 return;
791 }
792 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
793 ego_entry = get_egoentry_namestore (handle, egoname);
794
795 if (NULL == ego_entry)
796 {
797 handle->response_code = MHD_HTTP_NOT_FOUND;
798 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
799 GNUNET_SCHEDULER_add_now (&do_error, handle);
800 return;
801 }
802 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
803 handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle,
804 handle->zone_pkey,
805 handle->record_name,
806 &ns_lookup_error_cb,
807 handle,
808 &ns_lookup_cb,
809 handle);
810 if (NULL == handle->ns_qe)
811 {
812 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
813 GNUNET_SCHEDULER_add_now (&do_error, handle);
814 return;
815 }
816}
817
818
819/**
820 * Handle namestore PUT request
821 *
822 * @param con_handle the connection handle
823 * @param url the url
824 * @param cls the RequestHandle
825 */
826void
827namestore_update (struct GNUNET_REST_RequestHandle *con_handle,
828 const char *url,
829 void *cls)
830{
831 struct RequestHandle *handle = cls;
832 handle->update_strategy = UPDATE_STRATEGY_REPLACE;
833 namestore_add_or_update (con_handle, url, cls);
834}
835
836
837/**
838 * Handle namestore POST request
839 *
840 * @param con_handle the connection handle
841 * @param url the url
842 * @param cls the RequestHandle
843 */
844void
845namestore_add (struct GNUNET_REST_RequestHandle *con_handle,
846 const char *url,
847 void *cls)
848{
849 struct RequestHandle *handle = cls;
850 handle->update_strategy = UPDATE_STRATEGY_APPEND;
851 namestore_add_or_update (con_handle, url, cls);
852}
853
854
855/**
856 * Handle namestore DELETE request
857 *
858 * @param con_handle the connection handle
859 * @param url the url
860 * @param cls the RequestHandle
861 */
862void
863namestore_delete (struct GNUNET_REST_RequestHandle *con_handle,
864 const char *url,
865 void *cls)
866{
867 struct RequestHandle *handle = cls;
868 struct EgoEntry *ego_entry;
869 char *egoname;
870 char *labelname;
871
872 egoname = NULL;
873 ego_entry = NULL;
874
875 // set zone to name if given
876 if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url))
877 {
878 handle->response_code = MHD_HTTP_NOT_FOUND;
879 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
880 GNUNET_SCHEDULER_add_now (&do_error, handle);
881 return;
882 }
883 egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1];
884 ego_entry = get_egoentry_namestore (handle, egoname);
885 if (NULL == ego_entry)
886 {
887 handle->response_code = MHD_HTTP_NOT_FOUND;
888 handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND);
889 GNUNET_SCHEDULER_add_now (&do_error, handle);
890 return;
891 }
892 handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego);
893 labelname = &egoname[strlen (ego_entry->identifier)];
894 // set zone to name if given
895 if (1 >= strlen (labelname))
896 {
897 /* label is only "/" */
898 handle->response_code = MHD_HTTP_BAD_REQUEST;
899 handle->emsg = GNUNET_strdup ("Label missing");
900 GNUNET_SCHEDULER_add_now (&do_error, handle);
901 }
902
903 handle->record_name = GNUNET_strdup (labelname + 1);
904 handle->ns_qe = GNUNET_NAMESTORE_records_store (ns_handle,
905 handle->zone_pkey,
906 handle->record_name,
907 0,
908 NULL,
909 &del_finished,
910 handle);
911 if (NULL == handle->ns_qe)
912 {
913 handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED);
914 GNUNET_SCHEDULER_add_now (&do_error, handle);
915 return;
916 }
917}
918
919
920/**
921 * Respond to OPTIONS request
922 *
923 * @param con_handle the connection handle
924 * @param url the url
925 * @param cls the RequestHandle
926 */
927static void
928options_cont (struct GNUNET_REST_RequestHandle *con_handle,
929 const char *url,
930 void *cls)
931{
932 struct MHD_Response *resp;
933 struct RequestHandle *handle = cls;
934
935 // independent of path return all options
936 resp = GNUNET_REST_create_response (NULL);
937 MHD_add_response_header (resp, "Access-Control-Allow-Methods", allow_methods);
938 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
939 GNUNET_SCHEDULER_add_now (&cleanup_handle, handle);
940 return;
941}
942
943
944static void
945list_ego (void *cls,
946 struct GNUNET_IDENTITY_Ego *ego,
947 void **ctx,
948 const char *identifier)
949{
950 struct EgoEntry *ego_entry;
951 struct GNUNET_IDENTITY_PublicKey pk;
952
953 if ((NULL == ego) && (ID_REST_STATE_INIT == state))
954 {
955 state = ID_REST_STATE_POST_INIT;
956 return;
957 }
958 if (NULL == ego)
959 {
960 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
961 "Called with NULL ego\n");
962 return;
963 }
964 if (ID_REST_STATE_INIT == state)
965 {
966 ego_entry = GNUNET_new (struct EgoEntry);
967 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
968 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
969 ego_entry->ego = ego;
970 ego_entry->identifier = GNUNET_strdup (identifier);
971 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
972 ego_tail,
973 ego_entry);
974 }
975 /* Ego renamed or added */
976 if (identifier != NULL)
977 {
978 for (ego_entry = ego_head; NULL != ego_entry;
979 ego_entry = ego_entry->next)
980 {
981 if (ego_entry->ego == ego)
982 {
983 /* Rename */
984 GNUNET_free (ego_entry->identifier);
985 ego_entry->identifier = GNUNET_strdup (identifier);
986 break;
987 }
988 }
989 if (NULL == ego_entry)
990 {
991 /* Add */
992 ego_entry = GNUNET_new (struct EgoEntry);
993 GNUNET_IDENTITY_ego_get_public_key (ego, &pk);
994 ego_entry->keystring = GNUNET_IDENTITY_public_key_to_string (&pk);
995 ego_entry->ego = ego;
996 ego_entry->identifier = GNUNET_strdup (identifier);
997 GNUNET_CONTAINER_DLL_insert_tail (ego_head,
998 ego_tail,
999 ego_entry);
1000 }
1001 }
1002 else
1003 {
1004 /* Delete */
1005 for (ego_entry = ego_head; NULL != ego_entry;
1006 ego_entry = ego_entry->next)
1007 {
1008 if (ego_entry->ego == ego)
1009 break;
1010 }
1011 if (NULL == ego_entry)
1012 return; /* Not found */
1013
1014 GNUNET_CONTAINER_DLL_remove (ego_head,
1015 ego_tail,
1016 ego_entry);
1017 GNUNET_free (ego_entry->identifier);
1018 GNUNET_free (ego_entry->keystring);
1019 GNUNET_free (ego_entry);
1020 return;
1021 }
1022
1023}
1024
1025
1026/**
1027 * Function processing the REST call
1028 *
1029 * @param method HTTP method
1030 * @param url URL of the HTTP request
1031 * @param data body of the HTTP request (optional)
1032 * @param data_size length of the body
1033 * @param proc callback function for the result
1034 * @param proc_cls closure for callback function
1035 * @return GNUNET_OK if request accepted
1036 */
1037static enum GNUNET_GenericReturnValue
1038rest_process_request (struct GNUNET_REST_RequestHandle *rest_handle,
1039 GNUNET_REST_ResultProcessor proc,
1040 void *proc_cls)
1041{
1042 struct RequestHandle *handle = GNUNET_new (struct RequestHandle);
1043 struct GNUNET_REST_RequestHandlerError err;
1044 static const struct GNUNET_REST_RequestHandler handlers[] =
1045 { { MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_get },
1046 { MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_add },
1047 { MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_update },
1048 { MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete },
1049 { MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont },
1050 GNUNET_REST_HANDLER_END };
1051
1052 handle->response_code = 0;
1053 handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
1054 handle->proc_cls = proc_cls;
1055 handle->proc = proc;
1056 handle->rest_handle = rest_handle;
1057 handle->zone_pkey = NULL;
1058 handle->timeout_task =
1059 GNUNET_SCHEDULER_add_delayed (handle->timeout, &do_error, handle);
1060 handle->url = GNUNET_strdup (rest_handle->url);
1061 if (handle->url[strlen (handle->url) - 1] == '/')
1062 handle->url[strlen (handle->url) - 1] = '\0';
1063 GNUNET_CONTAINER_DLL_insert (requests_head,
1064 requests_tail,
1065 handle);
1066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting...\n");
1067 if (GNUNET_NO ==
1068 GNUNET_REST_handle_request (handle->rest_handle, handlers, &err, handle))
1069 {
1070 cleanup_handle (handle);
1071 return GNUNET_NO;
1072 }
1073
1074 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected\n");
1075 return GNUNET_YES;
1076}
1077
1078
1079/**
1080 * Entry point for the plugin.
1081 *
1082 * @param cls Config info
1083 * @return NULL on error, otherwise the plugin context
1084 */
1085void *
1086libgnunet_plugin_rest_namestore_init (void *cls)
1087{
1088 static struct Plugin plugin;
1089 struct GNUNET_REST_Plugin *api;
1090
1091 cfg = cls;
1092 if (NULL != plugin.cfg)
1093 return NULL; /* can only initialize once! */
1094 memset (&plugin, 0, sizeof(struct Plugin));
1095 plugin.cfg = cfg;
1096 api = GNUNET_new (struct GNUNET_REST_Plugin);
1097 api->cls = &plugin;
1098 api->name = GNUNET_REST_API_NS_NAMESTORE;
1099 api->process_request = &rest_process_request;
1100 state = ID_REST_STATE_INIT;
1101 GNUNET_asprintf (&allow_methods,
1102 "%s, %s, %s, %s, %s",
1103 MHD_HTTP_METHOD_GET,
1104 MHD_HTTP_METHOD_POST,
1105 MHD_HTTP_METHOD_PUT,
1106 MHD_HTTP_METHOD_DELETE,
1107 MHD_HTTP_METHOD_OPTIONS);
1108 ns_handle = GNUNET_NAMESTORE_connect (cfg);
1109 identity_handle = GNUNET_IDENTITY_connect (cfg, &list_ego, NULL);
1110
1111 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _ ("Namestore REST API initialized\n"));
1112 return api;
1113}
1114
1115
1116/**
1117 * Exit point from the plugin.
1118 *
1119 * @param cls the plugin context (as returned by "init")
1120 * @return always NULL
1121 */
1122void *
1123libgnunet_plugin_rest_namestore_done (void *cls)
1124{
1125 struct GNUNET_REST_Plugin *api = cls;
1126 struct Plugin *plugin = api->cls;
1127 struct RequestHandle *request;
1128 struct EgoEntry *ego_entry;
1129 struct EgoEntry *ego_tmp;
1130
1131 plugin->cfg = NULL;
1132 while (NULL != (request = requests_head))
1133 do_error (request);
1134 if (NULL != identity_handle)
1135 GNUNET_IDENTITY_disconnect (identity_handle);
1136 if (NULL != ns_handle)
1137 GNUNET_NAMESTORE_disconnect (ns_handle);
1138
1139 for (ego_entry = ego_head; NULL != ego_entry;)
1140 {
1141 ego_tmp = ego_entry;
1142 ego_entry = ego_entry->next;
1143 GNUNET_free (ego_tmp->identifier);
1144 GNUNET_free (ego_tmp->keystring);
1145 GNUNET_free (ego_tmp);
1146 }
1147
1148 GNUNET_free (allow_methods);
1149 GNUNET_free (api);
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Namestore REST plugin is finished\n");
1151 return NULL;
1152}
1153
1154
1155/* 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 6ce969c9b..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_absolute_get ().abs_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 = 0;
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 5e3e7bbd8..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.dummy.gnunet";
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 79fa4c9c6..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.dummy.gnunet";
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 4fc197750..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 "dummy.dummy.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 b6254e531..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.dummy.gnunet";
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 e66992909..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.dummy.gnunet";
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 3fd10e4a1..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_absolute_get ().abs_value_us;
220 rd.record_type = GNUNET_GNSRECORD_TYPE_PKEY;
221 rd.data_size = GNUNET_IDENTITY_key_get_length (&s_zone_value);
222 rd.data = &s_zone_value;
223 rd.flags = 0;
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 NULL);
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 44ea1e66c..000000000
--- a/src/namestore/test_namestore_delete.sh
+++ /dev/null
@@ -1,76 +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_NAME = false -a $FOUND_IP != false ]
65then
66 echo "PASS: Delete name in namestore"
67 exit 0
68elif [ $FOUND_NAME = true ]
69then
70 echo "FAIL: Delete name in namestore: name returned"
71 exit 1
72elif [ $FOUND_IP = true ]
73then
74 echo "FAIL: Delete name in namestore: IP returned"
75 exit 1
76fi
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 8a45cebf5..000000000
--- a/src/namestore/test_plugin_rest_namestore.sh
+++ /dev/null
@@ -1,137 +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
81gnunet-arm -i rest -c test_namestore_api.conf
82#Test GET
83gnunet-identity -C $TEST_ID -c test_namestore_api.conf
84test="$(gnunet-namestore -D -z $TEST_ID -c test_namestore_api.conf)"
85name=$TEST_ID
86public="$(gnunet-identity -d -c test_namestore_api.conf | grep $TEST_ID | awk 'NR==1{print $3}')"
87echo "$name $public"
88valgrind gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
89#curl_get "${namestore_link}" "HTTP/1.1 200 OK"
90curl_get "${namestore_link}/$name" "HTTP/1.1 200 OK"
91curl_get "${namestore_link}/$public" "error"
92gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf
93
94#Test POST with NAME
95curl_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"
96gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
97
98# invalid values
99curl_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"
100gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
101
102
103curl_post "${namestore_link}/$name" '{"data": [{"value":"", "record_type":"PKEY", "expiration_time":"1d","flag":0,"record_name"}]:"test_entry"}' "error"
104gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
105
106curl_post "${namestore_link}/$name" '{"data": [{"record_type":"PKEY", "expiration_time":"1d","flag":0}],"record_name":"test_entry"}' "error"
107gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
108
109#expirations
110curl_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"
111gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
112
113curl_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"
114gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
115
116curl_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"
117gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
118
119curl_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"
120gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
121
122#record_name
123curl_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"
124gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
125curl_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"
126gnunet-namestore -z $name -d -n "test_entry" -c test_namestore_api.conf > /dev/null 2>&1
127
128#Test DELETE
129gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
130curl_delete "${namestore_link}/$name/test_entry" "HTTP/1.1 204"
131curl_delete "${namestore_link}/$name/test_entry" "error"
132gnunet-namestore -z $name -p -a -n "test_entry" -e "1d" -V "000G006WVZ8HQ5YTVFNX09HK0VJVVQ9ZCBYDSCH3ERT04N5ZRBKEB82EP8" -t "PKEY" -c test_namestore_api.conf
133curl_delete "${namestore_link}/$public/test_entry" "error"
134
135gnunet-arm -e -c test_namestore_api.conf
136exit 0;
137